Categories
Backend Technology

How to install & secure WordPress on a small VPS with Debian, Nginx, MariaDB, 2FA and more

This blog is running on a tiny Linux VPS with 1GB RAM, 1 CPU Core and a 25GB SSD with Debian 10 installed. Thanks to a proper WordPress setup this VPS will handle itself just fine even with substantial traffic. This article describes my setup.

Moreover, it costs me only $5 per month. That’s like the cheapest WordPress.com plan, but fully featured with root access, and five times cheaper than the basic WPEngine plan.

You can probably find an even cheaper VPS than mine, but I recommend the Nanode from Linode. I’ve been a Linode customer since 2009 (11 years!) and they never failed me. And believe me, I tried many others….

Prepare your server

First, let’s make sure all is up to date and well clocked:

apt-get update; apt-get upgrade
dpkg-reconfigure tzdata

During date & time reconfiguration I suggest selecting “None of the above” and “UTC”. I always like to have all my servers on the same time, but it depends what you need really.

I also recommend “htop” to monitor & manage running processes:

apt-get install htop

Then I recommend setting a hostname to something familiar, so you know what your are connected to via SSH:

echo "example-hostname" > /etc/hostname
hostname -F /etc/hostname

SSH authentication using public key

At the moment, your new server allows access using a password. This is a bad idea, vulnerable to brute-force attacks. If you don’t already have a public key on your local machine, let’s create one:

ssh-keygen -t ed25519 -a 100

We use Ed25519, an EdDSA scheme, because it’s least likely to be backdoored. It’s a good practice to set a strong key passphrase as well. The public-private key pair will be saved in a hidden “/.ssh” directory in your home folder.

Now, follow this tutorial to harden your server and SSH configuration. I prefer the following parameters in “/etc/ssh/sshd_config”:

Port 22
AddressFamily inet
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM no

Firewall

I prefer UFW therefore I use the following:

apt-get install ufw
ufw default allow outgoing
ufw default deny incoming
ufw allow https
ufw allow http

If you happen to have a static IP at your home or office, I recommend limiting SSH access to that IP using the following command but substituting “0.0.0.0” with you IP:

ufw allow from 0.0.0.0 to any port 22

Otherwise just “ufw allow ssh”, but make sure to install Fail2Ban like in the tutorial I linked to earlier.

Install MariaDB

Why not MySQL? It’s a bit slower, it’s less open and when something crashes, it’s harder to recover. Anyway:

apt-get install mariadb-server
mysql_secure_installation
service mysqld start

Sometimes after starting the database for the first time you won’t be able to log into it using the root user. Something is wrong with the password. So just change it with this command, where “password” is your new password for database root user:

mysql -u root -p
> ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';

If you want to fine-tune MariaDB in terms of memory, here is a good calculator. To manage this database remotely I recommend an app that allows DB connections through SSH, like Sequel Pro for macOS. Never expose your database to the outside world.

Install Nginx

I’ve been using Apache a decade ago, but now I’m an Nginx fan. It makes things so much easier!

apt-get install nginx

There’s plenty of thing to tweak, but as a good practice start by making your server less identifiable.

nano /etc/nginx/nginx.conf
server_tokens off;

Install PHP

I’m not a big fan of PHP, but I really like how it gets the job done. And WordPress is built with it, so…

apt-get install php php-fpm imagemagick
apt-get install php-mysql php-curl php-gd php-mbstring php-xml php-xmlrpc php-soap php-intl php-zip php-imagick

Install WordPress

Now, the final step begins.

wget https://wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz
cp wordpress/wp-config-sample.php wordpress/wp-config.php
mkdir wordpress/wp-content/upgrade
chown -R www-data:www-data /var/www/wordpress
find /var/www/wordpress/ -type d -exec chmod 750 {} \;
find /var/www/wordpress/ -type f -exec chmod 640 {} \;

Configure WordPress

First, update your installation keys.

curl -s https://api.wordpress.org/secret-key/1.1/salt/
nano /var/www/wordpress/wp-config.php

Next, configure WordPress to work with Nginx following this article. If you run into problems, make sure php-fpm.sock (or php7.3-fpm.sock) have a correct path and filename set in your Nginx config.

Setup SSL with Lets Encrypt

Encryption is essential in this day and age. It’s good these days SSL certificates are free thanks to LE. Let’s install them.

apt-get install certbot python-certbot-nginx
certbot --nginx

This will start a step-by-step guide helping you install your cert. Afterwards, configure a cron job to automatically renew your cert when necessary.

crontab -e
0 0 * * * certbot renew

Finally, if you want to get an A or A+ on your SSL test, make sure to use strong ciphers in your nginx.conf.

Setup 2FA login

Two-factor authentication using an authenticator app from Google, Microsoft or Authy is a nice way to secure your login. It’s easy and free to set up using this plugin.

Other useful plugins

You could install a ton of plugins for WordPress, but that wouldn’t do you any good. You see, the more plugins you have, the more problems you encounter. Some plugins can slow down your blog, some can slow down each other, and some can just break things. I suggest you use the bare minimum:

  • Akismet to filter spam comments
  • Jetpack to get the official goodies
  • Hummingbird to speed up your blog but stay sane
  • Yoast SEO to learn how to write better content
  • Health Check to keep your blog in good condition
  • Two Factor mentioned above
  • AMP and Structured Data

By Marek Foss

I graduated Oxford University Computing Laboratory in 2008 and since then have been a full-stack lead on many projects, in different technologies. Myself, I like to code in Perl, Solidity and JavaScript, run on Debian & Nginx, design with Adobe CC & Affinity and work remotely, but overall I always do whatever gets the job done. I like to learn new things all the time!

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.