Docker Swarm is the main application runtime. Services are defined in ~/Docker-Swarm, deployed as stacks, routed by Traefik, and reconciled from Git by HiveMind.
The Swarm layer is intentionally boring. It is not trying to be Kubernetes; it is a practical container scheduler for a home lab where Compose files, Git review, shared storage, and predictable routing matter more than maximum abstraction. The active desired state lives in Docker-Swarm/stacks.yml, and HiveMind reconciles that desired state into the live Swarm cluster.
This page covers the runtime pieces. Physical networking and power live in Hardware, VM placement lives in VMs, and user-facing service names live in List of Services.
| Role | Nodes |
|---|---|
| Managers | ubuntu-ms-01, ubuntu-ms-02, ubuntu-ms-03 |
| Workers | ubuntu-m900-1, ubuntu-m900-4, ubuntu-neo-1, ubuntu-neo-2 |
| Shared manager VIP | 10.0.30.40 |
| Shared overlay network | Lab |
The Swarm managers run Keepalived so cluster join and control-plane operations can use the shared VIP instead of pinning everything to one manager IP.
Manager VMs sit on the MS-01 tier because those hosts are the primary cluster/storage systems. Worker VMs sit on the M900 and Neo systems, giving the app layer extra placement options without making every physical host part of the control plane.
Keepalived is installed by the keepalived Ansible role during playbooks/docker/provision-swarm.yml.
| Setting | Value |
|---|---|
| VIP | 10.0.30.40 |
| VRRP instance | VI_1 |
| Router ID | 31 |
| Interface default | bond0, auto-resolved to the default interface if missing |
| Participants | Swarm manager VMs |
| Master selection | First host in swarm_managers inventory starts as MASTER |
The primary manager initializes Swarm with its real address. Other managers and workers join through the VIP with docker swarm join --token ... 10.0.30.40.
Keepalived is host/VM infrastructure, not a Swarm service. If the VIP is not present, fix the Ansible/Keepalived layer before assuming HiveMind or an app stack is broken.
~/Docker-Swarm/Compose-Files.~/Docker-Swarm/stacks.yml groups compose files into enabled Swarm stacks.Nichols-HomeLab/Docker-Swarm on main.docker stack deploy.Lab network.| Stack | Purpose |
|---|---|
arr |
Media automation apps such as Radarr, Sonarr, Lidarr, Prowlarr, Bazarr, and helpers. |
backup |
Backrest and Restic backup runners. |
databases |
Shared PostgreSQL, MariaDB, MongoDB, Redis, and metrics storage components. |
DNS |
Technitium DNS. |
downloaders |
qBittorrent, SABnzbd, JDownloader, slskd, and related download workflows. |
external |
User-facing apps such as Plex, Jellyfin, Nextcloud, Immich, Paperless, Wiki.js, Gitea, and search tools. |
game-servers |
ATM10 and Minecraft. |
media |
Media maintenance helpers like Kometa, Gaps, Kavita, and watch-state sync. |
monitoring |
Grafana, Uptime Kuma, Dozzle, Homepage, Loki, Alloy, cAdvisor, node exporter, and Portainer. |
notifications |
ntfy. |
random |
Utility jobs and personal tools such as DDNS, GitHub backup, Ollama, Paperless AI, and Upsnap. |
registry |
Private container registry and garbage collection. |
reverse-proxy |
Traefik, Authentik, and CrowdSec. |
runners |
GitHub runner, HiveMind, and Renovate. |
security |
Trivy runner. |
The Lab Docker network is an attachable Swarm overlay network created by the docker_lab_network role. Traefik uses this network to reach services.
Public request path:
Lab network.Swarm uses two main shared storage patterns:
| Storage | Backing source | Used for |
|---|---|---|
| CephFS | MS-01 Ceph cluster | App config and shared service data under /mnt/cephfs/docker. |
| Unraid NFS bind volumes | Tower at 10.0.30.116 |
Media, games, backups, cloud data, and ISOs. |
Canonical Unraid-backed Docker volumes:
| Docker volume | Unraid share |
|---|---|
unraid-data |
:/mnt/user/data |
unraid-games |
:/mnt/user/Games |
unraid-backup |
:/mnt/user/Backup |
unraid-cloud |
:/mnt/user/cloud |
unraid-isos |
:/mnt/user/isos |
The HomeLab role mounts these shares under /srv/shared_volumes, creates bind-backed Docker volumes, and installs a timer to repair stale NFS handles.
| Service family | HA shape |
|---|---|
| PostgreSQL | Patroni plus etcd and controller endpoint. |
| MariaDB | Galera nodes plus controller endpoint. |
| MongoDB | Three-member replica set. |
| Redis | Redis nodes plus Sentinel and controller endpoint. |
Apps should use the shared controller endpoints when possible. Historical per-app databases are kept out of the active model unless an app requires a sidecar.
The tradeoff is that the database stack becomes especially important. If PostgreSQL, Redis, MariaDB, or MongoDB has a problem, multiple apps may fail at the same time. That is why the database stack needs clear monitoring, predictable backups, and careful changes.
docker node ls
docker stack ls
docker stack services <stack>
docker service logs -f <stack>_<service>
docker network inspect Lab
systemctl status keepalived
| Symptom | First checks |
|---|---|
| Nodes cannot join Swarm | Keepalived VIP, manager availability, join token, firewall, Docker daemon. |
| Public service is down | Traefik router labels, backend service health, Authentik/CrowdSec middleware, Lab network. |
| Many apps lose data/config | CephFS mount health or shared database stack. |
| Media/game paths fail | Unraid NFS mounts and bind-backed Docker volumes. |
| HiveMind does not deploy | GitHub checks, HiveMind logs, stacks.yml, compose file path. |