Skip to content

RobertDeRose/nix-hex-box

Repository files navigation

HexBox

HexBox logo

nix-hex-box is a nix-darwin module that configures an Apple container machine backed aarch64-linux remote builder for Nix.

Documentation site:

Current design highlights:

  • installs Apple container from the official signed GitHub release package
  • pulls the published Alpine/Lix-based builder image by default, with an optional local custom image build
  • creates a persistent Apple container machine instead of an ephemeral container
  • configures nix.buildMachines for ssh-ng://container-builder
  • uses ProxyCommand to auto-start the machine and relay SSH to guest sshd
  • lets the macOS root nix-daemon sudo back to the runtime-owning user for the Apple container command
  • connects as the guest builder user and uses a narrow passwordless sudo wrapper for the remote nix-daemon
  • keeps the guest /nix store persistent across machine stops and starts
  • powers the guest off after a configurable idle timeout with no active SSH connections
  • manages durable host state under ~/.local/state/hb
  • can install and manage Socktainer as an optional Docker-compatible API layer
  • installs host-side SSH aliases for both nix-builder and container-builder
  • writes a generated known_hosts file under ~/.local/state/hb so SSH verifies the builder host key
  • exposes host.container.internal for Apple containers by default via container system dns
  • waits for a real SSH handshake before considering the builder ready

Module

The flake exports:

  • darwinModules.default
  • darwinModules.container-builder

The repo also contains a scheduled workflow that opens a Robborg-authored PR for pinned runtime-version updates, validates it, and auto-merges it after the lint workflow passes.

Example

{
  inputs.hexbox.url = "github:RobertDeRose/nix-hex-box";

  outputs = inputs: {
    darwinConfigurations.my-host = inputs.darwin.lib.darwinSystem {
      system = "aarch64-darwin";
      modules = [
        inputs.hexbox.darwinModules.default
        {
          services.container-builder = {
            enable = true;
            cpus = 4;
            memory = "8G";
            maxJobs = 4;
            socktainer.enable = true;
            # Optional override if you do not want to use config.system.primaryUser.
            user = "myuser";
          };
        }
      ];
    };
  };
}

Status

This module is functional but still in progress.

Known open areas:

  • evaluating a smaller systemd-based image once Apple container machine handles larger systemd images reliably

Runtime

The module uses the HexBox builder image published by this repository by default:

ghcr.io/robertderose/nix-hex-box/hexbox-builder:latest

The image contains Alpine 3.22, OpenSSH, sudo, and Lix. The module creates a persistent Apple container machine from that image and bootstraps the host-specific SSH keys, nix.conf, sudoers rule, and idle timeout.

GitHub Actions rebuilds and publishes latest on the same weekly schedule as the runtime-version updater so Alpine package updates, such as OpenSSH fixes, are available to new or recreated machines. When the configured machine image contract changes, HexBox recreates the builder machine automatically; this also deletes the guest-local store. Builder image publishing is skipped until the configured Lix tag is at least seven days old. When the image definition changes on main, the workflow also publishes the versioned release tag alpine-3.22-lix-2.95.2-2 for users who prefer to pin.

The builder uses ssh-ng. The host SSH path is a generated ProxyCommand that runs Apple container machine run --root -i ... socat STDIO TCP:127.0.0.1:<containerPort>, so the machine starts on demand, IP changes do not affect Nix, and the relay closes cleanly when SSH finishes. Custom imageContainerfile images must include socat, or builder bootstrap will fail the SSH proxy preflight.

The guest /nix store lives in the machine's persistent storage. Stop/start keeps build outputs and downloaded substitutes. hb builder reset deletes and recreates the machine, which also deletes the guest-local store.

Available image options:

  • services.container-builder.imageRepository
  • services.container-builder.nixVersion
  • services.container-builder.imageContainerfile
  • services.container-builder.imageBuildContext

Set imageContainerfile to build and use a local custom image instead of the published GHCR image. Set imageBuildContext to an absolute host path string when the custom image needs a build context. Custom images must provide socat, base64, getent, and a working /sbin/init, because HexBox bootstrap, machine boot, and the SSH proxy all use those entrypoints. Bump nixVersion or remove the local image when the Containerfile or context changes.

Available machine options:

  • services.container-builder.cpus
  • services.container-builder.memory
  • services.container-builder.homeMount
  • services.container-builder.idleShutdown.enable
  • services.container-builder.idleShutdown.timeoutSeconds

Available host/container integration options:

  • services.container-builder.exposeHostContainerInternal
  • services.container-builder.socktainer.enable
  • services.container-builder.socktainer.homeDirectory
  • services.container-builder.socktainer.binary
  • services.container-builder.socktainer.installer.url
  • services.container-builder.socktainer.installer.hash
  • services.container-builder.socktainer.installer.version

The builder machine writes a minimal nix.conf with https://cache.nixos.org/ configured as a substituter.

Example:

services.container-builder = {
  enable = true;
};

Socktainer

Set services.container-builder.socktainer.enable = true; to install the official Socktainer pkg and manage a user launch agent for the current primary user.

This exposes a Docker-compatible Unix socket at:

$HOME/.socktainer/container.sock

Example:

export DOCKER_HOST=unix://$HOME/.socktainer/container.sock
docker ps

Set services.container-builder.socktainer.setDockerHost = true; if you want the module to export that socket as DOCKER_HOST in the user environment.

Helper

After activation, use:

hb builder status
hb builder repair
hb builder test
hb builder ssh
hb builder logs boot
hb builder logs idle
hb doctor

hb builder repair ensures the Apple container system is healthy, builds a custom local OCI image when configured and missing, creates or updates the container machine, verifies SSH, checks outbound connectivity, and pings the remote store. If repair fails, follow the reported recovery step for the runtime, machine, or network failure that was detected. After repair succeeds, run hb builder test to verify remote build execution.

See docs/spec.md for the detailed design notes.

About

A Nix-Darwin linux builder using Apple Contiainers

Resources

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors