Mein 1&1 cloud server, Teil 5, Umzug des WordPress Blogs

Im 5. Teil meiner Artikelserie beschäftigen wir uns mit WordPress. WordPress ist momentan das wohl am weitesten verbreitete freie Content Managment System. Mein Blog läuft unter WordPress und diesen Blog möchte ich nun auf unseren Cloud Server umziehen. Dazu müssen wir zunächst mit den Voraussetzungen für WordPress auseinander setzen. WordPress benötigt neben einem Webserver, dies kann ein Apache oder auch ein Nginx sein, PHP und die Datenbank MySQL. Prinzipiell läuft WordPress schon mit sehr alten Versionen von Apache, PHP und Mysql, aber aus Sicherheitsgründen werden aktuelle Versionen der Software empfohlen, siehe die Requirements Seite der englischen WordPress.org Webpage.

Schauen wir zuächst was auf unserem Server installiert ist:

Zur Zeit sind Apache 2.4.7, PHP 5.5.9 und MySQL 5.5.47 installiert. Leider gibt es in den offiziellen Repositories keine neueren Versionen. Deshalb wollen wir hier anders vorgehen. Wir werden Komponenten aus Personal Package Archiven (PPA) auf Launchpad installieren. Ondřej Surý stellt dort in seinem PHP 5.6 PPA aktuelle Versionen von Apache und PHP zur Verfügung.

Bevor wir beginnen legen wir zunächst noch im 1&1 Cloudpanel einen Snapshot unseres Servers an, damit wir, falls etwas schief läuft, unseren Server schnell wiederherstellen können. Details dazu im 1. Teil der Artikelserie geschildert.

Schließlich muss ich noch darauf hinweisen, dass die Benutzung dieser unsupporteten PPAs immer auf eigene Verantwortung und Risiko erfolgt.

Als erstes müssen wir das  PPA auf unserem System als Paketquelle hinzufügen. Dies erreichen wir mit folgendem Befehl:

An der Stelle „Press [ENTER] to continue or ctrl-c to cancel adding it“ werden wir aufgefordert die Return Taste zu drücken, um fortzufahren oder mit Strg und C Taste den Vorgang abzubrechen. Ich habe natürlich die Return Taste gedrückt.

Nun machen wir noch ein update der Packetliste:

Wie wir sehen, wird als erstes die Paketliste aus dem neu hinzugefügten PPA aktuaklisiert.

Um bequem die Paketversionen listen zu können, die wir upgraden können installieren wir zunächst noch das Paket apt-show-versions.

Nun können wir uns bequem anschauen für welche Pakete neuere Versionen vorliegen.

Wir sehen, dass wir den Apache auf Version 2.4.18 und PHP auf die Version 5.6.18 upgraden können. Diese Pakete wollen wir nun upgraden:

Wir sehen, dass nicht alle Pakete upgegradet werden, speziell die Apache und PHP Pakete fehlen noch, wie auch ein erneuter Aufruf von apt-show-versions zeigt:

Den Upgrade der restlichen Pakete erreichen wir folgendermaßen:

Das neue PHP Version 5.6.18 und der neue Apache Server Version 2.4.18 sind installiert und der neue Apache Server läuft. Auf die gleiche Weise fügen wir noch das PHP PPA von Ondřej Surý zu unseren Paketquellen hinzu und machen ein Upgrade bzw. Dist-Upgrade. In diesem PPA finden wir auch das neue PHP 7, falls wir es benötigen.

Es wäre nun schön, wenn wir online sehen könnten was unser Apache macht und wie er konfiguriert ist. Dazu gibt es die beiden Apache Module status und info. Wenn wir in das Verzeichnis /etc/apache2/mods-enabled schauen, sehen wir, dass das status Modul sogar aktiviert ist. Es ist jedoch aus Sicherheitsgesichts-punkten keine gute Idee diese beiden Module so zu konfigurieren, dass man die Infomationen von beliebigen Rechnern aus abrufen kann. Deshalb sind beide Module so konfiguriert, dass nur lokal vom Server auf die Seiten zugegriffen werden kann. Wenn wir versuchen auf unsere https://mysubdomain.mydomain.tld/server-status Seite zuzugreifen erhalten wir eine Fehlerseite „403 Forbidden“, wir haben keine Berechtigung auf die Seite zuzugreifen. Für die server-info Seite erhalten wir ein „404 Not Found“, das Modul ist nicht aktiviert.

Werfen wir einen Blick in die beiden Konfigurationsdateien:

In beiden Fällen ist der Zugriff, durch die Anweisung „Require local“, lokal auf den Server beschränkt. Wenn wir hinter einer festen IP-Adresse sitzen, können wir diese natürlich hier eintragen. Ich bevorzuge einen anderen Weg, da ich hinter einer AVM Fritzbox am Vodafone Kabelanschluss, ehemals Kabel Deutschland, sitze und keine feste IP-Adresse habe, jedenfalls keine feste IPv4 Adresse. Voraussetzung ist der Einsatz eines DynDNS Dienstes für meine Fritzbox. AVM bietet einen kostenlosen Dienst für seine Kunden an, den man sehr einfach konfigurieren kann. Einmal eingerichtet findet man den DNS Namen für seine Fritzbox in deren Konfigurationsoberfläche unter Internet -> Online-Monitor. Dort sollte dann ein Eintrag MyFRITZ! existieren, mit einer URL der Form https://routerkennung.myfritz.net und einem Benutzernamen. Der DNS Name für unseren Router ist dann routerkennung.myfritz.net und ein „host routerkennung.myfritz.net“ sollte die momentan zugewiesene IP-Adresse unseres Routers zurückliefern. Da sich zumindest bei Vodafone die zugewiesene IP-Adresse selten ändert könnten wir natürlich diese IP-Adresse in die Konfigurationsdateien eintragen. Ich mache es hier etwas anders.

Zunächst lege ich im Apache Konfigurationsverzeichnis ein neues Verzeichnis und darin eine neue leere Datei an:

In die Datei /etc/apache2/misc/my-current-admin-host.conf schreiben wir später eine passende „Require“ Anweisung. Dann tragen wir in allen Konfigurationen, in denen wir den Zugriff von unserem Heimnetz aus freischalten wollen, eine „Include“ Anweisung ein, die den Inhalt der Datei /etc/apache2/misc/my-current-admin-host.conf in die Konfiguration aufnimmt. Als Beispiel sehen wir hier die Datei /etc/apache2/mods-available/info.conf:

Das gleiche machen wir in der Datei status.conf. Nun haben wir eine zentrale Stelle an der wir die IP-Adresse unseres Admin Hostes, bzw. die unseres Internetrouters eintragen können. Am einfachsten wäre für mich, wenn der 1&1 Cloud Server auch über IPv6 ans Internet angebunden wäre. Dann wäre es jetzt ausreichend in unsere neu angelegte Konfigurationsdatei /etc/apache2/misc/my-current-admin-host.conf meine feste IPv6-Adresse einzutragen. Leider ist dem momentan nicht so.

Die nächste einfach aussehende Option wäre die folgende:

Dies funktioniert leider nicht. Wenn wir einen „host“ angeben, müssen die DNS-Auflösung und die reverse DNS-Auflösung zusammen passen. Das ist bei den DynDNS Namen nicht der Fall, wie man leicht selbst überprüfen kann. Da ich dennoch einen Hosteintrag einem IP-Eintrag vorziehe, wähle ich folgende Vorgehensweise. Ich bestimme mir anhand des DynDNS Namens die IP-Adresse und dann von dieser ausgehend den Hostnamen im Providernetz. Diesen Hostnamen trage ich dann in unsere Konfigurationsdatei ein. Anschliessend müssen wir den Apache noch veranlassen seine Konfiguration neu zu lesen.

Um den ganzen Vorgang zu automatisieren habe ich folgendes script geschrieben:

Das script erwartet einen existierenden Hostnamen als Argument. Die Optionen -v, –verbose triggern das eine ausführliche Ausgabe, während die Optionen -h, –help die Hilfe zum Script anzeigen. Die Funktionsweise ist wie oben beschrieben. Zunächst wird für den angegebenen Hostnamen die zugehörige IP-Adresse bestimmt und dann per reverse Auflösung der zugehörige Hostnamen. Dieser Hostnamen wird mit dem in der Datei /etc/apache2/misc/my-old-admin-host.txt abgelegten Namen verglichen. Nur wenn die beiden Namen voneinander abweichen, wird unsere Konfigurationsdatei für die Hostauthentifizierung /etc/apache2/misc/my-current-admin-host.conf neu geschrieben und ein Apache Reload durchgeführt. Anschließend wird der neue Namen in die /etc/apache2/misc/my-old-admin-host.txt geschrieben. Dies stellt sicher, dass nur wenn notwendig eine neue Konfigurationsdatei geschrieben und ein Apache Reload durchgeführt wird.

Wir packen das Script nach /root/bin/setmyhost.sh, ändern die Permissions und führen es zunächst an der Kommandozeile aus.

Wenn wir das Script erneut ausführen, erhalten wir keine Ausgabe, da nichts zu tun ist. Erst wenn sich IP-Adresse meines Routers ändert, wird die Konfigurationsdatei neu geschrieben und es erfolgt eine Ausgabe. Das hat den angenehmen Nebeneffekt, das wir eine E-Mail-Benachrichtigung mit den Änderungen erhalten, wenn wir das Script in einem cronjob ausführen und sich die IP-Adresse und damit der Hostnamen geändert hat.

Zuletzt tragen wir mit „crontab -e“ einen entsprechenden cronjob in unserer crontab ein.

Das Apache info Modul müssen wir noch aktivieren und den Apache restarten.

Damit können wir die Apache server-status und server-info Seiten nun nutzen. Wenn die beiden Module nicht benötigt werden, sollten wir sie sicherheitshalber jeweils mit a2dismod deaktivieren.

Nun wollen wir uns dem neu installierten PHP 5.6.18 zuwenden. Um bequem unsere PHP Konfiguration überprüfen zu können, werden wir zunächst eine PHP Info Webseite erstellen, auf die nur von unserem Admin-Host zugegriffen werden kann.

Zunächst erstellen wir ein neues Verzeichnis im Webserverbaum.

Dort erstellen wird die folgende Datei:

Nun brauchen wir noch eine Apache Konfigurationsdatei. Diese erstellen wir im Verzeichnis /etc/apache2/conf-available.

Die Include Anweisung bindet unsere Konfiguration zur Zugriffsbeschränkung  mit ein, sodass der Zugriff nur von unserem Admin-Host bzw. von unserem Heimnetz möglich ist. Nun müssen wir die Konfiguration noch aktivieren und den Apache anweisen seine Konfiguration neu zu laden.

Jetzt können wir unter https://mysubdomain.mydomain.tld/phpinfo, die Platzhalter mit den aktuellen Domain ersetzt, die Details unserer PHP Konfiguration sehen.

Nun wollen wir noch unsere MySQL Datenbank auf eine neuere Version upgraden. Ich möchte die MariaDB einsetzen. Dazu brauchen wir die beiden PPAs MySQL 5.6 PPA und MariaDB 10.0 PPA, ebenfalls von Ondřej Surý. Zunächst fügen wir die beiden PPAs als Paketquellen hinzu.

Danach lesen wir die Paketquellen neu ein.

Da wir noch keine Daten in unserer Database haben, deinstallieren wir MySQL zunächst komplett.

Bevor wir die Installation der MariaDB durchführen halten wir den Apparmor Dienst an und entladen alle Profile.

Danach installieren wir die MariaDB.

Bevor wir Apparmor wieder starten müssen wir noch einen Eingriff in die Apparmor Konfiguration vornehmen. Ansonsten wird unsere neue MySQL bzw. MariaDB Datenbank nicht richtig gestartet, da Apparmor den Zugriff auf die Konfigurationsdateien verhindert.

Zuletzt installieren wir noch das PHP MySQL Modul php5-mysql.

Damit haben wir die Voraussetzungen geschaffen, meinen WordPress Blog auf die neue Seite umzuziehen. Den Umzug des Blogs wollen wir mit dem WordPress Plugin Duplicator Pro vornehmen. Das Plugin ist zwar kostenpflichtig, für meine Zwecke aber genau das richtige.

Zunächst möchte ich die Vorbereitungen auf unserem Server vornehmen. Dazu gehören die Erstellung einer Apache Site Konfiguration und das Anlegen einer Datenbank für WordPress.

Bevor wir mit der lokalen Konfiguration des Virtualhost auf unserem Server beginnen können, müssen wir sicherstellen, dass die IP-Adresse unseres Servers auch unter den geplanten Hostnamen gefunden wird. Dazu muss ich für die beiden Subdomains blog.emrich-ebersheim.de und www.blog.emrich-ebersheim.de die DNS-Einstellungen im 1&1 Controlcenter meines SharedHosting-Vertrages anpassen und die IP-Adresse unseres Servres eintragen, siehe dazu auch Teil 2 der Artikelserie. Gegebenenfalls müssen wir danach 24 Stunden warten, bis die geänderte Namensauflösung sich im DNS-System aktualisiert hat. Andernfalls können wir unseren Server eventuell nicht unter dem gewählten Namen erreichen. Dies kann sich dann mit Fehlern beim Erstellen eines Let’s Encrypt Zertifikates bemerkbar machen.

Zunächst legen wir ein neues Verzeichnis /var/www/wp_01 an, in das wir WordPress installieren werden. Danach erzeugen wir die Site Konfiguration für den Apache.

Zugriff ist hier zunächst nur von unserem Adminhost oder lokal auf dem Server möglich. Dies Einstellung ändern wir erst, nachdem wir mit der Installation unserer WordPress Instanz fertig sind.

Nun wollen wir noch ein Zertifikat von Let’s Encrypt installieren. Wir wechseln in das Let’s Encrypt Verzeichnis und fordern das Zertifikat an.

Am Ende gibt das Let’s Encrypt Wrapper-Script eine Warnung aus, dass in unserem Konfiguationsfile keine key oder cert Direktive gefunden wurde. Das ist weiter kein Problem. Wir ergänzen diese Zeilen entsprechend der Konfiguration unserer Default Seite. Die fertige Sitekonfiguration sieht dann wie folgt aus:

Nun kommen wir zurück zur Datenbank MariaDB. Zunächst wollen wir unsere MariaDB Installation absichern. Hierzu führen wir das Script mysql_secure_installation aus.

Als nächstes müssen wir eine Datenbank und einen Datenbankbenutzer für WordPress erstellen.

Auf WordPress selbst, werde ich hier nicht weiter eingehen. Im Netz gibt es jede Menge Informationen zur Installation, Plugins und Sicherheitseinstellungen.

Wie bereits vorher erwähnt, werden wir nun das WordPress Plugin Duplicator Pro einsetzen, um meinen Blog umzuziehen. Wir loggen uns als Administrator auf unserer WordPress Seite ein. Das Duplicator Pro Plugin habe ich bereits installiert. Wir wählen links im Menü die Seite Duplicator Pro -> Packages, siehe nächste Abbildung.

Package Erstellen
Package Erstellen

Zur Zeit gibt existiert noch kein Package. Wir wollen nun ein neues Package mit dem derzeitigen Stand der WrodPress Seite erstellen. Dazu klicken wir auf den Button rechts oben Erstellen.

Package Create Step 1
Package Create Step 1

In einem ersten Schritt überprüft das Plugin, ob alle Voraussetzungen erfüllt sind. Das ist hier der Fall. Als Erstellungsmodus wählen wir Manuell. Den vorgeschlagenen Namen für das Package können wir übernehmen. Storage steht defaultmäßig auf lokalem Filesystem. Das können wir ebenfalls übernehmen. Dann klicken wir einfach auf den blauen Button Next.

Package Create Step 2
Package Create Step 2

Im zweiten Schritt checkt das Plugin die Datenbank und die Verzeichnisstruktur. Hier klicken wir den blauen Button Build um das Package zu erzeugen. Im dritten und letzten Step erzeugt das Plugin einen Installer und ein Package das die Datenbankdaten und die Verzeichnisstruktur inkl. aller Dateien unserer WordPress Seite enthält. Wenn die Erzeugung des Packages erfolgreich beendet wurde, kehrt das Plugin zur Packageliste zurück und wir sehen unser neu erzeugtes Package.

Package Liste
Package Liste

Mit Hilfe der beiden Buttons Installer und Archive, können wir die beiden Dateien auf unseren Rechner lokal herunterladen. Im nächsten Schritt kopieren wir diese beiden Dateien mit scp auf unserem Cloud Server. Wir loggen uns auf dem Server ein und verschieben die beiden Dateien ins DocumentRoot Verzeichnis unsers virtuellen Hostes für WordPress, in unserem Falle /var/www/wp_01. Dass der installer die Dateien entpacken kann, müssen wir den Besitzer für das Verzeichnis und die beiden darin enthaltenen Dateien ändern. Der Owner muss dem Account entsprechen unter dem der Apache Server läuft, das ist unter ubuntu der user www-data.

Dann öffnen wir mit unerem Webbrowser die URL https://mysubdomain.mydomain.tld/installer.php. Der Installer meldet sich mit der folgenden Seite:

Installer Step 1
Installer Step 1

Hier müssen wir unsere WordPress Datenbank, den Datenbank User sowie dessen Passwort angeben. Anschließend sollte man die Datenbankverbindung testen, siehe folgende Abbildung.

Installer Step 1, Datenbankdaten
Installer Step 1, Datenbankdaten

Hier tragen wir die Datenbankinformationen der weiter oben erzeugten Datenbank ein drücken den Button Test Connection. Nach erfolgreichem Verbindungsversuch setzen wir den Haken bei „I have read all warnings & notices“ und klicken den Button Run Deployment. Wir erhalten ein Popup das Nochmals nachfragt, ob wir das Deployment wirklich durchführen wollen. Den Dialog müssen wir bestätigen.

Nach kurzer Zeit kehrt der Installer mit der Seite für den 2. Step zurück.

Installer Step 2, Update
Installer Step 2, Update

Im zweiten Step ersetzt der Installer alle Verweise auf die alte URL und den alten Pfad mit der neuen URL bzw. dem neuen Pfad. Durch Drücken des Buttons Run Update starten wir den Vorgang. Anschließend gelangen wir zum 3. und letzten Schritt Test.

Installer Step 3 Test
Installer Step 3 Test

Diese Schritte sollten wir unbedingt durchführen. Klicken auf „Review Install Report“ zeigt uns Details des Installationsvorgangs. Danach klicken wir auf „Save Permalinks„. Dies bringt uns zur Login Seite, wo wir uns mit einem Administrator Account einloggen. Darauf landen wir in den Einstellungen im Abschnitt Permalinks.

Installer Step 3 Test, Permalinks
Installer Step 3 Test, Permalinks

Hier klicken wir auf Änderungen übernehmen. Anschließend sollten wir unseren Blog ausgiebig testen. Speziell die Bilder und Links sind zu überprüfen.

Im letzten Schritt führen wir den Security Cleanup aus.

Installer Step 3, Security Cleanup
Installer Step 3, Security Cleanup

Wir bestätigen die Nachfrage und erhalten dann die folgende Ausgabe.

Installer Step 3, Security Cleanup finished
Installer Step 3, Security Cleanup finished

Damit haben wir den Blog auf den Cloud Server umgezogen. Es bleibt jedoch noch die Aufgabe die WordPress Installation gegen Angriffe abzusichern. Hierzu findet man etliche Anregungen auf der WordPress.org Codex Seite unter Hardening WordPress. Nachdem wir die notwendigen Maßnahmen durchgeführt haben, können wir den Blog live schalten, indem wir die Beschränkung des Zugriffs von lokal und von unserem Adminhost aufheben. Dazu kommentieren wir die folgenden beiden Zeilen in unserer Siteconfiguration aus.

Danach führen wir noch ein „service apache2 reload“ aus, fertig.

Schließlich wollen wir noch ein Backup unserer Datenbank einrichten. Leider können wir das 1&1 Cloud Server Backup dafür nicht direkt einsetzen, da dieses unsere MariaDB nicht unterstützt. Wir gehen daher einen kleinen Umweg und machen den Datenbankdump mit einem eigenen Script in ein lokales Verzeichnis und sichern dieses dann mit dem 1&1 Cloud Server Backup. Mein Datenbank-Backupscript sieht wie folgt aus:

Mit der Variablen numbackup legen wir fest wieviele Datenbankdumps maximal vorgehalten werden. Die Variable BACKUPDIR gibt das Verzeichnis an, in das die Datenbankdumps geschrieben werden sollen. Nach dem Dump der Datenbank prüft das Script die Anzahl der momentan vorhandenen Dumps und löscht, falls mehr als die angegebene Anzahl Dumps vorhanden sind, die ältesten der überzähligen Dumps.

Unser Datenbank-Backupverzeichnis müssen wir dann noch der 1&1 Cloud Server Backup Selection hinzufügen. Das WordPress Verzeichnis sollten wir ebenfalls in das Backup aufnehmen.

Das Backup wollen wir automatisiert einmal täglich durchführen. Dazu legen wir noch zwei Scripts an. Das erste startet das 1&1 Cloud Server Backup für die aktuelle Filesystem Selection.

Das zweite Script führt den Datenbankdump und das Filesystembackup nach einander aus.

Dieses Script tragen wir als Cronjob mit einer zusätzlichen Zeile in der Crontab ein. Damit wird das Backup einmal täglich um 2:11 Uhr ausgeführt.

Dieser Artikel ist nun doch viel länger geworden, als ursprünglich geplant. Man könnte jetzt noch etliche Seiten zu WordPress und dessen Absicherung gegen Spam und Angriffe aus dem Netz schreiben. Dazu ist allerdings auch eine Vielzahl an Informationen bereits im Internet verfügbar.

Im 6. Teil meiner Artikel Serie werden wir uns mit einem Tool zur Auswertung unserer Apache Log Files und zur Erzeugung von Statistiken der Nutzung unseres Webservers beschäftigen.