diff --git a/README.md b/README.md index 084ea46..840e64c 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,8 @@ examples: **[docs/OVERRIDES.md](docs/OVERRIDES.md)**. | `nomarchy.services.wireshark.enable` | `false` | Opt-in: Wireshark Qt GUI (user in `wireshark` group, capture without root) | | `nomarchy.services.ollama.enable` | `false` | Opt-in: Ollama local LLM runtime on `127.0.0.1:11434` (CPU; GPU via `services.ollama.acceleration`) | | `nomarchy.services.printing.enable` | `false` | Opt-in: CUPS + Avahi/mDNS network printer discovery | +| `nomarchy.services.openrgb.enable` | `false` | Opt-in: OpenRGB daemon for RGB peripheral/motherboard lighting | +| `nomarchy.services.restic.enable` | `false` | Opt-in: scheduled daily restic backup (set `.repository` + `.passwordFile`; 7/4/6 retention) | Beyond the `nomarchy.*` surface, the system layer turns on the usual desktop services with `lib.mkDefault` (override natively). One worth diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 359e39a..02a69d2 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -291,7 +291,7 @@ how to override it. Items marked ✓ are shipped. application suite above — heavier or more personal integrations shipped **off by default**, each a `nomarchy.services..enable` toggle a downstream flips on in one line. Keeps the base lean while making common - additions trivial. **✓ Fifteen shipped** in `modules/nixos/services.nix` + additions trivial. **✓ Seventeen shipped** in `modules/nixos/services.nix` (system-side), each with a commented example in the downstream `system.nix` template: `tailscale`, `syncthing` (runs as the login user, GUI on 127.0.0.1:8384), `podman` (rootless, `docker` aliased, user subuid/subgid), @@ -302,24 +302,29 @@ how to override it. Items marked ✓ are shipped. usable as a webcam in Zoom/Teams), `docker` (rootful; asserts against the podman docker-compat), `kdeconnect`, `gamemode`, `adb` (android-tools; systemd handles the udev rules), `wireshark` (Qt GUI + the `wireshark` - group), `ollama` (local LLM - API on 127.0.0.1:11434), and `printing` (CUPS + Avahi mDNS). More - candidates by area: - - ✓ **cloud/sync:** Syncthing (`services.syncthing`); Nextcloud client (todo) + group), `ollama` (local LLM API on 127.0.0.1:11434), `printing` (CUPS + + Avahi mDNS), `openrgb` (RGB lighting daemon), and `restic` (scheduled + daily backup — a small option surface: `repository`/`passwordFile`/`paths`, + 7/4/6 retention). More candidates by area: + - ✓ **cloud/sync:** Syncthing (`services.syncthing`); Nextcloud client is a + bare tray app (in the app-suite menu, not a service) - ✓ **local AI:** Ollama (`nomarchy.services.ollama`, optional GPU accel) ships; LM Studio is a (commented) app-suite package (a bare GUI, no service) — pairs with the menu's Ask-Claude philosophy - ✓ **containers/VMs:** Podman (`virtualisation.podman`); libvirt + virt-manager (`nomarchy.services.libvirt`); Docker (`nomarchy.services.docker`) - - ✓ **networking:** Tailscale (`services.tailscale`); WireGuard (todo) + - ✓ **networking:** Tailscale (`services.tailscale`); WireGuard needs no + toggle — NetworkManager (on by default) imports `.conf` tunnels natively; + the `wireguard-tools` CLI is in the app-suite menu - ✓ **gaming/media:** Steam (`nomarchy.services.steam`); OBS Studio (`nomarchy.services.obs`, with the v4l2loopback virtual camera); GameMode (`nomarchy.services.gamemode`) - ✓ **devices:** printing (CUPS + Avahi, `nomarchy.services.printing`); KDE - Connect (`nomarchy.services.kdeconnect`); OpenRGB (todo). Plus dev tooling - — Android `adb` and `wireshark` toggles - - ✓ **backup:** Pika Backup (`pika-backup`, GUI over Borg); restic/borg - services (todo) + Connect (`nomarchy.services.kdeconnect`); OpenRGB + (`nomarchy.services.openrgb`). Plus dev tooling — Android `adb` and + `wireshark` toggles + - ✓ **backup:** Pika Backup (`pika-backup`, GUI over Borg); scheduled + headless restic (`nomarchy.services.restic`) - ✓ **escape hatch:** Flatpak (`services.flatpak`) + Flathub, for apps outside nixpkgs diff --git a/modules/nixos/services.nix b/modules/nixos/services.nix index 8c60057..fef37c6 100644 --- a/modules/nixos/services.nix +++ b/modules/nixos/services.nix @@ -76,6 +76,47 @@ in printing.enable = lib.mkEnableOption '' CUPS printing with Avahi/mDNS, so network printers are auto-discovered (add vendor drivers via `services.printing.drivers`)''; + + openrgb.enable = lib.mkEnableOption '' + the OpenRGB daemon and GUI for controlling RGB lighting on peripherals + and (where supported) motherboards — installs the udev rules for device + access. Some motherboard controllers also need `hardware.i2c.enable`''; + + restic = { + enable = lib.mkEnableOption '' + a scheduled (daily) restic backup — headless, complementing the Pika + GUI. Backs up `paths` with sane retention (7 daily / 4 weekly / + 6 monthly); needs a `repository` and a `passwordFile` (below)''; + + repository = lib.mkOption { + type = lib.types.str; + default = ""; + example = "/mnt/backup/restic"; + description = '' + The restic repository as a path or URL — e.g. `/mnt/backup/restic`, + `sftp:user@host:/srv/restic`, `b2:bucket:/path`. Required when + `restic.enable` is set. + ''; + }; + + passwordFile = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + example = "/etc/nomarchy/restic-password"; + description = '' + Path to a file holding the repository password. Give an absolute + path that lives ON THE MACHINE — not a `./file` in the flake, which + would copy the secret into the world-readable Nix store. Required + when `restic.enable` is set. + ''; + }; + + paths = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ "/home" ]; + description = "Paths to include in the backup."; + }; + }; }; config = lib.mkMerge [ @@ -204,5 +245,34 @@ in openFirewall = true; }; }) + + (lib.mkIf cfg.openrgb.enable { + services.hardware.openrgb.enable = true; + }) + + (lib.mkIf cfg.restic.enable { + assertions = [ + { + assertion = cfg.restic.repository != ""; + message = "nomarchy.services.restic.repository must be set when restic is enabled."; + } + { + assertion = cfg.restic.passwordFile != null; + message = "nomarchy.services.restic.passwordFile must be set when restic is enabled."; + } + ]; + services.restic.backups.nomarchy = { + repository = cfg.restic.repository; + passwordFile = cfg.restic.passwordFile; + paths = cfg.restic.paths; + initialize = true; # create the repo on first run if it doesn't exist + extraBackupArgs = [ "--exclude-caches" ]; + pruneOpts = [ "--keep-daily 7" "--keep-weekly 4" "--keep-monthly 6" ]; + timerConfig = { + OnCalendar = "daily"; + Persistent = true; # catch up a missed run after downtime + }; + }; + }) ]; } diff --git a/templates/downstream/home.nix b/templates/downstream/home.nix index ec897e9..984820b 100644 --- a/templates/downstream/home.nix +++ b/templates/downstream/home.nix @@ -131,6 +131,7 @@ # gnome-disk-utility # gparted # baobab # disk usage + # wireguard-tools # WireGuard CLI (NetworkManager imports .conf tunnels natively) # Local AI (Ollama is a service toggle in system.nix) # lmstudio # (unfree; large closure) diff --git a/templates/downstream/system.nix b/templates/downstream/system.nix index 9b88225..b8ab27b 100644 --- a/templates/downstream/system.nix +++ b/templates/downstream/system.nix @@ -46,6 +46,13 @@ # nomarchy.services.wireshark.enable = true; # Wireshark GUI (wireshark group, no root) # nomarchy.services.ollama.enable = true; # local LLM runtime (127.0.0.1:11434) # nomarchy.services.printing.enable = true; # CUPS + Avahi network printer discovery + # nomarchy.services.openrgb.enable = true; # RGB peripheral/motherboard lighting daemon + # nomarchy.services.restic = { # scheduled (daily) restic backup + # enable = true; + # repository = "/mnt/backup/restic"; # path or URL (sftp:/b2:/…) + # passwordFile = "/etc/nomarchy/restic-password"; # absolute path, NOT in the flake + # paths = [ "/home" ]; + # }; system.stateVersion = "26.05"; }