Eine WordPress-Installation in weniger als 5 Minuten migrieren

Ich arbeiten an WordPress Projekten immer lokal. Bei vielen Projekten gibt es zusätzlich einen Staging-Server. Die Migration einer WordPress-Installation ist also eine sehr häufig vorkommende Aufgabe für mich. Daher ist ein guter Prozess hier sehr wichtig.

Einfache Migration ohne Plugins

Wenn ich eine Seite migriere, dann verwende ich immer die WP-CLI. Die einzige Voraussetzung hierfür ist ein SSH-Zugang zum Zielserver. Mein Migrationsprozess unterteilt sich in wenige Schritte:

1. Dump der Quelldatenbank

Eine WordPress-Installation besteht aus zwei Teilen, der Datenbank und dem Dateisystem. Um einen Dump der Datenbank zu erstellen, muss nur der folgende Befehl im Hauptverzeichnis von WordPress (dem “document root”) ausgeführt werden:

wp db export
Success: Exported to 'wp_project-staging-2020-04-05-a2aa75c.sql'.

Der Dateiname startet mit dem Namen der Datenbank, gefolgt vom aktuellen Datum und einem zufälligen hexadezimalen Hash. Das ist sehr praktisch für den zweiten Schritt.

2. Packen aller Dateien auf der Quelle

Jetzt sind wir soweit, alle Dateien auf dem Quellserver zu packen. Das erledigen wir einfach mit zip, gzip oder einem anderen Tool:

zip -r wp_project-staging-2020-04-05-a2aa75c.zip .

Als Dateinamen verwenden wir einfach den gleich Namen wie beim Datenbank-Dump und ändern hierbei lediglich die Dateiendung von .sql zu .zip im Befehl. Das “schützt” den Dateinamen davor, einfach erraten werden zu können. Wenn man die Datei einfach nur dump.zip nennen würde, könnte sonst jeder einfach die Datei runterladen.

3. Übertragung der Datei auf den neuen Server

Jetzt ist es an der Zeit, die Datei auf den neuen Server zu übertragen. Das kann man über verschiedene Wege tun. Ein sehr einfacher ist die Verwendung von curl, wget oder ähnlichem:

wget https://staging.example.com/wp_project-staging-2020-04-05-a2aa75c.zip

Wenn man die Dateien von einem lokalen System überträgt, wird man vermutlich FTP verwenden, da man die Datei ja nicht per curl/wget von einer lokalen Domain laden kann.

4. Entpacken der Datei im Ziel

Der nächste Schritt ist sehr nahe liegend. Wir müssen die Datei im Ziel entpacken. Hat man eine ZIP-Datei verwendet, führt man einfach folgenden Befehl aus:

unzip wp_project-staging-2020-04-05-a2aa75c.zip

Wenn man die Dateien in Schritt 2 im Hautpverzeichnis gepackt hat, dann sollten die Dateien auch wieder im Hauptverzeichnis auf dem neuen Server einpackt werden und nicht in einem Unterordner.

5. Aktualisierung der Konfiguration

Bevor wir das Projekt auf dem neuen Server nutzen können, müssen wir die wp-config.php aktualisieren. Vermutlich nur alle Werte, die mit DB_ anfangen.

6. Import der Datenbank

Nun können wir die Datenbank importieren. Wenn die Datenbank auf dem neuen Server noch nicht existiert, kann sie entweder über das Verwaltungsprogramm der Hosters angelegt werden, oder ebenfalls mit einem einfachen WP-CLI Befehl (sofern der Datenbank-User dazu die Berechtigungen hat):

wp db create

Sobald die Datenkbank erstellt ist, können wir den Dump ähnlich zu Schritt 1 importieren:

wp db import wp_project-staging-2020-04-05-a2aa75c.sql

7. Aktualisierung der Domain in der Datenbank

Wie ihr vermutlich wisst, speichert WordPress alle Domainpfade als absolute Pfade in der Datenbank. Daher müssen diese ersetzt werden. Das funktioniert mit einem Plugin, aber noch einfacher über die WP-CLI:

wp search-replace "https://staging.example.com" "https://example.com"

Dies ist die einfachste Ersetzung. In manchen Fällen müssen aber noch andere Ersetzungen durchgeführt werden. Das werde ich in einem zukünftigen Beitrag behandeln.

Fazit

Die Migration eines WordPress-Projekts sollte so einfach und schnell wie möglich sein, gerade dann, wenn man diese Aufgabe sehr regelmäßig erledigt. Mein Ansatz benötigt nur 2 Befehle auf dem Quellserver und 4-5 auf dem Zielserver. Der Teil, der in der Regel die meiste Zeit benötigt, ist das Packen, Übertragen und Entpacken, welches länger dauert, je größer das Projekt ist. Für ein kleines Projekt mit nur wenigen Inhalten dauert es aber jeweils oft weniger als 10 Sekunden.

Ich hoffe, diese kleine Anleitung konnte euch helfen, damit eure nächste Migration genau so schnell und einfach geschieht wie bei mir. Falls ihr einen anderen Ansatz habt, der auch sehr praktisch ist, hinterlasst gerne einen Kommentar hierzu und stellt ihn vor.

Vielen Dank an die WordPress-Community!

Die letzte Woche war hart. Ich meine so richtig hart. Erst vor zwei Wochen habe ich an dieser Stelle allen Organisationsteam gedankt, die Konferenzen absagen mussten. Nun befinde ich mich in genau der gleichen Situation.

Die Absage des WordCamp Europe 2020

Am Donnestagabend vorletzte Woche hatte ich ein Telefonat mit Tess und Jonas, den anderen beiden Global-Leads des WCEU 2020 und mit Rocío, unserer Mentorin, sowie mit Andrea, die das globale WordPress-Community-Team leitet.

Wir haben über einen Zeitplan für die nächsten Wochen und Monate gesprochen und uns einen Plan gemacht, um das WordCamo Europe in Porto im Juni diesem Jahres durchführen zu können. Am 5. März sahen die Dinge noch ganz gut aus. Es gab nur wenige Fälle in Portugal und nur Italien hatte in Europe mit sehr vielen Fällen zu kämpfen. Wir beschlossen also, mit der Planung des Events im Juni weiterzufahren und waren optimistisch, dass es noch stattfinden könne. Wir haben uns bis Anfang April für eine Entscheidung Zeit lassen wollen.

Die letzten Tage

Nach diesem Meeting wurden die Dinge mit jedem Tag schlechter. Konferenzen in Europa wurden abgesagt. Am 9. Märze traf es eine große Joomla Konferenz in Lissabon, die nur eine Woche vor dem WordCamp Europe 2020 in Porto stattfinden sollte.

Am 11. März hat das globale Community-Team Empfehlungen herausgegeben, dass alle Veranstaltungen bis einschließlich 1. Juni abgesagt oder verschoben werden sollten. Da das WCEU 2020 vom 4. – 6. Juni geplant war, also nur bis ein paar Tage zuvor.

Schließlich hatten wir letzten Donnerstag, nur eine Woche nach unsere “Krisensitzung” eine Videokonferenz mit allen Organisatoren, in der wir beschlossen haben, dass wir das WordCamp Europe 2020 absagen und auf das Jahr 2021, ebenfalls in Porto, verschieben werden.

Danke an unserer Communtiy

Die Reaktionen, die auf unserer Ankündigung folgten, waren überwältigend. Wir haben viele empathische Nachichten auf Twitter und anderen Kanälen erhalten. Viele liebe Menschen aus der WordPress-Community haben mich direkt angeschrieben und gefragt, wie es mir geht und Hilfe angeboten.

Darum liebe ich diese Communtiy. In guten und in harten Zeiten unterstützen und helfen wird uns gegenseitig. Das ist auch der Grund, wieso das Organisationsteam positiv in die Zukunft schaut und noch intersiver am WordCamp Europe 2021 in Porto arbeiten wird.

Vielen Dank WordPress-Community ❤

Vielen Dank die Organisationsteams!

Ich hatte für diese Woche einen anderes Thema für den #projekt26 Beitrag geplant, aber die Ereignisse der letzten Wochen haben mich dazu veranlasst über etwas anderes zu schreiben.

WordCamp Asia 2020

Der Februar ist vorüber und es war ein sehr ereignisreicher Monat für mich. Oder sollte ich eher sagen, er war es nicht? Ich habe mich sehr auf keine erst Asienreise gefreut, meine Teilnahme am WordCamp Asia in Bangkok in Thailand. Es war vom 21. – 23. Feburar geplant und ich hatte Flug und Hotel schon vor Wochen geplant sowie Urlaub eingereicht (da Teilnahmen an WordCamps nicht Teil meines Jobs sind). Ich habe mich auch auf ein paar schöne warme Tage mit vielen alten und neuen Freunden gefreut. Aber am 12. Februar bekam ich dann überraschend die traurige Nachricht, dass das WordCamp Asia abgesagt werden musste.

Ich hatte großes Glück und konnte mein Hotel und meinem Flug kostenfrei stornieren. Daher habe ich meine gesamte erste Asienreise für dieses Jahr abgesagt.

CloudFest 2020 Hackathon

Diesen Monat vom 14. – 16. März werde ich meinen ersten echten Hackathon besuchen. Dieser wird nicht nur für Mitglieder der WordPress-Community, sondern für viele andere tolle Menschen aus anderen OpenSource-Communities veranstaltet, sowie Firmen, die sich auf das Thema Hosting spezialisiert haben. Aber auch an dieser Konferenz werde ich nicht teilnehmen, dann das CloudFest musste ebenfalls abgesagt werden.

WordCamp Retreat Soltau 2020

Vor zwei Jahren habe ich eines der besten WordCamps besucht, auf denen ich je als Teilnehmer dabei sein konnte. Es war keine normale Veranstaltung, auf der man sich für einen “Arbeitstag” zu Vorträgen und Workshop traf. Stattdessen verbrachte man 24 Stunden für über mehrere Tage mit allen anderen Teilnehmenden im selben Hotel und konnte neben Vorträgen auch an anderen Aktivitäten teilnehmen. Dieses Jahr war es vom 30. April bis zum 3. Mai geplant. Es war geplant, da auch diese Veranstaltung vor einer Woche abgesagt und auf das nächste Jahr verschoben wurde.

Danke Organisationsteams!

Falls ihr euch nun wundert, wieso ich mich dafür bedankte, dass diese Veranstaltungen abgesagt wurden, dann ist der Grund ganz einfach. Selbstverständlich bin ich sehr traurig darüber, dass ich an an diesen Events nicht teilnehmen kann … zumindest nicht dieses Jahr. Alle Organisationsteams haben aber angekündigt im nächsten Jahr die Veranstaltung erneut zu organisieren. Viele davon am gleichen Ort und ungefähr zur gleichen Zeit.

Ich habe bereits vier WordPress Konferenzen in Berlin organisiert und stecke gerade zum vierten Mal mitten in der Organisation des WordCamp Europe. Ich weiß, wie viel Zeit, Energie und Leidenschaft in die Organisation eines solchen Community-Events fließt. Ich kann mir nur vorstellen, wie schwer es für alle Beteiligten gewesen sein muss, diese Veranstaltungen abzusagen (es gab auch noch weitere).

Mit der Absage einer Veranstaltung ist die Arbeit aber nicht getan und man kann nicht einfach aufhören zu arbeiten. Man muss sich mit den ganzen Nachwehen einer solchen Absage beschäftigen, sämtliche Verträge kündigen und so vielen Menschen wie möglich eine Rückerstattung ermöglichen. Man wird außerdem mit vielen negativen Rückmeldungen zu kämpfen haben, denn nicht alle werden verstehen, wieso die Absage unausweichlich war (wie z.B. “es gab doch gar keine Corona-Infektionen in dem Gebiet”). Allen Personen, die an der Organisation und harten Entscheidung zur Absage beteiligten waren, gilt unsere Unterstützung.

Wenn es euch also wie mir geht und eine Veranstaltung, an der ihr teilnehmen wolltet, wurde abgesagt, dann nehmt euch bitte einen Moment und sendet ein Vielen Dank an das Organisationsteam, denn sie haben es sich mit ihrer Entscheidung sicher nicht einfach gemacht und diese schwierige Entscheidung im besten Interesse der Gesundheit der Community, sowohl der pysischen, als auch der psychischen, gemacht. Und bitte unterstützt sie dadurch, dass ihr auch im nächsten Jahr wieder teilnehmen werdet. Vielleicht ja sogar durch freiwillige Mithilfe auf der Veranstaltung als Volunteer. Damit erhalten ihr den besten Einblick darin, mit wie viel Leidenschaft alle daran arbeiten für uns allen ein tolles Event zu veranstalten!

Danke Ogranisationsteams ❤

Bildkonvertierung mit ImageMagick reparieren

Seit Version 4.7 erstellt WordPress von einer hochgeladenen PDF-Datei einen Screenshot der ersten Seite. Hierzu muss ImageMagick sowie die zugehörige PHP-Extension installiert sein.

Auf einem Server mit Ubuntu 18 funktionierte es aber trotzdem noch nicht, obwohl beide Komponenten installiert waren. Daher habe ich zum Test versucht, eine Konvertierung direkt auf der Kommandozeile durchzuführen:

convert test-pdf.pdf test-pdf.png

Dabei bekam ich dann folgende Fehlermeldung angezeigt:

convert: not authorized `test-pdf.pdf' @ error/constitute.c/ReadImage/412.
convert: no images defined `test-pdf.png' @ error/convert.c/ConvertImageCommand/3210.

Nach etwas Recherche bin ich dann auf die Lösung für das Problem gestoßen. ImageMagick hat seit einigen Versionen eine Security-Policy umgesetzt, in der man einschränken kann, welche Dateiformat umgewandelt werden dürfen. Leider gehört PDF zu den Erweiterungen, die nicht standardmäßig unter Ubuntu 18 konvertiert werden können. Die Policies kann man aber in der Datei /etc/ImageMagick-6/policy.xml anpassen:

<policymap>
  <!-- ... -->
  <policy domain="path" rights="none" pattern="@*" />
  <!-- disable ghostscript format types -->
  <policy domain="coder" rights="none" pattern="PS" />
  <policy domain="coder" rights="none" pattern="EPS" />
  <policy domain="coder" rights="none" pattern="PDF" />
  <policy domain="coder" rights="none" pattern="XPS" />
</policymap>

Hier kann man entweder die Zeile für das PDF-Format mit einem XML-Kommentar auskommentieren oder aber die rights auf read einstellen:

<policymap>
  <!-- ... -->
  <policy domain="path" rights="none" pattern="@*" />
  <!-- disable ghostscript format types -->
  <policy domain="coder" rights="none" pattern="PS" />
  <policy domain="coder" rights="none" pattern="EPS" />
  <policy domain="coder" rights="read" pattern="PDF" />
  <policy domain="coder" rights="none" pattern="XPS" />
</policymap>

Nun kann man auf der Kommandozeile noch einmal testen, ob die Einstellung angenommen wurde (in diesem Fall gibt das convert Kommando keine Rückmeldung). Anschließend sollte die automatische Konvertierung beim Upload von PDF Dateien in die WordPress-Mediathek auch funktionieren.

Fehlende Bilder von Live-Server im Entwicklungs-System anzeigen

Wenn man an einem bestehenden Projekt arbeite, das bereits live gegangen ist, dann ist es manchmal notwendig, dass man sich den aktuellen Stand einer Datenbank vom Live-System holt, um lokal Dinge zu testen. Aber wie sieht es mit den Mediendateien aus, die in der Zwischenzeit dazu gekommen sind und die schnell mehrere Gigabyte an Größe umfassen? Nun, oft wird man auch diese benötigen, vor allem, wenn man am Design arbeitet. Aber wie hält man diese auf dem aktuellen Stand mit der Live-Seite? Die gute Nachricht: das ist gar nicht notwendig und in diesem Blogbeitrag möchte ich euch zeigen, wie man es anders lösen kann.

Nehmen wir also an, dass ich euch gerade eine aktuelle Kopie der Live-Datenbank in euer lokalen Entwicklungs-System gespielt habt. Dann werden wahrscheinliche einige Bilder nicht angezeigt, da ihr ja die URL in der Datenbank auf die lokale Domain geändert habt und diese Bilder lokal nicht gefunden werden können. Ihr könntet auch nun natürlich mit dem Live-System verbinden und alle Bilder synchronisieren, was aber schnell viele Megabyte oder Gigabyte benötigt. Wenn ihr gleichzeitig an mehreren Projekten arbeitet, habt ihr sehr schnell denn Platz auf eurer Festplatte verbraucht. Ihr könnt aber auch einfach den gesamten Uploads-Ordner inklusive aller Unterordner (oder zumindest alle mit den hochgeladenen Mediendateien) löschen und sie stattdessen von der Live-Seite laden lassen.

Fehlende Dateien vom Live-Server laden

Falls ihr in eurer lokalen Entwicklungsumgebungen einen Apache Webserver einsetzt, müsst ihr hierzu lediglich folgende Zeilen in eure .htaccess eintragen:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^wp-content/uploads/(.*) https://xyz.com/wp-content/uploads/$1 [R=302,L]
</IfModule>

Diese Zeilen fügt man ganz oben in der .htaccess Datei vor allen anderen Angaben ein.

Wie es funktioniert

Der Apache Server prüft über die beiden RewriteCond, ob die Datei oder der Ordner, der angefragt wird, nicht existiert. Sollte dies der Fall sein greift die RewriteRule, die alle Aufrufe von Dateien im Ordner wp-content/uploads auf die Live-Seite umleitet.

Es werden also alle Bilder, die nicht lokal vorhanden sind, vom Live-Server abgerufen. Ist bei diesem das Caching richtig eingestellt, passiert dies in der Regel auch nur einmal pro individueller URL.

Somit kann man nun alle Bilder auch auf der lokalen Umgebung sehen, ohne diese vorher runterladen zu müssen. Man kann die Bilder sogar lokal über die Medienübersicht bearbeiten. Sobald man die Datei speichert, wird die Originaldatei sowie die anderen Bildgrößen im lokalen System abspeichert. Diese Änderungen werden aber natürlich nicht wieder ins Live-System zurückgespielt. Man kann hiermit aber schnell und gefahrlos lokale testen.

Einige Einschränkungen

Diese Technik funktioniert in den allermeisten Fällen. Falls der Webserver nicht bei der Generierung des HTML-Codes allerdings prüft, ob die Datei auch wirklich lokal vorhanden ist, dann scheitert es, denn in der Regel passieren solche Prüfungen auf die Existenz von Dateien über eine PHP-Funktion, die dann die Datei nicht finden kann, da unser Trick über den Webserver umgesetzt wird.

Da aber oft eher nur Dateien auf Existenz geprüft werden, die nicht im Uploads-Ordner, sondern in den Ordnern der Themes und Plugins gespeichert sind, sollte das kein allzu großes Problem darstellen. Im Zweifel müsstet ihr dann solche Dateien doch runterladen. Diese zu finden könnte aber etwas knifflig sein.

Eine weitere Einschränkung ist die Notwendigkeit einer Verbindung zum Webserver. Wenn man lokal entwickelt hat man ja in der Regel den Vorteil, dass dies auch ohne Internetverbindung möglich ist. Ich schreibe auch oft meine Blogbeiträge, wenn ich etwas im Zug unterwegs bin, wo die Internetverbindung häufiger abbricht. Falls ihr also Dateien unbedingt für die lokale Entwicklung benötigt, müsste ihr sie wohl doch synchronisieren.

Funktioniert es auch mit anderen Entwicklungsumgebungen?

Das Gleiche ist auch bei der Verwendung des nginx-Servers in der lokalen Entwicklung möglich. Da man aber beim nginx nicht einfach eine Datei im Verzeichnis der WordPress-Installation verwenden kann, müsste ihr folgende Zeilen in die nginx-Konfiguration hinzufügen:

location ~ ^/wp-content/uploads/(.*)$ {
	try_files $uri @missing;
}
location @missing {
	return https://xyz.com$uri;
}

Fazit

Man sollte immer mit einer lokalen Kopie einer Website ändern, wenn man daran entwickelt. Diese auf dem aktuellen Stand zu halten ist allerdings sehr zeitintensiv. Durch den Wegfall der Synchronisation von Mediendateien kann aber sehr viel Zeit und vor allem Speicherplatz eingespart werden.