events {}
http {
  # MIME types — without this, nginx serves every file as text/plain, and
  # browsers (with X-Content-Type-Options: nosniff set by Django) refuse to
  # apply CSS / execute JS / render SVG. Stylesheets silently fail.
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  sendfile on;
  tcp_nopush on;
  keepalive_timeout 65;

  gzip on;
  gzip_proxied any;
  gzip_vary on;
  gzip_min_length 1024;
  gzip_comp_level 5;
  gzip_types
    text/plain
    text/css
    text/xml
    text/html
    application/json
    application/javascript
    application/xml
    application/xml+rss
    image/svg+xml;

  client_max_body_size 100m;

  # Increase proxy buffering so larger Django responses (HTML with hundreds of
  # static refs, JSON exports) don't spill to disk. 4 buffers x 64k matches a
  # comfortable 256k working set per request.
  proxy_buffer_size 16k;
  proxy_buffers 4 64k;
  proxy_busy_buffers_size 128k;

  # 60s upstream timeout — long enough for heavy reports / exports, short
  # enough that hung requests don't pile up.
  proxy_connect_timeout 30s;
  proxy_send_timeout 60s;
  proxy_read_timeout 60s;

  # Docker's embedded DNS resolver (127.0.0.11). The `valid=10s` cache + variable
  # upstream below force nginx to re-resolve `web` periodically, so a recreated
  # web container (new IP) gets picked up automatically instead of producing
  # 502s until nginx is manually restarted.
  resolver 127.0.0.11 valid=10s ipv6=off;

  server {
    listen 80;
    server_name _;

    location /static/ {
      alias /app/staticfiles/;
      access_log off;
      expires 30d;
      add_header Cache-Control "public, immutable";
    }

    location /uploads/ {
      alias /app/uploads/;
      access_log off;
    }

    location / {
      set $upstream http://web:8000;
      proxy_pass $upstream;
      # $host strips the port (e.g. becomes "173.249.17.166" even when the
      # browser hit ":8001"), so any URL Django builds from request.get_host()
      # — password reset links being the sharpest example — silently drops
      # to the default port and points at the wrong server block/database.
      # $http_host preserves whatever the client actually sent.
      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_redirect off;
    }
  }

  # Moodle (rep.ruforum.org) — the LMS, proxied to the `moodle` service. A
  # specific server_name wins over the catch-all `_` web block above, so only
  # the rep.ruforum.org host reaches Moodle; iilmp.ruforum.org / IP stay on web.
  # Cloudflare (Flexible) terminates TLS and forwards X-Forwarded-Proto: https,
  # which Moodle (MOODLE_REVERSEPROXY + $CFG->sslproxy) uses to build https URLs.
  server {
    listen 80;
    server_name rep.ruforum.org;

    # Course backups / restores and file uploads can be large.
    client_max_body_size 200m;

    location / {
      set $upstream http://moodle:8080;
      proxy_pass $upstream;
      # Preserve the host so Moodle sees rep.ruforum.org (matches its wwwroot and
      # avoids a 303 redirect loop). $http_host keeps any port the client sent.
      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_redirect off;
    }
  }

  # Demo environment — seeded fake data, safe for testers.
  # Accessible at http://<server-ip>:8001
  server {
    listen 8001;
    server_name _;

    location /static/ {
      alias /app/staticfiles/;
      access_log off;
      expires 30d;
      add_header Cache-Control "public, immutable";
    }

    # web_demo writes uploads to the `demo_uploads` volume (mounted here at
    # /app/demo_uploads), NOT the prod `uploads_data`. Serve from there so demo
    # media resolves instead of 404ing against the prod volume.
    location /uploads/ {
      alias /app/demo_uploads/;
      access_log off;
    }

    location / {
      set $upstream http://web_demo:8000;
      proxy_pass $upstream;
      # $host strips the port (e.g. becomes "173.249.17.166" even when the
      # browser hit ":8001"), so any URL Django builds from request.get_host()
      # — password reset links being the sharpest example — silently drops
      # to the default port and points at the wrong server block/database.
      # $http_host preserves whatever the client actually sent.
      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_redirect off;
    }
  }
}
