Backend container is exposed on host port 3801, not 3001. This was preventing webhooks and API calls from reaching the backend.
202 lines
7.5 KiB
Plaintext
202 lines
7.5 KiB
Plaintext
# /etc/nginx/sites-available/puffinoffset.com
|
|
|
|
# 1) Redirect all HTTP to HTTPS, except the ACME challenge path
|
|
server {
|
|
listen 80;
|
|
server_name puffinoffset.com;
|
|
|
|
# Allow certbot to do HTTP-01 challenges
|
|
location ^~ /.well-known/acme-challenge/ {
|
|
root /var/www/html; # adjust if your webroot differs
|
|
try_files $uri =404;
|
|
}
|
|
|
|
# Redirect everything else to HTTPS
|
|
location / {
|
|
return 301 https://$host$request_uri;
|
|
}
|
|
}
|
|
|
|
# 2) HTTPS server block: reverse-proxy to your Docker app on localhost:3800
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name puffinoffset.com;
|
|
|
|
# === SSL certs from Let's Encrypt ===
|
|
# ssl_certificate /etc/letsencrypt/live/puffinoffset.com/fullchain.pem;
|
|
# ssl_certificate_key /etc/letsencrypt/live/puffinoffset.com/privkey.pem;
|
|
include /etc/letsencrypt/options-ssl-nginx.conf; # from certbot
|
|
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # from certbot
|
|
|
|
# === Proxy for direct image requests from Wren API ===
|
|
location ~* ^/images/(.*)$ {
|
|
proxy_pass https://www.wren.co/images/$1;
|
|
proxy_ssl_server_name on;
|
|
proxy_set_header Host www.wren.co;
|
|
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;
|
|
proxy_buffers 16 4k;
|
|
proxy_buffer_size 2k;
|
|
|
|
# Add CORS headers for images
|
|
add_header Access-Control-Allow-Origin '*' always;
|
|
add_header Access-Control-Allow-Methods 'GET, OPTIONS' always;
|
|
add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
|
|
|
|
# Cache control for images
|
|
expires 7d;
|
|
add_header Cache-Control "public, max-age=604800";
|
|
|
|
# Handle OPTIONS requests for CORS preflight
|
|
if ($request_method = 'OPTIONS') {
|
|
add_header Access-Control-Allow-Origin '*';
|
|
add_header Access-Control-Allow-Methods 'GET, OPTIONS';
|
|
add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization';
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Type 'text/plain charset=UTF-8';
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
}
|
|
|
|
# === Proxy for Wren API requests ===
|
|
location /api/wren/ {
|
|
proxy_pass https://www.wren.co/api/;
|
|
proxy_ssl_server_name on;
|
|
proxy_set_header Host www.wren.co;
|
|
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;
|
|
|
|
# Add CORS headers for API requests
|
|
add_header Access-Control-Allow-Origin '*' always;
|
|
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
|
|
add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
|
|
|
|
# Handle OPTIONS requests for CORS preflight
|
|
if ($request_method = 'OPTIONS') {
|
|
add_header Access-Control-Allow-Origin '*';
|
|
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
|
|
add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization';
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Type 'text/plain charset=UTF-8';
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
}
|
|
|
|
# === Backend API - Stripe Webhooks (specific route, no trailing slash) ===
|
|
location = /api/webhooks/stripe {
|
|
proxy_pass http://127.0.0.1:3801/api/webhooks/stripe;
|
|
proxy_http_version 1.1;
|
|
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;
|
|
|
|
# Stripe requires raw body for signature verification
|
|
proxy_request_buffering off;
|
|
|
|
# CORS headers
|
|
add_header Access-Control-Allow-Origin '*' always;
|
|
add_header Access-Control-Allow-Methods 'POST, OPTIONS' always;
|
|
add_header Access-Control-Allow-Headers 'Content-Type, Stripe-Signature' always;
|
|
}
|
|
|
|
# === Backend API - All other API routes ===
|
|
location /api/ {
|
|
proxy_pass http://127.0.0.1:3801/;
|
|
proxy_http_version 1.1;
|
|
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;
|
|
|
|
# CORS headers for API
|
|
add_header Access-Control-Allow-Origin '*' always;
|
|
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS' always;
|
|
add_header Access-Control-Allow-Headers 'Content-Type, Authorization' always;
|
|
|
|
# API timeouts
|
|
proxy_read_timeout 120;
|
|
proxy_connect_timeout 120;
|
|
proxy_send_timeout 120;
|
|
|
|
# Handle OPTIONS for CORS preflight
|
|
if ($request_method = 'OPTIONS') {
|
|
add_header Access-Control-Allow-Origin '*';
|
|
add_header Access-Control-Allow-Methods 'GET, POST, PUT, DELETE, OPTIONS';
|
|
add_header Access-Control-Allow-Headers 'Content-Type, Authorization';
|
|
add_header Access-Control-Max-Age 1728000;
|
|
add_header Content-Length 0;
|
|
return 204;
|
|
}
|
|
}
|
|
|
|
# === Proxy all other traffic to Frontend ===
|
|
location / {
|
|
proxy_pass http://127.0.0.1:3800;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
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;
|
|
|
|
# Add CORS headers for all responses
|
|
add_header Access-Control-Allow-Origin '*' always;
|
|
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS' always;
|
|
add_header Access-Control-Allow-Headers 'Origin, X-Requested-With, Content-Type, Accept, Authorization' always;
|
|
|
|
# Increase timeouts for potentially slow API calls
|
|
proxy_read_timeout 120;
|
|
proxy_connect_timeout 120;
|
|
proxy_send_timeout 120;
|
|
}
|
|
|
|
# === Additional common settings ===
|
|
|
|
# Increase client body size for file uploads if needed
|
|
client_max_body_size 10M;
|
|
|
|
# Enable compression for better performance
|
|
gzip on;
|
|
gzip_comp_level 5;
|
|
gzip_min_length 256;
|
|
gzip_proxied any;
|
|
gzip_vary on;
|
|
gzip_types
|
|
application/atom+xml
|
|
application/javascript
|
|
application/json
|
|
application/ld+json
|
|
application/manifest+json
|
|
application/rss+xml
|
|
application/vnd.geo+json
|
|
application/vnd.ms-fontobject
|
|
application/x-font-ttf
|
|
application/x-web-app-manifest+json
|
|
application/xhtml+xml
|
|
application/xml
|
|
font/opentype
|
|
image/bmp
|
|
image/svg+xml
|
|
image/x-icon
|
|
text/cache-manifest
|
|
text/css
|
|
text/plain
|
|
text/vcard
|
|
text/vnd.rim.location.xloc
|
|
text/vtt
|
|
text/x-component
|
|
text/x-cross-domain-policy;
|
|
|
|
# Optional: serve static assets directly if you ever add any here
|
|
# location /static/ {
|
|
# root /var/www/puffinoffset.com;
|
|
# try_files $uri $uri/ =404;
|
|
# }
|
|
}
|