Set up Nginx

Gisia runs in Docker and publishes its web port on 127.0.0.1:8080. In production you put Nginx in front of it as a reverse proxy, so you can serve your own domain, terminate HTTPS, and allow large Git pushes.

This guide keeps the config small. Start with plain HTTP, then add HTTPS once it works.

HTTP for a local network

Create /etc/nginx/sites-available/gisia:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name gisia.example.com;

    client_max_body_size 0;

    location / {
        proxy_pass http://127.0.0.1:8080;

        proxy_http_version 1.1;
        proxy_set_header Host              $http_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 $scheme;

        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_read_timeout    300;
        proxy_connect_timeout 300;
        proxy_redirect        off;
    }
}

Enable it and reload:

ln -s /etc/nginx/sites-available/gisia /etc/nginx/sites-enabled/gisia
nginx -t
systemctl reload nginx

What each setting does

  • map $http_upgrade — declared once at the top of the file, outside the server block. It powers the WebSocket upgrade so live features keep their connection.
  • client_max_body_size 0 — removes Nginx’s upload cap and lets Gisia enforce its own limits. Without this, large Git pushes and file uploads fail with 413 Request Entity Too Large.
  • Host $http_host — passes the host and port so Gisia builds correct URLs.
  • X-Forwarded-Proto $scheme — tells Gisia whether the original request was HTTP or HTTPS. Do not hard-code this value.
  • proxy_http_version 1.1 + Upgrade / Connection — required for WebSocket connections to be proxied instead of dropped.
  • proxy_read_timeout 300 — some clone and pipeline requests take longer than Nginx’s 60s default.

HTTPS for public access

Once HTTP works, get a certificate and switch to HTTPS. Redirect all HTTP traffic to HTTPS, and serve the app on 443:

server {
    listen 80;
    server_name gisia.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    http2 on;
    server_name gisia.example.com;

    ssl_certificate     /etc/letsencrypt/live/gisia.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/gisia.example.com/privkey.pem;

    client_max_body_size 0;

    location / {
        proxy_pass http://127.0.0.1:8080;

        proxy_http_version 1.1;
        proxy_set_header Host              $http_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 $scheme;

        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_read_timeout    300;
        proxy_connect_timeout 300;
        proxy_redirect        off;
    }
}

Keep the map $http_upgrade block from the HTTP example at the top of the file — it is shared by both servers.

Because HTTPS now terminates at Nginx, X-Forwarded-Proto $scheme reports https to Gisia, so redirects, secure cookies, and generated links all use https://.