Motivation#
I first tried NixOS seriously about four or five years ago. My impression at the time was this: the ideas are excellent — the whole operating system is described declaratively in a handful of files, managed with Git, and every change can be switched atomically and rolled back — but writing the configuration itself was too hard. The learning curve of the Nix language is steep, the nixpkgs option space is vast, and finding one correct way to write something usually meant digging through many forum posts, often written for versions years old. Without a ready-made answer, you could only trial and error: change a line, build, wait a long time, read the error, change it again. That “harder to write than to use” cost offset most of NixOS’s advantages, so I gave up after a while and kept my daily drivers on Fedora.
This year the situation changed. AI coding assistants (tools like Codex or OpenCode) can read an entire configuration tree, understand nixpkgs’s option structure, generate and fix Nix code — and NixOS’s “declarative + verifiable” nature is exactly the form AI handles best: the configuration is a complete, machine-checkable declaration; nix flake check and the build tell you directly whether it is right; a broken change can be rolled back immediately. The division of labor between human and AI therefore becomes very clear: the human decides “what I want”; the AI translates “what I want” into correct Nix code and verifies it. The difficulty of writing configuration disappeared, and NixOS’s advantages — reproducibility, rollback, Git-managed multi-host setups — finally stand out again.
So we started this migration: move most of our computers from Fedora to NixOS, and put the whole system configuration (including user environment, secrets, and self-hosted services) into a Git repository managed declaratively. This series of posts records the migration and the maintenance that followed, as reference material for me and my friends.
Prerequisites#
- One or more x86_64 machines, previously running Fedora or another distribution (our machines are a Surface Pro 6, an AMD Strix Halo desktop, and a ThinkPad T460s)
- Basic familiarity with Linux and Git
- A usable AI coding assistant (a terminal agent such as Codex CLI or OpenCode; a web-based one works too)
- Willingness to spend some time reading the rest of this series
Scope of the Migration#
The migration covers three machines, all completed in under a month between early August and early September 2026:
| Host | Machine | Role | Status |
|---|---|---|---|
surface-pro-6 | Surface Pro 6 convertible | Daily driver (writing, development) | Installed from Fedora on 2026-08-06; 115 system generations |
halo | AMD Strix Halo desktop (“Halo”) | Local AI inference and gaming box | Enrolled 2026-08-20; 44 generations; headless remote desktop |
t460s | ThinkPad T460s laptop | Self-hosting server running with the lid closed | Installed 2026-08-31; 15 generations; about 18 self-hosted services |
A “generation” is a NixOS concept: every activation of a new configuration produces a rollback target. Across the three machines, 174 generations and more than 280 Git commits are the product of one month-plus of human-and-AI iteration.
The declarative coverage goes well beyond “the operating system itself”:
- System configuration: kernel, services, firewall, user accounts — managed by a single flake repository (
modules/holds shared policy,hosts/<host>/holds each machine’s hardware and host-specific settings); - User environment: the shell (Zsh + Oh My Posh), input method (Fcitx5 + Rime), desktops (KDE Plasma, Niri + Noctalia), terminal (WezTerm), editor (Neovim/LazyVim), fonts — all declared with Home Manager;
- Secrets: SSH keys, service passwords and so on are encrypted with SOPS inside Git; each machine decrypts them with its own host key, so plaintext never enters the repository or the Nix store;
- Self-hosted services: about 18 Docker/Compose services on t460s (Authelia, Headscale, Nextcloud, Immich, SearXNG, etc.) plus a Traefik/Cloudflared edge stack — rendered at boot into runtime configuration by our own
containerctltool from “service manifests + encrypted secrets + host inventories”; - Remote access: key-only SSH, Tailscale, self-hosted NetBird, KRDP/Sunshine desktop sharing, and an EDID-backed virtual output for headless Halo.
Some of this work was routine (installing the system, installing software); some was genuinely interesting engineering (the container configuration v2 migration, for example, went through a dozen-plus staged per-service cutover phases). Each topic gets its own post later in the series.
Why NixOS’s Advantages Only Hold Now#
Let me revisit NixOS’s core advantages and why “AI-maintained configuration” is what makes them usable for the first time:
- Reproducibility: the same flake builds an identical system on another machine (the same
flake.lockpins every dependency version). Maintaining such a repository used to require personally ensuring that every update was deliberate; now AI can review theflake.lockdiff and estimate rebuild cost (for example, before rebuilding the Linux Surface kernel on Surf, it reclaims old generations to free 50 GiB of disk). - Atomic switching and rollback: a
nixos-rebuild switcheither takes effect completely or not at all; a broken configuration can be reverted from the boot menu or with--rollback. AI can take bigger swings because “breaking it” is caught by the system itself — which is also why we could iterate 174 generations in a month. - Git as documentation: the README, the runbooks under
docs/, and the per-generation release notes are a “second brain” maintained jointly by human and AI. Before taking over maintenance of any machine, AI reads these documents and recovers the full context. - Machine-verifiable:
nix flake check, building, andtest/switchform a complete verification loop; AI never has to guess whether a configuration is right — it just runs it.
Point 3 is actually the decisive shift: the maintenance cost of a NixOS configuration repository used to be dominated by writing, and writing depended on human experience. Now that AI has driven the cost of writing down sharply, what remains — verification, recording, rollback — is exactly what NixOS does natively well.
Structure of This Series#
The remaining posts unfold in this order (the series has 11 posts; this is post 1):
- Why I chose NixOS again now (this post)
- Core concepts: declarative configuration, nixpkgs, flakes and
flake.lock, generations and rollback — a concept introduction for friends who have never used NixOS - Repository architecture: how one flake manages three machines — directory layout, the split between shared modules and host modules, the day-to-day change workflow, per-generation release notes
- Maintaining configuration with AI: we wrote the standard workflow as a “maintainer skill” for AI agents, including validation order, activation handoff, and failure/safety rules
- Migrating the Surface Pro 6: installing from Fedora, generating the hardware file, the long Linux Surface kernel build and its disk budget, post-boot verification
- Enrolling a new machine: the reusable installation guide (using T460s as the example), including closed-lid server mode and failure recovery
- The user environment: Home Manager, the shell, input method, dual Plasma/Niri desktops, and the Conky iteration saga
- Networking and remote access: key-only SSH, Tailscale/NetBird, KRDP/Sunshine, headless Halo with EDID
- Secrets management: SOPS + sops-nix, using each host’s own SSH key as its decryption identity
- Self-hosted services v2: the containerctl architecture, staged migration of about 18 services, the edge stack and the MebTTY web terminal
- Local AI on Halo: Ollama, the ROCm container q38rocm, local models for AI agents, plus Steam/Proton
Posts 5 through 11 cite documents and Git history that already exist in the repository. If you are someone who was also “scared off by NixOS before and wants to try again”, start with posts 2 and 3.
Related Posts#
- “Local Large Language Model (1): Deploy on Local or Server with ollama and LobeChat”: our old approach of running local LLMs in Docker on Fedora; post 11 contrasts it with the NixOS-native management
- “OpenClaw AI Assistant Setup Summary”: configuring the AI assistant itself — during this migration it moved from a Docker container to a native NixOS user service
- “Container Technology (1): Introduction to Container Concepts — Containerization, docker, docker-compose, Kubernetes / K8s”: background on the self-hosted services
