Creative (i.e. weird) WordPress Hosting Tricks

Photo by Web Donut on Unsplash

Nginx vs. Apache2… tech folks seem to love such debates. In my experience, there’s pretty much never a single answer… it’s always “it depends.” Nginx is known for its power with static files, and since a) the front end is what your visitors experience and b) most front-ends are full of static files, one can see why Nginx is a popular choice for WordPress hosting. WordPress.com uses Nginx as do many of the leading managed WordPress hosting providers.

I’ve noticed, though, that there’s more and more happening on the back-end of some of my WordPress installs. If you haven’t seen, there are some pretty robust plugins where the action happens in the dashboard (such as WP ERP and ZBS CRM) … not to mention the things people might create with tools like CPT UI and Advanced Custom Fields.

I frequently play around with different ways of improving WordPress performance through hosting configurations, not so much because it’s necessary but because I have fun doing it. This was one of those times… I wondered about the value of catching the front-end of a WordPress installation with Nginx but directing everything on the dashboard side of things to Apache2. I don’t expect that this is a world-changing configuration, but it was something I wanted to explore and it was pretty simple to set up.

Step One: WordPress with Nginx

This post presupposes an installation of WordPress using Nginx as the web server on Ubuntu (I’m using 18.04 LTS). If you don’t have this, far and away the best instructions for how to get there can be found in the Hosting WordPress Yourself series at SpinupWP. (Or you could just let SpinupWP do it for you; it’s a great, time-saving, inexpensive service.)

Step Two: Install Apache2

Install Apache2 using the following command:

sudo apt install apache2 libapache2-mod-php7.3

Note that I’m using PHP 7.3; change this to the version appropriate to your installation.

Apache2 will fail to start because it defaults to ports 80/443 and those are already in use by Nginx, but it will install just fine. In order to get it started, you’ll need to change the ports, though, so do:

sudo nano /etc/apache2/ports.conf

and change the ports (in this example I’m replacing 80 with 8080 and 443 with 8443):

# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 8080

<IfModule ssl_module>
        Listen 8443
</IfModule>

<IfModule mod_gnutls.c>
        Listen 8443
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Save the file.

There are a couple of Apache2 modules that we should add (or at least make sure are already there); do so with the following command:

sudo a2enmod rewrite ssl

Go ahead and check your configuration at this point with:

sudo apachectl configtest

If all is well, start Apache2:

sudo systemctl start apache2.service

Verify that it’s running:

sudo systemctl status apache2.service
Apache2 is running

Step Three – Configure a Virtual Host

We’ll need to set up a virtual host to handle traffic to this site via Apache2. You should already have an SSL certificate from your Nginx setup, so this step is pretty simple. For the sake of our example, we’ll use “yourserverurl.com” as the domain, and call the new file yourserverurl-com-admin.conf, so:

sudo nano /etc/apache2/sites-available/yourserverurl-com-admin.conf

The contents of the file should end up looking something like this:

<IfModule mod_ssl.c>
        <VirtualHost _default_:8443>
                ServerName yourserverurl.com
                ServerAdmin your@emailaddress.net

                DocumentRoot /home/ubuntu/yourserverurl.com/public

                #LogLevel info ssl:warn

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

                #Include conf-available/serve-cgi-bin.conf

                SSLEngine on

                SSLCertificateFile      /etc/letsencrypt/live/yourserverurl.com/cert.pem
                SSLCertificateKeyFile   /etc/letsencrypt/live/yourserverurl.com/privkey.pem

                #   Server Certificate Chain:
                SSLCertificateChainFile /etc/letsencrypt/live/yourserverurl.com/chain.pem

                #   SSL Engine Options:
                <FilesMatch "\.(cgi|shtml|phtml|php)$">
                                SSLOptions +StdEnvVars
                </FilesMatch>
                <Directory /usr/lib/cgi-bin>
                                SSLOptions +StdEnvVars
                </Directory>

        </VirtualHost>
</IfModule>

# vim: syntax=apache ts=4 sw=4 sts=4 sr noet

Obviously you’ll need to replace the email address (“your@emailaddress.net”) and the URL (“yourserverurl.com”) to match your own values. Note also the “DocumentRoot” value: this should point to the root location of your WordPress installation.

Now we need to activate the new virtual host:

sudo a2ensite yourserverurl-com-admin.conf

You’ll need to reload Apache2 again to make this take effect:

sudo systemctl reload apache2.service

Step Four – Configure Nginx

Assuming you set up your own Nginx, you probably know where your site’s configuration file is. Normally for me it’s /etc/nginx/sites-available. You’ll want to edit the file for your site:

sudo nano /etc/nginx/sites-available/yourserverurl.com

There are a lot of different things that can appear in an Nginx configuration file. For a WordPress installation, somewhere toward the middle you’ll probably see a block that looks something like this:

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.3-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }

The magic addition is going to seem anticlimactic after all we’ve done to get to this point, but this is it… add the following lines (mine is above the first “location” block):

location ~/wp-admin(.*)$ {
    proxy_pass https://yourserverurl.com:8443;
}

This simply takes any request for “wp-admin” (and anything beneath it) and passes it over to our Apache2 instance.

Save the file and test your Nginx configuration:

sudo nginx -t

Assuming everything’s okay, reload Nginx:

sudo systemctl reload nginx.service

But wait! There’s more.

Before we test this out, there are a couple of caveats.

Apache2 normally runs under the user www-data. Nginx defaults to that user as well, but depending on your setup, you might be using another account. If you are, you’ll need to make these match up somehow. In some examples (such as the one I referred to earlier, Hosting WordPress Yourself, they take you down the path of configuring with your own user account. This is fine for Nginx, but if you use your own account for Apache2, it will stop running as soon as you log out. So it might be preferable just to switch your Nginx to www-data, or make a special account to run both.

Apache2 defaults to /var/www/ as the place where it expects to host files. If you’re using another location for the site files for your Nginx site(s), you’ll need to tell Apache2 how to handle those locations. So, using the example above where our files were in /home/ubuntu/yourserverurl.com/public, you’ll want to edit the Apache2 configuration file:

sudo nano /etc/apache2/apache2.conf

Scroll until you find this section:

<Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all denied
</Directory>

<Directory /usr/share>
        AllowOverride None
        Require all granted
</Directory>

<Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

Change “/var/www/” in the last one to match your location, so, for example:

<Directory /home/ubuntu/yourserverurl.com/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

Save and restart Apache2.

Step Five – Verifying

Did it work? It might sound hackish (hey, it’s not like I have a computer science degree or anything!) but I tested by visiting my site, logging in to the WordPress dashboard, and alternately stopping and starting Apache2 on the server while attempting to navigate the dashboard. With Apache2 stopped, expect to get an Nginx 502 Bad Gateway error; this is because Nginx is trying to hand off the connection and there’s nothing to receive it. With Apache2 running, the dashboard should respond normally.

Wrapping Up

Is this a dumb idea? Too little ROI? I haven’t decided. Like many experiments, one tries, tests, measures, retests. I’m going to do that for a bit and see how it goes.

Have you tried this? Feel free to comment and let me know your thoughts!

One comment

Leave a Reply

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