Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ services:
container_name: tinyurl-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./infra/nginx/nginx.prod.conf:/etc/nginx/nginx.conf:ro
- /etc/letsencrypt:/etc/letsencrypt:ro
depends_on:
app:
condition: service_healthy
Expand Down
44 changes: 34 additions & 10 deletions infra/nginx/nginx.prod.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,32 @@ http {
# -----------------------------------------------------------------------
# Real IP Resolution
#
# Traffic path: Client → Cloudflare → ALB → nginx
# Without this, $remote_addr = ALB private IP (10.x.x.x) for every request.
# Rate limiting keyed on ALB IP = all users share one limit = broken.
# Traffic path: Client → Cloudflare → nginx (no ALB)
# Without this, $remote_addr = Cloudflare edge IP for every request.
# Rate limiting keyed on Cloudflare IP = all users share one limit = broken.
#
# set_real_ip_from: trust the VPC (ALB) to forward the real client IP.
# set_real_ip_from: trust Cloudflare's published IP ranges.
# real_ip_header: read real client IP from Cloudflare's CF-Connecting-IP.
# real_ip_recursive: strip known proxy IPs from the chain to find the origin.
#
# After this, $remote_addr = actual client IP for all directives below.
# Cloudflare IP ranges: https://www.cloudflare.com/ips/
# -----------------------------------------------------------------------
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
real_ip_header CF-Connecting-IP;
real_ip_recursive on;

Expand Down Expand Up @@ -83,9 +96,21 @@ http {
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json;

# HTTP → HTTPS redirect
server {
listen 80;
server_name go.buffden.com;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name go.buffden.com;

ssl_certificate /etc/letsencrypt/live/go.buffden.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/go.buffden.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

# -------------------------------------------------------------------
# Block malicious scanner tools by User-Agent
Expand Down Expand Up @@ -213,9 +238,8 @@ http {
}

# -------------------------------------------------------------------
# ALB Health Check — must be before the /actuator/ block
# ALB targets port 80 on EC2 and checks this path every 30s.
# If this returns anything other than 200, the target goes Unhealthy.
# Health Check endpoint — must be before the /actuator/ block
# Used by monitoring and CI/CD deploy verification.
# -------------------------------------------------------------------
location = /actuator/health {
proxy_pass http://app:8080;
Expand Down
Loading