kammer/NIX_BUILD.md
Christopher Mühl 9141363e87 docs: add Nix build system documentation
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-27 00:00:44 +01:00

2.7 KiB

Nix Build System

SolidHaus uses Nix flakes for reproducible builds and automated OCI image creation.

Quick Start

# Build the SvelteKit app
nix build .#solidhaus

# Build the OCI image
nix build .#solidhaus-image

# Push to registry (requires authentication)
nix run .#push-solidhaus-image

# Enter dev shell
nix develop

Packages

solidhaus

Builds the SvelteKit application using buildNpmPackage.

  • Output: Static SPA in /nix/store/.../
  • Build command: npm run build
  • Dependencies: Locked with npmDepsHash

solidhaus-image

OCI image with nginx serving the built app.

  • Image name: registry.toph.so/solidhaus
  • Tag: latest
  • Web server: nginx
  • Port: 80

Features:

  • SPA fallback routing (try_files $uri /index.html)
  • Gzip compression for text assets
  • Security headers (X-Frame-Options, X-Content-Type-Options, X-XSS-Protection)
  • 1-year cache for static assets (.js, .css, .woff2, etc.)

CI/CD

Forgejo Actions workflow (.forgejo/workflows/build-image.yml) automatically:

  1. On every push/PR: Build OCI image to verify it works
  2. On main branch: Push image to registry.toph.so/solidhaus
    • Tagged as :latest
    • Tagged with :${commit-sha} for rollback capability

Requirements:

  • Forgejo runner with nix label
  • Uses registry.toph.so/nix-runner:latest (see /srv/infra/jobs/forgejo-runner/image.nix)

Updating Dependencies

When package.json dependencies change:

  1. Build will fail with hash mismatch
  2. Copy the "got:" hash from error message
  3. Update npmDepsHash in flake.nix
  4. Rebuild

Example:

error: hash mismatch in fixed-output derivation
         specified: sha256-AAAAA...
            got:    sha256-BBBBB...

Update flake.nix:

npmDepsHash = "sha256-BBBBB...";

Local Testing

Test the OCI image locally:

# Build image
nix build .#solidhaus-image

# Load into Docker/Podman
docker load < result

# Run
docker run -p 8080:80 registry.toph.so/solidhaus:latest

# Visit http://localhost:8080

Integration with /srv/infra

The Nomad job definition in /srv/infra/jobs/solidhaus/default.nix can be updated to use the OCI image:

task.web = {
  driver = "docker";
  config = {
    image = "registry.toph.so/solidhaus:latest";
    ports = ["http"];
  };
  # ... rest of config
};

This replaces the current two-task setup (build + web) with a single pre-built image.

Why Nix?

  • Reproducible builds: Same inputs = same outputs, always
  • Hermetic builds: No reliance on system Node.js version
  • Cacheable: Nix store enables efficient caching
  • Declarative: Build configuration is code
  • Flake-based: Pin exact dependency versions (flake.lock)