This repository contains my personal Nix configuration for managing my desktop, servers, and (occasionally) a Mac, using a declarative, reproducible approach with Nix flakes.
This configuration manages 9 hosts:
| Host | Platform | Role |
|---|---|---|
| gnomon | NixOS (x86_64-linux) | Primary desktop — niri + DankMaterialShell, gaming rig |
| ultraviolet | NixOS (x86_64-linux) | Main homelab server |
| bluedesert | NixOS (x86_64-linux) | Z-Wave bridge (zwave-js-ui) |
| vermissian | NixOS (x86_64-linux) | Work/dev server |
| echelon | NixOS (x86_64-linux) | Remote tailnet node |
| stygianlibrary | NixOS (x86_64-linux) | halmasuit test rig (portable, hardware-identical to gnomon) |
| ninuan | macOS (aarch64-darwin) | Rarely powered on now that gnomon is the primary desktop |
| testhost | NixOS (x86_64-linux) | VM fixture for the installer test, not a real machine |
| installer | NixOS (x86_64-linux) | Generic installer ISO output, not a deployed host |
On the target machine, run update — a writeShellScriptBin on PATH that dispatches to nh os switch/nh darwin switch (or SSHes into bluedesert, which has no local Nix). It pre-flights sudo -n true and refuses to hang waiting on a password prompt, so it's safe to run from scripts and agents:
update
Or invoke the underlying rebuild directly:
# macOS
darwin-rebuild switch --flake ".#$(hostname -s)" --option warn-dirty false
# Linux
sudo nixos-rebuild switch --flake ".#$(hostname)" --option warn-dirty false
git add . # flakes only see git-tracked files
nix flake check
nix flake update
nix build .#myCaddy # Custom Caddy web server
flake.nix - Main entry point and flake configurationhosts/ - System-level configurations for each machine
common.nix - Shared configuration for Linux servers (NFS mounts)home-manager/ - User-level dotfiles and application configs
common.nix - Shared configuration across all systemsaarch64-darwin.nix - macOS-specific user configurationheadless-x86_64-linux.nix - Linux server user configurationpkgs/ - Custom package definitionsoverlays/ - Nixpkgs modificationssecrets/ - Public keysTo add a new system:
hosts/<hostname>/flake.nix under appropriate section (nixosConfigurations or darwinConfigurations)To add a new package:
pkgs/<name>/default.nixpkgs/default.nixoverlays/default.nix if needed globallyThe dev context system unifies the metadata that describes where a shell is running. Every session exports DEV_CONTEXT, DEV_CONTEXT_KIND, and an optional DEV_CONTEXT_ICON, and all UI surfaces read from those variables. Starship prompts, Kitty tab titles, tmux status lines, and mobile notifications now stay in sync regardless of whether the context came from tmux, Coder, or a plain host shell.
tmux-devspace wraps tmux new-session/attach and immediately sets DEV_CONTEXT, DEV_CONTEXT_KIND=tmux, plus whatever DEV_CONTEXT_ICON value the caller provides via --icon. Legacy TMUX_DEVSPACE variables still exist for older scripts but should be treated as compatibility shims.t (defined in home-manager/zsh/default.nix) is the main entry point. Running t with no arguments creates an auto-named context. t feature-login ☾ sanitizes the label, records the icon, and spawns/attaches to feature-login. Use t feature-login -- cargo watch to skip the icon while forwarding a command after --.mercury, venus, earth, mars, jupiter) remain for muscle memory on both the servers and macOS clients. Each alias now calls t <planet> <icon> (or tmux-devspace attach --icon ... on macOS), so the icon travels with the context from the moment it is created.CODER_WORKSPACE_NAME seeds DEV_CONTEXT with DEV_CONTEXT_KIND=coder, so prompts stay labeled even when tmux is not involved.t # Create/switch to an auto-named context
t feature-login ☾ # Spawn or attach to feature-login with a moon icon
t feature-login -- cargo watch # Run a command without setting an icon
earth # Attach to the earth planetary context (via t earth ♁)
mars status # Invoke helper subcommands inside that context
devspace-status # List sessions on the current host (alias: ds)
dsl # Detailed tmux session listing
CODER_WORKSPACE_NAME, and finally to the system hostname (DEV_CONTEXT_KIND=host).DEV_CONTEXT. Coder contexts default to , tmux planetary contexts get their astronomical glyphs (☿♀♁♂♃), and non-planetary sessions display as ● <label>.@dev_context so Kitty tabs, native terminal windows, and the macOS tab bar all render the same label.ntfy notifier includes the context string (and icon when present), so phone alerts point to the exact session that completed.DEV_CONTEXT and friends.Compatibility aliases and historical docs still reference “devspaces”, but new code and copy should prefer the “dev context” terminology.
When SSH'd into a server, links can be opened on your local Mac browser automatically. This is especially useful for AWS SSO authentication.
BROWSER=remote-link-open# On the server
aws sso login # Will display a clickable authentication URL
remote-link-open https://example.com # Manually open a URL
See CLAUDE.md for detailed testing procedures. Quick summary:
# Validate configuration
nix flake check
# Preview changes
darwin-rebuild switch --flake ".#$(hostname -s)" --option warn-dirty false --dry-run
# Build specific components
nix build .#homeConfigurations."joshsymonds@$(hostname -s)".activationPackage
1,159 followers · starred Jul 2025
392 followers · starred Jul 2025
628 followers · starred Sep 2025
665 followers · starred Jul 2025
This repository contains my personal Nix configuration for managing my desktop, servers, and (occasionally) a Mac, using a declarative, reproducible approach with Nix flakes.
This configuration manages 9 hosts:
| Host | Platform | Role |
|---|---|---|
| gnomon | NixOS (x86_64-linux) | Primary desktop — niri + DankMaterialShell, gaming rig |
| ultraviolet | NixOS (x86_64-linux) | Main homelab server |
| bluedesert | NixOS (x86_64-linux) | Z-Wave bridge (zwave-js-ui) |
| vermissian | NixOS (x86_64-linux) | Work/dev server |
| echelon | NixOS (x86_64-linux) | Remote tailnet node |
| stygianlibrary | NixOS (x86_64-linux) | halmasuit test rig (portable, hardware-identical to gnomon) |
| ninuan | macOS (aarch64-darwin) | Rarely powered on now that gnomon is the primary desktop |
| testhost | NixOS (x86_64-linux) | VM fixture for the installer test, not a real machine |
| installer | NixOS (x86_64-linux) | Generic installer ISO output, not a deployed host |
On the target machine, run update — a writeShellScriptBin on PATH that dispatches to nh os switch/nh darwin switch (or SSHes into bluedesert, which has no local Nix). It pre-flights sudo -n true and refuses to hang waiting on a password prompt, so it's safe to run from scripts and agents:
update
Or invoke the underlying rebuild directly:
# macOS
darwin-rebuild switch --flake ".#$(hostname -s)" --option warn-dirty false
# Linux
sudo nixos-rebuild switch --flake ".#$(hostname)" --option warn-dirty false
git add . # flakes only see git-tracked files
nix flake check
nix flake update
nix build .#myCaddy # Custom Caddy web server
flake.nix - Main entry point and flake configurationhosts/ - System-level configurations for each machine
common.nix - Shared configuration for Linux servers (NFS mounts)home-manager/ - User-level dotfiles and application configs
common.nix - Shared configuration across all systemsaarch64-darwin.nix - macOS-specific user configurationheadless-x86_64-linux.nix - Linux server user configurationpkgs/ - Custom package definitionsoverlays/ - Nixpkgs modificationssecrets/ - Public keysTo add a new system:
hosts/<hostname>/flake.nix under appropriate section (nixosConfigurations or darwinConfigurations)To add a new package:
pkgs/<name>/default.nixpkgs/default.nixoverlays/default.nix if needed globallyThe dev context system unifies the metadata that describes where a shell is running. Every session exports DEV_CONTEXT, DEV_CONTEXT_KIND, and an optional DEV_CONTEXT_ICON, and all UI surfaces read from those variables. Starship prompts, Kitty tab titles, tmux status lines, and mobile notifications now stay in sync regardless of whether the context came from tmux, Coder, or a plain host shell.
tmux-devspace wraps tmux new-session/attach and immediately sets DEV_CONTEXT, DEV_CONTEXT_KIND=tmux, plus whatever DEV_CONTEXT_ICON value the caller provides via --icon. Legacy TMUX_DEVSPACE variables still exist for older scripts but should be treated as compatibility shims.t (defined in home-manager/zsh/default.nix) is the main entry point. Running t with no arguments creates an auto-named context. t feature-login ☾ sanitizes the label, records the icon, and spawns/attaches to feature-login. Use t feature-login -- cargo watch to skip the icon while forwarding a command after --.mercury, venus, earth, mars, jupiter) remain for muscle memory on both the servers and macOS clients. Each alias now calls t <planet> <icon> (or tmux-devspace attach --icon ... on macOS), so the icon travels with the context from the moment it is created.CODER_WORKSPACE_NAME seeds DEV_CONTEXT with DEV_CONTEXT_KIND=coder, so prompts stay labeled even when tmux is not involved.t # Create/switch to an auto-named context
t feature-login ☾ # Spawn or attach to feature-login with a moon icon
t feature-login -- cargo watch # Run a command without setting an icon
earth # Attach to the earth planetary context (via t earth ♁)
mars status # Invoke helper subcommands inside that context
devspace-status # List sessions on the current host (alias: ds)
dsl # Detailed tmux session listing
CODER_WORKSPACE_NAME, and finally to the system hostname (DEV_CONTEXT_KIND=host).DEV_CONTEXT. Coder contexts default to , tmux planetary contexts get their astronomical glyphs (☿♀♁♂♃), and non-planetary sessions display as ● <label>.@dev_context so Kitty tabs, native terminal windows, and the macOS tab bar all render the same label.ntfy notifier includes the context string (and icon when present), so phone alerts point to the exact session that completed.DEV_CONTEXT and friends.Compatibility aliases and historical docs still reference “devspaces”, but new code and copy should prefer the “dev context” terminology.
When SSH'd into a server, links can be opened on your local Mac browser automatically. This is especially useful for AWS SSO authentication.
BROWSER=remote-link-open# On the server
aws sso login # Will display a clickable authentication URL
remote-link-open https://example.com # Manually open a URL
See CLAUDE.md for detailed testing procedures. Quick summary:
# Validate configuration
nix flake check
# Preview changes
darwin-rebuild switch --flake ".#$(hostname -s)" --option warn-dirty false --dry-run
# Build specific components
nix build .#homeConfigurations."joshsymonds@$(hostname -s)".activationPackage
1,159 followers · starred Jul 2025
392 followers · starred Jul 2025
628 followers · starred Sep 2025
665 followers · starred Jul 2025