Raja's Exocortex

Nginx Video on Demand Caching

Nginx setup for man-in-the-middle caching of video files.

# nginx virtual host configuration for content.example.com
# Filename: /etc/nginx/sites-enabled/content.example.com
# Video on Demand proxy cache

# Proxy cache location and details:
#   use_temp_path=off       - download directly into cache dir
#   levels=1:2
#   keys_zone=cache:32m   - due to range caching, we need larger cache to track more objects
#   inactive=1d   - expire all content every 24 hours, upstream video may change
#   max_size=50g;
proxy_cache_path /tmp/ng-cache use_temp_path=off levels=1:2 keys_zone=cache:32m inactive=1d max_size=50g;

server {

    listen 443 ssl;

    # Hostname of the original content server we are caching
    server_name content.example.com;

    # No local content is served, only proxy caching
    root /dev/null;

    location / {
    
        # Backend original content server (AWS CloudFront)
        proxy_pass        https://content.example.com;
        
        # AWS CloudFront requires us to pass hostname in the request for SNI to work
        proxy_ssl_server_name on;

        # Enable caching, ignore query string in cache
        proxy_cache       cache;
        proxy_cache_key   $host$uri$slice_range;

        # Never serve cached content to unauth users, revalidate all requests with OCS
        proxy_cache_valid      200 206 1s;
        proxy_cache_revalidate on;
        proxy_cache_use_stale  error timeout updating;
        
        # Permit a single backend request during cache update, hold other requests
        # If multiple users concurrently access uncached video, this ensures a single request
        # is sent to the OCS while all users requests are queued and then served from cache
        proxy_cache_lock  on;
        
        # Break backend response (videos) into 1MB chunks for caching
        slice             1m;
        proxy_set_header  Range $slice_range;

        # DEBUG: Value must always be "REVALIDATED" or "MISS"
        add_header X-Cache-Status $upstream_cache_status;
    }

    # DEBUG: Use self-signed certs
    include snippets/snakeoil.conf;

    # DEBUG: Remove this in production
    access_log  /var/log/nginx/cache-server-access.log;
    error_log   /var/log/nginx/cache-server-error.log;
}

# Redirect all http requests to https
server {
    listen 80;
    server_name content.example.com;

    return 301 https://$server_name$request_uri;
}