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:
$ ./surreal start
/nix/store/.../surreal: error while loading shared libraries:
libz.so.1: cannot open shared object file: No such file or directoryThe 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:
$ curl -sSf https://install.surrealdb.com | shIt 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:
$ curl -sSf https://install.surrealdb.comYou’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:
{ 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.
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:
{
pkgs,
...
}:
{
imports = [
./surrealdb-fhs.nix
];
}Or if you’re using flakes:
{
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.