Skip to content
Cloudzyro

How to Set Up Nginx Reverse Proxy Caching

Updated

A reverse proxy cache sits between visitors and your app. The first visitor to ask for a page gets it from your app, and Nginx keeps a copy. Everyone after them gets the copy, so pages load faster and your app does less work. This guide puts Nginx in front of an app running on port 3000, on Ubuntu or Debian.

1. Install Nginx

sudo apt update && sudo apt install nginx

On Rocky Linux, AlmaLinux or Fedora, use sudo dnf install nginx.

2. Create a cache

Add this line inside the http block of /etc/nginx/nginx.conf. It keeps cached pages in /var/cache/nginx, up to 1 GB, and drops any page nobody has asked for in 60 minutes.

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=site_cache:10m
                 max_size=1g inactive=60m use_temp_path=off;

3. Put the cache in front of your app

Create /etc/nginx/sites-available/example.com with this, changing the name and your app's address:

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_cache site_cache;
        proxy_cache_valid 200 301 302 10m;
        proxy_cache_valid 404 1m;
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        proxy_cache_background_update on;
        proxy_cache_lock on;

        # Never cache or serve cached pages to signed-in visitors.
        proxy_cache_bypass $cookie_session $http_authorization;
        proxy_no_cache $cookie_session $http_authorization;

        add_header X-Cache-Status $upstream_cache_status;
    }
}

Change $cookie_session to the name of your own login cookie. Nginx already refuses to cache responses that set a cookie or are marked private or no-store, and follows your app's Cache-Control header when it sends one.

Then switch the site on:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

4. Check the settings and reload

sudo nginx -t && sudo systemctl reload nginx

nginx -t finds mistakes before they take the site down. Reloading applies the change without dropping visitors.

5. Check it's caching

Ask for the same page twice and look at X-Cache-Status:

curl -sI http://example.com/ | grep -i x-cache-status

The first answer says MISS, the second HIT. BYPASS means a rule above skipped the cache, which is what you want for signed-in visitors.

What the settings do

  • proxy_cache_valid: How long a response is kept, by status code, when your app doesn't say with its own Cache-Control header.
  • proxy_cache_use_stale: Serves the last good copy while your app is down, slow or being refreshed, instead of an error.
  • proxy_cache_background_update: Refreshes an expired copy in the background while visitors still get the old one.
  • proxy_cache_lock: When many visitors ask for the same uncached page at once, only one request goes to your app.
  • proxy_cache_bypass: Skips the cache for a request when any of its values isn't empty or 0, like a session cookie.
  • proxy_no_cache: Doesn't save the response for those requests, so one visitor's page is never shown to another.
  • proxy_cache_min_uses: How many times a page must be asked for before it's cached. Useful to keep rarely visited pages out.

Clearing the cache

The free version of Nginx can't remove one page from the cache. To clear everything, delete the cached files, then reload:

sudo find /var/cache/nginx -type f -delete && sudo systemctl reload nginx

Shorter times in proxy_cache_valid mean you rarely need to.

Hosting with Cloudzyro?

You don't need any of this. Every site on Sites & Apps sits behind Cloudflare, which caches your images, styles and scripts close to your visitors and never caches pages for signed-in visitors. The cache is cleared for you each time a new version goes live.

More about Nginx

Skip the server set-up

Put your site online from your AI tool, Git or a zip, with caching and HTTPS done for you.