Migrating a WordPress Site to Google Cloud

Migrating a WordPress Site to Google Cloud

Reading time1 min
#Cloud#WordPress#Hosting#GCP#Migration#Linux

Migrating a WordPress Site to Google Cloud

A WordPress site is two things: the files in the WordPress directory (core, themes, plugins, uploads) and one MySQL or MariaDB database. Moving it means copying both, pointing wp-config.php at the new database, and switching DNS once the new copy works. This post moves a site to a Compute Engine VM, the most direct target for a site coming from shared hosting or another VPS.

Choose the target

  • Compute Engine VM with Apache or Nginx, PHP and MariaDB. Full control, closest to typical hosting, covered below.
  • Cloud Marketplace WordPress image. Same as above with the stack preinstalled. Convenient, but you still own updates.
  • Cloud Run plus Cloud SQL plus Cloud Storage. Scales and needs no VM patching, but WordPress expects a writable local disk, so media uploads need an offload plugin and plugin installs belong in the container image. Worth it for high-traffic sites, too much for a simple move.

Before you start

  • Lower the TTL of the domain's DNS records to 300 seconds a day ahead, so the switch propagates quickly.
  • Note the PHP version and the extensions the site uses (Site Health in the admin shows both).
  • Take a full backup of the old site.

Create the VM

gcloud compute addresses create wp-ip --region=europe-west1

gcloud compute instances create wp-01 \
  --zone=europe-west1-b \
  --machine-type=e2-small \
  --image-family=ubuntu-2404-lts-amd64 --image-project=ubuntu-os-cloud \
  --boot-disk-size=30GB \
  --address=wp-ip \
  --tags=web

gcloud compute firewall-rules create allow-web \
  --network=default --allow=tcp:80,tcp:443 --target-tags=web

The reserved static IP survives VM restarts, which matters because DNS will point at it. e2-small is enough for a small site; resize later if needed.

Connect with gcloud compute ssh wp-01 --zone=europe-west1-b. Add --tunnel-through-iap if you do not want port 22 open to the internet (it needs a firewall rule allowing 35.235.240.0/20 on port 22).

Install the stack

sudo apt update && sudo apt upgrade -y
sudo apt install -y apache2 mariadb-server php libapache2-mod-php php-mysql \
  php-curl php-gd php-mbstring php-xml php-zip php-intl php-imagick unzip
sudo mariadb-secure-installation
sudo a2enmod rewrite

Ubuntu 24.04 ships PHP 8.3. If the old site runs on a much older PHP, update plugins and themes on the old host first, or test carefully on the new one.

Install WP-CLI, which makes the rest easier:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar && sudo mv wp-cli.phar /usr/local/bin/wp

Create the database and user:

sudo mariadb -e "CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'wp'@'localhost' IDENTIFIED BY 'change-me';
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp'@'localhost';"

Export from the old host

With shell access:

cd /var/www/html
wp db export ~/site.sql
tar czf ~/site-files.tar.gz -C /var/www/html .

Without shell access, download the files over SFTP or the hosting panel's file manager and export the database from phpMyAdmin (SQL format). Migration plugins such as All-in-One WP Migration or Duplicator also work when the hosting is very limited, but large sites often hit their upload limits.

Copy and import

From the old host, or from your machine after downloading:

gcloud compute scp site.sql site-files.tar.gz wp-01:~ --zone=europe-west1-b

On the VM:

sudo rm -f /var/www/html/index.html
sudo tar xzf ~/site-files.tar.gz -C /var/www/html
sudo chown -R www-data:www-data /var/www/html
sudo mariadb wordpress < ~/site.sql

Edit /var/www/html/wp-config.php and set DB_NAME, DB_USER, DB_PASSWORD and DB_HOST (localhost) to the new values. Leave the table prefix as it was.

Let Apache honor .htaccess for permalinks. In /etc/apache2/sites-available/000-default.conf, inside the VirtualHost:

<Directory /var/www/html>
    AllowOverride All
</Directory>

Then sudo systemctl reload apache2.

Test before switching DNS

Point the domain at the new IP only on your machine by adding a line to /etc/hosts:

203.0.113.10  example.com www.example.com

Click through the site and the admin, check images, forms, permalinks and anything plugins do on cron. Remove the line afterwards.

If the domain changes as part of the move, replace URLs in the database with WP-CLI, which handles PHP-serialized data correctly (plain SQL REPLACE breaks it):

sudo -u www-data wp search-replace 'https://old.example.com' 'https://example.com' \
  --skip-columns=guid --dry-run

Run it again without --dry-run when the output looks right.

Switch DNS and add HTTPS

If the site takes comments, orders or form submissions, freeze changes on the old site and repeat the database export and import right before switching, so nothing written in between is lost. Then update the A record (and www) to the static IP. Once DNS resolves to the new VM, get a certificate:

sudo apt install -y certbot python3-certbot-apache
sudo certbot --apache -d example.com -d www.example.com

Certbot configures the HTTPS virtual host and a renewal timer. Keep the old hosting for a week in case something was missed.

Email

Compute Engine blocks outbound connections to port 25, so WordPress's default mail() will not deliver. Use an SMTP plugin with a mail provider on port 587, or the provider's API.

Backups and upkeep

  • Attach a daily snapshot schedule to the boot disk (see Backing Up to Google Cloud Storage).
  • Dump the database to a bucket nightly with sudo -u www-data wp --path=/var/www/html db export - | gcloud storage cp - gs://my-backups/wp/$(date +%F).sql.
  • Turn on unattended security upgrades for the OS, and keep WordPress, themes and plugins updated.
  • For more traffic or less maintenance, move the database to Cloud SQL and put Cloud CDN in front of a load balancer later.

Quick reference

# old host
wp db export site.sql && tar czf site-files.tar.gz -C /var/www/html .
# new VM
sudo tar xzf site-files.tar.gz -C /var/www/html && sudo chown -R www-data:www-data /var/www/html
sudo mariadb wordpress < site.sql
sudo -u www-data wp search-replace 'https://old.example.com' 'https://example.com' --skip-columns=guid
sudo certbot --apache -d example.com -d www.example.com