1+ # Rate limiting zones
2+ limit_req_zone $binary_remote_addr zone=one:10m rate=20r/s;
3+ limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
4+ limit_req_zone $binary_remote_addr zone=create:10m rate=5r/s;
5+
6+ # Bot server IP whitelist (replace with your bot server's IP)
7+ geo $bot_server {
8+ default 0;
9+ # Add your bot server IP here
10+ 127.0.0.1 1;
11+ }
12+
13+ server {
14+ listen 443 ssl;
15+ server_name example.com www.example.com;
16+
17+ ssl_certificate /etc/nginx/your-fullchain.pem;
18+ ssl_certificate_key /etc/nginx/your-private-key.pem;
19+
20+ # Security headers
21+ # Production CSP (strict)
22+ add_header Content-Security-Policy "default-src 'self'; connect-src 'self' https://lottie.host https://*.lottie.host https://cdnjs.cloudflare.com https://unpkg.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.cloudflare.com; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https://cdnjs.cloudflare.com https://unpkg.com https://cdn.jsdelivr.net; font-src 'self' https://cdn.jsdelivr.net; img-src 'self' data: https:; media-src 'self' https:;" always;
23+
24+ # Alternative CSP for development (more permissive)
25+ # add_header Content-Security-Policy "default-src 'self' https:; connect-src 'self' https:; style-src 'self' 'unsafe-inline' https:; script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https:; font-src 'self' https:; img-src 'self' data: https:; media-src 'self' https:;" always;
26+
27+ add_header X-Frame-Options "DENY" always;
28+ add_header X-Content-Type-Options "nosniff" always;
29+ add_header Referrer-Policy "strict-origin-when-cross-origin" always;
30+ add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
31+
32+ # Serve robots.txt directly
33+ location = /robots.txt {
34+ alias /static/robots.txt;
35+ add_header Content-Type text/plain;
36+ }
37+
38+ # Serve sitemap.xml directly
39+ location = /sitemap.xml {
40+ alias /static/sitemap.xml;
41+ add_header Content-Type application/xml;
42+ }
43+
44+ location /static/ {
45+ alias /static/;
46+ expires 1y;
47+ add_header Cache-Control "public, immutable";
48+
49+ # Ensure proper MIME types for JavaScript files
50+ location ~* \.js$ {
51+ add_header Content-Type "application/javascript";
52+ add_header X-Content-Type-Options "nosniff";
53+ }
54+
55+ # Ensure proper MIME types for CSS files
56+ location ~* \.css$ {
57+ add_header Content-Type "text/css";
58+ add_header X-Content-Type-Options "nosniff";
59+ }
60+
61+ # Handle other static file types
62+ location ~* \.(png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
63+ expires 1y;
64+ add_header Cache-Control "public, immutable";
65+ }
66+ }
67+
68+ # Rate limit for paste creation (more strict)
69+ location ~ ^/create/?$ {
70+ limit_req zone=create burst=8 nodelay;
71+ proxy_pass http://web:8000;
72+ proxy_set_header Host $host;
73+ proxy_set_header X-Real-IP $remote_addr;
74+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
75+ proxy_set_header X-Forwarded-Proto $scheme;
76+ }
77+
78+ # API endpoints with bot whitelist - separate locations for different access methods
79+ location ~ ^/api/ {
80+ # Check for bot token header first
81+ set $skip_rate_limit 0;
82+
83+ if ($http_x_bot_token = "your-secret-token") {
84+ set $skip_rate_limit 1;
85+ }
86+
87+ if ($bot_server = 1) {
88+ set $skip_rate_limit 1;
89+ }
90+
91+ # Apply rate limiting only if not whitelisted
92+ if ($skip_rate_limit = 0) {
93+ limit_req zone=api burst=15 nodelay;
94+ }
95+
96+ proxy_pass http://web:8000;
97+ proxy_set_header Host $host;
98+ proxy_set_header X-Real-IP $remote_addr;
99+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
100+ proxy_set_header X-Forwarded-Proto $scheme;
101+ }
102+
103+ # General rate limiting for all other requests
104+ location / {
105+ limit_req zone=one burst=25 nodelay;
106+ proxy_pass http://web:8000;
107+ proxy_set_header Host $host;
108+ proxy_set_header X-Real-IP $remote_addr;
109+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
110+ proxy_set_header X-Forwarded-Proto $scheme;
111+ }
112+ }
113+
114+ # Redirect HTTP to HTTPS
115+ server {
116+ listen 80;
117+ server_name example.com www.example.com;
118+ return 301 https://$host$request_uri;
119+ }
0 commit comments