Run your own Syndicate appchain RPC node with Docker Compose.
- Docker with the Compose plugin (v2.20+)
curlandtar(for snapshot download)- Disk space: 1 TB+ recommended
- RAM: 16 GB+ recommended
- CPU: 4+ cores recommended
- Ports
8545(HTTP RPC) and8548(WebSocket RPC) available on the host - WebSocket RPC access to your sequencing chain and settlement chain (e.g. via Alchemy, Infura, or a self-hosted node)
Note
For synd-TEE withdrawals to be functional, you'll need to set up a synd-enclave on an AWS Nitro TEE instance and provide that URL as ENCLAVE_RPC_URL. See the TEE enclave setup guide for instructions.
cp .env.example .envOpen .env and supply your chain-specific values.
All initial values for your specific appchain can be provided by the Syndicate team.
Warning
BATCHER_PRIVATE_KEY and PROPOSER_PRIVATE_KEY must have funds on the sequencing / settlement chains respectively. Additionally, the BATCHER must be authorized to sequence on the sequencing contract.
To change the location where data is persisted, set DATA_DIR in your .env before running start.sh.
bash start.shThe script will:
- Create local data directories under
DATA_DIR(default:./data) - Download and extract the nitro snapshot if
NITRO_SNAPSHOT_URLis set - Start all services with
docker compose(the mchain container handles its own snapshot download viaMCHAIN_SNAPSHOT_URLif set)
Check that all containers are running:
docker compose psWait for the mchain and nitro to finish syncing, then test the RPC:
curl -s -X POST http://localhost:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'WebSocket RPC is also available at ws://localhost:8548.
# Follow logs for all services
docker compose logs -f
# Follow logs for a specific service
docker compose logs -f nitro
# Stop all services
docker compose down
# Stop and remove all persisted data (bind-mounted)
docker compose down && rm -rf ${DATA_DIR:-./data}
# Restart a single service
docker compose restart mchain./data/
├── mchain/ # RocksDB state for the intermediate chain node
├── nitro/ # Nitro node state
├── sequencing/ # filesystem cache for the sequencing ingestor
├── settlement/ # filesystem cache for the settlement ingestor
└── valkey/ # Valkey (Redis-compatible) persistence
At this point you should have a functional synd-stack rollup deriving state from the parent chains.
You can assert that the rollup node is synced by checking the eth_blockNumber rpc call result.
You should also be able to send new transactions by calling eth_sendRawTransaction on the rollup node.
Withdrawals should also be functional, you can assert this by monitoring the TEEModule contract for assertionPosted and closeChallengeWindow events (example)