Justin Merrill, MBA, BS .:|:. Platform Engineer

Platform | DevOps | SRE | K8s | GitOps | IaC | CICD | Security | IAM | Cloud | Software | Data | APIs

DevOps

Nginx1.18.+ Reverse-Proxy to Apache2.4+ Configuration For PHP7+ Web Applications (Including WordPress & WPMU) with Cloudflare SSL, DNS, Caching & More

I wanted to do find an optimal and “universal” Nginx Reverse-Proxy to Apache web server configuration For PHP7 web applications for a while. This configuration idea was inspired by a few posts I read about comparisons and contrasts between the two web server. The idea for combining the benefits of nginx caching abilities for smaller files and Apache for faster processing of larger workloads was on my mind. I wanted to explore the benefits by benchmarking improvements to WordPress & WPMU performance by reducing the Network, CPU and RAM costs. In combination with Cloudflare (SSL, DNS, Caching & more), I wasn’t sure if there would be a noticeable improvement to the end user, but perhaps the overall resource load may be reduced under the same average count of operations. I’ve been dabbling with a variety of ways to implement a template for using the Amazing Speed & Caching mechanisms of nginx for serving up static files & content that combines the superior Event MPM & PHP-FPM capabilities that Apache v2.4+ offers for crunching server-side processes (or something like FastCGI for Perl or FastCGI WSGI for Python).

There are a lot of different low-cost cloud infrastructure options that are becoming more appealing. If you prefer to play the “free trial for a year” games with the more complicated AWS & Azure service & stacks, you can also get some pretty cheap Cloud VMs that way, too (just brace yourself for the bill that’s coming next year when the trial is over & you’re married to the chosen platform).

When you combine the low-cost infrastructure options with services like Cloudflare DNS, & ZOHO suite, or some low-cost shared hosting solution combo product for managing data & email resources, you can really do a lot for very low cost.

A properly configured VPS using nginx for serving (& caching) HTML, CSS, JavaScript, images, videos, etc. with a load-balanced & reverse-proxy configuration to an Apache upstream to handle the PHP, Perl and/or Python combined with the power of Cloudflare DNS & its feature rich optimizations & caching… it’s not 2004 anymore! You can really serve up a TON of web requests with minimal resources & next to no cost at all for the static content itself. Prices start climbing higher when you get into things like network-intensive operations (eg: hosting or consuming huge amounts of API calls or maintaining a rapidly growing datastore of some kind) audio or video transcoding, sending or receiving large files or streaming. But most of these rather niche & specific operations can always be off-loaded to targeted resources or 3rd party services to cope with the heavy lifting.

Goals for this Guide:

  1. Have nginx serving up static content on port 80 and 443
  2. Use Apache for all things PHP, including running PHP-FPM with Event MPM Module

We won’t bother adding TLS/SSL with Apache since Nginx will be handling it. Though, if we start adding multiple remote Apache backends, we will need to add TLS/SSL to those as well. Since Apache will be running on the same server instance as nginx in this scenario, we will assume all traffic to Apache (basically any requests for PHP) gets sent to port 8080.

    We will assume Debian / Ubuntu-style Apache Web Server is being used for this guide. There are quite a few nuances between Debian/Ubuntu & CentOS/RHEL/Fedora Apache default install configurations (eg. “sites-available” symlinks), but if you are choosing those flavors of Linux, I hope you understand these nuances and adjust your configuration accordingly. Since Debian-based Linux is the most popular, I’ll stick with that paradigm throughout the rest of this guide. I’ll also assume you’re working off of a “fresh install” with no programs running that will conflict with ports 22, 80, 443, 3306 or 8080.

    Install apache2 with:

    Next, let’s change the default port that Apache2 listens on

    [/crayon]

    Inside /etc/apache2/ports.conf

    Save the /etc/apache2/ports.conf file & close it.

    Since the default Apache virtual host is also listening on port 80, let’s change that too in case in tries to cause us grief later on (sometimes it does).

    [/crayon]

    Inside the “file” /etc/apache2/sites-enabled/000-default.conf
    (It’s actually a symlink to /etc/apache2/sites-available/000-default.conf)

    Save & exit the “file” /etc/apache2/sites-enabled/000-default.conf

    By now, I’m sure the more seasoned & experiences Devs & Engineers are annoyed with my step-by-step for the n00bz. So this is where we would add in our own “custom” VirtualHost directive for Apache (aka vhost).

    Since we’re already in the apache directories, let’s do that now:

    Read this carefully:

    sudo nano /etc/apache/sites-available/domain-name-goes-here.com.conf

    Notice the difference between sites-enabled & sites-available. Very important for later.
    Also, obviously be sure to substitute your domain name (or even an IP address could potentially work) where you see: domain-name-goes-here.com

    You may have notice my super long path of:
    /var/www/vhosts/user_accountname/domain-name-goes-here.com/actual-web-site-doc-root

    You’ll need to change that to fit where ever your path is to your website DocumentRoot, below. I will suggest that if you plan on having more than one domain name hosted from your super nifty future bling bling tricked out nginx+Apache+Cloudflare site that we’re building now, that you at least separate your directory paths by one level instead of the 3 that I have shown as an example here. This will help keep your clients and their individual websites/apps separated and also give “one level up” for the actual website document root path to store certain content and provide some security. Sure, there’s a case against nesting too deeply due to “traversing” but CPUs are blistering fast nowadays. I wouldn’t worry about it. And that’s coming from an optimization enthusiast.

    Having a flexible directory structure to keep all your own projects as well as your client projects organized will probably help you out later down the road. You can also always symlink your directory tree to where ever you like on your server setup, too.

    Example file and directory structure in a crude & terrible, quick & dirty diagram that I’ll have to replace later:



    Anyway, edit your virtualhost .conf file to fit your directory layout.

    Save the file & exit.

    If you already have web content in your directory, cool. I’m assuming you do at least have an index.php or index.html/js/etc in your document root if you’re G enough to be looking into how to do a reverse proxy config in the first place. 😉

    Since we’re assuming a Debian-style default Apache setup (CentOS & RHEL don’t do this “sites-enabled” thing by default) we need to add a symlink to “enable it”. We can do that in two ways:

    or, use the apachectl tools with:

    There’s more to come with Apache, but for now, I’ll stop for the night and add the PHP7.4 install with all its modules and conf stuff, then onto nginx and the testing of the reverse proxy setup.

    I will go ahead and dump off the template for the nginx vhost.conf here to get that out of the way:

    j-merrill

    Justin Merrill, MBA, BS .:|:. Platform Engineer Engineer | Software | DevOps | CICD | Cloud | Security | IAM | SRE | K8s | GitOps | IaC | Data | APIs | Platform

    Leave a Reply

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

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