diff --git a/NIX_BUILD.md b/NIX_BUILD.md new file mode 100644 index 0000000..9645631 --- /dev/null +++ b/NIX_BUILD.md @@ -0,0 +1,120 @@ +# Nix Build System + +SolidHaus uses Nix flakes for reproducible builds and automated OCI image creation. + +## Quick Start + +```bash +# 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`: +```nix +npmDepsHash = "sha256-BBBBB..."; +``` + +## Local Testing + +Test the OCI image locally: + +```bash +# 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: + +```nix +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)