#cloud-config
# Cloud-init configuration for Nginx Proxy Server
# Routes Cloudflare traffic to backend Besu VMs across 5 US regions

package_update: true
package_upgrade: true

packages:
  - nginx
  - certbot
  - python3-certbot-nginx
  - curl
  - jq
  - wget
  - unzip
  - cloudflared

write_files:
  - path: /etc/nginx/nginx.conf
    content: |
      user www-data;
      worker_processes auto;
      pid /run/nginx.pid;
      
      events {
        worker_connections 1024;
        use epoll;
      }
      
      http {
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        
        log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
        
        access_log /var/log/nginx/access.log main;
        error_log /var/log/nginx/error.log warn;
        
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        client_max_body_size 20M;
        
        # Gzip compression
        gzip on;
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss;
        
        # Upstream backend servers (load balancing across 5 US regions)
        # NOTE: Backend VMs use private IPs only. Cross-region connectivity requires VPN/ExpressRoute
        # or Cloudflare Tunnel agents on each backend VM. For Phase 1, configure VPN or use
        # Cloudflare Tunnel on each backend VM to expose services.
        upstream besu_rpc_backend {
          least_conn;  # Load balancing method
          
          # Backend VMs from all regions (use private IPs - requires VPN/ExpressRoute for cross-region)
          %{ if length([for region, vms in backend_vms : length(vms.private_ips) > 0 ? 1 : 0]) > 0 ~}
          ${join("\n          ", [for region, vms in backend_vms : length(vms.private_ips) > 0 ? join("\n          ", [for idx, ip in vms.private_ips : "server ${ip}:8545 max_fails=3 fail_timeout=30s;"]) : "# No backend VMs in ${region}"])}
          %{ else ~}
          # No backend VMs configured - add default backend or configure backends
          server 127.0.0.1:8545 down;  # Placeholder - will return 502
          %{ endif ~}
        }
        
        upstream besu_ws_backend {
          least_conn;
          
          # Backend VMs from all regions (use private IPs - requires VPN/ExpressRoute for cross-region)
          %{ if length([for region, vms in backend_vms : length(vms.private_ips) > 0 ? 1 : 0]) > 0 ~}
          ${join("\n          ", [for region, vms in backend_vms : length(vms.private_ips) > 0 ? join("\n          ", [for idx, ip in vms.private_ips : "server ${ip}:8546 max_fails=3 fail_timeout=30s;"]) : "# No backend VMs in ${region}"])}
          %{ else ~}
          # No backend VMs configured - add default backend or configure backends
          server 127.0.0.1:8546 down;  # Placeholder - will return 502
          %{ endif ~}
        }
        
        # HTTP server (redirect to HTTPS)
        server {
          listen 80;
          server_name _;
          
          location /.well-known/acme-challenge/ {
            root /var/www/html;
          }
          
          location / {
            return 301 https://$host$request_uri;
          }
        }
        
        # HTTPS server
        server {
          listen 443 ssl http2;
          server_name _;
          
          # SSL configuration (will be updated by certbot)
          ssl_certificate /etc/letsencrypt/live/_/fullchain.pem;
          ssl_certificate_key /etc/letsencrypt/live/_/privkey.pem;
          ssl_protocols TLSv1.2 TLSv1.3;
          ssl_ciphers HIGH:!aNULL:!MD5;
          ssl_prefer_server_ciphers on;
          
          # Security headers
          add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" 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;
          
          # RPC HTTP endpoint
          location /rpc {
            proxy_pass http://besu_rpc_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_read_timeout 300s;
            proxy_connect_timeout 75s;
          }
          
          # WebSocket endpoint
          location /ws {
            proxy_pass http://besu_ws_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_read_timeout 3600s;
            proxy_connect_timeout 75s;
          }
          
          # Health check endpoint
          location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
          }
          
          # Metrics endpoint (if needed)
          location /metrics {
            deny all;
            return 403;
          }
        }
    permissions: '0644'
    owner: root:root

  - path: /opt/nginx/setup.sh
    content: |
      #!/bin/bash
      set -e
      
      ADMIN_USERNAME="${admin_username}"
      
      echo "Setting up Nginx Proxy Server..."
      
      # Create directories
      mkdir -p /var/www/html
      mkdir -p /etc/nginx/conf.d
      mkdir -p /etc/cloudflared
      
      # Test Nginx configuration
      nginx -t
      
      # Enable and start Nginx
      systemctl enable nginx
      systemctl restart nginx
      
      # Cloudflare Tunnel setup
      echo "Configuring Cloudflare Tunnel..."
      echo "NOTE: You need to run 'cloudflared tunnel login' and 'cloudflared tunnel create <tunnel-name>'"
      echo "      Then configure /etc/cloudflared/config.yml with your tunnel ID and credentials"
      echo "      See: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide/"
      
      # Create Cloudflare Tunnel systemd service (will be enabled after manual configuration)
      cat > /etc/systemd/system/cloudflared.service << 'EOF'
      [Unit]
      Description=Cloudflare Tunnel
      After=network.target
      
      [Service]
      Type=simple
      User=root
      ExecStart=/usr/bin/cloudflared tunnel --config /etc/cloudflared/config.yml run
      Restart=on-failure
      RestartSec=5s
      
      [Install]
      WantedBy=multi-user.target
      EOF
      
      # Create placeholder config file
      cat > /etc/cloudflared/config.yml << 'EOF'
      # Cloudflare Tunnel Configuration
      # Replace with your actual tunnel ID and credentials after running:
      #   cloudflared tunnel login
      #   cloudflared tunnel create <tunnel-name>
      #
      # Example configuration:
      # tunnel: <your-tunnel-id>
      # credentials-file: /etc/cloudflared/<tunnel-id>.json
      #
      # ingress:
      #   - hostname: your-domain.com
      #     service: http://localhost:443
      #   - service: http_status:404
      EOF
      
      chmod 600 /etc/cloudflared/config.yml
      
      echo "Nginx Proxy setup complete!"
      echo "Backend regions configured: ${join(", ", keys(backend_vms))}"
      echo ""
      echo "Next steps:"
      echo "1. SSH to this server: ssh ${admin_username}@<nginx-proxy-public-ip>"
      echo "2. Run: cloudflared tunnel login"
      echo "3. Run: cloudflared tunnel create <tunnel-name>"
      echo "4. Update /etc/cloudflared/config.yml with tunnel ID and ingress rules"
      echo "5. Enable and start: systemctl enable cloudflared && systemctl start cloudflared"
    permissions: '0755'
    owner: root:root

runcmd:
  - /opt/nginx/setup.sh
  - systemctl status nginx

final_message: "Nginx Proxy Server setup complete. Configure SSL with certbot after DNS is set up."

