From 2a9f6754ea251682c24801c22a4e7bbe055784b9 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 12 May 2025 16:55:34 -0400 Subject: [PATCH 01/14] feat: a nix package, config and devShell for supabase-auth --- .gitignore | 1 + flake.lock | 61 ++++++++++++++++ flake.nix | 170 +++++++++++++++++++++++++++++++++++++++++++ nix/auth-module.nix | 51 +++++++++++++ nix/steps-module.nix | 26 +++++++ 5 files changed, 309 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/auth-module.nix create mode 100644 nix/steps-module.nix diff --git a/.gitignore b/.gitignore index e3ca2170f..1852f3803 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ www/.DS_Store www/node_modules npm-debug.log .data +result diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..123b37c33 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1746576598, + "narHash": "sha256-FshoQvr6Aor5SnORVvh/ZdJ1Sa2U4ZrIMwKBX5k2wu0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b3582c75c7f21ce0b429898980eddbbf05c68e55", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..a46a7654d --- /dev/null +++ b/flake.nix @@ -0,0 +1,170 @@ +{ + description = "Supabase Auth Service with Nix modules and steps"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + let + systems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + + forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); + + mkAuthConfig = system: + let + pkgs = nixpkgs.legacyPackages.${system}; + lib = pkgs.lib; + + # Go package + auth-service = pkgs.buildGoModule { + pname = "supabase-auth"; + version = "0.1.0"; + src = ./.; + + vendorHash = "sha256-QBQUUFWT3H3L7ajFV8cgi0QREXnm0ReIisD+4ACfLZQ="; + + buildFlags = [ "-tags" "netgo" ]; + doCheck = false; + + # Specify the main package + subPackages = [ "." ]; + + # Specify the output binary name + postInstall = '' + mv $out/bin/auth $out/bin/supabase-auth + ''; + }; + + # Evaluate both the auth and steps modules + config = lib.evalModules { + modules = [ + ./nix/auth-module.nix + ./nix/steps-module.nix + { + _module.args.pkgs = pkgs; + auth = { + enable = true; + package = auth-service; + port = 9999; + settings = { + GOTRUE_DB_DRIVER = "postgres"; + GOTRUE_SITE_URL = "http://localhost:3000"; + SITE_URL = "http://localhost:3000"; + GOTRUE_API_EXTERNAL_URL = "http://localhost:9999"; + API_EXTERNAL_URL = "http://localhost:9999"; + GOTRUE_DB_HOST = "localhost"; + GOTRUE_DB_PORT = "5432"; + GOTRUE_DB_NAME = "postgres"; + GOTRUE_DB_USER = "postgres"; + GOTRUE_DB_PASSWORD = "postgres"; + DATABASE_URL = "postgres://postgres:postgres@localhost:5432/postgres"; + GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + GOTRUE_JWT_EXP = "3600"; + GOTRUE_JWT_DEFAULT_GROUP_NAME = "authenticated"; + GOTRUE_DISABLE_SIGNUP = "false"; + GOTRUE_MAILER_AUTOCONFIRM = "true"; + GOTRUE_SMTP_ADMIN_EMAIL = "admin@example.com"; + GOTRUE_SMTP_HOST = "localhost"; + GOTRUE_SMTP_PORT = "2500"; + GOTRUE_SMTP_USER = ""; + GOTRUE_SMTP_PASS = ""; + GOTRUE_SMTP_SENDER_NAME = "Supabase"; + }; + }; + steps = { + enable = true; + }; + } + ]; + }; + + authConfigOutput = pkgs.stdenv.mkDerivation { + name = "auth-config"; + src = ./.; + buildInputs = [ pkgs.bash auth-service ]; + + buildPhase = '' + mkdir -p $out/etc $out/bin + + # Write the auth configuration + cat > $out/etc/auth.env < $out/bin/manage-auth < /dev/null; then + echo "Auth service is running" + else + echo "Auth service is not running" + fi + ;; + *) + echo "Usage: \$0 {start|stop|restart|status}" + exit 1 + ;; + esac + EOF + chmod +x $out/bin/manage-auth + ''; + + installPhase = "true"; + }; + + in + { + packages.default = authConfigOutput; + devShells.default = pkgs.mkShell { + buildInputs = [ + pkgs.bash + auth-service + pkgs.go + pkgs.gopls + pkgs.gotools + pkgs.go-outline + pkgs.gocode + pkgs.gopkgs + pkgs.godef + pkgs.golint + pkgs.delve + ]; + shellHook = '' + echo "Build with: nix build ." + echo "Result will be in ./result" + echo "Auth service version: ${auth-service.version}" + ''; + }; + }; + in + { + packages = forAllSystems (system: (mkAuthConfig system).packages); + devShells = forAllSystems (system: (mkAuthConfig system).devShells); + }; +} \ No newline at end of file diff --git a/nix/auth-module.nix b/nix/auth-module.nix new file mode 100644 index 000000000..ddf3382d7 --- /dev/null +++ b/nix/auth-module.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.auth; +in { + options.auth = { + enable = mkEnableOption "Supabase Auth Service"; + + package = mkOption { + type = types.package; + description = "The Supabase Auth package to use."; + }; + + port = mkOption { + type = types.port; + default = 9999; + description = "Port to run the auth service on."; + }; + + settings = mkOption { + type = types.attrs; + default = { + SITE_URL = "http://localhost:3000"; + API_EXTERNAL_URL = "http://localhost:9999"; + DB_HOST = "localhost"; + DB_PORT = "5432"; + DB_NAME = "postgres"; + DB_USER = "postgres"; + DB_PASSWORD = "postgres"; + JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + JWT_EXP = "3600"; + JWT_DEFAULT_GROUP_NAME = "authenticated"; + DISABLE_SIGNUP = "false"; + MAILER_AUTOCONFIRM = "true"; + SMTP_ADMIN_EMAIL = "admin@example.com"; + SMTP_HOST = "localhost"; + SMTP_PORT = "2500"; + SMTP_USER = ""; + SMTP_PASS = ""; + SMTP_SENDER_NAME = "Supabase"; + }; + description = "Configuration settings for the auth service."; + }; + }; + + config = mkIf cfg.enable { + # No NixOS-specific options here + }; +} \ No newline at end of file diff --git a/nix/steps-module.nix b/nix/steps-module.nix new file mode 100644 index 000000000..d31ee2778 --- /dev/null +++ b/nix/steps-module.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.steps; +in { + options.steps = { + enable = mkEnableOption "Auth service initialization steps"; + + commands = mkOption { + type = types.listOf types.str; + default = []; + description = "Commands to run during service initialization."; + }; + }; + + config = mkIf cfg.enable { + steps.commands = [ + # Wait for database to be ready + #"until pg_isready -h ${config.auth.settings.DB_HOST} -p ${config.auth.settings.DB_PORT} -U ${config.auth.settings.DB_USER}; do sleep 1; done" + # Run migrations if they exist + #"if [ -d migrations ]; then go run main.go migrate up; fi" + ]; + }; +} \ No newline at end of file From 6b2b8a0b5a9583efd2103c06512ded788f60b08a Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Sat, 17 May 2025 18:00:36 -0400 Subject: [PATCH 02/14] feat: create an activation script and systemd service --- flake.nix | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index a46a7654d..cfdbfdb2a 100644 --- a/flake.nix +++ b/flake.nix @@ -91,7 +91,7 @@ buildInputs = [ pkgs.bash auth-service ]; buildPhase = '' - mkdir -p $out/etc $out/bin + mkdir -p $out/etc $out/bin $out/lib/systemd/system # Write the auth configuration cat > $out/etc/auth.env < $out/lib/systemd/system/gotrue.service < $out/bin/manage-auth < $out/bin/activate </dev/null; then + useradd -r -s /bin/false gotrue + fi + + # Set proper ownership + chown -R gotrue:gotrue /opt/gotrue + chown -R gotrue:gotrue /etc/auth.d + chown -R gotrue:gotrue /etc/gotrue + + # Set proper permissions + chmod 775 /opt/gotrue + chmod 775 /etc/auth.d + chmod 775 /etc/gotrue + + # Copy the binary + cp ${auth-service}/bin/supabase-auth /opt/gotrue/gotrue + chown gotrue:gotrue /opt/gotrue/gotrue + chmod 755 /opt/gotrue/gotrue + + # Copy the systemd unit file + cp $out/lib/systemd/system/gotrue.service /etc/systemd/system/ + chmod 644 /etc/systemd/system/gotrue.service + + # Copy the environment file + cp $out/etc/auth.env /etc/gotrue.generated.env + chown gotrue:gotrue /etc/gotrue.generated.env + chmod 600 /etc/gotrue.generated.env + + # Create symlinks for easy access + ln -sf $out/bin/manage-auth /usr/local/bin/gotrue-manage + ln -sf $out/share/gotrue/gotrue.service /usr/local/share/gotrue/gotrue.service + ln -sf $out/bin/activate /usr/local/bin/auth-activate + + # Reload systemd + systemctl daemon-reload + + # Enable and start the service + systemctl enable gotrue.service + systemctl restart gotrue.service + + echo "Gotrue service has been activated and started" + echo "You can manage the service using: gotrue-manage {start|stop|restart|status}" + EOF + chmod +x $out/bin/activate + + # Create symlinks to the systemd unit files for easy access + mkdir -p $out/share/gotrue + ln -s $out/lib/systemd/system/gotrue.service $out/share/gotrue/gotrue.service ''; installPhase = "true"; @@ -140,7 +226,9 @@ in { - packages.default = authConfigOutput; + packages = { + default = authConfigOutput; + }; devShells.default = pkgs.mkShell { buildInputs = [ pkgs.bash From e1f49c2c314ceac324624556072885d42e5388e0 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Sat, 17 May 2025 18:26:03 -0400 Subject: [PATCH 03/14] feat: package and activation --- flake.nix | 44 +++++++++++++++-------- nix/README.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 15 deletions(-) create mode 100644 nix/README.md diff --git a/flake.nix b/flake.nix index cfdbfdb2a..ea5b08139 100644 --- a/flake.nix +++ b/flake.nix @@ -170,11 +170,6 @@ mkdir -p /etc/auth.d mkdir -p /etc/gotrue - # Create gotrue user if it doesn't exist - if ! id "gotrue" &>/dev/null; then - useradd -r -s /bin/false gotrue - fi - # Set proper ownership chown -R gotrue:gotrue /opt/gotrue chown -R gotrue:gotrue /etc/auth.d @@ -185,7 +180,7 @@ chmod 775 /etc/auth.d chmod 775 /etc/gotrue - # Copy the binary + # Copy the binary to the correct location cp ${auth-service}/bin/supabase-auth /opt/gotrue/gotrue chown gotrue:gotrue /opt/gotrue/gotrue chmod 755 /opt/gotrue/gotrue @@ -194,15 +189,26 @@ cp $out/lib/systemd/system/gotrue.service /etc/systemd/system/ chmod 644 /etc/systemd/system/gotrue.service - # Copy the environment file - cp $out/etc/auth.env /etc/gotrue.generated.env - chown gotrue:gotrue /etc/gotrue.generated.env - chmod 600 /etc/gotrue.generated.env - - # Create symlinks for easy access - ln -sf $out/bin/manage-auth /usr/local/bin/gotrue-manage - ln -sf $out/share/gotrue/gotrue.service /usr/local/share/gotrue/gotrue.service - ln -sf $out/bin/activate /usr/local/bin/auth-activate + # Copy the environment file to the correct location + cp $out/etc/auth.env /etc/auth.d/20_generated.env + chown gotrue:gotrue /etc/auth.d/20_generated.env + chmod 600 /etc/auth.d/20_generated.env + + # Create symlinks for easy access from nix profile + mkdir -p /usr/local/bin + mkdir -p /usr/local/share/gotrue + + # Create symlinks to the nix profile locations + ln -sf "\$NIX_PROFILE/bin/manage-auth" /usr/local/bin/gotrue-manage + ln -sf "\$NIX_PROFILE/share/gotrue/gotrue.service" /usr/local/share/gotrue/gotrue.service + ln -sf "\$NIX_PROFILE/bin/activate" /usr/local/bin/auth-activate + ln -sf "\$NIX_PROFILE/bin/gotrue" /usr/local/bin/gotrue + + # Allow UFW connections to GoTrue metrics exporter if UFW is installed + if command -v ufw >/dev/null 2>&1; then + ufw allow 9122/tcp comment "GoTrue metrics exporter" + echo "Added UFW rule for GoTrue metrics exporter" + fi # Reload systemd systemctl daemon-reload @@ -213,12 +219,20 @@ echo "Gotrue service has been activated and started" echo "You can manage the service using: gotrue-manage {start|stop|restart|status}" + echo "The following commands are available:" + echo " gotrue-manage - Manage the Gotrue service" + echo " auth-activate - Run this activation script again" + echo " gotrue - The auth service binary" EOF chmod +x $out/bin/activate # Create symlinks to the systemd unit files for easy access mkdir -p $out/share/gotrue ln -s $out/lib/systemd/system/gotrue.service $out/share/gotrue/gotrue.service + + # Copy the auth binary to the package's bin directory + cp ${auth-service}/bin/supabase-auth $out/bin/gotrue + chmod +x $out/bin/gotrue ''; installPhase = "true"; diff --git a/nix/README.md b/nix/README.md new file mode 100644 index 000000000..8d9e38e02 --- /dev/null +++ b/nix/README.md @@ -0,0 +1,97 @@ +# Nix Configuration for Auth Service + +This directory contains Nix modules and configurations for the Auth service. The setup allows for building and installing the Auth service using Nix, with proper systemd integration and configuration management. + +## Files + +- `auth-module.nix`: Defines the Nix module for the Auth service configuration +- `steps-module.nix`: Defines the Nix module for service startup steps and commands + +## Building and Installation + +### Prerequisites + +- Nix package manager installed +- System with systemd (for service management) + +### Installation + +1. Install the package: +```bash +nix profile install . +``` + +2. Activate the service: +```bash +sudo auth-activate +``` + +### Available Commands + +After installation, the following commands are available: + +- `gotrue`: The auth service binary +- `gotrue-manage`: Manage the service (start/stop/restart/status) +- `auth-activate`: Run the activation script again + +## Configuration + +The service configuration is managed through environment variables, which are set in the Nix configuration. The main configuration file is generated at `/etc/auth.d/20_generated.env` during activation. + +### Service Structure + +- Binary: `/opt/gotrue/gotrue` +- Config directory: `/etc/auth.d` +- Systemd service: `gotrue.service` +- Metrics port: 9122 (automatically configured in UFW if available) + +## Development + +### Updating the Service + +1. Modify the relevant Nix files: + - `flake.nix` for package definition and build process + - `auth-module.nix` for service configuration + - `steps-module.nix` for startup steps + +2. Rebuild and reinstall: +```bash +nix profile install . +sudo auth-activate +``` + +### Testing Changes + +1. Build the package: +```bash +nix build . +``` + +2. The result will be in `./result/` with the following structure: + - `bin/`: Contains the binary and management scripts + - `share/gotrue/`: Contains the systemd service file + - `etc/`: Contains the environment configuration + +## System Requirements + +- Linux system with systemd +- UFW (optional, for metrics port configuration) +- Proper permissions for the `gotrue` user (created by system image) + +## Troubleshooting + +1. If the service fails to start: + - Check logs: `journalctl -u gotrue.service` + - Verify permissions: `ls -l /opt/gotrue /etc/auth.d` + - Check config: `cat /etc/auth.d/20_generated.env` + +2. If commands are not found: + - Verify installation: `nix profile list` + - Check symlinks: `ls -l /usr/local/bin/gotrue*` + +## Notes + +- The activation script assumes the `gotrue` user exists (created by system image) +- The service runs as the `gotrue` user +- Configuration is managed through environment variables +- The service is automatically started and enabled on activation \ No newline at end of file From dd56958998c4a6a25b188b5ff4bc1a138ab59fb7 Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Thu, 11 Sep 2025 11:05:22 +0200 Subject: [PATCH 04/14] fix: nix devshell using the right pkg name, s/gocode/gocode-gomod MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … while evaluating 'strict' to select 'drvPath' on it at /builtin/derivation.nix:1:552: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:1:208: (stack trace truncated; use '--show-trace' to show the full trace) error: attribute 'gocode' missing at /nix/store/7r2yz90q994vr66n8gy7r9wwjvd6pzif-source/flake.nix:270:15: 269| pkgs.go-outline 270| pkgs.gocode | ^ 271| pkgs.gopkgs Did you mean one of gecode, avocode, goose, lolcode or qrcode? --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index ea5b08139..a782bda59 100644 --- a/flake.nix +++ b/flake.nix @@ -251,7 +251,7 @@ pkgs.gopls pkgs.gotools pkgs.go-outline - pkgs.gocode + pkgs.gocode-gomod pkgs.gopkgs pkgs.godef pkgs.golint From c23848c21239b8bfa5c5436972a2f062b7102f27 Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Thu, 11 Sep 2025 11:02:32 +0200 Subject: [PATCH 05/14] chores: format nix files with treefmt and set up a default formatter --- flake.nix | 43 ++++++++++++++++++++++++++++++------------- nix/auth-module.nix | 12 +++++++++--- nix/steps-module.nix | 14 ++++++++++---- 3 files changed, 49 insertions(+), 20 deletions(-) diff --git a/flake.nix b/flake.nix index a782bda59..e8f3dd114 100644 --- a/flake.nix +++ b/flake.nix @@ -6,7 +6,12 @@ flake-utils.url = "github:numtide/flake-utils"; }; - outputs = { self, nixpkgs, flake-utils }: + outputs = + { + self, + nixpkgs, + flake-utils, + }: let systems = [ "x86_64-linux" @@ -17,7 +22,8 @@ forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); - mkAuthConfig = system: + mkAuthConfig = + system: let pkgs = nixpkgs.legacyPackages.${system}; lib = pkgs.lib; @@ -27,15 +33,18 @@ pname = "supabase-auth"; version = "0.1.0"; src = ./.; - + vendorHash = "sha256-QBQUUFWT3H3L7ajFV8cgi0QREXnm0ReIisD+4ACfLZQ="; - - buildFlags = [ "-tags" "netgo" ]; + + buildFlags = [ + "-tags" + "netgo" + ]; doCheck = false; # Specify the main package subPackages = [ "." ]; - + # Specify the output binary name postInstall = '' mv $out/bin/auth $out/bin/supabase-auth @@ -88,7 +97,10 @@ authConfigOutput = pkgs.stdenv.mkDerivation { name = "auth-config"; src = ./.; - buildInputs = [ pkgs.bash auth-service ]; + buildInputs = [ + pkgs.bash + auth-service + ]; buildPhase = '' mkdir -p $out/etc $out/bin $out/lib/systemd/system @@ -96,7 +108,9 @@ # Write the auth configuration cat > $out/etc/auth.env < $out/bin/manage-auth < Date: Fri, 12 Sep 2025 11:45:51 +0200 Subject: [PATCH 06/14] chores: change nixpkgs flake input to the IPV6-compatible one --- flake.lock | 17 +++++++---------- flake.nix | 2 +- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/flake.lock b/flake.lock index 123b37c33..1e3b72f8b 100644 --- a/flake.lock +++ b/flake.lock @@ -20,18 +20,15 @@ }, "nixpkgs": { "locked": { - "lastModified": 1746576598, - "narHash": "sha256-FshoQvr6Aor5SnORVvh/ZdJ1Sa2U4ZrIMwKBX5k2wu0=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "b3582c75c7f21ce0b429898980eddbbf05c68e55", - "type": "github" + "lastModified": 1757419078, + "narHash": "sha256-cUwlZ3aSduI9dw5AbF3PzktsCztcvt+0GBClTeGaksI=", + "rev": "b599843bad24621dcaa5ab60dac98f9b0eb1cabe", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/unstable/nixos-25.11pre858212.b599843bad24/nixexprs.tar.xz?rev=b599843bad24621dcaa5ab60dac98f9b0eb1cabe" }, "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" + "type": "tarball", + "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" } }, "root": { diff --git a/flake.nix b/flake.nix index e8f3dd114..c44dd2473 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Supabase Auth Service with Nix modules and steps"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"; flake-utils.url = "github:numtide/flake-utils"; }; From d4702bce1f5294fef9eba041efad8d5e9309745e Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Mon, 15 Sep 2025 09:50:33 +0200 Subject: [PATCH 07/14] chores: bump nixpkgs ($ nix flake update) --- flake.lock | 8 ++++---- flake.nix | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flake.lock b/flake.lock index 1e3b72f8b..9df89dcdb 100644 --- a/flake.lock +++ b/flake.lock @@ -20,11 +20,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1757419078, - "narHash": "sha256-cUwlZ3aSduI9dw5AbF3PzktsCztcvt+0GBClTeGaksI=", - "rev": "b599843bad24621dcaa5ab60dac98f9b0eb1cabe", + "lastModified": 1757808699, + "narHash": "sha256-rmyZ6B4DtU9MwkBSEf63NU4czFoM0budKcAtlhjaGEc=", + "rev": "c23193b943c6c689d70ee98ce3128239ed9e32d1", "type": "tarball", - "url": "https://releases.nixos.org/nixos/unstable/nixos-25.11pre858212.b599843bad24/nixexprs.tar.xz?rev=b599843bad24621dcaa5ab60dac98f9b0eb1cabe" + "url": "https://releases.nixos.org/nixos/unstable/nixos-25.11pre861038.c23193b943c6/nixexprs.tar.xz?rev=c23193b943c6c689d70ee98ce3128239ed9e32d1" }, "original": { "type": "tarball", diff --git a/flake.nix b/flake.nix index c44dd2473..58335a917 100644 --- a/flake.nix +++ b/flake.nix @@ -34,7 +34,7 @@ version = "0.1.0"; src = ./.; - vendorHash = "sha256-QBQUUFWT3H3L7ajFV8cgi0QREXnm0ReIisD+4ACfLZQ="; + vendorHash = "sha256-knYvNkEVffWisvb4Dhm5qqtqQ4co9MGoNt6yH6dUll8="; buildFlags = [ "-tags" From 1e1a1fde64ec6363bb149c144f5b52b1ef19220f Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Tue, 16 Sep 2025 10:35:26 +0200 Subject: [PATCH 08/14] feat: rewrite all Nix expressions using blueprint framework The flake now provides a straightforward devshell, a default package (the binary built from the Go sources in this repository), and an auth NixOS module with default settings that are turned into the required configuration files and a systemd service. Some utility scripts for managing the service have been removed, as we now expect this to be handled directly through systemd utilities. --- .editorconfig | 12 ++ flake.lock | 17 +- flake.nix | 287 +----------------------------- nix/README.md | 97 ---------- nix/auth-module.nix | 57 ------ nix/devshell.nix | 7 + nix/modules/nixosModules/auth.nix | 122 +++++++++++++ nix/package.nix | 20 +++ nix/steps-module.nix | 32 ---- 9 files changed, 177 insertions(+), 474 deletions(-) create mode 100644 .editorconfig delete mode 100644 nix/README.md delete mode 100644 nix/auth-module.nix create mode 100644 nix/devshell.nix create mode 100644 nix/modules/nixosModules/auth.nix create mode 100644 nix/package.nix delete mode 100644 nix/steps-module.nix diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..a72279722 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*.nix] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true \ No newline at end of file diff --git a/flake.lock b/flake.lock index 9df89dcdb..52233acf5 100644 --- a/flake.lock +++ b/flake.lock @@ -1,20 +1,23 @@ { "nodes": { - "flake-utils": { + "blueprint": { "inputs": { + "nixpkgs": [ + "nixpkgs" + ], "systems": "systems" }, "locked": { - "lastModified": 1731533236, - "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "lastModified": 1755332143, + "narHash": "sha256-jaiZPA5ND7HPJ4U/bzp+BKGOYR14+rIe9tC6XA4jBHU=", "owner": "numtide", - "repo": "flake-utils", - "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "repo": "blueprint", + "rev": "3c8bf84e28df2be19cc6623cb3ceeb6fc0839b91", "type": "github" }, "original": { "owner": "numtide", - "repo": "flake-utils", + "repo": "blueprint", "type": "github" } }, @@ -33,7 +36,7 @@ }, "root": { "inputs": { - "flake-utils": "flake-utils", + "blueprint": "blueprint", "nixpkgs": "nixpkgs" } }, diff --git a/flake.nix b/flake.nix index 58335a917..865f37ef2 100644 --- a/flake.nix +++ b/flake.nix @@ -1,289 +1,14 @@ { - description = "Supabase Auth Service with Nix modules and steps"; - inputs = { nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"; - flake-utils.url = "github:numtide/flake-utils"; + blueprint.url = "github:numtide/blueprint"; + blueprint.inputs.nixpkgs.follows = "nixpkgs"; }; outputs = - { - self, - nixpkgs, - flake-utils, - }: - let - systems = [ - "x86_64-linux" - "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; - - forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); - - mkAuthConfig = - system: - let - pkgs = nixpkgs.legacyPackages.${system}; - lib = pkgs.lib; - - # Go package - auth-service = pkgs.buildGoModule { - pname = "supabase-auth"; - version = "0.1.0"; - src = ./.; - - vendorHash = "sha256-knYvNkEVffWisvb4Dhm5qqtqQ4co9MGoNt6yH6dUll8="; - - buildFlags = [ - "-tags" - "netgo" - ]; - doCheck = false; - - # Specify the main package - subPackages = [ "." ]; - - # Specify the output binary name - postInstall = '' - mv $out/bin/auth $out/bin/supabase-auth - ''; - }; - - # Evaluate both the auth and steps modules - config = lib.evalModules { - modules = [ - ./nix/auth-module.nix - ./nix/steps-module.nix - { - _module.args.pkgs = pkgs; - auth = { - enable = true; - package = auth-service; - port = 9999; - settings = { - GOTRUE_DB_DRIVER = "postgres"; - GOTRUE_SITE_URL = "http://localhost:3000"; - SITE_URL = "http://localhost:3000"; - GOTRUE_API_EXTERNAL_URL = "http://localhost:9999"; - API_EXTERNAL_URL = "http://localhost:9999"; - GOTRUE_DB_HOST = "localhost"; - GOTRUE_DB_PORT = "5432"; - GOTRUE_DB_NAME = "postgres"; - GOTRUE_DB_USER = "postgres"; - GOTRUE_DB_PASSWORD = "postgres"; - DATABASE_URL = "postgres://postgres:postgres@localhost:5432/postgres"; - GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; - GOTRUE_JWT_EXP = "3600"; - GOTRUE_JWT_DEFAULT_GROUP_NAME = "authenticated"; - GOTRUE_DISABLE_SIGNUP = "false"; - GOTRUE_MAILER_AUTOCONFIRM = "true"; - GOTRUE_SMTP_ADMIN_EMAIL = "admin@example.com"; - GOTRUE_SMTP_HOST = "localhost"; - GOTRUE_SMTP_PORT = "2500"; - GOTRUE_SMTP_USER = ""; - GOTRUE_SMTP_PASS = ""; - GOTRUE_SMTP_SENDER_NAME = "Supabase"; - }; - }; - steps = { - enable = true; - }; - } - ]; - }; - - authConfigOutput = pkgs.stdenv.mkDerivation { - name = "auth-config"; - src = ./.; - buildInputs = [ - pkgs.bash - auth-service - ]; - - buildPhase = '' - mkdir -p $out/etc $out/bin $out/lib/systemd/system - - # Write the auth configuration - cat > $out/etc/auth.env < $out/lib/systemd/system/gotrue.service < $out/bin/manage-auth < /dev/null; then - echo "Auth service is running" - else - echo "Auth service is not running" - fi - ;; - *) - echo "Usage: \$0 {start|stop|restart|status}" - exit 1 - ;; - esac - EOF - chmod +x $out/bin/manage-auth - - # Write the activation script - cat > $out/bin/activate </dev/null 2>&1; then - ufw allow 9122/tcp comment "GoTrue metrics exporter" - echo "Added UFW rule for GoTrue metrics exporter" - fi - - # Reload systemd - systemctl daemon-reload - - # Enable and start the service - systemctl enable gotrue.service - systemctl restart gotrue.service - - echo "Gotrue service has been activated and started" - echo "You can manage the service using: gotrue-manage {start|stop|restart|status}" - echo "The following commands are available:" - echo " gotrue-manage - Manage the Gotrue service" - echo " auth-activate - Run this activation script again" - echo " gotrue - The auth service binary" - EOF - chmod +x $out/bin/activate - - # Create symlinks to the systemd unit files for easy access - mkdir -p $out/share/gotrue - ln -s $out/lib/systemd/system/gotrue.service $out/share/gotrue/gotrue.service - - # Copy the auth binary to the package's bin directory - cp ${auth-service}/bin/supabase-auth $out/bin/gotrue - chmod +x $out/bin/gotrue - ''; - - installPhase = "true"; - }; - - in - { - packages = { - default = authConfigOutput; - }; - devShells.default = pkgs.mkShell { - buildInputs = [ - pkgs.bash - auth-service - pkgs.go - pkgs.gopls - pkgs.gotools - pkgs.go-outline - pkgs.gocode-gomod - pkgs.gopkgs - pkgs.godef - pkgs.golint - pkgs.delve - ]; - shellHook = '' - echo "Build with: nix build ." - echo "Result will be in ./result" - echo "Auth service version: ${auth-service.version}" - ''; - }; - }; - in - { - packages = forAllSystems (system: (mkAuthConfig system).packages); - devShells = forAllSystems (system: (mkAuthConfig system).devShells); - formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.nixfmt-tree); + inputs: + inputs.blueprint { + inherit inputs; + prefix = "nix/"; }; } diff --git a/nix/README.md b/nix/README.md deleted file mode 100644 index 8d9e38e02..000000000 --- a/nix/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# Nix Configuration for Auth Service - -This directory contains Nix modules and configurations for the Auth service. The setup allows for building and installing the Auth service using Nix, with proper systemd integration and configuration management. - -## Files - -- `auth-module.nix`: Defines the Nix module for the Auth service configuration -- `steps-module.nix`: Defines the Nix module for service startup steps and commands - -## Building and Installation - -### Prerequisites - -- Nix package manager installed -- System with systemd (for service management) - -### Installation - -1. Install the package: -```bash -nix profile install . -``` - -2. Activate the service: -```bash -sudo auth-activate -``` - -### Available Commands - -After installation, the following commands are available: - -- `gotrue`: The auth service binary -- `gotrue-manage`: Manage the service (start/stop/restart/status) -- `auth-activate`: Run the activation script again - -## Configuration - -The service configuration is managed through environment variables, which are set in the Nix configuration. The main configuration file is generated at `/etc/auth.d/20_generated.env` during activation. - -### Service Structure - -- Binary: `/opt/gotrue/gotrue` -- Config directory: `/etc/auth.d` -- Systemd service: `gotrue.service` -- Metrics port: 9122 (automatically configured in UFW if available) - -## Development - -### Updating the Service - -1. Modify the relevant Nix files: - - `flake.nix` for package definition and build process - - `auth-module.nix` for service configuration - - `steps-module.nix` for startup steps - -2. Rebuild and reinstall: -```bash -nix profile install . -sudo auth-activate -``` - -### Testing Changes - -1. Build the package: -```bash -nix build . -``` - -2. The result will be in `./result/` with the following structure: - - `bin/`: Contains the binary and management scripts - - `share/gotrue/`: Contains the systemd service file - - `etc/`: Contains the environment configuration - -## System Requirements - -- Linux system with systemd -- UFW (optional, for metrics port configuration) -- Proper permissions for the `gotrue` user (created by system image) - -## Troubleshooting - -1. If the service fails to start: - - Check logs: `journalctl -u gotrue.service` - - Verify permissions: `ls -l /opt/gotrue /etc/auth.d` - - Check config: `cat /etc/auth.d/20_generated.env` - -2. If commands are not found: - - Verify installation: `nix profile list` - - Check symlinks: `ls -l /usr/local/bin/gotrue*` - -## Notes - -- The activation script assumes the `gotrue` user exists (created by system image) -- The service runs as the `gotrue` user -- Configuration is managed through environment variables -- The service is automatically started and enabled on activation \ No newline at end of file diff --git a/nix/auth-module.nix b/nix/auth-module.nix deleted file mode 100644 index 2749126bd..000000000 --- a/nix/auth-module.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: - -with lib; - -let - cfg = config.auth; -in -{ - options.auth = { - enable = mkEnableOption "Supabase Auth Service"; - - package = mkOption { - type = types.package; - description = "The Supabase Auth package to use."; - }; - - port = mkOption { - type = types.port; - default = 9999; - description = "Port to run the auth service on."; - }; - - settings = mkOption { - type = types.attrs; - default = { - SITE_URL = "http://localhost:3000"; - API_EXTERNAL_URL = "http://localhost:9999"; - DB_HOST = "localhost"; - DB_PORT = "5432"; - DB_NAME = "postgres"; - DB_USER = "postgres"; - DB_PASSWORD = "postgres"; - JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; - JWT_EXP = "3600"; - JWT_DEFAULT_GROUP_NAME = "authenticated"; - DISABLE_SIGNUP = "false"; - MAILER_AUTOCONFIRM = "true"; - SMTP_ADMIN_EMAIL = "admin@example.com"; - SMTP_HOST = "localhost"; - SMTP_PORT = "2500"; - SMTP_USER = ""; - SMTP_PASS = ""; - SMTP_SENDER_NAME = "Supabase"; - }; - description = "Configuration settings for the auth service."; - }; - }; - - config = mkIf cfg.enable { - # No NixOS-specific options here - }; -} diff --git a/nix/devshell.nix b/nix/devshell.nix new file mode 100644 index 000000000..92e50ad1b --- /dev/null +++ b/nix/devshell.nix @@ -0,0 +1,7 @@ +{ pkgs, ... }: +with pkgs; +mkShell { + packages = [ + go + ]; +} diff --git a/nix/modules/nixosModules/auth.nix b/nix/modules/nixosModules/auth.nix new file mode 100644 index 000000000..7a4778496 --- /dev/null +++ b/nix/modules/nixosModules/auth.nix @@ -0,0 +1,122 @@ +{ + pkgs, + lib, + config, + ... +}: +let + cfg = config.auth; +in +{ + options.auth = { + enable = lib.mkEnableOption "Supabase Auth Service"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.callPackage ../../package.nix { }; + description = "The Supabase Auth package to use."; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 9999; + description = "Port to run the auth service on."; + }; + + settings = lib.mkOption { + type = lib.types.attrs; + default = { + API_EXTERNAL_URL = "http://localhost:9999"; + DB_HOST = "localhost"; + DB_NAME = "postgres"; + DB_PASSWORD = "postgres"; + DB_PORT = "5432"; + DB_USER = "postgres"; + DISABLE_SIGNUP = "false"; + # TODO: should ENV vars be prefixed with GOTRUE_? + # DATABASE_URL = "postgres://postgres:postgres@localhost:5432/postgres"; + # GOTRUE_API_EXTERNAL_URL = "http://localhost:9999"; + # GOTRUE_DB_DRIVER = "postgres"; + # GOTRUE_DB_HOST = "localhost"; + # GOTRUE_DB_NAME = "postgres"; + # GOTRUE_DB_PASSWORD = "postgres"; + # GOTRUE_DB_PORT = "5432"; + # GOTRUE_DB_USER = "postgres"; + # GOTRUE_DISABLE_SIGNUP = "false"; + # GOTRUE_JWT_DEFAULT_GROUP_NAME = "authenticated"; + # GOTRUE_JWT_EXP = "3600"; + # GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + # GOTRUE_MAILER_AUTOCONFIRM = "true"; + # GOTRUE_SITE_URL = "http://localhost:3000"; + # GOTRUE_SMTP_ADMIN_EMAIL = "admin@example.com"; + # GOTRUE_SMTP_HOST = "localhost"; + # GOTRUE_SMTP_PASS = ""; + # GOTRUE_SMTP_PORT = "2500"; + # GOTRUE_SMTP_SENDER_NAME = "Supabase"; + # GOTRUE_SMTP_USER = ""; + JWT_DEFAULT_GROUP_NAME = "authenticated"; + JWT_EXP = "3600"; + JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + MAILER_AUTOCONFIRM = "true"; + SITE_URL = "http://localhost:3000"; + SMTP_ADMIN_EMAIL = "admin@example.com"; + SMTP_HOST = "localhost"; + SMTP_PASS = ""; + SMTP_PORT = "2500"; + SMTP_SENDER_NAME = "Supabase"; + SMTP_USER = ""; + }; + description = "Configuration settings for the auth service."; + }; + + config = lib.mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [ 9122 ]; + + users.users.gotrue = { + isSystemUser = true; + description = "gotrue service user"; + group = "gotrue"; + }; + users.groups.gotrue = { }; + + systemd.services.gotrue = { + description = "gotrue (auth)"; + wantedBy = [ "system-manager.target" ]; + serviceConfig = { + Type = "simple"; + WorkingDirectory = "/opt/gotrue"; + ExecStart = "${gotrue}/bin/gotrue --config-dir /etc/auth.d"; + User = "gotrue"; + Restart = "always"; + RestartSec = 3; + MemoryAccounting = true; + MemoryMax = "50%"; + Slice = "services.slice"; + EnvironmentFile = [ + # TODO: should the ENV file be provided by the module rather than the package? + # cat > $out/etc/auth.env < Date: Fri, 19 Sep 2025 11:58:10 +0200 Subject: [PATCH 09/14] Add basic nixos test Only test that the service starts for now. --- .gitignore | 2 + nix/checks/nixos.nix | 60 ++++++++++++++ nix/modules/nixos/auth.nix | 126 ++++++++++++++++++++++++++++++ nix/modules/nixosModules/auth.nix | 122 ----------------------------- nix/package.nix | 4 +- 5 files changed, 191 insertions(+), 123 deletions(-) create mode 100644 nix/checks/nixos.nix create mode 100644 nix/modules/nixos/auth.nix delete mode 100644 nix/modules/nixosModules/auth.nix diff --git a/.gitignore b/.gitignore index 1852f3803..d5f372378 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,6 @@ www/.DS_Store www/node_modules npm-debug.log .data + result +.nixos-test-history diff --git a/nix/checks/nixos.nix b/nix/checks/nixos.nix new file mode 100644 index 000000000..3b7f1bca1 --- /dev/null +++ b/nix/checks/nixos.nix @@ -0,0 +1,60 @@ +{ + pkgs, + flake, + perSystem, + ... +}: +flake.inputs.nixpkgs.lib.nixos.runTest { + name = "auth"; + hostPkgs = pkgs; + node.specialArgs = { inherit flake perSystem; }; + nodes.server = + { config, ... }: + { + imports = [ + (import flake.nixosModules.auth) + ]; + + virtualisation = { + forwardPorts = [ + { + from = "host"; + host.port = 13022; + guest.port = 22; + } + ]; + }; + services.openssh = { + enable = true; + }; + + services.auth.enable = true; + + services.postgresql = { + enable = true; + enableTCPIP = true; + initialScript = pkgs.writeText "init-postgres-with-password" '' + CREATE USER supabase_admin LOGIN CREATEROLE CREATEDB REPLICATION BYPASSRLS; + + -- Supabase super admin + CREATE USER supabase_auth_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION PASSWORD 'secret'; + CREATE SCHEMA IF NOT EXISTS auth AUTHORIZATION supabase_auth_admin; + GRANT CREATE ON DATABASE postgres TO supabase_auth_admin; + ALTER USER supabase_auth_admin SET search_path = 'auth'; + ''; + authentication = '' + host supabase_auth_admin postgres samenet scram-sha-256 + ''; + }; + }; + testScript = + { nodes, ... }: + '' + start_all() + + server.wait_for_unit("multi-user.target") + server.wait_for_unit("postgresql.service") + + server.wait_for_unit("gotrue.service") + ''; +} diff --git a/nix/modules/nixos/auth.nix b/nix/modules/nixos/auth.nix new file mode 100644 index 000000000..d24e4bfeb --- /dev/null +++ b/nix/modules/nixos/auth.nix @@ -0,0 +1,126 @@ +{ + pkgs, + lib, + config, + perSystem, + ... +}: +let + cfg = config.services.auth; + gotrue = perSystem.self.default; + default_settings = rec { + API_EXTERNAL_URL = "http://localhost:9999"; + DB_HOST = "localhost"; + DB_NAME = "postgres"; + DB_PASSWORD = "secret"; + DB_PORT = "5432"; + DB_USER = "supabase_auth_admin"; + DISABLE_SIGNUP = "false"; + DATABASE_URL = "postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}"; + GOTRUE_API_EXTERNAL_URL = "http://localhost:9999"; + GOTRUE_DB_DRIVER = "postgres"; + GOTRUE_DB_HOST = DB_HOST; + GOTRUE_DB_NAME = DB_NAME; + GOTRUE_DB_PASSWORD = DB_PASSWORD; + GOTRUE_DB_PORT = DB_PORT; + GOTRUE_DB_USER = DB_USER; + GOTRUE_DISABLE_SIGNUP = "false"; + GOTRUE_JWT_DEFAULT_GROUP_NAME = "authenticated"; + GOTRUE_JWT_EXP = "3600"; + GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + GOTRUE_MAILER_AUTOCONFIRM = "true"; + GOTRUE_SITE_URL = "http://localhost:3000"; + GOTRUE_SMTP_ADMIN_EMAIL = "admin@example.com"; + GOTRUE_SMTP_HOST = "localhost"; + GOTRUE_SMTP_PASS = ""; + GOTRUE_SMTP_PORT = "2500"; + GOTRUE_SMTP_SENDER_NAME = "Supabase"; + GOTRUE_SMTP_USER = ""; + JWT_DEFAULT_GROUP_NAME = "authenticated"; + JWT_EXP = "3600"; + JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + MAILER_AUTOCONFIRM = "true"; + SITE_URL = "http://localhost:3000"; + SMTP_ADMIN_EMAIL = "admin@example.com"; + SMTP_HOST = "localhost"; + SMTP_PASS = ""; + SMTP_PORT = "2500"; + SMTP_SENDER_NAME = "Supabase"; + SMTP_USER = ""; + }; + auth_env = pkgs.writeText "auth.env" ( + lib.concatStringsSep "\n" ( + (lib.mapAttrsToList (name: value: "${name}=${value}") (default_settings // cfg.settings)) + ) + ); +in +{ + options.services.auth = { + enable = lib.mkEnableOption "Supabase Auth Service"; + + package = lib.mkOption { + type = lib.types.package; + default = pkgs.callPackage ../../package.nix { }; + description = "The Supabase Auth package to use."; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 9999; + description = "Port to run the auth service on."; + }; + + settings = lib.mkOption { + type = lib.types.attrs; + default = { }; + description = "Configuration settings for the auth service."; + }; + }; + + config = lib.mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [ 9122 ]; + + users.users.gotrue = { + isSystemUser = true; + description = "gotrue service user"; + group = "gotrue"; + }; + users.groups.gotrue = { }; + + systemd.services.gotrue = { + description = "gotrue (auth)"; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "simple"; + WorkingDirectory = "/opt/gotrue"; + ExecStart = "${gotrue}/bin/gotrue --config-dir /etc/auth.d"; + User = "gotrue"; + Restart = "always"; + RestartSec = 3; + MemoryAccounting = true; + MemoryMax = "50%"; + Slice = "services.slice"; + EnvironmentFile = [ + "/etc/gotrue/auth.env" + "-/etc/gotrue.generated.env" + "-/etc/gotrue.overrides.env" + ]; + # preStart = '' + # pg_isready -h ${config.auth.settings.DB_HOST} -p ${config.auth.settings.DB_PORT} -U ${config.auth.settings.DB_USER}; do sleep 1; done + # ''; + }; + }; + + systemd.tmpfiles.rules = [ + "d /etc/auth.d 0755 gotrue gotrue -" + "d /opt/gotrue 0755 gotrue gotrue -" + "C /etc/gotrue/auth.env 0440 gotrue gotrue - ${auth_env}" + ]; + }; +} + +# TODO: initialization steps as activation script? +# - Wait for database to be ready: +# until pg_isready -h ${config.auth.settings.DB_HOST} -p ${config.auth.settings.DB_PORT} -U ${config.auth.settings.DB_USER}; do sleep 1; done +# - Run migrations if they exist: +# if [ -d migrations ]; then go run main.go migrate up; fi diff --git a/nix/modules/nixosModules/auth.nix b/nix/modules/nixosModules/auth.nix deleted file mode 100644 index 7a4778496..000000000 --- a/nix/modules/nixosModules/auth.nix +++ /dev/null @@ -1,122 +0,0 @@ -{ - pkgs, - lib, - config, - ... -}: -let - cfg = config.auth; -in -{ - options.auth = { - enable = lib.mkEnableOption "Supabase Auth Service"; - - package = lib.mkOption { - type = lib.types.package; - default = pkgs.callPackage ../../package.nix { }; - description = "The Supabase Auth package to use."; - }; - - port = lib.mkOption { - type = lib.types.port; - default = 9999; - description = "Port to run the auth service on."; - }; - - settings = lib.mkOption { - type = lib.types.attrs; - default = { - API_EXTERNAL_URL = "http://localhost:9999"; - DB_HOST = "localhost"; - DB_NAME = "postgres"; - DB_PASSWORD = "postgres"; - DB_PORT = "5432"; - DB_USER = "postgres"; - DISABLE_SIGNUP = "false"; - # TODO: should ENV vars be prefixed with GOTRUE_? - # DATABASE_URL = "postgres://postgres:postgres@localhost:5432/postgres"; - # GOTRUE_API_EXTERNAL_URL = "http://localhost:9999"; - # GOTRUE_DB_DRIVER = "postgres"; - # GOTRUE_DB_HOST = "localhost"; - # GOTRUE_DB_NAME = "postgres"; - # GOTRUE_DB_PASSWORD = "postgres"; - # GOTRUE_DB_PORT = "5432"; - # GOTRUE_DB_USER = "postgres"; - # GOTRUE_DISABLE_SIGNUP = "false"; - # GOTRUE_JWT_DEFAULT_GROUP_NAME = "authenticated"; - # GOTRUE_JWT_EXP = "3600"; - # GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; - # GOTRUE_MAILER_AUTOCONFIRM = "true"; - # GOTRUE_SITE_URL = "http://localhost:3000"; - # GOTRUE_SMTP_ADMIN_EMAIL = "admin@example.com"; - # GOTRUE_SMTP_HOST = "localhost"; - # GOTRUE_SMTP_PASS = ""; - # GOTRUE_SMTP_PORT = "2500"; - # GOTRUE_SMTP_SENDER_NAME = "Supabase"; - # GOTRUE_SMTP_USER = ""; - JWT_DEFAULT_GROUP_NAME = "authenticated"; - JWT_EXP = "3600"; - JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; - MAILER_AUTOCONFIRM = "true"; - SITE_URL = "http://localhost:3000"; - SMTP_ADMIN_EMAIL = "admin@example.com"; - SMTP_HOST = "localhost"; - SMTP_PASS = ""; - SMTP_PORT = "2500"; - SMTP_SENDER_NAME = "Supabase"; - SMTP_USER = ""; - }; - description = "Configuration settings for the auth service."; - }; - - config = lib.mkIf cfg.enable { - networking.firewall.allowedTCPPorts = [ 9122 ]; - - users.users.gotrue = { - isSystemUser = true; - description = "gotrue service user"; - group = "gotrue"; - }; - users.groups.gotrue = { }; - - systemd.services.gotrue = { - description = "gotrue (auth)"; - wantedBy = [ "system-manager.target" ]; - serviceConfig = { - Type = "simple"; - WorkingDirectory = "/opt/gotrue"; - ExecStart = "${gotrue}/bin/gotrue --config-dir /etc/auth.d"; - User = "gotrue"; - Restart = "always"; - RestartSec = 3; - MemoryAccounting = true; - MemoryMax = "50%"; - Slice = "services.slice"; - EnvironmentFile = [ - # TODO: should the ENV file be provided by the module rather than the package? - # cat > $out/etc/auth.env < Date: Fri, 19 Sep 2025 18:11:05 +0200 Subject: [PATCH 10/14] Fix auth package reference in nixos module --- nix/modules/nixos/auth.nix | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/nix/modules/nixos/auth.nix b/nix/modules/nixos/auth.nix index d24e4bfeb..c1d69fe5b 100644 --- a/nix/modules/nixos/auth.nix +++ b/nix/modules/nixos/auth.nix @@ -7,7 +7,6 @@ }: let cfg = config.services.auth; - gotrue = perSystem.self.default; default_settings = rec { API_EXTERNAL_URL = "http://localhost:9999"; DB_HOST = "localhost"; @@ -60,7 +59,7 @@ in package = lib.mkOption { type = lib.types.package; - default = pkgs.callPackage ../../package.nix { }; + default = perSystem.self.default; description = "The Supabase Auth package to use."; }; @@ -93,7 +92,7 @@ in serviceConfig = { Type = "simple"; WorkingDirectory = "/opt/gotrue"; - ExecStart = "${gotrue}/bin/gotrue --config-dir /etc/auth.d"; + ExecStart = "${cfg.package}/bin/gotrue --config-dir /etc/auth.d"; User = "gotrue"; Restart = "always"; RestartSec = 3; From f49ce4ada07eb981c20836923aec2e124327dd77 Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Mon, 22 Sep 2025 14:22:14 +0200 Subject: [PATCH 11/14] feat: update systemd service definition as per commit https://github.com/supabase/postgres/commit/493bd39a5e75228d34573ae3ecb010d2784e478a (HEAD -> develop, origin/develop, origin/HEAD) Author: Chris Stockton <180184+cstockton@users.noreply.github.com> Date: Wed Sep 17 07:48:52 2025 -0700 feat: tighten gotrue.service deps and startup behavior (#1783) --- nix/modules/nixos/auth.nix | 24 +++++++++++++++++++++++- nix/package.nix | 2 +- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/nix/modules/nixos/auth.nix b/nix/modules/nixos/auth.nix index c1d69fe5b..5a97a539a 100644 --- a/nix/modules/nixos/auth.nix +++ b/nix/modules/nixos/auth.nix @@ -28,6 +28,23 @@ let GOTRUE_JWT_EXP = "3600"; GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; GOTRUE_MAILER_AUTOCONFIRM = "true"; + + # Both v2 & v3 support reloading via signals, on linux this is SIGUSR1. + GOTRUE_RELOADING_SIGNAL_ENABLED = "true"; + GOTRUE_RELOADING_SIGNAL_NUMBER = "10"; + + # Both v2 & v3 disable the poller. While gotrue sets it to off by default we + # defensively set it to false here. + GOTRUE_RELOADING_POLLER_ENABLED = "false"; + + # Determines how much idle time must pass before triggering a reload. This + # ensures only 1 reload operation occurs during a burst of config updates. + GOTRUE_RELOADING_GRACE_PERIOD_INTERVAL = "2s"; + + # v3 does not use filesystem notifications for config reloads. + GOTRUE_RELOADING_NOTIFY_ENABLED = "false"; + + # TODO: remove duplicates? GOTRUE_SITE_URL = "http://localhost:3000"; GOTRUE_SMTP_ADMIN_EMAIL = "admin@example.com"; GOTRUE_SMTP_HOST = "localhost"; @@ -90,9 +107,10 @@ in description = "gotrue (auth)"; wantedBy = [ "multi-user.target" ]; serviceConfig = { - Type = "simple"; + Type = "exec"; WorkingDirectory = "/opt/gotrue"; ExecStart = "${cfg.package}/bin/gotrue --config-dir /etc/auth.d"; + ExecReload = "${pkgs.coreutils}/bin/kill -10 $MAINPID"; User = "gotrue"; Restart = "always"; RestartSec = 3; @@ -108,6 +126,10 @@ in # pg_isready -h ${config.auth.settings.DB_HOST} -p ${config.auth.settings.DB_PORT} -U ${config.auth.settings.DB_USER}; do sleep 1; done # ''; }; + unitConfig = { + StartLimitIntervalSec = 10; + StartLimitBurst = 5; + }; }; systemd.tmpfiles.rules = [ diff --git a/nix/package.nix b/nix/package.nix index d1037c879..64096649c 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -2,7 +2,7 @@ pkgs.buildGoModule { pname = "supabase-auth"; version = "2.180.0"; - src = ./..; + src = ./..; # TODO: better filters out what's not go files vendorHash = "sha256-knYvNkEVffWisvb4Dhm5qqtqQ4co9MGoNt6yH6dUll8="; From d6cccdc179964e70363b4edd9c3f30182782e2f6 Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Mon, 22 Sep 2025 14:59:20 +0200 Subject: [PATCH 12/14] feat: remove default package in auth NixOs module --- nix/checks/nixos.nix | 5 ++++- nix/modules/nixos/auth.nix | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/nix/checks/nixos.nix b/nix/checks/nixos.nix index 3b7f1bca1..22839a0b5 100644 --- a/nix/checks/nixos.nix +++ b/nix/checks/nixos.nix @@ -28,7 +28,10 @@ flake.inputs.nixpkgs.lib.nixos.runTest { enable = true; }; - services.auth.enable = true; + services.auth = { + enable = true; + package = perSystem.self.default; + }; services.postgresql = { enable = true; diff --git a/nix/modules/nixos/auth.nix b/nix/modules/nixos/auth.nix index 5a97a539a..a8371fcc7 100644 --- a/nix/modules/nixos/auth.nix +++ b/nix/modules/nixos/auth.nix @@ -2,7 +2,6 @@ pkgs, lib, config, - perSystem, ... }: let @@ -76,7 +75,6 @@ in package = lib.mkOption { type = lib.types.package; - default = perSystem.self.default; description = "The Supabase Auth package to use."; }; From 25c80bfdab07c3eb082dd10ba20f592b88bdc4d4 Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Mon, 22 Sep 2025 15:23:58 +0200 Subject: [PATCH 13/14] feat: wait for postgres.service in nix-generated systemd config --- nix/modules/nixos/auth.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/modules/nixos/auth.nix b/nix/modules/nixos/auth.nix index a8371fcc7..6cdcc1f8b 100644 --- a/nix/modules/nixos/auth.nix +++ b/nix/modules/nixos/auth.nix @@ -104,6 +104,7 @@ in systemd.services.gotrue = { description = "gotrue (auth)"; wantedBy = [ "multi-user.target" ]; + after = [ "postgresql.service" ]; serviceConfig = { Type = "exec"; WorkingDirectory = "/opt/gotrue"; From 468a5d2e8579453a7f251688a1bc33fbc51d63ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Roche?= Date: Mon, 22 Sep 2025 14:00:48 +0200 Subject: [PATCH 14/14] fix: include only necessary files in the Go module source Avoid rebuilding when unrelated files change. --- flake.lock | 16 ++++++++++++++++ flake.nix | 1 + nix/package.nix | 24 ++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/flake.lock b/flake.lock index 52233acf5..0ac272541 100644 --- a/flake.lock +++ b/flake.lock @@ -21,6 +21,21 @@ "type": "github" } }, + "nix-filter": { + "locked": { + "lastModified": 1757882181, + "narHash": "sha256-+cCxYIh2UNalTz364p+QYmWHs0P+6wDhiWR4jDIKQIU=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "59c44d1909c72441144b93cf0f054be7fe764de5", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1757808699, @@ -37,6 +52,7 @@ "root": { "inputs": { "blueprint": "blueprint", + "nix-filter": "nix-filter", "nixpkgs": "nixpkgs" } }, diff --git a/flake.nix b/flake.nix index 865f37ef2..f21c41272 100644 --- a/flake.nix +++ b/flake.nix @@ -3,6 +3,7 @@ nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"; blueprint.url = "github:numtide/blueprint"; blueprint.inputs.nixpkgs.follows = "nixpkgs"; + nix-filter.url = "github:numtide/nix-filter"; }; outputs = diff --git a/nix/package.nix b/nix/package.nix index 64096649c..d68987066 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -1,8 +1,28 @@ -{ pkgs, ... }: +{ + flake, + inputs, + pkgs, + ... +}: +let + filter = inputs.nix-filter.lib; +in pkgs.buildGoModule { pname = "supabase-auth"; version = "2.180.0"; - src = ./..; # TODO: better filters out what's not go files + src = filter { + root = flake; + include = [ + (filter.matchExt "go") + "go.mod" + "go.sum" + "client" + "cmd" + "internal" + "migrations" + "tools" + ]; + }; vendorHash = "sha256-knYvNkEVffWisvb4Dhm5qqtqQ4co9MGoNt6yH6dUll8=";