On Tue Aug 25, 2026 at 6:37 AM CDT, Andrew Dunstan wrote:
> Well, "growing" could cover a multitude of possibilities. It could mean
> there was one and now there are two. [...] But if you want to say that
> there is a significant number of people actually contributing here who
> use it that would be all the better for some evidence.
Fair, and I shouldn't have leaned on an unquantified "growing." Let me
separate what I can back up from what I can't.
What I can point to concretely:
- There is already an active pgsql-hackers thread, "Building with meson on
NixOS/nixpkgs," [1] where the Meson build was adjusted specifically
because of problems Nix/NixOS packagers hit. So Nix is already shaping
build-related decisions here whether or not we carry a flake.
- Wolfgang Walther maintains the PostgreSQL packaging in nixpkgs and has
posted here on exactly these issues.
- Supabase's fork use Nix extensively. [2]
- I keep a flake setup that I re-apply/use to enable predictable efficient
development cross-platform.
- Tristan (upthread) keeps a private flake and a NixOS-based buildfarm
client.
What I can't do is hand you a survey. I don't have a count of contributors
who develop on Nix, and I'd rather admit that than dress up a guess. If the
bar for this is demonstrated contributor demand, that's a reasonable bar and
I'm happy to let the thread be the evidence, if it's just me and Tristan, so
be it; this can wait.
> Historically we've been fairly resistant to carrying things related to
> how people build or develop postgres.
Understood, and I don't want to relitigate that policy. The narrower claim
I'd make is that a flake is closer to the .editorconfig / .dir-locals.el end
of the spectrum (declare-the-environment) than to endorsing a build system,
it doesn't touch configure, Meson, or the Makefiles. But I take the point
that the door being narrow is deliberate.
On Tue Aug 25, 2026 at 8:19 AM CDT, Tom Lane wrote:
> I might hold my nose if the effects extended only to one more root-level
> file (although that's not great). But if we're talking about rather
> expansive .gitexclude patterns, I'm going to push back on the grounds of
> possible unforeseen side-effects on other peoples' work.
That's a fair objection and easy to remove: v3 (attached) is exactly one new
root-level file, flake.nix, and nothing else. I've dropped the .gitignore
changes entirely.
For what it's worth on side-effects: the patterns I'd proposed were
root-anchored (/flake.lock, /result, /result-*), the same shape as the
existing /tmp_install/ and /portlock/ lines, so they couldn't have matched a
result/ elsewhere in the tree. But that's beside the point now, they're gone.
The build artifacts belong in each developer's own $GIT_DIR/info/exclude,
which is precisely what the .gitignore header already recommends for "files
from local workflows"; `nix build -o` can also just name the symlink. No
committed-ignore changes needed.
So the question really does reduce to your "one more root-level file, though
that's not great." I won't pretend that's nothing. If the consensus is that
even one file is more build/dev tooling than the tree wants to carry, I'll
accept that outcome, but if it's going to live somewhere, one self-contained
file at the root is the smallest footprint I can offer.
best.
-greg
[1]
https://pg.ddx.io/m/pgsql-hackers/[email protected]/T/
[2] https://github.com/supabase/postgres/blob/develop/flake.nix
From 83273f384bbf7d98418578697c3406e1c0699f73 Mon Sep 17 00:00:00 2001
From: Greg Burd <[email protected]>
Date: Tue, 25 Aug 2026 15:34:06 -0400
Subject: [PATCH v3] 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 increasingly BSD and illumos) get a single,
in-tree starting point instead of maintaining private, drifting copies.
It doesn't add a build system: `nix develop` drops you into a shell with
bison, flex, perl, the optional libraries, and the docs toolchain 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.
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.
This touches only a single new root-level file. Build artifacts
(flake.lock, result symlinks) are left to each developer's local ignore
($GIT_DIR/info/exclude), as the .gitignore header already recommends for
files from local workflows; `nix build -o` can also name the symlink.
---
flake.nix | 257 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 257 insertions(+)
create mode 100644 flake.nix
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 00000000000..7c113cdedc8
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,257 @@
+{
+ 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