WordPress in an LXC Container

We’ve set up several Proxmox LXC containers to host several WordPress sites on our server. LXC containers are more efficient in terms of server resource utilization. You can learn more about Proxmox LXC containers vs. Virtual Machines here. We went through the following steps to set this up.

WordPress Container

The setup uses the WordPress LXC container from Turnkey Linux. This lightweight Debian Linux environment uses MariaDB and Apache2 to complete the LAMP stack. I followed the following YouTube video to complete the installation –

Once the container was set up, I set the timezone for Debian as follows:

# timedatectl set-timezone "America/New_York"

Next, I updated the Debian installation via the following:

# apt update && apt upgrade

I also installed nslookup and apt-utils via the following:

# apt-get install dnsutils
# apt-get install apt-utils

Increase WordPress Memory Limit

The following addition was made just before the “…Happy publishing” line in the wp-config.php file to enable the WordPress installation to take advantage of the additional memory.

/* Increase WP Memory limit */
define('WP_MEMORY_LIMIT', '1024M');

/* That's all, stop editing! Happy publishing. */

Increase the Size of OPcache

The PHP OPcache stores the compiled versions of the PHP scripts that make up our websites. The default size of the cache is 128 MB. We’ve increased our OPcache to 512 MB to improve performance.  OPcache memory is shared across all of the WordPress sites in the host LXC container. The steps to modify the size of the OPcache are as follows:

# vi /etc/php/8.2/apache2

... Modify the following lines in the file

; The OPcache shared memory storage size.
;opcache.memory_consumption=128
opcache.memory_consumption=512

# systemctl restart apache2

Email Access

The supplied postfix MTA did not work, so we’ve installed the WP Mail SMTP plugin and configured it to forward email through our email service.

SPF and DMARC records need to be set up for the domain. This needs to be done properly to accommodate the multiple servers that can send e-mail on behalf of our domain. The DMARC step is simple – the necessary steps can be found here. The DMARC setup for a domain can be confirmed here.

SSL Certificate

This procedure was used to set up apache2 with a signed SSL certificate – click here. It uses Certbot with Let Encrypt to obtain and install a signed SSL certificate in Apache. A DNS-01 challenge is used, which does not require an external Internet connection for Apache.

Once the initial certificates are installed, a script can be created to run the certbot commands to check if the SSL certificates need to be updated.

The final step was to schedule weekly checks for SSL certificate updates using the cron. This is done by executing the script mentioned above once a week.

Persistent Object Cache

We are using the Redis persistent object cache on our sites. Information on Redis and how to install it may be found here and here.

The following changes in each site’s wp-config.php must be made first:

<?php

/* Enable Redis cache - this line must be
   right after the opening <?php line */
define( 'WP_CACHE', true );

Then add the following to the “salt” section of wp-config.php:

/* Redis cache salt - unique for each WordPress
                      site on this host */
define('WP_CACHE_KEY_SALT',
       'homelab.anita-fred.net');

The WP_CACHE_KEY_SALT can be anything, but the value must be unique for each WordPress site host on the LXC.

The next step is to install the redis and the php-redis packages on the LXC as follows:

# apt-get update
# apt-get install redis-server
# apt-get install php-redis
# systemctrl restart apache2

The final step is to install the Redis Object Cache plugin on each WordPress site and use the plugin to enable the Redis cache.

Enable Gzip Compression

Gzip compression helps users with slower internet connections to have a better overall experience. This feature can be enabled as follows (more info here). First, run the following command for the LXC container to enable gzip compression for all websites.

# a2enmod deflate

Next, use a plugin in each WordPress website to enable Gzip compression in the associated .htaccess file.

With these steps done, restarting apache2 will enable compression.

# systemctl restart apache2

You can confirm that Gzip compression is working via the GiftOfSpeed web tool.

Static Browser Caching

First, install the apache2 mod_expires extension using the following command –

# a2enmod expires
# systemctl restart apache2
# apachectl -M | grep expires

Next, set the static caching expiration header to 365 days using the caching plugin installed in each WordPress site.

Setup SSH Keys

A public/private key pair is created and set up for Proxmox VE and all VMs and LXC to ensure secure SSH access. The following procedure is used to do this. Access via password should be disabled once the SSH keys are in place and working.

Add Additional Websites

Apache2 can support multiple websites using a single IP address. This is the configuration that we are using for our home lab. The following procedure explains how to set this up:

Once an additional WordPress instance is installed and an associated database is set up, the following steps should be performed:

  • The SSL certificate for the site must be pulled and installed via certbot before enabling a new website via a2ensite
  • Set the owner and group permissions for all files in the WordPress installation

WordPress Scheduler

WordPress sites need periodic visits to each site to ensure that the internal scheduler runs properly. This can be a problem early in developing a new site when there are few visitors. To address this, we’ve installed a cron job for our sites as follows –

# Modify root crontab
cd /var/spool/cron/crontabs
vi root

... Add these lines...
... The first ensures SSL cert updates...

# m h dom mon dow command
0 4 * * sun /bin/sh /root/install_cert.sh
*/5 * * * * /usr/bin/curl https://travel.anita-fred.net/wp-cron.php?doing_wp_cron
*/5 * * * * /usr/bin/curl https://homelab.anita-fred.net/wp-cron.php?doing_wp_cron
*/5 * * * * /usr/bin/curl https://www.anita-fred.net/wp-cron.php?doing_wp_cron

Anita's and Fred's Home Lab

WordPress Appliance - Powered by TurnKey Linux