How to install Wordpress with SSL on a new Ubuntu server
There are probably thousands of guides on this, but I was looking for the basic steps and couldn't find anything I would be happy sending someone, so here's my take on it.
Aside from the operating system itself, three parts are needed to serve a Wordpress site:
- PHP, to run the Wordpress application itself;
- MySQL, as a database to store Wordpress data such as posts and user accounts;
- A webserver, which takes requests from your website visitors (which pages they want to see), passes them to Wordpress, and returns the result to the user for their browser to display. The most common webservers are Apache and Nginx, in this guide I'll use Apache.
Additionally, we'll request and install a free SSL certificate for the website. For this, a domain name (or subdomain) will be needed.
I'm going to use the example myblog.com
for the instructions, you'll need to substitute with your own domain name.
Also, this guide assumes you have configured DNS to point the A (and/or AAAA) record to your server. If you haven't, you can add the following entry to your hosts file and it will work for you (but the SSL section will not work):
11.22.33.44 myblog.com
- replace 11.22.33.44 with the IP address of your server. If you don't know it, curl ipv4.icanhazip.com
from the server.
Install the packages we need
We've determined we'll need PHP, MySQL, and Apache to run Wordpress. So let's start by installing them. Login as root (if you want to use sudo install, make sure it's configured for your user and prefix every command with sudo).
apt-get update
apt-get install php mysql-server apache2
Let's also install a couple of other libraries we will need or are recommended by Wordpress:
apt-get install pwgen unzip php-mysqli php-curl php-dom php-mbstring
Download Wordpress
This is usually the last step in guides, which I think is fine if you already know how it all fits together, but I want to take a more bottom-up approach here.
To download Wordpress, we first need to decide where to put it. Each website (in a basic sense) lives in a directory, which Apache calls the DocumentRoot
. This is where Apache looks for files, so for example if it sees a request for myblog.com/index.php
by default will look for a file called index.php
in the DocumentRoot (directory) specified for myblog.com
.
Let's say that the website will be in /var/www/myblog.com/
and so we'll download Wordpress there. First we'll create the directory, then we'll download Wordpress as a zip file into a temporary directory, unzip it, and move it in the new directory:
mkdir /var/www/myblog
cd /tmp/
wget https://wordpress.org/latest.zip
mv wordpress/* /var/www/myblog.com/
At this point, Wordpress is installed, but not connected to a website or a database.
Connect Wordpress to Apache
Apache is designed to handle multiple websites on the same server. A lot of the guides tell you to install Wordpress onto the default website (/var/www/html
) but we're not going to do this.
The main configuration file is in /etc/apache2/apache2.conf
, and it includes any websites (Virtual Hosts
) defined in /etc/apache2/sites-enabled
as long as they end with .conf
. Each config file in sites-enabled
should be a symbolic link (shortcut) to the real config file in /etc/apache2/sites-available
so we're going to do that.
Use your favourite text editor (or just cat) to create /etc/apache2/sites-available/myblog.com.conf
with the following content:
Next tell Apache to enable this website and allow rewrite rules:
a2enmod rewrite
a2ensite myblog.com.conf
systemctl reload apache2
Visit your website, and you should see Wordpress is installed, but is asking for database details:
Configuring MySQL
Here we need to configure three things. A database for Wordpress to use, and a user for Wordpress to connect to MySQL with, and access for that user. Use a strong password here, I use the command pwgen 20
and choose a password from there.
Run mysql to login:
mysql
Next, in the MySQL database, create the database,
mysql
CREATE DATABASE myblog;
CREATE USER 'wp_myblog'@'localhost' IDENTIFIED BY 'STRONGPASSWORDHERE';
GRANT ALL ON myblog.* TO 'wp_myblog'@'localhost';
exit;
Ignore all the guides telling you that you need to flush privileges, you don't if you use CREATE USER
and/or GRANT
. Now, we need to tell Wordpress to use that database.
At the moment, the user Apache is running as (www-data) can read all of the Wordpress files it needs but it cannot create or edit files. This is more secure, but means that Wordpress cannot setup the config file itself. So, we'll temporarily allow Apache to write files for Wordpress
chown -R www-data:www-data /var/www/myblog.com
Next to back to the website and click "Let's Go".
Fill in the database connection details you submitted above and click Submit:
Click Run the installation, choose a name for your blog, a username and password for logging into Wordpress, and enter your email address. You should now be able to login to Wordpress.
We now need to fix the permissions. I'm putting root here, but it would be better to create a user just for the site. I won't cover that here.
These are basic security recommendations but will stop Wordpress updating itself. You should do your own research on Wordpress permissions, these are the strictest permissions I've found that will still allow plugins to be installed.
chown -R root:root /var/www/myblog.com
chown -R www-data:www-data /var/www/myblog.com/wp-content
chown -R www-data:www-data /var/www/myblog.com/wp-admin
chgrp www-data /var/www/myblog.com
chmod 750 /var/www/myblog.com
SSL Certificate
Finally, we'll setup SSL. We need to request a certificate and then tell Apache to use it for HTTPS connections.
Request the certificate
We'll use acme.sh for this, the instructions are here but the following two commands should work for you:
curl https://get.acme.sh | sh -s email=my@example.com
/root/.acme.sh/acme.sh --issue -d myblog.com -d www.myblog.com --webroot /var/www/myblog.com/ --server letsencrypt
Once it runs you should see something like:
[Mon Sep 9 11:00:42 AM CEST 2024] Success
(text redacted)
[Mon Sep 9 11:00:44 AM CEST 2024] Your cert is in: /root/.acme.sh/myblog.com_ecc/myblog.com.cer
[Mon Sep 9 11:00:44 AM CEST 2024] Your cert key is in: /root/.acme.sh/myblog.com_ecc/myblog.com.key
[Mon Sep 9 11:00:44 AM CEST 2024] The intermediate CA cert is in: /root/.acme.sh/myblog.com/ca.cer
[Mon Sep 9 11:00:44 AM CEST 2024] And the full chain certs is there: /root/.acme.sh/myblog.com_ecc/fullchain.cer
We are interested in the cert key, and the full chain certs.
Configure Apache to use SSL
Now we need to configure Apache to use this certificate to encrypt and decrypt HTTPS connections (on port 443) for this website, using the above certificate and key.
First, we need to enable SSL in Apache:
a2enmod ssl
- it will tell you to restart Apache, we'll do that in a minute.
Next re-open /etc/apache2/sites-available/myblog.com.conf
and below the previous config add a new VirtualHost:
<VirtualHost *:443>
ServerName myblog.com
ServerAlias www.myblog.com
ServerAdmin you@youremail.com
DocumentRoot /var/www/myblog.com
<Directory /var/www/myblog.com>
AllowOverride all
Options -Indexes
</Directory>
ErrorLog ${APACHE_LOG_DIR}/myblog-error.log
CustomLog ${APACHE_LOG_DIR}/myblog-access.log combined
SSLEngine on
SSLCertificateFile /root/.acme.sh/myblog.com_ecc/fullchain.cer
SSLCertificateKeyFile /root/.acme.sh/myblog.com_ecc/myblog.com.key
</VirtualHost>
Ask Apache to double check the config to make sure you haven't made a mistake, and if it's ok, restart Apache
apache2ctl configtest
- it should say Syntax OK
systemctl reload apache2
Now visit https://myblog.com
and it should work. If it redirects to something (eg. https://YOURIPADDRESS
) you should be able to fix it by adding the following two lines to '/var/www/myblog.com/wp-config.php' just above DB_NAME
:
define( 'WP_HOME', 'https://myblog.com' );
define( 'WP_SITEURL', 'https://myblog.com' );
That's it. Happy blogging.