Cloud Use Cases: How to build a scalable nonprofit website part 4

Installing LAMP Stack

Now that our basic infrastructure is ready, we can install the LAMP (Linux, Apache, MySQL, PHP) Stack.

Log into your Server

You can access your server from Linux or Mac with the command below. If you are running Windows, the most popular way to run SSH is using the free PuTTY tool which can be downloaded here.

ssh root@

Update your server

The first thing you’ll want to do after accessing your server is making sure the software is up to date. Do this with the following command.

sudo apt update && sudo apt upgrade

Enabling the software firewall

Ubuntu comes pre-installed with UFW (Uncomplicated Fire Wall) but it is not set up by default. We can make a quick simple firewall by allowing port 22 for ssh and enabling UFW.

Allow port 22:

ufw allow 22

Enable UFW:

sudo ufw enable

You can read more about how to configure UFW here. It’s also highly recommended to take a look at this article to properly secure ssh before continuing with this guide. Among other things, it will show you how to create a sudo user which we’ll assume you have from this point on.

Install Apache

Apache is the web server of the LAMP stack. Install it with this command.

sudo apt install apache2

This command will allow http and https traffic over the internal network through your firewall. This will allow your load balancer to access the server.

sudo ufw allow in on eth1 to any port 443,80 proto tcp

Install PHP

Unfortunately there is a bug in the current release of PHP on Ubuntu 18.04 that will prevent it from connecting to MySQL in the most secure way. So we’ll add a PPA (Personal Package Archive) to install the latest version of PHP.

Add the PPA and update package cache.

sudo add-apt-repository ppa:ondrej/php && sudo apt update

Install PHP packages.

sudo apt install php libapache2-mod-php php-mysql

Configure Apache

NOTE: I’ll be using as and example domain throughout this article series. Make sure to always replace this with your domain.

Create the website directory.

sudo mkdir -p /var/www/vhosts/

Change the owner of the directory.

sudo chown www-data:www-data /var/www/vhosts/

With nano, create and open an Apache configuration file for the site.

sudo nano /etc/apache2/sites-available/

Copy the below text and paste it into nano. Make sure to change your web site name. Save and exit.

    DocumentRoot /var/www/vhosts/

        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted

    ErrorLog ${APACHE_LOG_DIR}/
    CustomLog ${APACHE_LOG_DIR}/circledemo-access.log combined

Enable your site and disable the default site with the next two commands.

sudo a2ensite


sudo a2dissite 000-default.conf

Any time you make a change to the Apache configuration, you’ll want to test your configuration before restarting or reloading the service. This can be done with the apache2ctl command.

sudo apache2ctl configtest

You should get a warning about the sites fully qualified domain name. This can be ignored. As long as you get a “Syntax OK” message, you’re good to go.

Restart apache2 so the changes will go into affect.

sudo systemctl restart apache2

Enable TLS with LetsEncrypt

LetsEncrypt is a nonprofit certificate authority that provides free and easy to obtain TLS (SSL) certificates. With the certbot tool, we can easily obtain the certificate and automate renewal.

Enable the certbot PPA and update package cache.

sudo add-apt-repository ppa:certbot/certbot && sudo apt update

Install certbot.

sudo apt install python-certbot-apache

Now as long as DNS is pointing to the server, we can obtain a certificate with this command. Make sure to replace with your domain.

sudo certbot --apache -d -d

Download and setup WordPress

Install php extensions needed for wordpress.

sudo apt install php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip

Restart apache2

sudo systemctl restart apache2

Before downloading WordPress, we’ll move to the tmp dir so our extra files will be cleaned up on the next reboot.

cd /tmp

Download the latest WordPress from

sudo wget

Extract the compressed files.

sudo tar -xzf latest.tar.gz

Next we’ll create the .htaccess file and at the same time block the security risk xmlrpc. You can read more about what this is and why you may want to disable it here.

sudo nano /tmp/wordpress/.htaccess

Paste in the following text, save, and exit.

# Block WordPress xmlrpc.php requests

order deny,allow
deny from all

Create an upgrade directory to avoid running into issues later down the road.

mkdir /tmp/wordpress/wp-content/upgrade

Now we can copy the installation over to the document root for our website.

sudo cp -a /tmp/wordpress/. /var/www/vhosts/

Change ownership of the files to the web server user.

sudo chown -R www-data:www-data /var/www/vhosts/

Change the permissions of the files and directories for security.

sudo find /var/www/vhosts/ -type d -exec chmod 750 {} ;


sudo find /var/www/vhosts/ -type f -exec chmod 640 {} ;

Create a configuration file using the template.

cp /var/www/vhosts/ /var/www/vhosts/

We need to secure our WordPress installation with a set of random keys. The easiest way to obtain random keys is with the WordPress api built for this purpose. Run this command and copy the output. We’ll use it in the next step.

curl -s

With the entire output copied to your clipboard, open the configuration file.

sudo nano /var/www/vhosts/

First thing to do here is replace the following lines with the keys you obtained from the WordPress api.

define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

Next, fill in the DB_NAME, DB_USER, DB_PASSWORD, and DB_HOST fields. And create the new field for FS_METHOD.

/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );

/** MySQL database username */
define( 'DB_USER', 'uniqueadmin' );

/** MySQL database password */
define( 'DB_PASSWORD', 'eiPae0lahc' );

/** MySQL hostname */
define( 'DB_HOST', '' );

define('FS_METHOD', 'direct');

Once done, save and exit nano.

Change Load Balancer to HTTPS

Now that TLS has been configured, we can change the Load Balancer’s protocol and port.

Part 5

Leave a Reply

Your email address will not be published. Required fields are marked *