diff --git a/.github/workflows/deploy-ec2.yml b/.github/workflows/deploy-ec2.yml index 9c3b5b02..310d940b 100644 --- a/.github/workflows/deploy-ec2.yml +++ b/.github/workflows/deploy-ec2.yml @@ -66,6 +66,12 @@ jobs: docker compose -f docker-compose.yml -f docker-compose.prod.yml pull docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d + # Reload nginx so it picks up the new nginx.conf and re-resolves + # upstream IPs (auth/chat-api/frontend get fresh IPs after recreate) + docker compose -f docker-compose.yml -f docker-compose.prod.yml exec -T nginx nginx -t \ + && docker compose -f docker-compose.yml -f docker-compose.prod.yml exec -T nginx nginx -s reload \ + || echo "nginx reload skipped (container not running yet)" + # Run migrations (wait for postgres) sleep 8 docker compose exec -T chat-api alembic upgrade head 2>/dev/null || true diff --git a/nginx/nginx.conf b/nginx/nginx.conf index ab820831..af27f5c6 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -22,20 +22,28 @@ http { client_max_body_size 10M; - # Auth service — only direct auth endpoints + # Use Docker Compose's embedded DNS so upstream IPs are re-resolved + # on every request. Without this nginx caches the IP at startup and + # serves 502s after any upstream container is recreated by `compose up`. + resolver 127.0.0.11 valid=10s ipv6=off; + + # Auth service — strip /api prefix, then forward to auth:8001/auth/... location /api/auth/ { limit_req zone=api burst=10 nodelay; - proxy_pass http://auth:8001/auth/; + set $upstream_auth auth; + rewrite ^/api/auth/(.*)$ /auth/$1 break; + proxy_pass http://$upstream_auth:8001; 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; } - # Chat API — direct to backend for conversations + streaming + # Chat API — pass through /api/conversations* unchanged location /api/conversations { limit_req zone=api burst=20 nodelay; - proxy_pass http://chat-api:8002/api/conversations; + set $upstream_chat chat-api; + proxy_pass http://$upstream_chat:8002; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -49,9 +57,11 @@ http { chunked_transfer_encoding off; } - # Grafana (optional) + # Grafana (optional) — strip /grafana/ prefix location /grafana/ { - proxy_pass http://grafana:3000/; + set $upstream_grafana grafana; + rewrite ^/grafana/(.*)$ /$1 break; + proxy_pass http://$upstream_grafana:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; @@ -62,7 +72,8 @@ http { # Next.js handles its own /api/* routes (conversations, chat/stream) # and proxies to backend services internally via CHAT_API_URL env var location / { - proxy_pass http://frontend:3000; + set $upstream_frontend frontend; + proxy_pass http://$upstream_frontend:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;