Guide to Migrating a WordPress Site to another Ubuntu 24.04 instance
Initial Steps:
-
Update the Package List:
First, update and upgrade the packages on both the old and new servers:
sudo apt update && sudo apt dist-upgrade -y
Install Required Packages on the New Server:
-
Install Apache, MySQL, and PHP (LAMP stack):
On the new server (DigitalOcean or AWS EC2):
sudo apt install apache2 mysql-server php libapache2-mod-php php-mysql php-xml php-mbstring php-curl -y
Obtain an SSL Certificate
To secure your site with HTTPS, you'll need an SSL certificate. We will use Certbot, a free tool provided by Let’s Encrypt, to manage the SSL certificates. First, install Certbot:
sudo apt install software-properties-common
sudo add-apt-repository universe
sudo apt update
sudo apt install certbot python3-certbot-nginx
---
### **Setting Up Permissions for `/var/www` and Web Files:**
**Note**
This section covers the recommended permissions setup for web directories and files on a Linux server, specifically for `/var/www` and `/var/www/example.com`. Ensure these permissions are applied during file migration and server setup to maintain security and proper functionality.
---
#### **Permissions Setup for `/var/www` and `/var/www/example.com`:**
1. **`/var/www` Directory:**
- **Owner:** `root`
- **Group:** `www-data`
- **Permissions:** `755`
Commands:
```bash copy
sudo chown root:www-data /var/www
sudo chmod 755 /var/www
-
/var/www/example.com
Directory:- Owner:
www-data
- Group:
www-data
- Permissions for directories:
755
- Permissions for files:
644
Commands:
sudo chown -R www-data:www-data /var/www/example.com sudo find /var/www/example.com -type d -exec chmod 755 {} \; sudo find /var/www/example.com -type f -exec chmod 644 {} \;
- Owner:
Nginx Configuration:
-
Add the Site to Nginx:
You can either create a new config based on Chapter 3 or copy the existing configuration. It's recommended to copy the existing configuration for consistency. Also, if permissions need to be changed temporarily as we did earlier, you can do the same.
On the old server, if permission changes are needed and folder moving is required :
sudo chown user:user /etc/nginx/sites-available/example.com sudo cp /etc/nginx/sites-available/example.com ~/
Copy the configuration file from the old server:
scp -r user@example.com:~/example.com ~/
Move the file to the Nginx configuration directory and set ownership:
sudo mv example.com /etc/nginx/sites-available sudo chown root:root /etc/nginx/sites-available/example.com
Enable the site by creating a symlink:
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
Reference for Nginx file ownership and permissions so we can set it back when needed:
Nginx File Ownership and Permissions
Overview
Files and directories in /etc/nginx/
should be owned by root
to maintain system security.
Permissions and Ownership
Directories
-
Path:
/etc/nginx/
,/etc/nginx/sites-available/
,/etc/nginx/sites-enabled/
-
Owner:
root
-
Group:
root
-
Permissions:
755
sudo chown root:root /etc/nginx sudo chmod 755 /etc/nginx
Files
-
Path:
/etc/nginx/nginx.conf
,/etc/nginx/sites-available/example.com
-
Owner:
root
-
Group:
root
-
Permissions:
644
sudo chown root:root /etc/nginx/nginx.conf sudo chmod 644 /etc/nginx/nginx.conf
sudo chown root:root /etc/nginx/sites-available/example.com sudo chmod 644 /etc/nginx/sites-available/example.com
Summary
- Directories:
755
permissions forroot
ownership - Files:
644
permissions forroot
ownership
SSL Certificates:
-
Copy SSL Certificates:
On the old server, if you encounter issues with
scp
and need to unlink symbolic links temporarily, follow these steps:Unlink symbolic links:
sudo rm /etc/letsencrypt/live/example.com/chain.pem sudo rm /etc/letsencrypt/live/example.com/fullchain.pem sudo rm /etc/letsencrypt/live/example.com/privkey.pem
Change ownership and copy the SSL certificates to your home directory:
sudo chown user:user /etc/letsencrypt/live/example.com sudo cp /etc/letsencrypt/archive/example.com/*.pem
Ensure your SSH user has access:
sudo chown user *.pem
Copy the certificates to the new server:
scp -r user@example.com:~/*.pem ~/
Once transferred, on the old server, restore the symbolic links and change ownership back to root:
sudo ln -s /etc/letsencrypt/archive/example.com/chain1.pem /etc/letsencrypt/live/example.com/chain.pem sudo ln -s /etc/letsencrypt/archive/example.com/fullchain1.pem /etc/letsencrypt/live/example.com/fullchain.pem sudo ln -s /etc/letsencrypt/archive/example.com/privkey1.pem /etc/letsencrypt/live/example.com/privkey.pem sudo chown root:root /etc/letsencrypt/live/example.com
On the new Server:
we will create the /etc/letsencrypt path and move the certs there and change owner to root then a symbolic link so it's the same setup:
sudo mkdir -p /etc/letsencrypt/live/example.com/
sudo mkdir -p /etc/letsencrypt/archive/example.com/
sudo mv ~/*.pem /etc/letsencrypt/archive/wpdev.yourbestbuystore.com/
sudo chown -R root:root /etc/letsencrypt/
sudo ln -s /etc/letsencrypt/archive/example.com/chain1.pem /etc/letsencrypt/live/example.com/chain.pem
sudo ln -s /etc/letsencrypt/archive/example.com/fullchain1.pem /etc/letsencrypt/live/example.com/fullchain.pem
sudo ln -s /etc/letsencrypt/archive/example.com/privkey1.pem /etc/letsencrypt/live/example.com/privkey.pem
Now we will change the permissions:
sudo find /etc/letsencrypt/ -type d -exec chmod 755 {} \;
sudo find /etc/letsencrypt/ -type f -exec chmod 644 {} \;
Note:
The permissions of a symlink don’t impact access; they only indicate the symlink's own attributes. Access to the actual file is determined by the file’s permissions. If the target file has 644
permissions, users can read it but only the owner can write to it, regardless of the symlink's permissions.
As we kept the same folder structure we do not need to update the Nginx configuration on the new server as the certificate paths we copied over are the same.
Test the Nginx configuration:
sudo nginx -t
Reload Nginx:
sudo service nginx reload
Spoof DNS for Testing:
-
Spoof DNS:
Add an entry to your
/etc/hosts
file to test the new server:sudo vim /etc/hosts
Add:
NEW_SERVER_IP example.com
Save the file and refresh the site. You should see “Error establishing a database connection” if the database is not yet migrated.
Note: After updating the DNS, you will need to SSH to the new server using its IP address.
File Migration Steps:
-
Backup the Database on the Old Server:
Use
mysqldump
to back up the database:mysqldump --no-tablespaces -u DB_USER -p DB_NAME > ~/backup.sql
Enter the password when prompted.
-
Copy the Site Files:
Temporarily change ownership of the files for migration:
sudo chown -R your_user:your_user /var/www/example.com cp -R /var/www/example.com/ ~/ sudo chown -R root:root /var/www/example.com
Use
scp
to transfer files from the old server to the new server:scp -r user@old_server_ip:/home/user/example.com ~/
After transferring, adjust ownership and move the files:
sudo chmod 755 example.com/ sudo chown root:www-data example.com/ sudo mv example.com/ /var/www/
Database Restoration on New Server:
-
Restore the Database on the New Server:
After transferring the backup file (
backup.sql
), restore it on the new server:mysql -u DB_USER -p DB_NAME < ~/backup.sql
Set Up MySQL for the First Time on the New Server
-
Run the Secure Installation Script
sudo mysql_secure_installation
Follow the prompts to set the
root
password and secure your installation. -
Create a New Database and User
Log into MySQL as the root user:
sudo mysql -u root -p
Then, create a new database and user:
CREATE DATABASE wordpress; CREATE USER 'wordpress_user'@'localhost' IDENTIFIED BY 'secure_password'; GRANT ALL PRIVILEGES ON wordpress.* TO 'wordpress_user'@'localhost'; FLUSH PRIVILEGES;
-
Check MySQL User Permissions
Ensure that the
DB_USER
has the correct permissions:SHOW GRANTS FOR 'DB_USER'@'localhost';
Troubleshooting mysqldump Error (Access denied for user
)
If you encounter an error with mysqldump
such as:
mysqldump: Got error: 1045: Access denied for user 'DB_USER'@'localhost' (using password: YES) when trying to connect
-
Verify MySQL User Permissions
Log into MySQL:
sudo mysql -u DB_USER -p
Check the permissions:
SHOW GRANTS FOR 'DB_USER'@'localhost';
-
Reset MySQL User Password if Necessary
If you forgot the password, log in as
root
and reset it:ALTER USER 'DB_USER'@'localhost' IDENTIFIED
BY 'new_password'; FLUSH PRIVILEGES;
3. **Ensure the Correct Password is Used with `mysqldump`**
When using `mysqldump`, avoid typing the password in the command:
```bash copy copy
mysqldump --no-tablespaces -u DB_USER -p DB_NAME > ~/export.sql
Enter the password when prompted.
Here’s how you can integrate the steps for migrating with minimum downtime into your existing Markdown documentation:
## **Guide to Migrating a WordPress Site to another Ubuntu 24.04 instance**
### **Initial Steps:**
1. **Update the Package List:**
First, update and upgrade the packages on both the old and new servers:
```bash
sudo apt update && sudo apt dist-upgrade -y
Install Required Packages on the New Server:
-
Install Apache, MySQL, and PHP (LAMP stack):
On the new server (DigitalOcean or AWS EC2):
sudo apt install apache2 mysql-server php libapache2-mod-php php-mysql php-xml php-mbstring php-curl -y
Setting Up Permissions for /var/www
and Web Files:
Note
This section covers the recommended permissions setup for web directories and files on a Linux server, specifically for /var/www
and /var/www/example.com
. Ensure these permissions are applied during file migration and server setup to maintain security and proper functionality.
Permissions Setup for /var/www
and /var/www/example.com
:
-
/var/www
Directory:- Owner:
root
- Group:
www-data
- Permissions:
755
Commands:
sudo chown root:www-data /var/www sudo chmod 755 /var/www
- Owner:
-
/var/www/example.com
Directory:- Owner:
www-data
- Group:
www-data
- Permissions for directories:
755
- Permissions for files:
644
Commands:
sudo chown -R www-data:www-data /var/www/example.com sudo find /var/www/example.com -type d -exec chmod 755 {} \; sudo find /var/www/example.com -type f -exec chmod 644 {} \;
- Owner:
Nginx Configuration:
-
Add the Site to Nginx:
You can either create a new config based on Chapter 3 or copy the existing configuration. It's recommended to copy the existing configuration for consistency. Also, if permissions need to be changed temporarily as we did earlier, you can do the same.
Migrating with Minimum Downtime
On busy sites, it's likely that the database will have changed since performing the previous export. To ensure data integrity, we need to prevent the live site from modifying the database while we carry out the migration. Follow these steps:
-
Update the Live Site to Show a ‘Back Soon’ Message:
Create a
back-soon.html
file with the following content:<!doctype html> <html> <head> <title>Back Soon</title> <style> body { text-align: center; padding: 150px; } h1 { font-size: 50px; } body { background-color: #e13067; font: 20px Helvetica, sans-serif; color: #fff; line-height: 1.5 } article { display: block; width: 650px; margin: 0 auto; } </style> </head> <body> <article> <h1>Back Soon!</h1> <p> We're currently performing server maintenance.<br> We'll be back soon! </p> </article> </body> </html>
Save this as
index.html
, upload it to the web root of your old server, and update Nginx to serve this file instead ofindex.php
:sudo nano /etc/nginx/sites-available/example.com
Ensure that the
index
directive is set as follows:index index.html index.php;
Reload Nginx to apply the changes:
sudo service nginx reload
Your live site will now display the ‘Back Soon’ message. Note that if you're using Nginx FastCGI caching, any cached pages will still be served from the cache, but requests to
admin-ajax.php
and the WordPress REST API will fail. -
Export the Live Database from the Old Server:
Perform the database export as outlined in the previous sections.
-
Import the Live Database to the New Server:
Import the database backup to the new server as previously described.
-
Switch the DNS to Point to the New Server:
Update your DNS records to point to the new server's IP address. Be aware that DNS queries are cached, so some users might still be routed to the old server until their DNS cache expires.
If
using Cloudflare or similar DNS providers, set a low TTL (e.g., 300 seconds) a few days before migration to expedite propagation.
Finishing Up
-
Add a Unix Cron Job:
Ensure that automatic backups are running as scheduled.
-
Generate a New SSL Certificate Using Let’s Encrypt:
Use the
certbot
command to generate a new certificate for your new server.sudo certbot --nginx -d example.com -d www.example.com
-
Verify Everything is Working:
- Test the site thoroughly.
- Confirm that the new server handles traffic correctly and all functionalities are intact.
Once everything is verified and working, you can remove the temporary ‘Back Soon’ page from your old server.
-
Cleanup:
Remove any temporary files or configurations used during migration:
rm ~/example.com
Update your Nginx configuration to reflect any permanent changes needed.
Important: Ensure you restore any original permissions or symbolic links if they were temporarily changed during the migration.
For AWS EC2 users, remember to adjust security groups to allow traffic on the appropriate ports (80 for HTTP, 443 for HTTPS).
Additional Note for AWS EC2 Users:
- Instance Size: Ensure the instance has adequate resources for your site’s traffic.
- Security Groups: Configure security groups to allow necessary traffic (HTTP/HTTPS).
- Elastic IP: Use an Elastic IP to maintain a consistent IP address for your instance.