1. Posts/

Nginx as Caching Proxy for Laravel

·2 mins

Caching is inevitable for higher traffic websites.
Even if you are not planning to hit high numbers you would still think about caching to speed up the website and reduce load to web servers.

Nginx to the rescue

One way to implement a cache layer is to use an Nginx proxy with an enabled proxy cache.
Wait, what..? Yes, Nginx can be used to cache your website and make it more like, well static.

Configuration

user  nginx;
worker_processes  auto;

error_log  stderr;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    proxy_cache_path  /tmp/nginx_cache levels=1:2 keys_zone=all:10m inactive=6h max_size=100m use_temp_path=off;
    
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    
    log_format  main  '$http_x_real_ip - $remote_user [$time_local] "$host" "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" $request_time $upstream_connect_time $upstream_header_time $upstream_response_time [$upstream_cache_status] $request_id';
    
    access_log  /var/log/nginx/access.log  main;
    
    sendfile        on;
    
    keepalive_timeout  65;
    
    # Add extra headers about server and cache state
    add_header X-Backend-Server $hostname;
    add_header X-Cache-Status $upstream_cache_status;
    add_header X-Cache-Date $upstream_http_date;
    
    server {
        listen 80;
    
        location / {
            # Normalize encoding for cache key
            set $encoding "";
            
            if ($http_accept_encoding ~ br) {
                set $encoding "br";
                break;
            }
            
            if ($http_accept_encoding ~ gzip) {
                set $encoding "gzip";
                break;
            }
            
            proxy_set_header Accept-Encoding $encoding;
            
            proxy_cache all;
            proxy_force_ranges on;
            proxy_cache_lock on;
            proxy_cache_use_stale updating error timeout http_500 http_503 http_504 http_429;
            proxy_cache_key $scheme://$host$encoding$uri$is_args$query_string;
            proxy_cache_bypass $arg_should_bypass_cache;
            
            proxy_pass_request_headers on;
            proxy_set_header Host $host;
            proxy_pass http://example.com/; # Adjust with proper URL
        }
    }
}

Laravel headers

Nginx respects cache headers, so the origin server has to be configured to provide valid headers for caching.
This can be done by using Laravel’s built-in cache control middleware.

Route::get('/')
    ->middleware('cache.headers:public;max_age=3600')
    ->uses(Controllers\HomepageController::class)
    ->name('home');

But…
There is one drawback if website uses cookies…
It is quite pointless to statically cache user-focused websites, read here why.

Happy caching!

References