diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index f29641d..5c8774f 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -1,25 +1,21 @@ # Production override — use with: # docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build # -# For SSL add docker-compose.ssl.yml as well: -# docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.ssl.yml up -d --build -# # What this changes from the base (dev) config: # - Backend: production Dockerfile (compiled JS, no watch, no devDeps) -# - Frontend: production Dockerfile (static build served by nginx, not Vite) +# - Frontend: production Dockerfile (static build served by nginx on port 3001) # - No source-code volume mounts (uses baked-in built code) # - Memory limits and health checks on backend +# - Tuned PostgreSQL for production workloads # - Restart policies for reliability +# +# SSL/TLS is handled at the host level (e.g., host nginx + certbot). +# The Docker nginx container listens on port 80 only. services: nginx: - ports: - - "80:80" - - "443:443" volumes: - ./nginx/production.conf:/etc/nginx/conf.d/default.conf:ro - - certbot_www:/var/www/certbot:ro - - certbot_conf:/etc/letsencrypt:ro restart: unless-stopped backend: @@ -81,16 +77,3 @@ services: redis: restart: unless-stopped - - certbot: - image: certbot/certbot:latest - volumes: - - certbot_www:/var/www/certbot - - certbot_conf:/etc/letsencrypt - networks: - - hoanet - entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --quiet; sleep 12h & wait $${!}; done'" - -volumes: - certbot_www: - certbot_conf: diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 410b311..b56bd2b 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -18,5 +18,5 @@ COPY --from=builder /app/dist /usr/share/nginx/html # Copy a small nginx config for SPA routing COPY nginx.conf /etc/nginx/conf.d/default.conf -EXPOSE 80 +EXPOSE 3001 CMD ["nginx", "-g", "daemon off;"] diff --git a/frontend/nginx.conf b/frontend/nginx.conf index cfbd098..e2a8a29 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -2,7 +2,7 @@ # The outer nginx reverse proxy forwards non-API requests here. server { - listen 80; + listen 3001; server_name _; root /usr/share/nginx/html; index index.html; diff --git a/nginx/production.conf b/nginx/production.conf index a53c192..9eec704 100644 --- a/nginx/production.conf +++ b/nginx/production.conf @@ -4,7 +4,7 @@ upstream backend { } upstream frontend { - server frontend:80; + server frontend:3001; keepalive 16; } @@ -22,44 +22,14 @@ proxy_buffer_size 16k; proxy_buffers 8 16k; proxy_busy_buffers_size 32k; -# Redirect HTTP → HTTPS +# Rate limit zone (10 req/s per IP for API) +limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; + +# HTTP server — SSL termination is handled by the host reverse proxy server { listen 80; server_name _; - location /.well-known/acme-challenge/ { - root /var/www/certbot; - } - - location / { - return 301 https://$host$request_uri; - } -} - -# HTTPS server -server { - listen 443 ssl; - # Replace with your hostname: - server_name staging.example.com; - - # --- TLS certificates --- - ssl_certificate /etc/letsencrypt/live/staging.example.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/staging.example.com/privkey.pem; - - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384'; - ssl_prefer_server_ciphers on; - ssl_session_cache shared:SSL:10m; - ssl_session_timeout 1d; - ssl_session_tickets off; - - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; - add_header X-Content-Type-Options nosniff always; - add_header X-Frame-Options SAMEORIGIN always; - - # --- Rate limit zone (10 req/s per IP for API) --- - limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s; - # --- API routes → backend --- location /api/ { limit_req zone=api_limit burst=30 nodelay; @@ -90,8 +60,6 @@ server { proxy_pass http://frontend; proxy_read_timeout 10s; proxy_connect_timeout 5s; - - # Cache static assets aggressively at the proxy level proxy_cache_bypass $http_upgrade; } } diff --git a/nginx/ssl.conf b/nginx/ssl.conf index bc398f7..7625aea 100644 --- a/nginx/ssl.conf +++ b/nginx/ssl.conf @@ -3,7 +3,7 @@ upstream backend { } upstream frontend { - server frontend:5173; + server frontend:3001; } # Redirect all HTTP to HTTPS