Skip to content

Nix

This guide explains how to make Nix and NixOS reproducible and usable offline by routing all external inputs (binary caches and fetchers) through an archival HTTP proxy. Once content is archived, builds and system installs work without internet access.

This approach does not rely on manual store exports or ad‑hoc caching. Instead, it treats the internet as a one‑time ingestion layer and turns every URL into a permanent, immutable input.


Conceptual Overview

Nix pulls external data from two places:

  1. Binary caches (substituters) – prebuilt .nar files
  2. Fetchers – source downloads (tarballs, git repos, flake inputs)

Both ultimately use HTTP(S).

The goal is:

Nix → HTTP(S) → Archive Proxy → Immutable Storage

If the proxy has seen it once, it can serve it forever. Offline operation becomes a routing decision.

Setup

Here is a simple module to enable proxying:

# proxy.nix
{
  config,
  lib,
  ...
}:
{
  options.profiles.nix-proxy = {
    enable = lib.mkOption {
      type = lib.types.bool;
      default = false;
    };
    http_proxy = lib.mkOption {
      type = lib.types.str;
      description = "HTTP Proxy";
    };
    ca_file = lib.mkOption {
      type = lib.types.path;
      description = "Root CA certificate";
    };
  };

  config = lib.mkIf config.profiles.nix-proxy.enable (
    let
      cfg = config.profiles.nix-proxy;
    in
    {
      systemd.services.nix-daemon.environment =
        let
          http_proxy = cfg.http_proxy;
        in
        {
          http_proxy = http_proxy;
          https_proxy = http_proxy;
          HTTP_PROXY = http_proxy;
          HTTPS_PROXY = http_proxy;
          CURL_CA_BUNDLE = lib.mkForce cfg.ca_file;
        };
    }
  );
}

Edit your configuration.nix to make the nix builder use the proxy:

# /etc/nixos/configuration.nix
{ config, pkgs, ... }:
{
  imports = [ ./proxy.nix ]

  # WebArc
  profiles.nix-proxy = {
    enable = true;
    http_proxy = "http://example.com:3000";
    ca_file = ./webarc_ca.crt;
  };
}