diff --git a/README.md b/README.md index b05b98e..1fb125f 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,48 @@ # nixos -One flake, two machines. Hyprland + greetd autologin, Zen+Tridactyl, neovim, zsh+starship. - -| host | arch | build | -|------|------|-------| -| `mbp` | aarch64 | MacBook M1 Pro (Asahi) | -| `pc` | x86_64 | any UEFI x86 | +One flake, one machine: x86_64 UEFI desktop. Hyprland + greetd autologin, +Zen+Tridactyl, neovim, zsh+starship. ``` -flake.nix all config (common + home modules, both hosts) -config/ raw configs: hypr eww fuzzel nvim -hosts/*/hardware-configuration.nix mbp: regenerate on Mac · pc: generic, as-is -firmware/ Mac Wi-Fi/BT blobs — git-add at install. KEEP REPO PRIVATE. +flake.nix all config (the `pc` system module + the `home` module) +hardware-configuration.nix generic x86_64 UEFI profile — mounts by label, as-is +config/ raw configs: hypr fuzzel nvim ``` -Set `time.timeZone` in `common`. Rename a host = change the `nixosConfigurations.` key + its `networking.hostName`. +Set `time.timeZone` in the `pc` module. Monitors, workspace placement and +keybinds live in `config/hypr/hyprland.conf`. ## Apply +The flake output is named after the hostname, so no `#target` is needed: + ```sh -sudo nixos-rebuild switch --flake ~/nixos#mbp # or #pc -nix flake update && sudo nixos-rebuild switch --flake ~/nixos#mbp # update +sudo nixos-rebuild switch --flake ~/nixos +nix flake update && sudo nixos-rebuild switch --flake ~/nixos # update ``` Roll back = pick an older generation at boot. -## Install: MacBook (Asahi) +## Install -Full/latest guide: . **Back up — a bad partition can brick the Mac.** +No hardware generation needed — `hardware-configuration.nix` is generic and +mounts by the labels below. Boot the NixOS ISO, `sudo -i`: -1. macOS Terminal: `curl https://alx.sh | sh` → `r` resize (≥20 GB free) → `f` install **UEFI environment only**, name `NixOS` → recovery: permissive security. Reboots to U-Boot; power off. -2. Installer USB (on a Linux+Nix box): `nix build github:nix-community/nixos-apple-silicon#installer-bootstrap -o installer` then `dd` the ISO to USB. -3. Boot USB → `sudo su`: -```sh -sgdisk /dev/nvme0n1 -n 0:0 -s && sgdisk /dev/nvme0n1 -p # note new 8300 part, e.g. p5 -mkfs.ext4 -L nixos /dev/nvme0n1p5 -mount /dev/disk/by-label/nixos /mnt && mkdir -p /mnt/boot -mount /dev/disk/by-partuuid/$(cat /proc/device-tree/chosen/asahi,efi-system-partition) /mnt/boot -nixos-generate-config --root /mnt -git clone /mnt/root/nixos && cd /mnt/root/nixos -cp /mnt/etc/nixos/hardware-configuration.nix hosts/mbp/ -mkdir -p firmware && cp /mnt/boot/asahi/{all_firmware.tar.gz,kernelcache*} firmware/ -git add -f hosts/mbp/hardware-configuration.nix firmware/* -nixos-install --flake .#mbp && reboot -``` - -## Install: x86 - -No hardware generation — `hosts/pc/hardware-configuration.nix` is generic (mounts by label). Boot the NixOS ISO, `sudo -i`: ```sh parted /dev/nvme0n1 -- mklabel gpt \ mkpart ESP fat32 1MiB 512MiB set 1 esp on \ mkpart primary 512MiB 100% -mkfs.fat -F32 -n BOOT /dev/nvme0n1p1 -mkfs.ext4 -L nixos /dev/nvme0n1p2 -mount /dev/disk/by-label/nixos /mnt && mkdir -p /mnt/boot && mount /dev/disk/by-label/BOOT /mnt/boot +mkfs.fat -F32 -n NIXBOOT /dev/nvme0n1p1 +mkfs.ext4 -L NIXROOT /dev/nvme0n1p2 +mount /dev/disk/by-label/NIXROOT /mnt && mkdir -p /mnt/boot +mount /dev/disk/by-label/NIXBOOT /mnt/boot git clone /mnt/root/nixos && cd /mnt/root/nixos nixos-install --flake .#pc && reboot ``` -Exotic storage controller won't boot? Add its module to `availableKernelModules` in `hosts/pc/hardware-configuration.nix` (`nixos-generate-config --show-hardware-config` lists it). +Exotic storage controller won't boot? Add its module to +`availableKernelModules` in `hardware-configuration.nix` +(`nixos-generate-config --show-hardware-config` lists it). ## After first boot -`passwd` (ships `initialPassword = "changeme"`). If you land on a tty instead of Hyprland, change greetd's `uwsm start hyprland` → `Hyprland` in `common`. +`passwd` (ships `initialPassword = "changeme"`). If you land on a tty instead +of Hyprland, change greetd's `uwsm start hyprland` → `Hyprland`. diff --git a/config/eww/eww.scss b/config/eww/eww.scss deleted file mode 100644 index 3041c68..0000000 --- a/config/eww/eww.scss +++ /dev/null @@ -1,14 +0,0 @@ -* { - all: unset; -} - -.battery-popup { - background-color: #16181a; - padding: 6px 10px; -} - -.battery-popup-text { - font-family: monospace; - font-size: 14px; - color: #ddd; -} diff --git a/config/eww/eww.yuck b/config/eww/eww.yuck deleted file mode 100644 index 280cab1..0000000 --- a/config/eww/eww.yuck +++ /dev/null @@ -1,17 +0,0 @@ -(defpoll battery-percent :interval "10s" "scripts/battery-capacity") -(defpoll battery-status :interval "10s" "scripts/battery-status") - -(defwidget battery-popup [] - (box :class "battery-popup" - :halign "center" - :valign "center" - (label :class "battery-popup-text" - :text "${battery-percent}% ${battery-status}"))) - -(defwindow battery-popup - :monitor 0 - :geometry (geometry :anchor "center") - :stacking "overlay" - :exclusive false - :focusable false - (battery-popup)) diff --git a/config/eww/scripts/battery-capacity b/config/eww/scripts/battery-capacity deleted file mode 100755 index 4c333f3..0000000 --- a/config/eww/scripts/battery-capacity +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# Print the charge % of the first real battery. Portable across machines -# (macsmc-battery on Asahi, BAT0/BAT1 on x86). -for d in /sys/class/power_supply/*; do - [ "$(cat "$d/type" 2>/dev/null)" = "Battery" ] || continue - cat "$d/capacity" 2>/dev/null && exit 0 -done -echo "?" diff --git a/config/eww/scripts/battery-status b/config/eww/scripts/battery-status deleted file mode 100755 index 68d7448..0000000 --- a/config/eww/scripts/battery-status +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# Print the charging status of the first real battery. Portable across machines. -for d in /sys/class/power_supply/*; do - [ "$(cat "$d/type" 2>/dev/null)" = "Battery" ] || continue - cat "$d/status" 2>/dev/null && exit 0 -done -echo "Unknown" diff --git a/config/hypr/hyprland.conf b/config/hypr/hyprland.conf index c441654..82b15b8 100644 --- a/config/hypr/hyprland.conf +++ b/config/hypr/hyprland.conf @@ -1,12 +1,14 @@ -# -- Monitors & input defaults -- -# Monitor layout is host-specific; written by the flake per host. -source = ~/.config/hypr/monitors.conf +# -- Monitors -- +monitor = desc:Lenovo Group Limited P27q-20 V909LRFR, 2560x1440@60, 0x0, 1.0 +monitor = desc:Lenovo Group Limited P27q-20 V909LPNY, 2560x1440@60, 2560x0, 1.0 +monitor = desc:Lenovo Group Limited P27q-20 V909LRDD, 2560x1440@60, 5120x0, 1.0 -device { - name = apple-spi-keyboard - kb_options = caps:ctrl_modifier,grp:win_space_toggle -} +# Each screen's home workspace; SUPER+ALT+h/l can still move it. +workspace = 1, monitor:desc:Lenovo Group Limited P27q-20 V909LRFR, default:true +workspace = 2, monitor:desc:Lenovo Group Limited P27q-20 V909LPNY, default:true +workspace = 3, monitor:desc:Lenovo Group Limited P27q-20 V909LRDD, default:true +# -- Input -- # TrackPoint (Corne nipple): hold middle button + move to scroll, joystick-style device { name = corne-tp @@ -23,13 +25,6 @@ input { repeat_delay = 300 accel_profile = custom scroll_points = 0.5 1.0 1.5 2.0 2.5 - touchpad { - natural_scroll = true - scroll_factor = 0.9 - tap-to-click = false - clickfinger_behavior = true # 2-finger click = right-click, 3-finger = middle (Mac-like) - disable_while_typing = true - } } general { @@ -77,14 +72,11 @@ exec-once = uwsm finalize # also unlocks the keyring (see security.pam.services.hyprlock in flake.nix). exec-once = hyprlock exec-once = swaybg -c '#16181a' -exec-once = GDK_BACKEND=wayland eww daemon exec-once = systemctl --user start hyprpolkitagent # -- Core -- bind = SUPER, Return, exec, kitty bind = SUPER, D, exec, fuzzel -bind = SUPER, R, exec, eww open battery-popup -bindr = SUPER, R, exec, eww close battery-popup bind = SUPER, Q, killactive bind = SUPER, F, fullscreen, 1 bind = SUPER SHIFT, Space, togglefloating @@ -97,9 +89,10 @@ bind = SUPER, A, exec, caffeine # Each gets its own app_id so the rule below floats only these and not every # terminal. Quit with the TUI's own `q`; no toggle wrapper. # -# The float/size rule is in monitors.conf, generated per host: Hyprland 0.56 -# `size` takes ONLY absolute pixels -- percentages are silently ignored (they -# parse fine and then do nothing), so the value depends on the resolution. +# Hyprland 0.56 `size` takes ONLY absolute pixels -- percentages are silently +# ignored (they parse fine and then do nothing), so this is 70% of 2560x1440. +windowrule = match:class ^(panel-wifi|panel-bt)$, float on, size 1792 1440, center on + bind = SUPER, W, exec, kitty --class panel-wifi impala bind = SUPER, E, exec, kitty --class panel-bt bluetui diff --git a/firmware/README.md b/firmware/README.md deleted file mode 100644 index 56acca6..0000000 --- a/firmware/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Asahi peripheral firmware (vendored) - -`hardware.asahi.peripheralFirmwareDirectory` points here. A **pure** flake -cannot read `/boot/vendorfw`, so the Wi-Fi/Bluetooth firmware must live inside -the repo tree and be git-tracked. - -Since nixos-apple-silicon 66d8dd2 the module expects the pre-extracted -`firmware.cpio` (placed on the ESP by the Asahi installer) instead of -`all_firmware.tar.gz` + `kernelcache.*`. - -## During install, on the Mac: - -```sh -cp /boot/vendorfw/firmware.cpio ~/.dotfiles/firmware/ -git -C ~/.dotfiles add -f firmware/firmware.cpio -``` - -(They're `.gitignore`-exempt via `-f` if needed — but the flake only sees -**tracked** files, so they must be added.) - -## ⚠ Keep this repository PRIVATE - -This firmware is **non-free and non-redistributable**. Do not push it to a -public remote. - -Until you copy these files in, `nixos-rebuild`/`nixos-install` will fail at the -firmware-extraction step — that's expected, same as the placeholder -`hardware-configuration.nix`. diff --git a/firmware/all_firmware.tar.gz b/firmware/all_firmware.tar.gz deleted file mode 100755 index 789eb34..0000000 Binary files a/firmware/all_firmware.tar.gz and /dev/null differ diff --git a/firmware/firmware.cpio b/firmware/firmware.cpio deleted file mode 100644 index ece822c..0000000 Binary files a/firmware/firmware.cpio and /dev/null differ diff --git a/firmware/kernelcache.release.mac13j b/firmware/kernelcache.release.mac13j deleted file mode 100755 index 71881bf..0000000 Binary files a/firmware/kernelcache.release.mac13j and /dev/null differ diff --git a/flake.lock b/flake.lock index 55bd3df..029bd05 100644 --- a/flake.lock +++ b/flake.lock @@ -1,26 +1,5 @@ { "nodes": { - "apple-silicon": { - "inputs": { - "flake-compat": "flake-compat", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1785426242, - "narHash": "sha256-QHAP8KsJQmI+dpNS/wfWAtEBQ0Zby+B0Ty+qZIO/U2w=", - "owner": "nix-community", - "repo": "nixos-apple-silicon", - "rev": "66d8dd2c27f99bd5420c99938b60695aac1785c4", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixos-apple-silicon", - "type": "github" - } - }, "firefox-addons": { "inputs": { "nixpkgs": [ @@ -43,21 +22,6 @@ "type": "gitlab" } }, - "flake-compat": { - "locked": { - "lastModified": 1761640442, - "narHash": "sha256-AtrEP6Jmdvrqiv4x2xa5mrtaIp3OEe8uBYCDZDS+hu8=", - "owner": "nix-community", - "repo": "flake-compat", - "rev": "4a56054d8ffc173222d09dad23adf4ba946c8884", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "flake-compat", - "type": "github" - } - }, "home-manager": { "inputs": { "nixpkgs": [ @@ -113,7 +77,6 @@ }, "root": { "inputs": { - "apple-silicon": "apple-silicon", "firefox-addons": "firefox-addons", "home-manager": "home-manager", "linear-tui-src": "linear-tui-src", diff --git a/flake.nix b/flake.nix index 4650ea1..01dd1ba 100644 --- a/flake.nix +++ b/flake.nix @@ -1,14 +1,9 @@ { - description = "mads — NixOS for Apple Silicon (mbp) and x86 (pc), one flake"; + description = "mads — NixOS on x86_64, one flake"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - apple-silicon = { - url = "github:nix-community/nixos-apple-silicon"; - inputs.nixpkgs.follows = "nixpkgs"; - }; - home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; @@ -34,7 +29,7 @@ }; }; - outputs = { self, nixpkgs, apple-silicon, home-manager, firefox-addons, zen-browser, linear-tui-src, ... }: + outputs = { self, nixpkgs, home-manager, firefox-addons, zen-browser, linear-tui-src, ... }: let # linear-tui, built from the pinned source input above. Upstream ships no # flake and it is not in nixpkgs, but it has a committed Cargo.lock, so @@ -55,48 +50,17 @@ meta.mainProgram = "linear-tui"; }; - # ───────────────────── shared home-manager user ───────────────────── - home = { pkgs, osConfig, ... }: { + # ───────────────────────── home-manager user ───────────────────────── + home = { pkgs, ... }: { imports = [ zen-browser.homeModules.beta ]; home.stateVersion = "25.11"; - programs.eww = { - enable = true; - package = pkgs.eww; - }; - # Raw configs that stay files (no good native module). - # `hypr` is recursive so we can drop a host-specific monitors.conf in - # alongside the shared files (hyprland.conf `source`s it). xdg.configFile = { - "hypr" = { source = ./config/hypr; recursive = true; }; - "hypr/monitors.conf".text = - if osConfig.networking.hostName == "mbp" - then '' - monitor = , preferred, auto, 2.0 - - # Floating TUI panels: 70% wide, full height. Absolute px because - # Hyprland 0.56 ignores percentages in `size`. 1728x1080 logical. - windowrule = match:class ^(panel-wifi|panel-bt)$, float on, size 1210 1080, center on - '' - else '' - monitor = desc:Lenovo Group Limited P27q-20 V909LRFR, 2560x1440@60, 0x0, 1.0 - monitor = desc:Lenovo Group Limited P27q-20 V909LPNY, 2560x1440@60, 2560x0, 1.0 - monitor = desc:Lenovo Group Limited P27q-20 V909LRDD, 2560x1440@60, 5120x0, 1.0 - - # Each screen's home workspace; SUPER+ALT+h/l can still move it. - workspace = 1, monitor:desc:Lenovo Group Limited P27q-20 V909LRFR, default:true - workspace = 2, monitor:desc:Lenovo Group Limited P27q-20 V909LPNY, default:true - workspace = 3, monitor:desc:Lenovo Group Limited P27q-20 V909LRDD, default:true - - # Same panels, sized for 2560x1440 logical. - windowrule = match:class ^(panel-wifi|panel-bt)$, float on, size 1792 1440, center on - ''; - "eww".source = ./config/eww; - "fuzzel".source = ./config/fuzzel; + "hypr".source = ./config/hypr; + "fuzzel".source = ./config/fuzzel; }; - # Launcher hygiene. These .desktop entries ship with packages we do want, # but they are noise in fuzzel. A NoDisplay entry in XDG_DATA_HOME # shadows the package's own copy, which is the only way to hide one @@ -125,7 +89,7 @@ # Notification daemon. Nothing owned org.freedesktop.Notifications before # this, so notify-send failed outright: hyprshot's "Screenshot saved" # toasts went nowhere, and kitty logged a DBus ServiceUnknown error on - # every launch. Colours match the cyberdream kitty theme above. + # every launch. Colours match the cyberdream kitty theme below. services.mako = { enable = true; settings = { @@ -222,7 +186,7 @@ ]; }; - # Zen browser + Tridactyl, extensions pinned (works on aarch64 + x86). + # Zen browser + Tridactyl, extensions pinned. programs.zen-browser = { enable = true; setAsDefaultBrowser = true; @@ -253,7 +217,7 @@ ]; }; }; - + # zsh + starship, no framework. programs.zsh = { enable = true; @@ -263,8 +227,6 @@ }; programs.starship.enable = true; - - # SSH auth via the 1Password agent — private keys stay in the vault, # never on disk or in the Nix store. programs.ssh = { @@ -294,8 +256,11 @@ home.packages = with pkgs; [ ripgrep fd tridactyl-native lazygit rustc cargo clippy rustfmt rust-analyzer claude-code gcc bluetui impala postgresql fastfetch (linearTui pkgs) ]; }; - # ───────────────────── shared system (both hosts) ───────────────────── - common = { pkgs, ... }: { + # ──────────────────────────── the machine ──────────────────────────── + pc = { config, pkgs, ... }: { + networking.hostName = "pc"; + nixpkgs.config.allowUnfree = true; + nix.settings.experimental-features = [ "nix-command" "flakes" ]; # Trusted so client-side nix config takes effect — substituters and # remote builders are trusted settings, silently ignored for anyone @@ -315,9 +280,7 @@ # the only form the calling process cannot read. nix.settings.netrc-file = "/etc/nix/netrc"; - # x86_64 derivations build off this machine rather than under local - # qemu emulation, and aarch64 ones go out too when the local - # machine is busy. + # Big builds go out to other machines rather than tying this one up. # # The host keys are pinned system-wide because the ssh'ing party is # the root daemon, which has no known_hosts and never gets a tty to @@ -342,8 +305,8 @@ maxJobs = 16; supportedFeatures = [ "big-parallel" "kvm" "nixos-test" ]; } - # nixbuild.net, for both architectures. Listed after `builder` so - # the machine we already pay for is preferred. + # nixbuild.net. Listed after `builder` so the machine we already pay + # for is preferred. # # Every feature it supports is advertised, not just the two in the # quickstart: nix only sends a derivation to a builder claiming @@ -358,15 +321,6 @@ maxJobs = 100; supportedFeatures = [ "benchmark" "big-parallel" "ca-derivations" "kvm" "nixos-test" ]; } - { - hostName = "eu.nixbuild.net"; - sshUser = "root"; - sshKey = "/home/mads/.ssh/id_ed25519"; - protocol = "ssh-ng"; - system = "aarch64-linux"; - maxJobs = 100; - supportedFeatures = [ "benchmark" "big-parallel" "ca-derivations" "kvm" "nixos-test" ]; - } ]; # iwd owns Wi-Fi (driven from impala, which is iwd-only); networkd does @@ -377,6 +331,19 @@ networking.useNetworkd = true; # DHCP on any ethernet/wifi by default systemd.network.wait-online.anyInterface = true; # one link up is enough + # GigE camera link: static, never a route out. The segment also + # carries AAU's IPv6 RAs, and taking them made v6 traffic default + # out this port into a dead end. + networking.interfaces.enp7s0 = { + useDHCP = false; + ipv4.addresses = [ { address = "192.168.12.1"; prefixLength = 24; } ]; + }; + systemd.network.networks."40-enp7s0" = { + networkConfig.IPv6AcceptRA = false; + networkConfig.ConfigureWithoutCarrier = true; # camera may be off + linkConfig.RequiredForOnline = "no"; + }; + # iwd only reads /var/lib/iwd. C = copy once, so a password added to # the file later (or via impala) is never overwritten. systemd.tmpfiles.rules = [ @@ -454,12 +421,25 @@ }; }; + # Desktop: never suspend or hibernate, even if something asks. + systemd.sleep.settings.Sleep = { + AllowSuspend = "no"; + AllowHibernation = "no"; + AllowHybridSleep = "no"; + AllowSuspendThenHibernate = "no"; + }; + # Ignore the keys that would normally trigger sleep. + services.logind.settings.Login = { + HandleSuspendKey = "ignore"; + HandleHibernateKey = "ignore"; + HandleLidSwitch = "ignore"; + }; + xdg.portal = { enable = true; extraPortals = [ pkgs.xdg-desktop-portal-hyprland ]; }; - # greetd autologins mads straight into Hyprland (via uwsm). services.greetd = { enable = true; @@ -469,6 +449,19 @@ }; }; + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; # normal x86 UEFI + + # NVIDIA (RTX 20-series or newer → open kernel module). + services.xserver.videoDrivers = [ "nvidia" ]; + hardware.graphics.enable = true; # OpenGL/Vulkan userspace (was hardware.opengl) + hardware.nvidia = { + modesetting.enable = true; # required for Wayland/Hyprland + open = true; # open kernel module (Turing+) + nvidiaSettings = true; + package = config.boot.kernelPackages.nvidiaPackages.stable; + }; + virtualisation.docker.enable = true; hardware.bluetooth.enable = true; @@ -536,151 +529,20 @@ home-manager.users.mads = home; }; - mkHost = { system, modules }: nixpkgs.lib.nixosSystem { - inherit system; - modules = [ - home-manager.nixosModules.home-manager - common - ({ pkgs, ... }: { - nixpkgs.config.allowUnfree = true; - }) - ] ++ modules; - }; - in { - nixosConfigurations = { - # ── Apple Silicon MacBook (Asahi) ── - mbp = mkHost { - system = "aarch64-linux"; - modules = [ - apple-silicon.nixosModules.apple-silicon-support - ./hosts/mbp/hardware-configuration.nix # generated on the Mac - ({ ... }: { - networking.hostName = "mbp"; - - # Wi-Fi/BT firmware, vendored (a pure flake can't read /boot/asahi). - hardware.asahi.peripheralFirmwareDirectory = ./firmware; - hardware.asahi.enable = true; - - boot.loader.systemd-boot.enable = true; - boot.loader.systemd-boot.configurationLimit = 3; # 500M ESP is small - boot.extraModprobeConfig = "options hid_apple fnmode=1"; - boot.blacklistedKernelModules = [ "pcspkr" ]; - - # Root is btrfs (p8). A scrub re-reads every block and verifies its - # checksum, which is the only way bit rot on this SSD surfaces before - # something tries to read the damaged file. Metadata is DUP, so a bad - # metadata block gets repaired from its copy automatically. - services.btrfs.autoScrub = { - enable = true; - interval = "monthly"; - fileSystems = [ "/" ]; - }; - - # 15G of RAM and no swap at all: a `nixos-rebuild` forks ~60 nix - # evaluators, and stacked on a browser and a few editor sessions - # that was enough to exhaust it. The kernel then OOM-killed a - # process inside wayland-wm@hyprland.service, and systemd's default - # OOMPolicy=stop tore the whole graphical session down with it. - # - # zram rather than a swapfile, because root is compress=zstd and a - # btrfs swapfile needs its own nodatacow, uncompressed subvolume. - zramSwap = { - enable = true; - memoryPercent = 50; # 7.6G of backing store, ~a third of that in real RAM - }; - - # Swapping to RAM is cheap, so let the kernel compress anon pages - # rather than evict page cache. At the OOM above, cache had already - # been squeezed to 40M while 13G sat in anon and nothing was - # reclaimable — the default swappiness of 60 gets that backwards here. - boot.kernel.sysctl = { - "vm.swappiness" = 180; - "vm.page-cluster" = 0; # zram has no seek penalty, so no readahead - }; - - # Build x86_64 derivations (packing-station iso/deploys) via qemu. - boot.binfmt.emulatedSystems = [ "x86_64-linux" ]; - - # Resolve .local names, so the packing stations can be reached and - # deployed to by hostname instead of by address. - services.avahi = { - enable = true; - nssmdns4 = true; - }; - services.resolved.settings.Resolve.MulticastDNS = false; # avahi owns mDNS - - # Asahi kernel + Mesa cache, and the Raspberry Pi vendor - # kernel/firmware cache (else both compile from source). - nix.settings = { - extra-substituters = [ - "https://nixos-apple-silicon.cachix.org" - "https://nixos-raspberrypi.cachix.org" - ]; - extra-trusted-public-keys = [ - "nixos-apple-silicon.cachix.org-1:8psDu5SA5dAD7qA0zMy5UT292TxeEPzIz8VVEr2Js20=" - "nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI=" - ]; - }; - }) - ]; - }; - - # ── Arbitrary x86_64 PC ── - pc = mkHost { - system = "x86_64-linux"; - modules = [ - ./hosts/pc/hardware-configuration.nix # generated on the PC - ({ config, ... }: { - networking.hostName = "pc"; - - # GigE camera link: static, never a route out. The segment also - # carries AAU's IPv6 RAs, and taking them made v6 traffic default - # out this port into a dead end. - networking.interfaces.enp7s0 = { - useDHCP = false; - ipv4.addresses = [ { address = "192.168.12.1"; prefixLength = 24; } ]; - }; - systemd.network.networks."40-enp7s0" = { - networkConfig.IPv6AcceptRA = false; - networkConfig.ConfigureWithoutCarrier = true; # camera may be off - linkConfig.RequiredForOnline = "no"; - }; - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; # normal x86 UEFI - - # Desktop: never suspend or hibernate, even if something asks. - systemd.sleep.settings.Sleep = { - AllowSuspend = "no"; - AllowHibernation = "no"; - AllowHybridSleep = "no"; - AllowSuspendThenHibernate = "no"; - }; - # Ignore the keys that would normally trigger sleep. - services.logind.suspendKey = "ignore"; - services.logind.hibernateKey = "ignore"; - services.logind.lidSwitch = "ignore"; - - # NVIDIA (RTX 20-series or newer → open kernel module). - services.xserver.videoDrivers = [ "nvidia" ]; - hardware.graphics.enable = true; # OpenGL/Vulkan userspace (was hardware.opengl) - hardware.nvidia = { - modesetting.enable = true; # required for Wayland/Hyprland - open = true; # open kernel module (Turing+) - nvidiaSettings = true; - package = config.boot.kernelPackages.nvidiaPackages.stable; - }; - }) - ]; - }; + nixosConfigurations.pc = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + home-manager.nixosModules.home-manager + ./hardware-configuration.nix + pc + ]; }; - # `nix develop` on either arch. - devShells = nixpkgs.lib.genAttrs [ "aarch64-linux" "x86_64-linux" ] (system: { - default = nixpkgs.legacyPackages.${system}.mkShell { - packages = [ nixpkgs.legacyPackages.${system}.nodejs ]; + devShells.x86_64-linux.default = + nixpkgs.legacyPackages.x86_64-linux.mkShell { + packages = [ nixpkgs.legacyPackages.x86_64-linux.nodejs ]; }; - }); }; } diff --git a/hosts/pc/hardware-configuration.nix b/hardware-configuration.nix similarity index 100% rename from hosts/pc/hardware-configuration.nix rename to hardware-configuration.nix diff --git a/hosts/mbp/hardware-configuration.nix b/hosts/mbp/hardware-configuration.nix deleted file mode 100644 index 21211e3..0000000 --- a/hosts/mbp/hardware-configuration.nix +++ /dev/null @@ -1,34 +0,0 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - -{ - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; - - boot.initrd.availableKernelModules = [ "usb_storage" "sdhci_pci" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ ]; - boot.extraModulePackages = [ ]; - - # Root lives on nvme0n1p8 (btrfs, subvol @) — the 256G reclaimed from - # the shrunk macOS container. The old ext4 p5 is kept as a rollback until - # it is added to this pool as a second device. - fileSystems."/" = - { device = "/dev/disk/by-uuid/c828c1a0-ce7b-4e27-b8e4-bce032bb30bf"; - fsType = "btrfs"; - options = [ "subvol=@" "compress=zstd" "noatime" ]; - }; - - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/0BB8-A960"; - fsType = "vfat"; - options = [ "fmask=0022" "dmask=0022" ]; - }; - - swapDevices = [ ]; - - nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; -}