Programming interview questions

Looking for good programming/interview questions?

Use the search below to find our solutions for selected questions!

Migrating WordPress site from a legacy hosting provider to AWS

Sharing is caring!

Up until now my blog (lucaslouca.com) was hosted on a traditional/old fashioned hosting provider, Their service provided a fixed 10GB of hosting storage together with FTP access and a cPanel.

So here are the reasons why I switched over to AWS:
– Less expensive
– More flexible due to the fact that you can launch unlimited virtual servers, database instances, configure firewalls, load balancers, etc
– More security: my database isn’t publicly available anymore and sits in a VPC, better user management
– Literally thousands of services from CloudWatch to Lambda

Overall using AWS you have more control over your web applications.

So lets get started with the migration process!

We are going to do the following:
• Setup an EC2 instance using a Basic 64-bit Amazon Linux AMI
• Setup a S3 bucket
• Setup a MySQL RDS Instance
• Migrate old MariaDB database to new AWS DB Instance
• Install Apache Web Server, MySql, PHP, Git and Python on EC2 instance
• Install WordPress on EC2 instance
• Issue a Let’s Encrypt certificate
• Configure Apache Web Server on EC2 for HTTPS

Create an S3 bucket
We will first create an S3 bucket that we can use to store any database dumps and files so we can access them through our new EC2 instance.

To create a new instance, access the AWS Management Console and click the S3 tab. Create a new bucket and give it a name. Mine is named lucaslouca.com-wordpress.

Create an EC2 instance
To create a new instance, access the AWS Management Console and click the EC2 tab:

  • Choose an AMI in the classic instance wizard: I chose the Basic 64-bit Amazon Linux AMI.
  • Instance details: Select the Instance Type you want to use. I chose t2.micro.
  • Create a new key pair. Enter a name for your key pair (i.e. lucasloucacom) and download your key pair (i.e. lucasloucacom.pem).
  • Make sure you create a new security group, give it a name (e.g. lucaslouca.com-security-group) and add inbound rules for SSH, HTTP and HTTPS that allow traffic from all sources.
  • Launch your instance.

Note:For security purposes you can edit the inbound rule for SSH to allow traffic only from your IP address.

Map IP Address and Domain Name
Your EC2 instance has an IP address as well as a DNS name. However, the default IP address is assigned dynamically and might change. You will keep the IP address as long as the instance is running and across reboots, but if you are forced to stop/start or anything like that you will lose it. If you have a domain name pointing to your instance, that is a bad thing. Thats why we need to associate an IP address to our instance and then map your domain name to that IP address.

To associate an IP address to your instance:
In the AWS Management Console, click Elastic IPs (left navigation bar). Click Allocate New Address, and confirm by clicking the Yes, Allocate button.
Select the newly allocated IP address and select Actions -> Associate address in the popup menu. Select the EC2 instance and click Yes, Associate

Note down the new Public DNS (e.g. ec2-35-158-16-195.eu-central-1.compute.amazonaws.com) of our EC2 instance. We will need it later.

Then, go to Route 53-> Hosted zones-> Create Hosted Zone. Amazon will list you four NS servers:

Note them down and login to your domain registrar. Under the DNS Manager delete the NS entries and any A records pointing to your web server. In my domain registrar I have deleted the NS and A entries and edited the names servers for my domain lucaslouca.com to point to the Route 53 provided name servers instead of my hosting providers defaults.

Back in the AWS console go to Route 53-> Hosted zones and select your newly created zone. Click on Create Record Set to setup some A records. Leave Alias to No and paste the elastic IP address of your EC2 instance into the value field. This will create a new A record pointing the domain name lucaslouca.com to the IP 35.158.16.195. You can repeat this for any subdomains also. For example you can click on Create Record Set again and under Name enter www, Alias set to Yes and from the Alias Target target you can select the previously created record (e.g. lucaslouca.com). That way www.lucaslouca.com will also point to the same IP as lucaslouca.com.

Install Updates, Apache Web Server, MySql, PHP, etc
Once the instance is up and running go ahead and ssh to your EC2 instance:

In order to install the required tools and updates run the following commands:

Create a DB instance
Next, we are going to need a MySQL database for our blog.

To create a new instance, access the AWS Management Console and click the Database -> RDS tab. Then click Launch a DB Instance and select MySQL.

Then specify a username, password and database name and make sure Publicly Accessible is set to NO. Make sure you also create a new security group.

Once the instance is created, select it and under Configuration Details click on the security group (e.g. rds-launch-wizard-3). Edit the inbound rules for that group and set the Source for the MYSQL/Aurora type to the security group you created earlier for your EC2 instance (e.g. lucaslouca.com-security-group). This will allow only traffic in that comes from the security group lucaslouca.com-security-group. In other words only traffic that comes from our EC2 web server is allowed in.

Once created note down the endpoint address (e.g. lucaslouca-com-wordpress-db.shsfahjkiahd.eu-central-1.rds.amazonaws.com:3306). You are going to need it later.

Install WordPress
Back in your EC2 shell:

Finaly, adjust wp-config.php to your database settings (i.e. username, passowrd, database name, host) that you created earlier.

By now you should be able to access your newly installed WordPress blog via http://ec2-35-158-16-195.eu-central-1.compute.amazonaws.com.

Export database from old blog
If your hosting server is as crapy as mine and your only option is to use phpMyAdmin then go ahead and login into your phpMyAdmin site. Then, select your blog database from the left side-bar and then go to Export. Select the Custom - display all possible options option and make sure you check the Add DROP TABLE / VIEW / PROCEDURE / FUNCTION setting. This will drop (delete) the table if it exists and recreate it in the database you are importing it to. For Format select SQL. and click Go.

Once you have your OLD_DB.sql go ahead and upload it to your S3 Bucket.

Backup wp-content from old blog
You also want to migrate any existing themes, plugins etc to your new AWS hosted blog. For that you need to migrate the contents of wp-content from your old blog into your newly installed wordpress blog. So for that you need to connect to your old hosting provider via FTP, navigate to your blog directory and download the entire wp-content directory. Archive it using:

Then go ahead and upload wp-content.tar to your S3 Bucket.

Create a new AMI access role for your EC2 instance
We need to be able to access our S3 bucket through our EC2 instance, so we can download our backed-up database and wp-content files. For that you need to login into your AWS console and navigate to your EC2 instance.

Select your EC2 instance and under Actions select Instance Settings -> Attach/Replace IAM role. From there you can select an existing role or create a new one by clicking Create new IAM role. Alternatively you can create a new role by from Services -> Security, Identity & Compliance -> IAM -> Roles -> Create new role.

So go ahead and create a new role providing it the policy AmazonS3FullAccess and attach the new role to your EC2 instance.

Access S3 from EC2
OK, once you have attached an IAM role with AmazonS3FullAccess policy to your EC2 instance you can go ahead and ssh to your EC2 instance:

Once you are logged in create a directory to sync our S3 bucket into:

Then try and sync the S3 bucket using:

In order to get the correct region type:

Then configure your aws client tot use it as the default region:

Verify your configuration using:

And then go ahead and try and sync your S3 bucket again:

Your files are now accessible under lucaslouca.com-wordpress/

Import old database into AWS hosted database
Go ahead and ssh to your EC2 instance:

And import your old database into your AWS RDS database:

Linking to new URL and defining new domain
Next you need to update any existing old URLs in your db to your new AWS URL. For that I temporary made my DB Instance Publicly Accessible and edited the security group’s inbound rules to allow any source (i.e. 0.0.0.0/0). That way I could access my db through a nice GUI SQL client (I used Sequel Pro) and run the following SQL:

Of course you could again ssh into your EC2 and use the mysql command.

Note: Once you are done do not forget to disable Publicly Accessible and remove the added inbound rules from the security group.

WordPress pretty permalinks on Amazon EC2 Linux instance
You will need to edit /etc/httpd/conf/httpd.conf and change AllowOverride None to AllowOverride All. So it should look like so:

Note: AllowOverride None appears two times in /etc/httpd/conf/httpd.conf and you need to change it in all cases.

Then, navigate to /var/www/html/blog and create an .htaccess file that looks like so:

Also create a .htaccess file under /var/www/html/ to route lucaslouca.com/ to lucaslouca.com/blog

This will transparently redirect all requests to /blog/{requested_resource}. If you have other subfolders that need to be excluded from this redirect you can just an .htaccess file in those directories saying:

For example, I wanted to leave https://lucaslouca.com/bargain and it’s content alone completely so I have just added such an .htaccess file under /var/www/html/bargain.

Finally, you then need to restart apache:

You should be able to view your old posts etc under the new host http://ec2-35-158-16-195.eu-central-1.compute.amazonaws.com.

Updated WordPress site URLs
In the previous section we updated out database entries to point to our ec2-35-158-16-195.eu-central-1.compute.amazonaws.com domain. That way we could continue working until the NS and A records are updated. We can run the sql script again to point to our domain name (http://lucaslouca.comNote: http and not https).

You may need to temporary make your DB Instance Publicly Accessible and edit the security group’s inbound rules to allow any source (i.e. 0.0.0.0/0). That way you can access your db through a nice GUI SQL client (I used Sequel Pro) and run the following SQL:

Enable HTTPS
We already enabled any HTTPS traffic in our lucaslouca.com-security-group. We now need to configure our Apache server to also listen on port 443 in order for us to be able to access our blog via HTTPS. For that we first need to obtain a CA-signed certificate. We will use Let’s Encrypt for our CA.

Add the following to your /etc/httpd/conf/httpd.conf:

Install python and git on your EC2:

Get the letsencrypt client:

Create a config file that will be used for new certificates and renewals. It contains the private key size and your email address.

Important: Before you run letsencrypt temporary disable /var/www/html/.htaccess:

Run letsencrypt:

You can also request a certificate for multiple domains:

Note: If you are trying to letsencrypt your AWS domain (e.g. ec2-35-158-16-195.eu-central-1.compute.amazonaws.com) and you are getting an error its because amazonaws.com happens to be on the blacklist of Let’s Encrypt.

Enable /var/www/html/.htaccess and clean up:

The certificates are located at /etc/letsencrypt/live/ and the last thing is to update your webserver’s configuration. So edit your /etc/httpd/conf.d/ssl.conf file:

Restart apache:

Try and access https://lucaslouca.com. It should work!

Finally, add the renew command in a crontab. Refresing your webserver command should also be here.

Updated WordPress site URLs
In the previous section we updated out database entries to point to our http://lucaslouca.com domain. Now that we got HTTPS up and running we can update our WordPress site URLs to point to HTTPS.

You may need to temporary make your DB Instance Publicly Accessible and edit the security group’s inbound rules to allow any source (i.e. 0.0.0.0/0). That way you can access your db through a nice GUI SQL client and run the following SQL:

Note: Once you are done do not forget to disable Publicly Accessible for your db instance and remove the added inbound rules from the security group.

Give Apache apache access to the folders
An issue still exists when you try to update/install plugins etc. The issue is that apache does not have access to the folders. The default permission is given to the ec2-user in the AMI.

Run this in your EC2 shell and you should be good to go:

Thats it guys!!