# /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;