Connect: X • Instagram • Bluesky • Mastodon
Blueprint-driven NixOS and nix-darwin configurations with declarative system management for multiple hosts.
This repository uses Nix Flakes to manage system configurations across NixOS and macOS systems. It leverages Blueprint for structured organization, making it easy to share configurations between hosts while maintaining host-specific customizations.
.
├── flake.nix # Main flake configuration with inputs and outputs
├── hosts/ # Individual host configurations (see hosts/README.md)
├── modules/ # Reusable NixOS, Darwin, and home-manager modules
│ ├── nixos/ # NixOS-specific modules
│ │ ├── default/ # Common NixOS modules (docker, tailscale, backups, etc.)
│ │ ├── desktop/ # Desktop environment modules (fonts, flatpak, steam, etc.)
│ │ └── common/ # Shared configurations
│ ├── darwin/ # macOS-specific modules
│ └── home/ # home-manager modules (fish, git, wezterm, tmux, etc.)
├── packages/ # Custom Nix packages (see packages/README.md)
├── users/ # User configurations (jmeskill, git, messy)
├── devshells/ # Development shell environments (see devshells/README.md)
├── lib/ # Custom Nix library functions
├── secrets/ # Encrypted secrets managed with agenix
├── files/ # Static configuration files
├── .claude/ # oh-my-opencode agents and commands
├── .opencode/ # oh-my-opencode project configuration
└── justfile # Command runner recipes (run `just` to see all)
This repository uses OpenCode with oh-my-opencode as the primary AI agent interface, with Sisyphus (Claude Opus 4.5) as the orchestrator.
# Start OpenCode with Sisyphus orchestration
opencode
# Magic word for maximum performance
# Include "ultrawork" or "ulw" in your prompt| Type | Agents | Purpose |
|---|---|---|
| Built-in | oracle, librarian, explore, frontend-ui-ux-engineer, document-writer | oh-my-opencode defaults |
| Project | agenix, cfnix, containnix, nix-packager | Custom agents in .claude/agents/ |
| Agent | Responsibilities |
|---|---|
agenix |
Secrets management (.age files), rekeying, encryption |
cfnix |
Cloudflare DNS records & Tunnel configuration |
containnix |
Docker/OCI container deployment, networking, proxy setup |
nix-packager |
Creating and converting Nix packages |
- Create Database:
/create-db-<host>(e.g.,/create-db-monolith) - Create Pi Host:
/create-pi-host
| File | Purpose |
|---|---|
| AGENTS.md | Primary context beacon for OpenCode |
| .claude/agents/ | Custom agent definitions |
| .claude/commands/ | Slash commands |
For complete documentation, see AGENTS.md.
This configuration manages 24 hosts across multiple platforms:
- 14 NixOS Servers (Physical infrastructure, Raspberry Pi cluster)
- 2 NixOS Thin Clients (High Availability pair)
- 1 Cloud VPS (Remote services)
- 2 NixOS Workstations (Desktop & Laptop)
- 2 NixOS MicroVMs (Development environments)
- 3 macOS Systems (Development workstations)
For detailed information about each host including hardware specifications, key features, and purposes, see hosts/README.md.
This repository includes custom Nix packages for specialized functionality:
- agenix-helper - Helper utility for managing passphrase-protected age identities with 1Password integration
- backup-docker-mariadb - Automated MariaDB backup with integrated NixOS module and systemd timer
- backup-docker-postgres - Automated PostgreSQL backup with integrated NixOS module and systemd timer
- docker-mcp-gateway - Docker CLI plugin for Model Context Protocol integration
- forgejo-shell - SSH shell wrapper for Forgejo Docker container
- messy-restricted-shell - Restricted shell with whitelisted commands
- nelko-pl70ebt - CUPS driver for Nelko PL70e-BT label printer
- pinentry-1password - Pinentry-compatible program using 1Password CLI for passphrase retrieval
- ssh-agent-check - Fast, cached SSH agent availability checker
For detailed information about each package including usage examples and dependencies, see packages/README.md.
A comprehensive design system providing consistent visual language across all CLI tools.
N0FRILLS is a minimalist design language built on four principles:
- No Waste - Remove purely decorative elements, focus on functional information
- Visual Stability - Consistent positioning across all tools prevents cognitive load
- Direct Voice - Functional bracket notation
[>][~][@]over icons - Absolute Consistency - Shared colorways across your entire CLI ecosystem
| Colorway | Primary | Accent | Character |
|---|---|---|---|
| classic | White #eeeeee |
Gray #8a8a8a |
Monochrome brutalism |
| ruin | Magenta #d75fd7 |
Cyan #5fd7d7 |
High-energy contrast |
| siege | Purple #875fd7 |
Teal #00afaf |
Professional depth |
| ghost | White #eeeeee |
Amber #ffaf00 |
Warm minimalism |
All colorways share a base palette:
fg: #eeeeee (primary text)
bg: #1c1c1c (background)
border: #3a3a3a (frames)
muted: #626262 (secondary text)
dim: #4e4e4e (inactive)
gray: #8a8a8a (labels)
Fully Implemented:
- WezTerm - 3 color schemes (ghost, ruin, siege) in
files/configs/wezterm/colors/ - Neovim - Custom colorscheme in
files/configs/nvim/colors/n0frills.lua - OpenCode - 3 themes in
files/configs/opencode/themes/ - tmux - Colorway support with shared palette in
modules/home/default/tmux.nix - Starship - Theme compositor: 4 colorways × 3 styles = 12 combinations in
modules/home/default/starship.nix - xplr - File manager theming in
modules/home/default/xplr.nix
Starship Styles:
- basic - Brutalist single-line, minimal modules
- advanced - Structured two-line, comprehensive status
- handcrafted - Artisanal with custom formatting
Select colorway in your host's home-configuration:
ruinous.colorscheme = "ruin"; # or "siege", "ghost", "classic"
ruinous.starship.style = "advanced"; # or "basic", "handcrafted"Implementation Guides:
- Gemini CLI - AI CLI theming
- Neovim - Editor colorscheme
- OpenCode - AI coding assistant themes
- Starship - Prompt theme compositor
- tmux - Terminal multiplexer theming
- WezTerm - Terminal emulator colors
- xplr - File manager theming
Research & Design:
- Starship Implementation Plan - Theme compositor design
- tmux Theming Research - Comprehensive theming patterns
- Extended Research - Tool-specific theming deep dives
All themes use the shared color definitions from modules/home/default/options.nix:
ruinous.colorschemes = {
ruin = { primary = "#d75fd7"; accent = "#5fd7d7"; };
siege = { primary = "#875fd7"; accent = "#00afaf"; };
ghost = { primary = "#eeeeee"; accent = "#ffaf00"; };
};Modules automatically inject colorway-specific values based on ruinous.colorscheme selection.
- Blueprint - Structured flake organization that maps directory structure to outputs
- Home Manager - Declarative dotfile and user environment management
- Agenix - Encrypted secrets management with age
- Disko - Declarative disk partitioning and formatting
- System Manager - Unified system configuration across NixOS and Darwin
Multiple desktop environment modules available:
- KDE Plasma 6
- Hyprland (Wayland compositor)
- GNOME
- LXQT
- XFCE
- Development Shells - Pre-configured environments (see devshells/README.md)
- Devenv - Integrated development environment support
- Fenix - Rust toolchain for reproducible Rust builds
- Docker - Container support on multiple hosts
- Lanzaboote - Secure boot with UEFI
- Tailscale - Mesh VPN networking
- Restic - Automated backups to remote storage
- Caddy - Reverse proxy and web server
- Cloudflared - Cloudflare tunnel support
- Grafana Alloy - Observability and monitoring
- Harmonia - Private Nix binary cache
Comprehensive user environment configurations for:
- Shell: fish, starship prompt, tmux
- Terminal: wezterm, alacritty
- Development: git, neovim, zed-editor, go
- CLI Tools: bat, eza, fzf, btop, bottom
- Productivity: todoist, vdirsyncer, khal
- Security: age, gpg, keychain, ssh
To build and apply the NixOS configuration for a specific host (e.g., framework):
nixos-rebuild switch --flake .#frameworkReplace framework with the name of your host.
To build and apply the nix-darwin configuration for a specific macOS host (e.g., jmacmini):
darwin-rebuild switch --flake .#jmacminiOr use the justfile helper (auto-detects local/remote, Darwin/NixOS):
just deploy # Deploy to current host
just deploy jmacmini # Deploy to specific hostTo deploy a configuration to a remote NixOS host:
just deploy <hostname>This will auto-detect the host type and connect to <hostname>.meskill.farm to apply the configuration.
To update all Nix flake inputs (nixpkgs, home-manager, etc.):
nix flake updateOr use the justfile:
just update-flakeEnter a development shell with project-specific tools:
nix develop # Default development shell
nix develop .#pdftools # PDF manipulation tools
nix develop .#python313 # Python 3.13 environment
nix develop .#n8n-node-dev # n8n custom node developmentFor detailed information about available shells, direnv integration, and creating custom shells, see devshells/README.md.
To bootstrap a fresh macOS system with Lix (Nix fork) and nix-darwin:
just installThis will:
- Install Lix via lix-installer (on macOS) or Nix (on Linux)
- Install nix-darwin (macOS only)
- Apply the configuration for the current hostname
- Create a new directory under
hosts/with your hostname - Add a
configuration.nix(NixOS) ordarwin-configuration.nix(macOS) - For NixOS, optionally run
nixos-generate-configto createhardware-configuration.nix - Import the appropriate modules from
modules/nixosormodules/darwin - Add user-specific home-manager configurations in
hosts/<hostname>/users/ - Build and apply:
nixos-rebuild switch --flake .#<hostname>
Secrets are encrypted using agenix and stored in secrets/.
For a streamlined experience when working with multiple secrets:
# Unlock once per session (enter passphrase once)
agenix-helper unlock
# Edit secrets without repeated passphrase prompts
agenix edit secrets/<secret-name>.age
agenix rekey -a
# Lock when done
agenix-helper lockIf you use 1Password CLI, you can store your age identity passphrase in 1Password and have agenix-helper retrieve it automatically:
# Set up 1Password secret reference
export OP_PIN_ITEM="op://Private/age-identity/passphrase"
# Unlock without typing passphrase (retrieved from 1Password)
agenix-helper unlockThis requires:
- 1Password CLI (
op) installed and authenticated pinentry-1passwordpackage installedOP_PIN_ITEMenvironment variable set to your 1Password secret reference
See the agenix-helper package documentation and pinentry-1password documentation for details.
To edit secrets directly (prompts for passphrase each time):
agenix -e secrets/<secret-name>.ageSecrets are automatically decrypted on the target system and available to services that reference them.
A private Harmonia binary cache is available for hosts on the Tailscale network at cache.nix.meskill.farm.
Add the following to your NixOS configuration to use the private cache:
nix.settings = {
substituters = [ "https://cache.nix.meskill.farm" ];
trusted-public-keys = [ "cache.nix.meskill.farm-1:9Ih1t1q9biWeHg28x+qunDj42JkaGfLd95YD2ltEAAw=" ];
};Or for flake-based configurations in flake.nix:
nixConfig = {
extra-substituters = [ "https://cache.nix.meskill.farm" ];
extra-trusted-public-keys = [ "cache.nix.meskill.farm-1:9Ih1t1q9biWeHg28x+qunDj42JkaGfLd95YD2ltEAAw=" ];
};- Host must be on the Tailscale network (100.0.0.0/8) or local network (10.55.0.0/16)
- No authentication required for authorized networks
- External requests receive HTTP 403
# Test cache connectivity
curl -I https://cache.nix.meskill.farm/nix-cache-info
# Expected response: HTTP 200 with cache metadata