StackServicesCachix

Cachix

Last updated: Sep 23, 2026


Rationale

Cachix is the hosted binary cache we use for Nix. Every derivation a job builds is pushed to our private cache, and every later job that needs the same derivation downloads it instead of building it again.

The main reasons why we chose it over other alternatives are:

  • It is a hosted service built specifically for Nix. There is no cache server to operate, and the client is a single command that configures the cache and pushes new store paths as they appear.
  • It serves cryptographically signed store paths. Our machines trust only the public keys of the caches we configure, so a path that was not signed by one of them is never substituted.
  • It supports private caches with authentication tokens, letting us cache everything that is built in the monorepo without exposing it publicly.
  • It integrates with GitLab CI and with the Batch jobs that run Nix, because it only needs the Nix configuration that our job templates and container images already carry.
  • It works for both architectures our jobs run on, since a Nix store path is cached per system and our runners build on x86_64 and aarch64.
  • Flakes integrate with it easily, which is one of the reasons we chose Nix Flakes over other environment managers.

Alternatives

As our CI evolved, so did our interest in a cache that is closer to the runners. Below are the approaches we have reviewed, ordered from most to least interesting based on our specific needs.

Local Nix store on a persistent runner

  • Jobs would be split into a build stage that populates the local Nix store of a runner and an execution stage that reuses it, with the runner created on demand and kept alive for a while after going idle.
  • It would remove the round trip to a remote cache and reduce data transfer costs.
  • The cache would live only as long as the machine, so the first job after a cold start would build everything.
  • It requires separating build and execution, which today happen in the same job.

Pre-built container images per execution flow

  • Each flow would run from an image that already contains everything it needs, removing the need for a cache at all.
  • It fits production workloads such as Batch jobs, which already run from a purpose-built image.
  • For development jobs, the team considers it too expensive in terms of complexity and maintainability.

Usage

We use Cachix for:

  • Substituting the Nix derivations that every GitLab CI job needs, and pushing the ones each job builds, so no derivation is built twice across branches and runners.
  • Substituting the Nix derivations that our Batch jobs and their container image need.
  • Trusting the cache's public key in the Nix configuration of our CI container image, next to the public cache of the Nix project.

We do not use Cachix for:

On this page