Julien LutranandClaude Opus 4.8 43ef0e5447 nuc/jellyfin-client: document host-side input hotplug auto-recovery
Add udev rule + oneshot service + script on nuc that restart the
container kiosk when the Logitech Unifying receiver is replugged, since
hotplug uevents don't cross into the container's netns and cage only
enumerates input at startup.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-11 01:39:27 +02:00

perso

Personal infrastructure notes.

  • nuc/ — home lab on nuc (see below)
  • ks4/ — prod server ks4 at OVH (see below)

Homelab: nuc

Incus host on the LAN.

  • Host: nuc192.168.0.3, Debian 13, Intel Alder Lake-N (iGPU i915, shared by both Jellyfin containers) — bare-metal reinstall: nuc/nuc-install.md
  • SSH: ssh -i id_rsa_claude root@192.168.0.3 (keys at repo root, gitignored)
  • Instances are bridged onto the LAN (192.168.0.0/24)
  • USB 4 TB WD Red: ZFS pool usb4tusb4t/backup/backup (incus exports, nuc/ + ks4/ subdatasets, 1 TB quota) and usb4t/media/srv/media (media library, shared into containers via shift=true disk devices; works because ZFS ≥ 2.2 supports idmapped mounts)
  • NAS: //192.168.0.10/Shared (CIFS) — original media source, normally offline; not mountable into containers (idmapped mounts unsupported on CIFS)
  • Backups: all local instances replicated to the USB pool (/root/scripts/incus-copy.sh -p backup -s nucbackup; replicas stopped, autostart off) — see nuc/nuc-install.md; ks4 replicas pulled into pool ks4backup — see ks4/incus-copy.md

Instances

Name IP Doc Features
jellyfin-server 192.168.0.5 unprivileged, autostart; iGPU render node (gpu device, render gid) for QSV/VAAPI transcoding; /srv/media disk device (shift=true); proxy device → host :8096
jellyfin-client 192.168.0.6 privileged, autostart; full iGPU (gpu device, gid 44) → HDMI kiosk (cage + Jellyfin Media Player); custom raw.lxc (bind /dev/snd, /dev/input, host /run/udev); Pioneer USB audio as ALSA default; FR keymap; go-librespot Spotify Connect ("Pioneer A-70")
transmission-bt 192.168.0.7 unprivileged, autostart; always-on WireGuard full tunnel → ks4 (egress = 193.70.35.17, kill switch: no default route); /srv/media disk device (shift=true), downloads to /media/downloads; web UI :9091 (LAN only)
blocky 192.168.0.254 unprivileged, autostart; DNS ad-blocker
privoxy 192.168.0.11 unprivileged, autostart; filtering HTTP proxy
pihole (stopped) unprivileged; superseded by blocky
homeassistant (stopped) virtual machine, 50 GiB root disk on pool data

Prod: ks4

Incus host at OVH — public-facing self-hosted services.

  • Host: ks4.lutran.fr193.70.35.17, SSH on port 2233, Debian 13, Xeon D-1521 / 32 GiB, 2× 6 TB (OS on mdraid RAID1, ZFS pool data on sda5) — setup & rebuild: ks4/install.md
  • SSH: ssh -i id_rsa_claude -p 2233 julien@193.70.35.17 (julien has passwordless sudo incus …)
  • Instances are on a NAT bridge incusbr0 (192.168.1.0/24); public ingress via Incus proxy devices. gateway (nginx) is the sole HTTP/S entry point and fans out to the app containers.
  • Services: gateway, mail, nextcloud, seafile, git, freshrss, bitwarden, outline, login (SSO), wireguard, + more — full table in ks4/install.md.
  • ⚠️ The ZFS data pool is single-disk (not mirrored); durability rests on two nightly root cron jobs — incus copy --refresh to remote host ks2 (moving to nuc pool ks4backup, see ks4/incus-copy.md), and an rsync backup (scripts/incus-backup.sh) to 164.132.173.57:/backup/ks4.

Network flows (nuc <-> ks4)

  nuc — home LAN 192.168.0.0/24                    ks4 — OVH 193.70.35.17
+-----------------------------------+       +-------------------------------------+
|                                   |       |                                     |
| host: wg-ks4 (10.8.0.20)          |       |  [wireguard] 192.168.1.18           |
|   incus remote "ks4"        ------+--WG-->|   wg0 10.8.0.1/24, udp 51845        |
|   pull ks4:* -> pool ks4backup    | udp   |    | masquerade -> eth0             |
|   on usb4t  [pending FTTH seed]   | 51845 |    |                                |
|                                   |       |    +-> incus API 192.168.1.1:8443   |
| [transmission-bt] wg0 (10.8.0.21) |       |    |   (ufw: only from .18)         |
|   full tunnel 0.0.0.0/0     ------+--WG-->|    |                                |
|   kill switch: no default route   | udp   |    +-> WAN egress: torrents +       |
|   downloads -> /srv/media         | 51845 |        apt of transmission-bt       |
|   (usb4t/media, read by jellyfin) |       |        exit as 193.70.35.17         |
|                                   |       |                                     |
| 03:00 instance snapshots          |       | 03:00 instance snapshots            |
| 03:30 incus-copy: all instances   |       | 01:00 incus-copy: all instances     |
|   -> project backup, pool         |       |   -> project backup, zpool          |
|   nucbackup (usb4t/backup/nuc)    |       |   backup (sdb5)          [planned]  |
| 05:00 apt upgrade all containers  |       | 04:00 incus-backup.sh: DB dumps     |
|                                   |       |   -> /backup (sdb5)      [planned]  |
+-----------------------------------+       +-------------------------------------+
   phones/laptops: WG peers 10.8.0.2-3 reach 192.168.1.x through the same endpoint

Both tunnels initiate from nuc (home NAT, dynamic IP) toward ks4's fixed endpoint; ks4's incus API is never exposed to the internet.

Conventions

  • One markdown file per instance in nuc/, containing the full install script (idempotent-ish, run as root on the host), first-run configuration, and troubleshooting notes.
  • Containers are built from images:ubuntu/24.04 and configured exclusively through incus exec/incus config so the doc is the single source of truth — rebuilding = re-running the script.
S
Description
No description provided
Readme
670 KiB
Languages
Markdown 100%