upstream app_server { # In production we proxy to the 'web' service (gunicorn) listening on 8000 server web:8000; } server { listen 80; listen [::]:80; server_name _; # Write logs to the host-mounted folder so Promtail can scrape them access_log /var/log/rad/nginx.access.log combined; error_log /var/log/rad/nginx.error.log warn; client_max_body_size 100M; # Serve static files from the static volume location /static/ { alias /usr/src/app/static/; expires 30d; add_header Cache-Control "public, max-age=2592000"; } # Serve media files from the media volume. CORS handling preserved. set $cors ""; if ($http_origin ~* (https?://(localhost:5173|viewer\.penracourses\.org\.uk))) { set $cors $http_origin; } location /media { if ($request_method = OPTIONS ) { add_header 'Access-Control-Allow-Origin' $cors always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Headers' "Origin, X-Requested-With, Content-Type, Accept" always; add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; return 200; } add_header 'Access-Control-Allow-Origin' $cors always; alias /usr/src/app/media; } # Viewer / OHIF / other static frontends - mount these into the nginx container at deploy time location /viewer { alias /srv/www/viewer; index index.html; try_files $uri $uri/ /viewer/index.html; add_header Cache-Control "no-store, no-cache, must-revalidate"; add_header 'Cross-Origin-Resource-Policy' 'cross-origin'; } location /ohif { add_header 'Cross-Origin-Opener-Policy' 'same-origin' always; add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always; add_header 'Cross-Origin-Resource-Policy' 'same-site' always; alias /srv/www/ohif; try_files $uri /ohif/index.html; } # rts and other host-mounted folders location /rts { alias /srv/www/rts; } location /rota { alias /srv/proc/rota; autoindex on; } location /uploader { alias /srv/uploader; autoindex on; } # Reporter proxy - if you run a reporter service, set it up on the 'reporter' network name location ~ ^/reporter/(.*)$ { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; proxy_set_header Authorization $http_authorization; proxy_pass_header Authorization; proxy_pass http://reporter:5129/$1?$args; proxy_set_header X-Forwarded-Prefix /reporter; proxy_redirect http://reporter:5129/ /reporter/; } # Default proxy to the Django/gunicorn upstream location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_redirect off; proxy_buffering off; add_header 'Cross-Origin-Embedder-Policy' 'require-corp' always; add_header 'Cross-Origin-Resource-Policy' 'same-site' always; proxy_pass http://app_server; } # Default dev / health server block; keep 443 managed outside of docker unless you mount certs } # A minimal HTTPS server block that expects certs to be mounted at /etc/letsencrypt server { listen 443 ssl; listen [::]:443 ssl; server_name www.penracourses.org.uk penracourses.org.uk viewer.penracourses.org.uk; ssl_certificate /etc/letsencrypt/live/www.penracourses.org.uk/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.penracourses.org.uk/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; client_max_body_size 4G; # Write logs to the host-mounted folder so Promtail can scrape them access_log /var/log/rad/nginx.access.log combined; error_log /var/log/rad/nginx.error.log warn; # Same static/media handling as above location /static/ { alias /usr/src/app/static/; } location /media { alias /usr/src/app/media; } location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_redirect off; proxy_buffering off; proxy_pass http://app_server; } }