From 8d2a0357c1ae81ec796e0acdb3a18d8af1bb037d Mon Sep 17 00:00:00 2001 From: Padreug Date: Sun, 28 Jun 2026 06:48:38 +0200 Subject: [PATCH] feat: NixOS system entry point (configuration.nix) Co-Authored-By: Claude Opus 4.8 --- configuration.nix | 245 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 configuration.nix diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..769aa9a --- /dev/null +++ b/configuration.nix @@ -0,0 +1,245 @@ +# Omnixient NixOS Configuration +# This is the main entry point — keep it thin. +# System-level config lives in modules/; this file is for per-host settings. + +{ + config, + pkgs, + lib, + settings, + ... +}: + +let + currentTheme = settings.theme; +in +{ + imports = [ + # NOTE: hardware-configuration.nix is imported per-host from + # hosts//default.nix (it's machine-specific), not here. + + # Omnixient modules + ./modules/lib.nix + ./modules/core.nix + ./modules/colors.nix + ./modules/boot.nix + ./modules/security.nix + ./modules/secrets.nix + ./modules/fastfetch.nix + ./modules/walker.nix + ./modules/scripts.nix + ./modules/menus.nix + ./modules/desktop/hyprland.nix + ./modules/packages.nix + ./modules/development.nix + ./modules/mcp.nix + ./modules/themes/${currentTheme}.nix + ./modules/users.nix + ./modules/services.nix + ./modules/hardware + ]; + + # --- Per-host settings (edit these) --- + + nixpkgs.config.allowUnfree = true; + # Electron 39 is EOL upstream but still bundled by signal-desktop / + # element-desktop / obsidian in current nixpkgs. Allow until those + # packages move to a supported electron. + nixpkgs.config.permittedInsecurePackages = [ "electron-39.8.10" ]; + + nix = { + settings = { + experimental-features = [ + "nix-command" + "flakes" + ]; + auto-optimise-store = true; + # Bound build concurrency so a big rebuild (lnbits/webapp/lamassu) + # can't allocate past available RAM and trigger the OOM-killer + # against the desktop session. 4×4 keeps headroom on a 16-core box. + max-jobs = 4; + cores = 4; + substituters = [ + "https://cache.nixos.org" + "https://nix-community.cachix.org" + "https://hyprland.cachix.org" + ]; + trusted-public-keys = [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=" + ]; + }; + # Run the daemon (and therefore all build workers it spawns) at idle + # CPU + IO priority, so interactive apps always preempt nix. + daemonCPUSchedPolicy = "idle"; + daemonIOSchedClass = "idle"; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 30d"; + }; + }; + + # Hard memory ceiling on the nix-daemon cgroup: MemoryHigh applies + # backpressure (slows builds before OOM); MemoryMax kills the build + # cgroup before the kernel reaps Chromium/waybar/walker. + systemd.services.nix-daemon.serviceConfig = { + MemoryHigh = "16G"; + MemoryMax = "20G"; + }; + + # Compressed swap-in-RAM. With no disk swap the kernel reaches for the + # OOM-killer the moment a build spikes; zram gives it a release valve + # for cold pages without thrashing a disk. + zramSwap = { + enable = true; + memoryPercent = 50; + algorithm = "zstd"; + }; + + networking = { + hostName = settings.hostName; + # iwd-only wifi (impala handles WPA2-Enterprise natively since v0.5.0) + networkmanager.enable = false; + wireless.iwd = { + enable = true; + settings = { + General.EnableNetworkConfiguration = true; + Network.EnableIPv6 = true; + }; + }; + firewall = { + enable = true; + allowedTCPPorts = [ + 22 + 80 + 443 + 3000 + 8080 + 5173 # webapp hub (Vite dev) + 5180 # libra + 5181 # activities (sortir) + 5182 # wallet + 5183 # chat + 5184 # forum + 5185 # market + 5186 # tasks + 5187 # restaurant + 5001 # LNbits + 3333 # Fava (docker maps :5000→:3333; also the deploy default) + 6033 # pict-rs + 6173 # chateau-du-faune dev + ]; + }; + }; + + time.timeZone = settings.timeZone; + i18n = { + defaultLocale = "en_US.UTF-8"; + extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + }; + + system.stateVersion = settings.stateVersion; + + # VM testing settings (ignored on real hardware) + virtualisation.vmVariant = { + virtualisation = { + memorySize = 4096; + cores = 2; + qemu.options = [ + "-vga virtio" + ]; + # Forward host port 2222 -> guest port 22 so we can ssh in + # from the host (`ssh -p 2222 user@localhost`) instead of + # typing into the QEMU window. The host_port=2222 avoids + # needing root for a low port and dodges any local sshd. + forwardPorts = [ + { + from = "host"; + host.port = 2222; + guest.port = 22; + } + ]; + }; + # Disable services that don't work in VMs + services.smartd.enable = lib.mkForce false; + services.power-profiles-daemon.enable = lib.mkForce false; + services.thermald.enable = lib.mkForce false; + # Use software rendering as fallback for Hyprland + environment.variables.WLR_RENDERER = "pixman"; + + # VM-only: re-enable password ssh auth so we can ssh in from + # the host to test without injecting keys. Production has these + # disabled in modules/services.nix; this override only applies + # to the vmVariant so it never reaches a real machine. + services.openssh.settings.PasswordAuthentication = lib.mkForce true; + services.openssh.settings.KbdInteractiveAuthentication = lib.mkForce true; + }; + + # --- Omnixient settings --- + + hardware.bluetooth.enhanced.enable = true; + + # udev rules for ZSA keyboards (Moonlander) — needed to flash firmware + # and use Oryx live-training. Flash with keymapp (see home.packages). + hardware.keyboard.zsa.enable = true; + + omni = { + enable = true; + desktop.enable = true; + mcp.enable = true; + mcp.servers.lnbits = { + enable = true; + url = "http://localhost:5001"; + }; + mcp.servers.nextcloud = { + enable = true; + url = "https://cloud.ariege.io"; + username = "pat"; + }; + user = settings.user; + theme = currentTheme; + displayManager = "tuigreet"; + preset = "developer"; + features = { + office = true; + communication = true; + }; + + security = { + enable = true; + fingerprint = { + enable = false; + autoDetect = true; + }; + fido2 = { + enable = false; + autoDetect = true; + }; + systemHardening = { + enable = true; + faillock = { + enable = true; + denyAttempts = 10; + unlockTime = 120; + }; + }; + }; + + # colorScheme = inputs.nix-colors.colorSchemes.tokyo-night-dark; + # wallpaper = /path/to/your/wallpaper.jpg; + # features = { coding = true; containers = true; }; + # packages.exclude = [ "discord" "spotify" ]; + }; +}