This tutorial will show you how to set up an Nginx proxy serving static content such as images directly and pass dynamic queries onto Apache.

In the last tutorial we set up Nginx, a lightweight and fast web server, as a front-end in Debian 9 to proxy requests to Apache web servers in the back end. We can take advantage of the power and flexibility of Apache to serve dynamic PHP content, such as a WordPress website. Also we can also make good use of the speed and small memory footprint of Nginx to serve the static content.

When it comes to serving static content directly with Nginx, I’ve had issues when serving SSL content with Nginx is the SSL termination. If you are proxying internally, there is no need to use SSL for traffic between Nginx and Apache. It makes sense to use Nginx as your SSL termination. In this tutorial I will only go into setting up Nginx to serve static content directly over HTTP. Once I sort out my issues with SSL, I’ll do a future tutorial.

Lets assume you’re serving content over HTTP only, and you have separate server entries in your nginx virtual host, or preferably, separate files for each virtual host, as I showed in the previous post. If you’re running a WordPress website on, as per the previous example, the following setup should work: It will use Nginx to serve any content that it knows how to serve directly, and proxy requests that end in .php to Apache (update red areas with your own configuration):

server {
	listen 80;
 root /var/www/;
	index index.php;
 location / {
		try_files $uri $uri/ /index.php;
	location ~ \\.php$ {
        proxy_pass http://localhost:8080$request_uri;
        proxy\_set\_header Host $host;
        proxy\_set\_header X-Real-IP $remote_addr;
        proxy\_set\_header X-Forwarded-For $remote_addr;
        proxy\_set\_header X-Forwarded-Proto $scheme;

 location ~ /\\. {
		deny all;

Location sections are evaluated by Nginx in the order that they appear in the file. This means that in our example Nginx would evaluate the first location block, and try to serve the request directly if it can find it in the document root we gave earlier (root /var/www/;). Thus it will first try the URI, then the URI ending in /, and if this also fails, passing the request to index.php.

The second location block then sends any requests ending in .php to Apache, using the same structure we have used in previous posts.

If you use Nginx to directly serve content, rather than proxying everything to Apache, then I’d highly recommend implementing security policies at the Nginx level.

Happy serving!