- PowerShell 50%
- Nix 47.6%
- AppleScript 1.7%
- Batchfile 0.7%
Add read-only Windows PowerShell collectors under scripts/hardware and scripts/software to inventory Atlas and Zephyr before migrating to NixOS. Each writes JSON and summary reports into a Git-ignored reports/ directory and includes offline fixture tests. |
||
|---|---|---|
| modules | ||
| packages | ||
| scripts | ||
| .envrc | ||
| .gitignore | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
Rose's NixOS configuration
| Host | Role | Physical architecture | UTM test configuration |
|---|---|---|---|
zephyr |
Laptop | x86_64-linux |
zephyr-utm, aarch64-linux |
atlas |
Desktop | x86_64-linux |
atlas-utm, aarch64-linux |
NixOS 26.05, wrapped Niri and Noctalia, Home Manager, and the rose account are shared by both hosts.
Zephyr adds battery monitoring and lid handling. UTM variants use virtual hardware
and a disposable test password. Noctalia Greeter opens with Rose and Niri selected.
Real hardware settings
never flow into the UTM variants.
Maintenance shell
direnv allow
check
format
write-flake
The shell follows devenv's flake-parts guide.
The .envrc uses its devenv-root override and watches the module tree, including
directories so adding a new feature reloads the environment. To enter manually:
mkdir -p .devenv
printf %s "$PWD" > .devenv/root
nix develop --override-input devenv-root "file+file://$PWD/.devenv/root"
check evaluates all four NixOS systems and the local flake outputs, and builds
the generated-flake consistency check. It uses
--impure so devenv can resolve the working directory, as required by its
flake-parts integration.
Dendritic structure
Every Nix file under modules/ is a flake-parts module, recursively loaded by
import-tree. A feature can contribute to
NixOS, Home Manager, development shells, and flake inputs in the same file.
Typed deferredModule options hold the shared profiles; hosts is a typed host
inventory. Modules merge by feature, and host assembly imports the relevant role.
Inputs are captured by lexical scope; no specialArgs plumbing is needed.
This follows the dendritic pattern.
Following Vimjoyer's wrapped flake-parts guide,
nix-wrapper-modules builds
Niri and Noctalia with their settings embedded in packages. Linux outputs
packages.<system>.niri and packages.<system>.noctalia-shell are reusable outside
these hosts. NixOS installs the configured Niri session; Home Manager installs
Rose's configured shell and applications. Niri starts Noctalia directly, which
provides the bar, launcher, notifications, control center and lock screen.
Noctalia 4.7.6 is pinned through NixOS 26.05 and matches the guide's Quickshell
wrapper; newer Noctalia releases use a different format.
Noctalia Greeter 1.6.0 uses its
upstream NixOS module, with the input declared alongside its feature. greetd starts
the bundled greeter session; Rose and Niri are selected by default. Both physical
hosts and UTM guests require login. Greeter settings live in
modules/features/greeter.nix; its built-in Noctalia scheme works independently
of the desktop shell. Appearance sync requires administrator authentication.
modules/flake.nix: flake generation, nixpkgs pin, supported development systems.modules/hosts.nix: typed profiles, host inventory, physical/UTM assembly.modules/hosts/{zephyr,atlas}.nix: each host's role and physical hardware.modules/features/: shared OS and Home Manager features.modules/features/{niri,noctalia}.nix: wrapped desktop packages and integration.modules/features/greeter.nix: Noctalia Greeter, greetd and declarative login defaults.- Application features own their Home Manager settings, OS services and package outputs.
packages/: vendor binary packaging, called by the feature that owns each app.modules/wrappers.nix: the wrapper library input.modules/virtualisation/utm.nix: virtual hardware and bootable image outputs.modules/development.nix: devenv and its input declarations.
flake.nix is generated by flake-file.
Edit flake-file.inputs in the module that owns a dependency, then regenerate:
nix run .#write-flake
nix flake lock
git add flake.nix flake.lock modules
New inputs must first exist in the generated flake before their values can be
used during evaluation. When bootstrapping a new dependency, declare and generate
its input first, then add references to inputs.<name>. Git flakes only include
tracked files: run git add when adding a module.
UTM on Apple Silicon
Build both complete, bootable QCOW2 images. On macOS this needs an
aarch64-linux remote builder; the configured OrbStack builder can provide it.
Image creation permits QEMU's software fallback because OrbStack does not expose
nested KVM. The resulting guests use Apple's hardware acceleration in UTM.
The images include this flake at /etc/nixos.
nix build .#packages.aarch64-linux.zephyr-utm -o result-zephyr
nix build .#packages.aarch64-linux.atlas-utm -o result-atlas
osascript scripts/setup-utm.applescript \
"$(realpath result-zephyr/zephyr-utm.qcow2)" \
"$(realpath result-atlas/atlas-utm.qcow2)"
The script creates two ARM64 QEMU VMs with UEFI, VirtIO disks, VirGL/SPICE graphics, four vCPUs, and 32 GiB disks. Zephyr gets 4 GiB RAM; Atlas gets 6 GiB. It preserves existing disks and refreshes display settings for stopped VMs with the same name. UTM copies images into writable VM disks; rebuilding a Nix image does not replace an existing VM's disk.
Retina mode and automatic resizing are enabled in UTM. The UTM NixOS profile
runs both the system SPICE daemon and its session agent, and sets Niri's virtual
output to 2× scale. Leave the output mode automatic so window resizing selects
the new preferred VirtIO mode. The greeter also uses 2× scale in UTM.
Physical hosts do not inherit these display settings.
Ghostty and the fallback Alacritty use software rendering in UTM to avoid blank windows with VirGL;
physical hosts retain accelerated rendering.
Zed uses software Vulkan in UTM, with its emulated-GPU warning disabled. This is
suitable for configuration testing; editor performance needs a physical GPU.
mpv uses its compatible OpenGL renderer in UTM; physical hosts use gpu-next.
Start a guest in UTM. The test-only login is rose / rose, with passwordless
sudo. SSH forwards bind only to the Mac's loopback interface:
ssh -F /dev/null -o PubkeyAuthentication=no -p 2222 rose@127.0.0.1 # Zephyr
ssh -F /dev/null -o PubkeyAuthentication=no -p 2223 rose@127.0.0.1 # Atlas
These commands bypass local SSH customizations for the disposable guests.
On a Mac keyboard, Super is Command:
| Shortcut | Action |
|---|---|
| Super+T or Super+Return | Ghostty with Nushell |
| Super+D | Noctalia launcher |
| Super+S | Control center |
| Super+Alt+L | Lock screen |
| Super+Shift+E | Session menu |
| Super+O | Niri overview |
| Super+H/J/K/L or arrows | Focus windows/columns |
| Super+1…9 | Switch workspace |
Edit modules/features/niri.nix for compositor settings and shortcuts, and
modules/features/noctalia.nix for shell settings. Noctalia's configured settings
are read-only; GUI adjustments are temporary. Use dump-noctalia-shell in the
running session to export settings for incorporation into Nix. Home Manager
continues to manage Rose's applications, zsh, Git and direnv.
Applications
Both hosts share the following declarative features. Proprietary packages are
enabled explicitly through allowUnfree. Vendor packages absent from Nixpkgs
have pinned versions and content hashes in packages/; their feature exports
them as packages.<system>.<name>.
| Feature | Configuration |
|---|---|
| Zed and VSCodium | Language servers, formatters, debuggers, Copilot and Codex; see Development. Nerd Font, telemetry off, Nushell terminals. VSCodium is the default editor. |
| Helium and Opera GX | Helium is the default browser. Opera GX is installed on both x86 hosts. |
| Ghostty, Nushell, Starship | Ghostty is the Niri terminal shortcut, with a black background and JetBrains Mono Nerd Font. Starship and direnv integrate with Nushell and zsh. zsh remains the login shell for POSIX session setup. |
| Git, GitHub CLI and Forgejo CLI | Main branches, fast-forward pulls, prune fetched refs, SSH transport in gh; the Forgejo command is fj. |
| 1Password | Desktop app starts with the graphical session; CLI uses the NixOS integration wrapper. SSH uses ~/.1password/agent.sock; Git can sign through op-ssh-sign. Helium and Opera are listed as additional trusted browsers. |
| YubiKey | ykman, Yubico Authenticator, personalization and PIV tools, PC/SC service, and udev rules. No key is reset or enrolled and no new login requirement is imposed. |
| Containers | Rootful Podman API at /run/podman/podman.sock, Docker socket compatibility, docker command, Compose, and container DNS. |
| Communication | Discord, Teams for Linux, Thunderbird with a Rose profile, remote mail images blocked, and default mail handlers. |
| Media | Spotify and mpv. mpv resumes playback and owns common audio/video file associations. |
| Steam | Both x86 hosts have Steam, GE-Proton and Protontricks with 32-bit graphics/audio support. |
Atlas additionally installs Firestorm, CurseForge and Heroic Games Launcher,
registers the Firestorm/CurseForge URL handlers, and adds an Overwatch 2 launcher
for Steam app 2357570. Sign into Epic in Heroic to access the account library
and choose which games to download. Firestorm's current vendor release requires
an AVX2-capable CPU and runs through Xwayland. CurseForge
includes an FHS runtime with Java 17/21 for Minecraft. Use CurseForge's Minecraft
page to install a modpack and sign into your Microsoft account.
In Steam, install Overwatch and select GE-Proton under Properties → Compatibility → Force the use of a specific Steam Play compatibility tool. Steam manages game files outside the Nix store. A Battle.net account is required; gameplay and GPU compatibility need testing on the physical desktop.
Rose's selected games are Overwatch 2, Second Life through Firestorm, Minecraft Java with CurseForge, Thomas & Friends: Wonders of Sodor, and Waterpark Simulator. The two latter games can be downloaded from the existing Steam account. Other Steam and Epic games remain in their account libraries until selected for installation; Nix installs the launchers and does not download games or store account credentials.
The ARM64 UTM guests install native Helium, Zed, VSCodium, Ghostty, 1Password,
Teams, Thunderbird and CLI tools. Discord uses a web launcher. Spotify uses the
native spotify_player terminal client, which requires Spotify Premium; Helium
does not provide Widevine DRM for Spotify's web player. Steam, Opera GX,
Firestorm, CurseForge, Heroic and Overwatch are omitted on ARM64 because these
packages or games ship x86 binaries. UTM does not emulate those applications.
After your first login:
- Sign into 1Password. In Settings → Developer, enable its SSH agent and CLI integration; enable system authentication in Settings → Security. Install the 1Password browser extension if desired. Account credentials stay out of Nix.
- Set your Git name/email and SSH signing public key before enabling automatic
commit signing. Authenticate
gh auth loginandfj auth logininteractively. - Add mail accounts in Thunderbird and sign into Discord, Teams and Spotify.
- Forward a YubiKey through UTM's USB menu when testing hardware-backed features.
Rose's membership in the podman group grants access to rootful containers and
therefore root-equivalent access. CONTAINER_HOST and DOCKER_HOST select the
system socket, so podman, docker and docker compose use the same rootful
engine. sudo podman also accesses that storage locally. Rootless socket startup
is disabled; containers are not pruned automatically.
To rebuild inside a guest after updating /etc/nixos:
cd /etc/nixos
sudo nixos-rebuild switch --flake .#zephyr-utm # or atlas-utm
Development
modules/features/development/ contains dendritic features: each language owns
its Home Manager tools and both editors' settings. These apply to both hosts
and their ARM64 UTM variants. VSCodium extensions come from pinned Nixpkgs or
hash-pinned publisher VSIXs in packages/editor-extensions.json. Zed installs
its configured extensions from its registry on first launch; their versions
are managed by Zed, while configured language-server binaries are pinned by Nix.
Zed's built-in Copilot client manages its own native server; nix-ld provides
the Linux loader and libraries it needs.
GNOME Keyring unlocks through the greeter; VSCodium explicitly uses its
libsecret backend to store credentials under Niri.
| Area | Included support |
|---|---|
| Nix / devenv | nixd, nixfmt, devenv CLI, automatic direnv loading in Zed and the direnv VSCodium extension. Approve each project's .envrc with direnv allow. |
| C# / .NET / ASP.NET | .NET 8 and 10 SDKs, ASP.NET runtimes, Entity Framework CLI, C# analysis/formatting. VSCodium uses free-csharp with Roslyn, Razor and NetCoreDbg; Zed uses csharp-ls. |
| Java | JDK 21, Maven, Gradle, JDTLS; VSCodium adds Java debugging, test discovery and project management. |
| Python | Python, uv, basedpyright, Ruff formatting/import sorting and VSCodium debugpy. Select the project's .venv interpreter in the editor. |
| Web / Bun | Bun, Node 24, TypeScript, HTML/CSS, JSX/TSX, Emmet, ESLint, Prettier and Tailwind IntelliSense; VSCodium adds Bun tests/debugging and the JS debugger. |
| Containers | Dockerfile/Containerfile and Compose support, with VSCodium Container Tools using the rootful Podman socket. |
| Databases | SQLTools with PostgreSQL, MySQL/MariaDB and SQL Server drivers, SQLite editor, DBeaver for queries and ER diagrams, sqlite3, psql, mongosh, and Zed SQL formatting. No database servers start automatically. |
| Coursework | PHP/Composer/Intelephense, Xdebug with an explicit trigger, REST Client, local PlantUML/Graphviz, draw.io, XML, YAML and TOML support. |
| Mobile / Unity | Node/Bun, Watchman and Android adb for React Native/Expo. Unity Hub is available on x86 hosts. |
| AI | Zed Copilot predictions and Codex ACP agent; VSCodium Copilot/Chat and Codex extension; codex CLI in either terminal. |
nixd uses this flake's pinned Nixpkgs and nixfmt. Both editors expose the current
host's NixOS and integrated Home Manager options, plus flake-parts and per-system
options (including devenv). These option expressions read the editable flake at
/etc/nixos; keep it updated when changing this configuration. For another
configuration checkout, override the expressions in that workspace's editor
settings. Zed explicitly disables nil. Flake-parts' debug outputs expose the
option declarations required by nixd, as described in its
configuration guide.
The Thomas More Geel programme was checked on 2026-10-11. Its public descriptions include SQL and document databases, UML, C#/Entity Framework, .NET, React/Vite, backend JavaScript, React Native/Expo and PHP/Unity challenges. They do not specify every SDK, database vendor or Unity version. Use the versions and project dependencies provided by your lecturer; the public catalogue is not a complete lab image.
Install React, Vite, Tailwind, Expo, test runners, ESLint/Prettier plugins and
@types/bun in the project, using its lockfile. Keep .NET's global.json and
project-local dotnet-ef tool manifest aligned with its target framework.
Use uv sync/a project venv for Python dependencies. The existing repository
devenv remains a small shell for maintaining this Nix configuration.
For SQL exercises, create a connection in SQLTools or DBeaver with your own
credentials. DBeaver can download the selected database's JDBC driver on first
connection. Run databases through a project's devenv services or Podman Compose;
SQL Server Linux images require an x86 machine, so use a remote server from UTM.
Document-database exercises can use mongosh with a course or project MongoDB
server. REST Client reads .http files; keep tokens in untracked environment files.
For PHP debugging, start VSCodium's Xdebug listener and run
XDEBUG_TRIGGER=1 php your-file.php; Xdebug connects to local port 9003.
For Expo, use Expo Go on a physical phone, or the web target while in UTM.
Forward an Android device's USB connection and use adb reverse tcp:8081 tcp:8081
with bunx expo start --localhost for USB development. Native Android builds
need a project-specific Android SDK/NDK; iOS builds need macOS/Xcode or EAS.
Unity Hub requires sign-in, licence activation and the course's Editor version.
Unity's Linux Editor has no ARM64 build, so it is omitted from UTM.
Windows-only desktop .NET assignments need a Windows environment.
Sign into GitHub Copilot separately in each editor and into Codex with your
ChatGPT account or an API key. Zed's Agent menu includes the declarative Codex
ACP agent. In VSCodium, use Codex: Open Codex Sidebar and the Copilot status
menu. The VSCodium Copilot guide
requires product.json authentication/chat metadata; Home Manager provides it.
AI credentials, subscriptions and project trust are never enabled automatically.
Copilot Chat compatibility follows the pinned VSCodium/extension versions;
authenticated requests require your account and have not been exercised here.
See OpenAI's IDE guide and
Zed's external agent guide.
Physical machines
The x86 hosts are configuration scaffolds until their actual hardware is known.
The provisional layout is UEFI, an ext4 root labelled nixos, and a FAT EFI
partition labelled BOOT. No disks are partitioned automatically.
Start on Windows with the hardware collector.
Run it elevated on each physical machine, choosing atlas for the desktop and
zephyr for the laptop, then return the two report ZIPs. It captures hardware
IDs, firmware, storage layout, displays and laptop details without changing the
machine. The guide also covers the remaining Linux live-USB checks.
Use the Windows program inventory to export registered applications, Store packages, Scoop/Chocolatey packages and Steam game manifests as CSV, JSON and a report ZIP before migrating.
During installation, after mounting the intended Linux filesystems under /mnt,
run nixos-generate-config --root /mnt --show-hardware-config on the target.
Put those hardware settings inside the hardware module in its host
file, replacing the provisional filesystem defaults as needed. Keep local Nix
files as top-level flake-parts modules; wrap generated hardware settings in
hosts.<name>.hardware = { ... }; rather than copying a bare NixOS module into
the auto-imported tree. Review CPU, GPU, storage, networking, and any encryption
requirements for the actual machine. Set Rose's password during installation;
the VM password is confined to the UTM profile.
Build on an x86 Linux machine or builder before installing:
nix build .#nixosConfigurations.zephyr.config.system.build.toplevel
nix build .#nixosConfigurations.atlas.config.system.build.toplevel