raspi traefik2 proxy

Änderungsstand: 2020-05-10

Nach mehreren Tests von verschiedenen Personen und etwas externer Hilfe, werde ich diesen Guide von Grund auf Neu gestalten. Die Scriptbefehle wurden als „zu kompliziert“ deklariert. Und ja – es geht übersichtlicher. Ich werde alles auf Traefik 2.2 auslegen, da dies momentan die aktuellste Version ist. Als Bonus gibt es dann noch ein sehr gut funktionierendes WordPress obendrauf. Bis es soweit ist, werde ich diesen Tread offen lassen. Etwas Grundinformation kann nicht schaden. Die geplante Aktualisierung werde ich wahrscheinlich auf’s kommendes Wochenende legen. Schauen wir, ob ich den Zeitplan halten kann.

Update: Der abgeänderte Guide ist nun endlich fertig. Wer sich schon etwas auskennt, kann direkt switchen und dort anfangen. Für alle Anfänger, die noch keine Grunderfahrung diesbezüglich haben, sollten sich erst hier paar Informationen abgreifen.

2 eingeschlichene Schreibfehler im Nextcoudscript wurden korrigiert. Jetzt funktionieren auch die restlichen Scriptbefehle. Mir ist es erst aufgefallen, nachdem ich die Befehle ausdruckte und nebeneinander liegen hatte.

Dieser Guide ist soweit fertig und funktionstüchtig. Änderungen wird es wahscheinlich hier keine mehr geben. Nur bin ich selbst noch nicht ganz zufrieden, wass die Aufteilung der Scriptbefehle angeht. Als ich mich vor Jahrzehnten mit Apache beschäftigte, war doch so vieles anders. Oder es kommt mir nur so vor, weil ich so ewig lange aus der Materie herausgewachsen bin.

Es wird ein Reverse-Proxy mit „traefik2“, SSL, Nextcloud mit Datenbankanbindung und phpMyAdmin zur Datenbankverwaltung eingerichtet.

Raspberry4, 1GB, OS: linux aarch64 Raspbian GNU/Linux 10 (buster), Kernel: 4.19.115-v8+

Tip: Für mich war es teilweise eine Qual, nach Änderungen in den Scripten, die Erfolge im Browser zu sehen. Der Browsercache machte mir oft einen Strich durch die Rechnung. Ich empfehle, einen zweiten (anderen) Browser zu verwenden und die Einstellung des Browsercache dort so zu stellen, dass beim Schließen des Browsers, dieser gelöscht wird. Das vereinfacht vieles…

Voraussetzung:

  • Guide raspi-traefik-vorbereitung (speziell DuckDNS-Docker)

Dieser Guide ist sehr angelehnt an das Original von „DoTheEvo / Traefik-v2-examples„. Als Neueinsteiger in Traefik2 habe ich mir mehrere Tage Grundwissen angeeignet, mit dem ich jetzt arbeite. Theoretisch kann man fast alles per Copy/Paste (allerdings mit Euren Daten) verwenden. Aber das ist nicht Sinn der Sache. Man möchte wenigsten verstehen, was man da anstellt 🙂

Dieser Raspi wird als Reverse-Proxy eingerichtet, mit gesichertem Zugriff auf separate Anwendungen von Aussen und ohne separater Serververwaltungssoftware, wie z.B. OMV5. Da ich keine externe Festplatte zur Hand hatte, arbeitete ich in diesem Guide mit dem /var/lib-Verzeichnis des Linux-Systems.

Alles Step by Step.

Meine verwendeten Sachen für diesen Guide:

  • portainer (optional – im vorhergehenden Guide eingerichtet)
  • duckdns (optional – im vorhergehenden Guide eingerichtet)
  • nginx-Installation (optional – zur Demonstration)
  • traefik-Docker
  • whoami-Docker (optional – zur Demonstration)
  • apache-Docker (optional – zur Demonstration)
  • nextcloud-Docker
  • mariadb-Docker
  • phpmyadmin (optional – zur Demonstration)
  • knilix.duckdns.org (verwendete Domain)

Zuerst installiere ich zu Demonstationszwecken ganz normal nginx :

sudo apt install nginx

Mit Eingabe von Server-IP im Browser erscheint schon die Willkommensseite von NginX. Jetzt stelle ich den Port von NginX von 80 auf 3200:

sudo nano /etc/nginx/sites-available/default

Folgende 2 Zeilen suchen

        listen 80 default_server;
        listen [::]:80 default_server;

und ändern zu:

        listen 3200 default_server;
        listen [::]:3200 default_server;

STRG-X, Y, Enter

sudo chown -R www-data:www-data /var/www/html
sudo systemctl restart nginx

Damit NginX auch beim Starten des Raspi mit gestartet wird:

sudo systemctl enable nginx.service
sudo apt update && apt-get upgrade

Nach Eingabe von Server-IP im Browser erscheint jetzt die Willkommensseite nicht mehr und wird mit einem „Fehler: Verbindung fehlgeschlagen“ angezeigt. Gibt man allerdings Server-IP:3200 ein, ist alles wieder da. Diesen kleinen Umweg musste ich erst einmal gehen, weil die Ports 80 und 443 für Traefik verwendet werden. Und da bin ich auch schon fast beim Stichwort – Traefik. Doch bevor ich jetzt mit Traefik anfange, öffne ich die Ports 80 und 443 für meinen Raspi in meiner FritzBox. Hier ein kurzer Guide dazu. Jetzt ist meine Willkommensseite auch über knilix.duckdns.org:3200 erreichbar. Doch das ist suboptimal. Um das zu verhindern, verwende ich einen Reverse-Proxy. In diesem Guide wird Traefik dafür verwendet.

traefik:

Ich arbeite mit einer traefik-Config-Datei Namens „traefik.yml“. In dieser werden Grundkonfigurationen hinterlegt. Beachtet, dass Sachen, die in der compose-docker-.yml-Datei diesbezüglich unter Umständen auch hinterlegt sind, aber andere Werte besitzen können, Vorrang haben.

Warum die yml und nicht die toml? Mir persönlich gefällt die Schreibweise in der yml einfach besser. Im Grunde ist es egal, ob die yml oder die toml verwendet wird.

Als Erstes erstelle ich einige Verzeichnisse und Dateien, die später benötigt werden und ein Docker-Netzwerk, Namens traefik-net. Ich verwende das /home/dockervolumes/ – Verzeichnis für meine Compose-Files.

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

Erstellen wir das Konfigurationsmenu von Traefik:

(Was ich seit Neuestem gern erwähne, weil es wirklich sehr wichtig ist, dass in der *.yml-Datei keine Tab-Taste verwendet werden darf! Alle Leerzeichen bitte mit Leertaste setzen!)

 sudo nano /home/dockervolumes/traefik/traefik.yml
## STATIC CONFIGURATION
log:
  level: INFO
  filePath: "/traefik.log"

api:
  insecure: true
  dashboard: true

entryPoints:
# (web=http, in verschiedenen *.compose.yml später als Zuweisung web zu finden)
  web:
    address: ":80"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

STRG-x, y, Enter

Jetzt erstellen wir die Docker-Compose-Datei:

sudo nano /home/dockervolumes/traefik/docker-compose.yml
version: "3.3"

services:
  traefik:
    image: "traefik:v2.1"
    container_name: "traefik"
    hostname: "traefik"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/var/log/traefik.log:/traefik.log"
      - "./traefik.yml:/traefik.yml:ro"

networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

Starten wir unseren traefik-Docker:

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

Mit docker logs traefik kann man die logs im Terminal einsehen. Das kann mitunder sehr informativ sein. Die Logdatei befindet sich unter /var/log/traefik.log.

Da „exposedbydefault“ in der traefik.yml auf false gesetzt ist, wird für Container, die von Traefik geroutet werden sollen, eine Bezeichnung „traefik.enable = true“ benötigt. Somit können wir selbst bestimmen, was an Docker über Traefik laufen soll. Es wird sonst soweit nichts anderes benötigt. Traefik kennt den Rest aus der Tatsache, dass die eingefügten „Labels“ aus dem Kontext eines Docker-Containers stammen. Nur das Netzwerk muss zu den „Labels“ extra angegeben werden, damit Traefik das auch verwerten kann. Schauen wir uns das im folgendem Beispiel von Apache-Docker an:

sudo mkdir -p /home/dockervolumes/apache
sudo nano /home/dockervolumes/apache/docker-compose.yml
version: "3.3"

services:
  apache:
    image: httpd:latest
    container_name: apache
    hostname: "apache"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.apache.entrypoints=web"
      - "traefik.http.routers.apache.rule=Host(`apache.knilix.duckdns.org`)"

networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

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

Mit Eingabe von apache.knilix.duckdns.org im Browser erscheint eine Willkommensseite. Allerdings die, von unserem Apache-Docker.

Was haben wir bis jetzt erreicht? Wir erstellten den Traefik-Docker mit einer minimalen Konfiguration, der Eingabebefehle an die konfigurierten Router weiterleitet. Die Traefik-Weboberfläche ist mit Server-IP:8080 erreichbar und mit unserer Konfiguration von Aussen nicht abrufbar. Jetzt installiere ich noch einen kleinen Docker (whoami), um die Unterschiede im Script darzustellen.

sudo mkdir -p /home/dockervolumes/whoami
sudo nano /home/dockervolumes/whoami/docker-compose.yml
version: "3.3"

services:
  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    hostname: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.rule=Host(`whoami.knilix.duckdns.org`)"

networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

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

Ruft man jetzt whoami.knilix.duckdns.org auf, sieht man, dass eine Ausgabe von verschiedenen Sachen erscheint. Das, was ausgegeben wird, ist für uns nicht ganz so wichtig. Ich wollte nur demonstieren, dass wir auch mit einer weiteren Subdomain (whoami) auf unseren Server, von Aussen, zugreifen, obwohl nur eine einzige Domain bei DuckDNS registriert wurde.

Middlewares:

Kommen wir zum Passwortschutz für unserer Zugriffe von Aussen. Wir können bestimmen, wo dieser „zuschlagen“ soll und wo vielleicht kein Schutz benötigt wird. Auf der Seite https://hostingcanada.org/htpasswd-generator/ geben wir einen Usernamen und ein Passwort ein. Ich verwende für diesen Guide 3 verschiedene User und 3 dazugehörige, verschiedene Passwörter. Verwendet bitte richtige Passwörter!!! karldall ist kein passwort – er ist ein Komiker 🙂 Dies dient nur zur Demonstration!!!

User1) admin Passwort: karldall

User2) clara Passwort: otto

User3) bilbo Passwort: karlmay

Diese User und die Passwörter gebe ich jetzt auf der zuvor verlinkten Seite ein und generiere meine Passwörter, die ich später für die *.yml benötige. Ich verwende mittlerweile *Bcrypt. In diesem Guide verwendete ich noch die Methode *Apache spezific…., die auch funktioniert, aber nicht so sicher ist, wie Bcrypt. Folgendes bekomme ich heraus:

admin:$apr1$zejclqhm$OdhdcM9CR37zSovA7o6mq1
clara:$apr1$cvo8n4p5$D0U8R38d5GCmL3T3srQFx/
bilbo:$apr1$vgzts8h7$kpR.nA.8h8FrpNLqCno041

Erstellen wir eine neue Datei und fügen folgende Zeilen ein:

sudo nano /home/dockervolumes/traefik/users_credentials
admin:$apr1$zejclqhm$OdhdcM9CR37zSovA7o6mq1
clara:$apr1$cvo8n4p5$D0U8R38d5GCmL3T3srQFx/
bilbo:$apr1$vgzts8h7$kpR.nA.8h8FrpNLqCno041

STRG-x, y, Enter

Jetzt mounten wir die „users_credentials“ in unserer traefik-docker-compose.yml, indem wir die letzte Zeile des folgenden Scripts unter volumes hinzufügen (die ersten 3 Zeilen stehen da schon drin):

sudo nano /home/dockervolumes/traefik/docker-compose.yml
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/var/log/traefik.log:/traefik.log"
      - "./traefik.yml:/traefik.yml:ro"
      - "./users_credentials:/users_credentials:ro"

STRG-x, y, Enter

Jetzt fügen wir jedem Container, der authentifiziert werden soll, zwei Labeleinträge hinzu. Der erste Eintrag hängt eine neue Middleware namens Auth-Middleware an einen von uns bereits erstellten Apache-Router an. Der Zweite gibt diesem Middleware-Typ „basicauth“ an und gibt an, wo sich die Datei (users_credentials) befindet, die zur Authentifizierung von Benutzern verwendet werden soll. Die letzten 2 „Einträge“ werden unter labels hinzugefügt. Die ersten 3 stehen schon drin:

sudo nano /home/dockervolumes/apache/docker-compose.yml
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.apache.entrypoints=web"
      - "traefik.http.routers.apache.rule=Host(`apache.knilix.duckdns.org`)"
      - "traefik.http.routers.apache.middlewares=auth-middleware"
      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=./users_credentials"

STRG-x, y, Enter

Das gleiche Szenario werde ich jetzt auch für „whoami“ vollziehen. Hier die vollständige Compose-Datei:

sudo nano /home/dockervolumes/whoami/docker-compose.yml
version: "3.3"

services:
  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    hostname: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.rule=Host(`whoami.knilix.duckdns.org`)"
      - "traefik.http.routers.whoami.middlewares=auth-middleware"
      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=./users_credentials"


networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

Starten wir die 3 geänderten Docker:

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

Wenn wir uns jetzt über apache.knilix.duckdns.org oder whoami.knilix.duckdns.org einloggen, erscheint ein Feld zur Passwortabfrage. Hier dann Benutzername und Passwort eingeben (z.B. Benutzername: admin Kennwort: karldall)

Hat alles bis hierher funktioniert, sind wir schon ein ganzes Stück voran gekommen. Noch ein Kaffee bitte…….

Jetzt sollten eigentlich 2 verschiedene Challenge Methoden erklärt werden, wo man sich entscheiden sollte, welche man verwendet!? Hier gibt es ausführliche Beschreibungen, welche Vor- und Nachteile und für welchen Anwendungsfall man welche Challenge verwendet. Leider habe ich die DNS Challenge mit DuckDNS NICHT hinbekommen! Demzufolge bleibt es beim http Challenge, was aber bestens funktioniert.

Lets Encrypt (http Challenge)

Zuerst wird die traefik.yml erweitert. Dazu ändern wir den Static Kontext folgendermassen (bitte eine gültige Email-Adresse angeben):

sudo nano /home/dockervolumes/traefik/traefik.yml
## STATIC CONFIGURATION
log:
  level: INFO
  filePath: "/traefik.log"

api:
  insecure: true
  dashboard: true

entryPoints:
# (web=http, websecure=https, in verschiedenen *.compose.yml als Zuweisung zu finden)
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

certificatesResolvers:
  lets-encr:
    acme:
      storage: acme.json
      email: EMAILADRESSE
      httpChallenge:
        entryPoint: web

STRG-X, y, Enter

Jetzt die docker-compose-Datei von traefik:

sudo nano /home/dockervolumes/traefik/docker-compose.yml
version: "3.3"

services:
  traefik:
    image: "traefik:v2.1"
    container_name: "traefik"
    hostname: "traefik"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/var/log/traefik.log:/traefik.log"
      - "./traefik.yml:/traefik.yml:ro"
      - "./users_credentials:/users_credentials:ro"
      - "./acme.json:/acme.json"

networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

Jetzt die whoami-compose-Datei:

sudo nano /home/dockervolumes/whoami/docker-compose.yml
version: "3.3"

services:
  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    hostname: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.rule=Host(`whoami.knilix.duckdns.org`)"
      - "traefik.http.routers.whoami.middlewares=auth-middleware"
      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=./users_credentials"
      - "traefik.http.routers.whoami.tls.certresolver=lets-encr"

networks:
  default:
    external:
      name: traefik-net

STRG-x. y, ENter

Jetzt Apache-Docker:

sudo nano /home/dockervolumes/apache/docker-compose.yml
version: "3.3"

services:
  apache:
    image: httpd:latest
    container_name: apache
    hostname: "apache"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.apache.entrypoints=websecure"
      - "traefik.http.routers.apache.rule=Host(`apache.knilix.duckdns.org`)"
      - "traefik.http.routers.apache.middlewares=auth-middleware"
      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=./users_credentials"
      - "traefik.http.routers.apache.tls.certresolver=lets-encr"

networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

Starten wir die 3 geänderten Docker:

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

Das Ganze dürfte jetzt ca. 1 Minute dauern. Kleiner Kaffee gefällig? 🙂

Funktioniert hier Lets Encrypt nicht, ist neben kleinen Schreibfehlern im Script, meist ein vergessener Befehl die Ursache. Ganz wichtig ist, dass man chmod 600 auf acme.json anwendet (siehe Befehl ziemlich weit am Anfang des Guides unter traefik).

Da wir aus den *.yml-Files der App’s den http-Zugang entfernt haben, funktionieren diese auch strikt nicht mehr! Das bedeuted, dass keine erzwungene Umleitung stattfindet (wird aber noch geändert!), sondern einfach nur kein Zugriff erfolgt. „404 page not found“. Gebe ich allerdings http(s)://whoami.knilix.duckdns.org ein, bekomme ich einen sicheren, verschlüsselten Zugang auf meiner Login-Seite. Das gleiche gilt natürlich auch für den Apache-Zugang. Wird alles neu aufgesetzt, sollte die acme.json vorher gelöscht werden. Beim hinzufügen von neuen Dockern muss diese vorher nicht gelöscht werden.

Https erzwingen

Mit diesem Konstrukt wird jeder http-Aufruf automatisch zu https umgeleitet. Ich erwähnte eben schon einmal, dass das bisher nicht funktioniert (http wurde einfach deaktiviert), da ich denke, dass es etwas übersichtlicher ist, wenn die Schritte nach und nach abgearbeitet werden, um das Schema zu verstehen. So in etwa versuchte auch der Ersteller des originalen Guides (siehe Quelle Nr.1) das Verständnis für traefik etwas näher zu bringen.

Wir öffnen wieder die traefik-docker-compose.yml und fügen einen Router hinzu, welchen man unter labels findet:

sudo nano /home/dockervolumes/traefik/docker-compose.yml
version: "3.3"

services:
  traefik:
    image: "traefik:v2.1"
    container_name: "traefik"
    hostname: "traefik"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/var/log/traefik.log:/traefik.log"
      - "./traefik.yml:/traefik.yml:ro"
      - "./users_credentials:/users_credentials:ro"
      - "./acme.json:/acme.json"
    labels:
      - "traefik.enable=true"
# http zu https Umleitung:
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
      - "traefik.http.routers.redirect-https.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.redirect-https.entrypoints=web"
      - "traefik.http.routers.redirect-https.middlewares=redirect-to-https"

networks:
  default:
    external:
      name: traefik-net

Strg-x, y, Enter

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

Gebe ich jetzt whoami.knilix.duckdns.org ein, diskutiert traefik gar nicht lange umher, sondern leitet automatisch auf https um. Ich habe nur noch nicht herausfinden können, ob auch der Login mit Benutzername und Passwort ebenfalls verschlüsselt übermittelt wird. Aus diesem Grund verwende ich im Vorfeld immer https://.

Im folgendem Abschnitt bringen wir traefik dazu, eine Anfrage von Aussen direkt zum Server durchzuleiten. Für dieses Beispiel installierte ich auch Anfangs NginX, um zeigen, dass es funktioniert.

Folgender Abschnitt zwischen den 2 schwarzen Balken ist optional und dient nur zur Veranschaulichung. Die ist kein nötiger Bestandteil dieses Guides.

.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Jetzt erweitern wir die „trafik.yml“, damit wir unsere Daten auf dem Raspi (Website oder interne Daten) später auch mit einem SubNamen erreichen. Den Inhalt der Traefik.yml löschen und folgendes einfügen:

sudo nano /home/dockervolumes/traefik/traefik.yml
## STATIC CONFIGURATION
log:
  level: INFO
  filePath: "/traefik.log"

api:
  insecure: true
  dashboard: true

entryPoints:
# (web=http, in verschiedenen *.compose.yml später als Zuweisung zu finden)
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: "traefik.yml"


## DYNAMIC CONFIGURATION
http:
  routers:
    route-to-local-ip:
      rule: "Host(`mytestfile.knilix.duckdns.org`)"
      service: route-to-local-ip-service
      priority: 1000
      entryPoint: web

  services:
    route-to-local-ip-service:
      loadBalancer:
        servers:
# Die Server-IP und mein geänderter nginx-Port
          - url: "http://192.168.252.118:3200"

STRG-x, y, Enter

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

Der „priority“-Wert mit 1000 angegeben, übertrifft von der „“Prioritätsliste““ alle andere Router, wie sie später von der http zu http Umleitung verwendet werden.

Jetzt werden wir über Aufruf von mytestfile.knilix.duckdns.org direkt zum Server:3200 durchgereicht und es erscheint die Willkommensseite von NginX. Man möchte aber bedenken, dass mit dieser Konfiguration https nicht über zertifiziertes LetsEncrypt läuft und auch http-Anfragen als dieses durchgereicht werden. Sicherlich könnte man auch das absichern – aber soweit bin ich noch nicht bzw. benötige ich das nicht.

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Nextcloud

Diese Nextcloudinstanz ist aussschließlich extern erreichbar.

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

    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik-net"
      - "traefik.http.middlewares.nextcloud-caldav.redirectregex.permanent=true"
      - "traefik.http.middlewares.nextcloud-caldav.redirectregex.regex=^https://(.*)/.well-known/(card|cal)dav"
      - "traefik.http.middlewares.nextcloud-caldav.redirectregex.replacement=https://$${1}/remote.php/dav/"
      - "traefik.http.middlewares.nextcloud-https.redirectscheme.scheme=https"
      - "traefik.http.routers.nextcloud-https.entrypoints=web"
      - "traefik.http.routers.nextcloud-https.rule=Host(`nc.knilix.duckdns.org`) || Host(`www.nc.knilix.duckdns.org`)"
      - "traefik.http.routers.nextcloud-https.middlewares=nextcloud-https@docker"
      - "traefik.http.routers.nextcloud.entrypoints=websecure"
      - "traefik.http.routers.nextcloud.rule=Host(`nc.knilix.duckdns.org`) || Host(`www.nc.knilix.duckdns.org`)"
      - "traefik.http.routers.nextcloud.middlewares=nextcloud-caldav@docker"
      - "traefik.http.routers.nextcloud.tls=true"
      - "traefik.http.routers.nextcloud.tls.certresolver=lets-encr"
      - "traefik.http.routers.nextcloud.middlewares=auth-middleware"
      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=./users_credentials"

    volumes:
      - /var/lib/Nextcloud/html:/var/www/html

networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

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

Die erste Initialisierung dauert etwas. Mit Aufruf von nc.knilix.duckdns.org erscheint unsere Passwortabfrage und anschließend die Nextcloudersteinrichtung. Da aber noch keine Datenbank installiert wurde und SQLite nicht wirklich das ist, womit man arbeiten möchte, lassen wir die Ersteinrichtung von Nextcloud vorerst links liegen und installieren die Datenbank. Da momentan noch unsere separate Passwortabfrage zuschlägt, kann derzeit auch kein anderer darauf zugreifen.

MariaDB

Die Datenbank lasse ich für traefik aussen vor.

sudo mkdir /home/dockervolumes/mariadb
cd /home/dockervolumes/mariadb && sudo nano docker-compose.yml
---
version: "2.1"
services:
  mariadb:
    image: linuxserver/mariadb
    container_name: mariadb
    restart: unless-stopped
    environment:
      - PUID=1000
      - PGID=1000
      - MYSQL_ROOT_PASSWORD=Sicheres_Passwort
      - TZ=Europe/Berlin
#      - MYSQL_DATABASE=nextcloud
#      - MYSQL_USER=Datenbankbenutzer
#      - MYSQL_PASSWORD=Passwort_des_Datenbankbenutzers
    volumes:
      - /var/lib/Mariadb:/config
    ports:
      - 3306:3306
##    labels:
##      - "traefik.enable=true"
##      - "traefik.http.routers.mariadb.entrypoints=websecure"

networks:
  default:
##    external:
##     name: traefik-net

STRG-x, y, Enter

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. Wer möchte, kann auch die # entfernen und die Daten direkt eingeben. Somit spart Ihr Euch phpmyadmin und das Selbsterstellen der Datenbank. Wenn Ihr die ## entfernt, läuft die Datenbank über das traefik-net.

phpmyadmin (optional)

Phpmyadmin lasse ich für traefik aussen vor! Für mich heisst das, dass ich nur einen internen Zugriff auf phpmyadmin bekomme und traefik diesen Docker nicht anrührt. Das ist von mir so gewünscht.

sudo mkdir /home/dockervolumes/phpmyadmin
cd /home/dockervolumes/phpmyadmin && sudo nano docker-compose.yml
---
version: "2"
services:
 phpmyadmin:
    image: jackgruber/phpmyadmin
    container_name: phpmyadmin
    restart: unless-stopped
    environment:
      - PMA_HOST=192.168.252.118
      - PMA_PORT=3306
    ports:
      - 8081:80
      - 9001:9000
##    labels:
##      - "traefik.enable=true"
##      - "traefik.http.routers.phpmyadmin.entrypoints=websecure"

networks:
  default:
##    external:
##      name: traefik-net

STRG-x, y, Enter

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

Wenn Ihr die ## entfernt, läuft phpmyadmin über das traefik-Net.

Aufruf im Browser mit Server-IP:8081

Login mit root und das Passwort, welches im mariadb-Dockerfile angegeben wurde. ! Falls Ihr schon einige Male probiert habt und anschließend kein root-Zugriff mehr funktioniert, löscht den Browsercache.

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“. Jetzt auf Datenbank (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!

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 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 🙂

Das phpmadmin-Fenster kann geschlossen werden.

Auf zur Einrichtung Nextcloud

Im Browser gebe ich jetzt nc.knilix.duckdns.org ein, bestätige das Login-Fenster mit meinen Daten (admin karldall) und erhalte das Konfigurationsmenu von Nextcloud – natürlich mit zertifiziertem https!

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: Server-IP:3306

Jetzt auf „Installation abschließen“ klicken. Da das jetzt eine gefühle Ewigkeit dauert, könnt Ihr Euch denken, was jetzt kommt…….. Kaffee 🙂 . Nach ca. 3-4 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 10 Minuten.

Fertig!

Ein wichtiger 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. Ich empfehle, dass nach dem Login in Nextcloud mind. ein weiterer Benutzer angelegt wird.

Sicherheits- & Einrichtungswarnungen:

Einige Sachen werden hier behoben.

Jetzt können wir den „extra-Passwortschutz“ von traefik entfernen. Da wir in Nextcloud (!hoffentlich!) schwere Passwörter angegeben haben, wird das separate Anmeldefenster nicht mehr benötigt.

Separater Passwortschutz entfernen:

Entfernt einfach die 2 Einträge, die für die separate Passwortabfrage zuständig sind oder setzt diese auf inaktiv (#).

cd /home/dockervolumes/nextcloud && sudo nano docker-compose.yml
version: "3.3"

services:
  nextcloud:
    image: nextcloud
    container_name: nextcloud
    hostname: "nextcloud"
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.docker.network=traefik-net"
      - "traefik.http.middlewares.nextcloud-caldav.redirectregex.permanent=true"
      - "traefik.http.middlewares.nextcloud-caldav.redirectregex.regex=^https://(.*)/.well-known/(card|cal)dav"
      - "traefik.http.middlewares.nextcloud-caldav.redirectregex.replacement=https://$${1}/remote.php/dav/"
      - "traefik.http.middlewares.nextcloud-https.redirectscheme.scheme=https"
      - "traefik.http.routers.nextcloud-https.entrypoints=web"
      - "traefik.http.routers.nextcloud-https.rule=Host(`nc.knilix.duckdns.org`) || Host(`www.nc.knilix.duckdns.org`)"
      - "traefik.http.routers.nextcloud-https.middlewares=nextcloud-https@docker"
      - "traefik.http.routers.nextcloud.entrypoints=websecure"
      - "traefik.http.routers.nextcloud.rule=Host(`nc.knilix.duckdns.org`) || Host(`www.nc.knilix.duckdns.org`)"
      - "traefik.http.routers.nextcloud.middlewares=nextcloud-caldav@docker"
      - "traefik.http.routers.nextcloud.tls=true"
      - "traefik.http.routers.nextcloud.tls.certresolver=lets-encr"
#      - "traefik.http.routers.nextcloud.middlewares=auth-middleware"
#      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=./users_credentials"

    volumes:
      - /var/lib/Nextcloud/html:/var/www/html

networks:
  default:
    external:
      name: traefik-net

STRG-x, y, Enter

cd /home/dockervolumes/nextcloud && sudo docker-compose restart

Geschafft. Die erstellte Nextcloud-Instanz ist Online!

Wie aktualisiert man jetzt die Docker? Ich verwende dafür ein kleines Script, welches ich momentan noch per Hand starte. Aber bedenkt, dass ALLE Docker, von denen sich in 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.

cd /usr/local/bin && sudo nano mydockerupdatecomposescript
#!/bin/bash
# Automatisches Update ALLER Docker in /home/dockervolumes/*
# Ablageverzeichnis: /usr/local/bin/mydockerupdatecomposescript
# Angabe Hauptverzeichnis

# Datenbank stoppen
##cd /home/dockervolumes/mariadb
##sudo docker-compose stop
# Datenbank gestoppt (wird automatisch wieder gestartet)

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

Zum Aufruf des Scriptes folgenden Befehl eingeben:

sudo bash mydockerupdatecomposescript

Fertig.

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.

Fazit: Ich habe mehrere Anläufe benötigt, um das Ganze funktionstüchtüchtüg rüber zu bringen. Obwohl ich jetzt schon bei einigen Sachen weiß, warum und wie diese funktionieren, bin ich aber immer noch unsicher, ob das alles auch so den Richtlinien entspricht. Gut ist schon mal, dass im Dashboard von Traefik keine Fehlermeldung erscheint.

Mit der Geschwindigkeit des Zugriffes auf die Nextcloudinstanz bin ich etwas, sagen wir mal vorsichtig, enttäuscht. Mag sein, dass ich von meiner Nextcloud-Docker-Instanz auf meinem Hauptserver verwöhnt bin, da ich da nur internen Zugriff habe und von extern, wenn es denn mal benötigt wird, mittels VPN-Verbindung zugreife. Aber der erste Schritt zu einer vollwertigen, eigenen Cloud, mit den Vorzügen des Internets, ist gegeben. Ich werde mich diesbezüglich weiter einlesen und wenn ich dann von jedem einzelnen Script-Befehl die Funktion auch nachvollziehen kann, wer weiss, vielleicht schreibe ich dann nochmal einen Guide darüber. Spaß macht es mir allemal.

.

.

Quelle(n):

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://teqqy.de/reverse-proxy-mit-traefik-unter-docker/