# ---- TERRA ---- { config, pkgs, lib, inputs, ... }: let unstable = import inputs.nixpkgs-unstable { inherit (pkgs.stdenv.hostPlatform) system; config = pkgs.config; }; in { imports = [ ./hardware-configuration.nix ./disk-config.nix ./secrets.nix ../../common.nix ../../services/containers.nix ../../services/vpn/tailscale.nix ../../services/monitoring/node-exporter.nix ../../services/desktop/desktop-hyprland.nix ../../services/desktop/desktop-apps.nix ../../services/desktop/librechat.nix ]; networking.hostName = "terra"; services.flatpak = { enable = true; remotes = [{ name = "flathub"; location = "https://dl.flathub.org/repo/flathub.flatpakrepo"; }]; packages = [ { appId = "com.github.tchx84.Flatseal"; origin = "flathub"; } { appId = "com.blitzfc.qbz"; origin = "flathub"; } { appId = "com.discordapp.Discord"; origin = "flathub"; } { appId = "org.telegram.desktop"; origin = "flathub"; } { appId = "com.bambulab.BambuStudio"; origin = "flathub"; } { appId = "md.obsidian.Obsidian"; origin = "flathub"; } ]; }; environment.systemPackages = [ unstable.proton-pass-cli ]; # ---- nix-ld: lets generic dynamically-linked Linux binaries run as-is — # needed for editor extensions (Zed/VSCode LSPs, debuggers, etc.) that # download prebuilt binaries not built for NixOS. See # https://nix.dev/permalink/stub-ld ---- programs.nix-ld.enable = true; # JetBrains IDEs installed via Toolbox bundle a JBR that aborts with # `libX11.so.6: cannot open shared object file` under the default (X11-less) # nix-ld set. Additive — merges with the module's own base list (zlib etc). programs.nix-ld.libraries = with pkgs; [ freetype fontconfig libGL libxkbcommon wayland libsecret libx11 libxext libxi libxrender libxtst libxcursor libxrandr libxinerama libxcb # CLion Nova's C++ backend is a .NET 10 app that needs ICU or reports # "Couldn't find a valid ICU package installed on the system". icu ]; # NixOS only ships /bin/sh; envfs serves /bin and /usr/bin from PATH so # third-party scripts hardcoding `#!/bin/bash` (e.g. JetBrains Toolbox's # generated launchers) still resolve. services.envfs.enable = true; # ---- home-manager (user-level config for darman) ---- # Base settings + shared zsh baseline live in common.nix + home/common.nix # (every host); this layers terra's desktop profile on top (imports merge). home-manager.extraSpecialArgs = { inherit unstable inputs; }; home-manager.users.darman.imports = [ ./home.nix ]; # ---- Boot (UEFI) ---- boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; hardware.cpu.amd.updateMicrocode = true; # Lets `nix build` target mercury (aarch64) from here — see CLAUDE.md's # aarch64 gotcha. boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; # ---- GPU (Radeon RX 6800 XT / Navi 21) ---- hardware.enableRedistributableFirmware = true; boot.initrd.kernelModules = [ "amdgpu" ]; # /dev/dri/renderD128 is root:render 0660 — host user needs render group for # rootless podman GPU containers (Vulkan whisper.cpp/llama.cpp). users.users.darman.extraGroups = [ "render" "video" ]; # ---- ollama (local LLM server, ROCm on the 6800 XT) ---- # Navi 21 (gfx1030) is officially ROCm-supported, so no # HSA_OVERRIDE_GFX_VERSION needed. Upstream module already runs under # DynamicUser with render/kfd/drm access wired, unlike jellyfin's static user. services.ollama = { enable = true; package = pkgs.ollama-rocm; # keep default model in sync with services/desktop/librechat.nix's # endpoints.custom default (its schema needs a non-empty value even # though fetch=true overrides it). # gemma4:12b: daily-driver chat/coding model, fits fully in 16G VRAM; also # doubles as LibreChat's memory-extraction agent (librechat.nix) since a # smaller model confused the user's stated facts with its own boilerplate. # qwen3.6:35b-a3b: MoE (3B active/36B total, ~24GB Q4_K_M) — doesn't fit # in VRAM alone, so ollama offloads inactive experts to CPU RAM; sparsity # makes that less painful than for a dense model this size, but still slower. # VladimirGav/qwen3.8-27B-14GB-IQ4: dense 27B at IQ4 (~14GB) — nominally # fits the 16G card but leaves little headroom, so expect partial CPU # offload as context grows. loadModels = [ "gemma4:12b" "qwen3.6:35b-a3b" "VladimirGav/qwen3.8-27B-14GB-IQ4" ]; # Ollama truncates context far below a model's real window unless told # otherwise. 131072 is the practical ceiling from load-testing: VRAM stays # 100% GPU with no CPU spillover up to here, but headroom and prefill # throughput both degrade near the top — going higher risks CPU spillover # under concurrent GPU load (compositor, jellyfin transcode) for little gain. environmentVariables.OLLAMA_CONTEXT_LENGTH = "131072"; }; # ---- Dev-data disks — NOT in disko, mounted read-write, never wiped ---- fileSystems."/mnt/hdd_01" = { device = "/dev/disk/by-uuid/b8445126-ec6d-4f88-818a-d9e13031d9a4"; fsType = "ext4"; options = [ "nofail" ]; }; fileSystems."/mnt/ssd_01" = { device = "/dev/disk/by-uuid/6ca18a9f-27bc-4e58-aea8-de43a0d0ed5d"; fsType = "ext4"; options = [ "nofail" ]; }; # jupiter's samba share (services/network/samba.nix) — mounted on demand so # terra doesn't stall boot/login when jupiter is off or unreachable. fileSystems."/mnt/jupiter" = { device = "//jupiter/data"; fsType = "cifs"; options = [ "credentials=${config.sops.templates."jupiter-smb.credentials".path}" "uid=1000" "gid=100" "nofail" "x-systemd.automount" "x-systemd.idle-timeout=60" "x-systemd.mount-timeout=10s" "_netdev" ]; }; system.stateVersion = "26.05"; }