Diese Serie lehrt dich, wie du von klassischem Hosting zu einer fortschrittlichen Architektur wechselst, und erklärt Schritt für Schritt, wie du deinen eigenen Docker Swarm Cluster implementierst, um eine vollständig skalierbare WordPress-Website zu betreiben.

🔹Episode 0: Aufstieg zum Enterprise-Level und Projektarchitektur

„Wir haben zusammen einen Panzer gebaut (Proxmox HA). Jetzt bauen wir statt eines klassischen Motors ein Raketentriebwerk ein: Docker Swarm.“

Willkommen zu einem neuen Kapitel unserer Reise. Wir lassen klassische Control Panels hinter uns und bauen unsere eigene Container-Infrastruktur.

Was wir aus der Serie „Von Null zur vollständigen Website“ beibehalten (Das obligatorische Fundament):

Damit dieses neue Projekt funktioniert, stützen wir uns auf die solide Infrastruktur, die wir in der vorangegangenen Serie aufgebaut haben ( https://tech.renuka.ro/de/pt-portfolio/von-null-zum-fertigen-website/ ). Wenn du diese Schritte noch nicht durchlaufen hast, empfehle ich dir, die folgenden Kapitel zu wiederholen:

  • Episode 0: Das Fundament. Proxmox Cluster und High Availability (HA)
  • Episode 1: Auswahl und Kauf einer günstigen Domain – Namecheap –
  • Episode 2: Konfiguration der Domain in Cloudflare + Kostenloses SSL
  • Episode 3: Unsichtbare Architektur. Cloudflare Tunnel und ZFS Replication

Struktur des neuen Projekts (Die 6 unzerstörbaren Episoden):

In diesem Projekt bauen wir Schritt für Schritt eine Enterprise-Architektur auf, die logisch auf die folgenden Episoden verteilt ist:

  • Episode 0: Die Software-Basis. Installation von Docker Swarm (Das Betriebssystem des Clusters).
  • Episode 1: Die Kommandozentrale. Installation von Portainer (Visuelles Management des Clusters).
  • Episode 2: Verbindung zum Internet. Rekonfiguration von Cloudflare Tunnel (Zugang und direktes Routing).
  • Episode 3: Die Website an sich. Start von WordPress (Der Motor) und MariaDB (Der Tresor).
  • Episode 4: Wartungswerkzeuge. Hinzufügen von FileBrowser und phpMyAdmin (Die Intervention).
  • Episode 5: Monitoring und Überleben. Grafana (Gesundheit) und Duplicati (Externes Backup).

🔹Präambel: Die Software-Basis. Installation der Docker Engine und Initialisierung des Swarms

Unsere Anwendungen benötigen einen stabilen „Boden“, auf dem sie aufgebaut werden können. Dieser Boden ist die Docker Engine, die wir auf zwei strategischen Knoten installieren werden: deinem physischen Ubuntu-Rechner (Manager – .111) und der virtuellen Maschine in Proxmox (Worker – .112), die von der ZFS Replication zwischen pve1 und pve2 für maximale Verfügbarkeit profitiert.

⚠️ ENTSCHEIDENDER HINWEIS: Sauberkeit der Umgebung. Installiere Docker nicht über das alte Projekt (CyberPanel), um Konflikte zu vermeiden. Wir verwenden eine komplett frische Umgebung.

a. Erstellung und Vorbereitung des „Zuhauses“ für Docker

In Proxmox haben wir die VM mit der ID 201 erstellt, benannt docker-worker-01 (Ubuntu Server, 4GB RAM, 2 CPU-Kerne).

Die goldene Regel (ZFS Replication): Sofort nach der Erstellung haben wir die Replikation auf jede Minute zum sekundären Knoten eingestellt. Um die Vorbereitung des Betriebssystems abzuschließen, führen wir die folgenden Befehle auf dem neuen Server aus:

# Systemaktualisierung und Installation des Proxmox-Kommunikationsagenten
sudo apt update && sudo apt upgrade -y
sudo apt install qemu-guest-agent -y
sudo systemctl enable --now qemu-guest-agent

# Synchronisation der Zeitzone (Bukarest)
sudo timedatectl set-timezone Europe/Bucharest

b. Installation der Docker Engine

Sobald die Systeme bereit sind, fahren wir mit der Installation der Docker Engine fort. Dieser Vorgang wird sowohl auf dem Manager-Laptop (.111) als auch auf der neuen Worker-VM (.112) durchgeführt:

# Herunterladen und Ausführen des offiziellen Docker-Skripts
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Anwenden der Berechtigungen für den aktuellen Benutzer
sudo usermod -aG docker $USER
newgrp docker

c. Erstellung des Clusters (Die große Docker Swarm Vereinigung)

Wir verwandeln die beiden Einheiten in einen einzigen Organismus. Der erste Schritt erfolgt auf dem Manager (.111):

# Initialisierung des Swarm-Clusters
docker swarm init --advertise-addr 192.168.1.111

Kopiere den vom Manager generierten Befehl docker swarm join --token... und führe ihn in der Konsole des Servers docker-worker-01 (.112) aus.

d. Überprüfung des Clusters

Kehre zum Laptop (Manager) zurück und überprüfe, ob der „Arbeiter“ erfolgreich beigetreten ist:

docker node ls

Wenn beide Knoten mit dem Status Ready erscheinen, herzlichen Glückwunsch! Du hast einen funktionsfähigen Docker Swarm Cluster.



🔹Zwischenepisode (0.5): Bereinigung und Namensvereinheitlichung

Bevor wir zur Konfiguration des externen Zugriffs übergehen, machen wir eine kurze Pause, um sicherzustellen, dass unsere Infrastruktur Enterprise-Standards entspricht. In den vorherigen Schritten haben wir das System unter einem generischen Benutzer (renuka) installiert, aber in einem professionellen Cluster möchten wir, dass die Identität jeder Maschine ihre Rolle widerspiegelt.

Warum machen wir diese Änderung?

  • Klarheit: Es ist viel einfacher, einen Knoten als worker-01 zu identifizieren, als nach dem Namen desjenigen, der ihn installiert hat.
  • Skalierbarkeit: Wir bereiten das Feld für die Momente vor, in denen wir worker-02, worker-03, etc. hinzufügen werden.

Befehle zur Vereinheitlichung (Ausgeführt auf dem Worker – .112)

Wir ändern den Hostnamen des Servers, um ihn an den Namen in Proxmox anzupassen. Führe diese Befehle im Terminal des sekundären Knotens aus:

# 1. Wir ändern den Namen der Maschine im System
sudo hostnamectl set-hostname docker-worker-01

# 2. Wir aktualisieren die interne Netzwerkdatei (ersetzen den alten Namen "renuka" durch den neuen)
sudo sed -i 's/renuka/docker-worker-01/g' /etc/hosts

# 3. Wir wenden die Änderung an (erfordert ein Logout/Login oder Neustart)
sudo reboot

Was hat sich geändert? Nach dem Neustart lautet dein Prompt nicht mehr renuka@renuka, sondern renuka@docker-worker-01. Der Docker Swarm Cluster übernimmt den neuen Namen automatisch in die Liste und bietet dir eine klare Sicht auf deine Ressourcen.

Fertig! Jetzt haben wir ein sauberes Fundament und sind bereit, in Episode 2 die Tore zum Internet zu öffnen.


🔹Episode 1: Die Kommandozentrale. Installation von Portainer

Unser Docker Swarm Cluster ist jetzt lebendig, aber momentan „blind“. Um Ressourcen effizient zu verwalten, ohne endlose Befehle in das Terminal einzutippen, benötigen wir einen zentralen Kontrollpunkt:

  • Portainer (Die Kommandozentrale): Die grafische Oberfläche, über die wir Container, Volumes und Netzwerke auf allen Knoten gleichzeitig verwalten.

a. Bau der „Autobahn“: Das Overlay Network

Vor den Anwendungen erstellen wir ein Overlay-Netzwerk. Dieses ermöglicht es Containern auf verschiedenen Servern (Laptop und Proxmox), sicher zu kommunizieren, als wären sie im selben Switch. Ausführen auf dem Manager (.111):

# Wir erstellen das primäre öffentliche Netzwerk des Clusters
docker network create --driver=overlay swarm-public

b. Installation des Portainer Stacks

In Swarm installieren wir Portainer als Stack. Dies startet automatisch einen „Agent“ auf jedem verfügbaren Knoten, um technische Daten zu sammeln. Wir führen auf dem Manager aus:

# Wir laden die offizielle Portainer-Konfiguration für Swarm herunter
curl -L https://downloads.portainer.io/ce2-19/portainer-agent-stack.yml -o portainer-agent-stack.yml

# Wir starten den Stack im Cluster
docker stack deploy -c portainer-agent-stack.yml portainer

⚠️ Sicherheit: Du hast 5 Minuten Zeit, um den Admin-Benutzer unter der Adresse https://192.168.1.111:9443 zu konfigurieren. Wenn die Zeit abläuft, setze den Dienst zurück mit: docker service update --force portainer_portainer.

c. Fertigstellung der Oberfläche und Bereinigung der Umgebungen

Nach dem Login, wenn du eine Umgebung namens “primary” mit einem Fehler bemerkst, empfiehlt es sich, diese unter Settings -> Environments zu löschen. Die funktionierende Umgebung ist diejenige, die durch die Verbindung zu den Agenten erstellt wurde und dir die gesamte Leistung deines Clusters unter einem einzigen Namen zeigt: Swarm-Cluster.

Der Cluster ist nun vollständig sichtbar! Du bist bereit, Anwendungen mit einem einfachen Klick zu starten.


🔹Under the Hood: The Docker Swarm DNS Magic

Beim ersten Start wird Portainer dich fragen, wie du dich mit der Docker-Umgebung verbinden möchtest. Bei einem Swarm-Cluster liegt das Geheimnis in der Nutzung des internen Docker-DNS.

Folge im Bildschirm “Environment Wizard” diesen kritischen Schritten:

  • Wähle den Umgebungstyp: Docker Swarm.
  • Wähle die Verbindungsmethode: Agent.
  • Gib im Feld Environment address die Adresse ein: tasks.agent:9001

Warum verwenden wir “tasks.agent” anstelle einer IP?

  • Service Discovery: In Docker Swarm ist tasks.service_name ein spezieller DNS-Eintrag, der die IPs aller Container in diesem Dienst zurückgibt.
  • Automatische Skalierbarkeit: Wenn du in Zukunft neue Knoten hinzufügst, weist Swarm ihnen automatisch eine interne IP zu und registriert sie unter diesem Namen. Portainer „sieht“ die neuen Server sofort, ohne dass du jemals die Konfiguration ändern musst.
  • Resilienz: Wenn ein Knoten ausfällt, entfernt der interne DNS diese IP aus der Liste, und Portainer kommuniziert ohne Unterbrechung mit dem Rest des Clusters weiter.

 


🔹Episode 2: Verbindung zum Internet. Neukonfiguration des Cloudflare-Tunnels

In diesem Kapitel verwandeln wir unseren Cluster von einem isolierten Labor in eine weltweit sichtbare Infrastruktur. Wir werden den Cloudflare-Tunnel nutzen, um den Datenverkehr sicher zu unseren Diensten zu leiten, ohne Ports am Router öffnen zu müssen.

Warum installieren wir den Tunnel auf dem Proxmox-Worker?

Obwohl wir zwei Knoten haben, haben wir uns entschieden, den cloudflared-Container auf der virtuellen Maschine in Proxmox (Worker – .112) auszuführen. Der Grund ist einfach: Überlebensfähigkeit. Dank der ZFS-Replikation und des High Availability (HA)-Systems in Proxmox wird die virtuelle Maschine bei einem Hardwarefehler des Hauptservers automatisch auf den Sekundärknoten verschoben und neu gestartet. So wird die Internetverbindung ohne manuelles Eingreifen wiederhergestellt.


a. Vorbereitung in Cloudflare Zero Trust

  1. Rufen Sie das Cloudflare Zero Trust Dashboard auf -> Networks -> Tunnels.
  2. Erstellen Sie einen neuen Tunnel mit dem Namen swarm-enterprise-tunnel.
  3. Wählen Sie die Installationsmethode Docker und kopieren Sie nur das Token (die lange Zeichenfolge nach --token).

b. Starten des Tunnels im Swarm (Ausgeführt auf dem Manager – .111)

Wir werden keinen einfachen Container ausführen, sondern einen Docker Service. Dieser wird an das swarm-public-Netzwerk angeschlossen und fungiert als “Eingangstür” für alle zukünftigen Anwendungen. Ersetzen Sie [IHR_TOKEN] durch das zuvor kopierte:

# Erstellen des Cloudflare-Tunnel-Dienstes im Cluster
docker service create \
  --name cloudflare-tunnel \
  --network swarm-public \
  --constraint 'node.role == worker' \
  --env TUNNEL_TOKEN=[IHR_TOKEN] \
  cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run

c. Routing der Dienste (Die “Port 9000”-Strategie)

Sobald der Tunnel in Cloudflare den Status HEALTHY anzeigt, können wir unsere Subdomains direkt den Containern im Netzwerk zuordnen. Da wir eine vereinfachte Benutzeroberfläche verwenden (in der erweiterte TLS-Einstellungen nicht sichtbar sind), nutzen wir die stabilste Methode:

  • Public Hostname: admin.renuka.site
  • Service Type: HTTP
  • URL: portainer_portainer:9000

💡 Enterprise-Hinweis & Fehlerbehebung: In der Videodemonstration haben wir die lokale IP (192.168.1.111:9000) für eine schnelle und universelle Verbindung genutzt. Für eine Enterprise-Architektur verwenden wir jedoch den Dienstnamen. Beachten Sie zwei kritische Details, damit dies funktioniert:

  1. Stack-Benennung: In Docker Swarm erhalten Dienste automatisch den Namen des Stacks als Präfix. Daher ist die korrekte Adresse portainer_portainer und nicht nur portainer.
  2. Gemeinsames Netzwerk: Damit der Tunnel Portainer “sehen” kann, müssen Sie den Dienst portainer_portainer manuell zum Netzwerk swarm-public in der Portainer-Oberfläche hinzufügen (Services -> portainer_portainer -> Network -> Add to swarm-public).


Resilienz-Prüfung: Ausfallszenarien und Sicherheitsnetze

Unsere Enterprise-Architektur ist so konzipiert, dass sie überlebt, wenn das Unvermeidliche eintritt. In einer realen Umgebung kann unser Worker (.112) aus verschiedenen Gründen offline gehen, was unterschiedliche Schutzschichten auslöst:

  • 1. Hardwarefehler (Der “Panzer” fällt aus): Der physische Hauptserver (pve1) verliert den Strom oder hat einen Defekt. Hier zahlt sich die Arbeit aus der Serie: “Von Null zur kompletten Website” ( Episode 0: Das Fundament. Proxmox-Cluster und High Availability (HA) ) aus: Proxmox greift ein, verschiebt die VM mittels ZFS-Replikation auf den Backup-Knoten (pve2) und stellt die Verbindung in etwa einer Minute wieder her.
  • 2. Fehler auf Betriebssystemebene: Der VM geht der RAM aus (Out of Memory), der Speicher ist voll oder Ubuntu erleidet einen kritischen Absturz (Kernel Panic).
  • 3. Netzwerk- oder Dienstfehler: Ein Netzwerkkabel wird versehentlich getrennt, eine Firewall blockiert plötzlich die Kommunikation oder der Docker Engine Dienst stoppt.

In den Fällen 2 und 3 oder während des Hardware-Transfers bei Punkt 1 greift der Software-Scheduler des Clusters (Manager .111) ein. Da wir die Regel --constraint 'node.role == worker' festgelegt haben, weiß der Manager, dass er die Last nicht selbst übernehmen darf. Während der Worker offline ist, zerstört Swarm die Dienste nicht, sondern verschiebt sie in eine Warteschlange (Pending). Sobald der Worker wieder online meldet, injiziert der Manager die Dienste sofort wieder auf ihn.

Um genau zu verstehen, wie das “Gehirn” des Clusters denkt und Zuweisungsentscheidungen trifft, haben wir den untenstehenden interaktiven Simulator gebaut. Schalten Sie den Worker aus, um einen Ausfall zu simulieren, und starten Sie Dienste, um die Warteschlange zu sehen:

Konfigurationsleitfaden: Der Enterprise-Pfad im Simulator

Um zu verstehen, wie das Sicherheitsnetz funktioniert, folgen Sie diesen Schritten im Simulator:

Schritt 1: Einschränkung festlegen
Wählen Sie im Dropdown-Menü: 🟢 Nur Worker (node.role==worker). Dies ist die entscheidende Einstellung, die dem Manager sagt, dass die WordPress-Seite ihre Daten vom ZFS-Laufwerk des Workers benötigt.

Schritt 2: Hardware-Ausfall simulieren
Schalten Sie den Worker auf AUS. Dies simuliert den Absturz des PVE1-Servers. Alle aktiven Tasks verschwinden vom Worker.

Schritt 3: Neuen Task starten
Klicken Sie auf ▶ Task starten. Der Task landet direkt in der Warteschlange (Pending), da der Manager weiß, dass er ihn nicht auf sich selbst ausführen darf.

Schritt 4: Wiederherstellung
Schalten Sie den Worker auf AN. Sobald Proxmox die VM auf PVE2 gestartet hat, “springt” der Task aus der Warteschlange sofort auf den Worker. Die Seite ist wieder online!

Warum ist dies der richtige Pfad? Obwohl wir Swarm erlauben könnten, den Task auf den Manager zu verschieben, würde die Seite fehlschlagen, da der Manager keinen Zugriff auf die replizierten ZFS-Daten hat. So zwingen wir die Software (Docker), auf die Hardware (Proxmox) zu warten.

Das ist das Geheimnis einer Enterprise-Architektur: Intelligente Geduld des Systems im Angesicht der Katastrophe.


🔹Episode 2.5 (Intermezzo): Die Cluster-Matrix. Live-Visualisierung mit Swarm Visualizer

„Bisher haben wir im Dunkeln gearbeitet und Befehle in einen schwarzen Bildschirm getippt. Es ist an der Zeit, das Licht einzuschalten und zu sehen, wie das ‘Gehirn’ und die ‘Muskeln’ unserer Infrastruktur wirklich aussehen.“

Docker Swarm ist eine abstrakte Entität. Wir wissen, dass es existiert, wir wissen, dass es Container von einem Knoten zum anderen verschiebt, aber ohne die richtigen Tools ist es schwer zu visualisieren. In diesem kurzen Intermezzo installieren wir ein Dienstprogramm, das Codezeilen in Live-Grafiken verwandelt.

Warum brauchen wir den Swarm Visualizer?

Während Portainer (Episode 1) uns die volle Kontrolle gibt, bietet der Swarm Visualizer eine räumliche Perspektive. Es ist das perfekte Werkzeug, um Folgendes zu verstehen:

  • Aufgabenverteilung (Task Distribution): Sehen Sie genau, auf welchem physischen Knoten jeder Container „gelandet“ ist.
  • Gesundheitszustand: Wenn ein Knoten ausfällt, sehen Sie in Echtzeit, wie die Container von ihm verschwinden und automatisch auf den verbleibenden aktiven Knoten neu erstellt werden.
  • Orchestrierungs-Simulation: Es ist die beste didaktische Methode, um zu sehen, wie der Container-„Schwarm“ operiert.

Installation des Visualizers (Aktivierungsbefehl)

Diese Anwendung muss zwingend auf dem Manager-Knoten (.111) laufen, da sie direkten Zugriff auf die Docker-Kommunikationsdatei (docker.sock) benötigt, um den Cluster-Status „auszulesen“. Führen Sie den folgenden Befehl im Terminal aus:

# Erstellen des Visualisierungsdienstes auf Port 8080
docker service create \
  --name=swarm-visualizer \
  --publish=8080:8080/tcp \
  --constraint=node.role==manager \
  --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
  dockersamples/visualizer

Wie greifen wir auf das „Dashboard“ zu?

Sobald der Dienst erstellt wurde, ist keine weitere Konfiguration in Cloudflare erforderlich (da es sich um ein internes Diagnose-Tool handelt). Öffnen Sie einfach einen Browser in Ihrem lokalen Netzwerk und rufen Sie auf:

http://192.168.1.111:8080

Was werden Sie sehen? Sie sehen eine Spalte für jeden aktiven Knoten. Innerhalb der Spalten finden Sie Ihre aktuellen Container: portainer, cloudflare-tunnel und natürlich den neuen swarm-visualizer.

Enterprise-Tipp: Sobald Sie den Worker-Knoten (.112) in den folgenden Episoden starten, werden Sie sehen, wie der Visualizer automatisch eine neue Spalte hinzufügt und wie die Aufgaben zwischen den beiden Maschinen ausbalanciert werden.


🔹Episode 3: Die Anwendungsebene. WordPress und MariaDB bereitstellen

In diesem Kapitel installieren wir das „Herzstück“ unseres Clusters. Wir starten nicht einfach nur Container, sondern ein vollständiges Enterprise-Stack. Diese Architektur stellt sicher, dass die Datenbank vollständig vom Internet isoliert ist, während die Website-Dateien durch die in Proxmox konfigurierte ZFS-Replikation geschützt sind.

1. Speichervorbereitung auf dem Worker (.112)

Damit bei einer automatischen Verschiebung des Workers zwischen den Proxmox-Nodes keine Daten verloren gehen, mappen wir die Volumes an einem replizierten Ort. Führen Sie die folgenden Befehle auf dem Worker-Node aus:

# Erstellen der Ordnerstruktur auf dem replizierten Speicher
sudo mkdir -p /mnt/data/wordpress/html
sudo mkdir -p /mnt/data/wordpress/db
sudo chmod -R 777 /mnt/data/wordpress/

2. Stack-Launch in Portainer

Gehen Sie in Portainer zu Stacks -> Add Stack und definieren Sie die gesamte Infrastruktur der Website. Wir nutzen den internen Docker-DNS, damit WordPress mit der Datenbank kommunizieren kann, ohne Ports nach außen zu öffnen:

version: '3.8'

services:
  db:
    image: mariadb:latest
    restart: always
    volumes:
      - /mnt/data/wordpress/db:/var/lib/mysql
    environment:
      MARIADB_ROOT_PASSWORD: DeinGeheimesRootPasswort
      MARIADB_DATABASE: wordpress
      MARIADB_USER: wp_user
      MARIADB_PASSWORD: DeinWPUserPasswort
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

  wordpress:
    image: wordpress:latest
    depends_on:
      - db
    volumes:
      - /mnt/data/wordpress/html:/var/www/html
    environment:
      WORDPRESS_DB_HOST: wordpress_db
      WORDPRESS_DB_USER: wp_user
      WORDPRESS_DB_PASSWORD: DeinWPUserPasswort
      WORDPRESS_DB_NAME: wordpress
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

networks:
  swarm-public:
    external: true

3. Konfiguration des externen Zugriffs (Cloudflare Tunnel)

Nun kommt der spannendste Teil: Die Verbindung von WordPress mit dem Internet. Im Cloudflare Zero Trust Panel fügen wir die neue Route hinzu:

  • Public Hostname: www.renuka.site
  • Service Type: HTTP
  • URL: wordpress_wordpress:80 (Regel: Stackname_Servicename)
🚀 Abschied von manuellen DNS-Einträgen!
Ein großer Vorteil dieser Methode ist, dass Sie keine A- oder CNAME-Records mehr im klassischen Cloudflare DNS-Panel hinzufügen müssen. Sobald Sie die Einstellungen im Tunnel speichern, erstellt Cloudflare automatisch die erforderliche DNS-Route. Das ist viel sicherer, da Ihre Heim-IP vollständig verborgen bleibt.

Warum ist dies eine Enterprise-Lösung?

Diese Konfiguration macht aus einer einfachen WordPress-Seite eine Festung:

  • „Unsichtbare“ Datenbank: MariaDB hat keine offenen Ports und ist nicht im Tunnel konfiguriert. Nur WordPress kann über das interne Netzwerk mit ihr kommunizieren.
  • Automatisches Überleben: Wenn der Worker ausfällt, verschiebt Proxmox ihn auf PVE2. Der Tunnel verbindet sich neu, WordPress findet die Datenbank unter demselben Hostnamen (wordpress_db) und die Dateien sind dank ZFS-Replikation vorhanden.
  • Effizienz: Der gesamte Datenverkehr wird über den Tunnel verschlüsselt, ohne dass SSL-Zertifikate manuell auf dem Server verwaltet werden müssen.
🚀 Performance-Hinweis: Turbo-Cache aktivieren (Redis)
Da wir von LiteSpeed auf eine Docker-Architektur umgestiegen sind, benötigen wir eine Caching-Engine, die direkt im RAM arbeitet. Um diesen „Turbo“ zu aktivieren, fügen Sie die folgenden Zeilen in die obige YAML-Datei ein, direkt unter dem wordpress-Dienst (jedoch vor dem Abschnitt networks):
  redis:
    image: redis:latest
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

Nachdem Sie den Stack aktualisiert haben, installieren Sie in WordPress das Plugin „Redis Object Cache“ und aktivieren Sie es. Dies wird die Datenbanklast drastisch reduzieren und eine Geschwindigkeit bieten, die weit über der liegt, die Sie von klassischen Control Panels gewohnt waren.


🔹Episode 4: Wartungstools. FileBrowser und phpMyAdmin

Sobald WordPress online und funktionsfähig ist, benötigen wir eine „zivilisierte“ Methode, um unter die Haube einzugreifen. In einer Enterprise-Architektur möchten wir uns nicht jedes Mal über das Terminal (SSH) anmelden, wenn wir ein Theme, eine .htaccess-Datei oder einen Datenbankwert ändern müssen.

Daher installieren wir zwei essenzielle Tools, die als „Service-Türen“ zu unserer Infrastruktur fungieren: FileBrowser (der Web-Dateimanager) und phpMyAdmin (die Schnittstelle für MariaDB).

1. Vorbereitung des Speichers auf dem Worker (.112)

Genau wie die Hauptseite benötigen diese Tools physischen Speicherplatz, um ihre eigenen Einstellungen und internen Datenbanken zu speichern. Um diese Daten bei einem möglichen Neustart nicht zu verlieren, erstellen wir dedizierte Ordner auf dem replizierten ZFS-Speicher. Ein kritisches Detail hierbei ist die manuelle Erstellung der Datenbankdatei für den FileBrowser vor dem Start.

Wir verbinden uns mit dem Worker-Node (.112) und führen Folgendes aus:

# Erstellen der Hauptkonfigurationsordner für die Wartung
sudo mkdir -p /mnt/data/maintenance/filebrowser
sudo mkdir -p /mnt/data/maintenance/pma

# Erstellen der leeren Datenbankdatei für FileBrowser (Kritischer Schritt!)
sudo touch /mnt/data/maintenance/filebrowser/filebrowser.db

# Zuweisen der 777-Berechtigungen, damit Docker Daten schreiben kann
sudo chmod -R 777 /mnt/data/maintenance/

2. Starten des Maintenance-Stacks

Eine Grundregel im DevOps-Bereich ist die Isolierung. Wir werden diese Tools nicht der Hauptanwendung (WordPress) hinzufügen. Stattdessen erstellen wir in Portainer einen neuen Stack namens maintenance. Warum? Wenn wir in Zukunft Ressourcen (RAM) freigeben möchten, können wir diesen Stack komplett stoppen, ohne dass die öffentliche Seite auch nur eine Sekunde lang beeinträchtigt wird.

Wir navigieren in Portainer zu Stacks -> Add Stack und fügen folgenden Code ein:

version: '3.8'

services:
  filebrowser:
    image: filebrowser/filebrowser:latest
    user: 0:0 # Ausführung mit Root-Rechten, um von WordPress erstellte Dateien bearbeiten zu können
    volumes:
      - /mnt/data/wordpress/html:/srv
      - /mnt/data/maintenance/filebrowser/filebrowser.db:/database.db
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

  phpmyadmin:
    image: phpmyadmin:latest
    environment:
      - PMA_HOST=wordpress_db # Essenziell: So rufen wir die Datenbank aus dem anderen Stack auf!
      - PMA_PORT=3306
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

networks:
  swarm-public:
    external: true

3. Konfiguration im Cloudflare Tunnel

Zu diesem Zeitpunkt laufen unsere Container, sind jedoch im internen Netzwerk isoliert. Um über unseren Browser darauf zugreifen zu können, nutzen wir den bestehenden Tunnel, den wir in den vergangenen Episoden erstellt haben.

Wir gehen zum Cloudflare Zero Trust -> Tunnels Dashboard, konfigurieren unseren Tunnel und fügen zwei neue Routen (Public Hostnames) hinzu:

      • Dateimanager: files.renuka.site ➡️ weitergeleitet an http://maintenance_filebrowser:80
      • Datenbank: db.renuka.site ➡️ weitergeleitet an http://maintenance_phpmyadmin:80

Sie müssen nichts manuell im DNS hinzufügen! Cloudflare erstellt die Routen automatisch und hält Ihre Heim-IP weiterhin komplett verborgen.

4. Authentifizierungs-Guide: Mit welchen Daten loggen wir uns ein?

Hier zeigt sich die Schönheit vernetzter Systeme. Wenn Sie versuchen, die neuen Adressen aufzurufen, werden Sie von Login-Bildschirmen begrüßt.

A. Im FileBrowser (files.renuka.site):

      • Versuchen Sie, sich mit den Standarddaten anzumelden: admin als Benutzer und admin als Passwort.
      • Ändern Sie das Passwort sofort über die Benutzeroberfläche! Sobald Sie eingeloggt sind, haben Sie visuellen Zugriff auf den gesamten WordPress-Ordner html.
🛠️ Troubleshooting: Was tun, wenn Sie “Wrong Credentials” erhalten?
Aus Sicherheitsgründen deaktivieren einige neuere Versionen von FileBrowser das Passwort “admin” und generieren beim ersten Start ein zufälliges. Wenn Sie sich nicht anmelden können, gehen Sie in Portainer zum Bereich Containers, klicken Sie auf das Logs-Symbol (das Blatt Papier) neben dem Container maintenance_filebrowser. Dort finden Sie das vom System generierte eindeutige Passwort. Verwenden Sie dieses für die erste Anmeldung!

B. In phpMyAdmin (db.renuka.site):

      • Hier benötigen Sie KEIN neu erstelltes Konto! phpMyAdmin verwendet die Identität der Datenbank.
      • Sie loggen sich mit den Daten ein, die Sie in der YAML-Datei aus Episode 3 definiert haben:
        • Für vollen Zugriff: Benutzer root + Passwort von MARIADB_ROOT_PASSWORD.
        • Für eingeschränkten Zugriff: Benutzer wp_user + Passwort von MARIADB_PASSWORD.
👁️ Enterprise-Tipp: Live-Visualisierung
Sobald Sie in Portainer auf den Button „Deploy“ klicken, öffnen Sie den Tab mit dem Swarm Visualizer (die Anwendung, die wir in Episode 2.5 installiert haben). Sie sehen in Echtzeit, wie das „Gehirn“ von Docker Swarm die neuen Container genau auf den Worker-Node (.112) sendet, direkt neben WordPress. Dies ist die absolute visuelle Bestätigung, dass beide Anwendungen physischen Zugriff auf dieselben ZFS-Festplatten haben.

Obwohl diese „Türen“ nun nur einen Klick entfernt sind, bleibt der Standort Ihres physischen Servers im Internet ein Rätsel, und der Eintritt ist an solide Schlüssel gebunden.

Stay Free! Stay Hidden!


🔹Episode 5: Monitoring und Überleben. Grafana (Systemzustand) und Duplicati (Externes Backup)

Eine unsichtbare Infrastruktur ist nutzlos, wenn sie fragil ist. In diesem letzten Kapitel schließen wir den Sicherheitskreis. Wir werden ein visuelles Überwachungssystem implementieren, um den „Puls“ des Clusters in Echtzeit zu verfolgen, und vor allem ein automatisiertes Backup-System, um unsere wertvollen Daten außerhalb des physischen Servers (Offsite) zu sichern.

1. Vorbereitung von Speicher und Überwachungsregeln

Wir verbinden uns mit dem Worker-Node (.112) und erstellen die Basisverzeichnisse auf dem replizierten ZFS-Speicher:

# Erstellen der Verzeichnisse für Überwachung und Backup
sudo mkdir -p /mnt/data/monitoring/grafana
sudo mkdir -p /mnt/data/monitoring/prometheus
sudo mkdir -p /mnt/data/backups/duplicati/config

# Manuelles Erstellen der Prometheus-Konfigurationsdatei
sudo nano /mnt/data/monitoring/prometheus/prometheus.yml

Fügen Sie im nano-Editor diese grundlegenden Regeln hinzu:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

Speichern Sie (STRG+X, Y, Enter) und weisen Sie globale Host-Berechtigungen zu, damit Docker die Daten nahtlos schreiben kann:

sudo chmod -R 777 /mnt/data/monitoring/
sudo chmod -R 777 /mnt/data/backups/

2. Starten des Monitoring-Stacks (Grafana & Prometheus)

In Portainer gehen wir zu Stacks -> Add Stack und erstellen einen neuen Stack namens monitoring:

version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    volumes:
      - /mnt/data/monitoring/prometheus:/prometheus
      - /mnt/data/monitoring/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

  grafana:
    image: grafana/grafana:latest
    volumes:
      - /mnt/data/monitoring/grafana:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=parola_ta_secreta_grafana
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

networks:
  swarm-public:
    external: true

3. Das Sicherheitsnetz auswerfen: Duplicati (Offsite-Backup)

Wir erstellen einen weiteren Stack in Portainer namens backups:

version: '3.8'

services:
  duplicati:
    image: linuxserver/duplicati:latest
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Bucharest
      # SETTINGS_ENCRYPTION_KEY ist zwingend erforderlich zur Absicherung der internen Datenbank
      - SETTINGS_ENCRYPTION_KEY=Renuka2026Backup
      # CLI_ARGS stellt den Zugriff über das Swarm-Netzwerk sicher und setzt das Startpasswort
      - CLI_ARGS=--webservice-interface=any --webservice-port=8200 --webservice-password=admin1234 --webservice-allowed-hostnames=*
    volumes:
      - /mnt/data/backups/duplicati/config:/config
      - /mnt/data/wordpress:/source/wordpress 
      - /mnt/data/maintenance:/source/maintenance 
    networks:
      - swarm-public
    deploy:
      placement:
        constraints: [node.role == worker]

networks:
  swarm-public:
    external: true
⚠️ Enterprise-Warnung: Die Datenbank-Falle
MariaDB ist eine „aktive“ Datenbank. Wenn Duplicati den Ordner db/ kopiert, während die Datenbank aktiv schreibt, wird das Backup korrumpiert.Die Lösung (Dynamischer Dump + Filterung):

  1. Schritt 1 (Cron-Job): Führen Sie crontab -e auf dem Worker-Node aus und fügen Sie die Zeile für 02:50 Uhr nachts hinzu:
    50 02 * * * docker exec $(docker ps -q -f name=wordpress_db) mariadb-dump -u root -pParolaTaSecreta wordpress > /mnt/data/wordpress/database_backup.sql
  2. Schritt 2 (Duplicati-Filter): Wählen Sie in der Duplicati-Benutzeroberfläche unter Filters die Option Exclude folder und wählen Sie source/wordpress/db/ aus.

Auf diese Weise sichern wir nur die statische .sql-Datei, was eine erfolgreiche Wiederherstellung garantiert!

4. Zugriff über Cloudflare Tunnel

Wir fügen die sicheren Routen im Cloudflare Zero Trust-Dashboard hinzu, um auf die neuen Tools zuzugreifen:

  • Grafana-Dashboard: stats.renuka.site ➡️ http://monitoring_grafana:3000
  • Backup-Oberfläche: backup.renuka.site ➡️ http://backups_duplicati:8200

5. Das Albtraum-Szenario: Disaster Recovery (Wie wird wiederhergestellt?)

Wenn Sie den physischen Server komplett verlieren, ist die Reihenfolge der Arbeitsschritte kritisch, um Schreibkonflikte zu vermeiden:

  • Schritt 1 (Wiederherstellung): Installieren Sie Docker auf dem neuen Server, starten Sie den Stack backups und stellen Sie die Daten in /mnt/data/wordpress wieder her.
  • Schritt 2 (Start): Erst jetzt starten Sie den Stack wordpress aus Portainer.
  • Schritt 3 (Automatisierte Injektion): Wir führen ein vorbereitetes „One-Click“-Skript auf dem Worker aus, um die leere Datenbank zu befüllen:
# Wir erstellen das Wiederherstellungsskript auf dem Worker-Node
sudo nano /mnt/data/wordpress/restore_db.sh

# Fügen Sie diesen Code hinzu (achten Sie auf Ihr Root-Passwort!):
#!/bin/bash
docker exec -i $(docker ps -q -f name=wordpress_db) mariadb -u root -pParolaTaSecreta wordpress < /mnt/data/wordpress/database_backup.sql

# Speichern und Ausführungsrechte erteilen:
sudo chmod +x /mnt/data/wordpress/restore_db.sh

Führen Sie sudo /mnt/data/wordpress/restore_db.sh aus, und die Website wird sofort wiederbelebt – identisch mit dem genauen Zeitpunkt des letzten Backups.

👁️ Fazit des „Invisible“-Projekts
Sie haben es geschafft! Sie haben einen komplexen technischen Weg hinter sich gelegt und den Sprung von einem klassischen Hosting zu einer verteilten Enterprise-Architektur gemeistert. Ihre Infrastruktur ist nun ein ausgereiftes, agiles Ökosystem, das für Angreifer völlig unsichtbar ist.

Stay Free! Stay Hidden! Stay Indestructible!