Add a Nix flake

Started by Greg Burd1 day ago5 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

appliessuccessCI history

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t253533
psql -h localhost -U postgres

Built from patchset v3 (message #3), August 25, 2026 at 10:06 AM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t253533_3 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t253533_3 && git checkout t253533_3

Patchset v3 (message #3) is on t253533_3

Jump to latest
#1Greg Burd
greg@burd.me

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:

t253533_1
v1-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patchtext/x-patch; name="=?UTF-8?Q?v1-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patc?= =?UTF-8?Q?h?="Download+261-1
#2Tristan Partin
tristan@partin.io
In reply to: Greg Burd (#1)
Re: Add a Nix flake

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)

#3Greg Burd
greg@burd.me
In reply to: Tristan Partin (#2)
Re: Add a Nix flake

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:

t253533_3
v2-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patchtext/x-patch; name="=?UTF-8?Q?v2-0001-Add-a-Nix-flake-for-reproducible-builds-and-dev-s.patc?= =?UTF-8?Q?h?="Download+262-1
#4Andrew Dunstan
andrew@dunslane.net
In reply to: Greg Burd (#1)
Re: Add a Nix flake

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

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andrew Dunstan (#4)
Re: Add a Nix flake

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