From 1579a47cad3ec021eab44edd4b68eb06a66e3b5b Mon Sep 17 00:00:00 2001 From: Vantz Stockwell Date: Sat, 21 Feb 2026 13:35:25 -0500 Subject: [PATCH] chore: Harden Docker and Nginx configuration - Pin NATS image to nats:2.10-alpine for reproducible builds - Add nginx healthcheck using wget (curl not present in alpine) - Upgrade nginx depends_on to use condition: service_started - Add proxy buffer directives to http block (prevents JWT/large-header truncation) - Add X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, and Referrer-Policy security headers to all SPA location blocks across all five server blocks Co-Authored-By: Claude Opus 4.6 --- docker/docker-compose.yml | 11 +++++++++-- docker/nginx.conf | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index cc9e8bb..e298e88 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -17,7 +17,7 @@ services: retries: 5 nats: - image: nats:latest + image: nats:2.10-alpine container_name: corrosion-nats command: - "--config=/etc/nats/nats.conf" @@ -77,7 +77,14 @@ services: - ./nginx.conf:/etc/nginx/nginx.conf:ro - map_data:/data/maps:ro depends_on: - - api + api: + condition: service_started + healthcheck: + test: ["CMD-SHELL", "wget -q --spider http://localhost:80/ || exit 1"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 10s volumes: pg_data: diff --git a/docker/nginx.conf b/docker/nginx.conf index 18c8895..4355e95 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -13,6 +13,11 @@ http { types_hash_max_size 2048; client_max_body_size 250M; # Map uploads up to 200MB + overhead + # Proxy buffer sizing — prevents JWT/large-header truncation on redirect + proxy_buffer_size 128k; + proxy_buffers 4 256k; + proxy_busy_buffers_size 256k; + # Gzip gzip on; gzip_types text/plain text/css application/json application/javascript text/xml; @@ -64,6 +69,11 @@ http { location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; + + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; } } @@ -86,6 +96,11 @@ http { location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; + + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; } } @@ -127,6 +142,11 @@ http { location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; + + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; } } @@ -146,6 +166,11 @@ http { location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; + + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; } }