pg.ddx.io pgsql-hackers@postgresql.org mailing list archive
help / color / mirror / Atom feedAdd a Nix flake
14+ messages / 8 participants
[nested] [flat]
* Add a Nix flake
@ 2026-08-24 16:58 Greg Burd <greg@burd.me>
0 siblings, 4 replies; 14+ messages in thread
From: Greg Burd @ 2026-08-24 16:58 UTC (permalink / raw)
To: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Hackers,
I'd like to propose adding a flake.nix at the repository root. Attached
is a first cut.
This is not another build system. It doesn't touch configure, Meson, or the
Makefiles, it wires up what we already have. A flake is a small, declarative
manifest that tells Nix how to fetch our build dependencies and drop a
developer into a shell where ./configure && make or meson setup just
works, with bison, flex, perl, the optional libraries, and the docs
toolchain all present and pinned to compatible versions. nix develop gives
you that shell; nix build produces a server.
The reason to carry it in-tree: Nix users are a growing segment of the
PostgreSQL developer base across Linux, macOS, and increasingly the BSDs and
even illumos. Today each of them keeps a private flake to hack on Postgres, I
have one, and I know I'm not alone. These private copies drift, disagree on
which features to enable, and have to be re-derived every time someone new
wants to contribute from a Nix machine. A single blessed flake in the tree
gives everyone the same reproducible starting point and one place to keep it
current, the same argument that motivates the .editorconfig and CI files we
already ship.
The flake exposes a toggle for every optional feature configure and Meson
support, both build systems, and platform-appropriate defaults (io_uring,
libnuma, systemd, PAM on Linux; Bonjour on macOS), so it's a starting point,
not a policy so flip anything with an override.
One deliberate omission: there is no flake.lock. A lock file pins the exact
nixpkgs revision, which is the right call for an application that wants a
frozen environment, but wrong for us. We don't want to freeze contributors to
one snapshot of the dependency universe, and we don't want a lock file to
become one more thing that goes stale in the tree and needs bumping. Leaving
it out means the flake tracks whatever nixpkgs the developer already runs,
which is exactly the behavior a build-from-source developer wants. Anyone who
needs reproducibility can generate a lock locally; the tree stays clean.
It's meant to sit at the root next to configure, not in a subdirectory, so
that a fresh checkout is immediately usable with nix develop.
To use it you'll need to be in a Nix environment. This means a Nix-based OS
like NixOS or the macOS/Windows layers that bring in the Nix environment.
Start by reading the https://nixos.org/learn/ information.
With a flake you can start a "developer shell" (a "dev shell") which will have
all the dependencies required to build and run Postgres, no installing All The
Things (TM) if you buy into this model you have a predictable environment, a
shell with developer tools prepared and present always at hand when needed.
So, first start the dev(eloper) shell:
```
nix develop
# then, meson (the default direction):
meson setup build && ninja -C build
# or classic autoconf:
./configure && make -j
```
You don't have to enter the dev shell, you could instead build a server:
```
nix build # default: meson, all features for your platform
./result/bin/postgres --version
```
The presets:
```
nix build .#postgresql-debug # cassert + debug syms + injection points
nix build .#postgresql-minimal # no optional libs — fastest compile
nix build .#postgresql-autoconf # configure/make instead of meson
```
Flip any single feature (26 toggles) without a preset:
```
nix build --expr '(builtins.getFlake (toString ./.)).packages.x86_64-linux.postgresql.override { llvmSupport = true; cassert = true; }'
```
Run without installing:
```
nix run . -- --version # runs postgres (mainProgram is psql, so:)
nix run .#postgresql -- --version
```
There are many other things we could add into the flake such as
cross-compilation, but to start off this should suffice. I hope this generates
interest and constructive debate. I'll say upfront, I'm not a Nix master,
just a user and I find it invaluable. I'm sure I'm not alone.
Feedback welcome.
best.
-greg
Attachments:
[text/x-patch] v1-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch (11.9K, ../../a0979d2a-4670-44fe-864f-c0425edbd4f1@app.fastmail.com/2-v1-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch)
download | inline diff:
From 0ceb158a9c610a017a1cf5298b58d469cf0d7646 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Mon, 24 Aug 2026 12:53:12 -0400
Subject: [PATCH v1] 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 and add a file that goes stale in
the tree. The flake instead tracks whatever nixpkgs the developer already
runs; anyone needing reproducibility can generate a lock locally.
---
flake.nix | 261 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 261 insertions(+)
create mode 100644 flake.nix
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 00000000000..ab376df4a76
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,261 @@
+{
+ 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`: full toolchain for configure/make, meson, docs,
+ # TAP tests, and all three PLs — regardless of which features a
+ # given build enables.
+ 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
+ libxslt
+ meson
+ ninja
+ perl
+ python3
+ tcl
+ ];
+ };
+ });
+
+ formatter = forAllSystems (pkgs: pkgs.nixfmt);
+ };
+}
--
2.54.0
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-24 19:39 Tristan Partin <tristan@partin.io>
parent: Greg Burd <greg@burd.me>
3 siblings, 1 reply; 14+ messages in thread
From: Tristan Partin @ 2026-08-24 19:39 UTC (permalink / raw)
To: Greg Burd <greg@burd.me>; +Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
On Mon Aug 24, 2026 at 11:59 AM CDT, Greg Burd wrote:
> Hackers,
>
> I'd like to propose adding a flake.nix at the repository root. Attached
> is a first cut.
+1
> This is not another build system. It doesn't touch configure, Meson, or the
> Makefiles, it wires up what we already have. A flake is a small, declarative
> manifest that tells Nix how to fetch our build dependencies and drop a
> developer into a shell where ./configure && make or meson setup just
> works, with bison, flex, perl, the optional libraries, and the docs
> toolchain all present and pinned to compatible versions. nix develop gives
> you that shell; nix build produces a server.
>
> The reason to carry it in-tree: Nix users are a growing segment of the
> PostgreSQL developer base across Linux, macOS, and increasingly the BSDs and
> even illumos. Today each of them keeps a private flake to hack on Postgres, I
> have one, and I know I'm not alone. These private copies drift, disagree on
> which features to enable, and have to be re-derived every time someone new
> wants to contribute from a Nix machine. A single blessed flake in the tree
> gives everyone the same reproducible starting point and one place to keep it
> current, the same argument that motivates the .editorconfig and CI files we
> already ship.
I am one of the people that has a private copy. I've also been working
on a NixOS-based buildfarm client that includes a derivation for the
buildfarm-client code.
> The flake exposes a toggle for every optional feature configure and Meson
> support, both build systems, and platform-appropriate defaults (io_uring,
> libnuma, systemd, PAM on Linux; Bonjour on macOS), so it's a starting point,
> not a policy so flip anything with an override.
>
> One deliberate omission: there is no flake.lock. A lock file pins the exact
> nixpkgs revision, which is the right call for an application that wants a
> frozen environment, but wrong for us. We don't want to freeze contributors to
> one snapshot of the dependency universe, and we don't want a lock file to
> become one more thing that goes stale in the tree and needs bumping. Leaving
> it out means the flake tracks whatever nixpkgs the developer already runs,
> which is exactly the behavior a build-from-source developer wants. Anyone who
> needs reproducibility can generate a lock locally; the tree stays clean.
I think the lack of flake.lock makes sense. I would add it to the
.gitignore. Additionally, I would also add `/result` and `/result-*` to
the .gitignore.
> It's meant to sit at the root next to configure, not in a subdirectory, so
> that a fresh checkout is immediately usable with nix develop.
>
> To use it you'll need to be in a Nix environment. This means a Nix-based OS
> like NixOS or the macOS/Windows layers that bring in the Nix environment.
> Start by reading the https://nixos.org/learn/ information.
Can be Linux as well! For instance, I am using Nix on Fedora, which is
available in the Fedora system repositories.
> With a flake you can start a "developer shell" (a "dev shell") which will have
> all the dependencies required to build and run Postgres, no installing All The
> Things (TM) if you buy into this model you have a predictable environment, a
> shell with developer tools prepared and present always at hand when needed.
>
> So, first start the dev(eloper) shell:
>
> ```
> nix develop
> # then, meson (the default direction):
> meson setup build && ninja -C build
>
> # or classic autoconf:
> ./configure && make -j
> ```
>
> You don't have to enter the dev shell, you could instead build a server:
>
> ```
> nix build # default: meson, all features for your platform
> ./result/bin/postgres --version
> ```
>
> The presets:
>
> ```
> nix build .#postgresql-debug # cassert + debug syms + injection points
> nix build .#postgresql-minimal # no optional libs — fastest compile
> nix build .#postgresql-autoconf # configure/make instead of meson
> ```
>
> Flip any single feature (26 toggles) without a preset:
>
> ```
> nix build --expr '(builtins.getFlake (toString ./.)).packages.x86_64-linux.postgresql.override { llvmSupport = true; cassert = true; }'
> ```
I didn't know that this was a thing. What a mouthful!
> Run without installing:
>
> ```
> nix run . -- --version # runs postgres (mainProgram is psql, so:)
> nix run .#postgresql -- --version
> ```
>
> There are many other things we could add into the flake such as
> cross-compilation, but to start off this should suffice. I hope this generates
> interest and constructive debate. I'll say upfront, I'm not a Nix master,
> just a user and I find it invaluable. I'm sure I'm not alone.
>
> Feedback welcome.
I think this is a great first pass! I am a recent Nix convert myself,
and I have found the development shell to be quite invaluable. I have
added flake.nix's to all of my personal projects. I think lowering the
bar to PostgreSQL development could really make a meaningful difference
in attracting new contributors.
I think this will also have side benefits of making things easier to
test. For instance, we could start inlining buildfarm client members
configurations as derivations in this repository. Then we can have
a library of derivations to test against that are tracked in version
control that are easily visible to everyone. People who find that their
submissions are failing on certain animals could more easily test and
diagnose what is causing the animal to fail. Additionally, I wonder if
NixOS VM tests could expose new ways to do automated testing of
Postgres. That is not something that I have thought about.
Regarding the code, can you explain the reasoning for the packages list
in the development shell? It seems like everything in the list is
already included by the Postgres package.
--
Tristan Partin
PostgreSQL Contributors Team
AWS (https://aws.amazon.com)
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-25 09:49 Greg Burd <greg@burd.me>
parent: Tristan Partin <tristan@partin.io>
0 siblings, 1 reply; 14+ messages in thread
From: Greg Burd @ 2026-08-25 09:49 UTC (permalink / raw)
To: Tristan Partin <tristan@partin.io>; +Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
On Mon Aug 24, 2026 at 2:39 PM CDT, Tristan Partin wrote:
> +1
Thanks Tristan, glad to have another Nix user weigh in.
>> A single blessed flake in the tree gives everyone the same reproducible
>> starting point [...]
>
> I am one of the people that has a private copy. I've also been working
> on a NixOS-based buildfarm client that includes a derivation for the
> buildfarm-client code.
That's cool, let's make sure this and that somehow knit up into something
useful. Do you want to share it on this thread or start another one?
>> One deliberate omission: there is no flake.lock.
>
> I think the lack of flake.lock makes sense. I would add it to the
> .gitignore. Additionally, I would also add `/result` and `/result-*` to
> the .gitignore.
Done. Added a small "Nix (see flake.nix)" block to the root .gitignore
covering /flake.lock, /result, and /result-*. Root-anchored so we don't
accidentally ignore a result/ somewhere in the tree.
>> To use it you'll need to be in a Nix environment. This means a Nix-based
>> OS like NixOS or the macOS/Windows layers [...]
>
> Can be Linux as well! For instance, I am using Nix on Fedora, which is
> available in the Fedora system repositories.
Good correction, you're right, and it's an important one. Nix runs anywhere
the package manager is installed; it doesn't require NixOS. I'll fix that
wording in the commit-message/docs framing rather than the code, since the
flake itself is already OS-agnostic and useful in all these locations. As
it happens I use Nix on Fedora on one host, Nix on BSD on another, NixOS
on a separate host and I'm also working to Nix-ify Illumos [1].
>> Flip any single feature (26 toggles) without a preset:
>> nix build --expr '(builtins.getFlake (toString ./.)).packages...'
>
> I didn't know that this was a thing. What a mouthful!
Agreed, it is. It's the escape hatch, not the ergonomic path, most people
will want a preset or their own thin wrapper flake with `.override { ... }`.
I included it only to show the full toggle surface is reachable without
editing the file.
I'm also sure there are ways to add simplified common config into the flake
but I was starting off with something very bland/effective and hopefully
not overly opinionated to gain buy-in.
> I think this will also have side benefits of making things easier to
> test. For instance, we could start inlining buildfarm client members
> configurations as derivations in this repository. [...] Additionally, I
> wonder if NixOS VM tests could expose new ways to do automated testing of
> Postgres.
Both are appealing, and I think they're the real long-term payoff, a
derivation library of animal configs under version control, and NixOS VM
tests for things that are painful to exercise otherwise (replication
topologies, systemd integration, upgrade paths). I'd like to keep v1 to just
the flake so it's easy to review and agree on, then build those out as
separate patches on top. Happy to collaborate!
> Regarding the code, can you explain the reasoning for the packages list
> in the development shell? It seems like everything in the list is
> already included by the Postgres package.
You're right, and thank you, that list was mostly redundant. `inputsFrom =
[ postgresql ]` already pulls in the package's nativeBuildInputs and
buildInputs, so meson, ninja, bison, flex, perl, python3, tcl, and libxslt
were all being listed twice. I've trimmed the devShell down to only what the
package does *not* provide:
- ccache (a dev convenience, not a build input), and
- docbook_xml_dtd_45 + docbook-xsl-nons (the DocBook toolchain, since docs
are off in the default package build, so `nix develop` can build docs
without a separate override).
Verified the trimmed shell still exposes meson/ninja/perl/python3/tcl/libxslt
via inputsFrom, so nothing was actually lost. Will include that in v2.
Thanks again for the careful read.
best.
-greg
Attachments:
[text/x-patch] v2-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch (12.2K, ../../7ee22a5d-3776-49d5-8309-98097ffb88b1@app.fastmail.com/2-v2-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch)
download | inline diff:
From 0e851da8690e57cff62e79e0722ebb5f2d5086e2 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Mon, 24 Aug 2026 12:53:12 -0400
Subject: [PATCH v2] 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 and add a file that goes stale in
the tree. The flake instead tracks whatever nixpkgs the developer already
runs; anyone needing reproducibility can generate a lock locally.
---
.gitignore | 5 ++
flake.nix | 257 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 262 insertions(+)
create mode 100644 flake.nix
diff --git a/.gitignore b/.gitignore
index 4e911395fe3..e46003ca051 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,3 +43,8 @@ lib*.pc
/Release/
/tmp_install/
/portlock/
+
+# Nix (see flake.nix)
+/flake.lock
+/result
+/result-*
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
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-25 11:37 Andrew Dunstan <andrew@dunslane.net>
parent: Greg Burd <greg@burd.me>
3 siblings, 2 replies; 14+ messages in thread
From: Andrew Dunstan @ 2026-08-25 11:37 UTC (permalink / raw)
To: Greg Burd <greg@burd.me>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
On 2026-08-24 Mo 12:58 PM, Greg Burd wrote:
>
> The reason to carry it in-tree: Nix users are a growing segment of the
> PostgreSQL developer base across Linux, macOS, and increasingly the BSDs and
> even illumos.
Well, "growing" could cover a multitude of possibilities. It could mean
there was one and now there are two. Maybe there are lots out there and
I at least just haven't heard of it. 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.
Historically we've been fairly resistant to carrying things related to
how people build or develop postgres.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-25 13:19 Tom Lane <tgl@sss.pgh.pa.us>
parent: Andrew Dunstan <andrew@dunslane.net>
1 sibling, 1 reply; 14+ messages in thread
From: Tom Lane @ 2026-08-25 13:19 UTC (permalink / raw)
To: Andrew Dunstan <andrew@dunslane.net>; +Cc: Greg Burd <greg@burd.me>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Andrew Dunstan <andrew@dunslane.net> writes:
> Historically we've been fairly resistant to carrying things related to
> how people build or develop postgres.
Yeah. 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.
regards, tom lane
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-26 05:33 Greg Burd <greg@burd.me>
parent: Tom Lane <tgl@sss.pgh.pa.us>
0 siblings, 1 reply; 14+ messages in thread
From: Greg Burd @ 2026-08-26 05:33 UTC (permalink / raw)
To: Tom Lane <tgl@sss.pgh.pa.us>; Andrew Dunstan <andrew@dunslane.net>; +Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
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/5d6b6485-9eff-44a0-99ac-661fdeb72a21@technowledgy.de/T/
[2] https://github.com/supabase/postgres/blob/develop/flake.nix
Attachments:
[text/x-patch] v3-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch (12.2K, ../../b6156ff0-d924-4a54-b4ef-7857da2dbc6a@app.fastmail.com/2-v3-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch)
download | inline diff:
From 83273f384bbf7d98418578697c3406e1c0699f73 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
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
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-26 05:45 Tom Lane <tgl@sss.pgh.pa.us>
parent: Greg Burd <greg@burd.me>
0 siblings, 1 reply; 14+ messages in thread
From: Tom Lane @ 2026-08-26 05:45 UTC (permalink / raw)
To: Greg Burd <greg@burd.me>; +Cc: Andrew Dunstan <andrew@dunslane.net>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
"Greg Burd" <greg@burd.me> writes:
> 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'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.
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.
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. (Some of our other root files
could use some self-justification too :-()
2. A suggestion to add thus-and-such personal ~/.gitexclude patterns
if you want to use Nix.
regards, tom lane
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-26 08:51 Daniel Gustafsson <daniel@yesql.se>
parent: Tom Lane <tgl@sss.pgh.pa.us>
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Gustafsson @ 2026-08-26 08:51 UTC (permalink / raw)
To: Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Greg Burd <greg@burd.me>; Andrew Dunstan <andrew@dunslane.net>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
> On 26 Aug 2026, at 07:45, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> 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. (Some of our other root files
> could use some self-justification too :-()
>
> 2. A suggestion to add thus-and-such personal ~/.gitexclude patterns
> if you want to use Nix.
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. (I obviously have no idea
what that something might be, maybe it's just "email -hackers"?) If this
information is better maintained as a Wiki page then a link would suffice of
course.
--
Daniel Gustafsson
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-26 16:56 Greg Burd <greg@burd.me>
parent: Daniel Gustafsson <daniel@yesql.se>
0 siblings, 0 replies; 14+ messages in thread
From: Greg Burd @ 2026-08-26 16:56 UTC (permalink / raw)
To: Daniel Gustafsson <daniel@yesql.se>; Tom Lane <tgl@sss.pgh.pa.us>; +Cc: Andrew Dunstan <andrew@dunslane.net>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
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
Attachments:
[text/x-patch] v4-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch (14.1K, ../../f1e5ef58-521f-4a35-b389-f2ac91ffb8b3@app.fastmail.com/2-v4-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch)
download | inline diff:
From 7b9cfc6223274956c66b8929f189b6762ca756ae Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
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
[application/octet-stream] Nix_Flake.mediawiki (7.1K, ../../f1e5ef58-521f-4a35-b389-f2ac91ffb8b3@app.fastmail.com/3-Nix_Flake.mediawiki)
download
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-26 18:28 Peter Eisentraut <peter@eisentraut.org>
parent: Greg Burd <greg@burd.me>
3 siblings, 0 replies; 14+ messages in thread
From: Peter Eisentraut @ 2026-08-26 18:28 UTC (permalink / raw)
To: Greg Burd <greg@burd.me>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
On 24.08.26 18:58, Greg Burd wrote:
> The reason to carry it in-tree: Nix users are a growing segment of the
> PostgreSQL developer base across Linux, macOS, and increasingly the BSDs and
> even illumos. Today each of them keeps a private flake to hack on Postgres, I
> have one, and I know I'm not alone.
I don't know. Over time, people made similar arguments about Homebrew,
Docker, and there will be more after this. People who are interested in
this can band together and maintain it among themselves.
> These private copies drift, disagree on
> which features to enable, and have to be re-derived every time someone new
> wants to contribute from a Nix machine. A single blessed flake in the tree
> gives everyone the same reproducible starting point and one place to keep it
> current, the same argument that motivates the .editorconfig and CI files we
> already ship.
I don't think these are good comparisons. A Nix configuration is
probably of interest to on the order of 1% of developers, whereas these
other things are relevant to most developers, and also importantly,
changes can be verified easily by anyone, without having to learn about
some new platform or tool.
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-26 19:36 Tristan Partin <tristan@partin.io>
parent: Greg Burd <greg@burd.me>
0 siblings, 1 reply; 14+ messages in thread
From: Tristan Partin @ 2026-08-26 19:36 UTC (permalink / raw)
To: Greg Burd <greg@burd.me>; +Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
On Tue Aug 25, 2026 at 9:50 AM UTC, Greg Burd wrote:
> On Mon Aug 24, 2026 at 2:39 PM CDT, Tristan Partin wrote:
>> +1
>
> Thanks Tristan, glad to have another Nix user weigh in.
>
>>> A single blessed flake in the tree gives everyone the same reproducible
>>> starting point [...]
>>
>> I am one of the people that has a private copy. I've also been working
>> on a NixOS-based buildfarm client that includes a derivation for the
>> buildfarm-client code.
>
> That's cool, let's make sure this and that somehow knit up into something
> useful. Do you want to share it on this thread or start another one?
I think it is probably best not to muddy up the thread. I can announce
the thing when it is ready to share publicly, probably after PGConf.EU.
I think it could be a game changer for allocating and maintaining
buildfarm clients. Eventually it might help bolster your effort in this
thread.
>>> One deliberate omission: there is no flake.lock.
>>
>> I think the lack of flake.lock makes sense. I would add it to the
>> .gitignore. Additionally, I would also add `/result` and `/result-*` to
>> the .gitignore.
>
> Done. Added a small "Nix (see flake.nix)" block to the root .gitignore
> covering /flake.lock, /result, and /result-*. Root-anchored so we don't
> accidentally ignore a result/ somewhere in the tree.
>
>>> To use it you'll need to be in a Nix environment. This means a Nix-based
>>> OS like NixOS or the macOS/Windows layers [...]
>>
>> Can be Linux as well! For instance, I am using Nix on Fedora, which is
>> available in the Fedora system repositories.
>
> Good correction, you're right, and it's an important one. Nix runs anywhere
> the package manager is installed; it doesn't require NixOS. I'll fix that
> wording in the commit-message/docs framing rather than the code, since the
> flake itself is already OS-agnostic and useful in all these locations. As
> it happens I use Nix on Fedora on one host, Nix on BSD on another, NixOS
> on a separate host and I'm also working to Nix-ify Illumos [1].
>
>>> Flip any single feature (26 toggles) without a preset:
>>> nix build --expr '(builtins.getFlake (toString ./.)).packages...'
>>
>> I didn't know that this was a thing. What a mouthful!
>
> Agreed, it is. It's the escape hatch, not the ergonomic path, most people
> will want a preset or their own thin wrapper flake with `.override { ... }`.
> I included it only to show the full toggle surface is reachable without
> editing the file.
>
> I'm also sure there are ways to add simplified common config into the flake
> but I was starting off with something very bland/effective and hopefully
> not overly opinionated to gain buy-in.
>
>> I think this will also have side benefits of making things easier to
>> test. For instance, we could start inlining buildfarm client members
>> configurations as derivations in this repository. [...] Additionally, I
>> wonder if NixOS VM tests could expose new ways to do automated testing of
>> Postgres.
>
> Both are appealing, and I think they're the real long-term payoff, a
> derivation library of animal configs under version control, and NixOS VM
> tests for things that are painful to exercise otherwise (replication
> topologies, systemd integration, upgrade paths). I'd like to keep v1 to just
> the flake so it's easy to review and agree on, then build those out as
> separate patches on top. Happy to collaborate!
More just throwing ideas into the ether of what this could enable.
Definitely not recommending it for a v1, but given the discussion in the
other subthread, maybe showing an example of what we could do in a NixOS
VM test that we currently don't do in our current setup could be
appealing to show people a benefit.
>> Regarding the code, can you explain the reasoning for the packages list
>> in the development shell? It seems like everything in the list is
>> already included by the Postgres package.
>
> You're right, and thank you, that list was mostly redundant. `inputsFrom =
> [ postgresql ]` already pulls in the package's nativeBuildInputs and
> buildInputs, so meson, ninja, bison, flex, perl, python3, tcl, and libxslt
> were all being listed twice. I've trimmed the devShell down to only what the
> package does *not* provide:
>
> - ccache (a dev convenience, not a build input), and
> - docbook_xml_dtd_45 + docbook-xsl-nons (the DocBook toolchain, since docs
> are off in the default package build, so `nix develop` can build docs
> without a separate override).
>
> Verified the trimmed shell still exposes meson/ninja/perl/python3/tcl/libxslt
> via inputsFrom, so nothing was actually lost. Will include that in v2.
For what it's worth, the docs targets on Meson, at least, are not built
by default, so adding enabling the docs feature by default seems fine to
me. Then it would just be ccache left in the devShell.
> Thanks again for the careful read.
--
Tristan Partin
PostgreSQL Contributors Team
AWS (https://aws.amazon.com)
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-08-31 04:57 Greg Burd <greg@burd.me>
parent: Tristan Partin <tristan@partin.io>
0 siblings, 0 replies; 14+ messages in thread
From: Greg Burd @ 2026-08-31 04:57 UTC (permalink / raw)
To: Peter Eisentraut <peter@eisentraut.org>; +Cc: PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>; Tristan Partin <tristan@partin.io>
On Tue Aug 26, 2026 at 1:28 PM CDT, Peter Eisentraut wrote:
> I don't know. Over time, people made similar arguments about Homebrew,
> Docker, and there will be more after this. People who are interested in
> this can band together and maintain it among themselves.
The Homebrew/Docker comparison is fair, those didn't go in-tree and so
perhaps this shouldn't either.
> A Nix configuration is probably of interest to on the order of 1% of
> developers, whereas these other things are relevant to most developers,
> and also importantly, changes can be verified easily by anyone, without
> having to learn about some new platform or tool.
I don't have numbers, and 1% is as plausible as anything I could claim.
Also, the comparison with .editorconfig/CI wasn't fair, that file is
near-universal and this isn't.
The second half is the argument I take most seriously, and I think it's the
real crux: a committer without Nix installed can't verify or fix a change to
flake.nix, so it's a file most of the tree's maintainers can't touch.
It puts the burden squarely on the people who want this to actually show
up, and it means the tree would be carrying something its own committers
can't independently check.
So, let's let the thread decide. If more Nix-using contributors don't
materialize I'm content to manage it out-of-tree.
Separately, and regardless of where this ends up: Tristan, thanks, I took
your docs suggestion. Since the Meson docs targets aren't built by default,
I've enabled the docs feature by default, which brings the DocBook toolchain
into the dev shell via the package itself and leaves just ccache in the
shell's own list. v5 attached.
best.
-greg
Attachments:
[text/x-patch] v5-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch (14.1K, ../../abc0fd2f-8b19-44b2-bb20-6274c84f1bfb@app.fastmail.com/2-v5-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patch)
download | inline diff:
From 5d06ddc2ab06034a1bf5dc7ef8a67eddb3c3b3e0 Mon Sep 17 00:00:00 2001
From: Greg Burd <greg@burd.me>
Date: Tue, 25 Aug 2026 15:34:06 -0400
Subject: [PATCH v5] 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 | 285 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 285 insertions(+)
create mode 100644 flake.nix
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 00000000000..3a97c39149b
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,285 @@
+# 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). Enabled by
+ # default; the docs targets are not part of the default build
+ # (only of `world`/`install-world`), so this adds the toolchain
+ # to the environment without slowing down a plain `nix build`.
+ docs ? true,
+ }:
+ 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, the
+ # optional libraries, and, since docs are on by default, the DocBook
+ # toolchain) via inputsFrom. We add only ccache on top.
+ devShells = forAllSystems (pkgs: {
+ default = pkgs.mkShell {
+ inputsFrom = [ self.packages.${pkgs.stdenv.hostPlatform.system}.postgresql ];
+ packages = [ pkgs.ccache ];
+ };
+ });
+
+ formatter = forAllSystems (pkgs: pkgs.nixfmt);
+ };
+}
--
2.54.0
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-09-20 11:42 Wolfgang Walther <walther@technowledgy.de>
parent: Greg Burd <greg@burd.me>
3 siblings, 0 replies; 14+ messages in thread
From: Wolfgang Walther @ 2026-09-20 11:42 UTC (permalink / raw)
To: Greg Burd <greg@burd.me>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
Greg Burd:
> A flake is a small, declarative
> manifest that tells Nix how to fetch our build dependencies and drop a
> developer into a shell where ./configure && make or meson setup just
> works, with bison, flex, perl, the optional libraries, and the docs
> toolchain all present and pinned to compatible versions. nix develop gives
> you that shell; nix build produces a server.
From the perspective of a Nixpkgs maintainer of PostgreSQL, having a
flake.nix in the repo does not make a difference for me. It does not
make it easier (or harder) to build PostgreSQL with it for me.
IMHO, the real value is in providing a developer shell - and you don't
need to be an everyday Nix user to benefit from it. Far from it, in fact
- you could install Nix *just* for the purpose of entering developer
shells for PostgreSQL development and not bother with it otherwise.
That's how I used Nix for years for PostgREST development initially.
I see roughly three target audiences for this:
1) Developers running NixOS. You essentially *need* a development shell
on that OS, because nothing is available globally by default.
2) New contributors, who don't want to go through setting up a
development environment from scratch for their first patch or review.
Starting a nix development shell is one command away - and no traces
left on the system afterwards.
3) Existing contributors, who need to deal with *different* sets of
dependencies. For example, I remember discussions around which minimal
versions of dependencies PostgreSQL should / will support - but how are
you going to test this as a contributor without installing either older
OS versions or keep a lot of versions for different dependencies around?
A nix flake would allow you to provide *multiple* different development
shells. One of them could be pinned to older dependencies, allowing you
to test all the minimally supported versions at once. Another one could
use the very latest dependencies of each - independent from what is
installed on the OS at the time.
> One deliberate omission: there is no flake.lock. A lock file pins the exact
> nixpkgs revision, which is the right call for an application that wants a
> frozen environment, but wrong for us. We don't want to freeze contributors to
> one snapshot of the dependency universe, and we don't want a lock file to
> become one more thing that goes stale in the tree and needs bumping. Leaving
> it out means the flake tracks whatever nixpkgs the developer already runs,
> which is exactly the behavior a build-from-source developer wants. Anyone who
> needs reproducibility can generate a lock locally; the tree stays clean.
I can see why you wouldn't want to update the lock file all the time -
but I'm afraid "the flake tracks whatever nixpkgs the developer already
runs" is not correct. Instead what happens when you run commands in this
case:
a) Nix will create a new .lock file for you, unless you pass
--no-write-lock-file.
b) No matter whether the new lock file is written or not, Nix will still
resolve the inputs the same way, i.e. taking the latest commit on
whichever channel / branch you specified in your inputs, when there is
no .lock file, yet.
In a way, this is worse: By default Nix will write a .lock file for you,
but once you .gitignore it, it won't be tracked and will be mostly
invisible. After a while the .lock file will be heavily outdated, but
you won't be aware of it.
And of course, it will break eventually, because the flake.nix file is
still written with certain assumptions, for example package names.
I'm not using flakes myself too much, so maybe I'm missing something,
though.
> Feedback welcome.
I'd suggest to approach this differently: Develop the flake in a
separate repository. Provide multiple different development shells to
choose from. Maybe a "quick start" one, one for latest deps, one for
oldest deps, possibly a shell that sets up various other tooling that is
helpful for development.
Then provide a nice readme in that repo, which allows non-Nix-users to
quickly set up Nix and use those development shells without needing to
dive into Nix itself.
The separate repo can carry a .lock file and update it regularly. It can
also move much faster initially. You can easily use these development
shells even on back branches.
Once this turns out helpful for other, previously non-Nix-using
contributors, re-evaluate whether it'd be useful to add to the main
repository.
Best,
Wolfgang
^ permalink raw reply [nested|flat] 14+ messages in thread
* Re: Add a Nix flake
@ 2026-09-20 12:06 Álvaro Herrera <alvherre@kurilemu.de>
parent: Andrew Dunstan <andrew@dunslane.net>
1 sibling, 0 replies; 14+ messages in thread
From: Álvaro Herrera @ 2026-09-20 12:06 UTC (permalink / raw)
To: Andrew Dunstan <andrew@dunslane.net>; +Cc: Greg Burd <greg@burd.me>; PostgreSQL Hackers <pgsql-hackers@lists.postgresql.org>
On 2026-Aug-25, Andrew Dunstan wrote:
> Well, "growing" could cover a multitude of possibilities. It could mean
> there was one and now there are two. Maybe there are lots out there and I at
> least just haven't heard of it. 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.
For what it's worth, I think a descriptive/declarative mechanism for
configuring buildfarm animals would beat the current Perl-code-based
system hands down. For instance, if I want to switch an animal from
Configure to Meson, I have to essentially redo the whole config from
scratch, which is rather a mess. I'd much rather state which features I
want to be used, and then have an intermediate layer figure out which
command line options must be used.
Maybe a Nix flake system would enable something like that without too
much development effort.
--
Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/
"I'm impressed how quickly you are fixing this obscure issue. I came from
MS SQL and it would be hard for me to put into words how much of a better job
you all are doing on [PostgreSQL]."
Steve Midgley, http://archives.postgresql.org/pgsql-sql/2008-08/msg00000.php
^ permalink raw reply [nested|flat] 14+ messages in thread
end of thread, other threads:[~2026-09-20 12:06 UTC | newest]
Thread overview: 14+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-08-24 16:58 Add a Nix flake Greg Burd <greg@burd.me>
2026-08-24 19:39 ` Tristan Partin <tristan@partin.io>
2026-08-25 09:49 ` Greg Burd <greg@burd.me>
2026-08-26 19:36 ` Tristan Partin <tristan@partin.io>
2026-08-31 04:57 ` Greg Burd <greg@burd.me>
2026-08-25 11:37 ` Andrew Dunstan <andrew@dunslane.net>
2026-08-25 13:19 ` Tom Lane <tgl@sss.pgh.pa.us>
2026-08-26 05:33 ` Greg Burd <greg@burd.me>
2026-08-26 05:45 ` Tom Lane <tgl@sss.pgh.pa.us>
2026-08-26 08:51 ` Daniel Gustafsson <daniel@yesql.se>
2026-08-26 16:56 ` Greg Burd <greg@burd.me>
2026-09-20 12:06 ` Álvaro Herrera <alvherre@kurilemu.de>
2026-08-26 18:28 ` Peter Eisentraut <peter@eisentraut.org>
2026-09-20 11:42 ` Wolfgang Walther <walther@technowledgy.de>
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox