Nix custom build auth callback path returning 404

I’m building nix packages for corteza and ui but I’ve hit an issue with the path /auth/callback returning a 404 when I attempt login with Google.

The following sequence happens:

GET https://XXX/auth/external/google < 307
GET https://accounts.google.com/o/oauth2/auth?client_id=XXX&redirect_uri=https%3A%2F%2FXXX%2Fauth%2Fexternal%2Fgoogle%2Fcallback&response_type=code&scope=email&state=XXX < 302
GET https://XXX/auth/external/google/callback?state=XXX&code=XXX&scope=email+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email&authuser=0&hd=XXX&prompt=none < 303
GET https://XXX/auth/oauth2/authorize-client < 303
GET https://XXX/auth/oauth2/authorize < 302
GET https://XXX/auth/callback?code=XXX&state=XXX < 404

It works fine if I use the docker image so I think I might have missed copying some files?

The 404 is still seen even without AUTH_DEVELOPMENT_MODE=true or AUTH_ASSETS_PATH set.

In case anyone finds this useful here are my nix files:


default.nix:

{ lib
, stdenv
, callPackage
, buildGoModule
, fetchFromGitHub
, fetchurl
}:
let
  version = "2021.3.11";
  server = callPackage ./server.nix { inherit version; };
  corteza-webapp-admin = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-admin-${version}.tar.gz";
    sha256 = "1in3nvh9skh64l4ba21vxlgvql1px7pf3ycm7sjr7a3vm26apwns"; # 2021.3.11
  };
  corteza-webapp-compose = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-compose-${version}.tar.gz";
    sha256 = "1kfjqlv1imy1kpfs66qy3xlrrm5ibk7fpirjxgs74fh97n7gkf9w"; # 2021.3.11
  };
  corteza-webapp-workflow = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-workflow-${version}.tar.gz";
    sha256 = "08pzd9ymx8yq8bjyhh154jwfrxybxybba0cq5kp0jsnm28bizxx6"; # 2021.3.11
  };
  corteza-webapp-one = fetchurl {
    url = "https://releases.cortezaproject.org/files/corteza-webapp-one-${version}.tar.gz";
    sha256 = "0354zshmdqxngaqg0lqzpcpk0l86m24asc5lsinard25bs9zlm4j"; # 2021.3.11
  };
in
stdenv.mkDerivation rec {
  pname = "corteza";
  inherit version;
  src = ./.;
  installPhase = ''
    mkdir -p $out
    cp -r ${server}/* $out
    mkdir -p $out/webapp/public/admin
    mkdir -p $out/webapp/public/compose
    mkdir -p $out/webapp/public/workflow
    tar -xzmokf ${corteza-webapp-one} --directory=$out/webapp/public
    tar -xzmokf ${corteza-webapp-admin} --directory=$out/webapp/public/admin
    tar -xzmokf ${corteza-webapp-compose} --directory=$out/webapp/public/compose
    tar -xzmokf ${corteza-webapp-workflow} --directory=$out/webapp/public/workflow
  '';
}

server.nix:

{ lib
, buildGoModule
, fetchFromGitHub
, version
}:
buildGoModule rec {
  pname = "corteza";
  inherit version;
  src = fetchFromGitHub {
    owner = "cortezaproject";
    repo = "corteza-server";
    rev = "${version}";
    sha256 = "1ni9wvpdxn7j12c2n593szls1bv0sgj47aglxsrz1bvf8p3a30rr";
  };
  vendorSha256 = null;
  subPackages = [ "cmd/corteza" ];
  postInstall = ''
    cp -r provision $out
    cp -r auth/assets $out/auth
  '';
  doCheck = false;
  meta = with lib; {
    description = "Corteza is the only 100% free, open-source, standardized and enterprise-grade Low-code platform";
    homepage = "https://cortezaproject.org/";
    license = licenses.asl20;
    # maintainers = [ maintainers. ];
  };
}

config-snippet.nix:

      corteza = rec {
        package = local.pkgs.corteza;
        host = "corteza${instance}";
        domain = local.secrets.domain;
        port = local.ports.corteza;
        fqdn = "${host}.${domain}";
        version = "2021.3";
        imageHost = "cortezaproject/corteza-server";
        image = "${imageHost}:${version}";
        listenAddress = "127.0.0.1:${toString port}";
        authBaseURL = "https://${fqdn}/auth";
        externalCallbackURL = "${authBaseURL}/external/{provider}/callback";
        db = local.secrets.corteza.db // {
          dsn = (c: "${c.username}:${c.password}@tcp(${c.host}:${toString c.port})/${c.database}?collation=utf8mb4_general_ci") local.secrets.corteza.db;
        };
        env = {
          "DB_DSN" = db.dsn;
          "DOMAIN" = fqdn;
          "VERSION" = version;
          "HTTP_ADDR" = listenAddress;
          "AUTH_BASE_URL" = authBaseURL;
          "AUTH_EXTERNAL_REDIRECT_URL" = externalCallbackURL;
          "HTTP_WEBAPP_ENABLED" = "true";
          "HTTP_LOG_REQUEST" = "true";
          "HTTP_LOG_RESPONSE" = "true";
          "HTTP_ENABLE_DEBUG_ROUTE" = "true";
          "ACTIONLOG_DEBUG" = "true";
          "CORREDOR_DEBUG" = "true";
          "CORREDOR_LOG_ENABLED" = "true";
          "GRPC_CLIENT_LOG" = "true";
          "DB_LOGGER" = "true";
          "HTTP_ERROR_TRACING" = "true";
          "HTTP_METRICS" = "true";
          "AUTH_DEVELOPMENT_MODE" = "true";
          "AUTH_ASSETS_PATH" = "${package}/auth";
          "UPGRADE_DEBUG" = "true";
        };
      };

Just in case, here is the auth.* settings from the db:

name value
auth.external.enabled true
auth.mail.from-address “info@example.tld”
auth.mail.from-name “Example Sender”
auth.internal.enabled false
auth.internal.signup.enabled false
auth.internal.signup.email-confirmation-required false
auth.internal.password-reset.enabled false
auth.external.providers.google.key “”
auth.external.providers.google.secret “”
auth.external.providers.google.enabled true
auth.external.providers.facebook.key “”
auth.external.providers.facebook.secret “”
auth.external.providers.facebook.enabled false
auth.external.providers.github.key “”
auth.external.providers.github.secret “”
auth.external.providers.github.enabled false
auth.external.providers.linkedin.key “”
auth.external.providers.linkedin.secret “”
auth.external.providers.linkedin.enabled false

I think I have resolved this. I moved the webapp/public content to the webapp directory and set "HTTP_WEBAPP_BASE_DIR" = "${package}/webapp"; in the environment.

I think it was because I didn’t set the working directory to the package directory which meant the default value for HTTP_WEBAPP_BASE_DIR (webapp/public) was not finding apps, only auth. Hopefully someone finds this helpful.

I’m working on a nixos module too but there is a fair bit to do as I’m planning on using caddy for tls, load balancing and static content, minio for files (and potential gateway to google bucket), and mysql. I’ve got a nixops deployment working for a single server. If anyone is interested in my nix related work let me know here.


Here’s my working nix package:

{ lib
, stdenv
, buildGoModule
, fetchFromGitHub
, fetchurl
}:
let
  meta = with lib; {
    description = "Corteza is the only 100% free, open-source, standardized and enterprise-grade Low-code platform";
    homepage = "https://cortezaproject.org/";
    license = licenses.asl20;
    # maintainers = [ maintainers. ];
  };
  version = "2021.3.11";
  server = buildGoModule rec {
    pname = "corteza-server";
    inherit version meta;
    src = fetchFromGitHub {
      owner = "cortezaproject";
      repo = pname;
      rev = "${version}";
      sha256 = "1ni9wvpdxn7j12c2n593szls1bv0sgj47aglxsrz1bvf8p3a30rr";
    };
    vendorSha256 = null;
    subPackages = [ "cmd/corteza" ];
    postInstall = ''
      cp -r provision $out
      rm -f $out/provision/README.adoc $out/provision/update.sh
      cp -r auth/assets $out/auth
    '';
    doCheck = false;
  };
  releasesURL = "https://releases.cortezaproject.org/files";
  webapp = app: "${releasesURL}/corteza-webapp-${app}-${version}.tar.gz";
  admin = fetchurl { url = webapp "admin"; sha256 = "1in3nvh9skh64l4ba21vxlgvql1px7pf3ycm7sjr7a3vm26apwns"; };
  compose = fetchurl { url = webapp "compose"; sha256 = "1kfjqlv1imy1kpfs66qy3xlrrm5ibk7fpirjxgs74fh97n7gkf9w"; };
  workflow = fetchurl { url = webapp "workflow"; sha256 = "08pzd9ymx8yq8bjyhh154jwfrxybxybba0cq5kp0jsnm28bizxx6"; };
  one = fetchurl { url = webapp "one"; sha256 = "0354zshmdqxngaqg0lqzpcpk0l86m24asc5lsinard25bs9zlm4j"; };
in
stdenv.mkDerivation rec {
  pname = "corteza";
  inherit version meta;
  src = ./.;
  installPhase = ''
    mkdir -p $out/webapp/admin $out/webapp/compose $out/webapp/workflow
    cp -r ${server}/* $out
    tar -xzmokf ${one} --directory=$out/webapp
    tar -xzmokf ${admin} --directory=$out/webapp/admin
    tar -xzmokf ${compose} --directory=$out/webapp/compose
    tar -xzmokf ${workflow} --directory=$out/webapp/workflow
  '';
}

1 Like

Thank you for posting a working solution; I’m sure someone will benefit from this!
Would you mind if we use this post as a base if we decide to incorporate this into the documentation?

I don’t mind if you use this for any purpose.

I’ve found something odd with my custom build not automatically creating the default oauth client on first installation. It worked at one point then didn’t. I’ve gone back to the docker image instead of my build for now.

It could be that I’m calling provision and migrate from the cli before running the api which might prevent the first run things from happening correctly. I’m doing this because I set some auth configuration so oauth2 sign on is the only option. I might have to use a modified copy of the provisioning yaml files and let the serve-api do the standard provisioning and migration with my yamls instead of running the cli as a pre-start script.

When I figure out what I missed, I’ll post here.

I got it to work. I was not running from a directory with the provisioning files so when starting, it didn’t create oauth clients or anything else.

I’m still refining the nix expressions but will share if anyone is interested.

Hey @andre , did you get any further with this? We are thinking about picking this up at Summer of Nix and would love to work forward from your solution.

Hey @matto, we have a lot of nix modules and packages related to corteza now. We’ve overcome most of the issues.

We found that Index of /files/ had some older files deleted. Since we’re trying to keep stability we had to mirror the old releases.

Also, we’re not building the web projects from source rather just using the build artifacts. Building from source would solve the issue of missing release files :wink: . I’d like to use GitHub - nix-community/dream2nix: Nixify software with less effort [maintainer=@DavHau] to do the builds but it’s not high priority currently.

There was also some issue with boot strapping in that we needed an API token to set some settings but couldn’t get one from the cli, only API. We added a API credentials cli module to fix this.

We deploy on GCP Cloud Run using terraform and found that the change to show a starting page on the API endpoint whilst waiting for the rest of the services to start meant that if there was a problem starting the services, e.g. database connection failure, then the cloud run would deploy successfully but fail to serve traffic. We also patched this to the old way in our build. It probably should be enabled with an env flag.

We had a nixos module at one point which would be useful for the nixos project but I’ve not sent it as it’s lacking tests and has too many hard coded things. A bit of work could see this ready for a PR to Nixos. This has since been moved to a corteza terraform module. We’re also developing a terraform provider to enable copying of permissions (and eventually pages, modules etc.) from one instance to another.

We have a derivation that doesn’t have any customisations and another expression we have our custom stuff in. I’d be happy to open source the relevant bits as having it in upstream would be appreciated. It’s not a nix flake (yet) but I’ve recently started moving all our repos to being flakes so it will be there eventually. We use nixos for all development and builds run the nix docker from Google cloud build.

There were a few more challanges we overcame but it’s probably worth a call to go over these as they are complex.