172 lines
10 KiB
Markdown
172 lines
10 KiB
Markdown
# Nix-Vibe Config Improvements
|
||
|
||
Prioritized from the package/service review (most important first).
|
||
|
||
> **Review status (2026-09-01):** All 20 items committed to `main`.
|
||
> `nix flake check` ✅ — all 8 hosts dry-build ✅.
|
||
> Reviewed against commits `f6d68b6`…`628f1b2`.
|
||
|
||
---
|
||
|
||
## 🔴 Critical — Security & Data Integrity
|
||
|
||
- [x] **OpenSSH hardening** — verified in `f6d68b6` (key-only auth, PermitRootLogin=no).
|
||
- [x] **Samba share security** — verified in `0f5065e` (authenticated, valid users = petere).
|
||
- [x] **Paperless to Tailscale only** — verified in `444705d` (firewall on `tailscale0` interface).
|
||
- [x] **Immich accelerationDevices** — verified in `dd15aa2` (explicit /dev/nvidia* nodes).
|
||
- [x] **Jellyfin SSO plugin bind-mount** — verified in `b8ba00c`, improved by `1f712f7`. ⚠️ Needs manual Pocket ID config.
|
||
|
||
## 🟠 High — Resource Waste / Performance
|
||
|
||
- [x] **Jellyfin NVENC acceleration** — verified in `a4bd8bd`.
|
||
- [x] **Nix GC + optimise** — verified in `dde980e`.
|
||
- [x] **Caddy cleanup** — verified in `df588e7` (unused module deleted).
|
||
- [x] **Formatter dedup** — verified in `1ae761a` (nixfmt only).
|
||
- [x] **Antigravity dedup** — verified in `4e72c58` (removed entirely).
|
||
|
||
## 🟡 Medium — Misconfigurations / Robustness
|
||
|
||
- [x] **homeserver-1 firewall scoping** — verified in `bc68837` (Immich→Tailscale).
|
||
- [x] **Laptop hardware module** — verified in `83ab88f` + `fe63013`.
|
||
- [x] **borgbackup → Backrest** — verified in `75b3c75`.
|
||
- [x] **Immich DB peer-auth** — ✅ socket auth, no secret needed.
|
||
- [x] **ntfy listen** — reverted in `628f1b2` (Docker nginx can't reach host localhost).
|
||
- [x] **Firefox sync pref** — verified in `005e421` (removed).
|
||
- [x] **Jellyfin group** — explicit `jellyfin` group (no `nobody` hack).
|
||
|
||
## 🟢 Low — Housekeeping
|
||
|
||
- [x] **Flatpak GC** — verified in `6d7effd`.
|
||
- [x] **VSCode extension pinned** — verified in `dd7deba`.
|
||
- [x] **OnlyOffice fonts** — kept activation approach (documented).
|
||
- [x] **Zsh secrets initContent** — kept interactive-only (documented).
|
||
|
||
---
|
||
|
||
## Remaining manual steps
|
||
|
||
- [ ] **Jellyfin**: configure Pocket ID SSO manually in admin UI.
|
||
- [ ] **Firefox Sync**: sign in once via browser UI.
|
||
|
||
---
|
||
|
||
## Hyprland / QuickShell — bigger projects (deferred from QoL pass)
|
||
|
||
From the research list (2026 session). The basics (media keys, animations, scratchpad,
|
||
OSD, clipboard, MPRIS, battery toast, night light, wofi icons/actions) are done.
|
||
These are the larger items parked for later:
|
||
|
||
- [x] **Notification center** — replaced mako with QuickShell native
|
||
`NotificationServer` (toasts, history, DND, clear, actions/buttons). mako
|
||
config + autostart fully removed. v2 options: per-app rules, inline replies.
|
||
- [x] **Workspace overview** — QuickShell-native "mission control" (no plugin):
|
||
fullscreen scrim, one card per workspace with window titles + active/focused
|
||
highlight, click **or** keyboard jump (arrows/enter, 1-9 direct), `SUPER+W`
|
||
→ `qs ipc call ws toggle`. Implemented in `quickshell-shell.qml` (titles via
|
||
root `Hyprland.toplevels` filtered by workspace id — `HyprlandWorkspace
|
||
.toplevels` doesn't exist in this build).
|
||
⚠️ `hyprspace` (live thumbnails) parked: `hyprlandPlugins.hyprspace` at the
|
||
pinned nixpkgs FAILS TO BUILD (`src/Globals.hpp:15: AnimationManager.hpp: no
|
||
such file` — hyprland source moved the header; nixpkgs package lags) and is
|
||
not in the binary cache. Revisit after a nixpkgs bump. (hyprbars/hyprtrails
|
||
also parked — hyprtrails isn't packaged.)
|
||
- [x] **Calendar + weather popup** on clock click (`SUPER+CTRL+C`) —
|
||
month-grid + Nextcloud CalDAV events + 3-day Open-Meteo forecast in a single
|
||
QuickShell `PanelWindow`. Implemented in `quickshell-shell.qml` (header with
|
||
month navigation, 6×7 GridView calendar, agenda list, weather row with
|
||
location editor). Data pipeline: HM user service `qs-cal-sync` → vdirsyncer
|
||
(CalDAV) + khal (`--json`) + Open-Meteo API → caches in
|
||
`~/.cache/quickshell-cal/`. Script: `quickshell-cal.py` (stdlib only), module:
|
||
`quickshell-cal.nix`. Secrets: `hp-laptop/nextcloud-cal-env` in SOPS
|
||
(`NEXTCLOUD_CALDAV_URL/USERNAME/PASSWORD` — **user must fill via `sops edit
|
||
secrets.yaml`**). IPC: `qs ipc call cal toggle/refresh/state`.
|
||
- [x] **Wallpaper picker widget** — thumbnail grid from `~/Pictures/wallpapers`,
|
||
click → hyprctl swap, persist choice to state file. ~half day.
|
||
- [x] **QuickShell lock screen replacing hyprlock** — `WlSessionLock` + PAM.
|
||
Decision (2026-09-11): NOT implementing — keep hyprlock. Its PAM service,
|
||
fingerprint support and the hypridle/lid `loginctl lock-session` chain are
|
||
battle-tested and already themed to match the shell; a QuickShell lock would
|
||
rebuild the auth stack for visual gain only. Reopen only if hyprlock is ever
|
||
dropped as a dependency.
|
||
- [x] **Lid close: lock then suspend (always, resume needs password)** — fixed
|
||
in `modules/desktop/hyprland.nix`: `HandleLidSwitchExternalPower` was
|
||
`ignore` so a plugged-in lid close did nothing. Now `suspend` on battery and
|
||
external power; hypridle's `before_sleep_cmd = loginctl lock-session` locks
|
||
(hyprlock) before logind sleeps, so reopening the lid resumes to a locked
|
||
screen. Docked keeps logind's `ignore` default. 5-min idle lock + 15-min
|
||
suspend unchanged.
|
||
- [x] **Bluetooth management** — QuickShell bluetooth popup mirroring the wifi
|
||
`netPopup` pattern: status-bar BT icon, power toggle, paired/known device list,
|
||
connect/disconnect/pair/trust. Backend: enable `hardware.bluetooth` (desktops —
|
||
currently disabled on ALL hosts) + a `qs-bt` helper over `bluetoothctl`/bluez
|
||
D-Bus (same pattern as `qs-wall`/`qs-cal.py`), IPC `qs ipc call bt toggle`.
|
||
Implemented: `hardware.bluetooth` + bluez polkit rule in `modules/desktop/gui.nix`,
|
||
backend `qs-bt` (`home-manager/modules/quickshell-bt.py`), QML popup (PanelWindow
|
||
`qs-bt` layer, FocusGrab), bt status icon, IPC `qs ipc call bt {toggle,state,power,scan}`.
|
||
|
||
## Rice backlog — Hyprland/QuickShell improvement list (#1–#10)
|
||
|
||
Recovered from the 2026 rice session (persisted here after being lost twice).
|
||
|
||
- [x] **#1 Wallpaper-driven palette + theme switcher** — matugen-based shared
|
||
palette unifying QML theme, wvkbd, wofi, hyprlock, kitty; wallpaper-picker
|
||
PALETTE button regenerates the theme (`qs-theme`).
|
||
- [x] **#2 Hyprland blur/shadow/animated borders** — gradient `active_border`,
|
||
shadow, `borderangle` animation loop in `hyprland.nix`.
|
||
- [x] **#3 System-stats chip + flake badge** — `qs-stats` probe (lm_sensors),
|
||
CPU/RAM/swap/disk/temps/load popup, flake.lock rev/date badge injected at
|
||
build time, copy command.
|
||
- [x] **#4 Dynamic island bar** — floating centered island pill, tucked-up when
|
||
hidden, peek on hover, event reveal (workspace/notification/media) + 10s
|
||
auto-retract.
|
||
- [x] **#5 Now-playing + battery info in hyprlock** — show MPRIS track + battery
|
||
percentage on the lock screen.
|
||
- [ ] **#6 Visual monitor manager** — ARandR-style hyprctl front-end
|
||
(rotate/scale/arrange monitors from a GUI). ⏸️ On hold until the laptop is
|
||
connected to multiple monitors so it can be tested properly.
|
||
- [x] **#7 OSD scroll-wheel on bar chips** — scroll the volume chip to nudge
|
||
PipeWire volume (5% steps, OSD tracks it); new brightness chip scrolls
|
||
`brightnessctl` (5% steps) with the neon OSD, click opens quick settings.
|
||
Shell-scope `shellBrightProbe`/`shellBrightSet` (throttled, 30s refresh)
|
||
keep chip/OSD/slider in sync.
|
||
⚠️ **Partially tested on x1carbon** — two-finger touchpad scroll works; still
|
||
needs verification with a real scroll wheel before fully relying on it.
|
||
- [x] **#8 Caffeine/idle-inhibit toggle** — already implemented as the
|
||
keep-awake IdleInhibitor badge (Hyprland) + Caffeine extension (GNOME).
|
||
- [x] **#9 Emoji picker + calculator in launcher** — `qs-launch` wofi modes:
|
||
`SUPER+SHIFT+E` emoji picker (curated 295-emoji list, copies to clipboard),
|
||
`SUPER+SHIFT+C` calculator (qalc eval, copies result + toast),
|
||
`SUPER+SHIFT+D` DuckDuckGo search (opens in browser).
|
||
- [ ] **#10 Screenshot → bar toast with copy** — `qs-shot` (`Print` opens a wofi
|
||
area/full-screen chooser, `SUPER+SHIFT+S`/`SUPER+SHIFT+R` capture directly):
|
||
grimblast copysave → toast with image thumbnail + OPEN/COPY action buttons
|
||
(intercepted in `calNotifAction` by `shot-open:`/`shot-copy:` identifiers;
|
||
also shown in the notification center history).
|
||
|
||
## Calendar popup — v2 improvements (deferred, all requested)
|
||
|
||
- [x] **Edit / delete events** — click an agenda entry to edit title/time/location
|
||
or delete it; syncs back to Nextcloud like `add` does. Backend `edit`/`delete`
|
||
modes rewrite the .ics (summary/location/alarms/RRULE) and push via vdirsyncer;
|
||
shell form gains EDIT EVENT mode with a DELETE button. Mutations rescan local
|
||
stores immediately (`refresh_local_cache`) so the popup reflects them without
|
||
waiting for the next timed sync.
|
||
- [x] **Recurring events on creation** — "repeat daily/weekly/monthly" (RRULE
|
||
options) in the NEW EVENT form. Backend `add` takes `repeat`; edit preserves
|
||
and can change an existing RRULE. Recurring events also scan/expand natively
|
||
(no khal) via `icalendar` + `recurring_ical_events`.
|
||
- [x] **Clickable + snoozeable reminders** — click a reminder toast to jump to the
|
||
event popup; add a snooze action on the notification. The remind notifier
|
||
encodes payloads in the action identifiers (`cal-open:<date>` opens the popup
|
||
at that day, `cal-snooze:<key>` delays the reminder 10 min via
|
||
`snoozes.json`); both toasts and the notification center route action clicks
|
||
through `calNotifAction`. Notifications are now `-t 0` (persist in center).
|
||
- [x] **Sync failure indicator** — subtle badge in the calendar header when the
|
||
last sync or event add fails. Backend writes `sync.json` (`ok/lastOk/
|
||
lastEffort/error`) on every sync/push; the shell shows a danger "!" badge with
|
||
a hover tooltip of the error and click-to-refresh.
|
||
- [x] **Weather upgrade** — hourly temps, precipitation chance, wind, more
|
||
forecast days. Backend Open-Meteo fetch now pulls 24 hourly rows (temp/code/
|
||
precip%/wind) and a 7-day daily forecast (plus precip% + max wind); the shell
|
||
renders a today-hourly strip and a compact 7-day grid (was 3).
|