A declarative, privacy-hardened NixOS configuration. Built for Wayland, aggressive application sandboxing, and local network control.
Perseus runs on Niri (scrollable-tiling Wayland compositor) with DankMaterialShell (DMS) providing the shell UI — widgets, app launcher, media controls, notifications, and system toggles.
To handle gaps in the Wayland ecosystem, Perseus ships three custom Rust daemons:
-
clammy— Wayland power and display management daemon. Hooks into D-Bus/logind and theext_idle_notify_v1Wayland protocol to manage: gradual screen dimming before lock (290s → 300s at default config), lock screen activation, DPMS toggling, system suspend, lid switch handling, and external monitor awareness for clamshell mode. -
niri-reaper— Flatpak zombie process killer. Watches the Niri event stream for window close events. When a Flatpak window is closed, the sandbox and child processes (including Wayland idle inhibitors) keep running —niri-reaperrunsflatpak killimmediately to clean them up. Targets: Slack, Spotify, Steam, Teams, Zoom. -
ntl-daemon(NastyTechLords) — Security auditing daemon. Runs every 6 hours via systemd timer, inspecting processes, network state, filesystem integrity, privacy leaks, and Nix configuration. Reports logged to/var/log/nastyTechLords/.
The network stack is default-deny.
- OpenSnitch + nftables: All outbound traffic is queued to OpenSnitch for per-application approval. The nftables output chain explicitly allows only DNS (to local
dnscrypt-proxy) and WireGuard before queuing everything else to OpenSnitch without thebypassflag — if OpenSnitch crashes, DNS and VPN keep working but all other traffic is dropped. - Encrypted DNS:
dnscrypt-proxy2on127.0.0.1:53handles all DNS (Cloudflare/Quad9, DNSSEC required). OISD domain blocklist updated daily. Application DoH/DoT endpoints are blackholed to prevent DNS bypass. - Telemetry blackhole: Known analytics, crash reporting, and AI telemetry domains (Google Analytics, Slack metrics, Microsoft Vortex, Copilot, Tabnine, Sentry, Codeium, Cursor) blackholed to
0.0.0.0in/etc/hosts. Corresponding environment variables (SLACK_DISABLE_TELEMETRY,DOTNET_CLI_TELEMETRY_OPTOUT, etc.) are set system-wide. - VPN: Native WireGuard integration for Mullvad, secrets encrypted via
sops-nixandage. - Network hardening: MAC address randomization (Wi-Fi and Ethernet), disabled IP forwarding, SYN cookies, martian logging, ICMP echo disabled.
- Fail2ban: SSH on port 7889, 3 attempts max, 24h ban with incremental escalation.
- AppArmor: Enabled with
killUnconfinedConfinables. - No swap: Both swap devices and zram are force-disabled to prevent memory dumps.
Daily applications are isolated using two methods:
Flatpak (primary): Slack, Spotify, Steam, Teams, and Zoom run as Flatpaks with strict system overrides — forced Wayland sockets, --nosocket=x11, --nofilesystem=home, --nofilesystem=host, and injected telemetry-kill environment variables. Overrides are applied declaratively in modules/apps/flatpak.nix.
Bubblewrap (supplementary): For binaries not in Flatpak, Perseus uses custom bwrap derivations:
sandboxed-logseq— Jailed Logseq with restricted namespace and filesystem access.sandboxed-frontend— Provides thejail-devcommand for spinning up temporary containers for untrusted NPM/Node projects with stripped SSH agent access and isolated filesystem.
Both LibreWolf and Firefox are provisioned with declarative policies.
- Hardening: Betterfox (
Fastfox.js,Peskyfox.js,Securefox.js,Smoothfox.js) loaded via flake input intoextraConfig. On top of that, declarativesettings.nixlocks down telemetry, disables Pocket, blocks fingerprinting (privacy.resistFingerprinting), enforces HTTPS-only, disables WebRTC, clears data on shutdown, and blocks DoH/DoT bypass. Firefox Studies and Normandy are disabled. - Theming: Catppuccin
userChrome.cssloaded via flake input. - Extensions: Force-installed: uBlock Origin, DarkReader, Firemonkey, ClearURLs. Extensions auto-enabled in private browsing.
- NVIDIA: Prime offloading configured (
nvidia-drm.modeset=1, early KMS). - Performance tooling:
gamemode,gamescope,mangohud. - Steam: Flatpak with forced Wayland, full device access, and
xdg-downloadfilesystem. - Controllers: DualSense and generic gamepad support via
antimicroxand system uinput access.
- Language stacks: Python, Go, Rust, and Node.js toggled via
user-config.nix. Paths and environment variables merged dynamically. - Per-project isolation:
direnvwith Nix integration — drop a.envrcin any project directory for automatic isolated environments. - Editor: Neovim via
nixvim— Catppuccin theme, Treesitter, Telescope,conform.nvim, and language-specific LSPs. - Jailed frontend dev:
jail-devcommand launches a Bubblewrap container for untrusted Node/NPM work with restricted filesystem and no SSH agent.
hosts/default/ # Machine-specific NixOS and hardware config
modules/
apps/ # Flatpak, LibreWolf, Thunderbird
dev/ # Language tooling, nixvim
hardware/ # clammy, NVIDIA, Thunderbolt
security/ # Privacy, firewall, telemetry deny, VPN, SSH, fail2ban
system/ # Niri, DMS, greetd, packages, environment
home/ # Home-manager: Firefox, zsh
programs/ # Custom Rust daemons (clammy, niri-reaper, ntl, perseus-net)
packages/ # Nix derivations for custom programs
configs/ # Dotfiles (Alacritty, GTK, LibreWolf userChrome, Mullvad)
secrets/ # sops-encrypted VPN config
Prerequisites: NixOS 25.11+ on bare metal, Git, 20GB+ free space.
-
Clone the repository:
git clone https://github.com/NeoMedSys/nix-up cd nix-up -
Run the setup script (required):
./setup.sh
Interactive wizard that detects hardware, lets you choose browsers, dev tools, Flatpak apps, and optional modules. Generates
user-config.nixand sets up Git smudge/clean filters so personal data never reaches the remote. Copieshardware-configuration.nixautomatically if found. -
Build and install:
sudo nixos-install --flake .#<your-hostname> sudo reboot
First install: Set
hasGPUandvpntofalseinuser-config.nix. Enable after first successful boot.
Everything toggleable lives in user-config.nix:
| Key | Type | Effect |
|---|---|---|
isLaptop |
bool | Enables clammy (idle/lock/suspend daemon) |
hasGPU |
bool | NVIDIA drivers + Prime offloading |
thunderbolt |
bool | Thunderbolt/dock support |
vpn |
bool | Mullvad WireGuard + sops-nix secrets |
email |
bool | Thunderbird |
flatpakApps |
list | Which Flatpak apps to install (empty = no Flatpak) |
browsers |
list | "librewolf", "firefox", or both |
devTools |
list | "python", "go", "rust", "node" |
extraHosts |
attrset | Custom /etc/hosts entries |
Requires vpn = true; in user-config.nix.
-
Generate an
agekey:mkdir -p ~/.config/sops/age nix-shell -p age -c "age-keygen -o ~/.config/sops/age/keys.txt"
-
Create
.sops.yamlin repo root pointing to your public key. -
Place WireGuard config in
secrets/wireguard.yamlundermullvad_conf. -
Encrypt:
nix-shell -p sops -c "sops -e -i secrets/wireguard.yaml"
nix flake update # Update inputs
sudo nixos-rebuild switch --flake .#<hostname> # Rebuild
sudo nixos-rebuild switch --rollback # Rollback
ntl report # Security audit reportGPL-3.0