Initial import: nuc and ks4 infrastructure documentation

README with instance tables and nuc<->ks4 network flow chart;
per-container install/troubleshooting docs for nuc (jellyfin
server/client, transmission-bt, bare-metal reinstall) and the
ks4 two-leg backup scheme (incus-copy over wireguard).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Julien Lutran
2026-08-09 22:50:07 +02:00
co-authored by Claude Fable 5
commit ee9eaee889
7 changed files with 1255 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
# perso
Personal infrastructure notes.
- [`nuc/`](nuc/) — home lab on `nuc` (see below)
- [`ks4/`](ks4/) — prod server `ks4` at OVH (see below)
## Homelab: nuc
Incus host on the LAN.
- Host: `nuc``192.168.0.3`, Debian 13, Intel Alder Lake-N
(iGPU `i915`, shared by both Jellyfin containers) —
bare-metal reinstall: [nuc/nuc-install.md](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 `usb4t``usb4t/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](nuc/nuc-install.md); ks4 replicas pulled into
pool `ks4backup` — see [ks4/incus-copy.md](ks4/incus-copy.md)
### Instances
| Name | IP | Doc | Features |
|---|---|---|---|
| [jellyfin-server](nuc/jellyfin-server.md) | 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](nuc/jellyfin-client.md) | 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](nuc/transmission-bt.md) | 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.fr``193.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](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](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](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.