feat(apps): starter workstation app suite + steam/libvirt/obs services

The "default application suite" roadmap item, but deliberately NOT a
nomarchy.apps.* option surface: a bare package install has no config to
put behind a toggle, so a thin `mkIf x { systemPackages = [p]; }` only
reinvents what a package list already gives. Instead the suite is a
curated home.packages list in templates/downstream/home.nix (extending
the existing `# firefox` convention) — active staples (libreoffice,
vscode, gimp, inkscape, mpv, amberol) plus commented suggestions. The
opt-out is deleting a line; it also keeps the apps out of the live ISO
automatically (the ISO never scaffolds from the template).

The members that DO need system config become nomarchy.services.* opt-in
toggles instead (config behind the switch, like the existing services):
  - steam   → programs.steam (32-bit stack, controller udev, RP ports)
  - libvirt → libvirtd + virt-manager, login user added to libvirtd group
  - obs     → obs-studio + a v4l2loopback virtual camera (exclusive_caps=1)
              selectable as a webcam in Zoom/Teams

README option table, ROADMAP (services item now "Eight shipped"; suite
item marked done with the no-surface rationale) and the downstream
system.nix examples updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-06-17 20:45:10 +01:00
parent 1f4bd3d5fa
commit 0c668c2eb1
5 changed files with 118 additions and 17 deletions

View File

@@ -224,6 +224,9 @@ examples: **[docs/OVERRIDES.md](docs/OVERRIDES.md)**.
| `nomarchy.services.podman.enable` | `false` | Opt-in: rootless Podman (`docker` aliased to it) | | `nomarchy.services.podman.enable` | `false` | Opt-in: rootless Podman (`docker` aliased to it) |
| `nomarchy.services.flatpak.enable` | `false` | Opt-in: Flatpak + the Flathub remote | | `nomarchy.services.flatpak.enable` | `false` | Opt-in: Flatpak + the Flathub remote |
| `nomarchy.services.pika.enable` | `false` | Opt-in: Pika Backup (GUI Borg backups) | | `nomarchy.services.pika.enable` | `false` | Opt-in: Pika Backup (GUI Borg backups) |
| `nomarchy.services.steam.enable` | `false` | Opt-in: Steam via `programs.steam` (32-bit libs, controller udev, Remote-Play ports) |
| `nomarchy.services.libvirt.enable` | `false` | Opt-in: libvirt/KVM + virt-manager GUI (login user added to `libvirtd`) |
| `nomarchy.services.obs.enable` | `false` | Opt-in: OBS Studio + a v4l2loopback virtual camera (selectable as a webcam in Zoom/Teams) |
Beyond the `nomarchy.*` surface, the system layer turns on the usual Beyond the `nomarchy.*` surface, the system layer turns on the usual
desktop services with `lib.mkDefault` (override natively). One worth desktop services with `lib.mkDefault` (override natively). One worth
@@ -336,6 +339,12 @@ reload # exec zsh (reload the shell)
example of it in `templates/downstream/home.nix` or `system.nix`. New example of it in `templates/downstream/home.nix` or `system.nix`. New
installs then enable it by uncommenting + tweaking, rather than hunting the installs then enable it by uncommenting + tweaking, rather than hunting the
docs for the option name. docs for the option name.
- **Applications:** the starter complete-workstation set (LibreOffice, VS
Code, GIMP, Inkscape) lives in the `home.packages` list in your
`home.nix` — it's a plain package list, so curate it directly: delete a
line to slim the machine, uncomment an extra (a browser, email, full TeX
Live), or add your own. No `nomarchy.apps.*` toggles — a package list is
already its own opt-out, so the distro doesn't impose these or wrap them.
## Roadmap & known issues ## Roadmap & known issues

View File

@@ -138,11 +138,21 @@ how to override it. Items marked ✓ are shipped.
tracks the palette), `ls`→eza, `cd`→zoxide, plus `lt`/`tree`. tracks the palette), `ls`→eza, `cd`→zoxide, plus `lt`/`tree`.
`nomarchy.shell.enable`. (Deliberately did NOT alias grep→rg / find→fd: `nomarchy.shell.enable`. (Deliberately did NOT alias grep→rg / find→fd:
their flags differ enough to surprise; `rg`/`fd` ship as themselves.) their flags differ enough to surprise; `rg`/`fd` ship as themselves.)
- **Default application suite:** install a complete-workstation set - **Default application suite:** a starter complete-workstation set
(vscode, libreoffice, gimp, inkscape, texlive-full, …) behind a `libreoffice-fresh`, `vscode`, `gimp`, `inkscape` — ships *active* in the
`nomarchy.apps.*` option surface so each is individually opt-out for downstream `templates/downstream/home.nix` `home.packages`, with the heavier
users who want a leaner machine. Watch closure size (texlive-full is opt-ins (`texliveFull` — multi-GB; `texliveMedium` is lighter — plus
multi-GB — likely default-off or a lighter scheme). browser/email) commented just below. **Decision: no `nomarchy.apps.*` option
surface.** Unlike `nomarchy.services.*` (real config behind each toggle —
systemd units, subuid ranges, the Flathub oneshot), a bare package install
has nothing behind the toggle: `mkIf x { environment.systemPackages = [p]; }`
just reinholds what a package list already gives, and the honest opt-out for
a package is *deleting the line*. So the suite is the user's own curated list
(extending the existing `# firefox` convention), not a distro-module feature —
which also keeps the apps out of the live ISO automatically (it never starts
from the template) and respects that editor/office/graphics are personal-taste
choices, not defaults to impose. Unfree `vscode` evaluates fine — `mkFlake`
and the system both set `allowUnfree = true`.
-**Plymouth logo contrast:** the shipped art was a fixed navy that -**Plymouth logo contrast:** the shipped art was a fixed navy that
vanished on dark bases. `modules/nixos/plymouth.nix` now recolors every vanished on dark bases. `modules/nixos/plymouth.nix` now recolors every
element from the palette at build time (flat fill, alpha kept): element from the palette at build time (flat fill, alpha kept):
@@ -281,19 +291,24 @@ how to override it. Items marked ✓ are shipped.
application suite above — heavier or more personal integrations shipped application suite above — heavier or more personal integrations shipped
**off by default**, each a `nomarchy.services.<name>.enable` toggle a **off by default**, each a `nomarchy.services.<name>.enable` toggle a
downstream flips on in one line. Keeps the base lean while making common downstream flips on in one line. Keeps the base lean while making common
additions trivial. **Five shipped** in `modules/nixos/services.nix` additions trivial. **Eight shipped** in `modules/nixos/services.nix`
(system-side), each with a commented example in the downstream `system.nix` (system-side), each with a commented example in the downstream `system.nix`
template: `tailscale`, `syncthing` (runs as the login user, GUI on template: `tailscale`, `syncthing` (runs as the login user, GUI on
127.0.0.1:8384), `podman` (rootless, `docker` aliased, user subuid/subgid), 127.0.0.1:8384), `podman` (rootless, `docker` aliased, user subuid/subgid),
`flatpak` (+ Flathub remote added by a oneshot), `pika` (Pika Backup GUI). `flatpak` (+ Flathub remote added by a oneshot), `pika` (Pika Backup GUI),
More candidates by area: `steam` (`programs.steam` — the 32-bit stack, controller udev, Remote-Play
ports a bare package can't), `libvirt` (libvirtd + virt-manager, user added
to the `libvirtd` group), `obs` (OBS Studio + a v4l2loopback virtual camera
usable as a webcam in Zoom/Teams). More candidates by area:
-**cloud/sync:** Syncthing (`services.syncthing`); Nextcloud client (todo) -**cloud/sync:** Syncthing (`services.syncthing`); Nextcloud client (todo)
- **local AI:** LM Studio (`lmstudio`); Ollama (`services.ollama`, optional - **local AI:** LM Studio ships as a (commented) app-suite package — a bare
GPU accel) — pairs with the menu's Ask-Claude philosophy GUI, no service config; Ollama (`services.ollama`, optional GPU accel) is
-**containers/VMs:** Podman (`virtualisation.podman`); Docker / libvirt + the service still todo — pairs with the menu's Ask-Claude philosophy
virt-manager (todo) -**containers/VMs:** Podman (`virtualisation.podman`); libvirt +
virt-manager (`nomarchy.services.libvirt`); Docker (todo)
-**networking:** Tailscale (`services.tailscale`); WireGuard (todo) -**networking:** Tailscale (`services.tailscale`); WireGuard (todo)
- **gaming/media:** Steam (`programs.steam`); OBS Studio - **gaming/media:** Steam (`nomarchy.services.steam`); OBS Studio
(`nomarchy.services.obs`, with the v4l2loopback virtual camera)
- **devices:** printing (CUPS + Avahi); KDE Connect / phone integration; - **devices:** printing (CUPS + Avahi); KDE Connect / phone integration;
OpenRGB OpenRGB
-**backup:** Pika Backup (`pika-backup`, GUI over Borg); restic/borg -**backup:** Pika Backup (`pika-backup`, GUI over Borg); restic/borg
@@ -303,9 +318,12 @@ how to override it. Items marked ✓ are shipped.
Surface decided: `nomarchy.services.*`, system-side for system services Surface decided: `nomarchy.services.*`, system-side for system services
(home-side ones can extend the same prefix later). Remaining: curate the (home-side ones can extend the same prefix later). Remaining: curate the
rest (Ollama, containers, Steam/OBS, printing, backups, Flatpak …) and rest (Ollama, containers, Steam/OBS, printing, backups, Flatpak …). The
decide how it relates to `nomarchy.apps.*` (opt-out suite). Unfree entries opt-out application *suite* is deliberately **not** a parallel
are already covered (`allowUnfree = true`). `nomarchy.apps.*` surface — it's a curated `home.packages` list in the
downstream template (see "Default application suite" above), since a bare
package install has no config to put behind a toggle. Unfree entries are
already covered (`allowUnfree = true`).
-**Display / monitor management:** declarative `nomarchy.monitors` (a -**Display / monitor management:** declarative `nomarchy.monitors` (a
per-output schema — name/resolution/position/scale/transform/mirror/ per-output schema — name/resolution/position/scale/transform/mirror/
bitdepth/vrr/disable) generates Hyprland `monitor` rules, keeping the bitdepth/vrr/disable) generates Hyprland `monitor` rules, keeping the

View File

@@ -29,6 +29,22 @@ in
pika.enable = lib.mkEnableOption '' pika.enable = lib.mkEnableOption ''
Pika Backup, a friendly GUI for scheduled Borg backups (the app; Pika Backup, a friendly GUI for scheduled Borg backups (the app;
configure repositories and schedules inside it)''; configure repositories and schedules inside it)'';
steam.enable = lib.mkEnableOption ''
Steam (Valve's game store/launcher) via programs.steam which wires up
the 32-bit graphics libraries, controller udev rules and Remote-Play
firewall ports a bare package can't. Unfree'';
libvirt.enable = lib.mkEnableOption ''
libvirt/KVM virtualisation with the virt-manager GUI runs the
libvirtd daemon and adds the login user to the `libvirtd` group, so VMs
can be managed without root'';
obs.enable = lib.mkEnableOption ''
OBS Studio for screen recording and streaming, plus a v4l2loopback
virtual camera so an OBS scene can be selected as a webcam in Zoom,
Teams or a browser (screen capture itself already works over the
desktop's PipeWire portal)'';
}; };
config = lib.mkMerge [ config = lib.mkMerge [
@@ -80,5 +96,31 @@ in
(lib.mkIf cfg.pika.enable { (lib.mkIf cfg.pika.enable {
environment.systemPackages = [ pkgs.pika-backup ]; environment.systemPackages = [ pkgs.pika-backup ];
}) })
(lib.mkIf cfg.steam.enable {
# The Steam package alone misses the system bits a game needs: the
# 32-bit graphics stack, controller udev rules, Remote-Play ports.
programs.steam.enable = true;
})
(lib.mkIf cfg.libvirt.enable {
virtualisation.libvirtd.enable = true;
programs.virt-manager.enable = true;
# Group membership lets the user reach the system libvirtd socket
# (manage VMs) without sudo. Merges with the user's other extraGroups.
users.users.${args.username}.extraGroups = [ "libvirtd" ];
})
(lib.mkIf cfg.obs.enable {
environment.systemPackages = [ pkgs.obs-studio ];
# Virtual camera: OBS streams a scene into a v4l2 loopback device that
# Zoom/Teams/browsers then pick up as a webcam. exclusive_caps=1 is the
# bit that makes those apps actually list the device.
boot.extraModulePackages = [ config.boot.kernelPackages.v4l2loopback ];
boot.kernelModules = [ "v4l2loopback" ];
boot.extraModprobeConfig = ''
options v4l2loopback devices=1 video_nr=10 card_label="OBS Virtual Camera" exclusive_caps=1
'';
})
]; ];
} }

View File

@@ -34,7 +34,36 @@
# nomarchy.keyboard.layouts = [ "de" "fr" ]; # rofi-prompt for a layout when a # nomarchy.keyboard.layouts = [ "de" "fr" ]; # rofi-prompt for a layout when a
# # new keyboard connects + remember it # # new keyboard connects + remember it
# ── Application suite ───────────────────────────────────────────────
# A starter complete-workstation set, installed for your user — yours to
# curate. Delete a line to slim the machine; uncomment a suggestion (or
# add your own) to extend it. The desktop itself — terminal, editor
# keybinds, theming — comes from the modules; these are the heavier
# standalone apps the distro doesn't impose by default.
#
# Gaming (Steam) and VMs (virt-manager) are NOT here — they need system
# setup beyond a package (32-bit libs, a daemon, group membership), so
# they're opt-in service toggles in system.nix instead
# (nomarchy.services.steam / nomarchy.services.libvirt).
home.packages = with pkgs; [ home.packages = with pkgs; [
# firefox libreoffice-fresh # office suite (documents, sheets, slides)
vscode # code editor (unfree; allowUnfree is on)
gimp # raster image editor
inkscape # vector graphics
mpv # media player
amberol # music player (local library; streaming → spotify below)
# ── Uncomment to add ──
# firefox # a web browser (pick your own)
# thunderbird # email client
# signal-desktop # Signal messenger
# telegram-desktop # Telegram
# zoom-us # Zoom video calls (unfree)
# teams-for-linux # Microsoft Teams (community client — no official Linux app)
# logseq # notes / outliner (PKM)
# lmstudio # local LLM runner (unfree; large closure)
# kdePackages.kdenlive # non-linear video editor (pulls in KDE libs)
# spotify # music streaming (unfree)
# texliveFull # full LaTeX toolchain — multi-GB (texliveMedium is lighter)
]; ];
} }

View File

@@ -36,6 +36,9 @@
# nomarchy.services.podman.enable = true; # rootless containers (docker → podman) # nomarchy.services.podman.enable = true; # rootless containers (docker → podman)
# nomarchy.services.flatpak.enable = true; # Flatpak + the Flathub remote # nomarchy.services.flatpak.enable = true; # Flatpak + the Flathub remote
# nomarchy.services.pika.enable = true; # Pika Backup (GUI Borg backups) # nomarchy.services.pika.enable = true; # Pika Backup (GUI Borg backups)
# nomarchy.services.steam.enable = true; # Steam (32-bit libs, controllers, ports)
# nomarchy.services.libvirt.enable = true; # libvirt/KVM + virt-manager GUI
# nomarchy.services.obs.enable = true; # OBS Studio + v4l2loopback virtual camera
system.stateVersion = "26.05"; system.stateVersion = "26.05";
} }