WordPress on Contabo VPS

For various reasons, I decided to change my hoster for the blog.

I did some research and now run WordPress on Contabo VPS.

The instances look like a good value, there’s a lot of positive feedback on the web, and the test results point to a significant performance gain compared to my old site.

I was impressed from the beginning, as they had my instance ready within four minutes.

The customer portal looks a bit dated and would love an overhaul:

WordPress on Contabo VPS

The VPS Control area looks solid:

I reset the password as a responsible IT dude (attention: the VPS reboots, so it takes a few minutes) and connected via SSH to my instance. 
It’s a plain Debian 11, so there’s much to do. Let’s start!


Let’s sort some basics out:

apt update && apt full-upgrade -y && apt autoremove -y

apt install software-properties-common wget curl sudo unzip -y

And do something which you won’t find in your average WordPress tutorial – we’re installing Redis first.
Redis is an in-memory database and allows caching of persistent objects; that’s something no plugin can help you with.

apt install redis -y && nano /etc/redis/redis.conf

At the end of the file, drop these two lines in:

maxmemory 256mb
maxmemory-policy allkeys-lru

That’s it for now, but we need to revisit it later. Let’s move on.

LAMP Deployment

Apache and PHP

Let’s install the database, web server, and PHP.
Starting with shooting these lines, I include Brotli compression as well:

apt install apache2 brotli -y

curl -sSL https://packages.sury.org/php/README.txt | sudo bash -x

apt install php8.1 php8.1-cli php8.1-common php8.1-curl php8.1-gd php8.1-intl php8.1-mbstring php8.1-mysql php8.1-opcache php8.1-readline php8.1-xml php8.1-xsl php8.1-zip php8.1-bz2 libapache2-mod-php8.1 php8.1-xmlrpc php8.1-soap php8.1-mcrypt php8.1-imagick  php-redis php8.1-igbinary php8.1-redis php8.1-bcmath -y

I know the last one is a killer, but it contains everything we need, including Redis.

Let’s adjust a few settings.

nano /etc/php/8.1/apache2/php.ini

Use the “Where Is” function in nano (CONTROL-W) to find the following variables and change the values:

upload_max_filesize = 100MB

post_max_size = 100MB

max_execution_time = 300

max_input_vars = 10000

memory_limit = 256M

And somewhere between the other extensions, add this one:


Database Installation

Great, the next step is deploying the database.
I’m not sure why we’re still calling it MySQL so frequently, but it’s MariaDB. If that’s new to you, Google will help.

Anyway, it’s straightforward:

apt install mariadb-server mariadb-client -y && mysql_secure_installation

This happens next; tag along, and enter a suitable password:

In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.

You already have your root account protected, so you can safely answer 'n'.

Switch to unix_socket authentication [Y/n] Y
Enabled successfully!
Reloading privilege tables..
 ... Success!

You already have your root account protected, so you can safely answer 'n'.

Change the root password? [Y/n] Y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] Y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] Y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] Y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] Y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

Once the DB system is up, we need to create the WordPress DB and a user with permissions. Change the user and password; those are just examples.

mysql -u root

	GRANT ALL PRIVILEGES ON wordpress.* TO 'user'@'localhost' IDENTIFIED BY 'password';

WordPress on Contabo VPS Deployment

As the title suggests, we’re running WordPress on Contabo VPS, so let’s paste these lines to download and unzip WordPress:

cd /var/www/html

wget https://wordpress.org/latest.zip

unzip latest.zip

Copy WordPress into a new folder. It should have the name of your domain, don’t use mine. 🙂
Alternatively, it’s possible to run WordPress from the root folder /var/www/html, but I create a virtual host in my scenario.

mv wordpress giese.cloud
cd giese.cloud
cp wp-config-sample.php wp-config.php
nano wp-config.php

Let’s adjust a few things here.
But first, visit https://api.wordpress.org/secret-key/1.1/salt/ in a different browser tab.

Copy and paste the results into the config file, replacing the empty lines on top.

Below add these two lines:

define('WP_CACHE', true);
define('WP_CACHE_KEY_SALT', 'giese.cloud');

And at the bottom, add this:

define( 'FS_METHOD', 'direct' );

Write the file, and let’s adjust permissions:

chown -R www-data:www-data /var/www/html/giese.cloud
find /var/www/html/giese.cloud -type d -exec chmod 755 {} \;
find /var/www/html/giese.cloud -type f -exec chmod 644 {} \;

Oh, and because of IT-OCD, let’s clean up:

rm latest.zip

Now we need to tell Apache to create a new virtual host. Add the following lines into the conf file, again with your domain. Don’t worry about HTTPS now; we will do it in a moment.

nano /etc/apache2/sites-available/giese.cloud.conf

<VirtualHost *:80>
ServerAdmin wordpress@giese.cloud
        ServerName giese.cloud
	    ServerAlias www.giese.cloud
        DocumentRoot /var/www/html/giese.cloud

        <Directory "/var/www/html/giese.cloud">
             AllowOverride All

        <IfModule mod_brotli.c>
           AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/xml text/css text/javascript application/x-javascript application/javascript application/json application/x-font-ttf application/vnd.ms-fontobject image/x-icon

        ErrorLog ${APACHE_LOG_DIR}/giese.error.log
        CustomLog ${APACHE_LOG_DIR}/giese.access.log combined

Quickly create a symbolic link in sites-enabled:

ln -s /etc/apache2/sites-available/giese.cloud.conf /etc/apache2/sites-enabled/

And finally, we can enable the site and Brotli:

a2ensite giese.cloud
a2enmod brotli
a2enmod rewrite
systemctl restart apache2

Let’s Encrypt

Now would be a good time to pull certificates so we can offer the site on HTTPS.

apt install certbot python3-certbot-apache -y

certbot --apache --agree-tos --redirect --hsts --uir --staple-ocsp --email xxx@giese.cloud -d giese.cloud,www.giese.cloud

Again, change your email and domain. 
If you’re interested in all these switches, open the documentation here.

And that’s it!

Let’s pop into the WordPress installer at:

WordPress – Restore from Backup

Give your site a name, an account, and a password.
Once that’s sorted, log in and go straight to plugins.
Delete the plugins showing:

And install the backup plugin of your choice. I’m on this one here, and it works flawlessly. Yes, would you believe it? I tested my backup before I started the migration. 🙂

I purchased the Google Drive extension for automated online backups. It’s a plugin that needs to be manually installed on top of the free one:

The first step is linking it to my Google account:

And I change a few settings:

I use incremental backups. Click the last one; it works.

Sure, I’m on the latest stuff now:

This will take a while. Maybe use the time to check on your cat!

According to their documentation, it’s necessary to click permalinks twice, so let’s do it.

Attention: The backup came with the previous password that overwrote the one you just provided, so you’ll need the old one to log in. You can change it anytime. 

Clean up!

Check your posts – everything should be there.

One thing, though, is that the backup will restore plugins and themes you might have used temporarily, so I suggest verifying and deleting what’s not in use.

The last step is finalizing Redis. Open the plugin under Settings/Redis and click Enable Object Cache.

Now jump back into SSH and pop into your themes folder. For me, it is:


I found a nice hint here, so let’s deal with it:

nano functions.php

Throw this to the bottom:

function vultr_maybe_clear_alloptions_cache( $option ) {
    if ( ! wp_installing() ) {
        $alloptions = wp_load_alloptions(); 
        if ( isset( $alloptions[ $option ] ) ) { 
            wp_cache_delete( 'alloptions', 'options' );
add_action( 'added_option',   'vultr_maybe_clear_alloptions_cache' );
add_action( 'updated_option', 'vultr_maybe_clear_alloptions_cache' );
add_action( 'deleted_option', 'vultr_maybe_clear_alloptions_cache' );

Now issue a quick service apache2 restart and return to the WordPress dashboard.

I clicked through a few areas and noticed that I had to log into Google Sitekit again.
I had to activate Yoast manually in my test environment, but that wasn’t necessary this time.

I’m unsure if it was a one-off or maybe because it was a different domain name.

That’s it! 
It took me a while, but the site is significantly faster than before.

Happy Sascha!

Next: VPS Security.

More technology posts:

Fail2Ban settings

VPS Security

VPS security is an important topic. Unsecured instances become zombies and will be abused for…

Read More
IT Pro Day 2021

IT Pro Day 2021: Orangematter

I’ve written a new article on our corporate blog, celebrating IT Pro Day 2021:https://orangematter.solarwinds.com/2021/09/01/it-pros-to-the-world-bring-it-on/ It’s…

Read More
1 2 3 4 5

Leave a Comment

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