Shipfox
Shipfox Caching

Nix

Cache Nix store paths with Shipfox's colocated binary cache, reducing derivation build times across CI runs

Nix is a purely functional package manager and build system. Its binary cache stores built derivations (store paths) so that any machine with access to the cache can download pre-built outputs instead of rebuilding them from source.

Shipfox provides a built-in Nix binary cache on every runner at $SHIPFOX_NIX_URL. Store paths are uploaded and fetched over the local network, making cache operations much faster than reaching a public cache server.

How it works

When a Nix derivation is built, its output is stored in the Nix store under a content-addressed path. Shipfox's cache server implements the Nix binary cache protocol, which means any nix-build, nix build, or store realisation can pull pre-built paths from it and upload new ones after building.

In automatic mode, Shipfox configures the cache as an extra substituter and installs a post-build hook that uploads newly built store paths. This works whether Nix is pre-installed on the runner image or installed during the job.

Automatic setup

Automatic Nix cache setup depends on whether Nix is already installed on the runner when the job starts:

When Nix is installed during the job (e.g. via DeterminateSystems/nix-installer-action or nixbuild/nix-quick-install-action), Shipfox pre-sets the NIX_CONFIG environment variable. Nix installers read this variable and apply the settings automatically:

extra-substituters = <shipfox-cache-url>
extra-trusted-substituters = <shipfox-cache-url>
require-sigs = false
post-build-hook = /tmp/shipfox-nix-upload.sh

When Nix is already installed on the runner image, Shipfox appends the same settings to /etc/nix/nix.conf and installs the upload hook at /etc/nix/upload-to-shipfox-cache.sh.

In both cases, no workflow changes are required:

- name: Install Nix
  uses: DeterminateSystems/nix-installer-action@v21

- name: Build
  run: nix build .#my-package

- name: Run tests
  run: nix develop --command make test

Automatic caching is enabled by default. You can disable it per tool from your Organization Settings in the Shipfox dashboard if you prefer to manage the configuration yourself.

Manual setup

If you want full control over the Nix cache configuration, use the $SHIPFOX_NIX_URL environment variable exposed on every runner.

Fetch from cache: set the substituter so Nix downloads pre-built paths before building:

- name: Install Nix
  uses: DeterminateSystems/nix-installer-action@v21
  with:
    extra-conf: |
      extra-substituters = ${{ env.SHIPFOX_NIX_URL }}
      extra-trusted-substituters = ${{ env.SHIPFOX_NIX_URL }}
      require-sigs = false

- name: Build
  run: nix build .#my-package

Push to cache: upload a store path after building:

- name: Build
  run: |
    STORE_PATH=$(nix build .#my-package --no-link --print-out-paths)
    nix copy --to "$SHIPFOX_NIX_URL" "$STORE_PATH"

Full round-trip example: build, push, then verify by fetching from cache:

- name: Build and cache
  run: |
    STORE_PATH=$(nix-build --no-out-link default.nix)
    nix copy --to "$SHIPFOX_NIX_URL" "$STORE_PATH"
    echo "STORE_PATH=$STORE_PATH" >> "$GITHUB_ENV"

- name: Fetch from cache
  run: nix copy --from "$SHIPFOX_NIX_URL" --no-check-sigs "$STORE_PATH"

require-sigs = false is required because Shipfox's cache does not sign store paths. If you manage your own signing keys, you can omit this and configure signing separately.