# /etc/nginx/sites-available/rental.call2arm.com.conf # 機材予約システム nginx設定ファイル # アップストリーム定義 upstream rental_backend { # Docker内のアプリケーションサーバー server rental-app:3000 max_fails=3 fail_timeout=30s; # 将来の負荷分散用(必要に応じて追加) # server rental-app-2:3000 max_fails=3 fail_timeout=30s backup; # コネクション設定 keepalive 32; keepalive_requests 100; keepalive_timeout 60s; } # レート制限設定 limit_req_zone $binary_remote_addr zone=rental_api:10m rate=10r/m; limit_req_zone $binary_remote_addr zone=rental_auth:10m rate=5r/m; limit_req_zone $binary_remote_addr zone=rental_general:10m rate=100r/m; # 接続数制限 limit_conn_zone $binary_remote_addr zone=rental_conn:10m; # HTTP → HTTPS リダイレクト server { listen 80; listen [::]:80; server_name rental.call2arm.com; # Let's Encrypt認証用 location /.well-known/acme-challenge/ { root /var/www/html; } # その他はHTTPSにリダイレクト location / { return 301 https://$server_name$request_uri; } } # メインHTTPSサーバー server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name rental.call2arm.com; # SSL証明書設定(Let's Encrypt wildcard証明書) ssl_certificate /etc/letsencrypt/live/call2arm.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/call2arm.com/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/call2arm.com/chain.pem; # SSL設定強化 ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets off; # OCSP Stapling ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # セキュリティヘッダー add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always; add_header X-Frame-Options DENY always; add_header X-Content-Type-Options nosniff always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always; # Content Security Policy add_header Content-Security-Policy " default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://auth.worksmobile.com https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https: blob:; connect-src 'self' https://auth.worksmobile.com https://www.worksapis.com; frame-src 'self' https://auth.worksmobile.com; object-src 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests; " always; # 社内IP制限(本番運用時に有効化) # allow 192.168.0.0/16; # allow 10.0.0.0/8; # allow 172.16.0.0/12; # allow 127.0.0.1; # deny all; # 接続数制限 limit_conn rental_conn 20; # ログ設定 access_log /var/log/nginx/rental.call2arm.com.access.log combined; error_log /var/log/nginx/rental.call2arm.com.error.log warn; # クライアント設定 client_max_body_size 50m; client_body_timeout 60s; client_header_timeout 60s; client_body_buffer_size 128k; client_header_buffer_size 1k; large_client_header_buffers 4 4k; # 基本設定 root /var/www/html; index index.html; server_tokens off; # 圧縮設定 gzip on; gzip_vary on; gzip_min_length 1024; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml image/svg+xml; # ====================================== # ロケーション設定 # ====================================== # ヘルスチェックエンドポイント location /health { access_log off; proxy_pass http://rental_backend; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 5s; proxy_send_timeout 5s; proxy_read_timeout 5s; } # API エンドポイント location /api/ { # レート制限適用 limit_req zone=rental_api burst=5 nodelay; # プロキシ設定 proxy_pass http://rental_backend; 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; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; # タイムアウト設定 proxy_connect_timeout 30s; proxy_send_timeout 60s; proxy_read_timeout 60s; # バッファリング設定 proxy_buffering on; proxy_buffer_size 4k; proxy_buffers 8 4k; proxy_busy_buffers_size 8k; # キャッシュ無効化(API) proxy_cache_bypass $http_upgrade; add_header Cache-Control "no-cache, no-store, must-revalidate" always; add_header Pragma "no-cache" always; add_header Expires "0" always; } # 認証系エンドポイント(より厳しいレート制限) location ~ ^/api/(auth|login|logout) { limit_req zone=rental_auth burst=3 nodelay; proxy_pass http://rental_backend; 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; # 認証系タイムアウト(短め) proxy_connect_timeout 15s; proxy_send_timeout 30s; proxy_read_timeout 30s; } # LINE WORKS Webhook エンドポイント location /api/lineworks/webhook { # Webhook専用設定 proxy_pass http://rental_backend; 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; # Webhook最適化 proxy_buffering off; proxy_request_buffering off; proxy_connect_timeout 10s; proxy_send_timeout 10s; proxy_read_timeout 10s; # セキュリティ(LINE WORKSからのアクセスのみ) # allow 203.104.144.0/24; # LINE WORKS IP range # deny all; } # 静的ファイル(画像、CSS、JS) location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { proxy_pass http://rental_backend; # 長期キャッシュ expires 30d; add_header Cache-Control "public, immutable"; add_header Vary "Accept-Encoding"; # 圧縮有効化 gzip_static on; # アクセスログ無効化 access_log off; # ETag有効化 etag on; } # アップロードファイル location /uploads/ { proxy_pass http://rental_backend; # 中期キャッシュ expires 7d; add_header Cache-Control "public"; # セキュリティ(実行ファイル拒否) location ~* \.(php|pl|py|jsp|asp|sh|cgi)$ { deny all; } } # 管理画面(追加認証) location /admin { # 社内IPのみ許可(管理機能) # allow 192.168.1.0/24; # deny all; proxy_pass http://rental_backend; 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; # 管理画面タイムアウト(長め) proxy_connect_timeout 60s; proxy_send_timeout 120s; proxy_read_timeout 120s; } # メインアプリケーション(SPA対応) location / { # 一般利用のレート制限 limit_req zone=rental_general burst=20 nodelay; # プロキシ設定 proxy_pass http://rental_backend; 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; proxy_cache_bypass $http_upgrade; # タイムアウト設定 proxy_connect_timeout 30s; proxy_send_timeout 60s; proxy_read_timeout 60s; # SPA用設定(React Router対応) try_files $uri $uri/ @fallback; } # SPA フォールバック location @fallback { proxy_pass http://rental_backend; 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; } # ====================================== # セキュリティ・拒否設定 # ====================================== # 隠しファイル・ディレクトリの拒否 location ~ /\. { deny all; access_log off; log_not_found off; } # 機密ファイルの拒否 location ~* \.(env|config|ini|log|sql|bak|backup|old)$ { deny all; access_log off; log_not_found off; } # 不要なリクエストの拒否 location ~* \.(aspx|asp|myadmin|admin|wp-admin|phpmyadmin) { deny all; access_log off; log_not_found off; } # robots.txt location = /robots.txt { add_header Content-Type text/plain; return 200 "User-agent: *\nDisallow: /api/\nDisallow: /admin/\nAllow: /\n"; access_log off; } # ====================================== # エラーページ設定 # ====================================== # 404エラーページ error_page 404 /404.html; location = /404.html { proxy_pass http://rental_backend; internal; } # 5xxエラーページ error_page 500 502 503 504 /50x.html; location = /50x.html { proxy_pass http://rental_backend; internal; } # メンテナンスページ(必要時) # location / { # return 503; # } # error_page 503 @maintenance; # location @maintenance { # root /var/www/maintenance; # try_files /maintenance.html =503; # } } # ====================================== # SSL設定共通化(将来のマルチサイト用) # ====================================== # SSL設定テンプレート # include /etc/nginx/snippets/ssl-call2arm.com.conf; # SSL強化設定テンプレート # include /etc/nginx/snippets/ssl-params.conf;