Make the whole workstation menu available, all off/commented by default.
home.nix: the bare GUI apps become a categorized commented menu (~50
suggestions across browsers, comms, office, notes, code, graphics, A/V,
media, gaming, files/sync, security, system, local AI) — uncomment to add.
services.nix: the members that need system config (not just a package)
become opt-in nomarchy.services.* toggles, each with a commented example
in the downstream system.nix:
- docker → rootful Docker + user in docker group; asserts against the
podman docker-compat (both provide the `docker` command)
- kdeconnect → programs.kdeconnect (opens phone-pairing ports)
- gamemode → Feral GameMode daemon
- adb → android-tools (programs.adb was removed; systemd ≥258 does
the device uaccess udev rules, so no group needed)
- wireshark → Qt GUI + user in wireshark group (capture without root)
- ollama → local LLM runtime on 127.0.0.1:11434
- printing → CUPS + Avahi/mDNS network printer discovery
README option table and ROADMAP (services item now "Fifteen shipped";
local-AI / containers / gaming / devices areas marked) updated. All seven
branches eval-verified with the toggles forced on; the docker/podman
assertion confirmed firing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
209 lines
8.0 KiB
Nix
209 lines
8.0 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)'';
|
|
|
|
docker.enable = lib.mkEnableOption ''
|
|
Docker (rootful) with the login user in the `docker` group. Mutually
|
|
exclusive with the podman toggle's docker-compat (both provide the
|
|
`docker` command) — enable only one'';
|
|
|
|
kdeconnect.enable = lib.mkEnableOption ''
|
|
KDE Connect for phone integration — shared clipboard, notifications and
|
|
file transfer with a paired phone; opens the firewall ports it needs'';
|
|
|
|
gamemode.enable = lib.mkEnableOption ''
|
|
Feral GameMode — a daemon games ask to apply a performance CPU governor
|
|
and IO/nice priorities while running (via `gamemoderun`)'';
|
|
|
|
adb.enable = lib.mkEnableOption ''
|
|
the Android platform tools (adb/fastboot) for flashing/debugging phones.
|
|
systemd ≥258 applies the device uaccess udev rules automatically, so the
|
|
tools alone are enough — no group dance'';
|
|
|
|
wireshark.enable = lib.mkEnableOption ''
|
|
Wireshark (the Qt GUI) for packet capture, with the login user in the
|
|
`wireshark` group so capture works without root'';
|
|
|
|
ollama.enable = lib.mkEnableOption ''
|
|
Ollama, a local LLM runtime serving an API on 127.0.0.1:11434 (pair it
|
|
with the lmstudio/alpaca GUIs). CPU by default — set
|
|
`services.ollama.acceleration` natively for GPU offload'';
|
|
|
|
printing.enable = lib.mkEnableOption ''
|
|
CUPS printing with Avahi/mDNS, so network printers are auto-discovered
|
|
(add vendor drivers via `services.printing.drivers`)'';
|
|
};
|
|
|
|
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
|
|
'';
|
|
})
|
|
|
|
(lib.mkIf cfg.docker.enable {
|
|
virtualisation.docker.enable = true;
|
|
users.users.${args.username}.extraGroups = [ "docker" ];
|
|
# Podman's docker-compat and real Docker both claim the `docker`
|
|
# command — guard against enabling both (unless you turn that off).
|
|
assertions = [{
|
|
assertion = !(cfg.podman.enable && config.virtualisation.podman.dockerCompat);
|
|
message = ''
|
|
nomarchy.services: docker and podman both provide the `docker`
|
|
command. Enable only one, or set
|
|
`virtualisation.podman.dockerCompat = false`.
|
|
'';
|
|
}];
|
|
})
|
|
|
|
(lib.mkIf cfg.kdeconnect.enable {
|
|
programs.kdeconnect.enable = true; # installs the app and opens its ports
|
|
})
|
|
|
|
(lib.mkIf cfg.gamemode.enable {
|
|
programs.gamemode.enable = true;
|
|
})
|
|
|
|
(lib.mkIf cfg.adb.enable {
|
|
# `programs.adb` was removed — systemd ≥258 handles the device uaccess
|
|
# udev rules, so the tools package is all that's needed now.
|
|
environment.systemPackages = [ pkgs.android-tools ];
|
|
})
|
|
|
|
(lib.mkIf cfg.wireshark.enable {
|
|
programs.wireshark = {
|
|
enable = true;
|
|
package = pkgs.wireshark; # the Qt GUI (the module defaults to the CLI)
|
|
};
|
|
users.users.${args.username}.extraGroups = [ "wireshark" ];
|
|
})
|
|
|
|
(lib.mkIf cfg.ollama.enable {
|
|
services.ollama.enable = true;
|
|
})
|
|
|
|
(lib.mkIf cfg.printing.enable {
|
|
services.printing.enable = true;
|
|
# mDNS so network printers show up without manual setup.
|
|
services.avahi = {
|
|
enable = true;
|
|
nssmdns4 = true;
|
|
openFirewall = true;
|
|
};
|
|
})
|
|
];
|
|
}
|