r/NixOS • u/zener79 • Mar 11 '26
I built a reproducible NixOS deployment system for a multi-PC school lab with no client internet access
Hi everyone,
I’m a teacher, and I’m responsible for a school computer lab with 30 student PCs.
In this kind of environment, reproducibility matters a lot. If even a few machines drift over time, maintenance becomes messy very quickly. Reinstalling systems by hand is slow, error-prone, and hard to repeat consistently even with Ansible.
So over the last month, I built this:
https://github.com/giovantenne/nixos-lab
I’m still a Nix beginner, so this was also a big learning project for me. A lot of the heavy lifting in the early phase came from working with Claude, which helped me get from “I kind of understand the pieces” to a setup that I can actually use and maintain in the real world.
The main challenge was this:
the lab PCs do not have internet access until a user logs into the school network.
That constraint made installation, updates, and recovery much harder than they should have been. So I built a local-first NixOS workflow centered around one master machine (pc99) that acts as the controller for the whole lab.
The setup is built around 31 machines: 1 controller (pc99) + 30 student workstations (pc01–pc30).
It currently uses:
- Nix flakes as the source of truth
- UEFI PXE/netboot for the initial installation only (I didn't want to boot every single PC from USB)
- Harmonia as a local binary cache
- Colmena for multi-machine orchestration
- Disko for declarative partitioning
- Btrfs for snapshots on the student machines
One networking detail that mattered a lot in my case is that the computers have both a DHCP address and a static lab IP. The DHCP address is used to integrate with the school network, while the static IP is used for the internal lab network.
The practical result is that I can now reinstall the whole lab in less than 20 minutes.
What I like most is not just the reinstall speed, but the fact that maintenance is now much more predictable:
- one declarative source of truth
- consistent configuration across all machines
- offline-friendly installation via a local cache
- easier recovery when a machine needs to be rebuilt
I also added two features that are especially useful in a school lab:
- student home directories are reset to a clean state
- snapshots are preserved for recovery
This means the machines stay clean for the next class, while still keeping a recovery path when needed.
The UEFI PXE boot — which was by far the hardest part to build and test — is only used for the initial installation of the workstations. After that, the machines are maintained declaratively through the NixOS configuration, the local binary cache, and multi-machine deployment tools (Colmena).
For experienced NixOS users this may not be especially advanced, but for me it was a big milestone: turning a difficult-to-maintain school lab into something reproducible, recoverable, fun and much less stressful to manage.
I’m sharing it in case it’s useful to anyone managing classrooms, training rooms, public labs, libraries, or other multi-PC environments.
Feedback, criticism, and suggestions are very welcome.
45
u/jerrygreenest1 Mar 11 '26
Giving your students linux is already a saints work, but giving them nix is god-like
27
15
u/VisualSome9977 Mar 11 '26
is there any infrastructure in place for the students to upload contents of their home directory somewhere permanent? You say the home directories get wiped, but I assume students have some things they want to preserve, right? So I am just curious if/how that exists. Really really cool idea though, I wish that the people managing my old school lab had something like this!
17
u/zener79 Mar 11 '26
They are required to use Git for programming, which is a win-win:
they learn a solid workflow, and the PC stays clean :-)
For other types of documents, they use Google Drive (the school uses Google for Education, and each student has an account).6
u/VisualSome9977 Mar 11 '26
I see, that's nice. Do you manage your own centralised git server for them, or do they upload to GitHub or some other alternative?
9
5
u/philosophical_lens Mar 11 '26
Thanks for sharing! I'm curious to learn more about your snapshot and recovery implementation with btrfs please.
8
u/zener79 Mar 11 '26
Thanks!
The Btrfs part is actually pretty simple in this project.The disk layout is declared with Disko, and on the student machines (put also on PC99) I create three Btrfs subvolumes:
- u/root mounted at /
- u/home-informatica mounted at /home/informatica
- u/snapshots mounted at /var/lib/home-snapshots
The interesting part is modules/home-reset.nix. At activation time, I generate a clean template for the informatica user under /var/lib/home-template/informatica, including Git config, XDG dirs, and preloaded VS Code extensions. Then, on every boot, a oneshot systemd service called home-reset runs before the display manager and resets /home/informatica from that template.
Before replacing the home, that reset flow keeps snapshots of the previous state in /var/lib/home-snapshots, and the repo currently keeps the last 5 versions there. The idea is: every class starts from a clean student environment, but I still have a practical recovery path if I need to recover files from a previous session.
If you want to look at the code, the main places are:
- disko-uefi.nix for the Btrfs subvolumes
- modules/home-reset.nix for the template creation + boot-time reset service
- scripts/home-reset.sh for the actual reset/snapshot logic
5
7
u/artnoi43 Mar 11 '26
Awesome. But damn I’d have made the control machine pc0 and not pc99 lol
8
u/zener79 Mar 11 '26
Yes, you're right! It bothers me too 😂
But the PC number will become the last octet of the static IP address, and it can’t be 10.22.9.0.
So I used the last available two-digit number (for simplicity) 10.22.9.99
Terrible choice!
3
u/landonr99 Mar 11 '26
What do students do on NixOS? Also curious what DE you have them using
9
u/zener79 Mar 11 '26
They mostly use VS Code, Chromium, Docker, and Git. I chose GNOME as the desktop environment since they are already familiar with it
2
u/4DBug Mar 11 '26
may I ask what grade(s) you teach?
3
u/zener79 Mar 11 '26
I teach students in the final year of high school in Italy, so they’re usually around 18–19 years old.
2
1
1
u/4DBug Mar 11 '26
This is wonderful I would love to be able to manage something like that.. I love nix
2
1
1
1
u/LippyGrips Mar 14 '26
You're already using btrfs. Can't you just keep one machine up to date and send fresh snapshots to the rest? It's been a while since I used btrfs, but that's how I'd do it with zfs.
1
u/zener79 Mar 14 '26
Thanks for the suggestion! btrfs send/receive is great, but since I'm already using Harmonia as a local binary cache and Colmena for deployment, it's actually redundant.
My current stack already avoids downloading from the internet (only the master node does) and handles the activation of new generations and bootloader updates atomically on all 30 machines. Using Btrfs for the /nix/store would be a bit more manual and rigid if I have slight hardware variations.
I still use Btrfs snapshots, though! I use them to 'reset' the students' /home at every reboot. It's the perfect combo.
1
u/LippyGrips Mar 14 '26
I actually meant deploying the entire system this way, not just the Nix store. But it sounds like you already have a good setup that works, which is the important thing.
1
u/zener79 Mar 14 '26 edited Mar 14 '26
I totally get it. That's basically a modern, incremental version of disk imaging, similar to what I used to do with Clonezilla (and then Ansible to manage the lab) in the past.
However, with Nix/Colmena approach I'm basically trading the raw speed of block transfers for the surgical precision of Nix deployments
1
51
u/_zonni Mar 11 '26
Good job, nix definitely serves this purpose the best
One question, have you considered applying impermanence to don't have unnecessary files on the PCs?