Running a Read-Only RPC Node
This page walks through the process of running a read-only OXN RPC node. Read Hardware Requirements first — SGX-capable hardware is a hard prerequisite.
The step-by-step commands below are guidance based on the current node architecture. Some specific image tags, config paths, and command flags may change; check the OXN releases or contact the team via Support for the latest.
Prerequisites
Confirm you have:
- SGX-capable hardware with
/dev/sgx_enclaveand/dev/sgx_provisionpresent. - Docker installed (20.10 or newer).
- Sufficient disk space (100+ GB for testnet).
- The Intel DCAP QCNL configured (
/etc/sgx_default_qcnl.conf).
Verify the SGX device nodes:
ls -la /dev/sgx_enclave /dev/sgx_provision
# Expected: two character device nodes with the correct owner
Docker-based deployment
The recommended way to run an OXN node is via Docker. Pull the node image:
docker pull zkpchain/sapphire-localnet:latest # placeholder tag; consult latest release
Prepare a data directory on the host:
sudo mkdir -p /data/oxn-node
sudo chown $USER /data/oxn-node
Start the container:
docker run -d \
--name oxn-rpc-node \
--restart unless-stopped \
-v /data/oxn-node:/serverdir/node \
-v /var/run/aesmd:/var/run/aesmd \
-v /etc/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf:ro \
--device /dev/sgx_enclave \
--device /dev/sgx_provision \
-p 8545:8545 \
zkpchain/sapphire-localnet:latest
Key flags:
-v /data/oxn-node:/serverdir/node— persistent chain state.-v /var/run/aesmd:/var/run/aesmd— SGX AESM service socket.--device /dev/sgx_enclave --device /dev/sgx_provision— SGX access.-p 8545:8545— JSON-RPC endpoint.
Waiting for sync
Initial sync takes time — often 5+ minutes for a fresh testnet node depending on chain size. Monitor with:
docker logs -f oxn-rpc-node
Look for Total: or Available: lines indicating the chain has reached ready state.
Query the node once it's up:
curl http://localhost:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_chainId","id":1}'
# Expected: {"jsonrpc":"2.0","id":1,"result":"0xba"}
Exposing to your application
If your dApp runs on the same machine, point it at http://localhost:8545. For remote access, put a reverse proxy (nginx, Caddy) in front with TLS:
server {
listen 443 ssl;
server_name your-node.example.com;
ssl_certificate /etc/letsencrypt/live/your-node.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-node.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8545;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_buffering off;
proxy_read_timeout 1d;
}
}
Do not expose the node without authentication or IP-based access control — anyone hitting it can consume your node's resources.
Configuration options
The default configuration serves standard eth_* JSON-RPC methods. Adjustments you may want:
- Archive vs pruned — control historical state retention.
- CORS policy — for browser-based dApps hitting the node directly.
debug_*andtrace_*methods — disabled by default; enable if you need them for debugging.- WebSocket endpoint — separate port, off by default in some configurations.
Specific configuration paths and syntax depend on the node image release. Contact Support for current specifics.
Monitoring
Basic health checks:
# Latest block height
curl -s http://localhost:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","id":1}' | jq .
# Sync status
curl -s http://localhost:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_syncing","id":1}' | jq .
For continuous monitoring, scrape a Prometheus metrics endpoint if the node exposes one. Alert on:
- Node stopped syncing (block height not advancing).
- Disk usage above threshold.
- SGX enclave errors in logs.
- Container restart loops.
Upgrading
When a new node image is released:
- Read the release notes for breaking changes.
- Stop the running container:
docker stop oxn-rpc-node. - Pull the new image.
- Recreate the container with the same volumes.
- Verify the node syncs and serves requests.
State persists across upgrades because it lives in the host-mounted volume.
Common issues
"Container fails to start with SGX error." Verify /dev/sgx_enclave and /dev/sgx_provision exist and the container has access. Check BIOS SGX setting and kernel version.
"Node is stuck at height 0 or a low number." Sync is in progress. Testnet initial sync takes minutes. Check docker logs for errors.
"eth_chainId returns wrong value." You may be talking to a local Hardhat network by mistake. Confirm you're hitting the OXN node's port.
"AESM service errors in logs." Install sgx-aesm-service on the host and confirm the socket exists at /var/run/aesmd/aesm.socket.
Next steps
- Node Operators Overview
- Public RPC Endpoints — the alternative