From 0be8de8ab04d9f9a54d7532475e005cf76f1ce27 Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Mon, 20 Apr 2026 22:14:13 -0700 Subject: [PATCH] fleet: register vm-esh-nas as 5th Docker host + canonical dockge stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vm-esh-nas (10.0.50.154) is a NAS-adjacent Docker VM on the esh-pve-nas hypervisor. Runs filezilla (port 5800), dockge, beszel-agent, dozzle-agent with /mnt/{share,music,books,media} NFS-mounted from 10.0.50.50. Use this host when a stack needs direct NFS mounts to the ESH NAS shares. Canonicalize dockge as stacks/dockge/ — single compose used on all five Docker hosts with per-host DOCKGE_HOST_LABEL/DOCKGE_HOST_IP in .env so each card on the homepage points at its own instance. Labeled homepage.group=Service Networking. Beszel + Dozzle agent dirs also renamed to beszel-agent- / dozzle-agent- pattern across the fleet for consistency. --- CLAUDE.md | 3 +- README.md | 11 +- servers/vm-esh-nas/README.md | 58 +++++ servers/vm-esh-nas/ssh-target | 1 + servers/vm-esh-nas/system-details.txt | 340 ++++++++++++++++++++++++++ stacks/dockge/.env.example | 23 ++ stacks/dockge/README.md | 66 +++++ stacks/dockge/compose.yaml | 37 +++ 8 files changed, 537 insertions(+), 2 deletions(-) create mode 100644 servers/vm-esh-nas/README.md create mode 100644 servers/vm-esh-nas/ssh-target create mode 100644 servers/vm-esh-nas/system-details.txt create mode 100644 stacks/dockge/.env.example create mode 100644 stacks/dockge/README.md create mode 100644 stacks/dockge/compose.yaml diff --git a/CLAUDE.md b/CLAUDE.md index eaef1fe..1e2c8c6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,6 +59,7 @@ Observed and standardized across servers: | nh3-docker | 10.100.50.40 | NH3 (`10.100.0.0/16`) | General-purpose Docker host (non-GPU VM on nh3-pve) | `servers/nh3-docker/README.md` | | nh3-pve | 10.100.250.60 | NH3 | Proxmox VE hypervisor | `servers/nh3-pve/README.md` | | esh-docker-vm | 10.0.50.45 | ESH home lab (`esteban.net`, `10.0.50.0/24`) | Home-lab Docker host (VM on esh-pve) | `servers/esh-docker-vm/README.md` | +| vm-esh-nas | 10.0.50.154 | ESH home lab | NAS-adjacent Docker host (VM on esh-pve-nas) | `servers/vm-esh-nas/README.md` | | esh-pve | 10.0.250.35 | ESH home lab | Proxmox VE hypervisor | `servers/esh-pve/README.md` | | esh-pve-nas | 10.0.50.55 | ESH home lab | Proxmox VE hypervisor (storage / media) | `servers/esh-pve-nas/README.md` | @@ -66,7 +67,7 @@ Observed and standardized across servers: - GPU-required stacks → `ana-ml2`. - Anaheim non-GPU services → `ana-docker`. - NH-site non-GPU services → `nh3-docker`. -- ESH home-lab workloads (`esteban.net`) → `esh-docker-vm`. Not part of the PFI colo topology, but shares monitoring/backup tooling. +- ESH home-lab workloads (`esteban.net`) → `esh-docker-vm` (general) or `vm-esh-nas` (needs direct NFS mounts from 10.0.50.50). Not part of the PFI colo topology, but shares monitoring/backup tooling. - Cross-site services (e.g. Beszel hub, Dozzle hub) live on `ana-docker` and pull from agents on the other hosts. - **Hypervisors** (`pfi-pve`, `nh3-pve`, `esh-pve`, `esh-pve-nas`) are tracked for inventory / capacity planning. Don't deploy Docker stacks directly on them; new workloads land as VMs. `server_inspect.sh` captures host-level detail only — VM/LXC/ZFS enumeration needs Proxmox-native tooling (`qm list`, `pvesh get …`, `zpool list`). diff --git a/README.md b/README.md index fdbf48c..d96957e 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ See **[CLAUDE.md](CLAUDE.md)** for the full set of conventions and the rules Cla | ana-docker | `10.250.50.70` | Anaheim | General-purpose Docker + cross-site hubs (VM on pfi-pve) | | nh3-docker | `10.100.50.40` | NH3 (`10.100.0.0/16`) | General-purpose Docker (VM on nh3-pve) | | esh-docker-vm | `10.0.50.45` | ESH home lab (`esteban.net`) | Home-lab Docker (VM on esh-pve, non-PFI scope) | +| vm-esh-nas | `10.0.50.154` | ESH home lab | NAS-adjacent Docker, NFS-mounted shares (VM on esh-pve-nas, non-PFI scope) | **Proxmox hypervisors** (tracked for inventory; not Docker targets): @@ -34,6 +35,7 @@ Per-host snapshots of the running system live under `servers//system-detai ├── README.md # this file ├── scripts/ # workstation tooling │ ├── server_inspect.sh # read-only diagnostic, runs on remote via stdin +│ ├── proxmox_inspect.sh # Proxmox-aware probe (VMs, LXCs, storage, backup coverage) │ ├── refresh-server-info.sh # pull fresh system-details.txt for one/all hosts │ ├── add-host.sh # register a new server (writes servers//ssh-target) │ ├── sync-stacks.sh # pull /opt/docker/{compose,conf}/ → stacks-mirror/ @@ -50,6 +52,7 @@ Per-host snapshots of the running system live under `servers//system-detai │ └── README.md ├── stacks-mirror/ # gitignored — live mirror from sync-stacks.sh ├── configs/ # host-level config files that aren't docker-compose +│ ├── homepage/ # canonical config for the fleet dashboard (on esh-docker-vm) │ └── restic// # resticprofile configs + pre-backup hooks └── docs/ # general reference (network, models, proxmox, etc.) └── pfi/ @@ -66,6 +69,9 @@ Per-host snapshots of the running system live under `servers//system-detai - Fleet services: `beszel` (metrics hub, port 8090), `dozzle-hub` (log viewer, 8088), `backrest` (restic UI, 9898) - Backup target: `rest-server-ana` on port 8000 +**GPU ana-ml2 (non-canonical for now):** +- `comfyui`, `kokoro`, `parakeet`, `vibevoice` alongside the canonical `llama-swap` + `vllm-qwen3` + **NH3 (nh3-docker):** - `adguard`, `dockge`, plus Beszel/Dozzle agents @@ -73,7 +79,10 @@ Per-host snapshots of the running system live under `servers//system-detai - `rest-server-nh3` — restic backup target (port 8000) **ESH home lab (esh-docker-vm):** -- `adguard`, `homeassistant` (macvlan), `esphome`, `mosquitto`, `paperless-ngx`, `pgadmin`, `calibre`, `calibre-web`, `drawio`, `traefik`, `homepage`, `uptime-kuma`, plus Beszel/Dozzle agents +- `adguard`, `homeassistant` (macvlan), `esphome`, `mosquitto`, `paperless-ngx`, `pgadmin`, `calibre-web-automated`, `drawio`, `traefik`, `homepage`, `uptime-kuma`, plus Beszel/Dozzle agents + +**ESH home lab (vm-esh-nas):** +- `filezilla` (web UI on port 5800), `dockge`, plus Beszel/Dozzle agents. Mounts `/mnt/{share,music,books,media}` from the Debian NAS at 10.0.50.50. ## Common tasks diff --git a/servers/vm-esh-nas/README.md b/servers/vm-esh-nas/README.md new file mode 100644 index 0000000..cc98513 --- /dev/null +++ b/servers/vm-esh-nas/README.md @@ -0,0 +1,58 @@ +# vm-esh-nas + +Docker VM on the `esh-pve-nas` hypervisor (10.0.50.55), at the ESH home +lab. Runs nas-adjacent containers that need local mounts of the shares +served by the Debian NAS at `10.0.50.50` — Filezilla, a Beszel agent, a +Dozzle agent, and Dockge. + +## Network + +- **LAN IP:** 10.0.50.154 +- **FQDN:** `vm-esh-nas.esteban.net` +- **SSH:** `lkraven@vm-esh-nas` (key auth; `/etc/hosts` entry on the workstation) + +## Hardware (from latest snapshot) + +- **OS:** Debian 12 (bookworm), kernel 6.1.0-32-amd64 +- **CPU:** 4 cores, Intel Xeon W-1250 @ 3.30 GHz (shared with the host) +- **RAM:** 3.8 GB total, ~3.1 GB available +- **Root disk:** 125 GB at 7% used +- **NFS mounts (all from `10.0.50.50`):** + - `/mnt/share` — 96 TB, 4 TB used (general share) + - `/mnt/music` — 92 TB, empty + - `/mnt/books` — 92 TB, 96 GB used + - `/mnt/media` — 111 TB, 20 TB used + - All in `/etc/fstab`, reconnect on boot. + +## What runs here + +| Container | Image | Role | +|---|---|---| +| `beszel-agent` | henrygd/beszel-agent:latest | Metrics agent reporting to the hub on ana-docker | +| `dozzle-agent` | amir20/dozzle:latest | Log agent (exposed on port 7007) | +| `dockge-dockge-1` | louislam/dockge:latest | Local compose UI, port 5001 | +| `filezilla` | jlesage/filezilla | Web Filezilla on port 5800 (referenced in homepage bookmarks.yaml under UltraSeedbox) | + +## Refresh state + +```bash +scripts/refresh-server-info.sh vm-esh-nas +``` + +## Stack mirror layout + +- `stacks-mirror/vm-esh-nas/beszel-agent-esh-nas/` — Beszel agent (canonical in `stacks/beszel/`) +- Other stacks (`dockge`, `dozzle-agent`, `filezilla`) not yet canonicalized; run `sync-stacks.sh vm-esh-nas` to pull them into the mirror. + +## Placement rule + +NAS-adjacent Docker host. Good choice for anything that needs direct NFS +mounts (`/mnt/{share,music,books,media}`) without routing through another +VM. Low RAM ceiling (3.8 GB) — keep heavy workloads elsewhere. + +## Known nits + +- `/opt/docker/compose` is world-writable (drwxrwxrwx). Harmless but + worth tightening at some point. +- `/opt/docker/conf` doesn't exist yet; stacks that need bind-mounted + config (Traefik, CrowdSec, etc.) would need to create it. diff --git a/servers/vm-esh-nas/ssh-target b/servers/vm-esh-nas/ssh-target new file mode 100644 index 0000000..1206dba --- /dev/null +++ b/servers/vm-esh-nas/ssh-target @@ -0,0 +1 @@ +lkraven@10.0.50.154 diff --git a/servers/vm-esh-nas/system-details.txt b/servers/vm-esh-nas/system-details.txt new file mode 100644 index 0000000..dcfd136 --- /dev/null +++ b/servers/vm-esh-nas/system-details.txt @@ -0,0 +1,340 @@ + +===== HOST ===== + +Hostname: vm-esh-nas.esteban.net +Date: 2026-04-20T19:01:19-07:00 +Uptime: up 3 weeks, 2 hours, 44 minutes +OS: Debian GNU/Linux 12 (bookworm) +Kernel: 6.1.0-32-amd64 +Arch: x86_64 + +===== HARDWARE ===== + +CPU cores: 4 +CPU model: Intel(R) Xeon(R) W-1250 CPU @ 3.30GHz +MemTotal: 3.8 GB +MemAvailable: 3.1 GB + +===== GPUS ===== + +nvidia-smi not present (no NVIDIA GPUs or driver not installed) + +===== FILESYSTEMS (df) ===== + +Filesystem Size Used Avail Use% Mounted on +/dev/sda1 125G 7.2G 111G 7% / +10.0.50.50:/mnt/share 96T 4.0T 92T 5% /mnt/share +10.0.50.50:/mnt/music 92T 0 92T 0% /mnt/music +10.0.50.50:/mnt/books 92T 96G 92T 1% /mnt/books +10.0.50.50:/mnt/media 111T 20T 92T 18% /mnt/media + +===== PERSISTENT MOUNTS (/etc/fstab, non-comment) ===== + +UUID=e7048b10-408e-4cf7-8d2c-e3a3b4b41454 / ext4 errors=remount-ro 0 1 +UUID=335486fa-ba3c-442d-99fe-a29ec498f218 none swap sw 0 0 +/dev/sr0 /media/cdrom0 udf,iso9660 user,noauto 0 0 +10.0.50.50:/mnt/books /mnt/books nfs defaults 0 0 +10.0.50.50:/mnt/media /mnt/media nfs defaults 0 0 +10.0.50.50:/mnt/share /mnt/share nfs defaults 0 0 +10.0.50.50:/mnt/music /mnt/music nfs defaults 0 0 + +===== TARGETED DATA PATHS ===== + +/opt (total: 60K) + total 16 + drwxr-xr-x 4 root root 4096 2024-06-08 10:55 . + drwxr-xr-x 19 root root 4096 2025-04-04 11:42 .. + drwx--x--x 4 root root 4096 2024-06-08 10:55 containerd + drwxrwxrwx 3 root root 4096 2026-04-20 18:56 docker + +/opt/docker (total: 52K) + total 12 + drwxrwxrwx 3 root root 4096 2026-04-20 18:56 . + drwxr-xr-x 4 root root 4096 2024-06-08 10:55 .. + drwxr-xr-x 6 lkraven lkraven 4096 2026-04-20 18:57 compose + +/opt/docker/compose (total: 48K) + total 24 + drwxr-xr-x 6 lkraven lkraven 4096 2026-04-20 18:57 . + drwxrwxrwx 3 root root 4096 2026-04-20 18:56 .. + drwxr-xr-x 2 lkraven lkraven 4096 2026-04-19 01:09 beszel-agent-esh-nas + drwxr-xr-x 2 lkraven lkraven 4096 2026-04-20 18:56 dockge + drwxr-xr-x 2 root root 4096 2026-04-19 00:43 dozzle-agent + drwxr-xr-x 2 root root 4096 2025-04-04 11:42 filezilla + +/var/lib/docker (total: 4.0K) + +/srv (total: 4.0K) + total 8 + drwxr-xr-x 2 root root 4096 2024-06-08 10:34 . + drwxr-xr-x 19 root root 4096 2025-04-04 11:42 .. + + +===== DOCKER ===== + +Server: 28.0.4 Client: 28.0.4 + +----- docker info ----- +Containers: 4 (running 4, paused 0, stopped 0) +Images: 9 +Runtimes: map[io.containerd.runc.v2:{{runc [] map[]} map[org.opencontainers.runtime-spec.features:{"ociVersionMin":"1.0.0","ociVersionMax":"1.2.0","hooks":["prestart","createRuntime","createContainer","startContainer","poststart","poststop"],"mountOptions":["async","atime","bind","defaults","dev","diratime","dirsync","exec","iversion","lazytime","loud","mand","noatime","nodev","nodiratime","noexec","noiversion","nolazytime","nomand","norelatime","nostrictatime","nosuid","nosymfollow","private","ratime","rbind","rdev","rdiratime","relatime","remount","rexec","rnoatime","rnodev","rnodiratime","rnoexec","rnorelatime","rnostrictatime","rnosuid","rnosymfollow","ro","rprivate","rrelatime","rro","rrw","rshared","rslave","rstrictatime","rsuid","rsymfollow","runbindable","rw","shared","silent","slave","strictatime","suid","symfollow","sync","tmpcopyup","unbindable"],"linux":{"namespaces":["cgroup","ipc","mount","network","pid","time","user","uts"],"capabilities":["CAP_CHOWN","CAP_DAC_OVERRIDE","CAP_DAC_READ_SEARCH","CAP_FOWNER","CAP_FSETID","CAP_KILL","CAP_SETGID","CAP_SETUID","CAP_SETPCAP","CAP_LINUX_IMMUTABLE","CAP_NET_BIND_SERVICE","CAP_NET_BROADCAST","CAP_NET_ADMIN","CAP_NET_RAW","CAP_IPC_LOCK","CAP_IPC_OWNER","CAP_SYS_MODULE","CAP_SYS_RAWIO","CAP_SYS_CHROOT","CAP_SYS_PTRACE","CAP_SYS_PACCT","CAP_SYS_ADMIN","CAP_SYS_BOOT","CAP_SYS_NICE","CAP_SYS_RESOURCE","CAP_SYS_TIME","CAP_SYS_TTY_CONFIG","CAP_MKNOD","CAP_LEASE","CAP_AUDIT_WRITE","CAP_AUDIT_CONTROL","CAP_SETFCAP","CAP_MAC_OVERRIDE","CAP_MAC_ADMIN","CAP_SYSLOG","CAP_WAKE_ALARM","CAP_BLOCK_SUSPEND","CAP_AUDIT_READ","CAP_PERFMON","CAP_BPF","CAP_CHECKPOINT_RESTORE"],"cgroup":{"v1":true,"v2":true,"systemd":true,"systemdUser":true,"rdma":true},"seccomp":{"enabled":true,"actions":["SCMP_ACT_ALLOW","SCMP_ACT_ERRNO","SCMP_ACT_KILL","SCMP_ACT_KILL_PROCESS","SCMP_ACT_KILL_THREAD","SCMP_ACT_LOG","SCMP_ACT_NOTIFY","SCMP_ACT_TRACE","SCMP_ACT_TRAP"],"operators":["SCMP_CMP_EQ","SCMP_CMP_GE","SCMP_CMP_GT","SCMP_CMP_LE","SCMP_CMP_LT","SCMP_CMP_MASKED_EQ","SCMP_CMP_NE"],"archs":["SCMP_ARCH_AARCH64","SCMP_ARCH_ARM","SCMP_ARCH_MIPS","SCMP_ARCH_MIPS64","SCMP_ARCH_MIPS64N32","SCMP_ARCH_MIPSEL","SCMP_ARCH_MIPSEL64","SCMP_ARCH_MIPSEL64N32","SCMP_ARCH_PPC","SCMP_ARCH_PPC64","SCMP_ARCH_PPC64LE","SCMP_ARCH_RISCV64","SCMP_ARCH_S390","SCMP_ARCH_S390X","SCMP_ARCH_X32","SCMP_ARCH_X86","SCMP_ARCH_X86_64"],"knownFlags":["SECCOMP_FILTER_FLAG_TSYNC","SECCOMP_FILTER_FLAG_SPEC_ALLOW","SECCOMP_FILTER_FLAG_LOG"],"supportedFlags":["SECCOMP_FILTER_FLAG_TSYNC","SECCOMP_FILTER_FLAG_SPEC_ALLOW","SECCOMP_FILTER_FLAG_LOG"]},"apparmor":{"enabled":true},"selinux":{"enabled":true},"intelRdt":{"enabled":true},"mountExtensions":{"idmap":{"enabled":true}}},"annotations":{"io.github.seccomp.libseccomp.version":"2.5.4","org.opencontainers.runc.checkpoint.enabled":"true","org.opencontainers.runc.commit":"v1.2.5-0-g59923ef","org.opencontainers.runc.version":"1.2.5"},"potentiallyUnsafeConfigAnnotations":["bundle","org.systemd.property.","org.criu.config"]}]} runc:{{runc [] map[]} map[org.opencontainers.runtime-spec.features:{"ociVersionMin":"1.0.0","ociVersionMax":"1.2.0","hooks":["prestart","createRuntime","createContainer","startContainer","poststart","poststop"],"mountOptions":["async","atime","bind","defaults","dev","diratime","dirsync","exec","iversion","lazytime","loud","mand","noatime","nodev","nodiratime","noexec","noiversion","nolazytime","nomand","norelatime","nostrictatime","nosuid","nosymfollow","private","ratime","rbind","rdev","rdiratime","relatime","remount","rexec","rnoatime","rnodev","rnodiratime","rnoexec","rnorelatime","rnostrictatime","rnosuid","rnosymfollow","ro","rprivate","rrelatime","rro","rrw","rshared","rslave","rstrictatime","rsuid","rsymfollow","runbindable","rw","shared","silent","slave","strictatime","suid","symfollow","sync","tmpcopyup","unbindable"],"linux":{"namespaces":["cgroup","ipc","mount","network","pid","time","user","uts"],"capabilities":["CAP_CHOWN","CAP_DAC_OVERRIDE","CAP_DAC_READ_SEARCH","CAP_FOWNER","CAP_FSETID","CAP_KILL","CAP_SETGID","CAP_SETUID","CAP_SETPCAP","CAP_LINUX_IMMUTABLE","CAP_NET_BIND_SERVICE","CAP_NET_BROADCAST","CAP_NET_ADMIN","CAP_NET_RAW","CAP_IPC_LOCK","CAP_IPC_OWNER","CAP_SYS_MODULE","CAP_SYS_RAWIO","CAP_SYS_CHROOT","CAP_SYS_PTRACE","CAP_SYS_PACCT","CAP_SYS_ADMIN","CAP_SYS_BOOT","CAP_SYS_NICE","CAP_SYS_RESOURCE","CAP_SYS_TIME","CAP_SYS_TTY_CONFIG","CAP_MKNOD","CAP_LEASE","CAP_AUDIT_WRITE","CAP_AUDIT_CONTROL","CAP_SETFCAP","CAP_MAC_OVERRIDE","CAP_MAC_ADMIN","CAP_SYSLOG","CAP_WAKE_ALARM","CAP_BLOCK_SUSPEND","CAP_AUDIT_READ","CAP_PERFMON","CAP_BPF","CAP_CHECKPOINT_RESTORE"],"cgroup":{"v1":true,"v2":true,"systemd":true,"systemdUser":true,"rdma":true},"seccomp":{"enabled":true,"actions":["SCMP_ACT_ALLOW","SCMP_ACT_ERRNO","SCMP_ACT_KILL","SCMP_ACT_KILL_PROCESS","SCMP_ACT_KILL_THREAD","SCMP_ACT_LOG","SCMP_ACT_NOTIFY","SCMP_ACT_TRACE","SCMP_ACT_TRAP"],"operators":["SCMP_CMP_EQ","SCMP_CMP_GE","SCMP_CMP_GT","SCMP_CMP_LE","SCMP_CMP_LT","SCMP_CMP_MASKED_EQ","SCMP_CMP_NE"],"archs":["SCMP_ARCH_AARCH64","SCMP_ARCH_ARM","SCMP_ARCH_MIPS","SCMP_ARCH_MIPS64","SCMP_ARCH_MIPS64N32","SCMP_ARCH_MIPSEL","SCMP_ARCH_MIPSEL64","SCMP_ARCH_MIPSEL64N32","SCMP_ARCH_PPC","SCMP_ARCH_PPC64","SCMP_ARCH_PPC64LE","SCMP_ARCH_RISCV64","SCMP_ARCH_S390","SCMP_ARCH_S390X","SCMP_ARCH_X32","SCMP_ARCH_X86","SCMP_ARCH_X86_64"],"knownFlags":["SECCOMP_FILTER_FLAG_TSYNC","SECCOMP_FILTER_FLAG_SPEC_ALLOW","SECCOMP_FILTER_FLAG_LOG"],"supportedFlags":["SECCOMP_FILTER_FLAG_TSYNC","SECCOMP_FILTER_FLAG_SPEC_ALLOW","SECCOMP_FILTER_FLAG_LOG"]},"apparmor":{"enabled":true},"selinux":{"enabled":true},"intelRdt":{"enabled":true},"mountExtensions":{"idmap":{"enabled":true}}},"annotations":{"io.github.seccomp.libseccomp.version":"2.5.4","org.opencontainers.runc.checkpoint.enabled":"true","org.opencontainers.runc.commit":"v1.2.5-0-g59923ef","org.opencontainers.runc.version":"1.2.5"},"potentiallyUnsafeConfigAnnotations":["bundle","org.systemd.property.","org.criu.config"]}]}] +Default runtime: runc +Storage driver: overlay2 +Root dir: /var/lib/docker +Server version: 28.0.4 + +----- running containers ----- +NAMES IMAGE STATUS PORTS +beszel-agent henrygd/beszel-agent:latest Up 4 minutes +dockge-dockge-1 louislam/dockge:latest Up 4 minutes (healthy) 0.0.0.0:5001->5001/tcp, [::]:5001->5001/tcp +dozzle-agent amir20/dozzle:latest Up 42 hours 0.0.0.0:7007->7007/tcp, 8080/tcp +filezilla jlesage/filezilla Up 2 weeks 0.0.0.0:5800->5800/tcp, [::]:5800->5800/tcp, 5900/tcp + +----- all containers ----- +NAMES IMAGE STATUS +beszel-agent henrygd/beszel-agent:latest Up 4 minutes +dockge-dockge-1 louislam/dockge:latest Up 4 minutes (healthy) +dozzle-agent amir20/dozzle:latest Up 42 hours +filezilla jlesage/filezilla Up 2 weeks + +----- networks ----- +NAME DRIVER SCOPE +bridge bridge local +filezilla_default bridge local +host host local +none null local +traefik-net bridge local + +----- networks (external, non-default — worth knowing for compose external: true) ----- +filezilla_default +traefik-net + +----- named volumes ----- +VOLUME NAME DRIVER +beszel-agent-esh-nas_beszel_agent_data local +beszel-vm-esh-nas_beszel_agent_data local +dockge_dockge_data local +dozzle-agent_dozzle_agent_data local + +----- compose projects currently running ----- +beszel-agent-esh-nas +dockge +dozzle-agent +filezilla + +===== COMPOSE FILES (/opt/docker/compose/) ===== + + +>>> /opt/docker/compose/beszel-agent-esh-nas/compose.yaml +# Beszel — lightweight server/container monitoring. +# +# Hub: single web UI with the SQLite store. Agents: per-host metric collectors +# that the hub pulls from over SSH. +# +# Multi-host layout via compose profiles: +# COMPOSE_PROFILES=hub → hub only (ana-docker) +# COMPOSE_PROFILES=hub,agent → hub + local agent on the same host +# COMPOSE_PROFILES=agent → agent only (ana-ml2) +# +# The agent uses network_mode: host so it sees real host CPU/mem/net/disk +# counters rather than container-scoped ones — that's why it can't share +# the tnet network with the hub. +# +# All tunables live in .env — edit that, not this file. + +services: + beszel: + image: henrygd/beszel:${BESZEL_VERSION} + container_name: beszel + profiles: [hub] + restart: unless-stopped + ports: + - "${BESZEL_PORT}:8090" + volumes: + - beszel_data:/beszel_data + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:8090/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 15s + networks: + - tnet + labels: + - homepage.group=PFI-ANA + - homepage.name=Beszel + - homepage.icon=mdi-chart-line + - homepage.description=Server + container monitoring + - homepage.href=http://10.250.50.70:${BESZEL_PORT} + + beszel-agent: + image: henrygd/beszel-agent:${BESZEL_VERSION} + container_name: beszel-agent + profiles: [agent] + restart: unless-stopped + network_mode: host + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - beszel_agent_data:/var/lib/beszel-agent + environment: + - PORT=${BESZEL_AGENT_PORT:-45876} + - KEY=${BESZEL_HUB_KEY} + - HUB_URL=${HUB_URL} + - TOKEN=${BESZEL_TOKEN} + - EXTRA_FILESYSTEMS=${BESZEL_EXTRA_FS:-} + +volumes: + beszel_data: + beszel_agent_data: + +networks: + tnet: + name: traefik-net + external: true +>>> /opt/docker/compose/dockge/compose.yaml +services: + dockge: + image: louislam/dockge:latest + restart: unless-stopped + ports: + # Host Port : Container Port + - 5001:5001 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - dockge_data:/app/data + - /opt/docker:/opt/docker + labels: + - homepage.group=ESH + - homepage.name=Dockge + - homepage.icon=si-portainer + - homepage.description=Docker on ESH-NAS + - homepage.href=http://10.0.50.55 + environment: + # Tell Dockge where is your stacks directory + - DOCKGE_STACKS_DIR=/opt/docker/compose + networks: + - tnet + +volumes: + dockge_data: null + +networks: + tnet: + name: traefik-net + external: true + +>>> /opt/docker/compose/dozzle-agent/compose.yaml +# Dozzle — container log viewer. +# +# Multi-host layout via compose profiles: +# COMPOSE_PROFILES=hub → runs the web UI (deploy on ana-docker) +# COMPOSE_PROFILES=agent → runs the remote agent (deploy on ana-ml2) +# +# Same compose.yaml on both servers; per-host `.env` picks the profile. +# +# All tunables live in .env — edit that, not this file. + +services: + dozzle: + image: amir20/dozzle:${DOZZLE_VERSION} + container_name: dozzle + profiles: + - hub + restart: unless-stopped + ports: + - ${DOZZLE_PORT}:8080 + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - dozzle_data:/data + environment: + - DOZZLE_HOSTNAME=${DOZZLE_HOSTNAME} + - DOZZLE_REMOTE_AGENT=${DOZZLE_REMOTE_AGENT:-} + - DOZZLE_AUTH_PROVIDER=${DOZZLE_AUTH_PROVIDER:-none} + - DOZZLE_USERNAME=${DOZZLE_USERNAME:-} + - DOZZLE_PASSWORD=${DOZZLE_PASSWORD:-} + healthcheck: + test: + - CMD + - /dozzle + - healthcheck + interval: 30s + timeout: 10s + retries: 3 + start_period: 15s + networks: + - tnet + labels: + - homepage.group=PFI-ANA + - homepage.name=Dozzle + - homepage.icon=mdi-text-box-search + - homepage.description=Container logs (ana-docker + ana-ml2) + - homepage.href=http://10.250.50.70:${DOZZLE_PORT} + dozzle-agent: + image: amir20/dozzle:${DOZZLE_VERSION} + container_name: dozzle-agent + profiles: + - agent + restart: unless-stopped + command: agent + ports: + - ${DOZZLE_AGENT_BIND:-0.0.0.0}:${DOZZLE_AGENT_PORT}:7007 + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - dozzle_agent_data:/data + environment: + - DOZZLE_HOSTNAME=${DOZZLE_HOSTNAME} + networks: + - tnet +volumes: + dozzle_data: null + dozzle_agent_data: null +networks: + tnet: + name: traefik-net + external: true +>>> /opt/docker/compose/filezilla/compose.yaml +services: + filezilla: + image: jlesage/filezilla + environment: + - PUID=2000 + - PGID=2000 + volumes: + - /home/user:/storage:rw + - /docker/appdata/filezilla:/config:rw + - /mnt/share:/NAS/share + - /mnt/music:/NAS/music + - /mnt/books:/NAS/books + - /mnt/media:/NAS/media + ports: + - 5800:5800 + container_name: filezilla +networks: {} + +===== CONFIG LAYOUT (/opt/docker/conf/ — top 200 entries) ===== + +/opt/docker/conf not present + +===== LISTENING PORTS ===== + +0.0.0.0:111 +0.0.0.0:22 +0.0.0.0:5001 +0.0.0.0:5800 +0.0.0.0:7007 +[::]:111 +[::]:22 +[::]:5001 +[::]:5800 + +===== MODEL / HUGGINGFACE CACHES ===== + + +===== DOCKER-ADJACENT SYSTEMD SERVICES ===== + +containerd.service running +docker.service running + +===== DONE ===== + +Paste the above back into the chat, or pass a path as argv[1] to save. diff --git a/stacks/dockge/.env.example b/stacks/dockge/.env.example new file mode 100644 index 0000000..b3d8c8f --- /dev/null +++ b/stacks/dockge/.env.example @@ -0,0 +1,23 @@ +# Dockge per-host tunables. +# +# Copy to .env on each host. Most defaults are fine; the HOST_LABEL and +# HOST_IP are what the homepage card shows, so they must be set per-host. + +# Image pin (blank = latest) +DOCKGE_VERSION=latest + +# Port on the host. Default matches the upstream docs. +DOCKGE_PORT=5001 + +# Human-readable host name for the homepage card, e.g. +# ana-docker, nh3-docker, esh-docker-vm, vm-esh-nas, ana-ml2 +DOCKGE_HOST_LABEL= + +# IP (or hostname) the browser uses to reach this Dockge. Used in +# homepage.href — must be reachable from wherever you view homepage. +# ana-docker → 10.250.50.70 +# ana-ml2 → 10.250.50.54 +# nh3-docker → 10.100.50.40 +# esh-docker-vm → 10.0.50.45 +# vm-esh-nas → 10.0.50.154 +DOCKGE_HOST_IP= diff --git a/stacks/dockge/README.md b/stacks/dockge/README.md new file mode 100644 index 0000000..700ad13 --- /dev/null +++ b/stacks/dockge/README.md @@ -0,0 +1,66 @@ +# dockge + +Per-host [Dockge](https://dockge.kuma.pet/) — a lightweight web UI for +the compose files in `/opt/docker/compose/`. Runs one instance on every +Docker host in the fleet. + +## Layout + +- `compose.yaml` — canonical, same file pushed to every host +- `.env.example` — per-host tunables; `DOCKGE_HOST_LABEL` + `DOCKGE_HOST_IP` vary + +## Homepage + +Labeled `homepage.group=Service Networking` so all five Dockge instances +collapse into the toolchain group on the dashboard, each card pointing +at its own host's web UI. + +## Deploy + +```bash +cp stacks/dockge/compose.yaml stacks-mirror//dockge/ +scripts/deploy-stack.sh dockge --compose +ssh -t 'cd /opt/docker/compose/dockge && sudo docker compose up -d --force-recreate' +``` + +The `.env` with the correct `DOCKGE_HOST_LABEL` / `DOCKGE_HOST_IP` must +exist on the host before the deploy — otherwise the homepage labels will +render with empty substitutions. Initial seed per host: + +```bash +# ana-docker +ssh -t ana-docker 'sudo tee /opt/docker/compose/dockge/.env > /dev/null < /dev/null < /dev/null < /dev/null < /dev/null </dockge/` before each deploy. diff --git a/stacks/dockge/compose.yaml b/stacks/dockge/compose.yaml new file mode 100644 index 0000000..3e70ff0 --- /dev/null +++ b/stacks/dockge/compose.yaml @@ -0,0 +1,37 @@ +# Dockge — per-host Docker Compose UI (https://dockge.kuma.pet/). +# +# One instance runs on every Docker host so the compose dir is manageable +# from a browser. Each host sets DOCKGE_HOST_LABEL + DOCKGE_HOST_IP in its +# .env so the homepage card points at the right place. +# +# All tunables live in .env — edit that, not this file. + +services: + dockge: + image: louislam/dockge:${DOCKGE_VERSION:-latest} + container_name: dockge + restart: unless-stopped + ports: + - "${DOCKGE_PORT:-5001}:5001" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - dockge_data:/app/data + - /opt/docker:/opt/docker + environment: + - DOCKGE_STACKS_DIR=/opt/docker/compose + networks: + - tnet + labels: + - homepage.group=Service Networking + - homepage.name=Dockge (${DOCKGE_HOST_LABEL}) + - homepage.icon=si-portainer + - homepage.description=Compose UI on ${DOCKGE_HOST_LABEL} + - homepage.href=http://${DOCKGE_HOST_IP}:${DOCKGE_PORT:-5001} + +volumes: + dockge_data: + +networks: + tnet: + name: traefik-net + external: true