NixOSSurrealDBInfrastructure
Mar 18, 2026

Installing SurrealDB on NixOS Is a Character-Building Exercise

The nixpkgs build takes forever and lags behind. Here is how to grab the prebuilt binary and make it work with an FHS wrapper.

D
Darius
darius.codes
3 min read

SurrealDB is the right database for the projects I build. Multi-model, schemaful when you want it, graph traversal without a separate graph DB, and a query language that doesn’t make you feel like you’re filling out tax forms.

Installing it on NixOS? That’s where it gets interesting.

There is a SurrealDB package in nixpkgs, and it works. But it builds from source — a full Rust compile that takes forever, stuck on whatever version nixpkgs happens to have packaged, pulling in the entire build toolchain when all you actually need is the binary. After getting annoyed by the build times one too many times, I wrote my own module.

The Problem

SurrealDB ships prebuilt Linux binaries. On a normal distro, you download, chmod +x, run. On NixOS, you immediately get:

terminalbash
$ ./surreal start
/nix/store/.../surreal: error while loading shared libraries:
  libz.so.1: cannot open shared object file: No such file or directory

The binary was compiled assuming a standard FHS filesystem — /lib, /usr/lib, the usual suspects. NixOS doesn’t have those paths. Libraries live at content-addressed paths in the Nix store, and the dynamic linker has no idea where to look.

The official install script doesn’t help either:

terminalbash
$ curl -sSf https://install.surrealdb.com | sh

It tries to drop the binary into /usr/local/bin or $HOME/.surrealdb and expects the system to have a standard library layout. Neither assumption holds on NixOS.

§

The Download URL

The install script is still useful though — not to run, but to read. If you inspect it:

terminalbash
$ curl -sSf https://install.surrealdb.com

You’ll find it constructs the download URL from a version, OS, and architecture:

https://download.surrealdb.com/v{VERSION}/surreal-v{VERSION}.linux-amd64.tgz

That’s the direct URL we need for pkgs.fetchurl. No need to reverse-engineer anything — the script hands it to you.

§

The FHS Wrapper

NixOS provides buildFHSEnv for exactly this scenario. It constructs a minimal chroot with standard library paths, links in the packages you specify, and gives the binary a filesystem it can actually navigate.

Here’s the full module:

surrealdb-fhs.nixnix
{ pkgs, ... }:

let
  surrealdb-bin = pkgs.fetchurl {
    url = "https://download.surrealdb.com/v3.0.3/surreal-v3.0.3.linux-amd64.tgz";
    hash = "sha256-A0jGLd5ld5YmzjqoCIp/hyRJrgbPW743WcwQxfORtwE=";
  };

  surrealdb-unpacked = pkgs.runCommand "surrealdb-unpack" {} ''
    mkdir -p $out/bin
    tar -xzf ${surrealdb-bin} -C $out/bin
    chmod +x $out/bin/surreal
  '';

  surrealdb-fhs = pkgs.buildFHSEnv {
    name = "surreal";
    targetPkgs = pkgs: with pkgs; [ openssl libgcc glibc ];
    runScript = "${surrealdb-unpacked}/bin/surreal";
  };
in {
  environment.systemPackages = [ surrealdb-fhs ];
}

That’s it. fetchurl grabs the tarball. runCommand unpacks it. buildFHSEnv wraps it in a chroot where the library lookups succeed. The binary is none the wiser.

Note
To update to a new version, change the version in the URL and the hash. You can get the new hash by running nix-prefetch-url --unpack with the new URL, or just set a dummy hash and let the build error tell you the correct one.
§

Wire It In

Import the module in your NixOS configuration:

configuration.nixnix
{
  pkgs,
  ...
}:
{
  imports = [
    ./surrealdb-fhs.nix
  ];
}

Or if you’re using flakes:

flake.nixnix
{
  description = "NixOS configuration with flakes";

  outputs = { self, nixpkgs, ... }: {
    nixosConfigurations.your-hostname = nixpkgs.lib.nixosSystem {
      modules = [
        ./configuration.nix
        ./surrealdb-fhs.nix
      ];
    };
  };
}

Then nixos-rebuild switch and you’re done. surreal is on your PATH.

No source builds, no waiting for nixpkgs to catch up, no bloat. Change two lines when a new version drops and rebuild.

ende