Skip to content

Nginx configuration

The core routing logic that makes PutFS work. Nginx decides what to handle itself (reads) and what to proxy to the API (writes, listings).

Routing

Two location blocks are needed to handle PutFS:

# Trailing slash → listing via API
location ~ /$ {
    proxy_pass http://api$uri$is_args$args;
}

# Everything else
location / {
    # PUT, DELETE → proxy to API
    limit_except GET HEAD {
        proxy_pass http://api;
    }
    # GET, HEAD → serve directly from disk
    root /data;
    try_files $uri =404;
}

How it works:

  • location ~ /$ catches paths ending in / (e.g. /my-dataset/) and proxies them to the API, which streams back the key listing.
  • location / catches everything else. limit_except GET HEAD means: for any method other than GET/HEAD, proxy to the API. GET and HEAD fall through to try_files, which serves the file directly from disk via sendfile – Python is never involved in the read path.

Minimal working config

worker_processes auto;
events {}
http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    access_log off;

    upstream api {
        server unix:/run/putfs/putfs.sock;
    }

    server {
        listen 80;

        location ~ /$ {
            proxy_pass http://api$uri$is_args$args;
        }

        location / {
            limit_except GET HEAD {
                proxy_pass http://api;
            }
            root /data;
            try_files $uri =404;
        }
    }
}

This is unauthenticated. For production, add auth and upload handling – see below.

What to add

Concern Where
Authentication Auth – map-based key+secret with path/method scoping, or auth_request
Upload size limits client_max_body_size 0; in the server block (default is 1MB)
Upload streaming proxy_request_buffering off; – avoids double disk I/O
Rate limiting limit_req_zone – see Nginx tuning
Timeouts client_body_timeout 300s; proxy_read_timeout 300s; for large files
Performance Nginx tuning – keepalive, gzip, high-concurrency settings