Hoste selbst! Die eigene SSL-Website mit Docker auf dem NAS

Sicherlich wissen einige von euch, dass ich seit längerem ein Synology NAS als zentralen Datenspeicher zuhause habe.

Das NAS leistet dabei gute Dienste als zentraler Datei-, Medien- und Photoserver, kann aber einiges mehr, wie ich auch schon an anderer Stelle beschrieben habe.

Seit kurzem betreibe ich auch eine private Website (diese hier jedoch [noch] nicht) auf dem NAS, was erst einmal ungewöhnlich klingen mag. Doch auf den zweiten Blick stellt sich heraus, dass die Lösung einige Vorteile gegenüber klassischen Webhosting-Angeboten hat.

Mein Projektziel war es, eine WordPress-basierende persönliche Website mit eigener Domain und SSL-Zertifikat auf meinem Synology-NAS zu betreiben und damit so wenig wie möglich am eigenen NAS-Betriebssystem ändern zu müssen. Fehlkonfigurationen oder andere Nachlässigkeiten könnten ansonsten das komplette NAS gefährden — viel zu riskant. Idealerweise sollte das ganze Setup auch portabel sein, falls mal ein Wechsel bei System, Hard- oder Software ansteht. Dieses Ziel wurde erreicht und ich möchte euch nun im Folgenden beschreiben, wie alles konfiguriert ist. Dies am Beispiel von WordPress mit LAMP-Stack. Grundsätzlich lässt sich die Vorgehensweise via DSM und Docker aber auch für jede andere Umgebung (MEAN-Stack etc.) oder andere Software (bspw. OwnCloud) umsetzen, es müssen dann natürlich andere Docker-Images gewählt und ggf. andere Konfigurationen getätigt werden.

Dieser Beitrag ist ziemlich lang, weil ich ausführlich beschrieben habe, was zu tun ist. Um das Beschriebene nachvollziehen zu können, solltet ihr zumindest über grundlegende Linux- und Terminal-Kenntnisse verfügen und außerdem wissen, wie DNS funktioniert. Ebenfalls solltet ihr nicht auf Kriegsfuß mit eurem Heimnetz stehen und wissen, was Portweiterleitungen sind und wie man Sie einrichtet. Ich gehe außerdem davon aus, dass euer Synology-NAS korrekt funktioniert und ihr (idealerweise) auch eine Synology Dyn-DNS-Konfiguration zur Erreichbarkeit des eigenen NAS über das Internet konfiguriert habt.

Ihr solltet euch ebenfalls im Klaren sein, was ihr den ganzen Prozess über tut und das am Ende quasi euer eigener Server im Internet steht und erreichbar ist. Ihr seid fortan für den Server verantwortlich, es gibt niemanden, der automatisch Patches oder Updates installiert. Das ist ein großer Unterschied zu normalen Shared-Hosting-Umgebungen, wenn auch einige Gefahren durch das Docker-Setup minimiert werden. Bitte kopiert aber bloß nicht blind Befehle fügt sie als root in eine Shell ein — das kann gefährlich sein.

0) Docker?

Tollerweise unterstützen einige moderne NAS-Systeme mit x86-CPU die Software Docker — ein gewaltiger Sprung und großer Vorteil für Heim-Hardware. Denn mittels Docker lassen sich Anwendungen und komplette Betriebssysteme quasi virtualisieren, isolieren und bewegen, ohne dabei die Konfiguration, Hard- oder Software des Host-Systems (des NAS) modifizieren zu müssen.
Man kann somit Betriebssysteme mit Anwendungen installieren, konfigurieren, kopieren, starten und stoppen, ohne direkt das Host-Betriebssystem des NAS anfassen zu müssen.

Ein Docker-Container — ein lauffähiges, virtuelles Betriebssystem — erhält somit Ressourcen, die komplett vom Host getrennt sind und hat auch nur eingeschränkten (oder gar keinen) Zugriff auf die Host-Umgebung.
Vergleichbar ist dies mit virtuellen Maschinen, die man im Profi-Umfeld schon seit langem einsetzt, allerdings werden bei Docker die Host-Ressourcen nicht durch Virtualisierung, sondern durch Rechtemanagement geschützt.

Zur Popularität von Docker trägt auch der zentrale Hub bei – ein Verzeichnis von Docker-Images, die man mit wenigen Handgriffen installieren kann.

Mit DSM 6 hat Synology auch noch eine schöne grafische Oberfläche für Docker bereit gestellt — sodass man neben dem klassischen Weg über die Kommandozeile die allermeisten Sachen auch in der webbasierten UI erledigen kann. Ein echter Vorteil für nicht so versierte Nutzer.

Neben der Verkapselung via Docker ist es ein ungemein beruhigendes Gefühl zu wissen, wo genau die eigenen Daten liegen — nämlich im eigenen Wohnzimmer und nicht in irgendeiner fremden Serverfarm, über deren Prozesse und Abläufe man keine Kontrolle hat. Sicher gibt es auch gute Gründe für Hosting in Rechenzentren oder bei AWS — aber denkt dran: Es soll hier um eine persönliche Website gehen, nicht um ein riesengroßes Business-Projekt. Meine DSM ist in englischer Sprache, die Screenshots sind also möglicherweise etwas anders als bei euch.

1) Docker-Image einrichten

Docker kann auf dem NAS mit Hilfe des »Package Centers« mit einem Klick installiert werden. Ist Docker dort nicht zu finden, ist das eigene NAS-Modell leider nicht kompatibel. Docker läuft dann auf dem DSM mit grafischer Oberfläche und ist recht einfach zu bedienen. Sucht man im Docker-Hub nach »Wordpress«, wird man schnell fündig. Zu beachten ist jedoch, dass jedes der Pakete einen unterschiedlichen Leistungsumfang hat. So bietet das offizielle WordPress-Image beispielsweise keinen MySQL-Server, den man von Hand im Container nachinstallierten oder separat betreiben müsste — machbar, aber aufwändig. Passender war für mich das docker-wordpress-cli-Paket von Kai Hofstetter, dass clever vorkonfiguriert ist und die wichtigsten Einstellungen per Laufzeitvariablen unterstützt und zudem noch Support für WordPress-CLI mitbringt.

Docker-Hub

Docker-Hub

Je nach Geschmack wird man auch in diesem Paket auch einige Kleinigkeiten noch konfigurieren müssen, dazu später mehr.

Das Image lädt man bequem per DSM herunter, anschließend sollte man es im »Images«-Bereich wiederfinden:

Der Container kann nach dem Download nun generiert werden

Der Container kann nach dem Download nun generiert werden

Per Klick auf den »Launch« Button wird der Assistent zum Starten eines Containers angezeigt. Hier empfiehlt es sich, den späteren Domainnamen als Containernamen einzutragen und die Ressourcen des Containers auf ein vernünftiges Level zu begrenzen. Ich habe bei 8GB RAM im NAS 512 MB RAM und die mittlere CPU-Begrenzung für das Image gewählt. Je nach eigener Hardware und geplanter Auslastung solltet ihr hier eventuell andere Werte eintragen. Anschließend durchlaufen wir den Assistenten in der erweiterten Einstellung, klickt also auf »Advanced Settings«.

Die Einstellungen des Container-Wizards

Die Einstellungen des Container-Wizards

Hier legen wir eine Reihe von Parametern fest: Der Container soll bitte von selbst neu starten, falls er ungeplant beendet wird.
Im Reiter »Volume« kann ein Austauschordner zwischen NAS und Docker-Container festgelegt werden. Dieser virtuelle Order wird im Container bereit gestellt und dort gespeicherte Daten wandern aber tatsächlich in einen Order des NAS. Ich nutze diese Funktion im Zusammenhang mit einem WordPress-Plugin als Backup-Option und stelle einen lokalen Ordner innerhalb von WordPress zur Verfügung. Das Plugin sichert die Daten dort rein und sie landen dann direkt auf dem NAS, wo sie in mein normales Backup mit einfließen.
Doch zuerst muss WordPress installiert und die Basis-Ordnerstruktur angelegt werden — wir legen den Austauschorder später fest und tragen hier zunächst nichts ein.

Im »Network«-Reiter ist für unser Projekt nichts zu ändern, wohl aber bei den Ports: Da WordPress im Gespann mit MySQL läuft, braucht es zumindest die Ports 80 (Apache / HTTP) und 3306 (MySQL) zur Kommunikation zur Außenwelt. HTTP wird dabei ins Internet weiter geleitet, MySQL sollte tunlichst im eigenen Heimnetz bleiben und nicht ins Internet bereit gestellt werden. Standardmäßig werden diese beiden Ports auf zufällige Ports des Host-Systems gemappt. Es empfiehlt sich hier aber, feste Ports zu wählen, denn dies macht das spätere Debugging um ein Vielfaches einfacher und es erlaubt auch, aus dem eigenen Heimnetzwerk direkt auf die SQL-Datenbank zugreifen zu können. Die Ports werden also auf dem Host bereit gestellt und in den Container geroutet. Ich habe hier die Ports 10000 und 10001 gewählt, grundsätzlich ist es egal, welche Ports man wählt. Man sollte allerdings keine Standardports (80, 21, 22, 25 etc) blockieren und sich ungenutzte, hohe Ports oberhalb von 10000 suchen. Wer ganz sicher gehen will, dass der Port ungestört ist, kann sich einen Port aus der Reihe der Ephemeral Ports aussuchen.

Die Port-Einstellungen des Containers.

Die Port-Einstellungen des Containers.

Der Bereich »Links« kann wieder unangetastet bleiben. Beim »Environment« kommen nun die von Kai vorgesehenen Variablen zum Zug — allen voran Datenbank- und WordPress-Usernamen und -Passwörter. Mit Klick auf dass (+) fügen wir bei den Variablen eine neue Reihe hinzu und setzen WP_ADMIN_USER mit einem selbst gewählten Wert ein — bitte auf keinen Fall admin nehmen! Das gleiche dann mit WP_ADMIN_PASSWORD, MYSQL_WP_USER und MYSQL_WP_PASSWORD tun und ein vernünftiges Passwort verwenden. Es ist wichtig, diese Parameter vor dem ersten Start des Containers zu setzen, denn nur so beachtet das interne Konfigurations-Script diese. Die Parameter sind später auch noch im Plaintext innerhalb Docker sichtbar, man läuft also nicht Gefahr, Usernamen oder Passwörter zu vergessen. Den Parameter WP_URL lassen wir zunächst weg, denn diesen werden wir in der SQL-Datenbank ändern, da sich der Hostname später noch mehrmals ändern wird.

Die verschiedenen Parameter, die in den Container übergeben werden.

Die verschiedenen Parameter, die in den Container übergeben werden.

Der Assistent wird dann mit Klick auf »OK, Next« abgeschlossen.

Unser laufender Container.

Unser laufender Container.

Im Bereich »Container« sollte der neu erschaffene Container nun zu sehen sein. Er sollte laufen und etwas CPU und RAM geschluckt haben. Schauen wir doch mal mit Klick auf »Details« rein. Wir sehen laufende Prozesse und im Log, das (mit Ausnahme von sendmail, dazu später mehr) alles funktioniert hat und WordPress fertig konfiguriert wurde.

Die Log-Datei des Containers

Die Log-Datei des Containers

Nun, da WordPress läuft, können wir noch den Austausch-Ordner zum Host-System hinzufügen. Änderungen an der Container-Konfiguration lassen sich aber nur durchführen, wenn der Container nicht läuft, also müssen wir in erst stoppen.
Nun können wir im Bereich »Volume« den Ordner hinzufügen, beispielsweise als /var/www/html/wp-content/uploads/wp_2_nas. Dieser Order ist innerhalb von WordPress erreichbar und beschreibbar, da /var/www/html/ der Standard-Dokumentenpfad von Apache ist. Um welchen lokalen (Unter)Ordner auf dem NAS es sich hier handelt, ist Geschmacksache.

Wir speichern die Konfiguration und starten den Container wieder. Nun müssen wir noch einige Kleinigkeiten konfigurieren, die das Leben vereinfachen:
Zunächst muss der oben eingerichtete Austauschordner von jedem innerhalb des Docker-Systems beschreibbar gemacht werden. Hierzu öffnen wir die Details des Containers und erstellen unter »Terminal« mit dem »Create«-Button ein neues Terminal. Dieses wird innerhalb weniger Sekunden als bash auf der linken Seite sichtbar:

Das Terminal - wir befinden uns nun im Container

Das Terminal – wir befinden uns nun im Container

Nun befinden wir uns, eingeloggt als root, innerhalb des Containers. Hier bearbeiten wir nun die Berechtigungen des Austauschorders:

chmod 777 -v /var/www/html/wp-content/uploads/wp_2_nas

Per -v-Parameter seht ihr genau, was gelaufen ist.

Nun müssen wir noch den Hostnamen der WordPress-Installation anpassen. Dies geschieht direkt in der SQL-Datenbank. Da wir den Host später nochmals ändern müssen, ist dies bequemer als in der Docker-Config.

Zur Datenbank-Verbindung kann jeder gängige SQL-Client genutzt werden, etwa Sequel Pro auf dem Mac. Dort bei einer neuen Verbindung die eben erstellen Parameter eintragen und sich verbinden.

Verbindung zur SQL-Datenbank

Verbindung zur SQL-Datenbank

In der Tabelle wp_options ändern wir nun die beiden Parameter siteurl und home auf http://10.10.10.10:10001 ab – wobei 10.10.10.10 der IP des NAS im Heimnetz und 10001 dem in der Docker-Konfiguration eingetragenen Port-80-Mapping entspricht. Beide Parameter könnten also bei euch anders sein, die IP ist es recht sicher.
Testweise können wir auch noch in die Tabelle wp_users schauen, dort sollte nun auch der oben konfigurierte, eigene Username zu sehen sein.

Die WordPress-SQL-Datenbank

Die WordPress-SQL-Datenbank mit den Parametern siteurl und home

Nun kommt der spannende Moment — alles sollte funktionieren: Öffnet einen Browser und gebt http://10.10.10.10:10001 (oder was auch immer eure NAS-IP / Port ist) ein — Ihr solltet vom WordPress Standard-Theme begrüßt werden und einen Demo-Post sehen.

Auch der Admin-Bereich via http://10.10.10.10:10001/wp-admin sollte funktionieren und ihr müsstet in der Lage sein, euch einzuloggen. Möchtet ihr die WordPress-Installation nur im Heimnetz, ohne Zugriff aus dem Internet, nutzen, seid ihr an dieser Stelle schon fertig.

Solltet ihr statt der WordPress-Seite die Login-Seite des NAS / DSM sehen oder vielleicht auch gar nichts: Checkt nochmals alle Einstellungen und Port-Nummern.

Geschafft - Die Seite ist erreichbar und funktioniert!

Geschafft – Die Seite ist erreichbar und funktioniert!

2) Verbindung zur Außenwelt

Eine Website ist natürlich dazu gedacht, über das Internet erreichbar zu sein, deshalb widmen wir uns nun der externen Erreichbarkeit.
Voraussetzung hierfür ist, dass das NAS schon über das Internet erreichbar ist. Sollte dies nicht der Fall sein, müsst ihr die entsprechende Konfiguration mit EZ-Internet und einer Synology-Dyn-DNS-Adresse / Synology Account (Control Panel > External Access) durchführen. Sicherlich funktioniert dies auch mit anderen DnyDNS-Providern, getestet habe ich es aber via Synology. Letztere ist nämlich der Trick, der dafür sorgt, dass die Seite auch trotz wechselnder IP-Adresse eures Heim-Internet-Anschlusses von außen erreicht werden kann. Die DiskStation kümmert sich hier um das Update des nötigen DNS-Mappings.

Zusätzlich muss euer Router so konfiguriert sein, dass die Ports 80 (HTTP) und 443 (HTTPS) an die DiskStation durchgeleitet werden. Prinzipiell funktioniert es auch mit anderen Ports, diese müssten dann von Besuchern aber immer beim Besuchen der Seite mit eingegeben werden – nicht ideal.

Ist eure Diskstation über eine feste Adresse wie bspw http(s)://meinnas.myds.me erreichbar, ist es nur noch ein kleiner Aufwand, eure WordPress-Installation ebenfalls erreichbar zu machen. Synology erlaubt (undokumentiert) beliebige Subdomains des eigenen DynDNS-Namens für verschiedene Dienste zu nutzen. Diese Unterscheidung zwischen NAS-Oberfläche und Blog-Oberfläche mit anderer Subdomain machen wir uns via Reverse-Proxy zu Nutze. Dieser hat seit DSM 6 eine grafische Oberfläche (Control Panel > Application Portal > Reverse Proxy), sodass man keine Config-Dateien mehr von Hand bearbeiten muss. Wir legen dort nun einen Eintrag wie folgt an:

Der Reverse-Proxy-Eintrag zum Zugriff von außen

Der Reverse-Proxy-Eintrag zum Zugriff von außen

Der gewählte Name muss dabei eine Subdomain des schon vorhandenen DynDNS-Namens sein (natürlich müsst ihr hier wieder blog.meinnas.myds.me durch eure eigene Adresse austauschen). Im Zielbereich unten wird der Port, der für die Docker-HTTP-Kommunikation zuständig ist und auf Port 80 des Containers geleitet wird, eingetragen.

Nun müsst ihr auch wieder in der SQL-Datenbank siteurl und home auf http://blog.meinnas.myds.me ändern, diesmal ohne Portangabe (denn der Reverse Proxy übernimmt die Umwandlung).

Nach der Änderung könnt ihr die Funktion wieder im Browser überprüfen — bei Aufruf von http://blog.meinnas.myds.me solltet ihr wieder die WordPress-Seite sehen. Um sicher zu gehen, dass auch die Portweiterleitung des Routers funktioniert, empfiehlt es sich, die Seite auch von außerhalb eures Heimnetzwerks aufzurufen, beispielsweise vom Handy via Mobilfunknetz.

Sollte der Zugriff intern klappen, von außen aber nicht, sind die Portweiterleitungs-Regeln im Router nicht korrekt gesetzt. Sollte gar nichts klappen, überprüft nochmals die Reverse-Proxy-Einstellungen und achtet auf die korrekte Portnummer.

Es ist wichtig zu verstehen, was hier nun genau passiert. Externe Zugriffe auf eure Subdomain http://blog.meinnas.myds.me werden per DNS auf eure aktuell gültige Heimnetz-IP gesendet. Mittels der Port-Weiterleitungs-Regel im Router werden gültige Zugriffe auf Port 80 (HTTP) auf diese IP an die DiskStation im LAN weiter geschickt. Diese erkennt via Reverse Proxy anhand des Hostnamens, der aufgerufen werden soll (Subdomain), dass es sich nicht um einen Zugriff auf die DSM-Oberfläche, sondern das Blog handelt, und leitet den Request auf den entsprechenden Port (bspw 10001) um. Dieser wiederum wird in den Docker-Container auf Port 80 geschickt, wo der Request vom dort laufenden Apache beantwortet und wieder raus ins Internet geschickt wird 1.

Solltet ihr happy mit einer Subdomain sein, dann könnt ihr Schritt 3) überspringen. Falls ihr natürlich eine eigene Domain haben wollt, lest weiter :)

3) Die eigene Domain

Richtig toll wird die eigene Website natürlich erst durch eine eigene Domain. Diese kann man sich bei einem beliebigen Anbieter für wenige Euros im Jahr mieten. Ihr ahnt es schon — auch die externe Domain lässt sich mit dem NAS verkuppeln. Hierzu ist es lediglich erforderlich, die DNS-Einstellungen der Domain bearbeiten zu können.
In der Regel lässt sich beim Eintrag für die Hauptdomain meinedomain.com bloß eine IP-Adresse und kein CNAME (Hostname) hinterlegen. Dies ist nicht weiter schlimm, denn wir können einfach eine Subdomain www.meinedomain.com anlegen. Für diese Subdomain muss der A-Record nun auf einen CNAME geändert werden, und zwar eure DynDNS-Subdomain http://blog.meinnas.myds.me (es sollte auch ohne blog. funktionieren).

Nun sollte sich bei einem PING an beide Adressen (einmal meinedomain.com und www.meinedomain.com) ein unterschiedliches Verhalten2 zeigen:

Ping auf die Hauptdomain und www.-Subdomain

Ping auf die Hauptdomain und www.-Subdomain

Die reine Domain liegt nach wie vor beim Hoster (hier die IP 74.208.xxx.xxx), die Subdomain www. wird aber zum NAS weitergeleitet und der Ping wird von dort beantwortet (die IP 172.249.xxx.xxx). Damit nun auch Aufrufe auf meinedomain.com auf dem Blog landen, muss man für diese Adresse noch eine permanente Umleitung zur www.-Subdomain einrichten. Dies funktioniert je nach Webhoster unterschiedlich, ist aber in der Regel problemlos möglich.

Zwei Einstellungen fehlen noch zum Glück:

  • Ein Reverse-Proxy-Eintrag für die neue Domain. Ihr könnt hier den aus Schritt 2 genutzten Eintrag abändern und den Domainnamen statt der blog.-Subdomain eintragen.
  • Die Anpassung des WordPress-Hosts: siteurl und home müssen in der Datenbank auf http://www.meinedomain.com geändert werden.

Auch hier nun der Ausflug in den Browser zum Testen – am besten ebenfalls von extern testen.

4) SSL, bitte!

Dank Let’s Encrypt ist es heutzutage so einfach wie nie, ein valides SSL-Zertifikat für die eigene Website zu erhalten, und das auch noch kostenlos. Die Einrichtung ist normalerweise schon recht einfach, aber mit DSM geht es noch schneller. Durch die obige Konfiguration mit dem Reverse Proxy lassen sich auch mehrere Zertifikate für verschiedene Domains / Dienste korrekt einbinden. Das heißt, ihr könnt auch mehrere Websites oder eure private Website und dazu das NAS mit eigenen Zertifikaten absichern.

SSL ist kein Muss und die Website funktioniert auch ohne — ich rate euch aber unbedingt, das Zertifikat zu installieren, zumal das in ein paar Minuten getan ist und es eigentlich nur Vorteile bietet.

Öffnet hierzu den Bereich »Security« im »Control Panel«. Setzt im Bereich »Advanced« einen Haken bei »Enable HTTP Compression« und wählt die »Modern Compatibility« für die TLS/SSL Cipher Suites aus. Mit dieser Einstellung schickt die DSM HTTP-Daten komprimiert übers Netz und blockiert außerdem ältere, weniger sichere Clients und aktiviert modernere Verschlüsselungsmethoden bei den Zertifikaten. 3

Schaut dann anschließend im Reiter »Certificate« rein und fügt ein neues Zertifikat hinzu. Im Wizard gebt ihr an, ein neues Zerfikat von Let’s Encrypt erhalten zu wollen. Als Name bietet sich euer Domainname an, den ihr auch im nächsten Schritt zusammen mit eurer E-Mail-Adresse nochmals eingeben müsst. Das Feld »Subject Alternative Name« könnt ihr leer lassen, sofern ihr nicht weitere Subdomains absichern wollt. Mit einem Klick auf »Apply« wird das Zertifikat generiert. Hierzu muss eure Domain aber bereits auf dem DSM erreichbar sein, sonst funktioniert dies nicht.

Ein neues Zertifikat für die externe Domain

Ein neues Zertifikat für die externe Domain

Im »Configure«-Schirm müsst ihr nun eurer externen Domain noch das korrekte Zertifikat zuweisen.

Zuweisung des Zertifikats zur Domain

Zuweisung des Zertifikats zur Domain

Damit das Zertifikat nun auch vom Reverse Proxy genutzt und ausgeliefert wird, muss die Konfiguration hier auch noch geändert werden. Hier ist wichtig zu verstehen, dass das Zertifikat gar nicht im Docker-Container installiert wird, sondern quasi vom Reverse-Proxy dem Traffic übergestülpt wird. 4

Öffnet also die Reverse-Proxy-Configuration und ändert den bestehenden Eintrag wie folgt ab:

Der Reverse-Proxy-Eintrag für die SSL-Domain

Der Reverse-Proxy-Eintrag für die SSL-Domain

Ändert das Protokoll von HTTP auf HTTPS ab und tragt euren Domainnamen (hier wie immer beispielhaft) ein. Wählt außerdem 443 als Port und hakt HSTS und HTTP/2 an. Die Ziel-Konfiguration könnt ihr bestehen lassen, hier bitte nicht HTTPS wählen.

Mittels HSTS und der strikten Cipher-Suite verdient sich die SSL-Konfiguration ein glattes A+ bei SSL Labs – perfekt.

Nun solltet ihr in der Lage sein, auf eure eigene Website mittels https://deinedomain.com zugreifen zu können und es sollte auch keine Zertifikatswarnung angezeigt werden. Es ist möglich, dass der Browser über Mixed Content meckert und die CSS-Dateien nicht lädt. Dies liegt daran, dass WordPress noch nichts über die SSL-Änderung erfahren hat.

Daher empfiehlt es sich, ein Plugin wie beispielsweise Really Simple SSL zu installieren – das sorgt dafür. Ironischerweise hat bei mir die Änderung von siteurl und home auf https:// in der SQL-Datenbank zu Problemen geführt – mit dem Plugin und unveränderter Datenbank-Config hat aber alles geklappt.

Nun sollte die Seite stehen und ein grünes Schloss im Browser erscheinen.

5) Feintuning und kleine Fehler

Die Website funktioniert nun ohne Probleme — fast. Das Docker-Image ist sehr minimalistisch und enthält daher einige Zusatzsoftware nicht, die vielleicht benötigt wird. Sichtbar wird dies unter anderem daran, dass die Permalinks in WordPress nicht funktionieren, weil das Apache-Modul mod_rewrite nicht aktiviert / konfiguriert ist. Um dies nachzuholen und bei der Gelegenheit noch weitere Sachen zu optimieren, begeben wir uns wieder ins Terminal. Keine dieser Änderungen ist zwingend notwendig, aber sie schaden auch nicht :)

Das Terminal kann wieder, wie oben schon geschrieben, via DSM als virtuelles Terminal geöffnet werden. Es ist auch möglich, sich mit einem nativen Terminal direkt in den Container zu verbinden. Hierzu müsst ihr euch erst einmal auf das NAS via SSH verbinden (etwa per ssh -l deinuser 10.10.10.10 wobei ihr den User und die IP natürlich ersetzen müsst5. Dann verbindet ihr euch im zweiten Schritt mit dem Docker-Container:

sudo docker exec -i -t deinedomain.com /bin/bash wobei deinedomain.com hier für den Containernamen steht.

Nun solltet ihr euch wieder als root im Docker-Container befinden. Alle nachfolgenden Befehle sind im Docker-Container (und keinesfalls auf dem Host-NAS!) auszuführen.

Um mod_rewrite zu aktivieren, zuerst

sudo a2enmod rewrite

eingeben. Dann mittels eines Editors (vi ist schon installiert, nano muss installiert werden) die Datei /etc/apache2/apache2.conf editieren und im Bereich /var/www/ den Wert AllowOverride auf FileInfo setzen — siehe Screenshot.

Per vi:
vi /etc/apache2/apache2.conf

Oder per nano (finde ich persönlich viel benutzerfreundlicher):

sudo apt-get install nano -y (nano ohne Nachfrage installieren)
nano /etc/apache2/apache2.conf (Datei bearbeiten)

Editieren der Apache-Config-Datei via nano

Editieren der Apache-Config-Datei via nano

Anschließend via sudo service apache2 restart Apache neu starten. Achtung: Hierbei fliegt ihr aus der Shell des Containers raus, ihr müsst euch anschließend neu verbinden. Die WordPress-Permalinks funktionieren nun.

Es gibt noch weitere Sachen, die wir via Terminal erledigen können:

Überprüfen, ob es neue Softwareupdates gibt…
apt-get update

… und diese dann auch installieren (-y erspart euch die Rückfragen)
apt-get upgrade -y

Das dauert eine Weile.

Anschließend lohnt sich sich, die PHP-Configuration einmal genauer unter die Lupe zu nehmen.
Die PHP-Version lässt sich auch direkt via php -v auslesen, detaillierter ist aber eine phpinfo-Datei, die wir wie folgt anlegen können:

nano /var/www/html/phpinfo.php

Diese wird mit dem Inhalt <php phpinfo() ?> befüllt und dann abgespeichert. Nun kann via deinedomain.de/phpinfo.php die gesamte Konfiguration betrachtet werden. Wir stellen schnell fest, dass das nicht mehr ganz taufrische PHP 5.x installiert ist. Dieses können wir in wenigen Handgriffen durch ein frisches PHP 7.1 ersetzen. Nochmals, das ist kein Muss, aber wo wir schon dabei sind…

Um PHP 7.1 zu installieren, müssen wir Ubuntu ein neues Repository bekannt machen. Hierzu müssen zunächst weitere Tools installiert werden:

sudo apt-get install python-software-properties software-properties-common -y

Dann das Repo ppa:ondrej hinzufügen:

sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php

und anschließend alles aktualisieren:

sudo apt-get update

Weiterhin das alte PHP5 deinstallieren…

sudo apt-get purge php5-common -y

…und PHP 7.1 nebst ein paar Zusatzfunktionen installieren:

sudo apt-get install php7.1 php7.1-fpm php7.1-curl php7.1-mysql php7.1-json -y

Dann muss PHP 7.1 noch mit Apache verbunden und aktiviert werden, dies klappt via

sudo apt install php libapache2-mod-php -y und

sudo a2enmod php7.1

Im Anschluss räumen wir noch auf und bringen den Müll raus, pardon, löschen die nicht mehr genutzten Pakete:

sudo apt-get --purge autoremove -y

Zu guter Letzt muss Apache wieder neu gestartet werden. Denkt daran, dass euch das wieder aus der Shell wirft.

sudo service apache2 restart

Nach neu verbinden sollte via php -v nun PHP 7.1 (oder neuer) sichtbar sein, in meinem Fall war es PHP 7.1.7-1+ubuntu14.04.1+deb.sury.org+1.

So schön die neueste Version auch ist, das sollte nicht unbedingt jeder auf die Nase gebunden bekommen. Deshalb löschen wir nun die phpinfo-Datei auch wieder (sofern Ihr sie nicht noch anderweitig braucht):

rm /var/www/html/phpinfo.php

Sicherlich gibt es noch andere Rädchen, an denen man drehen kann, aber diese Einstellungen und Aktualisierungen sind meiner Meinung nach die Wichtigsten.

Wie bereits oben geschrieben, funktioniert sendmail nicht. Keine Katastrophe, aber WordPress kann so leider keine E-Mails versenden. Ich habe mehrere Sachen erfolglos probiert. Solltet ihr eine Lösung haben — immer her damit.

6) Backup und Wiederherstellung

Ein toller Vorteil von Docker ist, dass man komplette Container in eine Backup-Datei wegsichern kann – und das solltet ihr auch tun. Dies funktioniert via DSM sehr einfach, indem ihr euren Container in der Übersicht markiert und ihn via Settings > Export in eine Datei schreibt. Dieser Vorgang funktioniert auch bei laufendem Container und dauert ca 10 Minuten. Die Backup-Datei wird bei der hier besprochenen Initial-Konfiguration etwa 80-100MB groß. Genau so einfach lässt sich der Container auch wiederherstellen — sicherheitshalber solltet ihr das einmal durchspielen.

Backup des Containers

Backup des Containers

Ebenfalls könnt ihr nun den oben eingerichteten Austauschorder wp_2_nas zum Leben erwecken. Er kann von einem WordPress-Backup-Plugin eurer Wahl als Ziel genutzt werden, da er um upload-Pfad von WordPress liegt. BackWPUp ist beispielsweise ein Plugin, das Backups von der kompletten Konfiguration, Daten und Datenbank erstellen kann und diese in den Ordner (und damit ja dann direkt auf euer Host-NAS) legen kann.

7) Testen und Freuen

Ihr solltet nun zum Abschluss nochmals alles testen und die Website aus verschiedenen Browsern und Netzen aufrufen. Grundsätzlich sollte aber durch die Schritt-für-Schritt-Anleitung nichts schief gegangen sein. Falls doch, schreibt mir einen Kommentar…

Noch eine letzte Warnung: Nutzt die im DSM vorhandenen Features wie den Sicherheitsberater, um sicher zu stellen, dass das System immer auf dem neuesten Stand ist und ihr keine Dienste im Internet bereit stellt, die dort nichts zu suchen haben (SQL, SSH etc). Nutzt außerdem einen von admin abweichenden Benutzernamen, die »automatische Blockierung« und die Firewall im DSM. So toll ein eigenes NAS auch ist — fremde Gäste sollten lieber draußen bleiben.

  1. Es ist ebenfalls wichtig, nur das ins Internet weiter zu leiten, was absolut notwendig ist. Es wäre beispielsweise Unsinn, den MySQL-Port nach außen zu öffnen, schlicht, weil hierfür keine Notwendigkeit besteht. Es ist in diesen Fällen sinnvoller, ein VPN zu erstellen und sich von außen so ins Heimnetz einzuwählen. Dort steht der MySQL-Server ja dann wieder zur Verfügung.
  2. Meine externe Domain ist in der Tat eine .net-Domain, deshalb ist der Screenshot etwas anders.
  3. Das stellt in der Regel kein Problem dar. Sollten Besucher allerdings sehr alte Systeme haben (Win XP etc), kann es sein, dass die Seite nicht aufrufbar ist. In diesem Fall könnt ihr die Kompatibilität schrittweise höher drehen, büßt damit aber Sicherheit ein.
  4. Natürlich wäre es auch möglich, das Zertifikat direkt im Docker-Container zu installieren, dies ist aber ungleich komplizierter.
  5. Damit das funktioniert, muss SSH im NAS aktiviert und konfiguriert sein. Ich empfehle hier nochmals, SSH keinesfalls ins Internet weiter zu leiten und nur im Heimnetz verfügbar zu machen.

9 Gedanken zu „Hoste selbst! Die eigene SSL-Website mit Docker auf dem NAS

  1. Hi Martin,
    deine Anleitung finde ich sehr gelungen. Ich hänge zur Zeit gerade bei dem Teil, bei welchem du dich das erste Mal mit der Datenbank verbindest.
    Hier fragt mich Sequel Pro immer nach dem Namen der Datenbank. Dieser wird ja aber in deiner Anleitung gar nicht gesetzt.
    Eventuell kannst du mir hier ja einen Tipp geben.
    Viele Grüße Stephanos

    1. Hi Stephanos,
      der Datenbanknamen wird in WordPress von der wp-config.php gesetzt, standardmässig lautet er schlicht wordpress. Diesen Teil habe ich in der Anleitung wohl übersehen. Schau mal nach ob das klappt und gib ggf. Bescheid.

  2. Wie kann ich denn auf die WordPress Daten in dem Container zugreife, also quasi auf das WordPress Root Verzeichnis? Ich würde gerne meine WordPress Installation auf ein Docker Image migrieren, weil Synology kein PHP 7.2 anbietet.

    1. Du kannst einen Austauschordner definieren wie beschrieben (siehe wp_2_nas). Dieser Ordner (der auch das Stammverzeichnis von WP sein kann) wird dann direkt über einen Ordner auf dem NAS gemappt. Was du in den Ordner schreibst, steht dem Docker-Image zur Verfügung.

  3. Hey, ich habe das ausprobiert. Wenn ich /var/www/html/ als „Austausch Ordner“ festlege, dann ist WordPress „weg“ und er zeigt mir nur eine leere Apache Index Seite an. Hast du eine Idee dazu? Theoretisch könnte ich natürlich da nun wieder WordPress von wordpress.org rein legen… aber dann ist das WordPress Dateisystem ja zweimal vorhanden. Nur einmal eben nicht erreichbar.

    1. Ja, der Ordner ist dann weg / leer, weil er auf einen (wohl leeren?) Ordner auf deinem NAS zeigt; in dessen Dateisystem. Wenn du dort nun Daten rein legst, stehen sie im Docker-Image zur Verfügung.

  4. Hallo Martin, klasse Anleitung – hat mir sehr im Verständnis geholfen.

    Zusatzfrage (bin neu bei Docker): Wie ist Deine Vorgehensweise, um einerseits die WP/MYSQL Container im Lebenszyklus zu aktualisieren (z.B., wenn Sicherheitslücken gepatcht werden müssen) andererseits aber Deine eigenen Daten in der Datenbank und dem Filesystem nicht zu verlieren?

    Ich habe Dein Setup so verstanden, dass die Nutzdaten ja innerhalb der Container landen? Oder abstrahiert Docker hier bereits … ?

    Danke für Deine Hilfe

    1. Hi Jörg,
      es gibt prinzipiell zwei Arten, dies zu tun (da die Nutzdaten ja außerhalb des Containers liegen können, was allerdings im Tutorial nicht vollständig der Fall ist, aber mit einer anderen Konfiguration machbar wäre). 1) Du updatest die entsprechenden Sachen innerhalb des Containers selbst, so wie ich das PHP-Update beschrieben habe. 2) Du schaust, ob der Maintainer der Docker-Images diese aktualisiert hat und ziehst diese neu, musst dann allerdings wieder die Konfiguration anpassen / linken / aktualisieren. Ich habe bisher den 1. Weg gewählt.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.