Personal NixOS configuration for multiple machines, managed with Nix Flakes, home-manager, deploy-rs for remote deployments, and agenix for secret management. The flake layout uses blueprint.
Enter the dev shell (defined in devshell.nix) for all tooling:
nix develop
# or, with direnv:
direnv allowCommon tasks are wrapped in the Justfile — run just to list all recipes.
Key groups: build, deploy, format, format-check, updaters, nix.
All SSH public keys for users and host systems — no secrets, just public keys.
Imported by secrets-registry.nix (to declare which hosts may decrypt each
secret) and by modules/nixos/data/ (which exposes the keys as
config.etu.data.pubkeys). Mittens' key is authorized for root SSH access on
server-sparv. The laptop-work-elis SSH key is retained for a separately
managed device; this repository no longer configures that host. The
macbook-air-elis key is the user key on the nix-darwin MacBook Air M5 and is
part of etu.computers and the agenix etu key set. The file also holds the
Nix remote builder keys: builders (the MacBook's dedicated passphrase-less
builder key, used by modules/darwin/base/nix/) and builderHostKeys (the
base64-encoded host keys that Nix's builders setting requires).
Main flake definition: inputs, blueprint wiring, deploy-rs nodes for the three
remotely-managed servers, and the live-iso package alias. Per-system outputs
are generated for aarch64-darwin, aarch64-linux and x86_64-linux only
(nixpkgs 26.11 dropped x86_64-darwin). nixpkgs is split by platform:
nixpkgs (nixos-unstable-small) for the NixOS hosts and nixpkgs-darwin
(nixpkgs-unstable, which waits for the darwin builds) for the MacBook, with
nix-darwin and home-manager-darwin following it. All other inputs follow
nixpkgs via .follows where possible. Key inputs: agenix, blueprint,
deploy-rs, disko, emacs-overlay, home-manager,
home-manager-darwin, impermanence, ip-failar-nu, nix-darwin,
nixos-hardware, nixpkgs-darwin, nur.
Task runner wrapping common nix, deploy, format, and update commands. Run
just to list everything. Notable recipes:
just build/just build-<hostname>/just build-all— build hosts withnom(just buildbuilds the current host, using its nix-darwin config on macOS)just deploy-server-main-elis/just deploy-server-sparv/just deploy-vps06just activate— build and activate the current host locally (darwin-rebuildon macOS,nixos-rebuildon Linux)just nix-fmt/just all-fmt-check— format and lint checksjust update-all— update flake inputs and all container image tags
MacBook Air M5 (aarch64-darwin) managed with
nix-darwin via
darwin-configuration.nix, which blueprint exposes as
darwinConfigurations.macbook-air-elis. The host file only sets the
hostname, platform, state version and a few etu.* options; everything else
comes from flake.darwinModules.default (see modules/darwin/ below): Nix
settings and caches (with weekly garbage collection and daily store
optimisation), the git revision for darwin-version, dark mode, an auto-hiding Dock without recent apps, battery percentage and Bluetooth in the menu bar, Caps Lock remapped
to Control, faster key repeat, Touch ID for sudo (also inside tmux), the command line tools (including NUR tools), aspell and hunspell with English and Swedish dictionaries (for Emacs' flyspell),
Tailscale (tailscaled as a launchd daemon; log in once with
sudo tailscale up), fish (in /etc/shells; set as login shell once with
chsh), Emacs with its overlay and fonts, Claude Code, VS Code, OpenSCAD, the AeroSpace tiling
window manager (sway-like bindings on Alt, see modules/darwin/graphical/aerospace),
and the shared emacs, fish, ghostty, git, htop and tmux
home-manager modules (Ghostty uses the macOS ghostty-bin package there,
always starts fish and quits after its last window closes; git always signs
commits with the SSH key), ssh using the macOS ssh-agent with key
passphrases in the Keychain (loaded into the agent at login), and direnv with
nix-direnv. The host has no separate home-manager file: the darwin modules set
up home-manager for etu.user.username (including zsh and
home.stateVersion from etu.stateVersion), and host-specific settings are
etu.* options in darwin-configuration.nix.
The emacs module uses the native macOS emacs build on darwin instead of
emacs-pgtk, and adds the Nix profiles to its PATH so Emacs.app launched
from Spotlight finds git and other tools instead of the Xcode stubs in
/usr/bin. Its Emacs.app starts Emacs as a separate process, like a
terminal would, so AeroSpace manages its windows. Bootstrap steps are in
the header of the configuration file; later changes are applied with
just activate. Since macOS cannot build x86_64-linux derivations locally,
Nix builds the NixOS hosts on server-main-elis from this machine (enabled
with base.nix.remoteBuilds in darwin-configuration.nix, backed by
nix.buildMachines in modules/darwin/base/nix/ and a dedicated
passphrase-less key in ~/.ssh/nix-builder, see pubkeys.nix), so
just build-<server> and just deploy-<server> work from the Mac too.
Built and cached in CI on a macos-latest (Apple Silicon)
runner alongside the NixOS hosts.
Home file server, deployed using deploy .#server-main-elis. Also the Nix
remote builder for the MacBook: it builds the x86_64-linux hosts (8 jobs,
ssh-ng with a dedicated key) so they can be built and deployed from macOS.
Primary ZFS backup target — pulls snapshots from configured backup sources via
syncoid.
Runs a large collection of services:
- Home automation: Home Assistant, Mosquitto MQTT, zwavejs2mqtt (all via Podman containers)
- Media stack: Jellyfin, NZBGet, Sonarr, Radarr, Lidarr, Bazarr
- Web services: Nextcloud, FreshRSS, Homepage dashboard, Nginx reverse proxy
- Monitoring: Beszel hub (collects from all three servers) + Beszel agent
- Infrastructure: Sanoid (ZFS snapshots), Syncoid (pulls backups from configured systems), Cloudflare DynDNS, smartd, libvirtd, ACME/Let's Encrypt
- Scheduled tasks: SVTPlay playlist downloader (daily), empty-dirs cleaner (hourly)
On-location server for speliarvika.se. Primarily a
game server host and LAN cache. Runs Valheim and Project Zomboid via Docker,
plus a whitelisted Minecraft server (NixOS service). Includes lancache
(monolithic + DNS) for LAN game cache. ZFS snapshots via sanoid. Monitoring
with Netdata (local dashboard) and Beszel agent. Deployed using
deploy .#server-sparv.
VPS running public-facing services, deployed using deploy .#vps06:
- Forgejo — git forge at
git.elis.nu - Matrix Synapse — homeserver on
failar.nu, with Element Web atelement.failar.nuand an IRC bridge - Grafana — dashboards at
grafana.elis.nu - Matomo — web analytics at
matomo.elis.nu - ip.failar.nu — custom service from the
ip-failar-nuflake input - Nginx reverse proxy — also forwards traffic to services hosted on
server-main-elis(Nextcloud, FreshRSS, Home Assistant, Jellyfin, etc.)
If you're adventurous and want to run a clone of this configuration from a live ISO (console only, without a graphical environment), it can be built locally:
nix build github:etu/nixconfig#isoReusable NixOS and home-manager modules with custom options.
modules/nixos/ — system-level modules for the servers and the live
ISO: base, data, development (git), graphical (only the font options
read by the Emacs module), hacks, services, user. There is no NixOS
desktop any more; the desktop is the nix-darwin MacBook. The shared NixOS and nix-darwin base modules blacklist the
compromised Comodo AAA Services root certificate (nss 3.131.1 removed the
also compromised emSign ECC Root CA - G3 itself).
modules/darwin/ — nix-darwin modules, mirroring modules/nixos/ and
its etu.* option names (so shared home modules reading osConfig.etu.*
work on macOS too): base (emacs, fish, htop, nix with remote builds on
server-main-elis, packages, spell, ssh, system defaults,
tailscale, tmux), development (claude-code, direnv, git, vscode), graphical (AeroSpace, fdm-printing,
Ghostty, theme fonts), user.
modules/home/ — user-level home-manager modules:
emacs, fish, ghostty, git, htop, restow, tmux, vscode.
restow updates ~/.dotfiles and stows it into the home directory, on
nix-darwin hosts that set etu.user.restow.enable. The shared Git
module globally ignores common macOS filesystem artifacts (such as
.DS_Store) on Darwin. The Ghostty module enables copy-on-select.
Secrets managed with agenix, which
age-encrypts files using the SSH public
keys of authorised users and hosts. Encrypted .age files are safe to commit.
secrets-registry.nix is the single source of truth: each secret is
defined once with its file path, optional agenix options (owner, path,
symlink), and the list of host keys allowed to decrypt it. Both
agenix-rules.nix (used by the agenix CLI) and config.etu.data.ageModules
(via modules/nixos/data/) are derived automatically from this registry.
Do not edit agenix-rules.nix by hand. This repository does not manage
Nextcloud administrator credentials.
Five workflows keep the repo healthy:
format.yml— Nix fmt, yamllint, deadnix, statix checks on every push/PRpull_request.yaml— builds dev shell, runs flake check, builds all hosts (NixOS hosts on Linux runners, the MacBook on a macOS runner)cache.yml— builds and caches all hosts (including the MacBook) to Cachix on pushes tomaindeploy.yml— deploys the three remote servers via deploy-rs after a push tomainupdate.yml— scheduled PRs to update flake inputs and container image tags