Some checks failed
Deploy to Test Environment / deploy-to-test (push) Has been cancelled
144 lines
5.6 KiB
Plaintext
144 lines
5.6 KiB
Plaintext
# docker/nginx/dev.conf
|
|
# ============================================================================
|
|
# Development Nginx Configuration (HTTPS)
|
|
# ============================================================================
|
|
# This configuration matches production by using HTTPS on port 443 with
|
|
# self-signed certificates generated by mkcert. Port 80 redirects to HTTPS.
|
|
#
|
|
# This allows the dev container to work the same way as production:
|
|
# - Frontend accessible on https://localhost (port 443)
|
|
# - Backend API on http://localhost:3001
|
|
# - Port 80 redirects to HTTPS
|
|
#
|
|
# IMPORTANT: Dual Hostname Configuration (localhost AND 127.0.0.1)
|
|
# ============================================================================
|
|
# The server_name directive includes BOTH 'localhost' and '127.0.0.1' to
|
|
# prevent SSL certificate errors when resources use different hostnames.
|
|
#
|
|
# Problem Scenario:
|
|
# 1. User accesses site via https://localhost/
|
|
# 2. Database stores image URLs as https://127.0.0.1/flyer-images/...
|
|
# 3. Browser treats these as different origins, showing ERR_CERT_AUTHORITY_INVALID
|
|
#
|
|
# Solution:
|
|
# - mkcert generates certificates valid for: localhost, 127.0.0.1, ::1
|
|
# - NGINX accepts requests to BOTH hostnames using the same certificate
|
|
# - Users can access via either hostname without SSL warnings
|
|
#
|
|
# The self-signed certificate is generated in Dockerfile.dev with:
|
|
# mkcert localhost 127.0.0.1 ::1
|
|
#
|
|
# This creates a certificate with Subject Alternative Names (SANs) for all
|
|
# three hostnames, allowing NGINX to serve valid HTTPS for each.
|
|
#
|
|
# See also:
|
|
# - Dockerfile.dev (certificate generation, ~line 69)
|
|
# - docs/FLYER-URL-CONFIGURATION.md (URL configuration details)
|
|
# - docs/development/DEBUGGING.md (SSL troubleshooting)
|
|
# ============================================================================
|
|
|
|
# HTTPS Server (main)
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
server_name localhost 127.0.0.1;
|
|
|
|
# SSL Configuration (self-signed certificates from mkcert)
|
|
ssl_certificate /app/certs/localhost.crt;
|
|
ssl_certificate_key /app/certs/localhost.key;
|
|
|
|
# Allow large file uploads (matches production)
|
|
client_max_body_size 100M;
|
|
|
|
# Proxy API requests to Express server on port 3001
|
|
location /api/ {
|
|
proxy_pass http://localhost:3001;
|
|
proxy_http_version 1.1;
|
|
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 $scheme;
|
|
}
|
|
|
|
# ============================================================================
|
|
# Bugsink Sentry API Proxy (for frontend error reporting)
|
|
# ============================================================================
|
|
# The frontend Sentry SDK cannot reach localhost:8000 directly from the browser
|
|
# because port 8000 is only accessible within the container network.
|
|
# This proxy allows the browser to send errors to https://localhost/bugsink-api/
|
|
# which NGINX forwards to the Bugsink container on port 8000.
|
|
#
|
|
# Frontend DSN format: https://localhost/bugsink-api/<project_id>
|
|
# Example: https://localhost/bugsink-api/2 for Frontend (Dev) project
|
|
#
|
|
# The Sentry SDK sends POST requests to /bugsink-api/<project>/store/
|
|
# This proxy strips /bugsink-api and forwards to http://localhost:8000/api/
|
|
# ============================================================================
|
|
location /bugsink-api/ {
|
|
proxy_pass http://localhost:8000/api/;
|
|
proxy_http_version 1.1;
|
|
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 $scheme;
|
|
|
|
# Allow large error payloads with stack traces
|
|
client_max_body_size 10M;
|
|
|
|
# Timeouts for error reporting (should be fast)
|
|
proxy_connect_timeout 10s;
|
|
proxy_send_timeout 30s;
|
|
proxy_read_timeout 30s;
|
|
}
|
|
|
|
# Proxy WebSocket connections for real-time notifications
|
|
location /ws {
|
|
proxy_pass http://localhost:3001;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
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 $scheme;
|
|
}
|
|
|
|
# Serve flyer images from static storage
|
|
location /flyer-images/ {
|
|
alias /app/public/flyer-images/;
|
|
expires 7d;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
|
|
# Proxy all other requests to Vite dev server on port 5173
|
|
location / {
|
|
proxy_pass http://localhost:5173;
|
|
proxy_http_version 1.1;
|
|
|
|
# WebSocket support for Hot Module Replacement (HMR)
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection 'upgrade';
|
|
proxy_set_header Host $host;
|
|
proxy_cache_bypass $http_upgrade;
|
|
|
|
# Forward real client IP
|
|
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;
|
|
}
|
|
|
|
# Security headers (matches production)
|
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
add_header X-XSS-Protection "1; mode=block" always;
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
}
|
|
|
|
# HTTP to HTTPS Redirect (matches production)
|
|
server {
|
|
listen 80;
|
|
listen [::]:80;
|
|
server_name localhost 127.0.0.1;
|
|
|
|
return 301 https://$host$request_uri;
|
|
}
|