Nginx for Finch

Nginx acts as a reverse proxy in front of your Finch application. Incoming requests hit Nginx first. Nginx then:

  • Serves static files (CSS, JS, images) directly from disk without touching Finch, which is much faster.
  • Proxies all other requests to the Finch server running on port 8085.
  • Handles WebSocket upgrades for paths like /ws and /debugger.
  • Forwards the real client IP address to Finch via headers.

Configuration File

The configuration below is the one used in the docker-live/ directory of the Finch repository. Place it at docker/nginx.conf and mount it into the Nginx container.

server {
    listen 8080;                          # Public-facing port
    server_name localhost;
    client_max_body_size 20M;             # Maximum upload size

    # Detect original scheme (HTTP/HTTPS) when behind another proxy
    set $real_scheme $http_x_forwarded_proto;
    if ($real_scheme = '') {
        set $real_scheme $scheme;
    }

    # Keep connections alive long enough for WebSocket
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;
    keepalive_timeout  3600s;

    # Serve static files from the public directory directly
    # Falls back to @dart (Finch) if the file does not exist
    location / {
        root /var/www/html;
        try_files /public$uri @dart;
    }

    # WebSocket routes require special headers for the protocol upgrade
    location ~ ^/(ws|debugger) {
        proxy_pass http://localhost:8085;

        proxy_http_version 1.1;
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $http_connection;

        proxy_set_header Host              $host;
        proxy_set_header X-Real-IP         $remote_addr;
        proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $real_scheme;

        proxy_buffering off;
        proxy_cache off;

        proxy_read_timeout    3600s;
        proxy_send_timeout    3600s;
        proxy_connect_timeout   60s;
        proxy_redirect off;
    }

    # Proxy all other requests to the Finch app
    location @dart {
        proxy_pass http://localhost:8085;
        proxy_pass_request_body    on;
        proxy_pass_request_headers on;

        proxy_set_header X-Real-IP          $remote_addr;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header Host               $http_host;
        proxy_set_header X-Forwarded-Proto  $real_scheme;
        proxy_set_header X-Forwarded-Host   $http_host;
        proxy_set_header X-Forwarded-Port   $server_port;
        proxy_set_header X-Original-Host    $http_host;
        proxy_redirect off;
    }
}

How Static File Serving Works

The try_files /public$uri @dart; directive means:

  1. Nginx looks for the requested file under /var/www/html/public/ (your publicDir).
  2. If found, Nginx serves it directly — Finch is never involved.
  3. If not found, Nginx forwards the request to Finch via the @dart named location.

This is important for performance: CSS, JS, and images are served by Nginx at near-zero cost.

Finch and Nginx Together with Docker Compose

In a Docker Compose setup, Finch and Nginx run as separate containers. Use the Nginx container's proxy_pass to point to the Finch container's hostname:

# Inside docker-compose, use container hostname
location @dart {
    proxy_pass http://finch:8085;  # 'finch' is the docker-compose service name
    ...
}
# docker-compose.yaml
services:
  finch:
    hostname: finch
    ports:
      - "8085:8085"
  nginx:
    image: nginx:latest
    ports:
      - "8080:8080"
    volumes:
      - ./public/:/var/www/html/public
      - ./docker/nginx.conf:/etc/nginx/conf.d/default.conf

See Docker for Finch for the full docker-compose.yaml example.