Step by step guide for setting up a docker-compose.yml for running a Sepolia Ethereum full node using Geth as the execution client and Prysm as the consensus client on an Ubuntu-based system.
| OS: Ubuntu 20.04 or later | ||
|---|---|---|
| RAM | CPU | Disk |
8-16 GB |
4-6 cores |
Initially 550 GB SSD - Can grow upto 1 TB |
Packages:
sudo apt-get update && sudo apt-get upgrade -ysudo apt install curl iptables build-essential git wget lz4 jq make gcc nano automake autoconf tmux htop nvme-cli libgbm1 pkg-config libssl-dev libleveldb-dev tar clang bsdmainutils ncdu unzip libleveldb-dev -yDocker:
sudo apt update -y && sudo apt upgrade -y
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update -y && sudo apt upgrade -y
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Test Docker
sudo docker run hello-world
sudo systemctl enable docker
sudo systemctl restart dockermkdir -p /root/ethereum/execution
mkdir -p /root/ethereum/consensusopenssl rand -hex 32 > /root/ethereum/jwt.hexVerify JWT secrets exist:
cat /root/ethereum/jwt.hexcd ethereumnano docker-compose.yml- Replace the following code into your
docker-compose.ymlfile:
services:
geth:
image: ethereum/client-go:stable
container_name: geth
network_mode: host
restart: unless-stopped
ports:
- 30303:30303
- 30303:30303/udp
- 8545:8545
- 8546:8546
- 8551:8551
volumes:
- /root/ethereum/execution:/data
- /root/ethereum/jwt.hex:/data/jwt.hex
command:
- --sepolia
- --http
- --http.api=eth,net,web3
- --http.addr=0.0.0.0
- --authrpc.addr=0.0.0.0
- --authrpc.vhosts=*
- --authrpc.jwtsecret=/data/jwt.hex
- --authrpc.port=8551
- --syncmode=snap
- --datadir=/data
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
prysm:
image: gcr.io/prysmaticlabs/prysm/beacon-chain
container_name: prysm
network_mode: host
restart: unless-stopped
volumes:
- /root/ethereum/consensus:/data
- /root/ethereum/jwt.hex:/data/jwt.hex
depends_on:
- geth
ports:
- 4000:4000
- 3500:3500
command:
- --sepolia
- --accept-terms-of-use
- --datadir=/data
- --disable-monitoring
- --rpc-host=0.0.0.0
- --execution-endpoint=http://127.0.0.1:8551
- --jwt-secret=/data/jwt.hex
- --rpc-port=4000
- --grpc-gateway-corsdomain=*
- --grpc-gateway-host=0.0.0.0
- --grpc-gateway-port=3500
- --min-sync-peers=3
- --checkpoint-sync-url=https://checkpoint-sync.sepolia.ethpandaops.io
- --genesis-beacon-api-url=https://checkpoint-sync.sepolia.ethpandaops.io
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"- The setup uses ports 30303, 8545, 8546, 8551, 4000, and 3500. Verify they’re free:
netstat -tuln | grep -E '30303|8545|8546|8551|4000|3500'
If a port is in use, edit the docker-compose.yml to map to a different host port (e.g., 8546:8545 to 8547:8545).
- Start Geth & Prysm Nodes:
docker compose up -d- Node Logs
# All lines of logs:
docker compose logs -f
# Last 100 lines of logs:
docker compose logs -fn 100- As you see in the logs,
Prysmis synced, andGethyet to be synced later.
➡️Execution Node (Geth)
curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' http://localhost:8545
- ✅Response if fully synced:
{"jsonrpc":"2.0","id":1,"result":false}- 🚫Response if still syncing:
{"jsonrpc":"2.0","id":1,"result":{"currentBlock":"0x1a2b3c","highestBlock":"0x1a2b4d","startingBlock":"0x0"}}- You'll see an object with
startingBlock,currentBlock, andhighestBlock, indicating the sync progress.
➡️Beacon Node (Prysm)
curl http://localhost:3500/eth/v1/node/syncing- ✅Response if fully synced:
{"data":{"head_slot":"12345","sync_distance":"0","is_syncing":false}}If is_syncing is false and sync_distance is 0, the beacon node is fully synced.
- 🚫Response if still syncing:
{"data":{"head_slot":"12345","sync_distance":"100","is_syncing":true}}- If
is_syncingistrue, the node is still syncing, andsync_distanceindicates how many slots behind it is.
- Enable Firewall:
sudo ufw allow 22
sudo ufw allow ssh
sudo ufw enable- Allow Geth P2P ports:
sudo ufw allow 30303/tcp # Geth P2P
sudo ufw allow 30303/udp # Geth P2P- Allow ports for local use (When your client, e.g. Aztec Sequencer, running locally)
sudo ufw allow from 127.0.0.1 to any port 8545 proto tcp
sudo ufw allow from 127.0.0.1 to any port 3500 proto tcpsudo ufw allow from <your-vps-ip> to any port 8545 proto tcp
sudo ufw allow from <your-vps-ip> to any port 3500 proto tcpReplace <your-vps-ip> with the IP you want to allow ports to.
- Allow/Deny ports for others IPs: (When your client, e.g. Aztec Sequencer, running on another server)
# Deny ports on all IPs
sudo ufw deny 8545/tcp
sudo ufw deny 3500/tcp- Reload Firewall:
sudo ufw reloadImportant Notes for Firewall Allow/Deny Settings:
ufwlistens to rules sequencially- View the rule sequence using
ufw status number - Delete a specific rule with
ufw delete <number> - When whitelisting specific IPs for specific ports, place
allowrules before the correspondingdenyrule for the port. - Example: To allow IP
134.12.44.177access to port8545, ensure thedenyrule for port8545is deleted first, then add theallowrule for the IP and port, and finally reapply thedenyrule for the port.
Geth provides an HTTP RPC endpoint for interacting with the execution layer of Ethereum. Based on docker-compose.yml setup, Geth exposes port 8545 for HTTP RPC. The endpoints are:
- Inside the VPS:
http://localhost:8545 - Outside the VPS:
http://<your-vps-ip>:8545(replace<your-vps-ip>with your VPS’s public IP address, e.g.,http://203.0.113.5:8545) - Aztec Sequencer Execution RPC (Running by CLI):
http://<your-vps-ip>:8545 - Aztec Sequencer Execution RPC (Running by
docker-compose.yml):http://127.0.0.1:8545orhttp://localhost:8545
Prysm, as the beacon node, offers an HTTP gateway on port 3500. the endpoints are:
- Inside the VPS:
http://localhost:3500 - Outside the VPS:
http://<your-vps-ip>:3500(e.g.,http://203.0.113.5:3500). - Aztec Sequencer Consensus Beacon RPC (Running by CLI):
http://<your-vps-ip>:3500 - Aztec Sequencer Consensus Beacon RPC (Running by
docker-compose.yml):http://127.0.0.1:3500orhttp://localhost:3500
- Monitor your hardware usage:
htop- Monitor your Disk usage:
df -h- Monitor Geth Disk usage:
docker exec -it geth du -sh /data- Monitor Prysm Disk usage:
docker exec -it prysm du -sh /data