This file provides guidance to AI coding assistants (Claude Code, GitHub Copilot, Cursor, etc.) when working with code in this repository.
This is a NixOS configuration repository using flakes with categorized hosts for better organization and security. It manages system configurations for multiple hosts with modular, reusable components. Secrets are managed via sops-nix with GPG/age encryption. All hosts include Tailscale, hardened firewall, and port knocking for secure remote access.
All commands use justfile - run just --list to see available commands.
Hosts are organized into categories with different configurations:
-
laptops/: Full-featured workstations (bit, spark, hermes)
- Desktop environments, development tools, Docker
- Power management, Bluetooth, audio
-
vps/: Minimal, hardened cloud VPS instances
- Headless, kernel hardening, aggressive security
- Port knocking for SSH access
- Auto-updates, minimal package set
-
servers/: On-premises servers
- Docker support, monitoring (Prometheus)
- Headless but less restrictive than VPS
-
experiments/: Testing and development hosts
- Relaxed security, development tools
- Quick iteration, temporary configurations
- flake.nix: Defines all hosts using
mkHosthelper for DRY configuration - Each host imports its category config (e.g.,
hosts/categories/laptops.nix) - Category configs import base modules (common, networking, security)
- Hostnames are opaque - use Tailscale or SSH config aliases for addressing
- hosts/common/: Shared configuration (nix settings, locale, common packages)
- hosts/categories/: Category-specific configurations (laptops.nix, vps.nix, servers.nix, experiments.nix)
- hosts/{category}/{hostname}/: Individual host configurations
- modules/users/: Home Manager configurations (overridable per-host)
- modules/system/: System-level modules (security)
- modules/networking/: Networking modules (tailscale, firewall, port knocking)
- packages/: Custom package definitions
- overlays/: Nixpkgs overlays
All hosts include:
- Tailscale: Zero-trust mesh VPN for secure access
- Hardened firewall: Only SSH allowed, protected by port knocking on VPS
- Port knocking: VPS hosts require knock sequence (encrypted in sops)
- SSH hardening: Key-only auth, rate limiting, fail2ban
- SOPS: GPG + age encryption for secrets
All commands use justfile. See docs/JUSTFILE_COMMANDS.md for complete reference.
# Enter development shell with all tools (deploy-rs, sops, knockd, etc.)
nix develop# Build and switch to new configuration
sudo nixos-rebuild switch --flake .#bit
# Test build without switching
sudo nixos-rebuild build --flake .#spark
# Build specific host configuration
nix build .#nixosConfigurations.hermes.config.system.build.toplevel# Deploy to remote machine
just deploy spark
just deploy vps-alpha
# Deploy to all hosts
just deploy-all
# Dry run to see what would change
just dry-run hermes# Check flake for errors (validates all configurations)
just check
# Format all Nix files
just fmt
# Format check without modifying
just fmt-check# Update all flake inputs (nixpkgs, home-manager, etc.)
just update
# Show flake outputs
nix flake show# Edit encrypted secrets
just secrets
just secrets secrets/vps/knock-sequences.yaml
# View decrypted content
just secrets-view secrets/vps/knock-sequences.yaml
# Update encryption keys for all secrets
just secrets-update# Knock and connect to VPS
just knock vps-alpha
# Or manually
knock -v vps-alpha 7000 8000 9000 && ssh giovanni@vps-alphaThis repository supports zero-touch installation - boot NixOS installer and deploy remotely with a single command.
# Boot NixOS installer on target, note IP, then run:
just install <hostname> <category> <ip>
# Examples:
just install spark laptops 192.168.1.100 # Laptop
just install vps-beta vps 203.0.113.50 # VPS
just install server-beta servers 10.0.0.50 # Server
just install test-vm experiments 192.168.1.200 # ExperimentWhat happens automatically:
- Generates age encryption key
- Partitions and formats disk
- Installs NixOS
- Deploys age key
- Fetches hardware config
- Creates host configuration
- Updates .sops.yaml automatically
- Updates flake.nix automatically
- Re-encrypts all secrets
- Commits changes to git
- Deploys full configuration
Time: ~15 minutes, completely hands-off.
See docs/WORKFLOW.md for complete installation workflow.
This repository supports centralized deployment from bit (main laptop) to all other machines without storing git credentials anywhere.
- Central laptop (bit): Has the repository and SSH agent with keys
- Remote machines: Receive deployments via deploy-rs over Tailscale
- Git operations: Use SSH agent forwarding (no credentials stored on remote machines)
# From bit
just deploy spark
just deploy vps-alphajust pull-deploy spark# Pull changes back to central repo
just sync-remote spark
# Then review, commit, and push
git diff
git add .
git commit -m "sync: changes from spark"
git pushjust remote-push spark mainRemote machines can perform git operations using your local SSH keys:
- Requires
ForwardAgent yesin SSH config - SSH agent must be running on bit:
eval "$(ssh-agent -s)" && ssh-add - Test with:
ssh -A spark 'ssh-add -l'
- Boot NixOS installer on target machine
- Run:
just install <hostname> <category> <ip> - Everything else is automatic (config creation, secrets, deployment)
See docs/WORKFLOW.md for detailed workflow guide.
If not using automated installation:
- Create directory:
mkdir -p hosts/{category}/{hostname} - Create
configuration.nixandhardware-configuration.nix - Add to
flake.nix:
nixosConfigurations.newhostname = mkHost {
hostname = "newhostname";
category = "laptops"; # or vps, servers, experiments
};- Add to deploy nodes for remote deployment
- Generate hardware config on target:
nixos-generate-config --show-hardware-config
- Create
modules/users/username.nixwith Home Manager config - Import in
flake.nixunderhome-manager.users.username - Add user to host configuration in
users.users.username
- Use sops-nix for all secrets (passwords, API keys, knock sequences)
- Never commit unencrypted secrets or private keys
- Secrets encrypted with GPG (admin) + age (per-host keys)
- Port knocking sequences stored in
secrets/vps/knock-sequences.yaml
- Common modules imported in
hosts/common/default.nix - Category configs imported from
hosts/categories/{category}.nix - Host configs import category + hardware config
- Networking modules (Tailscale, firewall) imported in category configs
- Primary workstation and deployment hub
- Full development environment
- SSH agent with keys for remote operations
- Framework-specific optimizations
- Lighter than bit, mobile-focused
- Framework kernel modules enabled
- Minimal laptop config
- Secondary/backup machine
- Minimal and hardened - kernel hardening, strict sysctls
- Port knocking required for SSH access
- Knock sequence encrypted in
secrets/vps/knock-sequences.yaml - Access via:
just knock vps-alpha - Auto-updates enabled (manual reboot)
- nix-fmt: Ensures all Nix files properly formatted
- nix-flake-check: Validates flake syntax and configuration
- detect-secrets: Scans for accidentally committed secrets
- prevent-secrets: Blocks hardcoded passwords, tokens, keys
GitHub Actions runs on every push/PR:
- Flake validation (
nix flake check) - Format checking (
nix fmt -- --check) - Dry-run builds of all configurations
- Secret scanning (detect-secrets, hardcoded pattern checks)
- Private key detection
VPS hosts use port knocking for SSH access:
- Knock sequence defined in encrypted
secrets/vps/knock-sequences.yaml - Sequence must be knocked before SSH port opens (30 second window)
- Use:
just knock vps-alpha - Change sequences periodically for security
All hosts connect via Tailscale mesh VPN:
- Zero-trust networking
- Use Tailscale hostnames for opaque addressing
- Firewall trusts Tailscale interface
- Enables secure deployment without exposing services
- Always run
just checkafter significant changes - Format with
just fmtbefore committing - Test with
nixos-rebuild buildbefore switching - Verify no secrets are hardcoded
hosts/{category}/{hostname}/hardware-configuration.nixgenerated bynixos-generate-config- Can be regenerated but may contain manual tweaks
- Machine-specific: filesystems, boot, kernel modules, hardware settings
- Changes to
hosts/categories/{category}.nixaffect ALL hosts in that category - Test changes across multiple hosts when possible
- Keep category configs focused on shared functionality
- Changes to
hosts/common/default.nixaffect ALL hosts - Extremely conservative changes only
- Test across all categories
# Check syntax
just check
# Verify imports are correct
# Check for circular dependencies
# Check for conflicting options across modules# Check knock sequence in secrets
just secrets-view secrets/vps/knock-sequences.yaml
# Knock and connect
just knock vps-alpha
# Check knockd status on VPS
ssh vps-alpha 'sudo systemctl status knockd'
# Check firewall rules
ssh vps-alpha 'sudo iptables -L INPUT -v -n'# Check Tailscale status
just tailscale-status spark
# Restart Tailscale on host
ssh hostname 'sudo systemctl restart tailscaled'
# Check firewall allows Tailscale
ssh hostname 'sudo iptables -L -v -n | grep tailscale'# Check GPG key available
gpg --list-secret-keys
# Check age key on host
ssh hostname 'sudo cat /var/lib/sops-nix/key.txt'
# Verify .sops.yaml has correct keys
cat .sops.yaml
# Re-encrypt with updated keys
just secrets-update# Rollback to previous generation
just rollback spark
# List all generations
just generations spark
# Clean old generations
just clean spark# List all commands
just --list
# Install new host (fully automated)
just install <hostname> <category> <ip>
# Deploy to specific host
just deploy spark
# Deploy to all hosts
just deploy-all
# Update flake inputs
just update
# Edit secrets
just secrets
# Port knock VPS
just knock vps-alpha
# Sync from remote
just sync-remote spark
# Check system info
just info spark
just tailscale-status spark
# Rollback and cleanup
just rollback spark
just clean sparkdocs/WORKFLOW.md: Complete hands-off installation and deployment workflowdocs/JUSTFILE_COMMANDS.md: Full command reference with examplesdocs/QUICK_START.md: Quick start guidedocs/SOPS_GPG_SETUP.md: Secrets management with SOPSdocs/STRUCTURE_OVERVIEW.md: Repository architectureREADME.md: Main repository documentation
When assisting with this repository:
- Use justfile commands - Never suggest old scripts or make commands
- Respect security - Never suggest hardcoding secrets or bypassing encryption
- Follow categories - Understand security differences between laptop/vps/server/experiment
- Test before deploy - Always suggest
just checkandjust dry-runbefore deployment - Maintain opacity - Use Tailscale hostnames, not IPs
- Preserve automation - Leverage the automated installation workflow
- Document changes - Suggest adding comments for non-standard configurations
- Security-first for VPS - Port knocking, hardening, minimal packages are intentional
- Modular approach - Use category configs for shared functionality
- Secrets via SOPS - All sensitive data must be encrypted with SOPS