- Nix 79%
- Just 14.4%
- Shell 6.2%
- Dockerfile 0.4%
| home | ||
| hosts | ||
| justfiles | ||
| manual | ||
| modules | ||
| packages | ||
| potential | ||
| scripts | ||
| secrets | ||
| users | ||
| .gitignore | ||
| .sops.yaml | ||
| CLAUDE.md | ||
| flake.lock | ||
| flake.nix | ||
| Justfile | ||
| QWEN.md | ||
| README.md | ||
NixOS Configuration
Multi-host NixOS configuration with modular structure.
Commands
Use just to manage your NixOS configuration. Run just or just --list to see all available recipes.
Common recipes:
just check— Validate flake syntaxjust deploy— Deploy current configuration (auto-detects specialisation)just deploy igpu— Deploy and activate a specific specialisationjust switch-spec igpu— Switch specialisation without rebuildingjust plasma-capture— Capture current KDE Plasma settings to home/plasma.nixjust diff-last-update— Show package changes from the last updatejust generations— List system generations (before rollback)just gc— Run garbage collectionjust firmware-update— Update firmware via LVFS
Timer management:
just restic-snapshots— List restic backupsjust restic-unlock— Remove stale restic locksjust restic-logs— Show restic backup logsjust restic-last-run— Show last restic backup run detailsjust restic-run-now— Trigger restic backup immediatelyjust nixos-gc-last-run— Show last GC run detailsjust nixos-gc-run-now— Trigger GC immediatelyjust nixos-auto-update-last-run— Show last auto-update run detailsjust nixos-auto-update-run-now— Trigger auto-update immediately
Directory Structure
nixos-config/
├── flake.nix # Flake definition (inputs & host configs)
├── flake.lock # Locked dependency versions
├── .sops.yaml # SOPS age key configuration for secrets
│
├── home/
│ ├── nimmo.nix # Home-manager config for nimmo (all hosts)
│ └── plasma.nix # Declarative KDE Plasma settings (via plasma-manager)
│
├── hosts/
│ ├── common/ # Shared across ALL hosts
│ │ ├── default.nix # Bootloader, networking, imports shared modules
│ │ ├── nix-settings.nix # Flakes, build parallelism, caches
│ │ └── locale.nix # Timezone, locale, keyboard layout
│ │
│ ├── electra/ # Framework 16 laptop
│ │ ├── default.nix # Unified config: base=battery, specialisations=igpu,dgpu
│ │ ├── hardware.nix # Host-specific hardware imports (base)
│ │ ├── hardware-dgpu.nix # NVIDIA/AMD Prime offload (dgpu specialisation)
│ │ └── framework-16.nix # AMD GPU, fingerprint, PipeWire, zram, Framework tools
│ │
│ ├── lena/ # Lenovo Ideapad 5 2-in-1 (Gen 9)
│ │ ├── default.nix # Tablet mode, fingerprint, touchscreen
│ │ ├── disko.nix # Btrfs partitioning layout
│ │ └── hardware-configuration.nix # Auto-generated hardware config
│ │
│
├── modules/ # Reusable feature modules
│ ├── common/
│ │ ├── default-config.nix # Portability options (user, email, paths)
│ │ └── sops-host.nix # sops-nix key source (host SSH key)
│ ├── boot/
│ │ └── silent-boot.nix # Plymouth splash, quiet kernel parameters
│ ├── desktop/
│ │ ├── plasma.nix # KDE Plasma 6 desktop environment
│ │ ├── apps.nix # Desktop applications (Kate, LibreOffice, VLC, etc.)
│ │ └── fonts.nix # Font packages and fontconfig defaults (desktop only)
│ ├── hardware/
│ │ ├── bluetooth.nix # Bluetooth with experimental features
│ │ ├── printing.nix # CUPS with Brother printer drivers, Avahi discovery
│ │ ├── removable-storage.nix # udisks2, NTFS support, polkit mount rules
│ │ └── expansion-card-mount.nix # 1TB expansion card automount (electra only)
│ ├── maintenance/
│ │ ├── garbage-collection.nix # Daily cleanup (3-day age limit)
│ │ └── btrfs-maintenance.nix # Monthly btrfs scrub (all hosts)
│ ├── networking/
│ │ └── wifi-networks.nix # WiFi network definitions (home + other known networks)
│ ├── power/
│ │ ├── auto-power-profile.nix # Automatic power profile switching
│ │ └── battery-mode.nix # Locked power-saver + iGPU runtime PM (battery spec)
│ ├── profiles/
│ │ ├── gaming.nix # Steam, Gamemode, Discord, MangoHUD, powertop (enable opt)
│ │ ├── ai-tools.nix # Claude Code, Qwen Code, desktop launcher (enable opt)
│ │ ├── ai-development.nix # ai-tools.nix + Ollama service (electra)
│ │ ├── maker.nix # Cura, OpenSCAD (3D printing/CAD) (enable opt)
│ │ └── server-base.nix # Common server CLI tools and SSH config (unused)
│ ├── services/
│ │ ├── nixos-auto-update.nix # Daily auto-update with rollback
│ │ ├── btrbk-home.nix # Hourly btrfs snapshots of /home (electra)
│ │ ├── ollama.nix # AMD Ollama + Open WebUI (electra)
│ │ ├── ollama-common.nix # Shared ollama user/group definition
│ │ ├── ollama-nvidia.nix # NVIDIA Ollama supplement (dgpu only)
│ │ ├── ollama-rocm.nix # AMD ROCm Ollama + Open WebUI (unused)
│ │ └── restic-backup.nix # Automated backups every 6 hours (sops-nix secrets)
│ └── virtualization/
│ ├── docker.nix # Base Docker with Btrfs
│ ├── docker-amd.nix # Docker with AMD GPU (ROCm) support
│ └── docker-nvidia.nix # Docker with NVIDIA Container Toolkit
│
├── packages/
│ └── system.nix # System-wide packages (all users, all hosts)
│
├── users/
│ ├── nimmo.nix # Admin user account definition
│ └── claire.nix # Standard user (lena only, no sudo)
│
├── secrets/
│ ├── secrets.yaml # Encrypted secrets (sops-nix, age-encrypted)
│ └── README.md # Secrets management documentation
│
├── scripts/
│ └── check-flake.sh # Container-based flake validation (podman fallback)
│
└── manual/ # NixOS training manual (learning path)
├── README.md # Start here for the learning path index
├── 01-configuration-structure.md # How this repo is organized
├── 02-workflows.md # Step-by-step common tasks
├── 03-host-configurations.md # Multi-host design decisions
├── 04-specialisations.md # Electra's three boot tiers
├── 05-package-management.md # Installing and finding software
├── 06-secrets-management.md # sops-nix encrypted secrets
├── 07-troubleshooting.md # Debugging and recovery
├── 08-quick-reference.md # Command cheat sheet
├── 09-nix-language.md # Nix syntax and data types
├── 10-declarative-configuration.md # Why NixOS is declarative
├── 11-flakes.md # Flake structure and reproducibility
├── 12-modules.md # Module system deep dive
└── 13-specialargs.md # How flake inputs reach modules
How It All Fits Together
Understanding the import chain is key to knowing where to make changes. Each host pulls in only what it needs:
flake.nix
└── hosts/electra/default.nix (or lena)
├── hosts/common/default.nix (shared across ALL hosts)
│ ├── nix-settings.nix
│ ├── locale.nix
│ ├── modules/common/default-config.nix
│ ├── modules/common/sops-host.nix
│ ├── modules/maintenance/garbage-collection.nix
│ └── modules/maintenance/btrfs-maintenance.nix
├── hosts/common/desktop.nix (desktop hosts only: electra, lena)
│ ├── modules/desktop/fonts.nix
│ ├── modules/hardware/printing.nix
│ └── modules/hardware/removable-storage.nix
├── hardware-configuration.nix
├── hardware.nix (imports framework-16.nix)
├── framework-16.nix (AMD GPU, fingerprint, PipeWire, zram)
├── modules/boot/silent-boot.nix
├── modules/desktop/plasma.nix
├── modules/desktop/apps.nix
├── modules/power/battery-mode.nix
├── modules/hardware/bluetooth.nix
├── modules/hardware/expansion-card-mount.nix
├── modules/services/restic-backup.nix
├── modules/services/btrbk-home.nix
├── modules/services/nixos-auto-update.nix
├── modules/networking/wifi-networks.nix
├── modules/profiles/ai-development.nix
│ ├── modules/profiles/ai-tools.nix
│ └── modules/services/ollama.nix
├── modules/profiles/maker.nix
├── modules/virtualization/docker-amd.nix
├── packages/system.nix
├── users/nimmo.nix
├── specialisation.igpu.configuration:
│ ├── modules/power/auto-power-profile.nix
│ ├── modules/profiles/gaming.nix
│ └── modules/profiles/maker.nix
└── specialisation.dgpu.configuration:
├── hardware-dgpu.nix (NVIDIA/AMD Prime offload)
├── modules/services/ollama-nvidia.nix
├── modules/virtualization/docker-nvidia.nix
├── modules/virtualization/docker-amd.nix
├── modules/power/auto-power-profile.nix
└── modules/profiles/gaming.nix
This means: if you want to change something for all hosts, edit hosts/common/. If you want to change something for electra only, edit hosts/electra/default.nix. If you want to change something for the dgpu specialisation only, edit hosts/electra/default.nix under specialisation.dgpu.configuration.
Home-Manager Integration
Home-manager manages user-level configuration declaratively across all hosts. It's integrated directly into the NixOS configuration (not standalone).
What's Managed by Home-Manager
User Packages (via capability profiles and home-manager):
- AI tools (Claude Code, Qwen Code) — via
modules/profiles/ai-tools.nix - Gaming packages (Discord, MangoHUD, powertop) — via
modules/profiles/gaming.nixon electra - 3D printing/CAD (Cura, OpenSCAD) — via
modules/profiles/maker.nix - Desktop apps (Element, Trilium, etc.) — via
modules/desktop/apps.nix - Conditional packages (only on unstable channel): opencode-desktop, whosthere
Shell Environment (programs.bash):
- Bash-it framework with rjorgenson theme
- Custom
nixos-rebuild-autofunction (rebuilds and reactivates current specialisation) - History search with up/down arrows
- Shell initialization
Development Tools:
- Git configuration (unified email across hosts)
- Direnv with nix-direnv integration
System Monitoring:
- btop with ROCm/libdrm wrapper for GPU monitoring
- Shows gpu0 and gpu1 slots; btop silently omits any GPU it cannot detect
Firefox (programs.firefox):
- Declarative default profile with privacy/security hardening
- Extensions from NUR: Bitwarden, Consent-O-Matic
- Full telemetry/tracking/study opt-out, HTTPS-only mode, Pocket disabled
Desktop Optimization:
- Autostart applications with delays (Nextcloud delayed 15s)
- Disabled applications (Discover update notifier)
- Faster login performance
Configuration Files
home/nimmo.nix- Main home-manager configuration~/.bash_it- Symlinked from Nix store (managed by bash-it flake input)- Firefox extensions - Declarative via NUR (
inputs.nur); manually-managed extensions: Floccus, Karakeep
KDE Plasma Configuration (plasma-manager)
KDE Plasma settings are declaratively managed via home/plasma.nix using the plasma-manager flake input. This file is generated by capturing the current Plasma state:
just plasma-capture
This captures themes, keybindings, window behaviour, panel configuration, and other Plasma settings into a Nix file that is applied on rebuild. To make Plasma changes:
- Adjust settings via the KDE System Settings GUI
- Run
just plasma-captureto capture the changes - Review the diff, rebuild, commit
What's NOT Managed by Home-Manager
- Application-specific configurations (managed via GUI)
- Runtime user data and state
Updating User Configuration
Edit home/nimmo.nix and rebuild:
# Edit configuration
vim home/nimmo.nix
# Apply changes
nixos-rebuild-auto
Changes to home-manager configuration take effect immediately on rebuild - no reboot required.
Common Tasks
Check Configuration Syntax
Validate the flake without building. Note: New untracked files must be staged with git add first, as Nix flakes only see files tracked by git.
git add <new-files> # If you created new files
nix flake check
Test Configuration
Build and activate without adding to boot menu (reverts on reboot):
sudo nixos-rebuild test --flake .#electra
Deploy Configuration
Build, activate, and add to boot menu:
# Auto-detect hostname and reactivate current specialisation (recommended)
nixos-rebuild-auto
# Or specify explicitly
sudo nixos-rebuild switch --flake .#electra
sudo nixos-rebuild switch --flake .#lena
The nixos-rebuild-auto command runs nixos-rebuild switch using the current hostname as the flake target, then reactivates the current specialisation (if any). All three boot entries (base, igpu, dgpu) are always built together in a single rebuild. It is defined as a bash function in home/nimmo.nix.
Switch Mode (Electra Specialisations)
Select the desired boot entry from the systemd-boot menu at startup. The bootloader uses @saved so it remembers your last selection across reboots.
- Base entry (
electra-battery): AMD iGPU, vanilla kernel, locked power-saver, no gaming/maker profiles — default mode - Specialisation entry (
electra-igpu): AMD iGPU only, stock kernel, dynamic power profile, gaming/maker profiles - Specialisation entry (
electra-dgpu): NVIDIA + AMD hybrid, Zen kernel — use when the NVIDIA expansion bay is installed
Update All Packages
Updates run automatically at 03:00 daily (both hosts, pull-only mode). To trigger manually:
just nixos-auto-update-run-now # Normal run (respects 6h freshness window)
sudo nixos-auto-update --force # Force update regardless of lock age
To see what changed after an update:
just diff-last-update
Adding Packages
There are three places to add packages, depending on scope:
System Packages (available to all users, all hosts)
Edit packages/system.nix. These are available system-wide via environment.systemPackages:
environment.systemPackages = with pkgs; [
# Add your package here
neovim
];
User Packages (nimmo, all hosts)
Edit home/nimmo.nix. These are managed by home-manager and available to nimmo on every host:
home.packages = with pkgs; [
# Add your package here
spotify
];
Capability Profiles
modules/profiles/ bundles related system and user-level config into a single import:
| Profile | What it enables | Enable option |
|---|---|---|
gaming.nix |
Steam, Gamemode, Discord, MangoHUD, powertop | Import to enable |
ai-tools.nix |
Claude Code, Qwen Code, Claude Code desktop launcher | profiles.aiTools.enable (default: true) |
ai-development.nix |
ai-tools.nix + Ollama service + Open WebUI |
Import to enable |
maker.nix |
Cura, OpenSCAD (3D printing/CAD) | Import to enable |
Add a profile to a host by importing it in that host's default.nix:
imports = [
# ...
../../modules/profiles/gaming.nix
];
For packages that don't fit an existing profile, add them directly to that host's default.nix (e.g. hosts/electra/default.nix or hosts/lena/default.nix).
Desktop Applications (all desktop hosts)
Edit modules/desktop/apps.nix. These are system-wide packages for desktop/laptop use (Kate, LibreOffice, VLC, Okular, Nextcloud, Bitwarden, etc.). Both electra and lena import this module.
Finding Package Names
Search for packages:
nix search nixpkgs firefox
nix search nixpkgs --json firefox | jq # Detailed output
Or browse https://search.nixos.org/packages
Adding External Flakes
1. Add the input to flake.nix
inputs = {
# ... existing inputs ...
# New flake
some-tool.url = "github:owner/repo";
some-tool.inputs.nixpkgs.follows = "nixpkgs"; # Use our nixpkgs
};
2. Pass it through specialArgs
Already configured - all inputs are passed via specialArgs = { inherit inputs; }.
3. Use the package
In any module that has inputs in its arguments:
{ pkgs, inputs, ... }:
{
environment.systemPackages = [
inputs.some-tool.packages.${pkgs.stdenv.hostPlatform.system}.default
];
}
4. Update the lock file
nix flake update some-tool
Adding a New Host
1. Create host directory
mkdir -p hosts/newhostname
2. Generate hardware config on the new machine
nixos-generate-config --show-hardware-config > hosts/newhostname/hardware-configuration.nix
3. Create host default.nix
{ config, pkgs, inputs, ... }:
{
imports = [
../common
./hardware-configuration.nix
# Add modules as needed
../../modules/boot/silent-boot.nix
../../modules/desktop/plasma.nix
../../modules/desktop/apps.nix
../../packages/system.nix
../../users/nimmo.nix
];
networking.hostName = "newhostname";
system.stateVersion = "25.11"; # Set to your NixOS version
}
4. Add to flake.nix
nixosConfigurations = {
electra = nixpkgs.lib.nixosSystem { ... };
newhostname = nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ ./hosts/newhostname ];
};
};
5. Deploy
# First deployment (explicit)
sudo nixos-rebuild switch --flake .#newhostname
# Subsequent deployments can use
nixos-rebuild-auto
Adding New Modules
Create a new file in modules/category/:
# modules/services/tailscale.nix
{ config, pkgs, ... }:
{
services.tailscale.enable = true;
environment.systemPackages = [ pkgs.tailscale ];
}
Then import it in the appropriate host config:
hosts/common/default.nix- for all hostshosts/electra/default.nix- for electra (both modes)hosts/electra/default.nix(underspecialisation.dgpu.configuration) orhosts/lena/default.nix- for a single mode/host
imports = [
# ...
../../modules/services/tailscale.nix
];
Rollback
Boot into previous generation
Select from boot menu at startup (systemd-boot shows all available generations).
Rollback from command line
# List generations
sudo nix-env --list-generations --profile /nix/var/nix/profiles/system
# Switch to specific generation
sudo nix-env --switch-generation 42 --profile /nix/var/nix/profiles/system
sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch
Garbage Collection
Automatic daily cleanup is configured in modules/maintenance/garbage-collection.nix:
- Deletes generations older than 3 days
- Runs daily with a randomized 1-hour delay to avoid contention
Additionally, nix-settings.nix configures automatic store GC to maintain 5-10GB free disk space.
Manual cleanup:
# Remove old generations (keeps last 7 days)
sudo nix-collect-garbage --delete-older-than 7d
# Remove ALL old generations (keep only current)
sudo nix-collect-garbage -d
Automated System Services
NixOS Auto-Update (All Hosts)
Defined in modules/services/nixos-auto-update.nix. Both hosts run in pull-only mode at 03:00 with a 15-minute randomised delay.
Pull-only mode (all hosts):
- Skips if the repository has uncommitted changes (work in progress detected)
- Pulls latest config from remote
- Validates the configuration with a dry-run build
- Builds the new configuration
- Switches to the new configuration and reactivates the current specialisation if applicable
- Desktop notifications at key points and on success/failure; warns separately if a reboot is needed for kernel changes
The flake.lock is updated either manually (nix flake update) or automatically via the nix binary cache webhook which triggers a rebuild on push.
The service also supports full mode (not currently used) which additionally runs nix flake update, validates, commits the lock file with a summary of input changes, and pushes — before switching. On switch failure it rolls back the commit.
Monitor the service:
journalctl -u nixos-auto-update.service -f
Trigger or inspect manually:
just nixos-auto-update-run-now # Trigger immediately (normal run)
just nixos-auto-update-last-run # Show last run status
sudo nixos-auto-update --force # Force flake update regardless of lock age
just diff-last-update # Show package changes from the last update
Restic Backup (Electra and Lena)
Defined in modules/services/restic-backup.nix. Automated backups of /home/nimmo:
- Runs every 6 hours with 15-minute randomized delay
- Credentials managed via sops-nix (encrypted in
secrets/secrets.yaml, decrypted to/run/secrets/at runtime) - Excludes configured via
/etc/restic/excludes.txt(created empty; edit to customise)
Monitor backups:
journalctl -u restic-backup.service -f
Silent Boot (All hosts)
Defined in modules/boot/silent-boot.nix. Plymouth splash screen with quiet kernel parameters for a clean boot experience.
Auto Power Profile (Electra igpu/dgpu and Lena)
Defined in modules/power/auto-power-profile.nix. Triggered by udev on AC plug/unplug events and switches profiles:
- Charging/Full + >25% battery: performance mode
- Charging/Full + <=25% battery: balanced mode
- Discharging + >50% battery: balanced mode
- Discharging + <=50% battery: power-saver mode
Monitor with:
journalctl -u auto-power-profile.service -f
Current Hosts
| Host | Machine | Channel | Key Differences |
|---|---|---|---|
| electra | Framework 16 | unstable | Base: battery mode (vanilla kernel, locked power-saver, iGPU runtime PM, maker). Specialisation igpu: dynamic power profile, gaming/maker. Specialisation dgpu: Zen kernel, NVIDIA/AMD hybrid, dual Ollama, Docker |
| lena | Lenovo Ideapad 5 2-in-1 | 25.11 stable | Tablet mode, touchscreen, Disko partitioning, auto-update (pull-only), no Ollama/gaming |
Shared Across All Hosts (via hosts/common/)
- Systemd-boot, NetworkManager
- Garbage collection (daily, 3-day age limit)
- btrfs scrub (monthly, all btrfs mounts)
- Portability options (
modules/common/default-config.nix) - sops-nix host key configuration
- UK locale (en_GB.UTF-8, Europe/London)
Desktop hosts only (electra, lena — via hosts/common/desktop.nix):
- Fonts (Noto, Fira Code, JetBrains Mono Nerd Font)
- Printing (CUPS with Brother drivers, Avahi network discovery)
- Removable storage (udisks2, NTFS support, polkit mount rules)
- KDE Plasma 6 (login manager is host-specific: plasma-login-manager on electra, SDDM on lena)
- Silent boot (Plymouth)
- Auto power profile switching (udev-triggered)
- Bluetooth
- Desktop apps (
modules/desktop/apps.nix) - System packages (
packages/system.nix)
Electra (All Modes)
- Framework 16 hardware module (AMD GTT 32GB, fingerprint, PipeWire, zram, ROCm)
- Expansion card automount (1TB NTFS at
/run/media/nimmo/Expansion1TB) - AI development profile (
modules/profiles/ai-development.nix): Ollama + Open WebUI + AI user tools - Maker profile (
modules/profiles/maker.nix): Cura, OpenSCAD - NixOS auto-update (daily)
- ROCm HSA override for AMD 780M iGPU (
HSA_OVERRIDE_GFX_VERSION=11.0.0) - Docker with AMD 780M iGPU access
Electra Base (battery)
- Linux vanilla kernel (mainline, no latency tuning)
- Power profile locked to power-saver (
modules/power/battery-mode.nix) - iGPU runtime power management (
amdgpu.runpm=1) - Gaming profile disabled
Electra igpu Specialisation Only
- Dynamic power profile switching (
modules/power/auto-power-profile.nix) - Gaming profile (
modules/profiles/gaming.nix): Steam, Gamemode, Discord, MangoHUD, powertop - Maker profile (
modules/profiles/maker.nix): Cura, OpenSCAD
Electra dgpu Specialisation Only
- Linux Zen kernel
- Dynamic power profile switching (
modules/power/auto-power-profile.nix) - Gaming profile (
modules/profiles/gaming.nix): Steam, Gamemode, Discord, MangoHUD, powertop - NVIDIA/AMD Prime offload drivers
- NVIDIA Ollama instance (port 11435, CUDA acceleration)
- Docker with NVIDIA Container Toolkit
- nvtop for GPU monitoring
Lena-Specific
- Tablet mode via
iio-sensor-proxy(automatic screen rotation) - Fingerprint reader via
fprintd - Btrfs with Disko-managed partitioning (subvolumes: @, @home, @nix, @log)
- Both nimmo (admin) and claire (standard user) accounts
- AI tools profile (
modules/profiles/ai-tools.nix): Claude Code, Qwen Code - Maker profile (
modules/profiles/maker.nix): Cura, OpenSCAD - NixOS 25.11 stable channel
User Accounts
nimmo (All hosts)
- Type: Administrator account
- Groups: wheel (sudo), networkmanager, video, audio, render, docker (all electra modes)
- Shell: bash with bash-it framework (rjorgenson theme)
- Configuration: Managed by home-manager in
home/nimmo.nix - Packages: Via capability profiles (
modules/profiles/); AI tools, gaming, and maker packages are per-host based on which profiles are imported - Features:
- Git configuration unified across all hosts (nimmo@nimmog.uk)
- Direnv with nix-direnv for automatic environment loading
- Custom
nixos-rebuild-autofunction (rebuilds and reactivates current specialisation) - Optimized autostart: Nextcloud delayed 15 seconds, Discover disabled for faster login
claire (Lena only)
- Type: Standard user account
- Groups: networkmanager, video, audio (no wheel/sudo)
- Purpose: Guest/family account with restricted privileges
- Packages: System packages only
Ollama with Open WebUI
Electra runs Ollama for local LLM inference with Open WebUI as the web interface, using native NixOS services.
Architecture
Base / both modes (modules/profiles/ai-development.nix → modules/services/ollama.nix): AMD Ollama instance + Open WebUI (imported via electra)
- AMD iGPU Instance (port 11434): For large models with 48GB shared RAM
- Context window: 65,536 tokens
- Vulkan acceleration
- Keep-alive: 24 hours
- Open WebUI (localhost:3000): Web interface for model interaction
dgpu specialisation (modules/services/ollama-nvidia.nix): Adds a second NVIDIA instance
- NVIDIA dGPU Instance (port 11435): For fast inference with 8GB VRAM
- Context window: 8,192 tokens
- CUDA acceleration
- Optimized for quick chats and coding completion
- Open WebUI is configured to connect to both instances
Both instances share a models directory at /run/media/models (btrfs subvolume), so models downloaded on one instance are available to the other.
Usage
Access the web interface at http://localhost:3000
Direct API access:
# AMD instance (electra, all tiers)
curl http://localhost:11434/api/generate -d '{"model":"llama3.2","prompt":"Hello"}'
# NVIDIA instance (electra-dgpu only)
curl http://localhost:11435/api/generate -d '{"model":"llama3.2","prompt":"Hello"}'
View logs:
journalctl -u ollama.service -f # AMD instance
journalctl -u ollama-nvidia.service -f # NVIDIA instance (electra-dgpu only)
journalctl -u open-webui.service -f # Web interface
Hardware Acceleration
dgpu specialisation:
- AMD instance uses Vulkan with GTT extended to 32GB (
amdgpu.gtt_size=32768) - NVIDIA instance uses CUDA
- Both instances run simultaneously, allowing you to choose the best hardware for each task
Base (iGPU mode):
- Uses Vulkan with GTT extended to 32GB
- HSA override for RDNA3 780M compatibility (
HSA_OVERRIDE_GFX_VERSION=11.0.0)
Model Recommendations
For NVIDIA dGPU (8GB VRAM) - Fast inference:
- Llama 3.2 3B (very fast, lightweight)
- Qwen 2.5 Coder 7B (excellent for code)
- Llama 3.1 8B (balanced performance)
- Mistral 7B (general purpose)
For AMD iGPU with 48GB shared RAM - Large models:
- Qwen 2.5 72B (high capability)
- CodeLlama 70B (specialized for code)
- QwQ 32B (reasoning focused)
- Llama 3.1 70B (general purpose)
- DeepSeek Coder 33B (advanced code generation)
Data Persistence
/run/media/models/ # Shared models directory (btrfs @models subvolume)
/var/lib/ollama/ # AMD instance state
/var/lib/ollama-nvidia/ # NVIDIA instance state (dgpu specialisation only)
/var/lib/open-webui/ # Open WebUI data (chat history, settings)
Flake Inputs
| Input | Purpose |
|---|---|
nixpkgs |
NixOS unstable (electra) |
nixpkgs-bitwarden |
Pinned nixpkgs for bitwarden-desktop (electron 39 workaround) |
nixpkgs-stable |
NixOS 25.11 (lena) |
home-manager |
User environment management (unstable) |
home-manager-stable |
User environment management (stable, for lena) |
bash-it |
Bash framework for themes and plugins |
claude-code-nix |
Claude Code AI assistant |
nixos-hardware |
Hardware-optimized configs (Lenovo Ideapad, Framework) |
disko |
Declarative disk partitioning |
nur |
Nix User Repository (Firefox extensions) |
sops-nix |
Encrypted secrets management (age-based) |
plasma-manager |
Declarative KDE Plasma configuration via home-manager |
framework-system |
Official Framework hardware tool (upstream flake) |
Learning More
The manual/ directory contains a 13-chapter learning manual designed to take you from relying on AI for config changes to understanding and confidently modifying the configuration yourself. Start with manual/README.md for the chapter index. Practical chapters come first; theory chapters come later.
- Need to do a specific task right now? Jump to Chapter 2 (Workflows) or Chapter 8 (Quick Reference).
- Want to understand how this repo is organised? Start at Chapter 1 (Configuration Structure).
- Something broke? Go to Chapter 7 (Troubleshooting).
- New to Nix entirely? Start at Chapter 9 (Nix Language) and work through Part 2.