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>
127 lines
4.9 KiB
Nix
127 lines
4.9 KiB
Nix
# Opt-in services & integrations — off by default, one toggle each, enabled
|
|
# in system.nix (see the commented examples in the downstream template).
|
|
# These are system-side: their own `nomarchy.services.*` namespace, distinct
|
|
# from the distro's core `nomarchy.system.*` toggles. `username` (from
|
|
# specialArgs) is read lazily, only where a service needs it.
|
|
{ config, lib, pkgs, ... }@args:
|
|
|
|
let
|
|
cfg = config.nomarchy.services;
|
|
in
|
|
{
|
|
options.nomarchy.services = {
|
|
tailscale.enable = lib.mkEnableOption ''
|
|
Tailscale, the mesh VPN — ships the daemon; authenticate once with
|
|
`sudo tailscale up`'';
|
|
|
|
syncthing.enable = lib.mkEnableOption ''
|
|
Syncthing continuous file sync, running as the login user — add
|
|
folders and devices in the web UI at http://127.0.0.1:8384'';
|
|
|
|
podman.enable = lib.mkEnableOption ''
|
|
Podman for rootless containers, with `docker` aliased to it and DNS on
|
|
the default network; the login user gets a subuid/subgid range'';
|
|
|
|
flatpak.enable = lib.mkEnableOption ''
|
|
Flatpak, with the Flathub remote added system-wide — install apps with
|
|
`flatpak install flathub <app>`'';
|
|
|
|
pika.enable = lib.mkEnableOption ''
|
|
Pika Backup, a friendly GUI for scheduled Borg backups (the app;
|
|
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 [
|
|
(lib.mkIf cfg.tailscale.enable {
|
|
services.tailscale.enable = true;
|
|
})
|
|
|
|
(lib.mkIf cfg.syncthing.enable {
|
|
services.syncthing = {
|
|
enable = true;
|
|
user = args.username;
|
|
# Manage folders/devices in the GUI; don't let the (empty) declarative
|
|
# config wipe them on a rebuild.
|
|
overrideDevices = false;
|
|
overrideFolders = false;
|
|
guiAddress = "127.0.0.1:8384";
|
|
};
|
|
})
|
|
|
|
(lib.mkIf cfg.podman.enable {
|
|
virtualisation.podman = {
|
|
enable = true;
|
|
dockerCompat = lib.mkDefault true; # `docker` → podman (off if you run real docker)
|
|
defaultNetwork.settings.dns_enabled = true; # DNS for rootless containers
|
|
};
|
|
# Rootless podman needs a subuid/subgid range for the user.
|
|
users.users.${args.username}.autoSubUidGidRange = lib.mkDefault true;
|
|
})
|
|
|
|
(lib.mkIf cfg.flatpak.enable {
|
|
services.flatpak.enable = true;
|
|
# Flatpak ships no remotes; add Flathub system-wide. Idempotent
|
|
# (--if-not-exists), and it reads the .flatpakrepo over the network, so
|
|
# it waits for connectivity and simply retries next boot if offline.
|
|
systemd.services.nomarchy-flathub = {
|
|
description = "Add the Flathub Flatpak remote";
|
|
wantedBy = [ "multi-user.target" ];
|
|
wants = [ "network-online.target" ];
|
|
after = [ "network-online.target" ];
|
|
path = [ pkgs.flatpak ];
|
|
serviceConfig.Type = "oneshot";
|
|
script = ''
|
|
flatpak remote-add --system --if-not-exists flathub \
|
|
https://dl.flathub.org/repo/flathub.flatpakrepo
|
|
'';
|
|
};
|
|
})
|
|
|
|
(lib.mkIf cfg.pika.enable {
|
|
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
|
|
'';
|
|
})
|
|
];
|
|
}
|