From 2ee7c42c56376664cd604290a387c3ea65a156e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Roche?= Date: Tue, 12 Aug 2025 20:31:51 +0200 Subject: [PATCH 1/2] ci: make sure we cache system manager and its test dependencies --- nix/checks.nix | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nix/checks.nix b/nix/checks.nix index 1217a0312..1c890e407 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -315,6 +315,9 @@ inherit self; inherit pkgs; }) - ); + ) + // pkgs.lib.optionalAttrs (pkgs.stdenv.hostPlatform.isLinux) { + inherit (self'.packages) ansible-test run-testinfra docker-image-ubuntu; + }; }; } From e0f85cee21f1a6fb9f5e77d21ce442b86959c610 Mon Sep 17 00:00:00 2001 From: Yvan Sraka Date: Mon, 15 Sep 2025 12:14:54 +0200 Subject: [PATCH 2/2] (WIP) feat: deploy gotrue using system manager --- ansible/files/gotrue-optimizations.service.j2 | 12 --- ansible/files/gotrue.service.j2 | 27 ------- ansible/playbook.yml | 17 ++-- ansible/tasks/setup-gotrue.yml | 66 ---------------- ansible/vars.yml | 3 - flake.lock | 59 ++++++++++++++ flake.nix | 9 ++- nix/systemConfigs.nix | 9 ++- nix/systemModules/default.nix | 1 + nix/systemModules/dummy-firewall.nix | 6 ++ nix/systemModules/gotrue.nix | 77 +++++++++++++++++++ nix/systemModules/tests/test_gotrue.py | 13 ++++ 12 files changed, 177 insertions(+), 122 deletions(-) delete mode 100644 ansible/files/gotrue-optimizations.service.j2 delete mode 100644 ansible/files/gotrue.service.j2 delete mode 100644 ansible/tasks/setup-gotrue.yml create mode 100644 nix/systemModules/dummy-firewall.nix create mode 100644 nix/systemModules/gotrue.nix create mode 100644 nix/systemModules/tests/test_gotrue.py diff --git a/ansible/files/gotrue-optimizations.service.j2 b/ansible/files/gotrue-optimizations.service.j2 deleted file mode 100644 index fe5b26cd7..000000000 --- a/ansible/files/gotrue-optimizations.service.j2 +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=GoTrue (Auth) optimizations - -[Service] -Type=oneshot -# we don't want failures from this command to cause PG startup to fail -ExecStart=/bin/bash -c "/opt/supabase-admin-api optimize auth --destination-config-file-path /etc/gotrue/gotrue.generated.env ; exit 0" -ExecStartPost=/bin/bash -c "cp -a /etc/gotrue/gotrue.generated.env /etc/auth.d/20_generated.env ; exit 0" -User=postgrest - -[Install] -WantedBy=multi-user.target diff --git a/ansible/files/gotrue.service.j2 b/ansible/files/gotrue.service.j2 deleted file mode 100644 index 2478e99e6..000000000 --- a/ansible/files/gotrue.service.j2 +++ /dev/null @@ -1,27 +0,0 @@ -[Unit] -Description=Gotrue - -[Service] -Type=simple -WorkingDirectory=/opt/gotrue -{% if qemu_mode is defined and qemu_mode %} -ExecStart=/opt/gotrue/gotrue -{% else %} -ExecStart=/opt/gotrue/gotrue --config-dir /etc/auth.d -{% endif %} - -User=gotrue -Restart=always -RestartSec=3 - -MemoryAccounting=true -MemoryMax=50% - -EnvironmentFile=-/etc/gotrue.generated.env -EnvironmentFile=/etc/gotrue.env -EnvironmentFile=-/etc/gotrue.overrides.env - -Slice=services.slice - -[Install] -WantedBy=multi-user.target diff --git a/ansible/playbook.yml b/ansible/playbook.yml index 0991a813a..db9c428a3 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -13,7 +13,7 @@ dest: "00-schema.sql", } - { source: "stat_extension.sql", dest: "01-extension.sql" } - + environment: PATH: /usr/lib/postgresql/bin:{{ ansible_env.PATH }} @@ -40,13 +40,6 @@ import_tasks: tasks/setup-wal-g.yml when: debpkg_mode or nixpkg_mode or stage2_nix - - name: Install Gotrue - import_tasks: tasks/setup-gotrue.yml - tags: - - install-gotrue - - install-supabase-internal - when: debpkg_mode or nixpkg_mode - - name: Install PostgREST import_tasks: tasks/setup-postgrest.yml tags: @@ -96,7 +89,7 @@ src: files/apt_periodic dest: /etc/apt/apt.conf.d/10periodic when: debpkg_mode or nixpkg_mode - + - name: Transfer init SQL files copy: src: files/{{ item.source }} @@ -131,13 +124,13 @@ tags: - install-supabase-internal when: debpkg_mode or stage2_nix - + - name: Finalize AMI import_tasks: tasks/finalize-ami.yml tags: - install-supabase-internal when: debpkg_mode or nixpkg_mode - + - name: Enhance fail2ban import_tasks: tasks/setup-fail2ban.yml when: debpkg_mode or nixpkg_mode @@ -218,7 +211,7 @@ systemctl stop postgresql.service when: stage2_nix - - name: Remove osquery + - name: Remove osquery become: yes shell: | sudo -u ubuntu bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && nix profile remove osquery" diff --git a/ansible/tasks/setup-gotrue.yml b/ansible/tasks/setup-gotrue.yml deleted file mode 100644 index 786f9a767..000000000 --- a/ansible/tasks/setup-gotrue.yml +++ /dev/null @@ -1,66 +0,0 @@ -- name: UFW - Allow connections to GoTrue metrics exporter - ufw: - rule: allow - port: "9122" - -# use this user for the Gotrue build and for running the service -- name: Gotrue - system user - user: name=gotrue - -- name: Setting arch (x86) - set_fact: - arch: "x86" - when: platform == "amd64" - -- name: Setting arch (arm) - set_fact: - arch: "arm64" - when: platform == "arm64" - -- name: gotrue - download commit archive - get_url: - url: "https://github.com/supabase/gotrue/releases/download/v{{ gotrue_release }}/auth-v{{ gotrue_release }}-{{ arch }}.tar.gz" - dest: /tmp/gotrue.tar.gz - checksum: "{{ gotrue_release_checksum }}" - -- name: gotrue - create /opt/gotrue - file: - path: /opt/gotrue - state: directory - owner: gotrue - mode: 0775 - -- name: gotrue - create /etc/auth.d - file: - path: /etc/auth.d - state: directory - owner: gotrue - mode: 0775 - -- name: gotrue - unpack archive in /opt/gotrue - unarchive: - remote_src: yes - src: /tmp/gotrue.tar.gz - dest: /opt/gotrue - owner: gotrue - -# libpq is a C library that enables user programs to communicate with -# the PostgreSQL database server. -# - name: gotrue - system dependencies -# apt: -# pkg: -# - libpq-dev - -- name: gotrue - create service file - template: - src: files/gotrue.service.j2 - dest: /etc/systemd/system/gotrue.service - -- name: gotrue - create optimizations file - template: - src: files/gotrue-optimizations.service.j2 - dest: /etc/systemd/system/gotrue-optimizations.service - -- name: gotrue - reload systemd - systemd: - daemon_reload: yes diff --git a/ansible/vars.yml b/ansible/vars.yml index 8cba94dbb..e5e079580 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -24,9 +24,6 @@ postgrest_release: "13.0.5" postgrest_arm_release_checksum: sha256:7b4eafdaf76bc43b57f603109d460a838f89f949adccd02f452ca339f9a0a0d4 postgrest_x86_release_checksum: sha256:05be2bd48abee6c1691fc7c5d005023466c6989e41a4fc7d1302b8212adb88b5 -gotrue_release: 2.179.0 -gotrue_release_checksum: sha1:e985fce00b2720b747e6a04420910015c4967121 - aws_cli_release: "2.23.11" salt_minion_version: 3007 diff --git a/flake.lock b/flake.lock index 9b67032d5..ab3344146 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,27 @@ { "nodes": { + "blueprint": { + "inputs": { + "nixpkgs": [ + "gotrue", + "nixpkgs" + ], + "systems": "systems_2" + }, + "locked": { + "lastModified": 1755332143, + "narHash": "sha256-jaiZPA5ND7HPJ4U/bzp+BKGOYR14+rIe9tC6XA4jBHU=", + "owner": "numtide", + "repo": "blueprint", + "rev": "3c8bf84e28df2be19cc6623cb3ceeb6fc0839b91", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "blueprint", + "type": "github" + } + }, "flake-compat": { "flake": false, "locked": { @@ -95,6 +117,27 @@ "type": "github" } }, + "gotrue": { + "inputs": { + "blueprint": "blueprint", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1758547438, + "narHash": "sha256-3JLWmqAHTQATV/cvFRfdkIePx0JF3qeRAejuSjdC0uQ=", + "owner": "yvan-sraka", + "repo": "auth", + "rev": "25c80bfdab07c3eb082dd10ba20f592b88bdc4d4", + "type": "github" + }, + "original": { + "owner": "yvan-sraka", + "repo": "auth", + "type": "github" + } + }, "nix-editor": { "inputs": { "nixpkgs": [ @@ -211,6 +254,7 @@ "flake-parts": "flake-parts", "flake-utils": "flake-utils", "git-hooks": "git-hooks", + "gotrue": "gotrue", "nix-editor": "nix-editor", "nix-fast-build": "nix-fast-build", "nix2container": "nix2container", @@ -277,6 +321,21 @@ "type": "github" } }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ diff --git a/flake.nix b/flake.nix index ecea0a91d..4302b67a9 100644 --- a/flake.nix +++ b/flake.nix @@ -33,8 +33,15 @@ inputs.nixpkgs.follows = "nixpkgs"; }; system-manager = { + # FIXME: remove custom branch when this PR is merged: + # https://github.com/numtide/system-manager/pull/266 url = "github:numtide/system-manager/users"; - #url = "git+file:///home/jfroche/projects/numtide/system-manager/fix/return-tmpfile-error"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + gotrue = { + # FIXME: remove custom fork when this PR is merged: + # https://github.com/supabase/auth/pull/2166 + url = "github:yvan-sraka/auth"; inputs.nixpkgs.follows = "nixpkgs"; }; }; diff --git a/nix/systemConfigs.nix b/nix/systemConfigs.nix index 356e591f0..bb3ff32dd 100644 --- a/nix/systemConfigs.nix +++ b/nix/systemConfigs.nix @@ -1,12 +1,19 @@ -{ self, inputs, ... }: +{ + self, + inputs, + ... +}: let mkModules = system: [ + self.systemModules.gotrue self.systemModules.postgres + inputs.gotrue.nixosModules.auth ( { pkgs, ... }: { services.nginx.enable = true; nixpkgs.hostPlatform = system; + supabase.services.gotrue.enable = true; supabase.services.postgres = { enable = true; package = self.packages.${system}."psql_17/bin"; diff --git a/nix/systemModules/default.nix b/nix/systemModules/default.nix index 4dd9eb6cd..ad69c5da8 100644 --- a/nix/systemModules/default.nix +++ b/nix/systemModules/default.nix @@ -6,6 +6,7 @@ flake = { systemModules = { postgres = ./postgres; + gotrue = ./gotrue.nix; }; }; } diff --git a/nix/systemModules/dummy-firewall.nix b/nix/systemModules/dummy-firewall.nix new file mode 100644 index 000000000..bf16fd00d --- /dev/null +++ b/nix/systemModules/dummy-firewall.nix @@ -0,0 +1,6 @@ +{ lib, ... }: +{ + options.networking.firewall = lib.mkOption { + type = lib.types.attrs; + }; +} diff --git a/nix/systemModules/gotrue.nix b/nix/systemModules/gotrue.nix new file mode 100644 index 000000000..1c500c976 --- /dev/null +++ b/nix/systemModules/gotrue.nix @@ -0,0 +1,77 @@ +{ + pkgs, + lib, + config, + self, + system, + ... +}: +let + cfg = config.supabase.services.gotrue; +in +{ + imports = [ + # TODO: actually open the ports it needs with ufw + ./dummy-firewall.nix + ]; + + options = { + supabase.services.gotrue = { + enable = lib.mkEnableOption "Supabase (gotrue) authentication service"; + }; + }; + + config = lib.mkIf cfg.enable { + services.auth = { + enable = true; + package = self.inputs.gotrue.packages.${system}.default; + }; + + supabase.services.postgres = { + initialScript = lib.mkForce ( + 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'; + + -- FIXME: gotrue service needs a postgres role + create role postgres superuser login; alter database postgres owner to postgres; + '' + ); + authentication = '' + host supabase_auth_admin postgres samenet scram-sha-256 + ''; + }; + + systemd.services.gotrue = { + after = lib.mkForce [ "postgresql-setup.service" ]; + wantedBy = lib.mkForce [ + "system-manager.target" + ]; + }; + services.userborn.enable = true; + + # TODO: supabase-admin-api haven't been turned into a system-manager module yet: + # + # systemd.services.gotrue-optimizations = { + # description = "gotrue (auth) optimizations"; + # wantedBy = [ "gotrue.service" ]; + # serviceConfig = { + # Type = "oneshot"; + # # we don't want failures from this command to cause PG startup to fail + # ExecStart = "/bin/bash -c '/opt/supabase-admin-api optimize auth --destination-config-file-path /etc/gotrue/gotrue.generated.env ; exit 0'"; + # ExecStartPost = "/bin/bash -c 'cp -a /etc/gotrue/gotrue.generated.env /etc/auth.d/20_generated.env ; exit 0'"; + # User = "postgrest"; + # }; + # }; + + # TODO: that's what the activation script was doing: + # 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 + }; +} diff --git a/nix/systemModules/tests/test_gotrue.py b/nix/systemModules/tests/test_gotrue.py new file mode 100644 index 000000000..84e6faa04 --- /dev/null +++ b/nix/systemModules/tests/test_gotrue.py @@ -0,0 +1,13 @@ +from time import sleep + + +def test_gotrue_service(host): + sleep( + 5000 + ) # Handy for interactive debugging (with docker exec -it $CONTAINER_ID /bin/bash) + assert host.service("gotrue.service").is_valid + assert host.service("gotrue.service").is_running, ( + "Auth service should be running but failed: {}".format( + host.run("systemctl status gotrue.service").stdout + ) + )