Themen, die für Gewächshaus (intern, Mimir) und Schaugarten (öffentlich, Hetzner) gleichermaßen gelten. Beide Standorte sind über WireGuard VPN verbunden.

Netzwerk & DNS

ZoneTypZweck
dyn.veedel.netInternNur im LAN/VPN auflösbar
dyn.nettailor.netExternÖffentliche IPs
nettailor.netExternÖffentliche Domains

DNS wird über BIND verwaltet (Details zum BIND-Host).

Docker-Container mit eigener LAN-IP

Für Container, die als eigenständiges Gerät im LAN auftreten müssen (z. B. AdGuard Home), kommt auf Mimir Docker Macvlan statt Bridge zum Einsatz. Details, Setup und die dabei aufgetretenen Stolperfallen (Host-Isolation, Shim-Interface) siehe Docker-Macvlan.

CI/CD

Seit Juli 2026 laufen die eigenen Container-Deployments über Komodo (Builds/Repos/Procedures), getriggert per Gitea-Webhook bei Push auf main:

  • Image-Builds (tally, inventar, dyn-dns-updater): Komodo Build → Gitea-Registry → Deployment.

  • Git-Repo-Stack (ki-trading-ibkr → Stack ki-trading-stack): Komodo Stack mit Git-Source (klont das Gitea-Repo, baut das build:-Image bei jedem Deploy neu via „Pre Build Images”, up -d recreated). Runtime-Daten liegen absolut außerhalb des Klons (/volume1/docker/ki-trading-data), Env im Komodo-Stack-Feld. Aug 2026 von „Files on Server” umgestellt. (Der frühere ki-trading/Alpaca-Stocks-Agent ist seit Aug 2026 stillgelegt.)

  • Git-Pull + Restart (crypto-ki-trading): Komodo Repo mit on_pull.

  • Statische Sites (garden, lost): Komodo Repo baut/kopiert nach /opt/npm/site/, NPM serviert statisch.

  • Gitea als SCM (gitea.nettailor.net, SSH auf Port 2222).

  • Drone CI (drone.nettailor.net, Server + Runner auf Hetzner + Mimir) bleibt verfügbar für künftige/fremde Repos, wird aber für die eigenen Container nicht mehr genutzt.

🔧 Lessons Learned: Docker Compose – Mount-Änderungen brauchen --force-recreate

Datum: Juli 2026

Nach der Migration von Caddy zu NPM funktionierten garden.nettailor.net und potentiell weitere statisch ausgelieferte Seiten nicht mehr (404). Ursache: der static-Container (nginx:alpine) lief noch mit dem alten Bind-Mount aus der Caddy-Zeit (/var/lib/docker/volumes/caddy_data/_data/site), obwohl das compose.yml längst auf /opt/npm/site umgestellt war.

Grund: Docker liest Volume-/Bind-Mounts nur bei der Erstellung eines Containers ein. Ein reines docker compose restart oder docker restart übernimmt Änderungen an volumes: im compose.yml nicht – der Container muss neu erstellt werden.

Fix:

docker compose up -d --force-recreate <service>

Debugging-Vorgehen, das zum Fehler geführt hat:

  1. docker exec -it static curl -H "Host: garden.nettailor.net" http://localhost:80/ → 404
  2. docker exec -it static ls -la /usr/share/nginx/site/digitalgarden → “No such file or directory”
  3. Host-Seite (ls -la /opt/npm/site/) zeigte aber korrekten Inhalt → Diskrepanz
  4. docker inspect static --format '{{json .Mounts}}' offenbarte den alten Mount-Pfad

Merke: Bei jeder Änderung an volumes: in einem compose.yml grundsätzlich --force-recreate verwenden (oder docker compose down && up -d), nicht nur restart. Betrifft potentiell auch andere Container, die während der Caddy→NPM-Migration nicht neu erstellt wurden – ggf. stichprobenartig mit docker inspect <container> --format '{{json .Mounts}}' gegenprüfen.