Trying to use nix
From the series
Updating fasterthanli.me for 2022
Now that my website is deployed as a container image, I wanted to give
nix a try. I'm still doing it the old-fashioned way right
now: with a Dockerfile
, running cargo
in a "builder" image, copying stuff
out of there into a slimmer image (that still has an Ubuntu base, even though
distroless images are a
thing now).
But why?
I was mostly interested in nix because some parts of my website have pretty big
native dependencies. futile
itself mostly relies on sqlite3 and some JS engine
(used to be quickjs, currently duktape because MSVC Windows builds). But the
asset processing pipeline, salvage
(which I'd like to integrate with futile
at some point) has a bunch more!
Not only does it need Google Chrome headless for diagrams (which are made in the excellent diagrams.net desktop application), it then exports those to PDF, which are converted to SVG (baking text into paths, so you don't need to have my fonts installed locally to view/print them), and then optimized further. That requires poppler and cairo, which requires glib, gobject, gio, etc.
And then there's webp processing, avif processing, etc.
In fact I wrote a whole series about this, how I got everything to link statically (except Google Chrome, which is a standalone executable) on both Linux and Windows, that involved the Meson build system, etc.
Nowadays I don't care so much about the Windows part, everything runs in a Linux VM anyway, but I figured nix would let me simplify a lot of this — no matter which distribution I chose to use day-to-day, all the dependencies would be statically defined in a single place, I could even apply my own patches if I wanted (which I do for the video processing pipeline — to get ffmpeg and libsvtav1 to play nice with each other), and I could link dynamically against libraries, which might speed up the link step and trim down the final executable quite a bit.
Also, apparently you can generate Docker images with nix, which sounded great.
Success (but at what cost?) with crane
So I started learning nix! I learned there's quite a few ways to build Rust code with nix, a lot of folks use naersk, but after a couple tries, I gravitated towards crane instead.
A still-experimental but not-so-new thing in nix are "flakes", I figured I'd make
a flake to build futile
(starting small), and got as far as this:
{ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; crane = { # url = "github:ipetkov/crane"; url = "path:/home/amos/bearcove/crane"; inputs.nixpkgs.follows = "nixpkgs"; }; flake-utils.url = "github:numtide/flake-utils"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs = { nixpkgs.follows = "nixpkgs"; flake-utils.follows = "flake-utils"; }; }; }; outputs = { self, nixpkgs, crane, flake-utils, rust-overlay }: flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { system = system; overlays = [ (import rust-overlay) ]; }; rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; lib = crane.lib.${system}.overrideToolchain rustToolchain; shipyardToken = builtins.readFile ./secrets/shipyard-token; craneLib = lib.appendCrateRegistries [ (lib.registryFromDownloadUrl { dl = "https://crates.shipyard.rs/api/v1/crates"; indexUrl = "https://git.shipyard.rs/bearcove/crate-index.git"; curlOptsList = [ "-H" "user-agent: shipyard ${shipyardToken}" ]; }) ]; futile = craneLib.buildPackage { src = ./.; nativeBuildInputs = with pkgs; [ pkg-config protobuf clang_14 mold ]; installCargoArtifactsMode = "use-symlink"; }; in { packages.default = futile; }); }
Wait, did you add nix syntax highlighting to futile
just now for this?
...maybe? Most of the work was already done.
I have no idea if this is idiomatic, it's also complicated by the fact that I use a private crate registry, so I immediately had to go contribute to crane, and despite my best efforts, I still don't deem it usable for now.
Building and installing a futile
binary via nix still takes a long time, and
the main offender is... removing references to /nix/store
paths! There's a
long and interesting discussion
going on about it right now, I might even get a chance to sneak some Rust in
your Rust, but for now I've decided it's outside the scope of this article, and
we'll revisit this all later.
It's time to tackle the one thing I actually meant to do with this series, which is: adding GitHub login.
This article is part 5 of the Updating fasterthanli.me for 2022 series.
If you liked what you saw, please support my work!