WordPress-Migration auf neuen Server – eine Leidensgeschichte

Aufgrund von internen Umstrukturierungen der IT mussten wir nun diesen Blog auf einen neuen Server mit einem neuen Domain-Namen (blog.e9a.at anstatt e9a.at) umsiedeln. Normalerweise verläuft so etwas bei uns relativ problemlos, wir haben das auch schon ein paar mal gemacht. Allerdings war es für uns ein Novum, eine WordPress-Instanz über die Kommandozeile zu migrieren. Und wie sich herausstellen sollte, kann es mit WordPress durchaus wilde Komplikationen geben. Vor allem, wenn man es sich zur Aufgabe macht, das ganze mit nginx und mit einem Reverse-Proxy laufen zu lassen. Hier nun eine Anweisung, wie wir schließlich ans Ziel gekommen sind, und welche Steine WordPress uns in den Weg gelegt hat.

Als erstes mussten wir die Seite vom alten Server wegbringen. Dazu haben wir den Ordner /var/www/e9a-webpage als tar.gz verpackt und mittels dem Tool „mysqldump“ die erforderliche Datenbank als SQL-Instruktionen in einer Datei abgespeichert.

Diese Daten haben wir auf dem neuen Server kopiert, fürs erste einmal ins Home-Verzeichnis. Nun mussten wir ein paar Applikationen installieren (wir verwenden Debian 9):

apt install nginx-full php-fpm php-gd php-mysql php-json php-hash mariadb-server

Hier haben wir nun eine nginx-Konfiguration eingepielt

# nginx local where wordpress is hosted
# Location: /etc/nginx/conf.d/blog.e9a.at.conf
# Upstream to abstract backend connection(s) for php
upstream php {
        server unix:/run/php/php7.0-fpm.sock;
        # server 127.0.0.1:9000;
}
server {
        ## Your website name goes here.
        server_name blog.e9a.at;
        ## Your only path reference.
        root /var/www/e9a-webpage;
        ## This should be in your http block and if it is, it's not needed here.
        index index.php;
        location = /favicon.ico {
                log_not_found off;
                access_log off;
        }
        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
        }
        location / {
                # This is cool because no php is touched for static content. include the "?$args" part so non-default permalinks doesn't break 
                # when using query string
                try_files $uri $uri/ /index.php?$args;
        }
        location ~ \.php$ {
                #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
                include fastcgi.conf;
                fastcgi_intercept_errors on;
                fastcgi_pass php;
        }
        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
                expires max;
                log_not_found off;
        }
}

Die php.ini von php-fpm müssen wir noch bearbeiten, weil wir den Parameter „cgi.fix_pathinfo = 0“ setzen müssen. Der Dateipfad lautet wie folgt:

/etc/php/7.0/fpm/php.ini

Jetzt haben wir die Backup-Daten in das enstprechende Verzeichnis entpackt und den mysqldump eingespielt. Den MySQL Benutzer und das Passwort wurde in unserem Fall neu gesetzt, wir können aber nicht mit Sicherheit behaupten, ob das auch notwendig war.

Am Reverse-Proxy kopierten wir folgende Konfiguration:

# nginx on Reverse Proxy
server {
    listen 443 ssl http2; 
    listen [::]:443 ssl http2; # OCSP Stapling fetch OCSP records from URL in ssl_certificate and cache them
    server_name blog.e9a.at; 

    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_certificate /etc/letsencrypt/live/blog.e9a.at/fullchain.pem; 
    ssl_trusted_certificate /etc/letsencrypt/live/blog.e9a.at/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.e9a.at/privkey.pem; 

    resolver 9.9.9.9;
    ssl_ecdh_curve prime256v1;
    #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;";
    #Server should determine the ciphers, not the client
    ssl_prefer_server_ciphers on;

    # SSL session handling
    ssl_session_timeout 24h;
    ssl_session_cache shared:SSL:50m;
       
    #add_header X-Content-Type-Options nosniff;
    #add_header X-XSS-Protection "1; mode=block";
    #add_header X-Robots-Tag none;
    #add_header X-Download-Options noopen;
    #add_header X-Permitted-Cross-Domain-Policies none;
        
        location / {
            proxy_pass http://172.17.0.20:80;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
	    proxy_set_header X-Forwarded-Server $host;
    }
# Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
}

Nach einem kurzen Neustart von nginx und php-fpm war die Konfiguration so weit fertig.

Nun hingen wir an einem Fehler, der uns einige Zeit kostete. Überzeugt davon, die File-Permissions richtig gesetzt zu haben, waren wir doch sehr überrascht, immer wieder nur eine weiße Seite mit einer Fehlermeldung wie „No Input File selected“ zu sehen. Nach einiger Recherche-Arbeit stießen wir dann an über folgenden Link:

https://stackoverflow.com/questions/25774999/nginx-stat-failed-13-permission-denied

Nachdem wir den Befehl (sudo muss nachinstalliert werden, sonst funktioniert es nicht)

sudo -u www-data stat /var/www/e9a-webpage/

wie im Artikel beschrieben probiert hatten, stellte wir tatsächlich fest, dass irgendeine Berechtigung nicht richtig gesetzt war. Wir sind uns bis jetzt nicht sicher, was genau da nicht gepasst hat, aber nachdem wir nochmal chmod und chown über das Verzeichnis gemacht haben, ging der Befehl auf einmal, und nach einem kurzen F5 im Browser hatten wir unsere Seite wieder vor uns. Aber Moment, WAS IST DAS DENN? Man konnte zwar fetzen von e9a.at sehen, aber alles war am falschen Platz. Kurz mit F12 einen Blick darauf geworfen, konnten wir feststellen, dass SSL nicht korrekt werkte und gewisse Inhalte von WordPress über HTTP geladen werden wollten, was dem Browser so gar nicht gefallen wollte.

Hier hat uns dieser Link extrem weitergeholfen:
https://www.variantweb.net/blog/wordpress-behind-an-nginx-ssl-reverse-proxy/

Wichtig ist dabei nur zu beachten, den auf dieser Website beschrieben Block am ANFANG der Config-File und nicht am Ende einzufügen. Ansonsten erwarten euch sehr komische Fehlermeldungen wie etwa “ Du bist leider nicht berechtigt, auf diese Seite zuzugreifen “ im Admin-Bereich… obwohl euer User die immer hatte.

UPDATE: Damit auch alle externen IP-Adressen richtig durchgeleitet werden, muss zusätzlich in die wp-config.php noch folgender Eintrag rein:

if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_X_FORWARDED_FOR"];
}

Der letzte wichtige Punkt ist, dass ihr in der Datenbank, solltet ihr die Website so wie wir unter einem neuen Hostnamen laufen haben, alle Verweise und Links auf die alte URL durch die neue erstetzt. Dies geschieht wie auf dieser Website beschrieben:

https://codex.wordpress.org/Changing_The_Site_URL

Links und Credit

https://stackoverflow.com/questions/25774999/nginx-stat-failed-13-permission-denied
https://www.variantweb.net/blog/wordpress-behind-an-nginx-ssl-reverse-proxy/
https://codex.wordpress.org/Changing_The_Site_URL
https://wordpress.org/support/topic/wordpress-behind-a-reverse-proxyssl-endpoint-slightly-borked/

Schreibe einen Kommentar

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