Compare commits
6 Commits
1f4bd3d5fa
...
v1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82659566ac | ||
|
|
994025f0c8 | ||
|
|
b0b2a4d732 | ||
|
|
964a5c98b7 | ||
|
|
c45fb80b79 | ||
|
|
0c668c2eb1 |
18
README.md
18
README.md
@@ -224,6 +224,18 @@ examples: **[docs/OVERRIDES.md](docs/OVERRIDES.md)**.
|
||||
| `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.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) |
|
||||
| `nomarchy.services.docker.enable` | `false` | Opt-in: rootful Docker (user in `docker` group); don't enable alongside podman |
|
||||
| `nomarchy.services.kdeconnect.enable` | `false` | Opt-in: KDE Connect phone integration (opens its firewall ports) |
|
||||
| `nomarchy.services.gamemode.enable` | `false` | Opt-in: Feral GameMode performance daemon (`gamemoderun`) |
|
||||
| `nomarchy.services.adb.enable` | `false` | Opt-in: Android adb/fastboot tools (systemd handles device udev rules) |
|
||||
| `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; list/restore via the `restic-nomarchy` wrapper) |
|
||||
|
||||
Beyond the `nomarchy.*` surface, the system layer turns on the usual
|
||||
desktop services with `lib.mkDefault` (override natively). One worth
|
||||
@@ -336,6 +348,12 @@ reload # exec zsh (reload the shell)
|
||||
example of it in `templates/downstream/home.nix` or `system.nix`. New
|
||||
installs then enable it by uncommenting + tweaking, rather than hunting the
|
||||
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
|
||||
|
||||
|
||||
@@ -138,11 +138,21 @@ how to override it. Items marked ✓ are shipped.
|
||||
tracks the palette), `ls`→eza, `cd`→zoxide, plus `lt`/`tree`.
|
||||
`nomarchy.shell.enable`. (Deliberately did NOT alias grep→rg / find→fd:
|
||||
their flags differ enough to surprise; `rg`/`fd` ship as themselves.)
|
||||
- **Default application suite:** install a complete-workstation set
|
||||
(vscode, libreoffice, gimp, inkscape, texlive-full, …) behind a
|
||||
`nomarchy.apps.*` option surface so each is individually opt-out for
|
||||
users who want a leaner machine. Watch closure size (texlive-full is
|
||||
multi-GB — likely default-off or a lighter scheme).
|
||||
- ✓ **Default application suite:** a starter complete-workstation set —
|
||||
`libreoffice-fresh`, `vscode`, `gimp`, `inkscape` — ships *active* in the
|
||||
downstream `templates/downstream/home.nix` `home.packages`, with the heavier
|
||||
opt-ins (`texliveFull` — multi-GB; `texliveMedium` is lighter — plus
|
||||
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
|
||||
vanished on dark bases. `modules/nixos/plymouth.nix` now recolors every
|
||||
element from the palette at build time (flat fill, alpha kept):
|
||||
@@ -281,31 +291,51 @@ how to override it. Items marked ✓ are shipped.
|
||||
application suite above — heavier or more personal integrations shipped
|
||||
**off by default**, each a `nomarchy.services.<name>.enable` toggle a
|
||||
downstream flips on in one line. Keeps the base lean while making common
|
||||
additions trivial. **✓ Five 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),
|
||||
`flatpak` (+ Flathub remote added by a oneshot), `pika` (Pika Backup GUI).
|
||||
More candidates by area:
|
||||
- ✓ **cloud/sync:** Syncthing (`services.syncthing`); Nextcloud client (todo)
|
||||
- **local AI:** LM Studio (`lmstudio`); Ollama (`services.ollama`, optional
|
||||
GPU accel) — pairs with the menu's Ask-Claude philosophy
|
||||
- ✓ **containers/VMs:** Podman (`virtualisation.podman`); Docker / libvirt +
|
||||
virt-manager (todo)
|
||||
- ✓ **networking:** Tailscale (`services.tailscale`); WireGuard (todo)
|
||||
- **gaming/media:** Steam (`programs.steam`); OBS Studio
|
||||
- **devices:** printing (CUPS + Avahi); KDE Connect / phone integration;
|
||||
OpenRGB
|
||||
- ✓ **backup:** Pika Backup (`pika-backup`, GUI over Borg); restic/borg
|
||||
services (todo)
|
||||
`flatpak` (+ Flathub remote added by a oneshot), `pika` (Pika Backup GUI),
|
||||
`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), `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), `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 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
|
||||
(`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
|
||||
|
||||
Surface decided: `nomarchy.services.*`, system-side for system services
|
||||
(home-side ones can extend the same prefix later). Remaining: curate the
|
||||
rest (Ollama, containers, Steam/OBS, printing, backups, Flatpak …) and
|
||||
decide how it relates to `nomarchy.apps.*` (opt-out suite). Unfree entries
|
||||
are already covered (`allowUnfree = true`).
|
||||
rest (Ollama, containers, Steam/OBS, printing, backups, Flatpak …). The
|
||||
opt-out application *suite* is deliberately **not** a parallel
|
||||
`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
|
||||
per-output schema — name/resolution/position/scale/transform/mirror/
|
||||
bitdepth/vrr/disable) generates Hyprland `monitor` rules, keeping the
|
||||
|
||||
@@ -41,9 +41,9 @@ let
|
||||
nomarchy-menu = pkgs.writeShellScriptBin "nomarchy-menu" ''
|
||||
# Nomarchy menu dispatcher — thin presentation layer over
|
||||
# `rofi -dmenu`; actions delegate to nomarchy-theme-sync, systemctl,
|
||||
# hyprctl and friends. Icons are nf-md glyphs (Pango falls back to a
|
||||
# Nerd Font for them). `nomarchy-menu` with no argument shows the
|
||||
# module picker.
|
||||
# hyprctl and friends. Menu entries carry real icons from the theme's
|
||||
# icon set (Papirus) via rofi's per-row icon protocol — see row() below.
|
||||
# `nomarchy-menu` with no argument shows the module picker.
|
||||
|
||||
urlencode() {
|
||||
local s="$1" out="" ch i
|
||||
@@ -58,16 +58,22 @@ let
|
||||
printf '%s' "$out"
|
||||
}
|
||||
|
||||
# Emit one dmenu row with a themed icon: `row "Label" icon-name`. The NUL
|
||||
# + 0x1f field separator is rofi's per-row icon protocol; printed straight
|
||||
# to the pipe because bash can't store NUL in a variable. Rendered when
|
||||
# rofi has show-icons (on globally; passed explicitly on the icon menus).
|
||||
row() { printf '%s\0icon\x1f%s\n' "$1" "$2"; }
|
||||
|
||||
case "''${1:-}" in
|
||||
power)
|
||||
choice=$(printf '%s\n' \
|
||||
" Lock" \
|
||||
" Logout" \
|
||||
" Suspend" \
|
||||
" Hibernate" \
|
||||
" Reboot" \
|
||||
" Shutdown" \
|
||||
| rofi -dmenu -p power) || exit 0
|
||||
choice=$( {
|
||||
row "Lock" system-lock-screen
|
||||
row "Logout" system-log-out
|
||||
row "Suspend" system-suspend
|
||||
row "Hibernate" system-hibernate
|
||||
row "Reboot" system-reboot
|
||||
row "Shutdown" system-shutdown
|
||||
} | rofi -dmenu -show-icons -p Power) || exit 0
|
||||
case "$choice" in
|
||||
*Lock) loginctl lock-session ;;
|
||||
*Logout) hyprctl dispatch exit ;;
|
||||
@@ -134,12 +140,12 @@ let
|
||||
exec blueman-manager ;;
|
||||
|
||||
capture)
|
||||
choice=$(printf '%s\n' \
|
||||
" Region → clipboard" \
|
||||
" Region → file" \
|
||||
" Full screen → clipboard" \
|
||||
" Full screen → file" \
|
||||
| rofi -dmenu -p capture) || exit 0
|
||||
choice=$( {
|
||||
row "Region → clipboard" applets-screenshooter
|
||||
row "Region → file" applets-screenshooter
|
||||
row "Full screen → clipboard" camera-photo
|
||||
row "Full screen → file" camera-photo
|
||||
} | rofi -dmenu -show-icons -p Capture) || exit 0
|
||||
dir="$HOME/Pictures/Screenshots"
|
||||
file="$dir/$(date +%Y%m%d-%H%M%S).png"
|
||||
case "$choice" in
|
||||
@@ -183,16 +189,16 @@ let
|
||||
tools)
|
||||
# Tools submenu — utilities you invoke. Each leaf is also reachable
|
||||
# directly (SUPER+CTRL+<mnemonic>); this just keeps the root short.
|
||||
choice=$(printf '%s\n' \
|
||||
" Calculator" \
|
||||
" Clipboard" \
|
||||
" Emoji" \
|
||||
" Files" \
|
||||
" Web search" \
|
||||
" Capture" \
|
||||
" Ask Claude" \
|
||||
" Back" \
|
||||
| rofi -dmenu -p tools) || exit 0
|
||||
choice=$( {
|
||||
row "Calculator" accessories-calculator
|
||||
row "Clipboard" edit-paste
|
||||
row "Emoji" face-smile-big
|
||||
row "Files" system-file-manager
|
||||
row "Web search" system-search
|
||||
row "Capture" applets-screenshooter
|
||||
row "Ask Claude" internet-chat
|
||||
row "Back" go-previous
|
||||
} | rofi -dmenu -show-icons -p Tools) || exit 0
|
||||
case "$choice" in
|
||||
*Calc*) exec "$0" calc ;;
|
||||
*Clipboard*) exec "$0" clipboard ;;
|
||||
@@ -208,18 +214,17 @@ let
|
||||
# System submenu — connectivity and machine state. Snapshots and the
|
||||
# power-profile picker self-gate (BTRFS+snapper / laptop on ppd), so
|
||||
# the submenu shrinks to match the hardware, like the Waybar modules.
|
||||
entries=(
|
||||
" Network"
|
||||
" Bluetooth"
|
||||
" Do Not Disturb"
|
||||
)
|
||||
command -v btrfs-assistant >/dev/null 2>&1 && entries+=(" Snapshots")
|
||||
bats=(/sys/class/power_supply/BAT*)
|
||||
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
||||
entries+=(" Power profile")
|
||||
fi
|
||||
entries+=(" Back")
|
||||
choice=$(printf '%s\n' "''${entries[@]}" | rofi -dmenu -p system) || exit 0
|
||||
choice=$( {
|
||||
row "Network" network-wireless
|
||||
row "Bluetooth" bluetooth
|
||||
row "Do Not Disturb" notification-disabled
|
||||
command -v btrfs-assistant >/dev/null 2>&1 && row "Snapshots" timeshift
|
||||
if [ -e "''${bats[0]}" ] && command -v powerprofilesctl >/dev/null 2>&1; then
|
||||
row "Power profile" preferences-system-power
|
||||
fi
|
||||
row "Back" go-previous
|
||||
} | rofi -dmenu -show-icons -p System) || exit 0
|
||||
case "$choice" in
|
||||
*Network*) exec "$0" network ;;
|
||||
*Bluetooth*) exec "$0" bluetooth ;;
|
||||
@@ -233,14 +238,14 @@ let
|
||||
# Root picker — grouped into category submenus so the top level stays
|
||||
# short and scannable. Apps/Theme/Power/Keybindings are frequent enough
|
||||
# to keep at the top; everything else lives under Tools or System.
|
||||
choice=$(printf '%s\n' \
|
||||
" Apps" \
|
||||
" Theme" \
|
||||
" Tools" \
|
||||
" System" \
|
||||
" Power" \
|
||||
" Keybindings" \
|
||||
| rofi -dmenu -p menu) || exit 0
|
||||
choice=$( {
|
||||
row "Apps" applications-all
|
||||
row "Theme" preferences-desktop-theme
|
||||
row "Tools" applications-utilities
|
||||
row "System" preferences-system
|
||||
row "Power" system-shutdown
|
||||
row "Keybindings" preferences-desktop-keyboard
|
||||
} | rofi -dmenu -show-icons -p Menu) || exit 0
|
||||
case "$choice" in
|
||||
*Apps*) exec rofi -show drun ;;
|
||||
*Theme*) exec "$0" theme ;;
|
||||
@@ -283,6 +288,10 @@ in
|
||||
drun-display-format = "{name}";
|
||||
display-drun = "apps";
|
||||
display-run = "run";
|
||||
# Size the window to the actual number of rows instead of always
|
||||
# reserving `lines` (8) — so a 6-entry menu doesn't leave empty space,
|
||||
# while the app launcher still fills + scrolls past `lines`.
|
||||
fixed-num-lines = false;
|
||||
};
|
||||
|
||||
# Whole-swap themes bring their own rofi.rasi; otherwise the theme
|
||||
@@ -335,22 +344,34 @@ in
|
||||
columns = 1;
|
||||
dynamic = true;
|
||||
scrollbar = false;
|
||||
spacing = px 2;
|
||||
spacing = px 4; # a little air so the rounded zebra rows separate
|
||||
padding = mkLiteral "8px 0px 0px 0px";
|
||||
};
|
||||
|
||||
# Rounded, roomy rows with subtle zebra striping: alternate rows
|
||||
# lift to @surface, the selected row to @accent. normal/alternate/
|
||||
# selected are rofi's row parities (the `.normal` suffix is the
|
||||
# match-state, untouched by our menus).
|
||||
"element" = {
|
||||
padding = mkLiteral "8px 12px";
|
||||
padding = mkLiteral "10px 14px";
|
||||
border-radius = px t.ui.rounding;
|
||||
spacing = px 8;
|
||||
spacing = px 12; # gap between the (larger) icon and the label
|
||||
};
|
||||
"element selected" = {
|
||||
"element normal.normal" = {
|
||||
background-color = mkLiteral "@bg";
|
||||
text-color = mkLiteral "@fg";
|
||||
};
|
||||
"element alternate.normal" = {
|
||||
background-color = mkLiteral "@surface";
|
||||
text-color = mkLiteral "@fg";
|
||||
};
|
||||
"element selected.normal" = {
|
||||
background-color = mkLiteral "@accent";
|
||||
text-color = mkLiteral "@bg";
|
||||
};
|
||||
"element-icon" = {
|
||||
background-color = mkLiteral "transparent";
|
||||
size = mkLiteral "1em";
|
||||
size = px t.ui.iconSize; # real icons (Papirus), not 1em font glyphs
|
||||
};
|
||||
"element-text" = {
|
||||
background-color = mkLiteral "transparent";
|
||||
|
||||
@@ -38,6 +38,7 @@ let
|
||||
gapsOut = 12;
|
||||
borderSize = 2;
|
||||
rounding = 10;
|
||||
iconSize = 36; # rofi launcher + menu icon size (px) for the generated theme
|
||||
activeOpacity = 1.0;
|
||||
inactiveOpacity = 0.95;
|
||||
terminalOpacity = 0.96;
|
||||
|
||||
@@ -29,6 +29,96 @@ in
|
||||
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`)'';
|
||||
|
||||
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). List
|
||||
and restore with the generated `restic-nomarchy` wrapper (repo +
|
||||
password baked in), e.g. `restic-nomarchy snapshots`'';
|
||||
|
||||
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 [
|
||||
@@ -80,5 +170,111 @@ in
|
||||
(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;
|
||||
};
|
||||
})
|
||||
|
||||
(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
|
||||
};
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||
|
||||
@@ -34,7 +34,107 @@
|
||||
# nomarchy.keyboard.layouts = [ "de" "fr" ]; # rofi-prompt for a layout when a
|
||||
# # 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.
|
||||
#
|
||||
# Apps that need system setup beyond a package (Steam's 32-bit stack,
|
||||
# a daemon, group membership, a kernel module) are NOT here — they're
|
||||
# opt-in service toggles in system.nix instead (nomarchy.services.* —
|
||||
# steam, libvirt, obs, docker, gamemode, kdeconnect, adb, wireshark,
|
||||
# ollama, printing).
|
||||
home.packages = with pkgs; [
|
||||
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)
|
||||
|
||||
# ── More apps — uncomment to add ─────────────────────────────────
|
||||
# Web browsers
|
||||
# firefox
|
||||
# chromium
|
||||
# ungoogled-chromium
|
||||
# brave # (unfree)
|
||||
# google-chrome # (unfree)
|
||||
|
||||
# Communication
|
||||
# signal-desktop
|
||||
# telegram-desktop
|
||||
# element-desktop # Matrix
|
||||
# vesktop # Discord (themeable client)
|
||||
# slack # (unfree)
|
||||
# zoom-us # (unfree)
|
||||
# teams-for-linux # community client (no official Linux app)
|
||||
# thunderbird # email
|
||||
|
||||
# Office & documents
|
||||
# onlyoffice-desktopeditors # stronger MS-Office fidelity
|
||||
# kdePackages.okular # PDF viewer
|
||||
# xournalpp # PDF annotation
|
||||
# pdfarranger
|
||||
# calibre # ebook library
|
||||
# texliveFull # full LaTeX toolchain — multi-GB (texliveMedium is lighter)
|
||||
|
||||
# Notes / research
|
||||
# logseq
|
||||
# obsidian # (unfree)
|
||||
# joplin-desktop
|
||||
# anki-bin # flashcards
|
||||
# zotero # reference manager
|
||||
|
||||
# Code & data
|
||||
# zed-editor
|
||||
# lazygit
|
||||
# dbeaver-bin # database GUI
|
||||
# bruno # API client
|
||||
# distrobox # containerized dev shells
|
||||
|
||||
# Graphics & design
|
||||
# krita # digital painting
|
||||
# blender # 3D
|
||||
# darktable # RAW photo
|
||||
|
||||
# Audio / video
|
||||
# audacity
|
||||
# shotcut # video editor
|
||||
# kdePackages.kdenlive # video editor (pulls in KDE libs)
|
||||
# handbrake # transcoder
|
||||
|
||||
# Media
|
||||
# vlc
|
||||
# spotify # (unfree)
|
||||
# newsflash # RSS reader
|
||||
|
||||
# Gaming (Steam + GameMode are service toggles in system.nix)
|
||||
# lutris
|
||||
# heroic # Epic/GOG launcher
|
||||
# bottles # Wine prefixes
|
||||
# prismlauncher # Minecraft
|
||||
# protonup-qt # Proton-GE manager
|
||||
# mangohud # in-game overlay
|
||||
|
||||
# Files, sync & torrents
|
||||
# nextcloud-client
|
||||
# localsend # AirDrop-like transfer
|
||||
# qbittorrent
|
||||
|
||||
# Security
|
||||
# keepassxc
|
||||
# bitwarden-desktop
|
||||
|
||||
# System
|
||||
# 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)
|
||||
# alpaca # GTK Ollama UI
|
||||
];
|
||||
}
|
||||
|
||||
@@ -36,6 +36,23 @@
|
||||
# nomarchy.services.podman.enable = true; # rootless containers (docker → podman)
|
||||
# nomarchy.services.flatpak.enable = true; # Flatpak + the Flathub remote
|
||||
# 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
|
||||
# nomarchy.services.docker.enable = true; # Docker rootful (not alongside podman)
|
||||
# nomarchy.services.kdeconnect.enable = true;# KDE Connect phone integration (opens ports)
|
||||
# nomarchy.services.gamemode.enable = true; # Feral GameMode performance daemon
|
||||
# nomarchy.services.adb.enable = true; # Android adb/fastboot tools
|
||||
# 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";
|
||||
}
|
||||
|
||||
@@ -29,7 +29,8 @@ window {
|
||||
border-color: @yellow;
|
||||
border-radius: 15px;
|
||||
width: 40%;
|
||||
height: 50%;
|
||||
/* No fixed height — size to content (fixed-num-lines:false) so every
|
||||
* entry shows without scrolling and there's no empty space below. */
|
||||
location: center;
|
||||
anchor: center;
|
||||
x-offset: 0;
|
||||
@@ -90,6 +91,12 @@ element {
|
||||
spacing: 15px;
|
||||
}
|
||||
|
||||
/* Zebra striping: every other row lifts with a faint light wash over the
|
||||
* dark window (bg0 at ~12% alpha). The selected row below still wins. */
|
||||
element alternate.normal {
|
||||
background-color: #fdf6e31f;
|
||||
}
|
||||
|
||||
element-icon {
|
||||
background-color: transparent;
|
||||
text-color: inherit;
|
||||
|
||||
@@ -29,7 +29,8 @@ window {
|
||||
border-color: @yellow;
|
||||
border-radius: 15px;
|
||||
width: 40%;
|
||||
height: 50%;
|
||||
/* No fixed height — size to content (fixed-num-lines:false) so every
|
||||
* entry shows without scrolling and there's no empty space below. */
|
||||
location: center;
|
||||
anchor: center;
|
||||
x-offset: 0;
|
||||
@@ -90,6 +91,12 @@ element {
|
||||
spacing: 15px;
|
||||
}
|
||||
|
||||
/* Zebra striping: every other row lifts with a faint dark wash over the
|
||||
* cream window (bg0 at ~12% alpha). The selected row below still wins. */
|
||||
element alternate.normal {
|
||||
background-color: #2d353b1f;
|
||||
}
|
||||
|
||||
element-icon {
|
||||
background-color: transparent;
|
||||
text-color: inherit;
|
||||
|
||||
Reference in New Issue
Block a user