# Nix Flakes Verification Checklist This document provides a comprehensive checklist for verifying the Nix flakes integration. ## Prerequisites - [ ] Nix installed with flakes enabled - [ ] direnv installed (optional) - [ ] Docker installed (for image testing) - [ ] Cachix account created (for binary caching) ## Phase 1: Core Flake Setup ### Verify flake.nix - [ ] `nix flake check` passes without errors - [ ] `nix flake show` displays all packages and devShells - [ ] `nix flake metadata` shows correct inputs ```bash cd towerops-web nix flake check nix flake show nix flake metadata ``` **Expected output:** ``` packages ├── aarch64-darwin │ ├── dockerImage │ ├── default: package 'towerops-0.1.0' │ ├── towerops: package 'towerops-0.1.0' │ └── towerops-nif: package 'towerops-nif-0.1.0' └── x86_64-linux ├── dockerImage ├── default: package 'towerops-0.1.0' ├── towerops: package 'towerops-0.1.0' └── towerops-nif: package 'towerops-nif-0.1.0' ``` ## Phase 2: C NIF Build ### Build C NIF - [ ] `nix build .#towerops-nif` completes successfully - [ ] Output binary exists at `result/lib/towerops_nif.so` - [ ] Binary links against libnetsnmp ```bash nix build .#towerops-nif ls -lh result/lib/towerops_nif.so ldd result/lib/towerops_nif.so | grep netsnmp ``` **Expected output:** ``` -rwxr-xr-x 1 user group 50K Feb 7 12:00 result/lib/towerops_nif.so libnetsnmp.so.40 => /nix/store/.../lib/libnetsnmp.so.40 ``` ### Verify NIF Functionality - [ ] NIF loads without errors - [ ] Can call MIB resolution functions ```bash nix develop iex -S mix # In IEx: ToweropsNative.load_mib_directory("priv/mibs") # Should return: {:ok, _} or {:error, :already_initialized} ``` ## Phase 3: Mix Release Build ### Build Elixir Release - [ ] `nix build .#towerops` completes successfully - [ ] Release binary exists at `result/bin/towerops` - [ ] Release contains MIB files - [ ] Release contains vendored Oban packages ```bash nix build .#towerops ls -lh result/bin/towerops find result -name "*.mib" | head -5 find result -name "oban_*" -type d ``` **Expected output:** ``` -rwxr-xr-x 1 user group 10K result/bin/towerops result/lib/towerops-0.1.0/priv/mibs/SNMPv2-MIB.mib result/lib/towerops-0.1.0/priv/mibs/IF-MIB.mib ... result/lib/oban_pro-1.6.0 result/lib/oban_web-2.11.0 result/lib/oban_met-1.0.0 ``` ### Test Release Execution - [ ] Release starts without errors - [ ] RPC commands work - [ ] MIB directory is accessible ```bash # Test RPC ./result/bin/towerops rpc "1 + 1" # Expected: 2 # Test MIB loading (requires database connection) # Set up DATABASE_URL, SECRET_KEY_BASE, etc. first export DATABASE_URL="ecto://user@localhost/towerops_dev" export SECRET_KEY_BASE="test_secret_key_base_at_least_64_bytes_long_for_phoenix" export CLOAK_KEY="test_cloak_key_base64_32bytes=" ./result/bin/towerops eval "Application.ensure_all_started(:towerops)" ``` ## Phase 4: Docker Image Build ### Build Docker Image - [ ] `nix build .#dockerImage` completes successfully - [ ] Image size is < 250 MB (target: 150-200 MB) - [ ] Image loads into Docker successfully ```bash nix build .#dockerImage nix path-info -S .#dockerImage docker load < result docker images | grep towerops ``` **Expected output:** ``` /nix/store/...-docker-image-towerops-latest.tar.gz 180.5 MiB registry.gitlab.com/towerops/towerops latest abc123def456 190MB ``` ### Verify Image Contents - [ ] Image contains towerops release - [ ] Image contains net-snmp runtime - [ ] Image contains MIB files - [ ] Image runs as non-root user ```bash # Check contents docker run --rm registry.gitlab.com/towerops/towerops:latest ls -la / # Check user docker run --rm registry.gitlab.com/towerops/towerops:latest id # Expected: uid=65534(nobody) gid=65534(nobody) # Check MIB files docker run --rm registry.gitlab.com/towerops/towerops:latest \ find / -name "*.mib" 2>/dev/null | head -5 # Check snmptranslate docker run --rm registry.gitlab.com/towerops/towerops:latest which snmptranslate ``` ### Test Image Execution - [ ] Image starts with healthcheck passing - [ ] Phoenix server responds on port 4000 - [ ] RPC commands work inside container ```bash # Start container (requires database) docker run --rm -p 4000:4000 \ -e DATABASE_URL="ecto://user@host.docker.internal/towerops_dev" \ -e SECRET_KEY_BASE="test_secret_key_base_at_least_64_bytes_long" \ -e CLOAK_KEY="test_cloak_key_base64_32bytes=" \ -e PHX_HOST="localhost" \ registry.gitlab.com/towerops/towerops:latest # Test healthcheck (in another terminal) docker ps --filter "name=towerops" --format "{{.Status}}" # Should show "healthy" after ~30 seconds # Test RPC docker exec /nix/store/.../bin/towerops rpc "1 + 1" ``` ## Phase 5: Development Shell ### Enter Development Shell - [ ] `nix develop` completes successfully - [ ] PostgreSQL auto-starts - [ ] Redis auto-starts - [ ] Databases are created - [ ] Welcome message displays ```bash nix develop # Should auto-start services and show welcome message ``` **Expected output:** ``` 🚀 Starting development services... 📦 Initializing PostgreSQL database... 🐘 Starting PostgreSQL on port 5432... ✓ PostgreSQL started successfully 📮 Starting Redis on port 6379... ✓ Redis started successfully ✨ Development environment ready! ╔═══════════════════════════════════════════════════════════╗ ║ ║ ║ Towerops Development Environment ║ ║ ║ ╚═══════════════════════════════════════════════════════════╝ ``` ### Verify Services - [ ] PostgreSQL responds to connections - [ ] Redis responds to PING - [ ] Databases exist - [ ] TimescaleDB extension available (optional) ```bash # In Nix shell pg_isready -h localhost -p 5432 # Expected: localhost:5432 - accepting connections redis-cli ping # Expected: PONG psql -U $USER -h localhost -p 5432 -l | grep towerops # Expected: towerops_dev, towerops_test psql -U $USER -h localhost -p 5432 -d towerops_dev -c "SELECT * FROM pg_extension WHERE extname = 'timescaledb';" # Expected: 1 row if TimescaleDB available, 0 rows if not (ok for dev) ``` ### Test Mix Commands - [ ] `mix deps.get` works - [ ] `mix compile` works - [ ] `mix ecto.migrate` works - [ ] `mix phx.server` starts - [ ] `mix test` runs ```bash mix deps.get mix compile mix ecto.migrate mix phx.server & sleep 5 curl http://localhost:4000 kill %1 # Stop Phoenix mix test --only quick || mix test | head -50 ``` ### Verify Pre-commit Hooks - [ ] Pre-commit hooks are installed - [ ] `mix format` hook works - [ ] `credo` hook works - [ ] `nixfmt` hook works ```bash # Make a formatting violation echo "defmodule Foo do end" >> lib/foo.ex git add lib/foo.ex git commit -m "test" # Should fail with formatting error # Fix and retry mix format git add lib/foo.ex git commit -m "test" # Should pass or fail on other hooks # Clean up git reset HEAD~1 rm lib/foo.ex ``` ## Phase 6: direnv Integration ### Configure direnv - [ ] `.envrc.example` exists - [ ] Can copy to `.envrc` - [ ] direnv loads environment automatically ```bash cp .envrc.example .envrc direnv allow cd .. cd towerops-web # Should auto-load environment and start services echo $MIX_ENV # Expected: dev which mix # Expected: /nix/store/.../bin/mix ``` ### Verify Environment Variables - [ ] `DATABASE_URL` is set - [ ] `REDIS_URL` is set - [ ] `MIX_ENV` is set to `dev` - [ ] `SECRET_KEY_BASE` is set ```bash echo $DATABASE_URL echo $REDIS_URL echo $MIX_ENV echo $SECRET_KEY_BASE | head -c 32 ``` ## Phase 7: Legacy Compatibility ### Test shell.nix Compatibility - [ ] `nix-shell` works (without flakes) - [ ] Environment is identical to `nix develop` ```bash nix-shell # Should enter same environment as `nix develop` echo $MIX_ENV which mix exit ``` ## Phase 8: Cachix Integration ### Set Up Cachix - [ ] Cachix account created - [ ] Cache created: `cachix create towerops` - [ ] Keypair generated - [ ] Public key added to `flake.nix` ```bash cachix create towerops cachix generate-keypair towerops cachix get towerops # Copy public key to flake.nix ``` ### Test Local Cachix Push - [ ] Can push builds to cache - [ ] Can pull builds from cache ```bash # Push build to cache nix build .#dockerImage nix path-info --json .#dockerImage | jq -r '.[].path' | cachix push towerops # Verify push cachix info towerops # Should show recent push # Clean local store nix-collect-garbage -d # Rebuild (should pull from cache) time nix build .#dockerImage # Should be much faster (seconds vs minutes) ``` ### Configure GitLab CI - [ ] `CACHIX_AUTH_TOKEN` added to GitLab variables - [ ] `.gitlab-ci.yml.nix` updated with correct public key - [ ] Ready to activate Nix CI ```bash # Get auth token cachix authtoken # Add to GitLab: Settings → CI/CD → Variables # Verify .gitlab-ci.yml.nix has correct key grep "towerops.cachix.org-1:" .gitlab-ci.yml.nix ``` ## Phase 9: Documentation ### Verify Documentation - [ ] `docs/nix.md` exists and is comprehensive - [ ] `docs/README-nix-section.md` created for README update - [ ] `docs/CLAUDE-nix-section.md` created for CLAUDE.md update - [ ] All code examples in docs are accurate ```bash ls -lh docs/nix.md docs/README-nix-section.md docs/CLAUDE-nix-section.md # Test commands from docs # (Run through "Quick Start" section) ``` ## Performance Benchmarks ### Measure Build Times - [ ] C NIF build time - [ ] Elixir release build time - [ ] Docker image build time - [ ] Total clean build time ```bash # Clean builds nix-collect-garbage -d time nix build .#towerops-nif # Target: < 1 minute time nix build .#towerops # Target: < 10 minutes (first build) time nix build .#dockerImage # Target: < 15 minutes (first build) # Cached rebuilds (after changing one Elixir file) echo "# comment" >> lib/towerops_web/router.ex time nix build .#towerops --rebuild # Target: < 5 minutes ``` ### Measure Image Size - [ ] Docker image size < 250 MB - [ ] Compare to previous Debian-based image ```bash nix path-info -S .#dockerImage docker images | grep towerops # Compare to old image (if available) # Target: ~50% reduction ``` ## Production Deployment Test ### Deploy to Staging/Production - [ ] Build image with Nix - [ ] Push to GitLab registry - [ ] Deploy to Kubernetes - [ ] Health checks pass - [ ] Application functionality verified ```bash # Build and tag nix build .#dockerImage docker load < result docker tag registry.gitlab.com/towerops/towerops:latest \ registry.gitlab.com/towerops/towerops:nix-test # Push to registry docker push registry.gitlab.com/towerops/towerops:nix-test # Deploy to staging (adjust namespace/deployment as needed) kubectl set image deployment/towerops \ towerops=registry.gitlab.com/towerops/towerops:nix-test \ -n towerops-staging # Verify deployment kubectl get pods -n towerops-staging kubectl logs -n towerops-staging deployment/towerops --tail=50 # Check health kubectl exec -n towerops-staging deployment/towerops -- \ /nix/store/.../bin/towerops rpc "1 + 1" ``` ## Success Criteria Summary All items below must pass: - [x] `nix flake check` passes - [ ] C NIF builds and links correctly - [ ] Mix release builds with assets and MIB files - [ ] Docker image builds and is < 250 MB - [ ] Development shell starts services automatically - [ ] direnv integration works seamlessly - [ ] Cachix push/pull works - [ ] Documentation is comprehensive - [ ] Production deployment succeeds ## Issues Tracker Document any issues encountered during verification: | Phase | Issue | Resolution | Status | |-------|-------|------------|--------| | Example | Error XYZ | Fixed by ABC | Resolved | | | | | | ## Final Sign-Off - [ ] All verification steps completed - [ ] All issues resolved or documented - [ ] Ready for production use - [ ] Team trained on Nix workflows **Verified by:** _______________ **Date:** _______________ **Nix version:** _______________ **Platform:** _______________