Skip to content

Commit 536cd9b

Browse files
committed
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.
1 parent 2b07c9c commit 536cd9b

File tree

4 files changed

+256
-22
lines changed

4 files changed

+256
-22
lines changed

flake.nix

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,8 @@
13821382
inherit (basePackages) wal-g-2 wal-g-3 dbmate-tool pg_regress;
13831383
} // pkgs.lib.optionalAttrs (system == "aarch64-linux") {
13841384
inherit (basePackages) postgresql_15_debug postgresql_15_src postgresql_orioledb-17_debug postgresql_orioledb-17_src postgresql_17_debug postgresql_17_src;
1385+
} // pkgs.lib.optionalAttrs (system == "x86_64-linux") {
1386+
vault = import ./nix/ext/tests/vault.nix { inherit self; inherit pkgs; };
13851387
};
13861388

13871389
# Apps is a list of names of things that can be executed with 'nix run';

nix/ext/tests/vault.nix

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
{ self, pkgs }:
2+
let
3+
pname = "supabase_vault";
4+
inherit (pkgs) lib;
5+
installedExtension =
6+
postgresMajorVersion: self.packages.${pkgs.system}."psql_${postgresMajorVersion}/exts/${pname}-all";
7+
versions = postgresqlMajorVersion: (installedExtension postgresqlMajorVersion).versions;
8+
postgresqlWithExtension =
9+
postgresql:
10+
let
11+
majorVersion = lib.versions.major postgresql.version;
12+
pkg = pkgs.buildEnv {
13+
name = "postgresql-${majorVersion}-${pname}";
14+
paths = [
15+
postgresql
16+
postgresql.lib
17+
(installedExtension majorVersion)
18+
self.packages.${pkgs.system}."psql_${majorVersion}/exts/pgsodium" # dependency
19+
];
20+
passthru = {
21+
inherit (postgresql) version psqlSchema;
22+
lib = pkg;
23+
withPackages = _: pkg;
24+
};
25+
nativeBuildInputs = [ pkgs.makeWrapper ];
26+
pathsToLink = [
27+
"/"
28+
"/bin"
29+
"/lib"
30+
];
31+
postBuild = ''
32+
wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
33+
wrapProgram $out/bin/pg_ctl --set NIX_PGLIBDIR $out/lib
34+
wrapProgram $out/bin/pg_upgrade --set NIX_PGLIBDIR $out/lib
35+
'';
36+
};
37+
in
38+
pkg;
39+
vaultGetKey = lib.getExe (
40+
pkgs.writeShellScriptBin "vault-getkey" ''
41+
echo 0000000000000000000000000000000000000000000000000000000000000000
42+
''
43+
);
44+
in
45+
self.inputs.nixpkgs.lib.nixos.runTest {
46+
name = pname;
47+
hostPkgs = pkgs;
48+
nodes.server =
49+
{ config, ... }:
50+
{
51+
virtualisation = {
52+
forwardPorts = [
53+
{
54+
from = "host";
55+
host.port = 13022;
56+
guest.port = 22;
57+
}
58+
];
59+
};
60+
61+
services.postgresql = {
62+
enable = true;
63+
package = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
64+
settings = {
65+
"shared_preload_libraries" = "${pname},pgsodium";
66+
"pgsodium.getkey_script" = vaultGetKey;
67+
"vault.getkey_script" = vaultGetKey;
68+
};
69+
};
70+
71+
specialisation.postgresql17.configuration = {
72+
services.postgresql = {
73+
package = lib.mkForce (postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17);
74+
};
75+
76+
systemd.services.postgresql-migrate = {
77+
serviceConfig = {
78+
Type = "oneshot";
79+
RemainAfterExit = true;
80+
User = "postgres";
81+
Group = "postgres";
82+
StateDirectory = "postgresql";
83+
WorkingDirectory = "${builtins.dirOf config.services.postgresql.dataDir}";
84+
};
85+
script =
86+
let
87+
oldPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_15;
88+
newPostgresql = postgresqlWithExtension self.packages.${pkgs.system}.postgresql_17;
89+
oldDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${oldPostgresql.psqlSchema}";
90+
newDataDir = "${builtins.dirOf config.services.postgresql.dataDir}/${newPostgresql.psqlSchema}";
91+
in
92+
''
93+
if [[ ! -d ${newDataDir} ]]; then
94+
install -d -m 0700 -o postgres -g postgres "${newDataDir}"
95+
${newPostgresql}/bin/initdb -D "${newDataDir}"
96+
echo "shared_preload_libraries = '${pname},pgsodium'" >> "${newDataDir}/postgresql.conf"
97+
echo "vault.getkey_script = '${vaultGetKey}'" >> "${newDataDir}/postgresql.conf";
98+
echo "pgsodium.getkey_script = '${vaultGetKey}'" >> "${newDataDir}/postgresql.conf";
99+
${newPostgresql}/bin/pg_upgrade --old-datadir "${oldDataDir}" --new-datadir "${newDataDir}" \
100+
--old-bindir "${oldPostgresql}/bin" --new-bindir "${newPostgresql}/bin"
101+
else
102+
echo "${newDataDir} already exists"
103+
fi
104+
'';
105+
};
106+
107+
systemd.services.postgresql = {
108+
after = [ "postgresql-migrate.service" ];
109+
requires = [ "postgresql-migrate.service" ];
110+
};
111+
};
112+
113+
};
114+
testScript =
115+
{ nodes, ... }:
116+
let
117+
pg17-configuration = "${nodes.server.system.build.toplevel}/specialisation/postgresql17";
118+
in
119+
''
120+
versions = {
121+
"15": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "15"))}],
122+
"17": [${lib.concatStringsSep ", " (map (s: ''"${s}"'') (versions "17"))}],
123+
}
124+
125+
def run_sql(query):
126+
return server.succeed(f"""sudo -u postgres psql -t -A -F\",\" -c \"{query}\" """).strip()
127+
128+
def check_upgrade_path(pg_version):
129+
with subtest("Check ${pname} upgrade path"):
130+
firstVersion = versions[pg_version][0]
131+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION IF EXISTS ${pname};'")
132+
run_sql(f"""CREATE EXTENSION ${pname} WITH VERSION '{firstVersion}' CASCADE;""")
133+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
134+
assert installed_version == firstVersion, f"Expected ${pname} version {firstVersion}, but found {installed_version}"
135+
for version in versions[pg_version][1:]:
136+
run_sql(f"""ALTER EXTENSION ${pname} UPDATE TO '{version}';""")
137+
installed_version = run_sql(r"""SELECT extversion FROM pg_extension WHERE extname = '${pname}';""")
138+
assert installed_version == version, f"Expected ${pname} version {version}, but found {installed_version}"
139+
140+
start_all()
141+
142+
server.wait_for_unit("multi-user.target")
143+
server.wait_for_unit("postgresql.service")
144+
145+
check_upgrade_path("15")
146+
147+
with subtest("Check ${pname} latest extension version"):
148+
server.succeed("sudo -u postgres psql -c 'DROP EXTENSION ${pname};'")
149+
server.succeed("sudo -u postgres psql -c 'CREATE EXTENSION ${pname} CASCADE;'")
150+
installed_extensions=run_sql(r"""SELECT extname, extversion FROM pg_extension;""")
151+
latestVersion = versions["15"][-1]
152+
assert f"${pname},{latestVersion}" in installed_extensions
153+
154+
with subtest("switch to postgresql 17"):
155+
server.succeed(
156+
"${pg17-configuration}/bin/switch-to-configuration test >&2"
157+
)
158+
159+
check_upgrade_path("17")
160+
'';
161+
}

nix/ext/vault.nix

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,83 @@
1-
{ lib, stdenv, fetchFromGitHub, libsodium, postgresql }:
1+
{ pkgs, lib, stdenv, fetchFromGitHub, libsodium, postgresql }:
2+
let
3+
pname = "supabase_vault";
24

3-
stdenv.mkDerivation rec {
4-
pname = "vault";
5-
version = "0.3.1";
5+
# Load version configuration from external file
6+
allVersions = (builtins.fromJSON (builtins.readFile ./versions.json)).${pname};
67

7-
buildInputs = [ libsodium postgresql ];
8+
# Filter versions compatible with current PostgreSQL version
9+
supportedVersions = lib.filterAttrs (
10+
_: value: builtins.elem (lib.versions.major postgresql.version) value.postgresql
11+
) allVersions;
812

9-
src = fetchFromGitHub {
10-
owner = "supabase";
11-
repo = pname;
12-
rev = "refs/tags/v${version}";
13-
hash = "sha256-MC87bqgtynnDhmNZAu96jvfCpsGDCPB0g5TZfRQHd30=";
14-
};
13+
# Derived version information
14+
versions = lib.naturalSort (lib.attrNames supportedVersions);
15+
latestVersion = lib.last versions;
16+
numberOfVersions = builtins.length versions;
17+
packages = builtins.attrValues (
18+
lib.mapAttrs (name: value: build name value.hash) supportedVersions
19+
);
20+
21+
# Build function for individual pgsodium versions
22+
build =
23+
version: hash:
24+
25+
stdenv.mkDerivation rec {
26+
inherit pname version;
27+
28+
buildInputs = [ libsodium postgresql ];
29+
30+
src = fetchFromGitHub {
31+
owner = "supabase";
32+
repo = "vault";
33+
rev = "refs/tags/v${version}";
34+
inherit hash;
35+
};
36+
37+
installPhase = ''
38+
mkdir -p $out/{lib,share/postgresql/extension}
39+
40+
41+
# Create version-specific control file
42+
sed -e "/^default_version =/d" \
43+
-e "s|^module_pathname = .*|module_pathname = '\$libdir/${pname}'|" \
44+
${pname}.control > $out/share/postgresql/extension/${pname}--${version}.control
45+
46+
'' + lib.optionalString (builtins.compareVersions "0.2.8" version < 0) ''
47+
# Install shared library with version suffix
48+
mv ${pname}${postgresql.dlSuffix} $out/lib/${pname}-${version}${postgresql.dlSuffix}
1549
16-
installPhase = ''
17-
mkdir -p $out/{lib,share/postgresql/extension}
50+
# For the latest version, copy the sql files
51+
if [[ "${version}" == "${latestVersion}" ]]; then
52+
install -D -t $out/share/postgresql/extension sql/*.sql
53+
{
54+
echo "default_version = '${latestVersion}'"
55+
cat $out/share/postgresql/extension/${pname}--${latestVersion}.control
56+
} > $out/share/postgresql/extension/${pname}.control
57+
fi
58+
ln -sfn ${pname}-${latestVersion}${postgresql.dlSuffix} $out/lib/${pname}${postgresql.dlSuffix}
59+
'';
1860

19-
install -D *${postgresql.dlSuffix} $out/lib
20-
install -D -t $out/share/postgresql/extension sql/*.sql
21-
install -D -t $out/share/postgresql/extension *.control
22-
'';
61+
meta = with lib; {
62+
description = "Store encrypted secrets in PostgreSQL";
63+
homepage = "https://github.com/supabase/${pname}";
64+
platforms = postgresql.meta.platforms;
65+
license = licenses.postgresql;
66+
};
67+
};
68+
in
69+
pkgs.buildEnv {
70+
name = pname;
71+
paths = packages;
72+
pathsToLink = [
73+
"/lib"
74+
"/share/postgresql/extension"
75+
];
2376

24-
meta = with lib; {
25-
description = "Store encrypted secrets in PostgreSQL";
26-
homepage = "https://github.com/supabase/${pname}";
27-
platforms = postgresql.meta.platforms;
28-
license = licenses.postgresql;
77+
passthru = {
78+
inherit versions numberOfVersions;
79+
pname = "${pname}-all";
80+
version =
81+
"multi-" + lib.concatStringsSep "-" (map (v: lib.replaceStrings [ "." ] [ "-" ] v) versions);
2982
};
3083
}

nix/ext/versions.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"supabase_vault": {
3+
"0.2.8": {
4+
"postgresql": [
5+
"15",
6+
"17"
7+
],
8+
"hash": "sha256-+QBd4/wj1n33ynt7Gopr6g3xT+TLJ9jMhLffdYeRy4k="
9+
},
10+
"0.3.1": {
11+
"postgresql": [
12+
"15",
13+
"17"
14+
],
15+
"hash": "sha256-MC87bqgtynnDhmNZAu96jvfCpsGDCPB0g5TZfRQHd30="
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)