Building Dubnium: A Super Workstation With Modes

Building Dubnium: A Super Workstation With Modes

Building Dubnium: A Super Workstation With Modes

Dubnium is one NixOS machine that can be a workstation, a local AI node, an automation host, a secure remote access point, and the base for an experimental lab.

This is the first post in the Dubnium series. The later posts move from the host itself into the agentic control plane and scheduled agentic work.

It is closer to a personal distro than a homelab box: an opinionated system shape where each role has boundaries instead of consuming the whole machine. The flake defines 7 machine configurations (dubnium, technetium, wsl, headless, verify, container-host, installer), 17 NixOS modules, and a service registry that keeps every component explicitly governed.

Common scenarios

The most common Dubnium scenario is ordinary desktop work that turns into remote compute. Development at a desk, switch into compute mode, leave with a laptop and keep using local AI over Tailscale. The heavy models, runtimes, and GPU posture stay on the home machine.

The second common scenario is background work: automations, research collection, scheduled jobs, and bounded workflows that keep running on their own. The third is project-local development through dedicated shells — the project gets the tools it needs, the host stays clean.

Profiles and modes

The core distinction is between profile and mode:

Mode    = what the machine is doing right now
Profile = what the machine is capable of doing

Profiles define installed capability. Modes define runtime posture. Targets bridge the two — they expose systemd target surfaces without selecting concrete services.

flowchart TD P[Profiles / Capabilities\ngraphical, studio, ai, compute] M[Runtime Mode\ndesktop or compute] S[Explicit Services\nLLM server, scheduler, gateway, cluster] P --> M P --> S M --> S

The mode controller

modectl manages runtime transitions through a guard system. Switching from desktop to compute checks CPU load, memory headroom, active user jobs, audio workloads, and GPU release. Each guard can be bypassed per transition. The controller maintains state in /run/mode-controller and logs every transition to an append-only event log.

Three systemd slices — interactive, ai, and platform — enforce resource boundaries. In desktop mode AI gets a moderate CPU weight. In compute mode AI gets priority. A studio-local mode reweights aggressively toward interactive latency, cutting AI and platform weight for low-latency audio work.

Dual GPU architecture

The machine has two GPUs with distinct roles. One drives the display. The other handles AI inference in desktop mode. In compute mode, both GPUs are available for model serving with tensor parallelism, and the display GPU is released. CUDA_VISIBLE_DEVICES is set per-mode in the LLM service, so a mode switch changes GPU assignment at the service level.

LLM backends

Dubnium supports vLLM and llama.cpp, each with per-mode profiles. The desktop profile runs at a longer context length with batch processing on a single GPU. The compute profile uses both GPUs with tensor parallelism. The service binds to localhost by default — Tailscale exposure is opt-in — and runs inside ai.slice with systemd hardening.

AI provider layer

The AI surface connects to multiple backends: local Ollama, a local OpenAI-compatible endpoint, and cloud providers. An agentic assistant handles prompts, shell help, and coding tasks with configurable approval boundaries. Transcripts are off by default.

Declarative systems need a writable edge

Purely declarative configuration is excellent for servers. Development machines are messier — editors write state, CLIs update config, AI tools expect mutable provider files.

Dubnium handles this with configctl, which scaffolds writable overlay files like git/local.config, zsh/local.zsh, and nvim/local.lua into ~/.config/local/. These are created at build time with the right ownership. XDG environment variables keep mutable state out of the Nix store.

configctl also manages global tool layers — npm and pip packages — through init contracts that reconcile declared vs observed state with a plan-apply-verify cycle.

Service registry

dubctl manages services through a Nix-declared registry. Each service has named profiles that map to concrete NixOS options. Enabling n8n with the tailscale-serve profile sets the port, host binding, and Tailscale Serve HTTPS in one command. The registry writes a generated.nix that the host imports, keeping ad-hoc enablement reviewable alongside the flake.

The registry also covers capabilities (dotfiles integration, Laboratory cluster bootstrap), flake input management (install, remove, update inputs), and a scheduler API for inspecting and triggering local job schedules.

The control surface

Three tools, one job each:

  • modectl changes runtime posture. Guards validate safety before transitions.
  • dubctl manages persistent capability state: flake inputs, services, capabilities, schedules, and rebuilds.
  • configctl manages the writable edge through init contracts.

Each tool stays within its boundary.

Machine vs User

The system flake owns the host: modules, services, workloads, installer, AI integration, system policy. The dotfiles repo owns the user layer: Home Manager, Hyprland, Waybar, shell and editor tooling. Home Manager runs as a systemd user service so user units exist before dotfiles activation.

Reconstruction path

Dubnium deploys onto different machines without creating sacred artifacts. Portable system shape separates from hardware detection. Local AI bring-up is part of reconstruction — runtime enablement and model seeding belong in the rebuild story.

flowchart LR I[Installer] HW[Hardware Detection\nper-machine specifics] HC[Host Config\nshared system shape] UC[User Layer Adoption] NET[Private Network Rejoin] AI[Local AI Runtime +\nModel Seed Reconcile] SVC[Explicit Service Enablement] I --> HW --> HC --> UC --> NET --> AI --> SVC

The installer builds a custom ISO with hardware detection, AI model seeding, and optional sops-nix secrets. After install, mode-runtime-init initializes the state directories and the machine converges to its boot default mode.

The point

Dubnium is a machine that can do several serious jobs while keeping the ability to explain itself. Reproducibility is the harder discipline. That is where the design starts.

The next post, Building Dubnium: An Agentic Orchestrator, looks at how Dubnium separates inference, orchestration, memory, policy, and effectful execution.

References

Project

System

AI and agents

Automation

Access and environments