Aimpress-site/server/nginx.conf
Vadym Samoilenko 7e67369600 Fix CSP violations: allow PostHog, TinaCMS visual editor framing
- script-src: add us-assets.i.posthog.com (TinaCMS bundles PostHog)
- connect-src: add us.i.posthog.com, us-assets.i.posthog.com
- frame-src: add ai-impress.com (TinaCMS visual editor iframes the site)
- font-src: add data: (TinaCMS font loading)
- X-Frame-Options: DENY → SAMEORIGIN (required for TinaCMS admin preview)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 22:03:33 +00:00

70 lines
3 KiB
Nginx Configuration File

server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Enable gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json;
# Cache static assets (Vite hashed filenames)
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Blog JSON/images - short cache for frequent updates
location /blog/ {
expires 10m;
add_header Cache-Control "public, must-revalidate";
try_files $uri /index.html;
}
# Chatbot API proxy
location /api/chat {
resolver 127.0.0.11 valid=30s;
set $chatbot_api http://aimpress-chatbot-api:8000;
proxy_pass $chatbot_api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Content-Type $http_content_type;
proxy_buffering off;
}
# API proxy to email service (resolver allows nginx to start even if email-api is down)
location /api/ {
resolver 127.0.0.11 valid=30s;
set $email_api http://aimpress-email-api:3001;
proxy_pass $email_api;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Content-Type $http_content_type;
}
# SEO headers
add_header X-Robots-Tag "index, follow" always;
# Reviews JSON - short cache
location = /reviews.json {
expires 1h;
add_header Cache-Control "public, must-revalidate";
}
# Security headers
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://cdn.mxpnl.com https://us-assets.i.posthog.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' data: https://fonts.gstatic.com; img-src 'self' data: https://lh3.googleusercontent.com https://www.googletagmanager.com; connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://*.google-analytics.com https://*.analytics.google.com https://api-js.mixpanel.com https://api.mixpanel.com https://*.mixpanel.com https://*.mxpnl.com https://*.amplitude.com https://content.tinajs.io https://*.tinajs.io https://api.tinajs.io https://us.i.posthog.com https://us-assets.i.posthog.com; frame-src https://www.youtube.com https://ai-impress.com; media-src 'self'; worker-src 'self' blob:;" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
# SPA fallback
location / {
try_files $uri $uri/ /index.html;
}
error_page 404 /index.html;
}