How to Set Up NGINX as a Reverse Proxy for Apache on Debian and Ubuntu

Learn how to setup NGINX as a reverse proxy for Apache on Debian and Ubuntu to improve performance.

Publish date: 10/22/2024

Using NGINX as a reverse proxy in front of Apache can significantly improve the performance and scalability of your web server. You can combine the strengths of both web servers.

That said, in this comprehensive guide, we'll walk you through the process of setting up NGINX as a reverse proxy for Apache on Ubuntu and Debian, two popular free and open-source Linux distributions. We'll also cover various configuration examples for different use cases.

But first:

Why use NGINX as a reverse proxy?

Setting up NGINX as a reverse proxy for Apache offers multiple benefits, here's a few key ones:

  • Performance: NGINX is well-known for its efficiency in serving static content like images, CSS, and JavaScript. By handling static content with NGINX, Apache can focus on dynamic content, leading to better overall performance and reduced load on Apache.
  • Load balancing: NGINX excels as a load balancer. It can distribute incoming traffic across multiple Apache servers (or other backend servers), allowing for greater scalability and ensuring that no single server gets overwhelmed by traffic.
  • Enhanced security: Using NGINX as a reverse proxy adds a layer of security. Since NGINX handles incoming requests and passes them to Apache, it prevents Apache from being directly exposed to the internet, which reduces the risk of attacks.

Step 1: Install NGINX and Apache

First, ensure that your system is updated and both NGINX and Apache are installed on your system.

Update and install NGINX:

sudo apt update
sudo apt install nginx -y

Start NGINX and enable it to start at boot:

sudo systemctl start nginx
sudo systemctl enable nginx

Install Apache:

sudo apt install apache2 -y

Step 2: Configure Apache to use a different port

Before starting Apache, we need to configure it to listen on a different port, as both NGINX and Apache use port 80 by default.

Edit the Apache ports configuration file:

sudo nano /etc/apache2/ports.conf

Find the line:

Listen 80

Change it to:

Listen 8080

Save the file and exit nano (press Ctrl+X, then type y and press Enter).

Next, update the virtual host configuration.

On Ubuntu/Debian, the default virtual host file is located at /etc/apache2/sites-available/000-default.conf:

sudo nano /etc/apache2/sites-available/000-default.conf

Ensure the <VirtualHost> block reflects the new port:

<VirtualHost *:8080>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
</VirtualHost>

Save and exit the file.

Now restart Apache for the changes to take effect:

sudo systemctl restart apache2

Apache will now run on port 8080.

Step 3: Configure NGINX as a reverse proxy

Now we'll configure NGINX to act as a reverse proxy, forwarding requests to Apache running on port 8080.

Edit the default NGINX server block configuration file:

sudo nano /etc/nginx/sites-available/default

Within the server block, configure NGINX to forward requests to Apache and serve static files:

server {
    listen 80;
    server_name your_domain_or_ip;

    # Serve static files directly with NGINX
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        root /var/www/html;
    }

    # Forward other requests to Apache 
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /var/www/html;
    }
}

This setup:

  • Serves static files (images, CSS, JS) directly with NGINX
  • Forwards other requests to Apache
  • Ensures proper forwarding of headers

Save and exit the file.

Step 4: Test the configuration and restart NGINX

Before restarting NGINX, check the configuration for syntax errors:

sudo nginx -t

If there are no errors, restart NGINX:

sudo systemctl restart nginx

Step 5: Adjust firewall settings

If ufw (Uncomplicated Firewall) is active on your Ubuntu server, you need to allow HTTP (port 80) and HTTPS (port 443) traffic for NGINX.

Debian shouldn't come with a firewall by default. ufw is a great option, however.

And since Apache is running behind NGINX, you don't need to expose port 8080 to external traffic.

Allow HTTP and HTTPS traffic:

sudo ufw allow 'Nginx Full'
sudo ufw reload

Step 6: Verify the setup

To verify the setup, we'll test both dynamic content (PHP) and static content (an image).

Testing with a PHP file

  1. First, make sure PHP is installed and enabled for Apache:

    sudo apt install php libapache2-mod-php -y
    sudo systemctl restart apache2
    
  2. Create a test PHP file in Apache's document root:

    sudo nano /var/www/html/test.php
    
  3. Add the following content to the file:

    <?php
    phpinfo();
    ?>
    
  4. Save and exit the file.

  5. Now, access this file through your web browser by navigating to:

http://your_server_ip/test.php

If everything is set up correctly, you should see the PHP info page.

Testing with an image file

  1. Let's add a sample image to test NGINX's static file serving:

    sudo wget https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Nginx_logo.svg/1280px-Nginx_logo.svg.png -O /var/www/html/nginx-logo.png
    
  2. Now, access this image through your web browser:

http://your_server_ip/nginx-logo.png

You should see the NGINX logo. To confirm that NGINX (not Apache) served this file, check NGINX's access log:

sudo tail -f /var/log/nginx/access.log

You should see a log entry for the image request.

To confirm that Apache is receiving the forwarded requests for PHP, check Apache's access logs:

sudo tail -f /var/log/apache2/access.log

You should see the requests being forwarded from NGINX to Apache for PHP files, but not for the image file.

Remember to remove or secure the test PHP file after confirming the setup:

sudo rm /var/www/html/test.php

Advanced NGINX configuration examples

Here are some advanced configuration examples for different scenarios:

Load balancing configuration

For distributing traffic among multiple backend servers:

upstream myapp1 {
    server backend1.example.com;
    server backend2.example.com;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://myapp1;
        proxy_next_upstream error timeout;
        # Additional settings...
    }
}  

Caching responses

To enable caching of responses from the proxied server:

http {
    proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

    server {
        location / {
            proxy_pass http://backend.example.com;
            proxy_cache my_cache;
        }
    }
}

SSL configuration

For secure connections to the proxied server:

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/certificate.key;

    location / {
        proxy_pass https://backend.example.com;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Fine-tuning proxy settings

For advanced configurations and performance tuning:

location / {
    proxy_pass http://backend.example.com;
    proxy_buffering off;
    proxy_buffer_size 4k;
    proxy_connect_timeout 60s; 
    proxy_read_timeout 60s;
    proxy_send_timeout 60s;
}

Conclusion

Setting up NGINX as a reverse proxy in front of Apache can significantly improve your server's performance by offloading static content to NGINX, allowing Apache to focus on dynamic content.

This setup also adds an extra layer of security and scalability to your web server infrastructure, making it an ideal choice for handling growing traffic and demanding web applications.

Thanks for reading!

If you're looking for reliable infrastructure to support your web server setup, xTom provides a range of solutions, including dedicated servers, colocation, IP transit services, and more.

Additionally, for flexible and scalable virtual private servers, V.PS offers NVMe VPS hosting.