# Public RPC Endpoint Routing Architecture **Last Updated:** 2026-01-28 **Document Version:** 1.1 **Status:** Active Documentation --- ## Architecture Overview The public RPC endpoints route through **NPMplus** (VMID 10233) to **Besu Public RPC** (VMID 2201). Edge path: **DNS (Cloudflare) → Fastly or 76.53.10.36 → UDM Pro → NPMplus → Besu RPC (2201)**. ``` Internet → Cloudflare DNS → Fastly or 76.53.10.36 → UDM Pro (76.53.10.36:443) → NPMplus (10233) → Besu RPC (2201) ``` **Ledger App-Ethereum** (ChainID 138): Wallets use `https://rpc-http-pub.d-bis.org` / `wss://rpc-ws-pub.d-bis.org`. See [PUBLIC_RPC_CHAIN138_LEDGER.md](../04-configuration/PUBLIC_RPC_CHAIN138_LEDGER.md). --- ## Endpoint Routing ### HTTP RPC Endpoint **URL**: `https://rpc-http-pub.d-bis.org` **Routing Path**: 1. **DNS** (Cloudflare): `rpc-http-pub.d-bis.org` → Fastly (CNAME) or 76.53.10.36 (A) 2. **Edge:** Fastly or 76.53.10.36 → UDM Pro port forward → NPMplus (192.168.11.167) 3. **NPMplus** (VMID 10233): SSL termination, reverse proxy to `http://192.168.11.221:8545` 4. **Besu RPC** (VMID 2201): besu-rpc-public-1 **Configuration**: - **Should NOT require authentication** (public endpoint) - **Must accept requests without JWT tokens** (for MetaMask / Ledger Live compatibility) ### WebSocket RPC Endpoint **URL**: `wss://rpc-ws-pub.d-bis.org` **Routing Path**: 1. **DNS** (Cloudflare): `rpc-ws-pub.d-bis.org` → Fastly (CNAME) or 76.53.10.36 (A) 2. **Edge:** Fastly or 76.53.10.36 → UDM Pro → NPMplus (192.168.11.167); WebSocket enabled 3. **NPMplus** (VMID 10233): SSL termination, WebSocket upgrade, reverse proxy to `http://192.168.11.221:8546` 4. **Besu RPC** (VMID 2201): besu-rpc-public-1 **Configuration**: - **Should NOT require authentication** (public endpoint) - **Must accept WebSocket connections without JWT tokens** - **WebSocket upgrade** must be enabled in NPMplus for both RPC domains --- ## Components ### 1. NPMplus (VMID 10233) - **IP**: 192.168.11.167 - **Purpose**: Reverse proxy for all public-facing services (including RPC) - **RPC proxy**: `rpc-http-pub.d-bis.org` → `http://192.168.11.221:8545`, `rpc-ws-pub.d-bis.org` → `http://192.168.11.221:8546` - **WebSocket**: Enabled for both. No JWT/auth for public RPC. ### 2. Besu Public RPC (VMID 2201) - **IP**: 192.168.11.221 - **Hostname**: besu-rpc-public-1 - **HTTP RPC**: 8545 | **WebSocket RPC**: 8546 - **Chain ID**: 138 (0x8a) - **Config**: `config-rpc-public.toml` (read-only; see below) #### Security: No contract deployment from public RPC The RPC on VMID 2201 allows **no** contract deployment: - **Account permissioning** is enabled with an **empty allowlist** (`permissions-accounts-public.toml`). - No account can submit transactions through this node; `eth_sendTransaction` / `eth_sendRawTransaction` are rejected. - Read-only methods (e.g. `eth_call`, `eth_getBalance`, `eth_chainId`) remain available for all. Contract deployment is allowed only via **Core RPC (VMID 2101)** and **Permissioned RPCs**, which use `permissions-accounts.toml` and require the sender to be on the allowlist (see [RPC_NODE_TYPES_ARCHITECTURE.md](RPC_NODE_TYPES_ARCHITECTURE.md)). To apply or refresh public RPC config on the host: `./scripts/apply-public-rpc-config-2201.sh` (run from project root; requires Proxmox host access). --- ## NPMplus Configuration Public RPC is configured in **NPMplus** (VMID 10233). Apply or verify via: - **API**: `scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh` - `rpc-http-pub.d-bis.org` → `http://192.168.11.221:8545` (WebSocket enabled) - `rpc-ws-pub.d-bis.org` → `http://192.168.11.221:8546` (WebSocket enabled) - `rpc.d-bis.org`, `rpc2.d-bis.org` → `http://192.168.11.221:8545` (WebSocket enabled) - `ws.rpc.d-bis.org`, `ws.rpc2.d-bis.org` → `http://192.168.11.221:8546` (WebSocket enabled) - **Browser UI**: `node scripts/nginx-proxy-manager/configure-npmplus-domains.js` Ensure **no JWT/auth** is applied to these proxy hosts (public RPC). See [PUBLIC_RPC_CHAIN138_LEDGER.md](../04-configuration/PUBLIC_RPC_CHAIN138_LEDGER.md). --- ## Common Issues ### Issue 1: "Could not fetch chain ID" (MetaMask / Ledger Live) **Symptom**: Wallet cannot connect to ChainID 138. **Causes**: NPMplus proxy has auth enabled for RPC, or backend (VMID 2201) is down. **Fix**: 1. Ensure NPMplus proxy hosts for `rpc-http-pub.d-bis.org`, `rpc-ws-pub.d-bis.org`, `rpc.d-bis.org`, `rpc2.d-bis.org`, `ws.rpc.d-bis.org`, `ws.rpc2.d-bis.org` use **no** access lists or JWT. 2. Re-apply config: `./scripts/nginx-proxy-manager/update-npmplus-proxy-hosts-api.sh` 3. Check Besu: `ssh root@ "pct exec 2201 -- curl -s -X POST http://127.0.0.1:8545 -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":1}'"` ### Issue 2: NPMplus Cannot Reach Backend (192.168.11.221) **Symptom**: 502/504 from `https://rpc-http-pub.d-bis.org`. **Fix**: Confirm NPMplus (10233) can reach `192.168.11.221:8545` (e.g. dual-NIC / routing). See [RPC_ENDPOINTS_MASTER.md](../04-configuration/RPC_ENDPOINTS_MASTER.md) Network section. ### Issue 3: Besu RPC (VMID 2201) Down **Symptom**: Backend unreachable. **Check**: ```bash ssh root@ "pct status 2201" ssh root@ "pct exec 2201 -- ss -tuln | grep -E '8545|8546'" ``` --- ## Testing ### Test HTTP RPC Endpoint ```bash curl -X POST https://rpc-http-pub.d-bis.org \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}' ``` **Expected Response**: ```json {"jsonrpc":"2.0","id":1,"result":"0x8a"} ``` ### Test WebSocket RPC Endpoint ```bash wscat -c wss://rpc-ws-pub.d-bis.org ``` Then send: ```json {"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1} ``` --- ## Verification Checklist - [ ] DNS resolves `rpc-http-pub.d-bis.org` (e.g. to 76.53.10.36 or Cloudflare) - [ ] NPMplus (VMID 10233) is running and proxies RPC to 192.168.11.221 - [ ] NPMplus proxy hosts for RPC do **not** use JWT/auth - [ ] Besu RPC (VMID 2201) is running and listening on 8545 / 8546 - [ ] `curl -X POST https://rpc-http-pub.d-bis.org -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":1}'` returns `"result":"0x8a"` - [ ] MetaMask / Ledger Live can connect to ChainID 138 using `https://rpc-http-pub.d-bis.org` --- ## Related Documentation ### Configuration - **[../04-configuration/PUBLIC_RPC_CHAIN138_LEDGER.md](../04-configuration/PUBLIC_RPC_CHAIN138_LEDGER.md)** – Public RPCs, NPMplus→VM mapping, Ledger App-Ethereum - **[../04-configuration/RPC_ENDPOINTS_MASTER.md](../04-configuration/RPC_ENDPOINTS_MASTER.md)** – All RPC endpoints - **[../04-configuration/NPMPLUS_CORRECT_CONFIGURATION.md](../04-configuration/NPMPLUS_CORRECT_CONFIGURATION.md)** – NPMplus domain config ### Network - **[RPC_NODE_TYPES_ARCHITECTURE.md](RPC_NODE_TYPES_ARCHITECTURE.md)** – RPC node types and VMIDs - **[CLOUDFLARE_ROUTING_MASTER.md](CLOUDFLARE_ROUTING_MASTER.md)** – Edge routing (Fastly/Direct → NPMplus) ### Troubleshooting - **[../09-troubleshooting/METAMASK_TROUBLESHOOTING_GUIDE.md](../09-troubleshooting/METAMASK_TROUBLESHOOTING_GUIDE.md)** – MetaMask --- **Last Updated:** 2026-02-05 **Document Version:** 1.2 **Review Cycle:** Quarterly