On Tue Aug 26, 2026 at 12:45 AM CDT, Tom Lane wrote:
> I don't want to block this if there's actually a reasonable amount
> of demand.  Let's wait a bit to see if other requestors show up.

That's fair and I'm happy to let it sit. I won't campaign for it, if the
demand isn't there, it isn't there, and I'd rather this land because people
actually want it than because I pushed hard. I'll leave the thread open for
others to chime in.

In the meantime I've addressed the concrete points so a v4 is ready to go if
and when it's wanted. Attached.

> If we do go forward, I think the flake.nix file needs a header comment
> covering at least these points:
> 1. An explanation of what it is/does, aimed at people who never heard
> of Nix.  Doesn't need to be long.
> 2. A suggestion to add thus-and-such personal ~/.gitexclude patterns
> if you want to use Nix.

Done, both. The file now opens with a short header that explains what Nix and
a flake are for someone who's never encountered them, states plainly that you
do not need Nix to build PostgreSQL (the normal instructions are unchanged
and nothing in the build depends on this file), and gives the exact
local-ignore incantation:

  printf '/flake.lock\n/result\n/result-*\n' >> "$(git rev-parse 
--git-dir)/info/exclude"

i.e. into the developer's own $GIT_DIR/info/exclude, not the committed
.gitignore.

On Tue Aug 26, 2026 at 3:51 AM CDT, Daniel Gustafsson wrote:
> I would add a third: A note on how the file is intended to be kept up to
> date for non-Nix users.  If I add a dependency to autoconf/meson, what am
> I expected to do to make sure this file doesn't become stale.

Good question, and it's the one that actually matters for whether this is a
burden on people who don't use Nix. The honest answer, which is now in the
header:

You are not expected to do anything. If you add a new optional dependency to
configure/meson and don't touch this file, the flake keeps building, it just
won't expose the new feature. The Meson path sets mesonAutoFeatures =
"disabled", so nothing gets silently auto-enabled or auto-broken by an
unknown dependency; the feature is simply off until someone adds a toggle.
Adding one is a two-line change (a boolean plus its buildInput and flag), and
such patches are welcome on -hackers, but the tree never breaks in the
meantime because no part of the normal build consults this file.

So the maintenance contract is deliberately weak by design: a non-Nix hacker
can ignore it entirely, and the worst outcome of it going stale is a missing
feature toggle, not a broken build.

Taking the wiki suggestion directly: I've drafted a companion page (attached,
Nix_Flake.mediawiki, not yet published) with the longer-form version, what
Nix is for someone who's never used it, a quick start, the local-ignore
recipe, the presets, and a full option reference alongside the same "keeping
it in sync" notes. If there's interest I'd post that to the wiki and keep the
in-file header short; if not, no harm done, the header stands on its own.

Happy to sit on this until the demand question resolves.

best.

-greg
From 7b9cfc6223274956c66b8929f189b6762ca756ae Mon Sep 17 00:00:00 2001
From: Greg Burd <[email protected]>
Date: Tue, 25 Aug 2026 15:34:06 -0400
Subject: [PATCH v4] Add a Nix flake for reproducible builds and dev shells

Provide a flake.nix at the repository root so contributors on Nix-based
systems (Linux, macOS, and the *BSDs) get a single, in-tree starting point
instead of maintaining private, drifting copies.

It doesn't add a build system and nothing in the normal build depends on
it: `nix develop` drops you into a shell with meson/ninja, bison, flex,
perl, and the optional libraries on PATH, where `meson setup` (the default)
or `./configure` just works; `nix build` produces a server.

Every optional configure/Meson feature is a boolean toggle with
platform-appropriate defaults (io_uring, libnuma, systemd, PAM on Linux;
Bonjour on macOS), so it is a starting point, not a policy. Presets cover
debug, minimal, and autoconf builds.

The file carries a header comment aimed at readers who have never used
Nix: what it is, how to run it, the personal ~/.git/info/exclude lines to
add (flake.lock and result symlinks are deliberately not in .gitignore),
and how the file is expected to be kept in sync as configure/meson gain
dependencies (a new optional dependency is simply left disabled until a
two-line toggle is added; the flake keeps building meanwhile).

No flake.lock is committed on purpose: pinning nixpkgs would freeze
contributors to one dependency snapshot. The flake instead tracks whatever
nixpkgs the developer already runs; anyone needing reproducibility can
generate a lock locally.
---
 flake.nix | 287 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 287 insertions(+)
 create mode 100644 flake.nix

diff --git a/flake.nix b/flake.nix
new file mode 100644
index 00000000000..ce4fb5a0052
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,287 @@
+# PostgreSQL Nix flake.
+#
+# What this is: Nix (https://nixos.org) is a package manager, available on
+# Linux, macOS, and the *BSDs, that can assemble an exact set of build
+# dependencies without installing them system-wide. A "flake" is the small
+# manifest below describing those dependencies. You do NOT need Nix to build
+# PostgreSQL; the usual `./configure`/`meson setup` instructions are
+# unchanged. This file only helps developers who already use Nix.
+#
+#   nix develop     -- drop into a shell with the full build toolchain
+#                      (meson/ninja, bison, flex, perl, and the optional
+#                      libraries) on PATH; then `meson setup build && ninja
+#                      -C build` or `./configure && make` as usual.
+#   nix build       -- build the server directly.
+#
+# Local ignores: Nix writes a `flake.lock` and `result` symlinks into the
+# working tree. These are intentionally NOT added to .gitignore (they are
+# not relevant to non-Nix developers). If you use Nix, add them to your
+# personal, non-committed ignore file instead:
+#
+#   printf '/flake.lock\n/result\n/result-*\n' >> "$(git rev-parse --git-dir)/info/exclude"
+#
+# Keeping this current: this flake does not track upstream automatically.
+# When a new optional dependency is added to configure/meson, this file will
+# simply not enable it (mesonAutoFeatures is "disabled"), so the flake keeps
+# building, it just won't expose the new feature until a toggle is added
+# here. Adding one is a two-line change (a boolean plus its buildInput/flag);
+# patches to keep this file in sync are welcome on pgsql-hackers. Nothing in
+# the normal build depends on this file, so it going briefly stale breaks
+# nothing.
+{
+  description = "PostgreSQL, built from this source tree";
+
+  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+
+  outputs =
+    { self, nixpkgs }:
+    let
+      systems = [
+        "x86_64-linux"
+        "aarch64-linux"
+        "x86_64-darwin"
+        "aarch64-darwin"
+      ];
+      forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
+
+      # A single builder covering every optional feature ./configure and
+      # meson expose. Each feature is a boolean toggle wired to its
+      # buildInput + flag; flip any of them via .override { ... }.
+      # Platform-specific features default to their availability.
+      postgresqlFor =
+        pkgs:
+        let
+          inherit (pkgs) lib stdenv;
+          onLinux = stdenv.hostPlatform.isLinux;
+          onDarwin = stdenv.hostPlatform.isDarwin;
+        in
+        lib.makeOverridable (
+          {
+            # Build system: "meson" (ninja) or "autoconf" (configure/make).
+            # Meson is the default; it is the project's eventual sole build system.
+            buildSystem ? "meson",
+
+            # Optional library features (buildInput + flag).
+            icuSupport ? true,
+            readlineSupport ? true,
+            zlibSupport ? true,
+            opensslSupport ? true,
+            libxmlSupport ? true,
+            libxsltSupport ? true,
+            lz4Support ? true,
+            zstdSupport ? true,
+            uuidSupport ? true,
+            curlSupport ? true,
+
+            # Procedural languages.
+            perlSupport ? true,
+            pythonSupport ? true,
+            tclSupport ? true,
+
+            # Platform-gated features.
+            systemdSupport ? onLinux,
+            selinuxSupport ? false,
+            liburingSupport ? onLinux,
+            numaSupport ? onLinux,
+            gssSupport ? true,
+            ldapSupport ? false,
+            pamSupport ? onLinux,
+            bonjourSupport ? onDarwin,
+            llvmSupport ? false,
+
+            # Developer / build-shape toggles (no extra deps).
+            cassert ? false,
+            debugSymbols ? false,
+            tapTests ? true,
+            injectionPoints ? false,
+
+            # Documentation build (SGML/DocBook toolchain).
+            docs ? false,
+          }:
+          let
+            useMeson = buildSystem == "meson";
+
+            # feature -> { flag = configure arg; dep = buildInput or null; }
+            featureFlag = cond: flag: lib.optional cond flag;
+            featureDep = cond: dep: lib.optional cond dep;
+
+            configureFeatures = lib.flatten [
+              (featureFlag icuSupport "--with-icu")
+              (featureFlag (!icuSupport) "--without-icu")
+              (featureFlag (!readlineSupport) "--without-readline")
+              (featureFlag (!zlibSupport) "--without-zlib")
+              (featureFlag opensslSupport "--with-ssl=openssl")
+              (featureFlag libxmlSupport "--with-libxml")
+              (featureFlag libxsltSupport "--with-libxslt")
+              (featureFlag lz4Support "--with-lz4")
+              (featureFlag zstdSupport "--with-zstd")
+              (featureFlag uuidSupport "--with-uuid=e2fs")
+              (featureFlag curlSupport "--with-libcurl")
+              (featureFlag perlSupport "--with-perl")
+              (featureFlag pythonSupport "--with-python")
+              (featureFlag tclSupport "--with-tcl")
+              (featureFlag systemdSupport "--with-systemd")
+              (featureFlag selinuxSupport "--with-selinux")
+              (featureFlag liburingSupport "--with-liburing")
+              (featureFlag numaSupport "--with-libnuma")
+              (featureFlag gssSupport "--with-gssapi")
+              (featureFlag ldapSupport "--with-ldap")
+              (featureFlag pamSupport "--with-pam")
+              (featureFlag bonjourSupport "--with-bonjour")
+              (featureFlag llvmSupport "--with-llvm")
+              (featureFlag cassert "--enable-cassert")
+              (featureFlag debugSymbols "--enable-debug")
+              (featureFlag tapTests "--enable-tap-tests")
+              (featureFlag injectionPoints "--enable-injection-points")
+            ];
+
+            # meson uses -Dfeature=enabled/disabled instead of --with-*.
+            mesonFeatures = lib.flatten [
+              [ "-Dicu=${if icuSupport then "enabled" else "disabled"}" ]
+              [ "-Dreadline=${if readlineSupport then "enabled" else "disabled"}" ]
+              [ "-Dzlib=${if zlibSupport then "enabled" else "disabled"}" ]
+              [ "-Dssl=${if opensslSupport then "openssl" else "none"}" ]
+              [ "-Dlibxml=${if libxmlSupport then "enabled" else "disabled"}" ]
+              [ "-Dlibxslt=${if libxsltSupport then "enabled" else "disabled"}" ]
+              [ "-Dlz4=${if lz4Support then "enabled" else "disabled"}" ]
+              [ "-Dzstd=${if zstdSupport then "enabled" else "disabled"}" ]
+              [ "-Duuid=${if uuidSupport then "e2fs" else "none"}" ]
+              [ "-Dlibcurl=${if curlSupport then "enabled" else "disabled"}" ]
+              [ "-Dplperl=${if perlSupport then "enabled" else "disabled"}" ]
+              [ "-Dplpython=${if pythonSupport then "enabled" else "disabled"}" ]
+              [ "-Dpltcl=${if tclSupport then "enabled" else "disabled"}" ]
+              [ "-Dsystemd=${if systemdSupport then "enabled" else "disabled"}" ]
+              [ "-Dselinux=${if selinuxSupport then "enabled" else "disabled"}" ]
+              [ "-Dliburing=${if liburingSupport then "enabled" else "disabled"}" ]
+              [ "-Dlibnuma=${if numaSupport then "enabled" else "disabled"}" ]
+              [ "-Dgssapi=${if gssSupport then "enabled" else "disabled"}" ]
+              [ "-Dldap=${if ldapSupport then "enabled" else "disabled"}" ]
+              [ "-Dpam=${if pamSupport then "enabled" else "disabled"}" ]
+              [ "-Dbonjour=${if bonjourSupport then "enabled" else "disabled"}" ]
+              [ "-Dllvm=${if llvmSupport then "enabled" else "disabled"}" ]
+              [ "-Dcassert=${lib.boolToString cassert}" ]
+              [ "-Dtap_tests=${if tapTests then "enabled" else "disabled"}" ]
+              [ "-Dinjection_points=${lib.boolToString injectionPoints}" ]
+            ];
+
+            buildInputs = lib.flatten (with pkgs; [
+              (featureDep icuSupport icu)
+              (featureDep readlineSupport readline)
+              (featureDep zlibSupport zlib)
+              (featureDep opensslSupport openssl)
+              (featureDep libxmlSupport libxml2)
+              (featureDep libxsltSupport libxslt)
+              (featureDep lz4Support lz4)
+              (featureDep zstdSupport zstd)
+              (featureDep uuidSupport libuuid)
+              (featureDep curlSupport curl)
+              (featureDep perlSupport perl)
+              (featureDep pythonSupport python3)
+              (featureDep tclSupport tcl)
+              (featureDep systemdSupport systemdLibs)
+              (featureDep selinuxSupport libselinux)
+              (featureDep liburingSupport liburing)
+              (featureDep numaSupport numactl)
+              (featureDep gssSupport libkrb5)
+              (featureDep ldapSupport openldap)
+              (featureDep pamSupport linux-pam)
+              (featureDep llvmSupport llvmPackages.llvm)
+            ]);
+          in
+          stdenv.mkDerivation {
+            pname = "postgresql";
+            version = "20devel";
+            src = self;
+
+            strictDeps = true;
+
+            nativeBuildInputs = lib.flatten (with pkgs; [
+              bison
+              flex
+              perl
+              pkg-config
+              (featureDep useMeson meson)
+              (featureDep useMeson ninja)
+              (featureDep llvmSupport llvmPackages.llvm.dev)
+              (featureDep docs docbook-xsl-nons)
+              (featureDep docs docbook_xml_dtd_45)
+              (featureDep docs libxslt)
+            ]);
+
+            inherit buildInputs;
+
+            # ---- autoconf path ----
+            configureFlags = lib.optionals (!useMeson) configureFeatures;
+
+            # ---- meson path ----
+            mesonBuildType = "release";
+            mesonFlags = lib.optionals useMeson mesonFeatures;
+            dontUseMesonConfigure = !useMeson;
+            mesonAutoFeatures = "disabled";
+
+            enableParallelBuilding = true;
+            doCheck = tapTests;
+
+            meta = with lib; {
+              description = "Object-relational database management system, built from source";
+              homepage = "https://www.postgresql.org/";;
+              license = licenses.postgresql;
+              platforms = platforms.unix;
+              mainProgram = "psql";
+            };
+          }
+        )
+        { };
+    in
+    {
+      packages = forAllSystems (pkgs: rec {
+        postgresql = postgresqlFor pkgs;
+        # Common presets built on top of the fully-parameterized default.
+        postgresql-autoconf = postgresql.override { buildSystem = "autoconf"; };
+        postgresql-debug = postgresql.override {
+          cassert = true;
+          debugSymbols = true;
+          injectionPoints = true;
+        };
+        postgresql-minimal = postgresql.override {
+          icuSupport = false;
+          readlineSupport = false;
+          zlibSupport = false;
+          opensslSupport = false;
+          libxmlSupport = false;
+          libxsltSupport = false;
+          lz4Support = false;
+          zstdSupport = false;
+          uuidSupport = false;
+          curlSupport = false;
+          perlSupport = false;
+          pythonSupport = false;
+          tclSupport = false;
+          systemdSupport = false;
+          liburingSupport = false;
+          numaSupport = false;
+          gssSupport = false;
+          pamSupport = false;
+        };
+        default = postgresql;
+      });
+
+      # `nix develop`: the postgresql package already brings in the full
+      # build toolchain (meson, ninja, bison, flex, perl, python3, tcl, and
+      # the optional libraries) via inputsFrom. We add only what a dev shell
+      # wants on top: ccache, and the DocBook toolchain for building docs
+      # (docs are off in the default package build).
+      devShells = forAllSystems (pkgs: {
+        default = pkgs.mkShell {
+          inputsFrom = [ self.packages.${pkgs.stdenv.hostPlatform.system}.postgresql ];
+          packages = with pkgs; [
+            ccache
+            docbook_xml_dtd_45
+            docbook-xsl-nons
+          ];
+        };
+      });
+
+      formatter = forAllSystems (pkgs: pkgs.nixfmt);
+    };
+}
-- 
2.54.0

Attachment: Nix_Flake.mediawiki
Description: Binary data

Reply via email to