From 384b6961a95915ec691f5ed188f577d17dd7a13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Mon, 5 Oct 2026 13:29:18 +0300 Subject: [PATCH 1/5] chore(deps): update nixpkgs but pin it for postgres Postgres, its extensions, and everything loaded into the postgres process stay on nixpkgs fb7944c, glibc 2.40, through a new nixpkgs-pg17 input. After a glibc bump, Postgres warns that the collation version stored in each database differs from the running one. The main nixpkgs input moves to the nixos-26.05 channel so it can be updated on a schedule. All PG outputs keep their drvPath on x86_64-linux, aarch64-linux, and aarch64-darwin: psql_*, every extension, postgresql_*, postgres-env, site-env, extension catalogs, gatekeeper, and groonga. Also: - nix-darwin follows its nix-darwin-26.05 branch to match nixpkgs. - ext tests import QemuMachine, since 26.05 dropped test_driver Machine. - hstore_copy_binary writes inside the data dir, not a shared /tmp path that collides across unsandboxed darwin builds. Co-Authored-By: Claude Opus 5.5 --- flake.lock | 28 +++++++++--- flake.nix | 8 +++- nix/docs/updating-dependencies.md | 9 ++++ nix/ext/tests/lib.py | 4 +- nix/nixpkgs.nix | 52 +++++++++++++---------- nix/packages/default.nix | 24 ++++++----- nix/packages/extension-catalog.nix | 20 ++++----- nix/packages/postgres-env.nix | 10 ++--- nix/packages/postgres.nix | 18 ++++---- nix/packages/site-env.nix | 10 +++-- nix/tests/expected/hstore_copy_binary.out | 4 +- nix/tests/sql/hstore_copy_binary.sql | 4 +- 12 files changed, 116 insertions(+), 75 deletions(-) diff --git a/flake.lock b/flake.lock index b48d1c2940..356e6ef0cb 100644 --- a/flake.lock +++ b/flake.lock @@ -154,15 +154,16 @@ ] }, "locked": { - "lastModified": 1767718503, - "narHash": "sha256-V+VkFs0aSG0ca8p/N3gib7FAf4cq9jyr5Gm+ZBrHQpo=", + "lastModified": 1783744694, + "narHash": "sha256-2cp6N3rrwnGYLTx9l6N+NI+kwrCWxvJUbj5WJhvB29A=", "owner": "nix-darwin", "repo": "nix-darwin", - "rev": "9f48ffaca1f44b3e590976b4da8666a9e86e6eb1", + "rev": "c3e90c89649b07d1a96e4b9dd6cd0d6e44b91a74", "type": "github" }, "original": { "owner": "nix-darwin", + "ref": "nix-darwin-26.05", "repo": "nix-darwin", "type": "github" } @@ -279,17 +280,31 @@ "type": "github" } }, - "nixpkgs_2": { + "nixpkgs-pg17": { "locked": { - "lastModified": 1767379071, + "lastModified": 1767460468, "narHash": "sha256-3xDI4xtzovwqE/eAxCwmXxUqBg6Yoam2L1u0IwRNhW4=", "rev": "fb7944c166a3b630f177938e478f0378e64ce108", "type": "tarball", "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz" }, + "original": { + "rev": "fb7944c166a3b630f177938e478f0378e64ce108", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1790920529, + "narHash": "sha256-S5MjznoY0gbQbcANPLz5RYjg+5/WQmFRgNbHcP+ydcg=", + "rev": "774debe7a0d1b496e35677ad955a1011c6ff74f3", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.11045.774debe7a0d1/nixexprs.tar.xz" + }, "original": { "type": "tarball", - "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz" + "url": "https://channels.nixos.org/nixos-26.05/nixexprs.tar.xz" } }, "root": { @@ -305,6 +320,7 @@ "nix2container": "nix2container", "nixpkgs": "nixpkgs_2", "nixpkgs-oldstable": "nixpkgs-oldstable", + "nixpkgs-pg17": "nixpkgs-pg17", "rust-overlay": "rust-overlay", "treefmt-nix": "treefmt-nix" } diff --git a/flake.nix b/flake.nix index 828a384e95..f27f73ee86 100644 --- a/flake.nix +++ b/flake.nix @@ -14,7 +14,7 @@ multigres.url = "github:multigres/multigres"; multigres.flake = false; nix-darwin.inputs.nixpkgs.follows = "nixpkgs"; - nix-darwin.url = "github:nix-darwin/nix-darwin"; + nix-darwin.url = "github:nix-darwin/nix-darwin/nix-darwin-26.05"; nix-editor.inputs.nixpkgs.follows = "nixpkgs"; nix-editor.inputs.utils.follows = "flake-utils"; nix-editor.url = "github:snowfallorg/nix-editor"; @@ -26,7 +26,11 @@ # Pin to a specific nixpkgs version that has compatible v8 and curl versions # for extensions that require older package versions nixpkgs-oldstable.url = "github:NixOS/nixpkgs/a76c4553d7e741e17f289224eda135423de0491d"; - nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz"; + # Postgres, its extensions, and anything else loaded into the postgres + # process stay on glibc 2.40. Postgres warns when the running glibc's + # collation version differs from the one stored in each database. + nixpkgs-pg17.url = "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz?rev=fb7944c166a3b630f177938e478f0378e64ce108"; + nixpkgs.url = "https://channels.nixos.org/nixos-26.05/nixexprs.tar.xz"; rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; rust-overlay.url = "github:oxalica/rust-overlay"; treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; diff --git a/nix/docs/updating-dependencies.md b/nix/docs/updating-dependencies.md index 695d85a852..ec96af2c71 100644 --- a/nix/docs/updating-dependencies.md +++ b/nix/docs/updating-dependencies.md @@ -67,3 +67,12 @@ Similar patterns can be followed for other dependencies defined in the nix packa 2. Update version numbers and hashes 3. Run local tests 4. Verify functionality before creating PR + +## Updating nixpkgs + +The flake uses two nixpkgs inputs: + +- `nixpkgs-pg17` pins the nixpkgs that builds Postgres, every extension, and anything loaded into the postgres process, such as `supabase-groonga` and the `gatekeeper` PAM module. It pins glibc 2.40. After a glibc change, Postgres warns that the running collation version differs from the one stored in each database. Leave this input alone unless you plan that migration. Code built against a newer glibc fails to load into a postgres process running an older one. +- `nixpkgs` tracks the current NixOS stable channel and builds everything else. Update it with `nix flake update nixpkgs`. When the stable release changes, also move `nix-darwin` to the matching `nix-darwin-YY.MM` branch. + +After an update, check that every Postgres output keeps its drvPath, for example `nix eval --raw .#packages.x86_64-linux."psql_17/bin".drvPath`. diff --git a/nix/ext/tests/lib.py b/nix/ext/tests/lib.py index b2cdbb7bc4..5f677f1729 100644 --- a/nix/ext/tests/lib.py +++ b/nix/ext/tests/lib.py @@ -7,7 +7,7 @@ from typing import Sequence, Mapping, Optional from pathlib import Path -from test_driver.machine import Machine +from test_driver.machine import QemuMachine Versions = Mapping[str, Sequence[str]] @@ -15,7 +15,7 @@ class PostgresExtensionTest(object): def __init__( self, - vm: Machine, + vm: QemuMachine, extension_name: str, versions: Versions, sql_test_dir: Path, diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 34ba4bd604..35d3ed482a 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -2,29 +2,35 @@ { perSystem = { system, ... }: + let + mkPkgs = + nixpkgs: + import nixpkgs { + inherit system; + config.allowUnfree = true; + permittedInsecurePackages = [ "v8-9.7.106.18" ]; + overlays = [ + (import inputs.rust-overlay) + self.overlays.default + ( + let + # Provide older versions of packages required by some extensions + oldstable = import inputs.nixpkgs-oldstable { + inherit system; + config.allowUnfree = true; + }; + in + _final: _prev: { + curl_8_6 = oldstable.curl; + v8_oldstable = oldstable.v8; + } + ) + inputs.devshell.overlays.default + ]; + }; + in { - _module.args.pkgs = import inputs.nixpkgs { - inherit system; - config.allowUnfree = true; - permittedInsecurePackages = [ "v8-9.7.106.18" ]; - overlays = [ - (import inputs.rust-overlay) - self.overlays.default - ( - let - # Provide older versions of packages required by some extensions - oldstable = import inputs.nixpkgs-oldstable { - inherit system; - config.allowUnfree = true; - }; - in - _final: _prev: { - curl_8_6 = oldstable.curl; - v8_oldstable = oldstable.v8; - } - ) - inputs.devshell.overlays.default - ]; - }; + _module.args.pkgs = mkPkgs inputs.nixpkgs; + _module.args.pkgs-pg17 = mkPkgs inputs.nixpkgs-pg17; }; } diff --git a/nix/packages/default.nix b/nix/packages/default.nix index bcb8ab0050..278f43c79c 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -11,6 +11,7 @@ inputs', lib, pkgs, + pkgs-pg17, self', ... }: @@ -22,14 +23,14 @@ let postgresqlPackage = self'.packages."postgresql_${version}"; in - pkgs.callPackage ../ext/pg_regress.nix { postgresql = postgresqlPackage; }; + pkgs-pg17.callPackage ../ext/pg_regress.nix { postgresql = postgresqlPackage; }; # Function to create the pg_isolation_regress package makePgIsolationRegress = version: let postgresqlPackage = self'.packages."postgresql_${version}"; in - pkgs.callPackage ../ext/pg_isolation_regress.nix { postgresql = postgresqlPackage; }; + pkgs-pg17.callPackage ../ext/pg_isolation_regress.nix { postgresql = postgresqlPackage; }; pgsqlSuperuser = "supabase_admin"; supascan-pkgs = pkgs.callPackage ./supascan.nix { inherit (pkgs) lib; @@ -64,14 +65,17 @@ github-matrix = pkgs.callPackage ./github-matrix { nix-eval-jobs = inputs'.nix-eval-jobs.packages.default; }; - gatekeeper = pkgs.callPackage ./gatekeeper.nix { inherit inputs pkgs; }; - supabase-groonga = pkgs.callPackage ../ext/pgroonga/groonga.nix { }; + gatekeeper = pkgs-pg17.callPackage ./gatekeeper.nix { + inherit inputs; + pkgs = pkgs-pg17; + }; + supabase-groonga = pkgs-pg17.callPackage ../ext/pgroonga/groonga.nix { }; http-mock-server = pkgs.callPackage ./http-mock-server.nix { }; image-size-analyzer = pkgs.callPackage ./image-size-analyzer.nix { }; local-infra-bootstrap = pkgs.callPackage ./local-infra-bootstrap.nix { }; - mecab-naist-jdic = pkgs.callPackage ./mecab-naist-jdic.nix { }; + mecab-naist-jdic = pkgs-pg17.callPackage ./mecab-naist-jdic.nix { }; migrate-tool = pkgs.callPackage ./migrate-tool.nix { psql_15 = self'.packages."psql_15/bin"; }; - overlayfs-on-package = pkgs.callPackage ./overlayfs-on-package.nix { }; + overlayfs-on-package = pkgs-pg17.callPackage ./overlayfs-on-package.nix { }; packer = pkgs.callPackage ./packer.nix { inherit inputs; }; pg-activity = inputs.nixpkgs.legacyPackages.${pkgs.stdenv.hostPlatform.system}.pg_activity; pg-backrest = pkgs.callPackage ./pg-backrest.nix { }; @@ -79,7 +83,7 @@ multigres-src = inputs.multigres; }; pg-restore = pkgs.callPackage ./pg-restore.nix { psql_15 = self'.packages."psql_15/bin"; }; - pg_prove = pkgs.perlPackages.TAPParserSourceHandlerpgTAP; + pg_prove = pkgs-pg17.perlPackages.TAPParserSourceHandlerpgTAP; pg_regress = makePgRegress activeVersion; pg_isolation_regress = makePgIsolationRegress activeVersion; run-testinfra = pkgs.callPackage ./run-testinfra.nix { }; @@ -90,7 +94,7 @@ psql_orioledb-17 = self'.packages."psql_orioledb-17/bin"; inherit (self.supabase) defaults; }; - psql_17_cli_portable = pkgs.callPackage ./postgres-portable.nix { + psql_17_cli_portable = pkgs-pg17.callPackage ./postgres-portable.nix { psql_17_cli = self'.legacyPackages.psql_17_cli; }; start-replica = pkgs.callPackage ./start-replica.nix { @@ -102,7 +106,7 @@ name = "start-postgres-server"; pgroonga = self'.legacyPackages."psql_${activeVersion}".exts.pgroonga; }; - switch-ext-version = pkgs.callPackage ./switch-ext-version.nix { + switch-ext-version = pkgs-pg17.callPackage ./switch-ext-version.nix { inherit (self'.packages) overlayfs-on-package; }; sync-exts-versions = pkgs.callPackage ./sync-exts-versions.nix { inherit (inputs') nix-editor; }; @@ -131,7 +135,7 @@ verify-darwin-linux-builder = pkgs.callPackage ./verify-darwin-linux-builder.nix { }; } // lib.filterAttrs (n: _v: n != "override" && n != "overrideAttrs" && n != "overrideDerivation") ( - pkgs.callPackage ../postgresql/default.nix { + pkgs-pg17.callPackage ../postgresql/default.nix { inherit self'; inherit (self.supabase) supportedPostgresVersions; } diff --git a/nix/packages/extension-catalog.nix b/nix/packages/extension-catalog.nix index 547f7baaa7..5d9909862f 100644 --- a/nix/packages/extension-catalog.nix +++ b/nix/packages/extension-catalog.nix @@ -2,7 +2,7 @@ { perSystem = { - pkgs, + pkgs-pg17, lib, self', ... @@ -13,7 +13,7 @@ # postgis and its `-3` convention) pass through untouched. mkGenericVersion = leanPkg: - pkgs.runCommand "${leanPkg.pname}-${leanPkg.version}-generic" { } '' + pkgs-pg17.runCommand "${leanPkg.pname}-${leanPkg.version}-generic" { } '' set -euo pipefail shopt -s nullglob mkdir -p "$out/lib" "$out/share/postgresql/extension" @@ -69,10 +69,10 @@ # which can differ (pgsql-http "1.5.0" builds extversion "1.5"). mkCatalogFile = wrappers: - pkgs.runCommand "pg-extensions-catalog" + pkgs-pg17.runCommand "pg-extensions-catalog" { paths = map toString (lib.concatMap lib.attrValues (lib.attrValues wrappers)); - nativeBuildInputs = [ pkgs.jq ]; + nativeBuildInputs = [ pkgs-pg17.jq ]; # Without this the literal wrapper paths in the JSON would pull # every wrapper's closure into the catalog's runtime closure. __structuredAttrs = true; @@ -104,7 +104,7 @@ catalogs = lib.mapAttrs' ( major: wrappers: lib.nameValuePair "site-extensions-catalog-${major}" ( - pkgs.runCommand "site-extensions-catalog" { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' + pkgs-pg17.runCommand "site-extensions-catalog" { nativeBuildInputs = [ pkgs-pg17.makeWrapper ]; } '' mkdir -p "$out/share" "$out/bin" ln -s ${mkCatalogFile wrappers}/share/pg-extensions-catalog.json "$out/share/" makeWrapper ${self'.packages.site-extensions-resolve}/bin/site-extensions-resolve \ @@ -122,11 +122,11 @@ # Takes manifest json as argument. Format: {: }. # Prints nix-store paths of the resolved extensions, one per line. # Does not download or install. - site-extensions-resolve = pkgs.writeShellApplication { + site-extensions-resolve = pkgs-pg17.writeShellApplication { name = "site-extensions-resolve"; runtimeInputs = [ - pkgs.coreutils - pkgs.jq + pkgs-pg17.coreutils + pkgs-pg17.jq ]; text = '' : "''${PG_EXTENSIONS_CATALOG:?PG_EXTENSIONS_CATALOG must point at a pg-extensions-catalog.json}" @@ -141,11 +141,11 @@ # Takes manifest json as argument. # Downloads paths and installs them as an env into the profile, replacing all existing ones. - site-extensions-update = pkgs.writeShellApplication { + site-extensions-update = pkgs-pg17.writeShellApplication { name = "site-extensions-update"; runtimeInputs = [ self'.packages.site-extensions-resolve - pkgs.nix + pkgs-pg17.nix ]; text = '' manifest="''${1:?Usage: $0 path-to/pg-extensions.json}" diff --git a/nix/packages/postgres-env.nix b/nix/packages/postgres-env.nix index 0ae009fff7..fda41b2db1 100644 --- a/nix/packages/postgres-env.nix +++ b/nix/packages/postgres-env.nix @@ -2,7 +2,7 @@ perSystem = { lib, - pkgs, + pkgs-pg17, self', ... }: @@ -11,7 +11,7 @@ # postgres user's nix profile, during image provisioning or instance update. makePostgresEnv = version: - pkgs.symlinkJoin { + pkgs-pg17.symlinkJoin { name = "postgres-env-${version}"; paths = [ self'.packages."psql_${version}/bin" @@ -19,12 +19,12 @@ self'.packages.supabase-groonga self'.packages."postgresql_${version}_src" ] - ++ lib.optionals pkgs.stdenv.isLinux [ self'.packages."postgresql_${version}_debug" ] - ++ lib.optionals (pkgs.stdenv.isLinux && version != "15") [ self'.packages.gatekeeper ] + ++ lib.optionals pkgs-pg17.stdenv.isLinux [ self'.packages."postgresql_${version}_debug" ] + ++ lib.optionals (pkgs-pg17.stdenv.isLinux && version != "15") [ self'.packages.gatekeeper ] # orioledb.so ships as a separate extension package (nix/ext/orioledb.nix), not # part of the postgresql derivation itself, so its debug output isn't covered by # postgresql_${version}_debug above and has to be pulled in explicitly. - ++ lib.optionals (pkgs.stdenv.isLinux && version == "orioledb-17") [ + ++ lib.optionals (pkgs-pg17.stdenv.isLinux && version == "orioledb-17") [ self'.legacyPackages."psql_${version}".exts.orioledb.debug ]; }; diff --git a/nix/packages/postgres.nix b/nix/packages/postgres.nix index 9184badb63..11f5172dd8 100644 --- a/nix/packages/postgres.nix +++ b/nix/packages/postgres.nix @@ -1,10 +1,10 @@ { inputs, ... }: { perSystem = - { pkgs, lib, ... }: + { pkgs-pg17, lib, ... }: let # Minimal glibc locales for slim images - only en_US.UTF-8 (~3MB vs ~200MB) - glibcLocalesMinimal = pkgs.glibcLocales.override { + glibcLocalesMinimal = pkgs-pg17.glibcLocales.override { allLocales = false; locales = [ "en_US.UTF-8/UTF-8" ]; }; @@ -76,7 +76,7 @@ getPostgresqlPackage = version: latestOnly: let - base = pkgs."postgresql_${version}"; + base = pkgs-pg17."postgresql_${version}"; in if latestOnly then base.override { systemdSupport = false; } else base; # Create a 'receipt' file for a given postgresql package. This is a way @@ -96,13 +96,13 @@ # merged with the PostgreSQL installation using 'symlinkJoin'. makeReceipt = pgbin: ourExts: - pkgs.writeTextFile { + pkgs-pg17.writeTextFile { name = "receipt"; destination = "/receipt.json"; text = builtins.toJSON { psql-version = pgbin.version; nixpkgs = { - revision = inputs.nixpkgs.rev; + revision = inputs.nixpkgs-pg17.rev; }; extensions = ourExts; @@ -131,8 +131,8 @@ dbExtensions17 else ourExtensions; - extCallPackage = pkgs.lib.callPackageWith ( - pkgs + extCallPackage = pkgs-pg17.lib.callPackageWith ( + pkgs-pg17 // { inherit postgresql latestOnly; switch-ext-version = extCallPackage ./switch-ext-version.nix { }; @@ -195,11 +195,11 @@ pgbin = postgresql.withPackages (_ps: postgres-pkgs); # For slim packages, include minimal glibc locales for initdb locale support - extraPaths = lib.optionals (latestOnly && pkgs.stdenv.isLinux) [ + extraPaths = lib.optionals (latestOnly && pkgs-pg17.stdenv.isLinux) [ glibcLocalesMinimal ]; in - pkgs.symlinkJoin { + pkgs-pg17.symlinkJoin { inherit (pgbin) name version; paths = [ pgbin diff --git a/nix/packages/site-env.nix b/nix/packages/site-env.nix index 4fa580e99a..7047bdf6ed 100644 --- a/nix/packages/site-env.nix +++ b/nix/packages/site-env.nix @@ -4,14 +4,14 @@ perSystem = { self', - pkgs, + pkgs-pg17, lib, ... }: let makeSiteEnv = version: extraPaths: - pkgs.buildEnv { + pkgs-pg17.buildEnv { name = "site-env-${version}"; paths = [ self'.legacyPackages."psql_${version}".exts.supautils ] ++ extraPaths; }; @@ -22,10 +22,12 @@ # gatekeeper is only available for pg 17+ on linux - "site-env-17" = makeSiteEnv "17" (lib.optionals pkgs.stdenv.isLinux [ self'.packages.gatekeeper ]); + "site-env-17" = makeSiteEnv "17" ( + lib.optionals pkgs-pg17.stdenv.isLinux [ self'.packages.gatekeeper ] + ); "site-env-orioledb-17" = makeSiteEnv "orioledb-17" ( - lib.optionals pkgs.stdenv.isLinux [ self'.packages.gatekeeper ] + lib.optionals pkgs-pg17.stdenv.isLinux [ self'.packages.gatekeeper ] ); }; in diff --git a/nix/tests/expected/hstore_copy_binary.out b/nix/tests/expected/hstore_copy_binary.out index c96abb526d..460c6ade48 100644 --- a/nix/tests/expected/hstore_copy_binary.out +++ b/nix/tests/expected/hstore_copy_binary.out @@ -30,14 +30,14 @@ SELECT lo_from_bytea(81000, 81000 (1 row) -SELECT lo_export(81000, '/tmp/pg_regress_hstore_dup.bin') AS exported; +SELECT lo_export(81000, 'pg_regress_hstore_dup.bin') AS exported; exported ---------- 1 (1 row) -- Must not crash the backend; the duplicate key is de-duplicated on receive. -COPY hstore_dst FROM '/tmp/pg_regress_hstore_dup.bin' WITH (FORMAT binary); +COPY hstore_dst FROM 'pg_regress_hstore_dup.bin' WITH (FORMAT binary); SELECT h AS received, akeys(h) AS keys FROM hstore_dst; received | keys ----------+------ diff --git a/nix/tests/sql/hstore_copy_binary.sql b/nix/tests/sql/hstore_copy_binary.sql index 35da4f02cb..299818ee0a 100644 --- a/nix/tests/sql/hstore_copy_binary.sql +++ b/nix/tests/sql/hstore_copy_binary.sql @@ -28,10 +28,10 @@ SELECT lo_from_bytea(81000, '\x00000001'::bytea||'\x61'::bytea||'\x00000001'::bytea||'\x31'::bytea || -- 'a' => '1' '\x00000001'::bytea||'\x61'::bytea||'\xffffffff'::bytea || -- 'a' => NULL '\xffff'::bytea) AS loid; -- COPY trailer -SELECT lo_export(81000, '/tmp/pg_regress_hstore_dup.bin') AS exported; +SELECT lo_export(81000, 'pg_regress_hstore_dup.bin') AS exported; -- Must not crash the backend; the duplicate key is de-duplicated on receive. -COPY hstore_dst FROM '/tmp/pg_regress_hstore_dup.bin' WITH (FORMAT binary); +COPY hstore_dst FROM 'pg_regress_hstore_dup.bin' WITH (FORMAT binary); SELECT h AS received, akeys(h) AS keys FROM hstore_dst; From 11c704e72accad5c3481f84510e212bbc48d3e38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Mon, 5 Oct 2026 15:22:35 +0300 Subject: [PATCH 2/5] refactor(nix): rename nixpkgs-pg, drop overlays from main nixpkgs - Rename nixpkgs-pg17 to nixpkgs-pg, since it also builds pg15. - Import the main nixpkgs without overlays. Only nixpkgs-pg needs rust-overlay, cargo-pgrx, cgal, and the oldstable curl and v8. - Build site-env from the main nixpkgs, so supautils and gatekeeper pick up updates. Co-Authored-By: Claude Opus 5.5 --- flake.lock | 4 +-- flake.nix | 2 +- nix/checks.nix | 5 +-- nix/devShells.nix | 3 +- nix/docs/updating-dependencies.md | 2 +- nix/nixpkgs.nix | 55 ++++++++++++++---------------- nix/packages/default.nix | 25 +++++++------- nix/packages/extension-catalog.nix | 20 +++++------ nix/packages/postgres-env.nix | 10 +++--- nix/packages/postgres.nix | 18 +++++----- nix/packages/site-env.nix | 20 +++++++---- 11 files changed, 85 insertions(+), 79 deletions(-) diff --git a/flake.lock b/flake.lock index 356e6ef0cb..e1033a5967 100644 --- a/flake.lock +++ b/flake.lock @@ -280,7 +280,7 @@ "type": "github" } }, - "nixpkgs-pg17": { + "nixpkgs-pg": { "locked": { "lastModified": 1767460468, "narHash": "sha256-3xDI4xtzovwqE/eAxCwmXxUqBg6Yoam2L1u0IwRNhW4=", @@ -320,7 +320,7 @@ "nix2container": "nix2container", "nixpkgs": "nixpkgs_2", "nixpkgs-oldstable": "nixpkgs-oldstable", - "nixpkgs-pg17": "nixpkgs-pg17", + "nixpkgs-pg": "nixpkgs-pg", "rust-overlay": "rust-overlay", "treefmt-nix": "treefmt-nix" } diff --git a/flake.nix b/flake.nix index f27f73ee86..038fdbe1de 100644 --- a/flake.nix +++ b/flake.nix @@ -29,7 +29,7 @@ # Postgres, its extensions, and anything else loaded into the postgres # process stay on glibc 2.40. Postgres warns when the running glibc's # collation version differs from the one stored in each database. - nixpkgs-pg17.url = "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz?rev=fb7944c166a3b630f177938e478f0378e64ce108"; + nixpkgs-pg.url = "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz?rev=fb7944c166a3b630f177938e478f0378e64ce108"; nixpkgs.url = "https://channels.nixos.org/nixos-26.05/nixexprs.tar.xz"; rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; rust-overlay.url = "github:oxalica/rust-overlay"; diff --git a/nix/checks.nix b/nix/checks.nix index 1d4b8c2723..5604315b09 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -13,6 +13,7 @@ psql_17 = self'.packages."psql_17/bin"; psql_orioledb-17 = self'.packages."psql_orioledb-17/bin"; inherit (self.supabase) defaults; + inherit (self'.packages) supabase-groonga; }; bashlog = builtins.fetchurl { url = "https://raw.githubusercontent.com/Zordrak/bashlog/master/log.sh"; @@ -271,7 +272,7 @@ procps python3 start-postgres-server-bin - supabase-groonga + self'.packages.supabase-groonga which ]; @@ -355,7 +356,7 @@ export HTTP_MOCK_PORT #First we need to create a generic pg cluster for pgtap tests and run those - export GRN_PLUGINS_DIR=${pkgs.supabase-groonga}/lib/groonga/plugins + export GRN_PLUGINS_DIR=${self'.packages.supabase-groonga}/lib/groonga/plugins PGTAP_CLUSTER=$(mktemp -d) log info "Creating temporary PostgreSQL cluster at $PGTAP_CLUSTER" log_cmd initdb --locale=C --username=supabase_admin -D "$PGTAP_CLUSTER" diff --git a/nix/devShells.nix b/nix/devShells.nix index 652a41a037..9986c237e2 100644 --- a/nix/devShells.nix +++ b/nix/devShells.nix @@ -2,6 +2,7 @@ { perSystem = { + inputs', pkgs, self', config, @@ -27,7 +28,7 @@ in { devShells = { - default = pkgs.devshell.mkShell { + default = inputs'.devshell.legacyPackages.mkShell { packages = with pkgs; [ coreutils just diff --git a/nix/docs/updating-dependencies.md b/nix/docs/updating-dependencies.md index ec96af2c71..d2ee9fdf6a 100644 --- a/nix/docs/updating-dependencies.md +++ b/nix/docs/updating-dependencies.md @@ -72,7 +72,7 @@ Similar patterns can be followed for other dependencies defined in the nix packa The flake uses two nixpkgs inputs: -- `nixpkgs-pg17` pins the nixpkgs that builds Postgres, every extension, and anything loaded into the postgres process, such as `supabase-groonga` and the `gatekeeper` PAM module. It pins glibc 2.40. After a glibc change, Postgres warns that the running collation version differs from the one stored in each database. Leave this input alone unless you plan that migration. Code built against a newer glibc fails to load into a postgres process running an older one. +- `nixpkgs-pg` pins the nixpkgs that builds Postgres, every extension, and anything loaded into the postgres process, such as `supabase-groonga` and the `gatekeeper` PAM module. It pins glibc 2.40. After a glibc change, Postgres warns that the running collation version differs from the one stored in each database. Leave this input alone unless you plan that migration. Code built against a newer glibc fails to load into a postgres process running an older one. - `nixpkgs` tracks the current NixOS stable channel and builds everything else. Update it with `nix flake update nixpkgs`. When the stable release changes, also move `nix-darwin` to the matching `nix-darwin-YY.MM` branch. After an update, check that every Postgres output keeps its drvPath, for example `nix eval --raw .#packages.x86_64-linux."psql_17/bin".drvPath`. diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 35d3ed482a..1e2554c4a1 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -2,35 +2,32 @@ { perSystem = { system, ... }: - let - mkPkgs = - nixpkgs: - import nixpkgs { - inherit system; - config.allowUnfree = true; - permittedInsecurePackages = [ "v8-9.7.106.18" ]; - overlays = [ - (import inputs.rust-overlay) - self.overlays.default - ( - let - # Provide older versions of packages required by some extensions - oldstable = import inputs.nixpkgs-oldstable { - inherit system; - config.allowUnfree = true; - }; - in - _final: _prev: { - curl_8_6 = oldstable.curl; - v8_oldstable = oldstable.v8; - } - ) - inputs.devshell.overlays.default - ]; - }; - in { - _module.args.pkgs = mkPkgs inputs.nixpkgs; - _module.args.pkgs-pg17 = mkPkgs inputs.nixpkgs-pg17; + _module.args.pkgs = import inputs.nixpkgs { + inherit system; + config.allowUnfree = true; + }; + _module.args.pkgs-pg = import inputs.nixpkgs-pg { + inherit system; + config.allowUnfree = true; + permittedInsecurePackages = [ "v8-9.7.106.18" ]; + overlays = [ + (import inputs.rust-overlay) + self.overlays.default + ( + let + # Provide older versions of packages required by some extensions + oldstable = import inputs.nixpkgs-oldstable { + inherit system; + config.allowUnfree = true; + }; + in + _final: _prev: { + curl_8_6 = oldstable.curl; + v8_oldstable = oldstable.v8; + } + ) + ]; + }; }; } diff --git a/nix/packages/default.nix b/nix/packages/default.nix index 278f43c79c..d7468b262f 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -11,7 +11,7 @@ inputs', lib, pkgs, - pkgs-pg17, + pkgs-pg, self', ... }: @@ -23,14 +23,14 @@ let postgresqlPackage = self'.packages."postgresql_${version}"; in - pkgs-pg17.callPackage ../ext/pg_regress.nix { postgresql = postgresqlPackage; }; + pkgs-pg.callPackage ../ext/pg_regress.nix { postgresql = postgresqlPackage; }; # Function to create the pg_isolation_regress package makePgIsolationRegress = version: let postgresqlPackage = self'.packages."postgresql_${version}"; in - pkgs-pg17.callPackage ../ext/pg_isolation_regress.nix { postgresql = postgresqlPackage; }; + pkgs-pg.callPackage ../ext/pg_isolation_regress.nix { postgresql = postgresqlPackage; }; pgsqlSuperuser = "supabase_admin"; supascan-pkgs = pkgs.callPackage ./supascan.nix { inherit (pkgs) lib; @@ -44,6 +44,7 @@ psql_17 = self'.packages."psql_17/bin"; psql_orioledb-17 = self'.packages."psql_orioledb-17/bin"; inherit (self.supabase) defaults; + inherit (self'.packages) supabase-groonga; }; in { @@ -65,17 +66,17 @@ github-matrix = pkgs.callPackage ./github-matrix { nix-eval-jobs = inputs'.nix-eval-jobs.packages.default; }; - gatekeeper = pkgs-pg17.callPackage ./gatekeeper.nix { + gatekeeper = pkgs-pg.callPackage ./gatekeeper.nix { inherit inputs; - pkgs = pkgs-pg17; + pkgs = pkgs-pg; }; - supabase-groonga = pkgs-pg17.callPackage ../ext/pgroonga/groonga.nix { }; + supabase-groonga = pkgs-pg.callPackage ../ext/pgroonga/groonga.nix { }; http-mock-server = pkgs.callPackage ./http-mock-server.nix { }; image-size-analyzer = pkgs.callPackage ./image-size-analyzer.nix { }; local-infra-bootstrap = pkgs.callPackage ./local-infra-bootstrap.nix { }; - mecab-naist-jdic = pkgs-pg17.callPackage ./mecab-naist-jdic.nix { }; + mecab-naist-jdic = pkgs-pg.callPackage ./mecab-naist-jdic.nix { }; migrate-tool = pkgs.callPackage ./migrate-tool.nix { psql_15 = self'.packages."psql_15/bin"; }; - overlayfs-on-package = pkgs-pg17.callPackage ./overlayfs-on-package.nix { }; + overlayfs-on-package = pkgs-pg.callPackage ./overlayfs-on-package.nix { }; packer = pkgs.callPackage ./packer.nix { inherit inputs; }; pg-activity = inputs.nixpkgs.legacyPackages.${pkgs.stdenv.hostPlatform.system}.pg_activity; pg-backrest = pkgs.callPackage ./pg-backrest.nix { }; @@ -83,7 +84,7 @@ multigres-src = inputs.multigres; }; pg-restore = pkgs.callPackage ./pg-restore.nix { psql_15 = self'.packages."psql_15/bin"; }; - pg_prove = pkgs-pg17.perlPackages.TAPParserSourceHandlerpgTAP; + pg_prove = pkgs-pg.perlPackages.TAPParserSourceHandlerpgTAP; pg_regress = makePgRegress activeVersion; pg_isolation_regress = makePgIsolationRegress activeVersion; run-testinfra = pkgs.callPackage ./run-testinfra.nix { }; @@ -94,7 +95,7 @@ psql_orioledb-17 = self'.packages."psql_orioledb-17/bin"; inherit (self.supabase) defaults; }; - psql_17_cli_portable = pkgs-pg17.callPackage ./postgres-portable.nix { + psql_17_cli_portable = pkgs-pg.callPackage ./postgres-portable.nix { psql_17_cli = self'.legacyPackages.psql_17_cli; }; start-replica = pkgs.callPackage ./start-replica.nix { @@ -106,7 +107,7 @@ name = "start-postgres-server"; pgroonga = self'.legacyPackages."psql_${activeVersion}".exts.pgroonga; }; - switch-ext-version = pkgs-pg17.callPackage ./switch-ext-version.nix { + switch-ext-version = pkgs-pg.callPackage ./switch-ext-version.nix { inherit (self'.packages) overlayfs-on-package; }; sync-exts-versions = pkgs.callPackage ./sync-exts-versions.nix { inherit (inputs') nix-editor; }; @@ -135,7 +136,7 @@ verify-darwin-linux-builder = pkgs.callPackage ./verify-darwin-linux-builder.nix { }; } // lib.filterAttrs (n: _v: n != "override" && n != "overrideAttrs" && n != "overrideDerivation") ( - pkgs-pg17.callPackage ../postgresql/default.nix { + pkgs-pg.callPackage ../postgresql/default.nix { inherit self'; inherit (self.supabase) supportedPostgresVersions; } diff --git a/nix/packages/extension-catalog.nix b/nix/packages/extension-catalog.nix index 5d9909862f..75a878ee19 100644 --- a/nix/packages/extension-catalog.nix +++ b/nix/packages/extension-catalog.nix @@ -2,7 +2,7 @@ { perSystem = { - pkgs-pg17, + pkgs-pg, lib, self', ... @@ -13,7 +13,7 @@ # postgis and its `-3` convention) pass through untouched. mkGenericVersion = leanPkg: - pkgs-pg17.runCommand "${leanPkg.pname}-${leanPkg.version}-generic" { } '' + pkgs-pg.runCommand "${leanPkg.pname}-${leanPkg.version}-generic" { } '' set -euo pipefail shopt -s nullglob mkdir -p "$out/lib" "$out/share/postgresql/extension" @@ -69,10 +69,10 @@ # which can differ (pgsql-http "1.5.0" builds extversion "1.5"). mkCatalogFile = wrappers: - pkgs-pg17.runCommand "pg-extensions-catalog" + pkgs-pg.runCommand "pg-extensions-catalog" { paths = map toString (lib.concatMap lib.attrValues (lib.attrValues wrappers)); - nativeBuildInputs = [ pkgs-pg17.jq ]; + nativeBuildInputs = [ pkgs-pg.jq ]; # Without this the literal wrapper paths in the JSON would pull # every wrapper's closure into the catalog's runtime closure. __structuredAttrs = true; @@ -104,7 +104,7 @@ catalogs = lib.mapAttrs' ( major: wrappers: lib.nameValuePair "site-extensions-catalog-${major}" ( - pkgs-pg17.runCommand "site-extensions-catalog" { nativeBuildInputs = [ pkgs-pg17.makeWrapper ]; } '' + pkgs-pg.runCommand "site-extensions-catalog" { nativeBuildInputs = [ pkgs-pg.makeWrapper ]; } '' mkdir -p "$out/share" "$out/bin" ln -s ${mkCatalogFile wrappers}/share/pg-extensions-catalog.json "$out/share/" makeWrapper ${self'.packages.site-extensions-resolve}/bin/site-extensions-resolve \ @@ -122,11 +122,11 @@ # Takes manifest json as argument. Format: {: }. # Prints nix-store paths of the resolved extensions, one per line. # Does not download or install. - site-extensions-resolve = pkgs-pg17.writeShellApplication { + site-extensions-resolve = pkgs-pg.writeShellApplication { name = "site-extensions-resolve"; runtimeInputs = [ - pkgs-pg17.coreutils - pkgs-pg17.jq + pkgs-pg.coreutils + pkgs-pg.jq ]; text = '' : "''${PG_EXTENSIONS_CATALOG:?PG_EXTENSIONS_CATALOG must point at a pg-extensions-catalog.json}" @@ -141,11 +141,11 @@ # Takes manifest json as argument. # Downloads paths and installs them as an env into the profile, replacing all existing ones. - site-extensions-update = pkgs-pg17.writeShellApplication { + site-extensions-update = pkgs-pg.writeShellApplication { name = "site-extensions-update"; runtimeInputs = [ self'.packages.site-extensions-resolve - pkgs-pg17.nix + pkgs-pg.nix ]; text = '' manifest="''${1:?Usage: $0 path-to/pg-extensions.json}" diff --git a/nix/packages/postgres-env.nix b/nix/packages/postgres-env.nix index fda41b2db1..0ef6de40d8 100644 --- a/nix/packages/postgres-env.nix +++ b/nix/packages/postgres-env.nix @@ -2,7 +2,7 @@ perSystem = { lib, - pkgs-pg17, + pkgs-pg, self', ... }: @@ -11,7 +11,7 @@ # postgres user's nix profile, during image provisioning or instance update. makePostgresEnv = version: - pkgs-pg17.symlinkJoin { + pkgs-pg.symlinkJoin { name = "postgres-env-${version}"; paths = [ self'.packages."psql_${version}/bin" @@ -19,12 +19,12 @@ self'.packages.supabase-groonga self'.packages."postgresql_${version}_src" ] - ++ lib.optionals pkgs-pg17.stdenv.isLinux [ self'.packages."postgresql_${version}_debug" ] - ++ lib.optionals (pkgs-pg17.stdenv.isLinux && version != "15") [ self'.packages.gatekeeper ] + ++ lib.optionals pkgs-pg.stdenv.isLinux [ self'.packages."postgresql_${version}_debug" ] + ++ lib.optionals (pkgs-pg.stdenv.isLinux && version != "15") [ self'.packages.gatekeeper ] # orioledb.so ships as a separate extension package (nix/ext/orioledb.nix), not # part of the postgresql derivation itself, so its debug output isn't covered by # postgresql_${version}_debug above and has to be pulled in explicitly. - ++ lib.optionals (pkgs-pg17.stdenv.isLinux && version == "orioledb-17") [ + ++ lib.optionals (pkgs-pg.stdenv.isLinux && version == "orioledb-17") [ self'.legacyPackages."psql_${version}".exts.orioledb.debug ]; }; diff --git a/nix/packages/postgres.nix b/nix/packages/postgres.nix index 11f5172dd8..fb297f187d 100644 --- a/nix/packages/postgres.nix +++ b/nix/packages/postgres.nix @@ -1,10 +1,10 @@ { inputs, ... }: { perSystem = - { pkgs-pg17, lib, ... }: + { pkgs-pg, lib, ... }: let # Minimal glibc locales for slim images - only en_US.UTF-8 (~3MB vs ~200MB) - glibcLocalesMinimal = pkgs-pg17.glibcLocales.override { + glibcLocalesMinimal = pkgs-pg.glibcLocales.override { allLocales = false; locales = [ "en_US.UTF-8/UTF-8" ]; }; @@ -76,7 +76,7 @@ getPostgresqlPackage = version: latestOnly: let - base = pkgs-pg17."postgresql_${version}"; + base = pkgs-pg."postgresql_${version}"; in if latestOnly then base.override { systemdSupport = false; } else base; # Create a 'receipt' file for a given postgresql package. This is a way @@ -96,13 +96,13 @@ # merged with the PostgreSQL installation using 'symlinkJoin'. makeReceipt = pgbin: ourExts: - pkgs-pg17.writeTextFile { + pkgs-pg.writeTextFile { name = "receipt"; destination = "/receipt.json"; text = builtins.toJSON { psql-version = pgbin.version; nixpkgs = { - revision = inputs.nixpkgs-pg17.rev; + revision = inputs.nixpkgs-pg.rev; }; extensions = ourExts; @@ -131,8 +131,8 @@ dbExtensions17 else ourExtensions; - extCallPackage = pkgs-pg17.lib.callPackageWith ( - pkgs-pg17 + extCallPackage = pkgs-pg.lib.callPackageWith ( + pkgs-pg // { inherit postgresql latestOnly; switch-ext-version = extCallPackage ./switch-ext-version.nix { }; @@ -195,11 +195,11 @@ pgbin = postgresql.withPackages (_ps: postgres-pkgs); # For slim packages, include minimal glibc locales for initdb locale support - extraPaths = lib.optionals (latestOnly && pkgs-pg17.stdenv.isLinux) [ + extraPaths = lib.optionals (latestOnly && pkgs-pg.stdenv.isLinux) [ glibcLocalesMinimal ]; in - pkgs-pg17.symlinkJoin { + pkgs-pg.symlinkJoin { inherit (pgbin) name version; paths = [ pgbin diff --git a/nix/packages/site-env.nix b/nix/packages/site-env.nix index 7047bdf6ed..e58937a62c 100644 --- a/nix/packages/site-env.nix +++ b/nix/packages/site-env.nix @@ -1,19 +1,27 @@ # These are envs (package sets per pg major version) deployed to instances # at /nix/var/nix/profiles/site and updated regularly. +{ inputs, ... }: { perSystem = { self', - pkgs-pg17, + pkgs, lib, ... }: let + # Built from the main nixpkgs. Both are dlopen'd into postgres without an + # RPATH, so they run against the postgres process's glibc. + supautils = + version: + pkgs.callPackage ../ext/supautils.nix { postgresql = self'.packages."postgresql_${version}"; }; + gatekeeper = pkgs.callPackage ./gatekeeper.nix { inherit inputs pkgs; }; + makeSiteEnv = version: extraPaths: - pkgs-pg17.buildEnv { + pkgs.buildEnv { name = "site-env-${version}"; - paths = [ self'.legacyPackages."psql_${version}".exts.supautils ] ++ extraPaths; + paths = [ (supautils version) ] ++ extraPaths; }; siteEnvs = { @@ -22,12 +30,10 @@ # gatekeeper is only available for pg 17+ on linux - "site-env-17" = makeSiteEnv "17" ( - lib.optionals pkgs-pg17.stdenv.isLinux [ self'.packages.gatekeeper ] - ); + "site-env-17" = makeSiteEnv "17" (lib.optionals pkgs.stdenv.isLinux [ gatekeeper ]); "site-env-orioledb-17" = makeSiteEnv "orioledb-17" ( - lib.optionals pkgs-pg17.stdenv.isLinux [ self'.packages.gatekeeper ] + lib.optionals pkgs.stdenv.isLinux [ gatekeeper ] ); }; in From 3c2a1fddaf6808589d2145cdc359712417ea3d82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Mon, 5 Oct 2026 16:26:09 +0300 Subject: [PATCH 3/5] refactor(nix): build gatekeeper and pg_regress from main nixpkgs gatekeeper loads into postgres without an RPATH, like supautils, so site-env and postgres-env now share one build from the main nixpkgs. pg_regress and pg_isolation_regress are test clients. Co-Authored-By: Claude Opus 5.5 --- nix/packages/default.nix | 9 +++------ nix/packages/site-env.nix | 10 ++++------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/nix/packages/default.nix b/nix/packages/default.nix index d7468b262f..bdc1beec25 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -23,14 +23,14 @@ let postgresqlPackage = self'.packages."postgresql_${version}"; in - pkgs-pg.callPackage ../ext/pg_regress.nix { postgresql = postgresqlPackage; }; + pkgs.callPackage ../ext/pg_regress.nix { postgresql = postgresqlPackage; }; # Function to create the pg_isolation_regress package makePgIsolationRegress = version: let postgresqlPackage = self'.packages."postgresql_${version}"; in - pkgs-pg.callPackage ../ext/pg_isolation_regress.nix { postgresql = postgresqlPackage; }; + pkgs.callPackage ../ext/pg_isolation_regress.nix { postgresql = postgresqlPackage; }; pgsqlSuperuser = "supabase_admin"; supascan-pkgs = pkgs.callPackage ./supascan.nix { inherit (pkgs) lib; @@ -66,10 +66,7 @@ github-matrix = pkgs.callPackage ./github-matrix { nix-eval-jobs = inputs'.nix-eval-jobs.packages.default; }; - gatekeeper = pkgs-pg.callPackage ./gatekeeper.nix { - inherit inputs; - pkgs = pkgs-pg; - }; + gatekeeper = pkgs.callPackage ./gatekeeper.nix { inherit inputs pkgs; }; supabase-groonga = pkgs-pg.callPackage ../ext/pgroonga/groonga.nix { }; http-mock-server = pkgs.callPackage ./http-mock-server.nix { }; image-size-analyzer = pkgs.callPackage ./image-size-analyzer.nix { }; diff --git a/nix/packages/site-env.nix b/nix/packages/site-env.nix index e58937a62c..bc5890e275 100644 --- a/nix/packages/site-env.nix +++ b/nix/packages/site-env.nix @@ -1,6 +1,5 @@ # These are envs (package sets per pg major version) deployed to instances # at /nix/var/nix/profiles/site and updated regularly. -{ inputs, ... }: { perSystem = { @@ -10,12 +9,11 @@ ... }: let - # Built from the main nixpkgs. Both are dlopen'd into postgres without an - # RPATH, so they run against the postgres process's glibc. + # Built from the main nixpkgs. supautils is dlopen'd into postgres without + # an RPATH, so it runs against the postgres process's glibc. supautils = version: pkgs.callPackage ../ext/supautils.nix { postgresql = self'.packages."postgresql_${version}"; }; - gatekeeper = pkgs.callPackage ./gatekeeper.nix { inherit inputs pkgs; }; makeSiteEnv = version: extraPaths: @@ -30,10 +28,10 @@ # gatekeeper is only available for pg 17+ on linux - "site-env-17" = makeSiteEnv "17" (lib.optionals pkgs.stdenv.isLinux [ gatekeeper ]); + "site-env-17" = makeSiteEnv "17" (lib.optionals pkgs.stdenv.isLinux [ self'.packages.gatekeeper ]); "site-env-orioledb-17" = makeSiteEnv "orioledb-17" ( - lib.optionals pkgs.stdenv.isLinux [ gatekeeper ] + lib.optionals pkgs.stdenv.isLinux [ self'.packages.gatekeeper ] ); }; in From 8480983c795813f49ae194a14f91bac59e628f6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Tue, 6 Oct 2026 23:56:32 +0300 Subject: [PATCH 4/5] refactor(nix): use one nixpkgs for postgres and everything else Drop the nixpkgs-pg pin. Postgres and its extensions build from the nixos-26.05 nixpkgs too, which moves them to glibc 2.42. pg_net builds against the main curl instead of curl_8_6 from nixpkgs-oldstable. Versions before 0.20.4 need -DCURL_DISABLE_TYPECHECK, since newer curl headers break their multi.h include. Co-Authored-By: Claude Opus 5.5 --- flake.lock | 15 ----------- flake.nix | 4 --- nix/checks.nix | 5 ++-- nix/devShells.nix | 3 +-- nix/docs/updating-dependencies.md | 7 ++--- nix/ext/pg_net.nix | 42 ++++++++++++++++-------------- nix/nixpkgs.nix | 6 +---- nix/packages/default.nix | 16 +++++------- nix/packages/extension-catalog.nix | 20 +++++++------- nix/packages/postgres-env.nix | 10 +++---- nix/packages/postgres.nix | 18 ++++++------- nix/packages/site-env.nix | 8 +----- 12 files changed, 60 insertions(+), 94 deletions(-) diff --git a/flake.lock b/flake.lock index e1033a5967..9fb6230565 100644 --- a/flake.lock +++ b/flake.lock @@ -280,20 +280,6 @@ "type": "github" } }, - "nixpkgs-pg": { - "locked": { - "lastModified": 1767460468, - "narHash": "sha256-3xDI4xtzovwqE/eAxCwmXxUqBg6Yoam2L1u0IwRNhW4=", - "rev": "fb7944c166a3b630f177938e478f0378e64ce108", - "type": "tarball", - "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz" - }, - "original": { - "rev": "fb7944c166a3b630f177938e478f0378e64ce108", - "type": "tarball", - "url": "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz" - } - }, "nixpkgs_2": { "locked": { "lastModified": 1790920529, @@ -320,7 +306,6 @@ "nix2container": "nix2container", "nixpkgs": "nixpkgs_2", "nixpkgs-oldstable": "nixpkgs-oldstable", - "nixpkgs-pg": "nixpkgs-pg", "rust-overlay": "rust-overlay", "treefmt-nix": "treefmt-nix" } diff --git a/flake.nix b/flake.nix index 038fdbe1de..ea3b0d149d 100644 --- a/flake.nix +++ b/flake.nix @@ -26,10 +26,6 @@ # Pin to a specific nixpkgs version that has compatible v8 and curl versions # for extensions that require older package versions nixpkgs-oldstable.url = "github:NixOS/nixpkgs/a76c4553d7e741e17f289224eda135423de0491d"; - # Postgres, its extensions, and anything else loaded into the postgres - # process stay on glibc 2.40. Postgres warns when the running glibc's - # collation version differs from the one stored in each database. - nixpkgs-pg.url = "https://releases.nixos.org/nixos/unstable/nixos-26.05pre921484.fb7944c166a3/nixexprs.tar.xz?rev=fb7944c166a3b630f177938e478f0378e64ce108"; nixpkgs.url = "https://channels.nixos.org/nixos-26.05/nixexprs.tar.xz"; rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; rust-overlay.url = "github:oxalica/rust-overlay"; diff --git a/nix/checks.nix b/nix/checks.nix index 2d80a58973..5bf0670897 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -13,7 +13,6 @@ psql_17 = self'.packages."psql_17/bin"; psql_orioledb-17 = self'.packages."psql_orioledb-17/bin"; inherit (self.supabase) defaults; - inherit (self'.packages) supabase-groonga; }; bashlog = builtins.fetchurl { url = "https://raw.githubusercontent.com/Zordrak/bashlog/master/log.sh"; @@ -273,7 +272,7 @@ procps python3 start-postgres-server-bin - self'.packages.supabase-groonga + supabase-groonga which ]; @@ -357,7 +356,7 @@ export HTTP_MOCK_PORT #First we need to create a generic pg cluster for pgtap tests and run those - export GRN_PLUGINS_DIR=${self'.packages.supabase-groonga}/lib/groonga/plugins + export GRN_PLUGINS_DIR=${pkgs.supabase-groonga}/lib/groonga/plugins PGTAP_CLUSTER=$(mktemp -d) log info "Creating temporary PostgreSQL cluster at $PGTAP_CLUSTER" log_cmd initdb --locale=C --username=supabase_admin -D "$PGTAP_CLUSTER" diff --git a/nix/devShells.nix b/nix/devShells.nix index 9986c237e2..652a41a037 100644 --- a/nix/devShells.nix +++ b/nix/devShells.nix @@ -2,7 +2,6 @@ { perSystem = { - inputs', pkgs, self', config, @@ -28,7 +27,7 @@ in { devShells = { - default = inputs'.devshell.legacyPackages.mkShell { + default = pkgs.devshell.mkShell { packages = with pkgs; [ coreutils just diff --git a/nix/docs/updating-dependencies.md b/nix/docs/updating-dependencies.md index d2ee9fdf6a..5af4969ae4 100644 --- a/nix/docs/updating-dependencies.md +++ b/nix/docs/updating-dependencies.md @@ -70,9 +70,6 @@ Similar patterns can be followed for other dependencies defined in the nix packa ## Updating nixpkgs -The flake uses two nixpkgs inputs: +`nixpkgs` tracks the current NixOS stable channel and builds everything, including Postgres and its extensions. Update it with `nix flake update nixpkgs`. When the stable release changes, also move `nix-darwin` to the matching `nix-darwin-YY.MM` branch. -- `nixpkgs-pg` pins the nixpkgs that builds Postgres, every extension, and anything loaded into the postgres process, such as `supabase-groonga` and the `gatekeeper` PAM module. It pins glibc 2.40. After a glibc change, Postgres warns that the running collation version differs from the one stored in each database. Leave this input alone unless you plan that migration. Code built against a newer glibc fails to load into a postgres process running an older one. -- `nixpkgs` tracks the current NixOS stable channel and builds everything else. Update it with `nix flake update nixpkgs`. When the stable release changes, also move `nix-darwin` to the matching `nix-darwin-YY.MM` branch. - -After an update, check that every Postgres output keeps its drvPath, for example `nix eval --raw .#packages.x86_64-linux."psql_17/bin".drvPath`. +A nixpkgs update can change glibc. After a glibc change, Postgres warns that the collation version stored in each database differs from the running one, until each database runs `ALTER DATABASE ... REFRESH COLLATION VERSION`. diff --git a/nix/ext/pg_net.nix b/nix/ext/pg_net.nix index f769bad314..e3e60955a4 100644 --- a/nix/ext/pg_net.nix +++ b/nix/ext/pg_net.nix @@ -7,13 +7,10 @@ libuv, makeWrapper, switch-ext-version, - curl_8_6, + curl, latestOnly ? false, }: -let - curl = curl_8_6; -in let pname = "pg_net"; build = @@ -50,23 +47,28 @@ let rm sql/pg_net--0.5.1--0.6.sql ''; + # curl >= 8.17 makes pull in the curl_multi_setopt + # typecheck macro, which breaks the declaration in multi.h before 0.20.4. env.NIX_CFLAGS_COMPILE = - if (lib.versionOlder version "0.19.1") then - "-Wno-error" - else if - ( - builtins.elem version [ - "0.19.5" - "0.20.0" - ] - && stdenv.isDarwin - ) - then - # Fix for dangling pointer warning on darwin with newer clang - # 0.19.5: src/core.c:177, 0.20.0: src/core.c:317 - "-Wno-error=dangling-assignment" - else - ""; + lib.optionalString (lib.versionOlder version "0.20.4") "-DCURL_DISABLE_TYPECHECK " + + ( + if (lib.versionOlder version "0.19.1") then + "-Wno-error" + else if + ( + builtins.elem version [ + "0.19.5" + "0.20.0" + ] + && stdenv.isDarwin + ) + then + # Fix for dangling pointer warning on darwin with newer clang + # 0.19.5: src/core.c:177, 0.20.0: src/core.c:317 + "-Wno-error=dangling-assignment" + else + "" + ); installPhase = '' mkdir -p $out/{lib,share/postgresql/extension} diff --git a/nix/nixpkgs.nix b/nix/nixpkgs.nix index 1e2554c4a1..6b7a541587 100644 --- a/nix/nixpkgs.nix +++ b/nix/nixpkgs.nix @@ -6,10 +6,6 @@ _module.args.pkgs = import inputs.nixpkgs { inherit system; config.allowUnfree = true; - }; - _module.args.pkgs-pg = import inputs.nixpkgs-pg { - inherit system; - config.allowUnfree = true; permittedInsecurePackages = [ "v8-9.7.106.18" ]; overlays = [ (import inputs.rust-overlay) @@ -23,10 +19,10 @@ }; in _final: _prev: { - curl_8_6 = oldstable.curl; v8_oldstable = oldstable.v8; } ) + inputs.devshell.overlays.default ]; }; }; diff --git a/nix/packages/default.nix b/nix/packages/default.nix index bdc1beec25..bcb8ab0050 100644 --- a/nix/packages/default.nix +++ b/nix/packages/default.nix @@ -11,7 +11,6 @@ inputs', lib, pkgs, - pkgs-pg, self', ... }: @@ -44,7 +43,6 @@ psql_17 = self'.packages."psql_17/bin"; psql_orioledb-17 = self'.packages."psql_orioledb-17/bin"; inherit (self.supabase) defaults; - inherit (self'.packages) supabase-groonga; }; in { @@ -67,13 +65,13 @@ nix-eval-jobs = inputs'.nix-eval-jobs.packages.default; }; gatekeeper = pkgs.callPackage ./gatekeeper.nix { inherit inputs pkgs; }; - supabase-groonga = pkgs-pg.callPackage ../ext/pgroonga/groonga.nix { }; + supabase-groonga = pkgs.callPackage ../ext/pgroonga/groonga.nix { }; http-mock-server = pkgs.callPackage ./http-mock-server.nix { }; image-size-analyzer = pkgs.callPackage ./image-size-analyzer.nix { }; local-infra-bootstrap = pkgs.callPackage ./local-infra-bootstrap.nix { }; - mecab-naist-jdic = pkgs-pg.callPackage ./mecab-naist-jdic.nix { }; + mecab-naist-jdic = pkgs.callPackage ./mecab-naist-jdic.nix { }; migrate-tool = pkgs.callPackage ./migrate-tool.nix { psql_15 = self'.packages."psql_15/bin"; }; - overlayfs-on-package = pkgs-pg.callPackage ./overlayfs-on-package.nix { }; + overlayfs-on-package = pkgs.callPackage ./overlayfs-on-package.nix { }; packer = pkgs.callPackage ./packer.nix { inherit inputs; }; pg-activity = inputs.nixpkgs.legacyPackages.${pkgs.stdenv.hostPlatform.system}.pg_activity; pg-backrest = pkgs.callPackage ./pg-backrest.nix { }; @@ -81,7 +79,7 @@ multigres-src = inputs.multigres; }; pg-restore = pkgs.callPackage ./pg-restore.nix { psql_15 = self'.packages."psql_15/bin"; }; - pg_prove = pkgs-pg.perlPackages.TAPParserSourceHandlerpgTAP; + pg_prove = pkgs.perlPackages.TAPParserSourceHandlerpgTAP; pg_regress = makePgRegress activeVersion; pg_isolation_regress = makePgIsolationRegress activeVersion; run-testinfra = pkgs.callPackage ./run-testinfra.nix { }; @@ -92,7 +90,7 @@ psql_orioledb-17 = self'.packages."psql_orioledb-17/bin"; inherit (self.supabase) defaults; }; - psql_17_cli_portable = pkgs-pg.callPackage ./postgres-portable.nix { + psql_17_cli_portable = pkgs.callPackage ./postgres-portable.nix { psql_17_cli = self'.legacyPackages.psql_17_cli; }; start-replica = pkgs.callPackage ./start-replica.nix { @@ -104,7 +102,7 @@ name = "start-postgres-server"; pgroonga = self'.legacyPackages."psql_${activeVersion}".exts.pgroonga; }; - switch-ext-version = pkgs-pg.callPackage ./switch-ext-version.nix { + switch-ext-version = pkgs.callPackage ./switch-ext-version.nix { inherit (self'.packages) overlayfs-on-package; }; sync-exts-versions = pkgs.callPackage ./sync-exts-versions.nix { inherit (inputs') nix-editor; }; @@ -133,7 +131,7 @@ verify-darwin-linux-builder = pkgs.callPackage ./verify-darwin-linux-builder.nix { }; } // lib.filterAttrs (n: _v: n != "override" && n != "overrideAttrs" && n != "overrideDerivation") ( - pkgs-pg.callPackage ../postgresql/default.nix { + pkgs.callPackage ../postgresql/default.nix { inherit self'; inherit (self.supabase) supportedPostgresVersions; } diff --git a/nix/packages/extension-catalog.nix b/nix/packages/extension-catalog.nix index 75a878ee19..547f7baaa7 100644 --- a/nix/packages/extension-catalog.nix +++ b/nix/packages/extension-catalog.nix @@ -2,7 +2,7 @@ { perSystem = { - pkgs-pg, + pkgs, lib, self', ... @@ -13,7 +13,7 @@ # postgis and its `-3` convention) pass through untouched. mkGenericVersion = leanPkg: - pkgs-pg.runCommand "${leanPkg.pname}-${leanPkg.version}-generic" { } '' + pkgs.runCommand "${leanPkg.pname}-${leanPkg.version}-generic" { } '' set -euo pipefail shopt -s nullglob mkdir -p "$out/lib" "$out/share/postgresql/extension" @@ -69,10 +69,10 @@ # which can differ (pgsql-http "1.5.0" builds extversion "1.5"). mkCatalogFile = wrappers: - pkgs-pg.runCommand "pg-extensions-catalog" + pkgs.runCommand "pg-extensions-catalog" { paths = map toString (lib.concatMap lib.attrValues (lib.attrValues wrappers)); - nativeBuildInputs = [ pkgs-pg.jq ]; + nativeBuildInputs = [ pkgs.jq ]; # Without this the literal wrapper paths in the JSON would pull # every wrapper's closure into the catalog's runtime closure. __structuredAttrs = true; @@ -104,7 +104,7 @@ catalogs = lib.mapAttrs' ( major: wrappers: lib.nameValuePair "site-extensions-catalog-${major}" ( - pkgs-pg.runCommand "site-extensions-catalog" { nativeBuildInputs = [ pkgs-pg.makeWrapper ]; } '' + pkgs.runCommand "site-extensions-catalog" { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' mkdir -p "$out/share" "$out/bin" ln -s ${mkCatalogFile wrappers}/share/pg-extensions-catalog.json "$out/share/" makeWrapper ${self'.packages.site-extensions-resolve}/bin/site-extensions-resolve \ @@ -122,11 +122,11 @@ # Takes manifest json as argument. Format: {: }. # Prints nix-store paths of the resolved extensions, one per line. # Does not download or install. - site-extensions-resolve = pkgs-pg.writeShellApplication { + site-extensions-resolve = pkgs.writeShellApplication { name = "site-extensions-resolve"; runtimeInputs = [ - pkgs-pg.coreutils - pkgs-pg.jq + pkgs.coreutils + pkgs.jq ]; text = '' : "''${PG_EXTENSIONS_CATALOG:?PG_EXTENSIONS_CATALOG must point at a pg-extensions-catalog.json}" @@ -141,11 +141,11 @@ # Takes manifest json as argument. # Downloads paths and installs them as an env into the profile, replacing all existing ones. - site-extensions-update = pkgs-pg.writeShellApplication { + site-extensions-update = pkgs.writeShellApplication { name = "site-extensions-update"; runtimeInputs = [ self'.packages.site-extensions-resolve - pkgs-pg.nix + pkgs.nix ]; text = '' manifest="''${1:?Usage: $0 path-to/pg-extensions.json}" diff --git a/nix/packages/postgres-env.nix b/nix/packages/postgres-env.nix index 0ef6de40d8..0ae009fff7 100644 --- a/nix/packages/postgres-env.nix +++ b/nix/packages/postgres-env.nix @@ -2,7 +2,7 @@ perSystem = { lib, - pkgs-pg, + pkgs, self', ... }: @@ -11,7 +11,7 @@ # postgres user's nix profile, during image provisioning or instance update. makePostgresEnv = version: - pkgs-pg.symlinkJoin { + pkgs.symlinkJoin { name = "postgres-env-${version}"; paths = [ self'.packages."psql_${version}/bin" @@ -19,12 +19,12 @@ self'.packages.supabase-groonga self'.packages."postgresql_${version}_src" ] - ++ lib.optionals pkgs-pg.stdenv.isLinux [ self'.packages."postgresql_${version}_debug" ] - ++ lib.optionals (pkgs-pg.stdenv.isLinux && version != "15") [ self'.packages.gatekeeper ] + ++ lib.optionals pkgs.stdenv.isLinux [ self'.packages."postgresql_${version}_debug" ] + ++ lib.optionals (pkgs.stdenv.isLinux && version != "15") [ self'.packages.gatekeeper ] # orioledb.so ships as a separate extension package (nix/ext/orioledb.nix), not # part of the postgresql derivation itself, so its debug output isn't covered by # postgresql_${version}_debug above and has to be pulled in explicitly. - ++ lib.optionals (pkgs-pg.stdenv.isLinux && version == "orioledb-17") [ + ++ lib.optionals (pkgs.stdenv.isLinux && version == "orioledb-17") [ self'.legacyPackages."psql_${version}".exts.orioledb.debug ]; }; diff --git a/nix/packages/postgres.nix b/nix/packages/postgres.nix index fb297f187d..9184badb63 100644 --- a/nix/packages/postgres.nix +++ b/nix/packages/postgres.nix @@ -1,10 +1,10 @@ { inputs, ... }: { perSystem = - { pkgs-pg, lib, ... }: + { pkgs, lib, ... }: let # Minimal glibc locales for slim images - only en_US.UTF-8 (~3MB vs ~200MB) - glibcLocalesMinimal = pkgs-pg.glibcLocales.override { + glibcLocalesMinimal = pkgs.glibcLocales.override { allLocales = false; locales = [ "en_US.UTF-8/UTF-8" ]; }; @@ -76,7 +76,7 @@ getPostgresqlPackage = version: latestOnly: let - base = pkgs-pg."postgresql_${version}"; + base = pkgs."postgresql_${version}"; in if latestOnly then base.override { systemdSupport = false; } else base; # Create a 'receipt' file for a given postgresql package. This is a way @@ -96,13 +96,13 @@ # merged with the PostgreSQL installation using 'symlinkJoin'. makeReceipt = pgbin: ourExts: - pkgs-pg.writeTextFile { + pkgs.writeTextFile { name = "receipt"; destination = "/receipt.json"; text = builtins.toJSON { psql-version = pgbin.version; nixpkgs = { - revision = inputs.nixpkgs-pg.rev; + revision = inputs.nixpkgs.rev; }; extensions = ourExts; @@ -131,8 +131,8 @@ dbExtensions17 else ourExtensions; - extCallPackage = pkgs-pg.lib.callPackageWith ( - pkgs-pg + extCallPackage = pkgs.lib.callPackageWith ( + pkgs // { inherit postgresql latestOnly; switch-ext-version = extCallPackage ./switch-ext-version.nix { }; @@ -195,11 +195,11 @@ pgbin = postgresql.withPackages (_ps: postgres-pkgs); # For slim packages, include minimal glibc locales for initdb locale support - extraPaths = lib.optionals (latestOnly && pkgs-pg.stdenv.isLinux) [ + extraPaths = lib.optionals (latestOnly && pkgs.stdenv.isLinux) [ glibcLocalesMinimal ]; in - pkgs-pg.symlinkJoin { + pkgs.symlinkJoin { inherit (pgbin) name version; paths = [ pgbin diff --git a/nix/packages/site-env.nix b/nix/packages/site-env.nix index bc5890e275..4fa580e99a 100644 --- a/nix/packages/site-env.nix +++ b/nix/packages/site-env.nix @@ -9,17 +9,11 @@ ... }: let - # Built from the main nixpkgs. supautils is dlopen'd into postgres without - # an RPATH, so it runs against the postgres process's glibc. - supautils = - version: - pkgs.callPackage ../ext/supautils.nix { postgresql = self'.packages."postgresql_${version}"; }; - makeSiteEnv = version: extraPaths: pkgs.buildEnv { name = "site-env-${version}"; - paths = [ (supautils version) ] ++ extraPaths; + paths = [ self'.legacyPackages."psql_${version}".exts.supautils ] ++ extraPaths; }; siteEnvs = { From a9ef86e94f1f427058974ee05770f4d173696b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 16 Oct 2026 15:03:35 +0300 Subject: [PATCH 5/5] fix(nix): keep the portable cli bundle on pre-2.42 glibc hosts glibc 2.42 re-versions cfgetospeed, so the bundled libncursesw needed GLIBC_2.42 and failed on Ubuntu 24.04. The bundle now ships an ncurses that resolves the GLIBC_2.17 symbol at runtime. Also fix the two nixos-26.05 deprecation warnings in groonga: a nested buildInputs list and the xxHash rename. Refs: MPG-1323 Co-Authored-By: Claude Opus 5.5 --- nix/ext/pgroonga/default.nix | 10 +- nix/ext/pgroonga/groonga.nix | 6 +- ...ncurses-cfgetospeed-old-glibc-compat.patch | 127 ++++++++++++++++++ nix/packages/postgres-portable.nix | 11 +- 4 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch diff --git a/nix/ext/pgroonga/default.nix b/nix/ext/pgroonga/default.nix index b9c3829a0d..91bdaf9c26 100644 --- a/nix/ext/pgroonga/default.nix +++ b/nix/ext/pgroonga/default.nix @@ -7,7 +7,7 @@ msgpack-c, mecab, makeWrapper, - xxHash, + xxhash, buildEnv, supabase-groonga, mecab-naist-jdic, @@ -64,7 +64,7 @@ let supabase-groonga mecab ] - ++ lib.optionals stdenv.isDarwin [ xxHash ]; + ++ lib.optionals stdenv.isDarwin [ xxhash ]; propagatedBuildInputs = [ supabase-groonga @@ -89,7 +89,7 @@ let "-Wno-error=format" "-Wno-format" "-I${supabase-groonga}/include/groonga" - "-I${xxHash}/include" + "-I${xxhash}/include" "-DPGRN_VERSION=\"${version}\"" ] ); @@ -100,8 +100,8 @@ let export MECAB_CONFIG="${mecab}/bin/mecab-config" export MECAB_DICDIR="${mecab-naist-jdic}/lib/mecab/dic/naist-jdic" ${lib.optionalString stdenv.isDarwin '' - export CPPFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" - export CFLAGS="-I${supabase-groonga}/include/groonga -I${xxHash}/include -DPGRN_VERSION=\"${version}\"" + export CPPFLAGS="-I${supabase-groonga}/include/groonga -I${xxhash}/include -DPGRN_VERSION=\"${version}\"" + export CFLAGS="-I${supabase-groonga}/include/groonga -I${xxhash}/include -DPGRN_VERSION=\"${version}\"" export PG_CPPFLAGS="-Wno-error=incompatible-function-pointer-types -Wno-error=format" ''} ''; diff --git a/nix/ext/pgroonga/groonga.nix b/nix/ext/pgroonga/groonga.nix index c6d734db6c..41eb756ac2 100644 --- a/nix/ext/pgroonga/groonga.nix +++ b/nix/ext/pgroonga/groonga.nix @@ -8,7 +8,7 @@ mecab, pkg-config, rapidjson, - xxHash, + xxhash, zstd, makeWrapper, suggestSupport ? false, @@ -38,14 +38,14 @@ stdenv.mkDerivation (finalAttrs: { ]; buildInputs = [ rapidjson - xxHash + xxhash zstd mecab kytea msgpack-c ] ++ lib.optionals lz4Support [ lz4 ] - ++ lib.optional zlibSupport [ zlib ] + ++ lib.optionals zlibSupport [ zlib ] ++ lib.optionals suggestSupport [ zeromq libevent diff --git a/nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch b/nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch new file mode 100644 index 0000000000..1a1766675c --- /dev/null +++ b/nix/packages/patches/ncurses-cfgetospeed-old-glibc-compat.patch @@ -0,0 +1,127 @@ +--- a/ncurses/tinfo/lib_baudrate.c 2026-07-31 08:24:24 ++++ b/ncurses/tinfo/lib_baudrate.c 2026-07-31 12:03:39 +@@ -45,6 +45,39 @@ + #endif + + /* ++ * On Linux/glibc, resolve cfgetospeed to the old (functionally identical) ++ * GLIBC_2.17 symbol version at runtime, so binaries built against newer ++ * glibc still run on hosts with older glibc that only export that version. ++ * Done via dlvsym rather than a link-time .symver directive, since the ++ * latter conflicts with ncurses' own --version-script linking. Both dlvsym ++ * and its dlsym fallback are declared directly (rather than via ++ * /_GNU_SOURCE, which may already be locked in by earlier headers ++ * in this file), and neither path calls the bare cfgetospeed identifier, so ++ * no versioned reference to it survives in the compiled output. ++ */ ++#if defined(__linux__) && defined(__GLIBC__) ++extern void *dlvsym(void *handle, const char *symbol, const char *version); ++extern void *dlsym(void *handle, const char *symbol); ++static speed_t ++_supabase_compat_cfgetospeed(const struct termios *t) ++{ ++ static int inited = 0; ++ static speed_t (*fn)(const struct termios *) = NULL; ++ if (!inited) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlvsym((void *) 0, "cfgetospeed", "GLIBC_2.17"); ++ if (!fn) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlsym((void *) 0, "cfgetospeed"); ++ } ++ inited = 1; ++ } ++ return fn ? fn(t) : 0; ++} ++#define cfgetospeed(t) _supabase_compat_cfgetospeed(t) ++#endif ++ ++/* + * These systems use similar header files, which define B1200 as 1200, etc., + * but can be overridden by defining USE_OLD_TTY so B1200 is 9, which makes all + * of the indices up to B115200 fit nicely in a 'short', allowing us to retain +--- a/ncurses/tinfo/tinfo_driver.c 2026-07-31 08:24:24 ++++ b/ncurses/tinfo/tinfo_driver.c 2026-07-31 12:03:50 +@@ -37,6 +37,39 @@ + #include + #include /* ospeed */ + ++/* ++ * On Linux/glibc, resolve cfgetospeed to the old (functionally identical) ++ * GLIBC_2.17 symbol version at runtime, so binaries built against newer ++ * glibc still run on hosts with older glibc that only export that version. ++ * Done via dlvsym rather than a link-time .symver directive, since the ++ * latter conflicts with ncurses' own --version-script linking. Both dlvsym ++ * and its dlsym fallback are declared directly (rather than via ++ * /_GNU_SOURCE, which may already be locked in by earlier headers ++ * in this file), and neither path calls the bare cfgetospeed identifier, so ++ * no versioned reference to it survives in the compiled output. ++ */ ++#if defined(__linux__) && defined(__GLIBC__) ++extern void *dlvsym(void *handle, const char *symbol, const char *version); ++extern void *dlsym(void *handle, const char *symbol); ++static speed_t ++_supabase_compat_cfgetospeed(const struct termios *t) ++{ ++ static int inited = 0; ++ static speed_t (*fn)(const struct termios *) = NULL; ++ if (!inited) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlvsym((void *) 0, "cfgetospeed", "GLIBC_2.17"); ++ if (!fn) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlsym((void *) 0, "cfgetospeed"); ++ } ++ inited = 1; ++ } ++ return fn ? fn(t) : 0; ++} ++#define cfgetospeed(t) _supabase_compat_cfgetospeed(t) ++#endif ++ + #if HAVE_NANOSLEEP + #include + #if HAVE_SYS_TIME_H +--- a/progs/tset.c 2026-07-31 08:24:24 ++++ b/progs/tset.c 2026-07-31 12:03:59 +@@ -89,6 +89,40 @@ + #include + #include + #include ++ ++/* ++ * On Linux/glibc, resolve cfgetospeed to the old (functionally identical) ++ * GLIBC_2.17 symbol version at runtime, so binaries built against newer ++ * glibc still run on hosts with older glibc that only export that version. ++ * Done via dlvsym rather than a link-time .symver directive, since the ++ * latter conflicts with ncurses' own --version-script linking. Both dlvsym ++ * and its dlsym fallback are declared directly (rather than via ++ * /_GNU_SOURCE, which may already be locked in by earlier headers ++ * in this file), and neither path calls the bare cfgetospeed identifier, so ++ * no versioned reference to it survives in the compiled output. ++ */ ++#if defined(__linux__) && defined(__GLIBC__) ++extern void *dlvsym(void *handle, const char *symbol, const char *version); ++extern void *dlsym(void *handle, const char *symbol); ++static speed_t ++_supabase_compat_cfgetospeed(const struct termios *t) ++{ ++ static int inited = 0; ++ static speed_t (*fn)(const struct termios *) = NULL; ++ if (!inited) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlvsym((void *) 0, "cfgetospeed", "GLIBC_2.17"); ++ if (!fn) { ++ fn = (speed_t (*)(const struct termios *)) ++ dlsym((void *) 0, "cfgetospeed"); ++ } ++ inited = 1; ++ } ++ return fn ? fn(t) : 0; ++} ++#define cfgetospeed(t) _supabase_compat_cfgetospeed(t) ++#endif ++ + #include + + #if HAVE_GETTTYNAM diff --git a/nix/packages/postgres-portable.nix b/nix/packages/postgres-portable.nix index 5caf370308..9fd60f101d 100644 --- a/nix/packages/postgres-portable.nix +++ b/nix/packages/postgres-portable.nix @@ -3,11 +3,18 @@ stdenv, writeTextFile, patchelf, + ncurses, psql_17_cli, }: let configDir = ./cli-config; + # glibc 2.42 re-versions cfgetospeed. The bundle runs on the host's glibc, + # so ship an ncurses that resolves the older symbol at runtime. + ncursesCompat = ncurses.overrideAttrs (old: { + patches = (old.patches or [ ]) ++ [ ./patches/ncurses-cfgetospeed-old-glibc-compat.patch ]; + }); + receipt = writeTextFile { name = "cli-receipt"; destination = "/receipt.json"; @@ -218,7 +225,9 @@ stdenv.mkDerivation { break fi done - + ${lib.optionalString stdenv.isLinux '' + cp -f ${ncursesCompat}/lib/libncursesw.so.6 $out/lib/libncursesw.so.6 + ''} # Copy share directory if [ -d ${psql_17_cli.bin}/share ]; then cp -rL ${psql_17_cli.bin}/share/* $out/share/ 2>/dev/null || true