Wer Webdienste wie WordPress an entfernten Standorten (z. B. auf einem Home-Server, Proxmox VE oder DietPi beim Kollegen) betreiben möchte, steht meist vor den üblichen Hürden: IPv6-only/DS-Lite-Anschlüsse, dynamische IP-Adressen und das Sicherheitsrisiko offener Router-Ports.
In diesem Setup lösen wir das Problem elegant: Ein öffentlich erreichbarer vServer (1blu) terminiert SSL über Traefik und leitet Anfragen über ein verschlüsseltes Tailscale-Mesh-Netzwerk direkt an die WordPress-Instanz am Remote-Standort weiter.
Vorteile:
- Keine offenen Ports oder Portweiterleitungen am Remote-Standort nötig.
- Automatisches Let’s Encrypt SSL-Management auf dem VPS.
- Vollständig verschlüsselter Transportweg via WireGuard.
1. Die Architektur
Plaintext
[ Browser / Internet ]
│ (HTTPS / 443)
▼
[ 1blu vServer ]
├── Traefik v3 (SSL-Terminierung & Dynamic Routing)
└── Tailscale Container (network_mode: host)
│
▼ (Tailscale Mesh / WireGuard UDP via DERP/P2P)
[ Remote Proxmox / DietPi ]
├── Tailscale Client (100.104.85.99)
└── Webserver / WordPress (Port 80)
2. Server-Setup (1blu VPS)
Schritt 2.1: IP-Forwarding aktivieren
Damit Docker-Container Pakete in das Tailscale-Netzwerk weiterleiten dürfen:
Bash
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf
Schritt 2.2: Tailscale Client als Host-Service im Docker
Der entscheidende Punkt: Tailscale muss mit network_mode: host laufen, damit das tailscale0-Interface direkt auf dem Host-Kernel existiert.
Datei: ~/tailscale/compose.yml
YAML
services:
tailscale:
image: tailscale/tailscale:latest
container_name: tailscale
hostname: v31480-relay
network_mode: host
environment:
- TS_STATE_DIR=/var/lib/tailscale
- TS_USERSPACE=false
- TS_ACCEPT_DNS=true
- TS_EXTRA_ARGS=--reset
volumes:
- ./tailscale-state:/var/lib/tailscale
- /dev/net/tun:/dev/net/tun
- /var/run/tailscale:/var/run/tailscale
cap_add:
- NET_ADMIN
- NET_RAW
- SYS_MODULE
restart: unless-stopped
Starten und Verifizieren:
Bash
cd ~/tailscale
docker compose up -d
docker exec tailscale tailscale ping 100.104.85.99
Schritt 2.3: Traefik Docker-Compose erweitern
Traefik muss ein Verzeichnis für dynamische Datei-Konfigurationen (dynamic/) überwachen, um externe IP-Backends ansteuern zu können.
Auszug aus ~/traefik/docker-compose.yml:
YAML
services:
traefik:
image: traefik:v3.0
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./acme.json:/letsencrypt/acme.json
- ./dynamic:/dynamic:ro # Dynamische Konfigurationsdateien
command:
- --api.dashboard=true
- --providers.docker=true
- --providers.docker.exposedbydefault=false
- --providers.file.directory=/dynamic # File-Provider aktivieren
- --providers.file.watch=true
- --entrypoints.web.address=:80
- --entrypoints.websecure.address=:443
- --entrypoints.web.http.redirections.entrypoint.to=websecure
- --entrypoints.web.http.redirections.entrypoint.scheme=https
- --certificatesresolvers.letsencrypt.acme.tlschallenge=true
- --certificatesresolvers.letsencrypt.acme.email=webmaster@traunrocks.de
- --certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json
networks:
- traefik-net
networks:
traefik-net:
driver: bridge
Schritt 2.4: Traefik Dynamic Route für WordPress anlegen
Verzeichnis anlegen und Konfigurationsdatei mit vi erstellen:
Bash
mkdir -p ~/traefik/dynamic
vi ~/traefik/dynamic/wordpress.yml
Inhalt von ~/traefik/dynamic/wordpress.yml:
YAML
http:
routers:
wordpress:
rule: "Host(`wp.minirocks.dynipv6.de`)"
entryPoints:
- websecure
service: wordpress-service
tls:
certResolver: letsencrypt
services:
wordpress-service:
loadBalancer:
servers:
- url: "http://100.104.85.99:80" # Tailscale-IP der DietPi-Instanz
passHostHeader: true
Danach Traefik neu starten:
Bash
cd ~/traefik
docker compose up -d
3. Remote-Setup: Was auf der WordPress-Instanz noch fehlt
Da Traefik die SSL-Verschlüsselung übernimmt (SSL-Offloading) und die Anfrage intern per HTTP über Tailscale weiterleitet, weiß WordPress standardmäßig nicht, dass der Besucher HTTPS verwendet. Ohne Anpassung führt dies zu Redirect-Loops (ERR_TOO_MANY_REDIRECTS) oder Mixed-Content-Fehlern.
Der Reverse-Proxy Snippet-Block für wp-config.php
Öffne auf dem Remote-Server (DietPi) die Konfigurationsdatei:
Bash
vi /var/www/wordpress/wp-config.php
Füge diesen Block ganz oben, direkt nach dem öffnenden <?php, ein:
PHP
/**
* Reverse Proxy & SSL Offloading Konfiguration für Traefik über Tailscale
*/
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
$_SERVER['HTTPS'] = 'on';
}
// Host-Header explizit weiterreichen (verhindert interne IP-Verlinkungen)
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
$_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}
4. Wichtigste Troubleshooting-Takeaways
- Host vs. Bridge bei Tailscale-Containern: Läuft Tailscale in einem Standard-Docker-Bridge-Netzwerk, sieht der Host das
tailscale0-Interface nicht. Pings und Routen vom Host auf100.x.y.zscheitern dann. Lösung: Immernetwork_mode: hostfür den Tailscale-Container nutzen. - Crash-Loop
changing settings requires mentioning all non-default flags: Tritt auf, wenn im State-Ordner alte Flags gespeichert sind. Abhilfe schafft die UmgebungsvariableTS_EXTRA_ARGS=--resetin dercompose.yml. - URLs in WordPress Allgemein: Beide Einträge (WordPress-Adresse und Website-Adresse) müssen zwingend auf die öffentliche Domain mit
https://zeigen (z. B.[https://wp.minirocks.dynipv6.de](https://wp.minirocks.dynipv6.de)).