diff --git a/README.md b/README.md index 56caa2e..585033f 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ See the full table in [`containers/index.md`](containers/index.md). Quick links: | 103 | [paperless](containers/103-paperless.md) | 192.168.8.130 | Document mgmt | | 104 | [gitea](containers/104-gitea.md) | 192.168.8.121 | Git server | | 105 | [apps](containers/105-apps.md) | 192.168.8.205 | Docker host (Artifacto / Booklore / PlantUML / Portainer / WriteFreely) | -| 109 | [syncthing](containers/109-syncthing.md) | (stopped) | File sync | | 114 | [nextcloud](containers/114-nextcloud.md) | 192.168.8.224 | Personal cloud | | 118 | [elementsynapse](containers/118-elementsynapse.md) | 192.168.8.239 | Matrix Synapse | | 119 | [sophia](containers/119-sophia.md) | 192.168.8.157 | Sophia | diff --git a/containers/102-nfs-export.md b/containers/102-nfs-export.md index b57be10..7ec89a9 100644 --- a/containers/102-nfs-export.md +++ b/containers/102-nfs-export.md @@ -8,14 +8,14 @@ Dedicated, single-purpose LXC that re-exports `/mnt/library` over NFSv4 to clien - **LAN DNS:** `nfs-export.hubris.network` → `192.168.8.200` (direct, no Caddy) - **Privilege:** privileged (`unprivileged: 0`) + `lxc.apparmor.profile: unconfined` — required for `nfs-kernel-server` - **Resources:** 1 core / 512 MiB RAM / 2 GiB rootfs / 256 MiB swap -- **Mounts:** host `/mnt/library` ↔ container `/mnt/library` (same path on both sides — matches the bind-mount convention used by jellyfin, paperless, arriman, nextcloud, mule-images, plato, syncthing, apps) +- **Mounts:** host `/mnt/library` ↔ container `/mnt/library` (same path on both sides — matches the bind-mount convention used by jellyfin, paperless, arriman, nextcloud, mule-images, plato, apps) ## What it does ``` /mnt/library (host ext4 on nvme1n1) │ - ├── bind-mounted into 8 other LXCs (jellyfin, paperless, …) + ├── bind-mounted into 7 other LXCs (jellyfin, paperless, …) └── bind-mounted into LXC 102 │ └── nfs-kernel-server exports /mnt/library diff --git a/containers/109-syncthing.md b/containers/109-syncthing.md deleted file mode 100644 index bdad580..0000000 --- a/containers/109-syncthing.md +++ /dev/null @@ -1,26 +0,0 @@ -# 109 — `syncthing` - -Cross-device file sync into `/mnt/library/syncthing`. - -## At a glance -- **Hostname:** `syncthing` -- **IP:** (none — currently stopped) -- **Privilege:** **unprivileged** + idmap (for the `media` GID 10000 standard) -- **Resources:** 2 cores / 2 GiB RAM / 8 GiB rootfs -- **Mounts:** `/mnt/library` ↔ `/mnt/library` -- **Status:** **stopped** (was running prior to 2026-04-21). - -## Permissions quirk -The syncthing systemd unit runs with `User=root`, and systemd skips `initgroups()` for `User=root`. Drop-in adds `SupplementaryGroups=media` to `syncthing@.service` so it actually picks up GID 10000. See [media permissions](../infrastructure/media-permissions.md). - -## Related -- [Media permissions](../infrastructure/media-permissions.md) -- [Hubris host](../hosts/hubris.md) - -## Changelog - -### 2026-04-28 — wiki entry created -Initial documentation. Container is currently stopped — reason not yet documented; investigate before re-enabling or destroying. - -### 2026-04-20 — joined the `media` GID 10000 standard -Idmap block + drop-in `SupplementaryGroups=media` on `syncthing@.service`. Config backup: `/root/109.conf.bak.*`. diff --git a/containers/index.md b/containers/index.md index 95e65b1..e54f9e5 100644 --- a/containers/index.md +++ b/containers/index.md @@ -8,7 +8,6 @@ All containers live on [`hubris`](../hosts/hubris.md). Each row links to the per | 103 | [paperless](103-paperless.md) | 192.168.8.130 | priv | 2 | 3 GiB | 8 GiB | `/mnt/library` | `paperless.hubris.network` | running | | 104 | [gitea](104-gitea.md) | 192.168.8.121 | priv | 1 | 1 GiB | 8 GiB | `/mnt/library` | `git.hubris.network` | running | | 105 | [apps](105-apps.md) | 192.168.8.205 | priv | 2 | 4 GiB | 30 GiB | `/mnt/library` | `docker` / `books` / `artifacto` / `blog` | running | -| 109 | [syncthing](109-syncthing.md) | (stopped) | unpriv (idmap) | 2 | 2 GiB | 8 GiB | `/mnt/library` | — | **stopped** | | 114 | [nextcloud](114-nextcloud.md) | 192.168.8.224 | priv | 4 | 6 GiB | 25 GiB | `/mnt/library` | `cloud.hubris.network` | running | | 118 | [elementsynapse](118-elementsynapse.md) | 192.168.8.239 | unpriv | 1 | 2 GiB | 8 GiB | — | `matrix.hubris.network` | running | | 119 | [sophia](119-sophia.md) | 192.168.8.157 | priv | 2 | 1 GiB | 10 GiB | `/mnt/library` | — | running | @@ -26,6 +25,7 @@ All containers live on [`hubris`](../hosts/hubris.md). Each row links to the per | 100 | arr (yunohost) | ~2026-04-28 | Migrated to docker stack on [arriman](122-arriman.md); planned retention window expired | | 106 | flaresolverr | ~2026-04-28 | Folded into the arriman docker compose | | 116 | heaper | 2026-05-14 | Decommissioned by user; data subtree at `/mnt/library/heaper` (224 MiB) retained | +| 109 | syncthing | 2026-05-14 | Decommissioned by user; `/mnt/library/syncthing` was already empty | | 125 | seafile | 2026-05-13 | Seafile Pro evaluation, user disliked the product; teardown also removed `files.hubris.network` from caddy + dnsmasq | | 107 | marimo | between 2026-04-21 and 2026-04-28 | Decommissioned | | 110 | photoprism | between 2026-04-21 and 2026-04-28 | Replaced by [mulita](120-mule-images.md) | @@ -40,7 +40,7 @@ All containers live on [`hubris`](../hosts/hubris.md). Each row links to the per - All net0 are `bridge=vmbr0`, `ip=dhcp` except [124 (authentik)](124-authentik.md) which is statically `192.168.8.180/24`. IPs are stable via the LAN router's DHCP reservations. - `onboot=1` on every container — the host brings them up after `pve-guests.service`. - Bind mounts are declared as `mp0: /mnt/library,mp=/mnt/library`. Containers that don't mount `/mnt/library` don't need it. -- Most containers are privileged. Unprivileged ones (`101`, `109`, `118`, `121`, `123`) require an idmap block in their conf to participate in the [media GID 10000](../infrastructure/media-permissions.md) standard. +- Most containers are privileged. Unprivileged ones (`101`, `118`, `121`, `123`) require an idmap block in their conf to participate in the [media GID 10000](../infrastructure/media-permissions.md) standard. ## Related - [Hubris host](../hosts/hubris.md) diff --git a/hosts/hubris.md b/hosts/hubris.md index 26d2a63..ec259e8 100644 --- a/hosts/hubris.md +++ b/hosts/hubris.md @@ -19,7 +19,7 @@ Single-node Proxmox VE running 1 VM and 13 LXC containers. The whole homelab. | `local-lvm` | lvmthin | 856G | LXC/VM rootfs | | `library` | lvmthin | 3.7T | Backs `/mnt/library` ext4 (mounted as `/dev/mapper/library-library`) | -`/mnt/library` holds the shared media + data pool: `anime`, `audiobooks`, `books`, `comics`, `documents`, `downloads`, `heaper`, `homecloud`, `images`, `marimo`, `movies`, `music`, `notes`, `podcasts`, `repos`, `roms`, `sophia`, `syncthing`. Bind-mounted into every container that needs it. Permissions standard: [media GID 10000](../infrastructure/media-permissions.md). +`/mnt/library` holds the shared media + data pool: `anime`, `audiobooks`, `books`, `comics`, `documents`, `downloads`, `heaper`, `homecloud`, `images`, `marimo`, `movies`, `music`, `notes`, `podcasts`, `repos`, `roms`, `sophia`. Bind-mounted into every container that needs it. Permissions standard: [media GID 10000](../infrastructure/media-permissions.md). ## Tenants @@ -27,7 +27,7 @@ Single-node Proxmox VE running 1 VM and 13 LXC containers. The whole homelab. - [108 — `haos-16.3`](../vms/108-haos.md) — Home Assistant OS, 4 GiB / 32 GiB ### LXC containers -See [containers/index](../containers/index.md). 13 active. +See [containers/index](../containers/index.md). 13 active (109 syncthing destroyed 2026-05-14). ## Boot-time tuning (load-bearing) @@ -99,6 +99,9 @@ OpenSSH on `0.0.0.0:22`. Netbird's built-in SSH server is on `100.122.38.109:220 ## Changelog +### 2026-05-14 — LXC 109 (syncthing) decommissioned +User destroyed the syncthing LXC (had been stopped since 2026-04-21, never re-enabled). `pct destroy 109 --purge` cleaned `vm-109-disk-0` on `local-lvm` and the `/etc/pve/lxc/109.conf` entry. Data subtree `/mnt/library/syncthing` was already empty and retained as an empty dir. No DNS, Caddy, NFS-export, or claudio-monitor references to clean up. Entry moved to the "recently destroyed" table in [containers/index](../containers/index.md#recently-destroyed-kept-for-archaeology); references stripped from [README](../README.md), [media-permissions](../infrastructure/media-permissions.md), [vms/100-zimaos](../vms/100-zimaos.md), and [containers/102-nfs-export](../containers/102-nfs-export.md). + ### 2026-05-14 — network performance baseline captured First explicit speed snapshot: WAN ↓113.5 / ↑19.9 Mbit (24.6 ms), `eno1` 1 Gb full-duplex negotiated, intra-host `vmbr0` ~34.7 Gbit/s host↔LXC and ~34.8 Gbit/s LXC↔LXC (single TCP stream, zero retransmits). `iperf3` + `speedtest-cli` installed on host. Noted `eno1` `rx_errors` at 1.62 M (~1.7 % of 96 M RX packets in 14 d uptime) plus 10.9 k `align_errors` — flagged for follow-up; expect to recheck the trend in ~1 week, suspect patch cable / switch port first if still climbing. See new "Network performance baseline" section above. diff --git a/infrastructure/media-permissions.md b/infrastructure/media-permissions.md index edb76f9..eded0e5 100644 --- a/infrastructure/media-permissions.md +++ b/infrastructure/media-permissions.md @@ -8,7 +8,7 @@ Every LXC that mounts `/mnt/library` participates in a shared `media` group with ## Why -`/mnt/library` is a cross-container storage pool. \*arr writes, jellyfin reads, syncthing syncs, photoprism / immich / mulita scan, paperless ingests. Without a shared group, each container sees files as `nobody:nogroup` (unprivileged) or `www-data` (privileged 1:1) and the permission web collapses into one-off chmods. GID 10000 bridges privileged and unprivileged containers. +`/mnt/library` is a cross-container storage pool. \*arr writes, jellyfin reads, mulita scans, paperless ingests. Without a shared group, each container sees files as `nobody:nogroup` (unprivileged) or `www-data` (privileged 1:1) and the permission web collapses into one-off chmods. GID 10000 bridges privileged and unprivileged containers. ## Onboarding a new LXC @@ -26,7 +26,7 @@ Every LXC that mounts `/mnt/library` participates in a shared `media` group with lxc.idmap: g 10001 110001 55535 ``` Then `pct stop && pct start `. -4. For systemd services running with `User=root` (not typical — but [syncthing (109)](../containers/109-syncthing.md) is one), add a drop-in with `SupplementaryGroups=media`. Systemd skips `initgroups()` for `User=root`. +4. For systemd services running with `User=root` (not typical), add a drop-in with `SupplementaryGroups=media`. Systemd skips `initgroups()` for `User=root`. 5. `pct exec` sessions don't get supplementary groups (no initgroups). Use `sudo -i` or `su - ` inside the container to verify membership interactively. Real services use `initgroups` and work correctly. ## State snapshot @@ -41,7 +41,7 @@ Every LXC that mounts `/mnt/library` participates in a shared `media` group with - `downloads` — \*arr stack output - `images` — photoprism / immich / mulita - `roms` — emu frontends - - `syncthing` — cross-device sync + - `syncthing` — empty subtree, retained for archaeology (LXC 109 destroyed 2026-05-14) - Container-specific subtrees intentionally **not** migrated (keep their own owner:group): - `documents` (paperless, `www-data:www-data 750`) - `homecloud` (nextcloud — its own permission model, easy to break) @@ -57,20 +57,19 @@ Every LXC that mounts `/mnt/library` participates in a shared `media` group with | 103 | [paperless](../containers/103-paperless.md) | priv | www-data | | 104 | [gitea](../containers/104-gitea.md) | priv | www-data, gitea | | 105 | [apps](../containers/105-apps.md) | priv | www-data | -| 109 | [syncthing](../containers/109-syncthing.md) | **unpriv + idmap** | root (via `SupplementaryGroups=media` drop-in on `syncthing@.service`) | | 114 | [nextcloud](../containers/114-nextcloud.md) | priv | www-data | | 119 | [sophia](../containers/119-sophia.md) | priv | www-data | | 120 | [mule-images](../containers/120-mule-images.md) | priv | www-data | | 122 | [arriman](../containers/122-arriman.md) | priv | www-data, audiobookshelf, radarr, sonarr, lidarr, prowlarr, qbittorrent, bazarr, jellyseerr, mylar, jackett, overseerr, plex, arr | -> Some entries from earlier snapshots — 100 (arr-yunohost), 107 (marimo), 110 (photoprism), 112 (immich), 116 (heaper) — referenced LXCs that have since been destroyed. See [containers/index](../containers/index.md#recently-destroyed-kept-for-archaeology). +> Some entries from earlier snapshots — 100 (arr-yunohost), 107 (marimo), 109 (syncthing), 110 (photoprism), 112 (immich), 116 (heaper) — referenced LXCs that have since been destroyed. See [containers/index](../containers/index.md#recently-destroyed-kept-for-archaeology). -Config backups: `/root/101.conf.bak.*`, `/root/109.conf.bak.*`. +Config backups: `/root/101.conf.bak.*`, `/root/109.conf.bak.*` (109 destroyed 2026-05-14). ## Gotchas - **[apps (105)](../containers/105-apps.md) is a Docker host.** Adding `media` to the LXC alone is *not* enough for Docker containers inside. Each Docker container needs its GID passed in explicitly: `--group-add 10000` or `user: ":10000"` in compose. Booklore, audiobookshelf-in-docker, etc. need this per-container. -- **`pct exec` does NOT run initgroups.** So `pct exec 109 -- id` shows only the primary group. For interactive verification, use `pct exec 109 -- sudo -i -u root id` or `su - -c id`. Real systemd services work fine. +- **`pct exec` does NOT run initgroups.** So `pct exec -- id` shows only the primary group. For interactive verification, use `pct exec -- sudo -i -u root id` or `su - -c id`. Real systemd services work fine. - **systemd `User=root`** skips initgroups — explicit `SupplementaryGroups=media` drop-in needed. - **`pct restore`** or template rebuilds wipe in-container group membership and unprivileged-LXC idmap blocks. Re-apply from this page. - **`/etc/subgid`** must retain both `root:100000:65536` AND `root:10000:1`. Dropping the second breaks startup of any unprivileged LXC with the idmap block. @@ -84,6 +83,9 @@ Config backups: `/root/101.conf.bak.*`, `/root/109.conf.bak.*`. ## Changelog +### 2026-05-14 — LXC 109 (syncthing) destroyed +Removed the syncthing row from the membership table and the syncthing-as-`User=root` example from the onboarding section. `/mnt/library/syncthing` subtree was already empty and retained as an empty dir. + ### 2026-05-14 — LXC 116 (heaper) destroyed Removed the heaper row from the LXC membership table and noted the orphaned `/mnt/library/heaper` subtree (224 MiB retained). See [host changelog](../hosts/hubris.md#changelog). diff --git a/vms/100-zimaos.md b/vms/100-zimaos.md index d8a7981..4afbe7f 100644 --- a/vms/100-zimaos.md +++ b/vms/100-zimaos.md @@ -1,6 +1,6 @@ # 100 — `zimaos` -ZimaOS (IceWhale / CasaOS-family NAS distro), installed as a Proxmox VM to evaluate it as a potential primary NAS frontend in front of `/mnt/library` — alongside the existing fleet ([nextcloud (114)](../containers/114-nextcloud.md), [jellyfin (101)](../containers/101-jellyfin.md), [syncthing (109)](../containers/109-syncthing.md), [mule-images (120)](../containers/120-mule-images.md)). +ZimaOS (IceWhale / CasaOS-family NAS distro), installed as a Proxmox VM to evaluate it as a potential primary NAS frontend in front of `/mnt/library` — alongside the existing fleet ([nextcloud (114)](../containers/114-nextcloud.md), [jellyfin (101)](../containers/101-jellyfin.md), [mule-images (120)](../containers/120-mule-images.md)). ## At a glance - **Type:** QEMU VM