# Portainer EE mit Remote-Agent (Hetzner) über SSH-Tunnel ## Ziel Lokaler Portainer EE verwaltet zusätzlich einen entfernten Docker-Host (Hetzner), ohne dass der Agent-Port (9001) öffentlich erreichbar ist. Der Key für die EE ist in Bitwarden hinterlegt. Die Verbindung erfolgt ausschließlich über einen SSH-Tunnel. --- # Architektur ## Übersicht - Heimserver: Portainer EE - Hetzner-Server: Portainer Agent - Verbindung: SSH-Tunnel (autossh + systemd) - Kein öffentlicher Port 9001 --- ## Netzwerkarchitektur mit Namespace- und Layer-Trennung ``` ┌────────────────────────────┐ │ Internet │ └──────────────┬─────────────┘ │ │ SSH (TCP 22) │ ┌──────────────────────────┴──────────────────────────┐ │ Hetzner VPS (Host OS) │ │------------------------------------------------------│ │ │ │ Docker Engine │ │ ┌──────────────────────────────────────────────┐ │ │ │ portainer_agent Container │ │ │ │----------------------------------------------│ │ │ │ Agent lauscht auf: 0.0.0.0:9001 │ │ │ └──────────────────────────────────────────────┘ │ │ │ │ Host-Port-Mapping: 9001 -> Container 9001 │ └──────────────────────────┬───────────────────────────┘ │ │ localhost:9001 ============================================== SSH Tunnel ============================================== ssh -L 0.0.0.0:9002:localhost:9001 root@hetzner-ip ========================================================================================================= │ │ 0.0.0.0:9002 (Heimserver Host) ┌──────────────────────────┴──────────────────────────┐ │ Heimserver (Host OS) │ │------------------------------------------------------│ │ │ │ autossh Service │ │ lauscht auf: 0.0.0.0:9002 │ │ │ │ Docker Bridge Netzwerk │ │ IP: 172.17.0.1 │ │ │ │ Docker Engine │ │ ┌──────────────────────────────────────────────┐ │ │ │ portainer-ee Container │ │ │ │----------------------------------------------│ │ │ │ Verbindet zu: 172.17.0.1:9002 │ │ │ │ (Host-Bridge-IP) │ │ │ └──────────────────────────────────────────────┘ │ │ │ └──────────────────────────────────────────────────────┘ ``` # Funktionsweise 1. Der Portainer-Agent läuft auf Hetzner und lauscht auf Port 9001. 2. Dieser Port ist **nicht öffentlich relevant**, da keine direkte Nutzung erfolgt. 3. Der Heimserver baut per SSH einen Tunnel auf: - Lokaler Port 9002 → Hetzner localhost:9001 4. Portainer EE verbindet sich intern über: 172.17.0.1:9002 (docker bridge) 5. Der gesamte Traffic läuft verschlüsselt über SSH. ``` # 1. Portainer-Agent auf Hetzner ## docker-compose.yml ``` yaml version: "3.8" services: portainer_agent: image: portainer/agent:2.27.3 container_name: portainer_agent restart: unless-stopped ports: - "9001:9001" volumes: - /var/run/docker.sock:/var/run/docker.sock - /var/lib/docker/volumes:/var/lib/docker/volumes ``` Starten: docker compose up -d Prüfen: ss -tlnp | grep 9001 Erwartet: 0.0.0.0:9001 # 2. SSH-Tunnel automatisieren (Heimserver) ## autossh installieren apt update apt install autossh -y ## systemd Service anlegen Datei: /etc/systemd/system/portainer-hetzner-tunnel.service Inhalt: ``` ini [Unit] Description=SSH Tunnel to Hetzner Portainer Agent After=network.target [Service] User=root Environment="AUTOSSH_GATETIME=0" ExecStart=/usr/bin/autossh \ -M 0 \ -N \ -o "ServerAliveInterval=30" \ -o "ServerAliveCountMax=3" \ -o "ExitOnForwardFailure=yes" \ -o "StrictHostKeyChecking=no" \ -i /root/.ssh/portainer_tunnel \ -L 0.0.0.0:9002:localhost:9001 \ root@65. Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ## Service aktivieren ``` snippet systemctl daemon-reload systemctl enable portainer-hetzner-tunnel systemctl start portainer-hetzner-tunnel ``` Status prüfen: ``` systemctl status portainer-hetzner-tunnel ``` Port prüfen: ``` ss -tlnp | grep 9002 ``` Erwartet: ``` 0.0.0.0:9002 ``` ## 3. Portainer EE konfigurieren In der WebUI: Environments → Add Environment → Agent Adresse: 172.17.0.1:9002 Hinweis: 172.17.0.1 ist die Docker-Bridge-IP des Hosts Portainer läuft im Container Der Tunnel läuft auf dem Host # Sicherheitsmodell - Port 9001 nicht öffentlich erreichbar - Kommunikation ausschließlich über SSH - SSH-Key-basierte Authentifizierung - Automatischer Reconnect via autossh - Kein zusätzlicher VPN erforderlich # Troubleshooting |Problem |Ursache | Prüfen |connection refused |Agent nicht auf 9001 gemappt | - ports9001:9001 in der docker-compose |SSH channel open failed |Agent lauscht nicht |keys vorhanden? |Endpoint unreachable |Tunnel nicht aktiv |curl localhost:9001 schlägt fehl |Agent läuft nicht korrekt