supabase-postgres.git / summary / log / commit / refs
commit 3b2b18a3b09b741ca96b2ffc2875e7674371a4e5
Author: Jean-François Roche <jfroche@pyxel.be>
Commit: GitHub <noreply@github.com>
Date: Tue Nov 04 00:55:09 2025 +0000
feat: multiple versions for the vault extension (#1661)
* feat: multiple versions for the vault extension
Build multiple versions of the vault extension on different PostgreSQL versions.
Add test for the extensions and their upgrade on PostgreSQL 15 and 17.
* fix: nixos tests for pg_repack, pgroonga, and plpgsql_check to use the supabase_admin user
We switched to using the supabase_admin user for our Postgres tests instead of the default postgres user.
This change updates the authentication methods and user management in the NixOS test configurations for the pg_repack, pgroonga, and plpgsql_check extensions.
* fix: nixos test for plv8 extension to use the supabase_admin user
We switched to using the supabase_admin user for our Postgres tests instead of the default postgres user.
This change updates the authentication methods and user management in the NixOS test configurations for the plv8 extension.
* chore: bump one more
---------
Co-authored-by: Sam Rose <samuel@supabase.io>
ansible/vars.yml | 6 +-
nix/ext/tests/default.nix | 16 +++-
nix/ext/tests/lib.py | 4 +-
nix/ext/tests/pg_repack.nix | 16 +++-
nix/ext/tests/pgmq.nix | 14 +++
nix/ext/tests/pgroonga.nix | 18 +++-
nix/ext/tests/plpgsql_check.nix | 16 +++-
nix/ext/tests/plv8.nix | 14 +++
nix/ext/tests/timescaledb.nix | 16 ++++
nix/ext/tests/vault.nix | 200 ++++++++++++++++++++++++++++++++++++++++
nix/ext/vault.nix | 105 ++++++++++++++++-----
nix/ext/versions.json | 18 +++-
12 files changed, 399 insertions(+), 44 deletions(-)
diff --git a/ansible/vars.yml b/ansible/vars.yml
index 691b2fc3..d75fe045 100644
--- a/ansible/vars.yml
+++ b/ansible/vars.yml
@@ -10,9 +10,9 @@ postgres_major:
# Full version strings for each major version
postgres_release:
- postgresorioledb-17: "17.5.1.058-orioledb"
- postgres17: "17.6.1.037"
- postgres15: "15.14.1.037"
+ postgresorioledb-17: "17.5.1.059-orioledb"
+ postgres17: "17.6.1.038"
+ postgres15: "15.14.1.038"
# Non Postgres Extensions
pgbouncer_release: 1.19.0
diff --git a/nix/ext/tests/default.nix b/nix/ext/tests/default.nix
index f8b69cd3..c21cedd2 100644
--- a/nix/ext/tests/default.nix
+++ b/nix/ext/tests/default.nix
@@ -69,12 +69,20 @@ let
enable = true;
package = psql_15;
enableTCPIP = true;
- initialScript = pkgs.writeText "init-postgres-with-password" ''
- CREATE USER test WITH PASSWORD 'secret';
- '';
authentication = ''
- host test postgres samenet scram-sha-256
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
'';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ ];
settings = (installedExtension "15").defaultSettings or { };
};
diff --git a/nix/ext/tests/lib.py b/nix/ext/tests/lib.py
index 3383f249..42b5eb36 100644
--- a/nix/ext/tests/lib.py
+++ b/nix/ext/tests/lib.py
@@ -38,12 +38,12 @@ class PostgresExtensionTest(object):
def run_sql(self, query: str) -> str:
return self.vm.succeed(
- f"""sudo -u postgres psql -t -A -F\",\" -c \"{query}\" """
+ f"""psql -U supabase_admin -d postgres -t -A -F\",\" -c \"{query}\" """
).strip()
def run_sql_file(self, file: str) -> str:
return self.vm.succeed(
- f"""sudo -u postgres psql -v ON_ERROR_STOP=1 -f \"{file}\""""
+ f"""psql -U supabase_admin -d postgres -v ON_ERROR_STOP=1 -f \"{file}\""""
).strip()
def drop_extension(self):
diff --git a/nix/ext/tests/pg_repack.nix b/nix/ext/tests/pg_repack.nix
index 41860d84..dae534d2 100644
--- a/nix/ext/tests/pg_repack.nix
+++ b/nix/ext/tests/pg_repack.nix
@@ -59,12 +59,20 @@ self.inputs.nixpkgs.lib.nixos.runTest {
enable = true;
package = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
enableTCPIP = true;
- initialScript = pkgs.writeText "init-postgres-with-password" ''
- CREATE USER test WITH PASSWORD 'secret';
- '';
authentication = ''
- host test postgres samenet scram-sha-256
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
'';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ ];
};
networking.firewall.allowedTCPPorts = [ config.services.postgresql.settings.port ];
diff --git a/nix/ext/tests/pgmq.nix b/nix/ext/tests/pgmq.nix
index eabebff9..94438d61 100644
--- a/nix/ext/tests/pgmq.nix
+++ b/nix/ext/tests/pgmq.nix
@@ -47,6 +47,20 @@ self.inputs.nixpkgs.lib.nixos.runTest {
services.postgresql = {
enable = true;
package = (postgresqlWithExtension psql_15);
+ authentication = ''
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
+ '';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ ];
settings = (installedExtension "15").defaultSettings or { };
};
diff --git a/nix/ext/tests/pgroonga.nix b/nix/ext/tests/pgroonga.nix
index dd15b918..83af20ac 100644
--- a/nix/ext/tests/pgroonga.nix
+++ b/nix/ext/tests/pgroonga.nix
@@ -60,6 +60,21 @@ self.inputs.nixpkgs.lib.nixos.runTest {
services.postgresql = {
enable = true;
package = psql_15;
+ enableTCPIP = true;
+ authentication = ''
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
+ '';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ ];
};
systemd.services.postgresql.environment.MECAB_DICDIR = "${
self.packages.${pkgs.system}.mecab-naist-jdic
@@ -120,7 +135,6 @@ self.inputs.nixpkgs.lib.nixos.runTest {
"17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
}
extension_name = "${pname}"
- support_upgrade = False
pg17_configuration = "${pg17-configuration}"
ext_has_background_worker = ${
if (installedExtension "15") ? hasBackgroundWorker then "True" else "False"
@@ -135,7 +149,7 @@ self.inputs.nixpkgs.lib.nixos.runTest {
server.wait_for_unit("multi-user.target")
server.wait_for_unit("postgresql.service")
- test = PostgresExtensionTest(server, extension_name, versions, sql_test_directory, support_upgrade)
+ test = PostgresExtensionTest(server, extension_name, versions, sql_test_directory)
with subtest("Check upgrade path with postgresql 15"):
test.check_upgrade_path("15")
diff --git a/nix/ext/tests/plpgsql_check.nix b/nix/ext/tests/plpgsql_check.nix
index 5ab950df..105ed8a8 100644
--- a/nix/ext/tests/plpgsql_check.nix
+++ b/nix/ext/tests/plpgsql_check.nix
@@ -61,12 +61,20 @@ self.inputs.nixpkgs.lib.nixos.runTest {
enable = true;
package = psql_15;
enableTCPIP = true;
- initialScript = pkgs.writeText "init-postgres-with-password" ''
- CREATE USER test WITH PASSWORD 'secret';
- '';
authentication = ''
- host test postgres samenet scram-sha-256
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
'';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ ];
settings = (installedExtension "15").defaultSettings or { };
};
diff --git a/nix/ext/tests/plv8.nix b/nix/ext/tests/plv8.nix
index 37b4da82..085ddd42 100644
--- a/nix/ext/tests/plv8.nix
+++ b/nix/ext/tests/plv8.nix
@@ -60,6 +60,20 @@ self.inputs.nixpkgs.lib.nixos.runTest {
services.postgresql = {
enable = true;
package = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
+ authentication = ''
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
+ '';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ ];
};
};
testScript =
diff --git a/nix/ext/tests/timescaledb.nix b/nix/ext/tests/timescaledb.nix
index 85755a82..1bab187d 100644
--- a/nix/ext/tests/timescaledb.nix
+++ b/nix/ext/tests/timescaledb.nix
@@ -46,6 +46,22 @@ self.inputs.nixpkgs.lib.nixos.runTest {
services.postgresql = {
enable = true;
package = (postgresqlWithExtension psql_15);
+ authentication = ''
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
+ '';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ { name = "service_role"; }
+ ];
+
settings = {
shared_preload_libraries = "timescaledb";
};
diff --git a/nix/ext/tests/vault.nix b/nix/ext/tests/vault.nix
new file mode 100644
index 00000000..f5cbd872
--- /dev/null
+++ b/nix/ext/tests/vault.nix
@@ -0,0 +1,200 @@
+{ self, pkgs }:
+let
+ pname = "supabase_vault";
+ inherit (pkgs) lib;
+ installedExtension =
+ postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all";
+ versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions;
+ postgresqlWithExtension =
+ postgresql:
+ let
+ majorVersion = lib.versions.major postgresql.version;
+ pkg = pkgs.buildEnv {
+ name = "postgresql-${majorVersion}-${pname}";
+ paths = [
+ postgresql
+ postgresql.lib
+ (installedExtension majorVersion)
+ self.packages.${pkgs.system}."psql_${majorVersion}/exts/pgsodium-all" # dependency
+ ];
+ passthru = {
+ inherit (postgresql) version psqlSchema;
+ lib = pkg;
+ withPackages = _: pkg;
+ };
+ nativeBuildInputs = [ pkgs.makeWrapper ];
+ pathsToLink = [
+ "/"
+ "/bin"
+ "/lib"
+ ];
+ postBuild = ''
+ wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
+ wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
+ wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
+ '';
+ };
+ in
+ pkg;
+ vaultGetKey = lib.getExe (
+ pkgs.writeShellScriptBin "vault-getkey" ''
+ echo 0000000000000000000000000000000000000000000000000000000000000000
+ ''
+ );
+ psql_15 = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
+ psql_17 = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
+in
+self.inputs.nixpkgs.lib.nixos.runTest {
+ name = pname;
+ hostPkgs = pkgs;
+ nodes.server =
+ { config, ... }:
+ {
+ virtualisation = {
+ forwardPorts = [
+ {
+ from = "host";
+ host.port = 13022;
+ guest.port = 22;
+ }
+ ];
+ };
+
+ services.postgresql = {
+ enable = true;
+ package = psql_15;
+ authentication = ''
+ local all postgres peer map=postgres
+ local all all peer map=root
+ '';
+ identMap = ''
+ root root supabase_admin
+ postgres postgres postgres
+ '';
+ initialScript = pkgs.writeText "vault-init.sql" ''
+ CREATE SCHEMA vault;
+ '';
+ ensureUsers = [
+ {
+ name = "supabase_admin";
+ ensureClauses.superuser = true;
+ }
+ { name = "service_role"; }
+ ];
+ settings = {
+ "shared_preload_libraries" = "${pname},pgsodium";
+ "pgsodium.getkey_script" = vaultGetKey;
+ "vault.getkey_script" = vaultGetKey;
+ };
+ };
+
+ specialisation.postgresql17.configuration = {
+ services.postgresql = {
+ package = lib.mkForce psql_17;
+ };
+
+ systemd.services.postgresql-migrate = {
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ User = "postgres";
+ Group = "postgres";
+ StateDirectory = "postgresql";
+ WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}";
+ };
+ script =
+ let
+ oldPostgresql = psql_15;
+ newPostgresql = psql_17;
+ oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}";
+ newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}";
+ in
+ ''
+ if [[ ! -d ${newDataDir} ]]; then
+ install -d -m 0700 -o postgres -g postgres "${newDataDir}"
+ ${newPostgresql}/bin/initdb -D "${newDataDir}"
+ echo "shared_preload_libraries = '${pname},pgsodium'" >> "${newDataDir}/postgresql.conf"
+ echo "vault.getkey_script = '${vaultGetKey}'" >> "${newDataDir}/postgresql.conf";
+ echo "pgsodium.getkey_script = '${vaultGetKey}'" >> "${newDataDir}/postgresql.conf";
+ ${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
+ --old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
+ else
+ echo "${newDataDir} already exists"
+ fi
+ '';
+ };
+
+ systemd.services.postgresql = {
+ after = [ "postgresql-migrate.service" ];
+ requires = [ "postgresql-migrate.service" ];
+ };
+ };
+ };
+ testScript =
+ { nodes, ... }:
+ let
+ pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17";
+ in
+ ''
+ from pathlib import Path
+ versions = {
+ "15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}],
+ "17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
+ }
+ extension_name = "${pname}"
+ support_upgrade = True
+ pg17_configuration = "${pg17-configuration}"
+ ext_has_background_worker = ${
+ if (installedExtension "15") ? hasBackgroundWorker then "True" else "False"
+ }
+ sql_test_directory = Path("${../../tests}")
+ pg_regress_test_name = "${(installedExtension "15").pgRegressTestName or pname}"
+
+ ${builtins.readFile ./lib.py}
+
+ start_all()
+
+ server.wait_for_unit("multi-user.target")
+ server.wait_for_unit("postgresql.service")
+
+ test = PostgresExtensionTest(server, extension_name, versions, sql_test_directory, support_upgrade)
+
+
+ with subtest("Check upgrade path with postgresql 15"):
+ test.check_upgrade_path("15")
+
+ with subtest("Check pg_regress with postgresql 15 after extension upgrade"):
+ test.run_sql_file("${../../../ansible/files/postgresql_extension_custom_scripts/supabase_vault/after-create.sql}")
+ test.check_pg_regress(Path("${psql_15}/lib/pgxs/src/test/regress/pg_regress"), "15", pg_regress_test_name)
+
+ last_version = None
+ with subtest("Check the install of the last version of the extension"):
+ last_version = test.check_install_last_version("15")
+
+ with subtest("Check pg_regress with postgresql 15 after installing the last version"):
+ test.run_sql_file("${../../../ansible/files/postgresql_extension_custom_scripts/supabase_vault/after-create.sql}")
+ test.check_pg_regress(Path("${psql_15}/lib/pgxs/src/test/regress/pg_regress"), "15", pg_regress_test_name)
+
+ with subtest("switch to postgresql 17"):
+ server.succeed(
+ f"{pg17_configuration}/bin/switch-to-configuration test >&2"
+ )
+
+ with subtest("Check last version of the extension after postgresql upgrade"):
+ test.assert_version_matches(last_version)
+
+ with subtest("Check upgrade path with postgresql 17"):
+ test.check_upgrade_path("17")
+
+ with subtest("Check pg_regress with postgresql 17 after extension upgrade"):
+ test.run_sql_file("${../../../ansible/files/postgresql_extension_custom_scripts/supabase_vault/after-create.sql}")
+ test.check_pg_regress(Path("${psql_17}/lib/pgxs/src/test/regress/pg_regress"), "17", pg_regress_test_name)
+
+ with subtest("Check the install of the last version of the extension"):
+ test.check_install_last_version("17")
+
+ with subtest("Check pg_regress with postgresql 17 after installing the last version"):
+ test.run_sql_file("${../../../ansible/files/postgresql_extension_custom_scripts/supabase_vault/after-create.sql}")
+ test.check_pg_regress(Path("${psql_17}/lib/pgxs/src/test/regress/pg_regress"), "17", pg_regress_test_name)
+ '';
+}
diff --git a/nix/ext/vault.nix b/nix/ext/vault.nix
index 275d6967..c518e1e1 100644
--- a/nix/ext/vault.nix
+++ b/nix/ext/vault.nix
@@ -1,39 +1,96 @@
{
+ pkgs,
lib,
stdenv,
fetchFromGitHub,
libsodium,
postgresql,
}:
+let
+ pname = "supabase_vault";
-stdenv.mkDerivation rec {
- pname = "vault";
- version = "0.3.1";
+ # Load version configuration from external file
+ allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
- buildInputs = [
- libsodium
- postgresql
- ];
+ # Filter versions compatible with current PostgreSQL version
+ supportedVersions = lib.filterAttrs (
+ _: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
+ ) allVersions;
- src = fetchFromGitHub {
- owner = "supabase";
- repo = pname;
- rev = "refs/tags/v${version}";
- hash = "sha256-MC87bqgtynnDhmNZAu96jvfCpsGDCPB0g5TZfRQHd30=";
- };
+ # Derived version information
+ versions = lib.naturalSort (lib.attrNames supportedVersions);
+ latestVersion = lib.last versions;
+ numberOfVersions = builtins.length versions;
+ packages = builtins.attrValues (
+ lib.mapAttrs (name: value: build name value.hash) supportedVersions
+ );
+
+ # Build function for individual pgsodium versions
+ build =
+ version: hash:
+
+ stdenv.mkDerivation rec {
+ inherit pname version;
+
+ buildInputs = [
+ libsodium
+ postgresql
+ ];
- installPhase = ''
- mkdir -p $out/{lib,share/postgresql/extension}
+ src = fetchFromGitHub {
+ owner = "supabase";
+ repo = "vault";
+ rev = "refs/tags/v${version}";
+ inherit hash;
+ };
- install -D *${postgresql.dlSuffix} $out/lib
- install -D -t $out/share/postgresql/extension sql/*.sql
- install -D -t $out/share/postgresql/extension *.control
- '';
+ installPhase =
+ ''
+ mkdir -p $out/{lib,share/postgresql/extension}
+
+ # Create version-specific control file
+ sed -e "/^default_version =/d" \
+ -e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
+ ${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
+
+ ''
+ # for versions <= 0.2.8, we don't have a library to install
+ + lib.optionalString (builtins.compareVersions "0.2.8" version < 0) ''
+ # Install shared library with version suffix
+ mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix}
+
+ # For the latest version, copy the sql files
+ if [[ "${version}" == "${latestVersion}" ]]; then
+ install -D -t $out/share/postgresql/extension sql/*.sql
+ {
+ echo "default_version = '${latestVersion}'"
+ cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
+ } > $out/share/postgresql/extension/${pname}.control
+ fi
+ ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix}
+ '';
+
+ meta = with lib; {
+ description = "Store encrypted secrets in PostgreSQL";
+ homepage = "https://github.com/supabase/vault";
+ platforms = postgresql.meta.platforms;
+ license = licenses.postgresql;
+ };
+ };
+in
+pkgs.buildEnv {
+ name = pname;
+ paths = packages;
+ pathsToLink = [
+ "/lib"
+ "/share/postgresql/extension"
+ ];
- meta = with lib; {
- description = "Store encrypted secrets in PostgreSQL";
- homepage = "https://github.com/supabase/${pname}";
- platforms = postgresql.meta.platforms;
- license = licenses.postgresql;
+ passthru = {
+ inherit versions numberOfVersions;
+ pname = "${pname}-all";
+ version =
+ "multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
+ pgRegressTestName = "vault";
};
}
diff --git a/nix/ext/versions.json b/nix/ext/versions.json
index d106c2c8..e91d7919 100644
--- a/nix/ext/versions.json
+++ b/nix/ext/versions.json
@@ -459,7 +459,23 @@
"revision": "1.3.14"
}
},
- "timescaledb": {
+ "supabase_vault": {
+ "0.2.8": {
+ "postgresql": [
+ "15",
+ "17"
+ ],
+ "hash": "sha256-+QBd4/wj1n33ynt7Gopr6g3xT+TLJ9jMhLffdYeRy4k="
+ },
+ "0.3.1": {
+ "postgresql": [
+ "15",
+ "17"
+ ],
+ "hash": "sha256-MC87bqgtynnDhmNZAu96jvfCpsGDCPB0g5TZfRQHd30="
+ }
+ },
+ "timescaledb": {
"2.9.1": {
"postgresql": [
"15"
[parent: f8c523cb5b44]