*Stand: November 2026
Komodo ist eine Weboberfläche für Docker. Du legst darin Stacks an, bearbeitest Compose-Dateien und Konfigurationswerte im Browser, liest Protokolle mit und siehst, welcher Container wie viel Speicher und Prozessorzeit belegt. Komodo ersetzt Docker nicht, es steuert es – auf einem Server oder auf mehreren aus derselben Oberfläche.
In dieser Reihe ist Komodo ab jetzt der Weg, auf dem jede weitere Anwendung auf den VPS kommt. Der Artikel baut auf Docker mit den beiden Netzen aus Artikel 03 und auf Tailscale aus Artikel 05 auf: Komodo ist ausschließlich über das VPN erreichbar – kein offener Port, keine Domain, kein Anmeldeformular im Internet.
Am Ende hast du
- Komodo Core + Periphery installiert (mit Postgres + FerretDB)
- Web-Oberfläche erreichbar unter
http://vps:9120– nur über Tailscale - Admin-Account angelegt, Registrierung wieder geschlossen
- Core und Periphery verbunden – über automatisch ausgetauschte Schlüssel, ohne manuell verwaltete Secrets
- Die Variablen
DOCKER_ROOTundDATA_ROOTangelegt - Einen Test-Stack über die Komodo-UI ausgerollt und wieder entfernt
- Komodos tägliche Sicherung der eigenen Datenbank in einem Verzeichnis, das mitgesichert wird
- Verstanden, warum genau dieser eine Stack von Hand entsteht und alle folgenden nicht
Voraussetzungen
- Artikel 02–05 abgeschlossen
- Tailscale läuft auf Server und lokalem Rechner,
ssh vpsgeht über das VPN docker composefunktioniert als Benutzermartinohnesudohomelab_netundhomelab_internexistieren (aus Artikel 03)- Die Tailscale-Adresse deines Servers, notiert in Artikel 05 – wir holen sie gleich noch einmal
Getestet mit: Debian 13 · Docker Engine 29.9.3 · Komodo 2.3.4 · FerretDB
Zuletzt durchgespielt: November 2026
1. Was Komodo dir gibt
Im Einzelnen:
- Alle Container auf einen Blick mit CPU-, RAM- und Status-Anzeige
- Logs in Echtzeit im Browser, ohne
docker logs -fim Terminal - Compose-Dateien direkt in der UI editieren, mit Syntax-Highlighting
- Stacks ausrollen, neu starten, stoppen per Mausklick
- Update-Erkennung für Container-Images
- Mehrere Server verwalten aus einem Dashboard (über Periphery-Agents auf jedem Host)
- Meldungen bei Problemen oder Updates – als Push-Nachricht aufs Handy
Core und Periphery
Komodo besteht aus zwei Bausteinen:
| Komponente | Wofür? |
|---|---|
| Komodo Core | Die Web-UI, die du im Browser aufrufst. Speichert Stack-Definitionen, Logins, History. |
| Komodo Periphery | Ein Agent, der auf jedem verwalteten Server läuft und dort tatsächlich die docker-Befehle ausführt. |
Auf einem einzelnen Server laufen beide auf demselben Gerät, getrennt nur durch das interne Docker-Netz. Kommt später ein zweiter Server dazu, installierst du dort nur Periphery – Core bleibt einmal zentral.
Im fertigen Stack laufen am Ende vier Container: Komodo Core, Komodo Periphery, Postgres (mit DocumentDB-Extension) und FerretDB als MongoDB-Adapter dazwischen.
Authentifizierung zwischen Core und Periphery
Core und Periphery authentifizieren sich über automatisch erzeugte Schlüsselpaare (Ed25519). Du musst kein Geheimnis selbst generieren und in Config-Dateien synchron halten:
- Beim ersten Start erzeugen Core und Periphery jeweils ihr eigenes Schlüsselpaar in einem geteilten Docker-Volume.
- In der
.envweisen wir beide an, den Public Key des jeweils anderen direkt aus diesem Volume zu lesen. - Ab da läuft die gegenseitige Authentifizierung über die ausgetauschten Public Keys – ohne manuellen Eingriff.
Für einen zweiten Server gibt es zusätzlich einen Onboarding-Key, mit dem sich dessen Periphery beim bestehenden Core anmeldet. Für einen einzelnen Server brauchst du ihn nicht.
⚠️ Was du Komodo damit gibst
Periphery bekommt Zugriff auf den Docker-Steuerkanal des Servers (
/var/run/docker.sock). Ein Container mit diesem Zugriff kann faktisch alles auf dem Host tun – Container starten, Verzeichnisse einbinden, Rechte ausweiten. Das ist bei jeder Docker-Verwaltungsoberfläche so, egal welche.Genau deshalb steht Komodo hinter dem VPN und nicht hinter einem Anmeldeformular im Internet. Halt dich an diese Regel, auch wenn dir später eine bequemere Variante begegnet.
2. Zugriff: ausschließlich über Tailscale
Komodo darf alle Container auf deinem Server starten, stoppen, löschen. Das bedeutet: kein öffentliches Login-Formular, kein offener Port im Internet, keine Domain. Die Oberfläche ist nur über das Tailscale-VPN erreichbar – genau dafür haben wir es im letzten Artikel eingerichtet.
Wir binden Komodos Port 9120 deshalb gezielt an die Tailscale-Adresse deines Servers. Docker veröffentlicht den Port dann nur auf diesem Interface, nicht auf 0.0.0.0. Damit umgehen wir auch das aus Artikel 03, Abschnitt 7 bekannte Problem, dass Docker veröffentlichte Ports an UFW vorbei in die Firewall einträgt: Wenn der Port erst gar nicht auf der öffentlichen IP gebunden wird, kommt da auch nichts an.
Tailscale-Adresse ermitteln:
tailscale ip -4
Check
Ausgabe: Eine Adresse aus dem Bereich 100.x.x.x – dieselbe, die du in Artikel 05 notiert hast. Du trägst sie gleich zweimal in die .env-Datei ein.
3. Stack-Verzeichnis anlegen
Ab dem nächsten Artikel legt Komodo die Verzeichnisse seiner Stacks selbst an. Für Komodo selbst geht das nicht – es kann sich nicht selbst ausrollen. Dieser eine Stack entsteht deshalb von Hand, im Muster aus Artikel 03:
mkdir -p /srv/docker/stacks/komodo
cd /srv/docker/stacks/komodo
Die Daten-Verzeichnisse für Postgres und FerretDB legt Docker beim ersten Start selbst als benannte Volumes an.
4. Secrets generieren
Komodo nutzt Schlüsselpaare für die Core-Periphery-Authentifizierung (siehe Abschnitt 1) – das spart einige Geheimnisse, die du sonst selbst pflegen müsstest. Was bleibt, sind drei Werte:
echo "DB Passwort: $(openssl rand -hex 24)"
echo "JWT Secret: $(openssl rand -hex 32)"
echo "Webhook Secret: $(openssl rand -hex 24)"
Das Ergebnis sind drei Zeichenketten. Kopiere sie in deinen Passwort-Manager. Du brauchst sie gleich in der .env-Datei und noch einmal, falls du den Stack neu aufsetzt.
Warum hexadezimal?
openssl rand -hexerzeugt nur Ziffern und die Buchstaben a bis f. Damit kann keiner der Werte etwas kaputtmachen: Das Datenbank-Passwort landet in einer Verbindungsadresse der Formmongodb://user:PASSWORT@host, in der+,/und=eine eigene Bedeutung haben, und ab Artikel 07 stehen Geheimnisse in Konfigurationswerten, in denen$eine eigene Bedeutung hat. Ein Zeichensatz für alle Werte erspart dir die Frage, welcher wo hingehört.
⚠️ Niemals Sample-Werte aus Tutorials oder dieser Anleitung übernehmen
Jeder Generator-Aufruf erzeugt frische Zufallswerte. Wenn du Secrets aus Beispielen oder einer öffentlichen Doku übernimmst, sind sie aus Sicherheitssicht wertlos – sie sind ja öffentlich. Generiere immer eigene.
5. .env-Datei erstellen
Komodo nutzt eine .env-Datei zur Konfiguration. Lege sie an:
nano /srv/docker/stacks/komodo/.env
Inhalt (Platzhalter <...> durch deine echten Werte ersetzen – inklusive der eben generierten Secrets und deiner Tailscale-Adresse):
####################################
# 🦎 KOMODO - KONFIGURATION #
####################################
# Image-Version
COMPOSE_KOMODO_IMAGE_TAG=2
# Wo Komodo später erreichbar ist (für Webhook-URLs, Anzeige)
KOMODO_HOST=http://<TAILSCALE-IP>:9120
KOMODO_TITLE=Komodo
# Port-Bindung: Komodo nur über Tailscale erreichbar
TAILSCALE_IP=<TAILSCALE-IP>
# Postgres / FerretDB Zugangsdaten
KOMODO_DATABASE_USERNAME=komodo
KOMODO_DATABASE_PASSWORD=<DB-PASSWORT-AUS-OPENSSL-HEX>
# Krypto-Secrets
KOMODO_JWT_SECRET=<JWT-SECRET-AUS-OPENSSL>
KOMODO_WEBHOOK_SECRET=<WEBHOOK-SECRET-AUS-OPENSSL>
# Auth-Verhalten
KOMODO_LOCAL_AUTH=true
KOMODO_DISABLE_USER_REGISTRATION=false
KOMODO_DISABLE_NON_ADMIN_CREATE=false
KOMODO_TRANSPARENT_MODE=false
KOMODO_JWT_TTL="1-day"
# Monitoring-Intervalle
KOMODO_MONITORING_INTERVAL="15-sec"
KOMODO_RESOURCE_POLL_INTERVAL="5-min"
# Anmeldung über fremde Dienste aus
KOMODO_OIDC_ENABLED=false
KOMODO_GITHUB_OAUTH_ENABLED=false
KOMODO_GOOGLE_OAUTH_ENABLED=false
# Lokalen Server automatisch beim ersten Start anlegen
KOMODO_FIRST_SERVER_NAME=vps
# Schlüsseltausch: Core und Periphery lesen sich gegenseitig
# automatisch aus dem geteilten keys-Volume
KOMODO_PERIPHERY_PUBLIC_KEY=file:/config/keys/periphery.pub
# Periphery
PERIPHERY_CORE_ADDRESS=ws://core:9120
PERIPHERY_CONNECT_AS=${KOMODO_FIRST_SERVER_NAME}
PERIPHERY_CORE_PUBLIC_KEYS=file:/config/keys/core.pub
PERIPHERY_ROOT_DIRECTORY=/srv/docker/stacks/komodo/periphery
PERIPHERY_STACK_DIR=/srv/docker/stacks
# Zeitzone
TZ=Europe/Berlin
Speichern mit Strg + X, Y, Enter.
Check
grep -n "<" /srv/docker/stacks/komodo/.env
Ausgabe: keine. Kommt eine Zeile zurück, ist dort ein Platzhalter stehen geblieben – spitze Klammern gibt es in keinem der echten Werte. Diese Prüfung ist nicht Formsache: Bei KOMODO_DATABASE_PASSWORD fällt ein Platzhalter sofort auf, weil der Stack nicht startet. Bei KOMODO_HOST startet er, und die Zeile fällt erst später auf.
Zu drei Zeilen kurz die Begründung:
KOMODO_DISABLE_USER_REGISTRATION=falseerlaubt gleich das Anlegen des Admin-Accounts. Sobald das erledigt ist, drehen wir den Wert um – damit niemand sonst einen Account anlegen kann.
PERIPHERY_STACK_DIR=/srv/docker/stackslegt fest, dass alle künftigen Stacks unter/srv/docker/stacks/<n>/landen – im Muster aus Artikel 03. Ohne diese Zeile legt Komodo sie in einem eigenen Verzeichnis irgendwo im System ab.
PERIPHERY_ROOT_DIRECTORYist das Arbeitsverzeichnis von Periphery. Es liegt im Komodo-Ordner, damit alles, was zu Komodo gehört, an einer Stelle unter/srv/docker/stackssteht.
Wie die Authentifizierung zwischen Core und Periphery funktioniert: Beide Container teilen sich ein gemeinsames Docker-Volume namens
keys. Beim ersten Start erzeugt Core dort sein Schlüsselpaar (core.key+core.pub), Periphery seins (periphery.key+periphery.pub). Die beiden Public-Key-Pfade stehen oben in der.env. Damit weiß Core, welchem Periphery er vertrauen darf, und umgekehrt. DerKOMODO_FIRST_SERVER_NAMElegt beim ersten Start automatisch einen Server-Eintrag in der UI an, und Periphery verbindet sich überPERIPHERY_CONNECT_ASgenau mit diesem.
Zugriffsrechte einschränken (die Datei enthält jetzt Klartext-Passwörter):
chmod 600 /srv/docker/stacks/komodo/.env
Bei den Stacks ab Artikel 07 entfällt dieser Schritt – dort schreibt Komodo die
.envselbst.
6. compose.yaml erstellen
nano /srv/docker/stacks/komodo/compose.yaml
Inhalt:
name: komodo
services:
postgres:
image: ghcr.io/ferretdb/postgres-documentdb
container_name: komodo-postgres
restart: unless-stopped
labels:
komodo.skip: ""
environment:
POSTGRES_USER: ${KOMODO_DATABASE_USERNAME}
POSTGRES_PASSWORD: ${KOMODO_DATABASE_PASSWORD}
POSTGRES_DB: postgres
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- komodo_internal
ferretdb:
image: ghcr.io/ferretdb/ferretdb
container_name: komodo-ferretdb
restart: unless-stopped
labels:
komodo.skip: ""
environment:
FERRETDB_POSTGRESQL_URL: postgres://${KOMODO_DATABASE_USERNAME}:${KOMODO_DATABASE_PASSWORD}@postgres:5432/postgres
depends_on:
- postgres
volumes:
- ferretdb-state:/state
networks:
- komodo_internal
core:
image: ghcr.io/moghtech/komodo-core:${COMPOSE_KOMODO_IMAGE_TAG}
container_name: komodo-core
init: true
restart: unless-stopped
labels:
komodo.skip: ""
env_file: .env
environment:
KOMODO_DATABASE_ADDRESS: ferretdb:27017
ports:
- "${TAILSCALE_IP}:9120:9120"
volumes:
- keys:/config/keys
- /srv/docker/stacks/komodo/backups:/backups
depends_on:
- ferretdb
networks:
- komodo_internal
- homelab_net
periphery:
image: ghcr.io/moghtech/komodo-periphery:${COMPOSE_KOMODO_IMAGE_TAG}
container_name: komodo-periphery
init: true
restart: unless-stopped
labels:
komodo.skip: ""
env_file: .env
volumes:
- keys:/config/keys
- /var/run/docker.sock:/var/run/docker.sock
- /proc:/proc
- /srv/docker/stacks:/srv/docker/stacks
depends_on:
- core
networks:
- komodo_internal
volumes:
postgres-data:
ferretdb-state:
keys:
networks:
komodo_internal:
name: komodo_internal
homelab_net:
external: true
Speichern und schließen.
Was passiert hier?
| Block | Erklärung |
|---|---|
name: komodo |
Expliziter Projektname (wie in Artikel 03 etabliert). |
komodo.skip: "" |
Markiert alle Container, damit Komodo seinen eigenen Stack nicht stoppt oder neu ausrollt. |
init: true |
Sorgt für sauberes Aufräumen beendeter Prozesse im Container. |
postgres mit DocumentDB-Image |
Postgres + DocumentDB-Extension, Basis für FerretDB. |
keys-Volume |
Speichert die automatisch erzeugten Schlüsselpaare von Core und Periphery. Es muss erhalten bleiben, sonst müssen sich beide bei jedem Neustart neu bekannt machen. |
core mit ports: "${TAILSCALE_IP}:9120:9120" |
Port 9120 wird ausschließlich auf das Tailscale-Interface gebunden. Über die öffentliche IP des VPS ist nichts erreichbar. |
core mit /backups |
Hierhin schreibt Komodo jede Nacht eine Sicherung seiner eigenen Datenbank. Ohne diese Zeile landen die Abzüge nur im Container und sind beim nächsten Update weg. Das Verzeichnis legt Docker beim ersten Start an. |
core an beiden Netzen |
An komodo_internal für den Datenbankzugriff, an homelab_net für den Weg nach draußen. |
periphery ohne ports: |
Periphery ist nur intern erreichbar – Core spricht es über den Container-Namen an. |
/var/run/docker.sock |
Der Steuerkanal zu Docker. Ohne ihn kann Periphery nichts ausführen. |
/proc |
Damit Periphery Prozessorlast und Speicher des Servers auslesen kann. |
/srv/docker/stacks:/srv/docker/stacks |
Innen unter demselben Pfad wie außen. Diese Gleichheit ist wichtig: Periphery gibt Pfade an Docker weiter, und Docker liest sie als Pfade des Hosts. Über diesen einen Eintrag erreicht Periphery beides – die Verzeichnisse der Stacks und sein eigenes Arbeitsverzeichnis. |
komodo_internal mit name: |
Ohne die Zeile hängt Compose den Projektnamen davor. |
Eine bewusste Abweichung von Artikel 03: Das interne Netz bekommt hier kein
internal: true. Komodo sieht regelmäßig nach, ob es neue Versionen der verwendeten Images gibt, und verschickt später Meldungen – beides braucht einen Weg nach draußen. Bei den Anwendungen der App-Artikel ist das anders: Dort wird die Datenbank abgeriegelt.
7. Stack starten
cd /srv/docker/stacks/komodo
docker compose up -d
Beim ersten Start richtet sich Postgres ein (das kann eine Minute dauern), FerretDB verbindet sich, Core kommt hoch und legt sein Schlüsselpaar an, Periphery ebenso.
Check
docker compose ps
Ausgabe: Vier Container, alle Up:
NAME STATUS PORTS
komodo-core Up 30 seconds 100.x.x.x:9120->9120/tcp
komodo-ferretdb Up 35 seconds
komodo-periphery Up 30 seconds
komodo-postgres Up 1 minute
Achte auf die Portspalte bei komodo-core: Dort muss deine Tailscale-Adresse stehen, nicht 0.0.0.0.
Dass sich die beiden Teile gefunden haben, steht im Protokoll:
docker compose logs periphery | grep -i "logged in"
Ausgabe: Eine Zeile in der Art Logged in to Komodo Core core:9120 websocket as Server vps.
Eine Meldung im Protokoll, die harmlos ist:
Failed to connect to websocket … Connection refuseddirekt beim Start. Periphery ist schneller oben als Core, versucht es alle paar Sekunden erneut, und die Erfolgsmeldung steht kurz darauf darunter.Ein Verzeichnis
peripheryunter/srv/docker/stacks/komodo/suchst du an dieser Stelle vergeblich. Periphery legt es erst an, wenn es gebraucht wird.
Wenn etwas nicht startet, zeigen die Protokolle warum:
docker compose logs postgres
docker compose logs ferretdb
docker compose logs core
docker compose logs periphery
Häufigste Ursache: ein Tippfehler in der .env-Datei oder ein Platzhalter, der stehen geblieben ist.
Wenn
komodo-corein einer Restart-Schleife hängt (Restartingindocker compose ps) und das Logpassword must be URL encodedzeigt: Dein DB-Passwort enthält Sonderzeichen. Du hast es vermutlich mit-base64statt-hexerzeugt. Lösung: ein neues Passwort mitopenssl rand -hex 24erzeugen, in der.enveintragen – und weil Postgres das alte Passwort bereits im Volume gespeichert hat, das Volume neu aufsetzen:docker compose down -v docker compose up -dDas ist verlustfrei, solange Komodo noch nie vollständig lief – es sind ja noch keine Daten drin. Achtung:
down -vlöscht alle Volumes des Stacks, auch daskeys-Volume. Das ist hier in Ordnung, weil Komodo die Schlüssel beim nächsten Start neu erzeugt. Bei einem laufenden Komodo wäre derselbe Befehl ein Datenverlust.
8. Erstaufruf der Web-UI
Im Browser, auf einem Gerät, das im Tailscale-Netz angemeldet ist:
http://vps:9120
Der Name kommt aus MagicDNS, eingerichtet in Artikel 05.
Hinweis zur Browser-Warnung „Nicht sicher": Du sprichst Komodo über
http://an, nicht überhttps://– deshalb meldet dein Browser eine fehlende Zertifikatsabsicherung. Das ist hier kein Problem: Die Verbindung läuft durch den Tailscale-Tunnel und ist dort verschlüsselt. Caddy und HTTPS brauchen wir ab dem nächsten Artikel nur für Dienste, die übers offene Internet erreichbar sein sollen.
Falls die Seite nicht lädt, prüfe in dieser Reihenfolge:
- Bist du im Tailscale-Netz aktiv?
tailscale statusauf dem lokalen Rechner sollte den Server zeigen.docker compose psauf dem Server – läuftkomodo-core?- Stimmt die Tailscale-Adresse in der
.env?tailscale ip -4auf dem Server gibt die korrekte Adresse aus.
Admin-Account anlegen
Beim ersten Aufruf erscheint ein Formular, das gleichzeitig Anmeldung und Registrierung ist – ein getrennter Registrieren-Knopf fehlt:
- Benutzernamen eintragen (z. B.
martin) - Passwort vergeben (mindestens 12 Zeichen, am besten aus deinem Passwort-Manager)
- Auf Sign Up klicken
Der erste Account bekommt automatisch alle Rechte. Du bist danach angemeldet.
Wenn nach dem Sign-Up nur „Komodo Log in" ohne Felder erscheint: Die UI hält Dateien hartnäckig im Zwischenspeicher. Strg + Shift + R lädt die Seite vollständig neu und löst das fast immer. Sonst hilft ein privates Browserfenster.

Registrierung schließen
Sofort danach, damit niemand sonst einen Account anlegen kann:
nano /srv/docker/stacks/komodo/.env
Diese Zeile ändern:
KOMODO_DISABLE_USER_REGISTRATION=true
Speichern, dann:
cd /srv/docker/stacks/komodo
docker compose up -d
Docker erneuert nur die Container, die es betrifft. Postgres und FerretDB laufen unverändert weiter.
Check
Im privaten Browserfenster Komodo aufrufen: Jetzt erscheint nur noch die Anmeldung, kein Sign-Up mehr.
9. Server in der UI prüfen
Du musst nichts verbinden – das ist beim ersten Start bereits passiert. Core und Periphery haben ihre Schlüssel ausgetauscht, und KOMODO_FIRST_SERVER_NAME=vps hat den Eintrag für den Server angelegt.
Im Menü auf Servers. Rechts öffnet sich die Übersicht, und darin steht eine Zeile für vps mit der Komodo-Version.
Check
Die Zeile ist grün. Damit steht die Verbindung zwischen Core und Periphery.
Ein Klick auf den Server führt zu seiner Konfiguration; die Live-Werte – Prozessorlast, Speicher, Plattenbelegung – liegen dort im Reiter Stats. Brauchen musst du beides jetzt nicht, aber du weißt, wo es steht.
Den Namen lässt du so. Core ordnet die Anmeldung des Agenten über den Namen zu: Der Eintrag in der Oberfläche muss Zeichen für Zeichen so heißen wie
PERIPHERY_CONNECT_ASin der.env. Benennst du ihn später hier um, musst du die Zeile mitziehen – sonst meldet sich Periphery an, Core findet keinen passenden Eintrag, und der Server steht auf „is not connected".

10. Zwei Variablen anlegen
Bevor der erste App-Stack entsteht, legst du zwei Werte an, die Komodo später in jede Compose-Datei einsetzt. Das ist der Grund, warum die App-Artikel dieser Reihe eine Compose-Datei zeigen, die auf dem VPS und auf einer NAS gleichermaßen funktioniert: Die Pfade stehen nicht in der Datei, sondern hier.
- Unten links auf Settings, dann auf den Reiter Variables
- + New Variable, zweimal:
| Name | Wert |
|---|---|
DOCKER_ROOT |
/srv/docker/stacks |
DATA_ROOT |
/srv/data |
Die Option Secret bleibt bei beiden aus – es sind Pfade, keine Geheimnisse.
DATA_ROOT ist der Ort für Nutzdaten, die nicht zur Container-Ebene gehören: Dokumente, Bilder, Musik. Falls das Verzeichnis noch nicht existiert:
sudo mkdir -p /srv/data
sudo chown -R $(id -un):$(id -gn) /srv/data
So werden die Werte später benutzt. In jedem App-Stack stehen im Abschnitt Environment zwei Zeilen:
DOCKER_ROOT=[[DOCKER_ROOT]]
DATA_ROOT=[[DATA_ROOT]]
Die doppelten eckigen Klammern sind Komodos Schreibweise: Beim Ausrollen ersetzt Komodo sie durch die Werte von oben und schreibt das Ergebnis in die .env neben der Compose-Datei. Die Compose-Datei selbst nutzt danach die gewohnte Docker-Schreibweise:
volumes:
- ${DOCKER_ROOT}/beispiel/config:/config
- ${DATA_ROOT}/dokumente:/data
Warum dieser Umweg? Weil dadurch kein einziger App-Artikel mehr einen Pfad nennen muss. Ziehst du später um, änderst du die Variable an dieser einen Stelle statt in zwanzig Stacks. Und dieselbe Compose-Datei läuft unverändert auf einem Gerät mit ganz anderer Verzeichnisstruktur.




11. Workflow ab jetzt: Stacks über die UI
Ab diesem Punkt installierst du neue Docker-Stacks nicht mehr per SSH und docker compose up -d. Du legst sie über die Komodo-UI an, pflegst die compose.yaml direkt im Browser-Editor und rollst sie per Mausklick aus.
Die eine Ausnahme ist der Komodo-Stack selbst, weil Komodo sich nicht selbst ausrollen kann. Wenn du Komodos Konfiguration änderst oder Komodo aktualisierst, machst du das per SSH. Dafür ist das komodo.skip-Label gesetzt – Komodo lässt seinen eigenen Stack in Ruhe. Wie das Update läuft, steht in Abschnitt 13.
12. Test-Deployment: whoami über die Komodo-UI
Bevor im nächsten Artikel mit Caddy der erste echte Stack entsteht, einmal trocken durchspielen: ein winziger Test-Stack, der nichts weiter tut, als seinen eigenen Namen zu melden.
In der UI:
- Links auf Stacks → oben rechts + New Stack
- Name:
test-whoami - Server:
vps - Stack Type:
UI Defined - Im Bereich Compose File folgendes einfügen:
name: test-whoami
services:
whoami:
image: traefik/whoami
container_name: test-whoami
restart: unless-stopped
networks:
- homelab_intern
networks:
homelab_intern:
external: true
- Save – damit ist die Stack-Definition gespeichert, gestartet ist noch nichts
- Deploy, dann im Bestätigungsdialog Confirm
Komodo schreibt die compose.yaml auf den Server, Periphery startet den Container, und in der Übersicht erscheint test-whoami als laufend. Die Logs des Containers sind einen Klick entfernt.







Check
ls -ld /srv/docker/stacks/test-whoami
ls /srv/docker/stacks/test-whoami
Ausgabe: Ein Verzeichnis mit der compose.yaml darin. Das zeigt, dass PERIPHERY_STACK_DIR sitzt – deine Stacks landen unter /srv/docker/stacks/, nicht irgendwo im System.
Aufräumen – in zwei Schritten, und der zweite geht nur über die Übersicht:
- In der Ansicht des Stacks auf Destroy – stoppt und entfernt den Container
- Links auf Stacks zurück in die Übersicht. Dort den Stack
test-whoamiauswählen und auf Execute, dann Delete – das entfernt die Definition aus Komodo
Den zweiten Schritt suchst du in der Ansicht des Stacks vergeblich: Gelöscht wird eine Definition nur über die Auswahl in der Übersicht.
Das Verzeichnis auf dem Server bleibt dabei liegen. Komodo räumt es nicht mit weg – bei einer echten Anwendung stünden dort deine Daten. Beim Test-Stack ist nichts drin, also weg damit:
sudo rm -rf /srv/docker/stacks/test-whoami
Merk dir das für später. Eine gelöschte Anwendung hinterlässt ihr Verzeichnis. Wer über Monate ausprobiert und wieder verwirft, sammelt Ordner an, die zu nichts mehr gehören – und sichert sie beim Backup mit.
Du hast den kompletten Ablauf damit einmal gesehen: anlegen, ausrollen, kontrollieren, entfernen. Genau so entsteht ab dem nächsten Artikel jeder neue Stack.
13. Komodo im Alltag
Der Installationsteil ist durch. Ein paar Dinge lohnt sich zu kennen, bevor du sie das erste Mal brauchst.
Stack-Typen: drei Wege zum Compose-File
Komodo bietet drei Wege an, eine compose.yaml zu pflegen. Für diese Reihe gilt durchgängig der erste:
UI Defined – du tippst compose.yaml und Konfigurationswerte direkt im Komodo-Editor. Komodo schreibt die Dateien beim Ausrollen auf den Server (unter /srv/docker/stacks/<n>/). Kein SSH zum Editieren, alles an einer Stelle. Nachteil: keine echte Versionierung – Komodo hat eine begrenzte Änderungshistorie, aber keinen vollwertigen Vergleich.
Files on Host – Komodo liest eine compose.yaml, die schon auf dem Server liegt. Praktisch, wenn du einen bestehenden Stack übernehmen willst.
Git Repo – Komodo holt die compose.yaml aus einem Git-Repository. Damit bekommst du Versionierung und Rücksprünge auf ältere Stände. Das ist die Ausbaustufe für später und braucht ein paar Anpassungen an unserem Aufbau.
Compose File und Environment: zwei Bereiche pro Stack
In der Konfiguration eines Stacks liegen zwei Eingabebereiche untereinander. Oben Compose File, darunter Environment – und was du in Environment schreibst, legt Komodo beim Ausrollen als .env neben der Compose-Datei ab. Daher der Name.
Passwörter, Adressen und Versionsnummern stehen deshalb in Environment, in der Compose-Datei nur Verweise darauf. Das ist dasselbe Muster wie in Artikel 03 – nur dass du beide Dateien jetzt im Browser bearbeitest. In dieser Reihe heißt der Inhalt von Environment im Fließtext „die Konfigurationswerte".
Praktischer Nebeneffekt: Wenn du einen Stack kopierst („Copy Stack"), übernimmt Komodo die compose.yaml, aber nicht automatisch die Konfigurationswerte. So landen Secrets nicht ungewollt in mehreren Stacks.
Updates erkennen
Komodo prüft im Hintergrund regelmäßig, ob es für die Images in deinen Stacks eine neuere Version gibt – alle 5 Minuten, einstellbar über KOMODO_RESOURCE_POLL_INTERVAL. Findet es eine, erscheint in der Stack-Übersicht ein Hinweis.
Pro Stack gibt es dafür zwei Schalter:
- Poll for Updates – Komodo sieht nach und meldet, du entscheidest, wann du ausrollst
- Auto Update – Komodo zieht das neue Image und rollt den Stack selbst aus
Für jeden Stack dieser Reihe gilt: Poll for Updates an, Auto Update aus. Größere Versionssprünge können Datenbanken umbauen oder Konfigurationen ändern. Wenn das nachts von allein passiert und am Morgen läuft etwas nicht mehr, fehlt dir der Zusammenhang.
Beide Schalter stehen in derselben Konfiguration wie Compose File und Environment, und Save sichert alles zusammen.
Komodo selbst aktualisieren
Der Weg von oben gilt für alle Stacks außer einem. Komodos eigener trägt das komodo.skip-Label und bleibt von Poll for Updates ausgenommen – er wird per SSH aktualisiert, wie jede Änderung an diesem Stack:
cd /srv/docker/stacks/komodo
docker compose pull
docker compose up -d
pull holt die neuesten Abbilder zur Marke 2 aus der .env, up -d tauscht nur die Container, deren Abbild sich geändert hat. Die Volumes bleiben unberührt: Stack-Definitionen, Konten und Historie überleben das.
Check
docker compose ps
docker compose logs periphery | grep -i "logged in"
Ausgabe: Vier Container Up, und eine neue logged in-Zeile mit aktuellem Zeitstempel. Der zweite Befehl ist der wichtigere: Wird Core neu erstellt, muss Periphery ihn wiederfinden.
Die abgelösten Abbilder bleiben auf der Platte liegen. docker image prune -f entfernt die, die kein Container mehr nutzt.
Ein Sprung auf eine neue Hauptversion – von
2auf3– folgt anderen Regeln. Zwischen 1.x und 2.x wechselten das Postgres-Abbild, die Authentifizierung und die Pflichtangaben in der.env. Dafür liest man zuerst die Release Notes des Projekts und sichert die Datenbank – wie, steht im nächsten Unterabschnitt. Innerhalb von2passiert das nicht.
Komodos eigene Sicherung
Komodo legt bei einer neuen Installation von selbst eine Prozedur namens Backup Core Database an. Sie läuft jede Nacht um 01:00 und schreibt einen Ordner mit Datum in das Verzeichnis, das du in Abschnitt 6 bei core als /backups eingehängt hast – darin je eine gepackte Datei für Stacks, Server, Variablen, Empfänger, Konten und den Rest von Komodos Konfiguration.
Zu finden ist sie links unter Procedures. Dort startest du sie auch von Hand, etwa vor einem Sprung auf eine neue Hauptversion.
Check – am Tag nach der Einrichtung:
ls /srv/docker/stacks/komodo/backups
Ausgabe: ein Ordner mit Datum und Uhrzeit im Namen.
Gesichert ist damit Komodos eigene Datenbank, nicht die Daten deiner Anwendungen – die liegen in deren Verzeichnissen. Weil das Sicherungsverzeichnis unter /srv/docker/stacks liegt, nimmt der Backup-Artikel in Phase 4 es ohne weiteren Handgriff mit nach draußen.
Meldungen
Unter Alerters in den Settings lässt sich einstellen, dass Komodo aktiv meldet: Container ausgefallen, Server nicht erreichbar, Speicher knapp, Update verfügbar.
Als Empfänger kommt keine Mailadresse in Frage. Komodo verschickt keine Mail – ein SMTP-Versand ist nicht vorgesehen, auch nicht über den Mail-Weiterleiter aus Artikel 08. Es meldet an Push- und Chatdienste: Slack, Discord, Pushover und ntfy sind eingebaut, alles andere braucht einen Zwischenbaustein.
Deshalb bleibt dieser Punkt vorerst offen. In Artikel 10 – 10. ntfy: Meldungen von VPS und NAS direkt aufs Handy – richtest du einen eigenen Meldedienst ein und trägst ihn hier als Empfänger nach. Für jetzt reicht zu wissen, wo die Einstellung sitzt.
Zwei-Faktor-Anmeldung
Komodo kann die Anmeldung mit einer Zwei-Faktor-Anmeldung (2FA) absichern, in zwei Varianten – über einen Passkey oder über eine Authenticator-App mit Zahlencode. Du findest beides oben rechts im Profil unter Account.
Der Passkey funktioniert hier nicht, und das liegt nicht an Komodo: Browser geben die dafür nötige Schnittstelle nur auf Seiten mit gültigem HTTPS frei. Komodo rufst du über http:// auf, also meldet die Oberfläche, es sei kein Anbieter verfügbar. Das ist erwartet.
Die Authenticator-App funktioniert, weil der Zahlencode auf dem Server geprüft wird. Nimm dieselbe App wie in Artikel 05.
Pflicht ist 2FA hier nicht – wer die Oberfläche erreichen will, muss ohnehin erst im Tailscale-Netz sein. Aber es kostet zwei Minuten.
Was Komodo nicht ist
Komodo verwaltet Container. Es ist kein Reverse Proxy, kein Backup-Werkzeug für deine Anwendungen und keine Benutzerverwaltung. Adressen und Zertifikate macht Caddy im nächsten Artikel, die vorgeschaltete Anmeldung Authelia in Artikel 09, Sicherungen kommen in Phase 4.
Wenn es nicht klappt
| Was du siehst | Ursache | Weiter |
|---|---|---|
komodo-core hängt auf Restarting, im Protokoll password must be URL encoded |
Datenbank-Passwort mit Sonderzeichen erzeugt | → Abschnitt 7, Kasten |
komodo-core steigt mit Exited (128) aus |
In der .env ist ein Platzhalter stehen geblieben, am 18.10.2026 bei KOMODO_HOST |
grep -n "<" → Abschnitt 5 |
Failed to connect to websocket … Connection refused direkt nach dem Start |
Harmlos – Periphery ist schneller oben als Core | → Abschnitt 7 |
Die Seite unter http://vps:9120 lädt nicht |
Tailscale aus, Core gestoppt oder falsche Tailscale-Adresse in der .env |
→ Abschnitt 8, drei Prüfungen |
| Nach Sign Up steht nur „Komodo Log in" ohne Felder | Zwischenspeicher des Browsers | Strg + Shift + R → Abschnitt 8 |
| Der Server steht auf „is not connected" | Name in der Oberfläche passt nicht zu PERIPHERY_CONNECT_AS |
→ Abschnitt 9, Kasten |
In einer .env steht [[DOCKER_ROOT]] wörtlich |
Variable fehlt oder ist vertippt – Komodo setzt unbekannte Namen nicht ein | Schreibweise unter Settings → Variables prüfen → Abschnitt 10 |
Und jetzt?
Du verwaltest Docker ab hier im Browser, erreichbar nur über dein VPN. SSH brauchst du künftig fast nur noch für Änderungen an Komodo selbst, gelegentliche Fehlersuche und die Dateien, die außerhalb von Komodo gepflegt werden.
Eine davon kommt sofort. Noch ist keiner deiner Dienste öffentlich erreichbar, und Komodo bleibt das auch. Für die Anwendungen, die öffentlich sein sollen, richtest du im nächsten Artikel Caddy ein: den einen Eingang von außen, mit automatischem HTTPS. Dort lernst du auch VS Codium kennen, das sich über SSH mit dem Server verbindet – dann ist nano Vergangenheit.
👉 Nächster Artikel: 07. Caddy auf dem VPS: ein Eingang, HTTPS für jede Anwendung
Discussion