WordPress naar een nieuwe server verhuizen zonder downtime

Gepubliceerd op 15 min leestijd

De volgorde bepaalt alles: nieuwe server voorbereiden, gegevens kopiëren, via het hosts-bestand onder het echte domein testen, het certificaat vooraf uitgeven en pas daarna DNS omzetten. Met de weg terug en de echte foutmeldingen.

Een WordPress-verhuizing mislukt zelden door één enkel commando. Ze mislukt door de verkeerde volgorde. Wie eerst DNS omzet en daarna pas kopieert, krijgt gegarandeerd een venster waarin bezoekers ofwel een foutpagina ofwel een half gevulde installatie te zien krijgen. Andersom kunt u de nieuwe server rustig afmaken, hem onder het echte domein testen en het DNS-record pas wijzigen op het moment dat alles aantoonbaar werkt.

Dit artikel beschrijft precies die volgorde, plus de plekken waar het in de praktijk misgaat: geserialiseerde gegevens in de database, collations bij de overstap van MySQL naar MariaDB, certificaten zonder een DNS-record dat al naar de nieuwe machine wijst, en de weg terug voor het geval er toch iets over het hoofd is gezien.

De volgorde die geen downtime oplevert

De oude site blijft tot het allerlaatste moment online. Er wordt niets uitgeschakeld en niets verwijderd. De nieuwe server draait parallel, wordt getest en neemt het pas over zodra het DNS-record is omgezet.

  1. Verlaag de TTL van het A- en het AAAA-record naar 300 seconden, minstens 24 tot 48 uur van tevoren.
  2. Zet de nieuwe server op: webserver, PHP, database, gebruikers, mappen.
  3. Kopieer de bestanden, kopieer de database.
  4. Geef het certificaat voor het domein uit, ook al wijst DNS nog naar de oude server.
  5. Pas op uw eigen computer het hosts-bestand aan en klik de site onder het echte domein helemaal door.
  6. Draai vlak vóór de omschakeling een delta-sync, zodat de laatste wijzigingen meekomen.
  7. Zet DNS om. Laat de oude server daarna nog enkele dagen draaien.

Het enige punt waarop theoretisch een gat kan ontstaan, is stap 6. Hoe klein dat gat blijft, bepaalt stap 1.

TTL verlagen voordat er iets anders gebeurt

De TTL vertelt resolvers wereldwijd hoe lang ze een antwoord mogen bewaren. Staat die op 86400, dan kan een resolver uw oude IP-adres nog 24 uur lang blijven uitleveren nadat u hebt omgezet. En dit wordt graag over het hoofd gezien: een verlaagde TTL werkt pas nadat de oude TTL is verlopen. Gaat u van 86400 naar 300, dan kan het een dag duren voordat alle resolvers de korte waarde kennen.

Daarom is dit de eerste handeling en niet de laatste. dig hoort op geen enkele distributie bij de basisinstallatie en is in deze handleiding voortdurend nodig, installeer het dus als eerste:

apt install -y bind9-dnsutils

Op Debian 11, Ubuntu 22.04 en Ubuntu 24.04 heet het pakket nog dnsutils. Vanaf Debian 12 is dnsutils alleen nog een overgangspakket dat naar bind9-dnsutils verwijst, op Debian 13 zelfs een puur virtueel pakket zonder eigen versie. Allebei werken ze, want apt lost de enige aanbieder zelf op, maar bind9-dnsutils is de naam die blijft. Controleer daarna de huidige waarde:

dig +noall +answer example.com A
dig +noall +answer example.com SOA

Het getal in de tweede kolom van het A-antwoord is de resterende TTL. Vraag het rechtstreeks na bij de autoritatieve nameserver, anders ziet u alleen de restwaarde uit de cache van uw eigen resolver:

dig @a.ns14.net example.com A +noall +answer

Zet de TTL na de verhuizing weer omhoog, naar 3600 of meer. Permanent korte TTL's zorgen voor onnodige belasting en maken storingen bij uw DNS-provider langer voelbaar.

De nieuwe server passend inrichten

Hier ontstaan de meeste vervelende verrassingen, want de distributie op de nieuwe server levert andere versies dan de oude. Alle pakketcommando's in deze handleiding gaan uit van Debian of Ubuntu. Op AlmaLinux, Rocky Linux en Oracle Linux bestaat apt niet en wijken de pakketnamen af. Stand juli 2026 ziet het er zo uit:

SysteemPHPDatabasenginx
Debian 138.4MariaDB 11.8 (geen mysql-server)1.26.3
Debian 128.2MariaDB 10.111.22.1
Ubuntu 24.048.3MySQL 8.0.46 of MariaDB 10.111.24.0
Ubuntu 22.048.1MySQL 8.0.46 of MariaDB 10.61.18.0

Daaruit volgen twee dingen. Ten eerste: op Debian krijgt u geen mysql-server, daar draait altijd MariaDB. Draaide de oude site op MySQL 8, dan is de verhuizing naar Debian tegelijk een databasewissel, met een heel concrete valkuil verderop. Ten tweede: de sprong van PHP 8.1 naar 8.4 gaat niet vanzelf. Oudere thema's en plugins reageren op verwijderde functies met een Fatal error: Uncaught Error: Call to undefined function of met een witte pagina. Draaide de oude installatie op PHP 8.1 en wilt u de verhuizing niet aan een PHP-upgrade koppelen, dan is Ubuntu 22.04 of een PHP-versie uit een externe pakketbron de rustigere keuze. Wat bewust in de tabel ontbreekt, is Debian 11: daar levert php-cli nog PHP 7.4.33, dus een versie zonder beveiligingsonderhoud en onder wat WordPress aanraadt. Als doel van een verhuizing valt Debian 11 daarmee af, tenzij u vooraf de Sury-pakketbron toevoegt.

De basispakketten voor een typische installatie met nginx en PHP-FPM:

apt update
apt install -y nginx php-fpm php-mysql php-xml php-curl php-mbstring php-zip php-gd php-intl
apt install -y mariadb-server mariadb-client rsync curl

Details over de webserver staan in de nginx-handleiding, de basisbeveiliging van de database in MariaDB en MySQL beveiligen. Is de server gloednieuw, dan loont vooraf een blik in de checklist voor nieuwe rootservers.

Maak de database en de gebruiker aan, met dezelfde tekenset als op de bron:

CREATE DATABASE wp_nieuw CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp_nieuw'@'localhost' IDENTIFIED BY 'een-lang-wachtwoord';
GRANT ALL PRIVILEGES ON wp_nieuw.* TO 'wp_nieuw'@'localhost';
FLUSH PRIVILEGES;

Bestanden overzetten zonder de rechten te slopen

Er wordt rechtstreeks van server naar server gekopieerd, niet via uw eigen aansluiting thuis. Het eenvoudigst gaat dat met rsync van de oude naar de nieuwe server, met een SSH-sleutel in plaats van een wachtwoord:

rsync -az --delete --exclude 'wp-content/cache/' --exclude 'wp-content/uploads/backup*' \
  -e 'ssh -p 22' /var/www/html/ root@nieuwe.ip:/var/www/html/

De eerste doorloop mag lang duren. Precies daarom draait u die dagen vóór de omschakeling, en vlak ervoor nog één keer hetzelfde commando, dat dan alleen de verschillen overzet.

Na het kopiëren moeten eigenaar en rechten worden rechtgezet, want UID's verschillen per systeem en rsync zet getallen over, geen namen:

chown -R www-data:www-data /var/www/html
find /var/www/html -type d -exec chmod 755 {} \;
find /var/www/html -type f -exec chmod 644 {} \;
chmod 640 /var/www/html/wp-config.php

Twee bestanden gaan er vóór de eerste start uit, als ze aanwezig zijn: wp-content/object-cache.php en wp-content/advanced-cache.php. Beide zijn drop-ins van cacheplugins die naar een Redis- of Memcached-socket wijzen die op de nieuwe server nog niet bestaat. Het resultaat zou een witte pagina zijn, zonder bruikbare melding.

De database overzetten en de valkuil met de collation

De dump maakt u met WP-CLI of op de klassieke manier. WP-CLI heeft het voordeel dat het tekenset en prefix uit wp-config.php haalt:

cd /var/www/html
wp db export /root/wp-dump.sql --add-drop-table

Zonder WP-CLI: op een actueel MariaDB-systeem heet het gereedschap mariadb-dump. De oude naam mysqldump is vanaf MariaDB 11.0 nog slechts een verouderde symlink en meldt zich met Deprecated program name. It will be removed in a future release:

mariadb-dump --single-transaction --default-character-set=utf8mb4 wp_oud > /root/wp-dump.sql

Dan nu de plek waar een verhuizing van Ubuntu met MySQL 8 naar Debian met MariaDB regelmatig onderuitgaat. MySQL 8 gebruikt standaard de collation utf8mb4_0900_ai_ci, die in MariaDB helemaal niet bestaat. De import breekt af met:

ERROR 1273 (HY000) at line 42: Unknown collation: 'utf8mb4_0900_ai_ci'

Repareer dat vóór de import, rechtstreeks in de dump:

sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g; s/utf8mb4_0900_as_cs/utf8mb4_unicode_ci/g' /root/wp-dump.sql
grep -c utf8mb4_unicode_ci /root/wp-dump.sql

Daarna importeren:

mariadb --default-character-set=utf8mb4 wp_nieuw < /root/wp-dump.sql

Staat er na de import overal geïnstalleerd in plaats van geïnstalleerd, dan is de tekenset bij de dump of bij de import verloren gegaan. Dat repareert u niet met zoeken en vervangen, maar door dump en import over te doen met --default-character-set=utf8mb4. Precies daarom staat de oude database op dit moment nog onaangeroerd klaar.

Pas daarna op de nieuwe server de inloggegevens in wp-config.php aan: DB_NAME, DB_USER, DB_PASSWORD, en heel belangrijk DB_HOST, mocht de oude installatie naar een externe databaseserver hebben gewezen. Blijft daar het oude adres staan, dan krijgt u Error establishing a database connection te zien, terwijl lokaal alles draait. Klemt de verbinding ondanks correcte gegevens, dan helpt Access denied for user oplossen.

Het domein vervangen, en waarom een SQL-replace de site sloopt

Eerst het goede nieuws: verandert alleen de server en blijft het domein gelijk, dan hoeft u in de database helemaal niets te vervangen. Dat is precies een van de redenen waarom de test via het hosts-bestand beter is dan een test via een tijdelijk domein. Vervangen is alleen nodig als het domein werkelijk wisselt, als u de verhuizing combineert met de stap van http naar https, of als u toch met een testdomein werkt en achteraf moet terugvervangen.

En nu de reden waarom u dat nooit met een eenvoudig SQL-commando doet. WordPress slaat opties, widgetinstellingen en themaconfiguraties op als geserialiseerde PHP-arrays. Een URL staat daarin niet kaal, maar met de bytelengte ervoor:

s:19:"https://example.com"

Vervangt u example.com via UPDATE ... REPLACE() door nieuw-domein.nl, dan wordt de string langer terwijl het getal 19 blijft staan. PHP kan de array daarna niet meer uitpakken, unserialize() geeft false terug en de betreffende instelling is weg. Typische symptomen: widgets verdwenen, thema-opties teruggezet, lege menu-items, en in de logbestanden Notice: unserialize(): Error at offset.

WP-CLI lost dat wel goed op, want het pakt de gegevens uit, vervangt ze en schrijft ze met een gecorrigeerde lengte terug. Altijd eerst met --dry-run:

wp search-replace 'https://oud-domein.nl' 'https://nieuw-domein.nl' --all-tables --precise --dry-run --report-changed-only

Wat de losse opties doen: --all-tables pakt ook tabellen aan die de WordPress-prefix niet volgen, bijvoorbeeld van webshop- of formulierplugins. --precise dwingt verwerking in PHP af in plaats van in SQL, is trager, maar gaat betrouwbaar om met geserialiseerde gegevens. --report-changed-only kort de uitvoer in tot de tabellen met echte treffers.

Ziet de voorvertoning er plausibel uit, laat dan hetzelfde commando zonder --dry-run lopen. Daarna volgt de doorloop die bijna alle handleidingen overslaan: page builders zoals Elementor bewaren hun inhoud als JSON in de database, en daar zijn de schuine strepen gemaskeerd. Een vervanging van https://oud-domein.nl vindt https:\/\/oud-domein.nl eenvoudigweg niet. Vandaar een tweede doorloop:

wp search-replace 'https:\/\/oud-domein.nl' 'https:\/\/nieuw-domein.nl' --all-tables --precise --report-changed-only

Bij Elementor hoort daarna in de backend onder Gereedschap het opnieuw genereren van de CSS-bestanden erbij, anders blijven de gegenereerde stylesheets naar het oude domein wijzen.

Twee dingen bereikt search-replace niet: constanten in wp-config.php en multisite. Staat daar define('WP_HOME', 'https://oud-domein.nl');, dan overschrijft dat elke waarde uit de database en zoekt u urenlang op de verkeerde plek. Bij multisite hebt u bovendien --network nodig en moet u de domeinen in wp_blogs en wp_site aanpassen.

En een waarschuwing over de tabelprefix: verander die niet tijdens de verhuizing. De prefix zit ook in de optienaam wp_user_roles en in de gebruikersmetavelden wp_capabilities en wp_user_level. Wie alleen de tabellen hernoemt, kan weliswaar nog inloggen, maar krijgt daarna Sorry, you are not allowed to access this page. en heeft geen beheerder meer.

Certificaat uitgeven voordat DNS ernaartoe wijst

Hier zit een kip-en-eiprobleem. De gebruikelijke HTTP-validatie van Let's Encrypt eist dat de domeinnaam al naar de validerende server wijst. Dat doet hij op dit moment nog niet, want hij moet de oude site nog uitleveren. Wie toch certbot --nginx start, krijgt:

Certbot failed to authenticate some domains (authenticator: nginx).
Invalid response from http://example.com/.well-known/acme-challenge/...: 404

De nette uitweg is de DNS-validatie. Die controleert een TXT-record _acme-challenge.example.com en trekt zich niets aan van de vraag waar het A-record naartoe wijst:

certbot certonly --manual --preferred-challenges dns -d example.com -d www.example.com

Certbot toont een waarde die u als TXT-record in uw DNS-zone vastlegt. Kijk vóór het bevestigen beslist zelf na of de zone het record al uitlevert, anders verspilt u een mislukte poging:

dig +short TXT _acme-challenge.example.com

Bij wildcarddomeinen of als u dit wilt automatiseren, staat de weg via de DNS-API in het artikel over het wildcardcertificaat. De handmatige variant vernieuwt zichzelf niet, dus schakelt u na de DNS-omschakeling over op de gewone HTTP-validatie. Vanaf dat moment werkt die wel, want het domein wijst nu naar de nieuwe server.

Testen met het hosts-bestand, als een echte bezoeker

Nu volgt het deel dat het verschil maakt tussen "zou moeten werken" en "werkt". U stuurt alleen uw eigen computer naar de nieuwe server, terwijl de rest van de wereld nog de oude site ziet.

Onder Linux en macOS bewerkt u /etc/hosts als root, onder Windows C:\Windows\System32\drivers\etc\hosts in een als beheerder gestarte editor. Voeg een regel toe met het IP-adres van de nieuwe server:

203.0.113.10 example.com www.example.com

Leeg daarna de DNS-cache, anders werkt de wijziging niet meteen door:

resolvectl flush-caches

Onder Windows is dat ipconfig /flushdns, onder macOS sudo dscacheutil -flushcache gevolgd door sudo killall -HUP mDNSResponder. Controleer of het effect heeft gehad:

getent hosts example.com

Een valkuil die veel uren kost: Firefox met DNS over HTTPS ingeschakeld negeert het hosts-bestand. Mozilla heeft dat uitdrukkelijk als "wontfix" gemarkeerd. U blijft dan de oude site zien en houdt de test voor mislukt, terwijl de nieuwe server allang correct antwoordt. Schakel daarom in de testbrowser de versleutelde DNS-resolutie uit, of beter nog: controleer los van de browser. curl kan de resolutie per aanroep overschrijven, helemaal zonder hosts-bestand:

curl -sI --resolve example.com:443:203.0.113.10 https://example.com/

Wat u in deze toestand zou moeten nalopen: de startpagina, minstens twee onderliggende pagina's, een bericht met afbeeldingen, de login op /wp-login.php, de backend, een contactformulier en bij een webshop een testartikel tot aan de kassa. Afbeeldingen verdienen extra aandacht, want ontbrekende uploads vallen in de backend niet op.

Wat de hosts-test uitdrukkelijk niet afdekt: alles wat van buitenaf de server benadert. Webhooks van betaaldiensten, externe cronjobs, crawlers van zoekmachines en uw e-mailverzending komen nog steeds bij de oude bestemming uit. Dat is prima, u moet het alleen weten.

De omschakeling: delta-sync en DNS

Tussen de eerste kopieerslag en de omschakeling zijn er reacties, bestellingen of berichten bij gekomen. De volgorde voor een schone omschakeling:

  1. Zet op de oude server de onderhoudsmodus aan, of stop op zijn minst even de bestellingen en reacties.
  2. Synchroniseer de bestanden opnieuw, deze keer duurt het seconden.
  3. Exporteer de database opnieuw en importeer die op de nieuwe server.
  4. Leeg de caches: wp cache flush en wp rewrite flush --hard.
  5. Controleer nogmaals met curl tegen het nieuwe IP-adres.
  6. Zet het A- en het AAAA-record om.

Vergeet het AAAA-record niet. Blijft dat op het oude IPv6-adres staan, dan komen alle bezoekers met IPv6 nog steeds op de oude server terecht, terwijl bezoekers via IPv4 de nieuwe site zien. Dat levert precies het soort foutbeeld op waarbij twee mensen naast elkaar zitten en verschillende websites voor zich hebben.

De oude server laat u minstens een week draaien, zonder wijzigingen. Hij is uw weg terug en uw archief.

Waaraan u ziet dat het echt gelukt is

Niet "de site laadt", maar meetbare bewijzen:

dig +short A example.com
dig +short AAAA example.com
curl -sI https://example.com/ | head -n 12

In de header mag geen 301 naar een oud domein of naar http:// staan. Vraag daarna de database welk adres WordPress zelf voor het juiste houdt:

wp option get siteurl
wp option get home

Een betrouwbare test op vergeten restanten is een zoekopdracht in de proefmodus. Meldt die nul vervangingen, dan staat het oude adres werkelijk nergens meer vastgelegd:

wp search-replace 'oud-domein.nl' 'oud-domein.nl' --all-tables --dry-run --report-changed-only

Controleer daarbij ook het certificaat, inclusief looptijd en de namen die het dekt:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject

En tot slot het foutlogbestand van de webserver, terwijl u vijf minuten door de site klikt. Duikt daar niets nieuws op, dan bent u klaar. Hapert er toch iets, dan is 502 Bad Gateway oplossen het meest voor de hand liggende aanknopingspunt, meestal omdat de PHP-FPM-socket in het nginx-blok nog het pad van de oude PHP-versie bevat.

Als het misgaat: de weg terug

De weg terug bestaat uit één enkele handeling, en daarom was stap 1 zo belangrijk: zet het A- en het AAAA-record terug op het oude IP-adres. Bij een TTL van 300 seconden zitten de meeste bezoekers binnen vijf minuten weer op de oude server, die ongewijzigd is blijven draaien.

Er is precies één geval waarin dat niet schoon verloopt: wanneer op de nieuwe server al gegevens zijn ontstaan die op de oude ontbreken. Nieuwe bestellingen, reacties, registraties. Na een rollback bestaan die gegevens alleen nog in het nieuwe systeem. Daarom beslist u binnen de eerste minuten of helemaal niet. En daarom die onderhoudsmodus tijdens de omschakeling: die houdt het tijdvenster klein waarin beide gegevensverzamelingen uit elkaar kunnen gaan lopen.

Moet u toch later terug, exporteer dan van de nieuwe server alleen de betrokken tabellen en speel die op de oude in, in plaats van de complete database terug te schuiven. Een kale rollback via een oude volledige back-up wist alles wat er in de tussentijd is gebeurd.

Foutmeldingen letterlijk

Error establishing a database connection
De inloggegevens of DB_HOST in wp-config.php passen niet bij de nieuwe server. Vaak staat daar nog het IP-adres van een externe databaseserver in plaats van localhost.

ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci'
Een dump uit MySQL 8 wordt in MariaDB geïmporteerd. Zet de collation in de dump met sed op utf8mb4_unicode_ci.

Error: This does not seem to be a WordPress installation.
WP-CLI is in de verkeerde map gestart, of de bestanden staan niet waar u ze vermoedt. Werk met --path=/var/www/html.

ERR_TOO_MANY_REDIRECTS
Bijna altijd een tegenstrijdigheid tussen siteurl in de database, een constante in wp-config.php en de doorverwijzing in de webserver. Daarnaast treft het installaties achter een proxy die de HTTPS-status niet meekrijgen en daardoor eindeloos van http naar https en terug sturen.

De startpagina laadt, alle onderliggende pagina's geven 404
De klassieker bij de overstap van Apache naar nginx. De .htaccess met de permalinkregels wordt door nginx genegeerd, daar is try_files $uri $uri/ /index.php?$args; in het location-blok nodig.

Het geüploade bestand overschrijdt de upload_max_filesize-instructie in php.ini.
De PHP-configuratie is niet mee verhuisd. Zet upload_max_filesize, post_max_size en memory_limit op de waarden van de oude server.

Witte pagina, geen regel in het logbestand
Meestal een drop-in die naar het niets wijst: wp-content/object-cache.php of advanced-cache.php. Hernoemen en opnieuw laden.

Een verhuizing die zo verloopt, kent geen tijdvenster zonder website. Het enige merkbare moment is de DNS-wissel, en de duur daarvan hebt u twee dagen eerder zelf bepaald.

Veelgestelde vragen

Hoe lang duurt het voordat de DNS-omzetting overal doorwerkt?
Dat hangt uitsluitend af van de TTL die vóór de omzetting gold. Bij 300 seconden zijn praktisch alle resolvers binnen vijf tot tien minuten omgeschakeld. Bij 86400 kan het een hele dag duren. Omdat een verlaagde TTL pas werkt nadat de oude is verlopen, verlaagt u die 24 tot 48 uur vóór de verhuizing.
Waarom mag ik het domein niet gewoon met een SQL-commando in de database vervangen?
WordPress slaat veel instellingen op als geserialiseerde PHP-arrays, waarin vóór elke tekst de bytelengte staat, bijvoorbeeld s:19:"https://example.com". Een REPLACE() verandert de tekst, maar niet die lengte. PHP kan de array daarna niet meer uitpakken en de instelling is verloren. WP-CLI pakt uit, vervangt en serialiseert opnieuw, en daarom is wp search-replace de juiste weg.
Moet ik het domein wel vervangen als alleen de server wisselt?
Nee. Blijft het domein identiek, dan verandert er in de database niets. Vervangen is alleen nodig bij een echte domeinwissel, bij een gelijktijdige overstap van http naar https, of wanneer u via een testdomein hebt gewerkt en achteraf moet terugvervangen.
Hoe kom ik aan een Let's Encrypt-certificaat als het domein nog naar de oude server wijst?
Via de DNS-validatie in plaats van de HTTP-validatie: certbot certonly --manual --preferred-challenges dns -d example.com. Gecontroleerd wordt een TXT-record onder _acme-challenge, het A-record speelt daarbij geen rol. Na de DNS-omzetting schakelt u over op de automatische HTTP-validatie, zodat de vernieuwing zonder handwerk verloopt.
Ik heb het hosts-bestand aangepast, maar zie nog steeds de oude site. Hoe kan dat?
Ofwel is de DNS-cache van het besturingssysteem nog warm, dan helpt ipconfig /flushdns, resolvectl flush-caches of dscacheutil -flushcache. Ofwel lost uw browser zelf op via DNS over HTTPS. Firefox negeert het hosts-bestand in die stand aantoonbaar. Betrouwbaar is de controle met curl en --resolve, die de browser volledig omzeilt.
Wat is de snelste weg terug als er na de omzetting iets niet werkt?
Zet het A- en het AAAA-record terug op het oude IP-adres. De oude server draait immers ongewijzigd verder. Bij een korte TTL zitten de meeste bezoekers binnen enkele minuten weer daar. Het addertje: gegevens die inmiddels alleen op de nieuwe server zijn ontstaan, bijvoorbeeld bestellingen, ontbreken dan op de oude. Daarom houdt u het tijdvenster met een korte onderhoudsmodus klein en beslist u snel.

WordPress Servermigratie DNS WP-CLI MariaDB Let's Encrypt VPS