# Nginx Configurations for VMIDs 2400-2508

**Date**: 2026-01-27  
**Status**: Current Active Configurations

---

## Summary

| VMID | Active Config | Status | Purpose |
|------|---------------|--------|---------|
| 2400 | `rpc-thirdweb` | ✅ Active | ThirdWeb RPC endpoint (Cloudflare Tunnel) |
| 2500 | `rpc-core` | ✅ Active | Core RPC node (internal/permissioned) |
| 2500 | `rpc-public` | ⚠️ Not active | Public RPC endpoints (backup config) |
| 2501 | `rpc-perm` | ✅ Active | Permissioned RPC with JWT auth |
| 2501 | `rpc-public` | ⚠️ Not active | Public RPC endpoints (backup config) |
| 2502 | `rpc` | ✅ Active | Public RPC endpoints (no auth) |
| 2503-2508 | N/A | ❌ Nginx not installed | Besu validator/sentry nodes (no RPC) |

---

## VMID 2400 - ThirdWeb RPC (Cloudflare Tunnel)

**Active Config**: `/etc/nginx/sites-enabled/rpc-thirdweb`  
**Domain**: `rpc.public-0138.defi-oracle.io`  
**IP**: 192.168.11.240

### Configuration Overview

- **Port 80**: Returns 204 (no redirect) for RPC clients
- **Port 443**: HTTPS server handling both HTTP RPC and WebSocket RPC
- **Backend**: 
  - HTTP RPC → `127.0.0.1:8545`
  - WebSocket RPC → `127.0.0.1:8546` (detected via `$http_upgrade` header)
- **SSL**: Cloudflare Origin Certificate
- **Cloudflare Integration**: Real IP headers configured for Cloudflare IP ranges

### Key Features

- WebSocket detection via `$http_upgrade` header
- CORS headers enabled for ThirdWeb web apps
- Cloudflare real IP support
- Health check endpoint at `/health`

### Full Configuration

```nginx
# RPC endpoint for rpc.public-0138.defi-oracle.io

server {
    listen 80;
    listen [::]:80;
    server_name rpc.public-0138.defi-oracle.io;

    # Avoid redirects for RPC clients (prevents loops and broken POST behavior)
    return 204;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name rpc.public-0138.defi-oracle.io;

    ssl_certificate     /etc/nginx/ssl/cloudflare-origin.crt;
    ssl_certificate_key /etc/nginx/ssl/cloudflare-origin.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    access_log /var/log/nginx/rpc-thirdweb-access.log;
    error_log  /var/log/nginx/rpc-thirdweb-error.log;

    client_max_body_size 10M;

    proxy_connect_timeout 300s;
    proxy_send_timeout    300s;
    proxy_read_timeout    300s;
    send_timeout          300s;

    # Optional: if you need real client IPs from Cloudflare
    real_ip_header CF-Connecting-IP;
    set_real_ip_from 173.245.48.0/20;
    set_real_ip_from 103.21.244.0/22;
    set_real_ip_from 103.22.200.0/22;
    set_real_ip_from 103.31.4.0/22;
    set_real_ip_from 141.101.64.0/18;
    set_real_ip_from 108.162.192.0/18;
    set_real_ip_from 190.93.240.0/20;
    set_real_ip_from 188.114.96.0/20;
    set_real_ip_from 197.234.240.0/22;
    set_real_ip_from 198.41.128.0/17;
    set_real_ip_from 162.158.0.0/15;
    set_real_ip_from 104.16.0.0/13;
    set_real_ip_from 104.24.0.0/14;
    set_real_ip_from 172.64.0.0/13;
    set_real_ip_from 131.0.72.0/22;

    location / {
        # Default backend = HTTP RPC
        set $backend "http://127.0.0.1:8545";

        # If websocket upgrade requested, use WS backend
        if ($http_upgrade = "websocket") {
            set $backend "http://127.0.0.1:8546";
        }

        proxy_pass $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;

        # WebSocket support (safe defaults)
        proxy_set_header Upgrade    $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_buffering off;
        proxy_request_buffering off;

        # CORS (optional; keep if Thirdweb/browser clients need it)
        add_header Access-Control-Allow-Origin "*" always;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;

        if ($request_method = OPTIONS) {
            return 204;
        }
    }

    location /health {
        access_log off;
        add_header Content-Type text/plain;
        return 200 "healthy\n";
    }
}
```

---

## VMID 2500 - Core RPC Node

**Active Config**: `/etc/nginx/sites-enabled/rpc-core`  
**Domains**: 
- `rpc-core.d-bis.org`
- `besu-rpc-1`
- `192.168.11.250`
- `rpc-core.besu.local`
- `rpc-core.chainid138.local`

**IP**: 192.168.11.250

### Configuration Overview

- **Port 80**: HTTP to HTTPS redirect
- **Port 443**: HTTPS HTTP RPC API (proxies to `127.0.0.1:8545`)
- **Port 8443**: HTTPS WebSocket RPC API (proxies to `127.0.0.1:8546`)
- **SSL**: Let's Encrypt certificate (`rpc-core.d-bis.org`)
- **Rate Limiting**: Enabled (zones: `rpc_limit`, `rpc_burst`, `conn_limit`)

### Key Features

- Rate limiting enabled
- Metrics endpoint at `/metrics` (proxies to port 9545)
- Separate ports for HTTP RPC (443) and WebSocket RPC (8443)
- Health check endpoints

### Full Configuration

```nginx
# HTTP to HTTPS redirect
server {
    listen 80;
    listen [::]:80;
    server_name rpc-core.d-bis.org besu-rpc-1 192.168.11.250 rpc-core.besu.local rpc-core.chainid138.local;
    
    # Redirect all HTTP to HTTPS
    return 301 https://$host$request_uri;
}

# HTTPS server - HTTP RPC API (port 8545)
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name rpc-core.d-bis.org besu-rpc-1 192.168.11.250 rpc-core.besu.local rpc-core.chainid138.local rpc-core.chainid138.local;

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/rpc-core.d-bis.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rpc-core.d-bis.org/privkey.pem;
    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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

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

    # Logging
    access_log /var/log/nginx/rpc-core-http-access.log;
    error_log /var/log/nginx/rpc-core-http-error.log;

    # Increase timeouts for RPC calls
    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;
    send_timeout 300s;
    client_max_body_size 10M;

    # HTTP RPC endpoint (port 8545)
    location / {
        proxy_pass http://127.0.0.1:8545;
        limit_req zone=rpc_limit burst=20 nodelay;
        limit_conn conn_limit 10;
        
        # Rate limiting
        proxy_http_version 1.1;
        
        # Headers
        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 Connection "";
        
        # Buffer settings (disable for RPC)
        proxy_buffering off;
        proxy_request_buffering off;
        
        # CORS headers (if needed for web apps)
        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
        
        # Handle OPTIONS requests
        if ($request_method = OPTIONS) {
            return 204;
        }
    }

    # Health check endpoint
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }

    # Metrics endpoint (if exposed)
    location /metrics {
        proxy_pass http://127.0.0.1:9545;
        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;
    }
}

# HTTPS server - WebSocket RPC API (port 8546)
server {
    listen 8443 ssl http2;
    listen [::]:8443 ssl http2;
    server_name besu-rpc-1 192.168.11.250 rpc-core-ws.besu.local rpc-core-ws.chainid138.local;

    # SSL configuration
    ssl_certificate /etc/letsencrypt/live/rpc-core.d-bis.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/rpc-core.d-bis.org/privkey.pem;
    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:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Logging
    access_log /var/log/nginx/rpc-core-ws-access.log;
    error_log /var/log/nginx/rpc-core-ws-error.log;

    # WebSocket RPC endpoint (port 8546)
    location / {
        proxy_pass http://127.0.0.1:8546;
        limit_req zone=rpc_burst burst=50 nodelay;
        limit_conn conn_limit 5;
        
        # Rate limiting
        proxy_http_version 1.1;
        
        # WebSocket headers
        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;
        
        # Long timeouts for WebSocket connections
        proxy_read_timeout 86400;
        proxy_send_timeout 86400;
        proxy_connect_timeout 300s;
    }

    # Health check endpoint
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}
```

**Note**: There's also a `rpc-public` config file that's not currently active.

---

## VMID 2501 - Permissioned RPC (JWT Authentication)

**Active Config**: `/etc/nginx/sites-enabled/rpc-perm`  
**Domains**:
- `rpc-http-prv.d-bis.org` (HTTP RPC with JWT)
- `rpc-ws-prv.d-bis.org` (WebSocket RPC with JWT)
- `besu-rpc-2`
- `192.168.11.251`

**IP**: 192.168.11.251

### Configuration Overview

- **Port 80**: HTTP to HTTPS redirect
- **Port 443**: HTTPS servers for both HTTP RPC and WebSocket RPC (same port, different server_name)
- **JWT Authentication**: Required for all RPC endpoints (via auth_request to `http://127.0.0.1:8888/validate`)
- **SSL**: Self-signed certificate (`/etc/nginx/ssl/rpc.crt`)

### Key Features

- JWT authentication using `auth_request` module
- JWT validator service running on port 8888
- Separate error handling for authentication failures
- Health check endpoint (no JWT required)

### Full Configuration

```nginx
# HTTP to HTTPS redirect
server {
    listen 80;
    listen [::]:80;
    server_name rpc-http-prv.d-bis.org rpc-ws-prv.d-bis.org besu-rpc-2 192.168.11.251;
    return 301 https://$host$request_uri;
}

# Internal server for JWT validation
server {
    server_name _;
    
    location /validate {
        fastcgi_pass unix:/var/run/fcgiwrap.socket;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/local/bin/jwt-validate.py;
        fastcgi_param HTTP_AUTHORIZATION $http_authorization;
    }
}

# HTTPS server - HTTP RPC API (Permissioned with JWT)
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name rpc-http-prv.d-bis.org besu-rpc-2 192.168.11.251;

    ssl_certificate /etc/nginx/ssl/rpc.crt;
    ssl_certificate_key /etc/nginx/ssl/rpc.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    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;

    access_log /var/log/nginx/rpc-http-prv-access.log;
    error_log /var/log/nginx/rpc-http-prv-error.log;

    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;
    send_timeout 300s;

    # JWT authentication using auth_request
    location = /auth {
        internal;
        proxy_pass http://127.0.0.1:8888/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header Authorization $http_authorization;
    }

    # HTTP RPC endpoint
    location / {
        auth_request /auth;
        auth_request_set $auth_status $upstream_status;
        
        # Return 401 if auth failed
        error_page 401 = @auth_failed;
        
        proxy_pass http://127.0.0.1:8545;
        proxy_http_version 1.1;
        proxy_set_header Host localhost;
        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 Connection "";
        proxy_buffering off;
        proxy_request_buffering off;
    }
    
    # Handle auth failures
    location @auth_failed {
        return 401 '{"jsonrpc":"2.0","error":{"code":-32000,"message":"Unauthorized. Missing or invalid JWT token. Use: Authorization: Bearer <token>"},"id":null}';
        add_header Content-Type application/json;
    }

    # Health check endpoint (no JWT required)
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}

# HTTPS server - WebSocket RPC API (Permissioned with JWT)
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name rpc-ws-prv.d-bis.org;

    ssl_certificate /etc/nginx/ssl/rpc.crt;
    ssl_certificate_key /etc/nginx/ssl/rpc.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    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;

    access_log /var/log/nginx/rpc-ws-prv-access.log;
    error_log /var/log/nginx/rpc-ws-prv-error.log;

    # JWT authentication for WebSocket connections
    location = /auth {
        internal;
        proxy_pass http://127.0.0.1:8888/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header Authorization $http_authorization;
    }

    location / {
        auth_request /auth;
        auth_request_set $auth_status $upstream_status;
        
        error_page 401 = @auth_failed;
        
        proxy_pass http://127.0.0.1:8546;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host localhost;
        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 86400;
        proxy_send_timeout 86400;
    }
    
    location @auth_failed {
        return 401 '{"error": "Unauthorized. Missing or invalid JWT token. Use: Authorization: Bearer <token>"}';
        add_header Content-Type application/json;
    }

    # Health check endpoint (no JWT required)
    location /health {
        access_log off;
        return 200 "healthy\n";
        add_header Content-Type text/plain;
    }
}
```

**Note**: There's also a `rpc-public` config file that's not currently active.

---

## VMID 2502 - Public RPC (No Authentication)

**Active Config**: `/etc/nginx/sites-enabled/rpc`  
**Domains**:
- `rpc-http-prv.d-bis.org` (HTTP RPC - Note: domain name suggests private but config has no auth)
- `rpc-ws-prv.d-bis.org` (WebSocket RPC - Note: domain name suggests private but config has no auth)
- `rpc-http-pub.d-bis.org` (Public HTTP RPC)
- `rpc-ws-pub.d-bis.org` (Public WebSocket RPC)
- `besu-rpc-3`
- `192.168.11.252`

**IP**: 192.168.11.252

### Configuration Overview

- **Port 80**: HTTP to HTTPS redirect
- **Port 443**: HTTPS servers for multiple domains (HTTP RPC and WebSocket RPC)
- **Authentication**: None (all endpoints are public)
- **SSL**: Self-signed certificate (`/etc/nginx/ssl/rpc.crt`)
- **Cloudflare Integration**: Real IP headers configured

### Key Features

- No authentication required (public endpoints)
- CORS headers enabled
- Multiple server blocks for different domain names
- Cloudflare real IP support for public domains

### Configuration Notes

⚠️ **Important**: The configuration includes server blocks for both `rpc-http-prv.d-bis.org`/`rpc-ws-prv.d-bis.org` (which suggests private endpoints) and `rpc-http-pub.d-bis.org`/`rpc-ws-pub.d-bis.org` (public endpoints), but **none of them require authentication**. This appears to be a configuration where VMID 2502 handles public RPC endpoints, while VMID 2501 handles the authenticated private endpoints.

### Full Configuration

The configuration file contains 4 server blocks:
1. HTTP to HTTPS redirect (port 80)
2. HTTPS server for `rpc-http-prv.d-bis.org` (HTTP RPC, no auth)
3. HTTPS server for `rpc-ws-prv.d-bis.org` (WebSocket RPC, no auth)
4. HTTPS server for `rpc-http-pub.d-bis.org` (Public HTTP RPC, no auth)
5. HTTPS server for `rpc-ws-pub.d-bis.org` (Public WebSocket RPC, no auth)

All server blocks proxy to:
- HTTP RPC: `127.0.0.1:8545`
- WebSocket RPC: `127.0.0.1:8546`

See previous command output for the complete configuration (too long to include here).

---

## VMIDs 2503-2508 - No Nginx

**Status**: Nginx is not installed on these containers

These VMIDs are Besu validator or sentry nodes that do not expose RPC endpoints, so nginx is not required.

---

## Summary of Port Usage

| VMID | Port 80 | Port 443 | Port 8443 | Purpose |
|------|---------|----------|-----------|---------|
| 2400 | Returns 204 | HTTP/WebSocket RPC | - | ThirdWeb RPC (Cloudflare Tunnel) |
| 2500 | Redirect to 443 | HTTP RPC | WebSocket RPC | Core RPC (internal) |
| 2501 | Redirect to 443 | HTTP/WebSocket RPC (JWT) | - | Permissioned RPC |
| 2502 | Redirect to 443 | HTTP/WebSocket RPC (public) | - | Public RPC |
| 2503-2508 | N/A | N/A | N/A | No nginx installed |

---

## SSL Certificates

| VMID | Certificate Type | Location |
|------|-----------------|----------|
| 2400 | Cloudflare Origin Certificate | `/etc/nginx/ssl/cloudflare-origin.crt` |
| 2500 | Let's Encrypt | `/etc/letsencrypt/live/rpc-core.d-bis.org/` |
| 2501 | Self-signed | `/etc/nginx/ssl/rpc.crt` |
| 2502 | Self-signed | `/etc/nginx/ssl/rpc.crt` |

---

## Access Patterns

### Public Endpoints (No Authentication)
- `rpc.public-0138.defi-oracle.io` (VMID 2400) - ThirdWeb RPC
- `rpc-http-pub.d-bis.org` (VMID 2502) - Public HTTP RPC
- `rpc-ws-pub.d-bis.org` (VMID 2502) - Public WebSocket RPC

### Permissioned Endpoints (JWT Authentication Required)
- `rpc-http-prv.d-bis.org` (VMID 2501) - Permissioned HTTP RPC
- `rpc-ws-prv.d-bis.org` (VMID 2501) - Permissioned WebSocket RPC

### Internal/Core Endpoints
- `rpc-core.d-bis.org` (VMID 2500) - Core RPC node (internal use)

---

**Last Updated**: 2026-01-27
