Raspi als Reverse Proxy

Änderungsstand: 2021-05-05

2021-05-05: Crontab angepasst. Ein eingeschlichener Fehler wurde behoben.

Dieser Raspi wird später als Server mit traefik2 als Reverse-Proxy eingerichtet, mit zertifiziertem SSL – Zugriff von aussen und ohne separater Serversoftware. Ich installiere einige Programme nach, die ich im späteren Verlauf noch benötige. Dann installiere ich Portainer und DuckDNS. Mit Portainer kann ich schnell meine Docker-Konfigurationen überprüfen, ohne das Terminal zu verwenden.

Ich wählte für die Installation der folgenden Sachen das Raspian-Lite BUSTER als Betriebssystem aus. Hier geht’s zum Guide.

Vorbereitungen:

Zu Beginn erstelle ich ein DuckDNS-Konto um einen DynDns-Dienst zu haben. Dort erstelle ich 1 Hostnamen.

Jetzt installiere ich folgende Sachen:

sudo apt install docker docker-compose curl jq mc

portainer:

Jetzt installiere ich den ersten Docker. Das wird Portainer sein. Ich erstelle meine Docker-*.yml Dateien im /home/dockervolumes-Verzeichnis:

sudo mkdir /home/dockervolumes

Nun folgende Befehle im Terminal eingeben ( Ordner wird erstellt und die *.yml wird dort geöffnet).

sudo mkdir /home/dockervolumes/portainer
cd /home/dockervolumes/portainer && sudo nano docker-compose.yml

Folgendes dort einfügen (vorher Eure Werte überprüfen):

version: '2'
  
services:
  portainer:
    image: portainer/portainer
    command: -H unix:///var/run/docker.sock
    restart: always
    ports:
      - 9000:9000
      - 8000:8000
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/PortainerData:/data

Speichern mit Strg-x, y, Enter

Quelle: https://portainer.readthedocs.io/en/latest/deployment.html

Anschließend die „yml“ starten mit

cd /home/dockervolumes/portainer && sudo docker-compose up -d

Mit IP-Adresse:9000 kann man die Portainer-Web-Oberfläche im Browser starten. Auf die Funktionsweise des Portainers gehe ich hier nicht ein.

duckdns:

Meine verwendete Domain in diesem Guide ist knilix.duckdns.org.

sudo mkdir -p /home/dockervolumes/duckdns
nano /home/dockervolumes/duckdns/docker-compose.yml
---
version: "2"
services:
  duckdns:
    image: linuxserver/duckdns
    container_name: duckdns
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Berlin
      - SUBDOMAINS=knilix
      - TOKEN=DASTOKEN
      - LOG_FILE=true
    volumes:
      - /var/lib/DuckdnsConfig:/config
    restart: unless-stopped

STRG-x, y, Enter

Quelle: https://hub.docker.com/r/linuxserver/duckdns

Anschließend die „yml“ starten:

cd /home/dockervolumes/duckdns &&sudo docker-compose up -d

Die Vorbereitungen wären abgeschlossen.

Traefik:

Hier nur die kompletten Befehle und Infos, die nötig sind.

sudo mkdir -p /home/dockervolumes/traefik
sudo touch /home/dockervolumes/traefik/acme.json
sudo chmod 600 /home/dockervolumes/traefik/acme.json
sudo touch /var/log/traefik.log
sudo chmod 600 /var/log/traefik.log
sudo docker network create traefik-net
sudo docker network create intern

Middlewares (Passwortschutz der Weboberfläche):

Auf der Seite https://hostingcanada.org/htpasswd-generator/ geben wir einen Usernamen und ein Passwort ein. Ich verwende für diesen Guide 1 User und 1 dazugehöriges Passwort. Verwendet bitte richtige Passwörter!!! karldall ist kein passwort – er ist ein Komiker 🙂 Dies dient nur zur Demonstration!!!

User) admin Passwort: karldall

Diesen User und das Passwort gebe ich jetzt auf der zuvor verlinkten Seite ein und generiere meine Passwort, welches ich später für die traefik-docker.yml benötige. Ich verwende die Methode *Apache spezific….. Folgendes bekomme ich heraus:

admin:$apr1$zejclqhm$OdhdcM9CR37zSovA7o6mq1

Jetzt ist wichtig, vor JEDEM $ noch ein $ zu setzen!!!

admin:$$apr1$$zejclqhm$$OdhdcM9CR37zSovA7o6mq1

Diese Ausgabe merken bzw. kopieren.

Jetzt eine neue Datei anlegen. Nennen wir diese dynamic_conf.yml.

dynamic_conf.yml

sudo nano /home/dockervolumes/traefik/dynamic_conf.yml
tls:
  options:
    default:
      minVersion: VersionTLS12
      cipherSuites:
        - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
        - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
        - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
        - TLS_AES_128_GCM_SHA256
        - TLS_AES_256_GCM_SHA384
        - TLS_CHACHA20_POLY1305_SHA256
      curvePreferences:
        - CurveP521
        - CurveP384
      sniStrict: true
http:
  middlewares:
    secHeaders:
      headers:
        browserXssFilter: true
        contentTypeNosniff: true
        frameDeny: true
        sslRedirect: true
        #HSTS Configuration
        customFrameOptionsValue: "SAMEORIGIN"
        stsIncludeSubdomains: true
        stsPreload: true
        stsSeconds: 31536000
    https-redirect:
      redirectScheme:
        scheme: https

STRG-x, y, Enter

Vielen Dank an dieser Stelle an https://goneuland.de/traefik-v2-https-verschluesselung-sicherheit-verbessern/. Ohne diesen Tip wäre es hier nicht so einfach weiter gegangen. Ganz speziell die Header-Sache hat mich am WordPress fast zum Verzweifeln gebracht. Ich habe diese Datei um ein kleines Extra erweitert (die letzten 3 Zeilen).

Traefik.yml

Nicht vergessen, Eure Email einzutragen!

sudo nano /home/dockervolumes/traefik/traefik.yml
## STATIC CONFIGURATION
log:
  level: INFO
  filePath: "/traefik.log"
  
api:
  insecure: true
  dashboard: true
  
entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"
  
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    network: traefik-net
    exposedByDefault: false
  file:
    filename: "/dynamic_conf.yml"
  
certificatesResolvers:
  lets-encr:
    acme:
      storage: acme.json
      email: EMAIL-ADRESSE
  
      httpChallenge:
        entryPoint: http

STRG-x, y, Enter

Passen wir die traefik-docker-compose.yml noch an. Traefik wird nun von Innen und von Aussen erreichbar sein. Natürlich hier unbedingt von Aussen Passwortgeschützt und mit einer sicheren Verbindung. Wartet bitte ca. 1 Minute nach dem Start von Traefik, dass Letsencrypt genügent Zeit hat, die Zertifikate anzulegen. Das gilt auch für die anderen Docker.

Traefik-Compose

Hier tritt die Wirksamkeit des Passwortschutzes in Kraft (In Zeile 32, hinter users= die Ausgabe des vorhin erstellten Passwortes eingeben (das “ am Ende nicht vergessen!))!

sudo nano /home/dockervolumes/traefik/docker-compose.yml
version: '3'
  
services:
  traefik:
    image: "traefik:v2.2"
    container_name: "traefik"
    hostname: "traefik"
    restart: unless-stopped
  
    security_opt:
      - no-new-privileges:true
  
    networks:
      - traefik-net
  
    ports:
      - 80:80
      - 443:443
      - 8080:8080
  
    volumes:
      - "/etc/localtime:/etc/localtime:ro"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/var/log/traefik.log:/traefik.log"
      - "./traefik.yml:/traefik.yml:ro"
      - "./acme.json:/acme.json"
      - "./dynamic_conf.yml:/dynamic_conf.yml:ro"
  
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`traefik.knilix.duckdns.org`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$2W74R0Cf$$HD9TjPUXTtDIfbdFU3FtN."
      - "traefik.http.routers.traefik.middlewares=https-redirect@file"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`traefik.knilix.duckdns.org`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=lets-encr"
      - "traefik.http.routers.traefik-secure.service=api@internal"
  
networks:
  traefik-net:
    external: true

STRG-x, y, Enter

Falls sich jemand fragt, was es mit der letzten Zeile external: true auf sich hat, bekommt jetzt die Antwort. Damit wird dem Docker nur angegeben, dass es sich um ein selbst-angelegtes Netwerk handelt und bei beenden und/oder Löschen des Dockers, das Netzwerk, in diesem Fall traefik-net, nicht mit gelöscht werden soll. Oder so ähnlich…

cd /home/dockervolumes/traefik && sudo docker-compose up -d

Mit Aufruf von traefik.knilix.duckdns.org sehen wir, nach Passworteingabe, die Benutzeroberfläche von Traefik, natürlich mit SSL. Von Innen ist Traefik weiterhin mit VM-Server-IP:8080 erreichbar.

MariaDB

Erstellen wir unsere Datenbank, die auf dem System zuständig sein wird:

sudo mkdir /home/dockervolumes/mariadb
cd /home/dockervolumes/mariadb && sudo nano docker-compose.yml
---
version: "2"
services:
  mymariadb:
    image: linuxserver/mariadb
    container_name: mariadb
    restart: unless-stopped
  
    environment:
      - PUID=1000
      - PGID=1000
      - MYSQL_ROOT_PASSWORD=123458789
      - TZ=Europe/Berlin
  
    volumes:
      - /var/lib/MariaDB:/config
  
    ports:
      - 3306:3306
  
    networks:
      - intern
  
networks:
  intern:
    external: true

STRG-x, y, Enter

MariaDB wird nur im Netzerk intern verfügbar sein. Und das auch richtig so! Keiner will, dass eine Datenbank irgendwo Frei-Zugänglich herumliegt!

Nach dem Start, zur ersten Initialisierung, benötigt MariaDB eine Weile. 1 Minute warten, bevor man darauf zugreift.

cd /home/dockervolumes/mariadb && sudo docker-compose up -d

Schön, dass wir jetzt die Datenbank installiert haben. Mit unserer Angabe von „volumes“ haben wir den Vorteil, dass die Datenbankbankdaten ausserhalb des Dockers abgelegt werden. Somit bleiben die Daten erhalten, auch wenn der Docker mal gelöscht werden sollte. Mit Hilfe von phpMyAdmin lege ich mir meine Datenbanken selbst an.

PhpMyAdmin

Da wir in unserer eigenen VM die Sachen installieren, verzichte ich auch bei PhpMyAdmin auf den Zugriff von Aussen.

sudo mkdir -p /home/dockervolumes/phpmyadmin
sudo nano /home/dockervolumes/phpmyadmin/docker-compose.yml
---
version: "2"
services:
 phpmyadmin:
    image: jackgruber/phpmyadmin
    container_name: phpmyadmin
    restart: unless-stopped
  
    environment:
# IP des Raspi verwenden!
      - PMA_HOST=192.168.252.118
      - PMA_PORT=3306
    ports:
      - 8081:80
      - 9001:9000
  
    networks:
      - intern
  
networks:
  intern:
    external: true

STRG-x, y, Enter

Starten wir den Docker:

cd /home/dockervolumes/phpmyadmin && sudo docker-compose up -d

Jetzt lege ich meine Datenbank per Hand an. Aufruf von PhpMyAdmin im Browser mit VM-IP:8081

Login mit root und das Passwort, welches im mariadb-Dockerfile angegeben wurde. !

Auch hier machte der Browsercache, bei meinen unendlichen Versuchen, immer wieder den Spaß zunichte. Aber irgendwann gewöhnt man sich dran…

Phpmyadmin startet und knallt uns prompt einen kleinen Warnhinweis um die Ohren. Doch das ist normal.

Einfach auf „Finden Sie heraus, warum“ klicken

Und jetzt auf „anlegen“ klicken – Fertig. Es erscheinen ganz viele „OK’s“.

Dann auf Datenbanken (oberes Menufeld) klicken, einen Datenbanknamen im Eingabefeld eintragen (nextcloud) und utf8_general_ci und auf „Anlegen“ klicken.

Jetzt im linken Menu auf „Neu“ und im oberen Menu auf „Benutzerkonten“ klicken. Nun auf „Neu – Benutzerkonto hinzufügen“

Benutzername und Passwort angeben. Hostname gebe ich mit % an. Authentifizierung ist „Native MYSQL.Authentifizierung“.

Jetzt ganz runter scrollen und auf „OK“ klicken. Alles was mit „Globale Rechte“ zu tun hat, bleibt bitte AUS! Auch Datenbank für Benutzerrechte lassen wir unberührt.

Jetzt legen wir noch für unseren soeben erstellten Benutzer die Datenbankrechte an. Links im Menu auf „Neu“ und oben im Menu auf „Benutzerkonten“. Jetzt an den soeben erstellten Benutzernamen „Rechte ändern“ klicken, oben, in der zweiten Reihe, den Reiter „Datenbank“ wählen, im Auswahlmenu „nextcloud“ selektieren und OK. Jetzt bei „Datenbankspezifife Rechte“ – „Alle auswählen“ und OK.

Soeben wurde eine Datenbank für nextcloud erstellt, mit einem Benutzer, der NUR Rechte für die Datenbank nextcloud besitzt. Was wir heute nicht alles lernen 🙂

Da wir jetzt wissen, wie es funktioniert, legen wir auch gleich eine Datenbank und einen Benutzernamen für WordPress an

Wenn fertig, kann das phpmadmin-Fenster geschlossen werden.

Nextcloud

Hier wäre der Eintrag external_links wichtig: Hier kommt die Datenbankzuweisung des Services der MariaDB rein. In meinen Fall mymariadb. Die Passwortabfrage kann man sich bei einer Cloud sparen. Aber ich habe diese absichtlich reingesetzt, damit man mit den einzelnen Befehlen erste „Gehversuche“ machen kann. Die Zeilen 17 bis 19 und 24 bis 26 können theoretisch raus. Oder man setzt ein # vor der Zeile 18 und Zeile 25.

sudo mkdir /home/dockervolumes/nextcloud
cd /home/dockervolumes/nextcloud && sudo nano docker-compose.yml
version: "3.3"
  
services:
   nextcloud:
    image: nextcloud
    container_name: nextcloud
    hostname: "nextcloud"
    restart: unless-stopped
    ports:
      - 8082:80
    volumes:
      - /var/lib/Nextcloud/html:/var/www/html
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nextcloud.entrypoints=http"
      - "traefik.http.routers.nextcloud.rule=Host(`nc.knilix.duckdns.org`)"
## Passwortabfrage
      - "traefik.http.middlewares.nextcloud-auth.basicauth.users=admin:$$apr1$$2W74R0Cf$$HD9TjPUXTtDIfbdFU3FtN."
##
      - "traefik.http.routers.nextcloud.middlewares=https-redirect@file"
      - "traefik.http.routers.nextcloud-secure.entrypoints=https"
      - "traefik.http.routers.nextcloud-secure.middlewares=calcarddav,secHeaders@file"
      - "traefik.http.routers.nextcloud-secure.rule=Host(`nc.knilix.duckdns.org`)"
## gehört zu Passwortabfrage
      - "traefik.http.routers.nextcloud-secure.middlewares=nextcloud-auth"
##
      - "traefik.http.routers.nextcloud-secure.tls=true"
      - "traefik.http.routers.nextcloud-secure.tls.certresolver=lets-encr"
# Traefik-Redirects für CalDAV / CardDAV:
      - "traefik.http.middlewares.calcarddav.redirectregex.permanent=true"
      - "traefik.http.middlewares.calcarddav.redirectregex.regex=https://(.*)/.well-known/(card|cal)dav"
      - "traefik.http.middlewares.calcarddav.redirectregex.replacement=https://$$1/remote.php/dav/"
  
    external_links:
       - mymariadb
  
    networks:
      - intern
      - traefik-net
  
networks:
  intern:
    external: true
  traefik-net:
    external: true

STRG-x, y, Enter

cd /home/dockervolumes/nextcloud && sudo docker-compose up -d

Auf zur Einrichtung Nextcloud

Im Browser gebe ich jetzt nc.knilix.duckdns.org ein und erhalte das Konfigurationsmenu von Nextcloud – natürlich mit zertifiziertem https, wenn man kurz wartet! Bevor mann die Einrichtung beginnt, unbedingt schauen, dass man auch https verwendet!

Administrator-Konto anlegen: lasst Euch was einfallen

Datenverzeichnis: /var/www/html/data

Speicher & Datenbank: MySQL/MARIADB

Datenbankbenutzer: Euren Benutzer, der soeben in phpmyadmin erstellt wurde

Datenbankpasswort: Das dazugehörige Passwort

Datenbankname: nextcloud

Datenbank-Host: Raspi-IP:3306

Jetzt auf „Installation abschließen“ klicken. Da dauert dauert jetzt etwas. Nach ca. 1-2 Minuten springt das Anmeldefenster um und es werden noch empfohlene Apps installiert, weil ich den Haken bei „Empfohlene Apps installieren“ gesetzt habe. Irgendwas ist doch immer^^.

Die gesamte Ersteinrichtung dauerte dann doch gefühlte 4 Minuten.

Fertig!

Ein Tip!

Das Login mit dem Benutzernamen, welchen wir für Nextcloud in der *.yml angelegt haben, gilt NUR für den Datenbankzugriff (z.B über phpmyadmin). Der Login im Nextcloud ist das Administrator-Login, welches vor der Ersteinrichtung im Browser angelegt wurde.

Sicherheits- & Einrichtungswarnungen in Nextcloud:

Einige Sachen werden hier behoben.

Ein weiterer Tip (Login-Problem Handy-App)!

Nach dem Browser-Login im Nextcloud, erstelle ich einen weiteren Benutzer, der keine admin-Rechte hat. Dann logge ich mit diesem Benutzer ein, gehe auf Einstellungen (rechts oben) und dann links auf Sicherheit. Dort im Hauptfenster, ziemlich weit unten auf App-Name, dort gebe ich einen Namen ein, klicke auf „Neues App-Passwort erstellen“ und dann auf „QR-Code für mobile Apps anzeigen“. Diesen QR-Code verwende ich dann für das erste Login in der Nextcloud-App am Handy. Somit wäre binnen Sekunden die Einrichtung der Handy-App erledigt.

WordPress

Wichtig! DB_Host ist der Name des Services, welcher in der maraidb-compose hinterlegt ist. Ebenso external_links.

sudo mkdir -p /home/dockervolumes/wordpress
sudo nano /home/dockervolumes/wordpress/docker-compose.yml
version: '3.1'
  
services:
  
   wordpress:
    image: wordpress
    restart: unless-stopped
  
    ports:
      - 8083:80
  
    environment:
# Daten müssen in der Datenbank schon angelegt sein!
      WORDPRESS_DB_HOST: mymariadb
      WORDPRESS_DB_USER: wie_in_Datenbank
      WORDPRESS_DB_PASSWORD: 'wie_in_Datenbank'
      WORDPRESS_DB_NAME: wordpress
  
    volumes:
      - /var/lib/Wordpress:/var/www/html
  
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.wordpress.entrypoints=http"
      - "traefik.http.routers.wordpress.rule=Host(`wordpress.knilix.duckdns.org`)"
      - "traefik.http.routers.wordpress.middlewares=https-redirect@file"
      - "traefik.http.routers.wordpress-secure.entrypoints=https"
      - "traefik.http.routers.wordpress-secure.rule=Host(`wordpress.knilix.duckdns.org`)"
      - "traefik.http.routers.wordpress-secure.middlewares=secHeaders@file"
      - "traefik.http.routers.wordpress-secure.tls=true"
#
      - "traefik.http.routers.wordpress-secure.tls.certresolver=lets-encr"
  
  
    external_links:
       - mymariadb
  
    networks:
      - traefik-net
      - intern
  
networks:
  traefik-net:
    external: true
  intern:
    external: true

STRG-x, y, Enter

cd /home/dockervolumes/wordpress && sudo docker-compose up -d

Aufruf mit wordpress.knilix.duckdns.org. Es erfolgt eine automatische Umleitung zu https und die Ersteinrichtung kann beginnen.

Fertig. Im wahrsten Sinne des Wortes^^.

Jetzt noch ein Check auf SSL Labs (https://www.ssllabs.com/ssltest/)

Bingo-Soweit scheint wohl alles zu passen

Update der Docker.

.

Wie aktualisiert man jetzt die Docker? Ich verwende dafür ein kleines Script. Bedenkt, dass ALLE Docker, von denen sich in /home/dockervolumes die Scripte befinden, geupdated und gestartet werden, auch wenn diese nicht relevant sind. Soll heissen, dass die Compose-Files von Dockern, die keine Verwendung mehr haben oder momentan nicht benötigt werden, nicht im Verzeichnis /home/dockervolumes sein sollten. Als Bonus kann man in einem Logfile schauen, wann das letzte Update mit diesem Script getätigt wurde.

Im Terminal:

sudo touch /home/updatelog.txt && echo // Updates mit "updatescript"  | sudo tee -a /home/updatelog.txt 
#!/bin/bash
# Automatisches Update ALLER Docker der Docker-Compose-Scriptfiles: /home/dockervolumes/*
# Dateipfad: /scriptfiles/updatescript.sh
# Logfile: /home/updatelog.txt

# System-Update, falls gewünscht
###sudo apt update && sudo apt upgrade -y
   
# Datenbank stoppen
##cd /home/dockervolumes/mariadb
##sudo docker-compose stop
# Datenbank gestoppt (wird automatisch wieder gestartet)

# Angabe Docker-Hauptverzeichnis   
cd /home/dockervolumes
    
readarray -d '' composeConfigs < <(find . -type f -name docker-compose.y* -print0)
    
for cfg in "${composeConfigs[@]}"; do
  docker-compose -f "$cfg" pull
  docker-compose -f "$cfg" up -d
done
    
# Alte Images automatisch löschen
docker image prune -f

Strg-x, y, Enter

chmod 700 updatescript.sh

Zum Aufruf des Scriptes folgenden Befehl eingeben:

sudo ./updatescript.sh

Entfernt man bei den beiden Befehlen mit ## davor die ##, wird die Datenbank vor der Überprüfung der Docker gestoppt. Anschließend wird diese automatisch wieder gestartet. Dies dient zur Sicherheit, um einen Crash oder Datenverlust vorzubeugen, falls bei der Aktualisierung im selben Moment darauf geschrieben werden sollte.

Unter /home/updatelog.txt kann man den Zeitpunkt der Updates einsehen. Mein erster Eintrag sieht folgendermaßen aus:

// Updates mit updatescript
d=21-05-04_23:44:03

Möchte man dieses Script täglich durchlaufen lassen, dann hilft folgendes:

sudo crontab -e 

Falls noch nicht geschehen, den Editor wählen. Ich verwende die 1 (nano). Folgendes am Ende der Datei einfügen (das Hashtag am Ende nicht vergessen):

0 5 * * * sudo ~/scriptfiles/updatescript.sh >/dev/null 2>&1
#

STGR-x, y, Enter

Jetzt wird täglich 05:00 Uhr geschaut, ob ein Update des Dockers verfügbar ist und gegebenenfalls geupdated.

Möchte man nur einmal pro Woche updaten, z.B Montag 05:00 Uhr, dann:

0 5 * * 1 sudo ~/scriptfiles/updatescript.sh >/dev/null 2>&1
#

STGR-x, y, Enter

Oder nur einmal im Monat, z.B. am 01. jeden Monats um 05:00 Uhr:

0 5 * 1 * sudo ~/scriptfiles/updatescript.sh >/dev/null 2>&1
#

STGR-x, y, Enter

.Quelle(n):

Quelle(n):

https://projekt-rootserver.de

https://greenitsolutions.at/traefik-docker-lets-encrypt-tutorial/

https://goneuland.de/traefik-v2-reverse-proxy-fuer-docker-unter-debian-10-einrichten/

https://github.com/DoTheEvo/Traefik-v2-examples

https://docs.traefik.io

https://thibmaek.com/post/updating-all-docker-compose-container

https://www.smarthomebeginner.com/traefik-reverse-proxy-tutorial-for-docker

https://chriswiegman.com/2020/01/running-nextcloud-with-docker-and-traefik-2

https://www.teqqy.de/reverse-proxy-mit-traefik-unter-docker

Erstelle eine Website wie diese mit WordPress.com
Jetzt starten