Skip to content

Running a validator node on fly.io

Idogwu Chinonso edited this page Jun 13, 2025 · 2 revisions

βœ… Prerequisites

  • An Ethereum RPC provider (e.g., Infura or paid Alchemy)
  • A funded Sepolia or Mainnet account with access to the private key (used to sign and submit claims)
  • Your system should have the flyctl installed. Check this page for guide.

πŸ“‚ 1. Set up the Project Directory

mkdir ./cartesi-honeypot
cd cartesi-honeypot

πŸ“‚ 2. Set up a Dockerfile for your node

  • For deployments to fly.io we'll be using a Dockerfile to set up our PRT Node and Honeypot snapshot. This will make our deployment step easier since fly.io already understands and supports deployment via Dockerfiles. Create a Dockerfile using this command:
touch Dockerfile
  • Replace the content of your Dockerfile with the block below:
###
# Build arguments
ARG HONEYPOT_SNAPSHOT=0x615acc9fb8ae058d0e45c0d12fa10e1a6c9e645222c6fd94dfeda194ee427c14
ARG HONEYPOT_VERSION=2.0.0
ARG HONEYPOT_CHAIN_NAME=mainnet
ARG HONEYPOT_CHECKSUM=3ac94517756af3e57b3130ed71b2399fe5f23db4450693ae8321d32890aa95b9

ARG CARTESI_ROLLUPS_PRT_NODE_VERSION=1.0.0
ARG CARTESI_ROLLUPS_PRT_NODE_CHECKSUM_AMD64=5c9a30c862cf87b0f206287b9537b7297a9a4e07b1557bc7249ffbaf54e65aa7
ARG CARTESI_ROLLUPS_PRT_NODE_CHECKSUM_ARM64=9c8b1cfbb2df1fa1e542833b65ca8b63a6ecc391948f9b2a260e0661c08e7f56

###
# base image stage
FROM debian:bookworm-20250520@sha256:bd73076dc2cd9c88f48b5b358328f24f2a4289811bd73787c031e20db9f97123 AS base

ARG DEBIAN_FRONTEND=noninteractive
SHELL ["/bin/bash", "-eu", "-c"]

RUN <<EOF
apt-get update
apt-get install -y --no-install-recommends \
    ca-certificates \
    curl \
    xxd
EOF

###
# cartesi-rollups-prt-node stage
FROM base AS cartesi-rollups-prt-node
ARG CARTESI_ROLLUPS_PRT_NODE_VERSION
ARG CARTESI_ROLLUPS_PRT_NODE_CHECKSUM_AMD64
ARG CARTESI_ROLLUPS_PRT_NODE_CHECKSUM_ARM64
ARG TARGETARCH

RUN <<EOF
case "${TARGETARCH}" in
    amd64) curl -fsSL https://github.com/cartesi/dave/releases/download/v${CARTESI_ROLLUPS_PRT_NODE_VERSION}/cartesi-rollups-prt-node-Linux-gnu-x86_64.tar.gz \
            -o /tmp/cartesi-rollups-prt-node.tar.gz; \
        echo "${CARTESI_ROLLUPS_PRT_NODE_CHECKSUM_AMD64}  /tmp/cartesi-rollups-prt-node.tar.gz" | sha256sum -c ;;
    arm64) curl -fsSL https://github.com/cartesi/dave/releases/download/v${CARTESI_ROLLUPS_PRT_NODE_VERSION}/cartesi-rollups-prt-node-Linux-gnu-${TARGETARCH}.tar.gz \
            -o /tmp/cartesi-rollups-prt-node.tar.gz; \
        echo "${CARTESI_ROLLUPS_PRT_NODE_CHECKSUM_ARM64}  /tmp/cartesi-rollups-prt-node.tar.gz" | sha256sum -c ;;
    *) echo "unsupported architecture: ${TARGEARCH}"; exit 1 ;;
esac

tar -xzf /tmp/cartesi-rollups-prt-node.tar.gz -C /usr/local/bin
rm /tmp/cartesi-rollups-prt-node.tar.gz
EOF

###
## honeypotv2-machine-snapshot stage
FROM base AS honeypotv2-machine-snapshot
ARG HONEYPOT_SNAPSHOT
ARG HONEYPOT_VERSION
ARG HONEYPOT_CHAIN_NAME
ARG HONEYPOT_CHECKSUM

WORKDIR /var/lib/cartesi-rollups-prt-node/snapshots/${HONEYPOT_SNAPSHOT}
RUN <<EOF
curl -fsSL https://github.com/cartesi/honeypot/releases/download/v${HONEYPOT_VERSION}/honeypot-snapshot-${HONEYPOT_CHAIN_NAME}.tar.gz \
    -o /tmp/honeypot-snapshot.tar.gz
echo "${HONEYPOT_CHECKSUM} /tmp/honeypot-snapshot.tar.gz" | sha256sum -c
tar -xzf /tmp/honeypot-snapshot.tar.gz -C /var/lib/cartesi-rollups-prt-node/snapshots/${HONEYPOT_SNAPSHOT}
test "${HONEYPOT_SNAPSHOT}" = "0x$(xxd -p -c32 /var/lib/cartesi-rollups-prt-node/snapshots/${HONEYPOT_SNAPSHOT}/hash)"
EOF

###
# final stage
FROM base
ARG HONEYPOT_SNAPSHOT

COPY --from=cartesi-rollups-prt-node /usr/local/bin/cartesi-rollups-prt-node /usr/local/bin/cartesi-rollups-prt-node

WORKDIR /var/lib/cartesi-rollups-prt-node/snapshots/${HONEYPOT_SNAPSHOT}

COPY --from=honeypotv2-machine-snapshot /var/lib/cartesi-rollups-prt-node/snapshots/${HONEYPOT_SNAPSHOT} ./

USER root
WORKDIR /var/lib/cartesi-rollups-prt-node
VOLUME [ "/var/lib/cartesi-rollups-prt-node" ]
CMD ["cartesi-rollups-prt-node", "pk"]

The above Dockerfile is configured to run an Ethereum Mainnet instance, if you intend to run a Seploia instance, simply modify the first four lines of the build argument section with:

ARG HONEYPOT_SNAPSHOT=0xdbe72e1624cfed0e83469f1f5104709ecfc0d4ff6edaa7745d5912b2e184b278
ARG HONEYPOT_VERSION=2.0.0
ARG HONEYPOT_CHAIN_NAME=sepolia
ARG HONEYPOT_CHECKSUM=c0331c9689f663ae9a0f6ded113fd51d993b2d1131db8dc9cccb22945f0a6d53

πŸ“‚ 3. Set up a fly.toml file

Next we'll need to set up a fly.toml file which would hold the configurations for our remote machine and also some necessary env variables which the node requires.

  • Create a fly.toml file using this command:
touch fly.toml
  • Replace the content of the fly.toml file with the below:
app = '<App Name>'

[build]
  dockerfile = 'Dockerfile'

[env]
  APP_ADDRESS = '0x4c1E74EF88a75C24e49eddD9f70D82A94D19251c'
  CONSENSUS = '0x6CE590b9F0697327f18c601DF6f0baE4a0801B68'
  INPUT_BOX = '0xc70074BDD26d8cF983Ca6A5b89b8db52D5850051'
  MACHINE_PATH = '/var/lib/cartesi-rollups-prt-node/snapshots/0x615acc9fb8ae058d0e45c0d12fa10e1a6c9e645222c6fd94dfeda194ee427c14'
  RUST_LOG = 'debug'
  STATE_DIR = '/var/lib/cartesi-rollups-prt-node/state'
  WEB3_CHAIN_ID = '1'

[[mounts]]
  source = 'eth_mainnet_honeypot_v2_state'
  destination = '/var/lib/cartesi-rollups-prt-node/state'
  initial_size = '2gb'

[[vm]]
  size = 'shared-cpu-4x'
  memory = '2048'

Note that the above fly.toml block requires that you replace the <App Name> section with the actual name you intend to call your application. If you intend to call your application example-one then the line should be:

 app = 'example-one'

It's also important to note that the app_address, consensus, input_box and machine_path in the current fly.toml file are all configured to Ethereum Mainnet, if you intend to run a Sepolia instance, check out the Deployments page and replace the app_address, consensus and input_box with the Sepolia address while the machine path should be change to:

MACHINE_PATH = '/var/lib/cartesi-rollups-prt-node/snapshots/0xdbe72e1624cfed0e83469f1f5104709ecfc0d4ff6edaa7745d5912b2e184b278'

πŸ“¦ 4. Create an application instance on fly.io

This section assumes that you already have the flyctl installed on your computer, and you've also already created a dashboard and done all the necessary payment configurations fly.io requires.

  • Run the command below to create an application instance on fly.io, please note that the name of your application should be the same as contained in the first line of your fly.toml file. Simply replace the <App Name> in the below command with the actual name of your application and hit enter.
fly app create <App Name> 

πŸ”‘ 5. Set Up your App Secrets

Your fly.toml file already contains most of the environment variables your node needs, but it's advisable that your more sensitive environmental variables should be setup as app secrets on fly.io and not contained in the fly.toml file.

  • Run the below commands and replace <App Name> with the name of your application, <SEPOLIA OR MAINNET RPC> and <PRIVATE_KEY> respectively should also be replaced with the PRC and private key for your specified network (Sepolia or Mainnet).

Note ⚠️:: Free Alchemy plans may hit a 500 block range limit, causing the node to fail syncing. Prefer Infura (free) for limited use (~2h/day), or upgrade to a paid plan of Alchemy or Infura.

fly secrets set -a <App Name> WEB3_RPC_URL=<SEPOLIA OR MAINNET RPC OF CHOICE>
fly secrets set -a <App Name> WEB3_PRIVATE_KEY=<PRIVATE_KEY>

πŸš€ 6. Deploying the Validator Node

Now run the below command to deploy the node:

fly deploy

πŸ“‹ 7. Expected local deploy logs

After running the deploy command the fly CLI will attempt to build your docker container locally after which it pushes the required layers to your remote application. For a successful deploy precess you should see a log similar to this:

              
==> Verifying app config
Validating /Users/idogwuchi/Documents/Cartesi/honeypot/fly.toml
βœ“ Configuration is valid
--> Verified app config
==> Building image
==> Building image with Depot
--> build:  (​)
[+] Building 31.7s (13/13) FINISHED                                                                                                                                                                                                                                                                                                                                                                                                              
 => [internal] load build definition from Dockerfile 
 {
    ....
 }            
--> Build Summary:  (​)
--> Building image done
image: registry.fly.io/<App Name>:deployment-01JXMM7K8SJYNG6FPJJK10QCC5
image size: 129 MB

Watch your deployment at https://fly.io/apps/<App Name>/monitoring

Creating a 2 GB volume named 'eth_mainnet_honeypot_v2_state' for process group 'app'. Use 'fly vol extend' to increase its size
This deployment will:
 * create 1 "app" machine

No machines in group app, launching a new machine
Finished launching new machines
-------
 βœ” Machine 91853417c13368 [app] update finished: success

πŸ“‹ 8. Expected application logs on fly.io

Visit your application dashboard on fly.io to monitor and check your application logs.

2025-06-13 13:09:18.454 [2025-06-13T12:09:18Z INFO  cartesi_rollups_prt_node] Hello from PRT Rollup Node!
2025-06-13 14:09:21.899	[2025-06-13T13:18:21Z INFO  cartesi_rollups_prt_node] Running with config:
2025-06-13 14:09:21.899	App Address: 0x4c1E74EF88a75C24e49eddD9f70D82A94D19251c {...}

2025-06-13 14:56:05.143	[2025-06-13T13:56:05Z INFO  cartesi_prt_core::strategy::player] Enter tournament at address: 0xDaa497885D83f345CBcbF071d7201230A8CBd68A

2025-06-13 14:55:34.534	[2025-06-13T13:55:34Z INFO  cartesi_prt_core::strategy::player] no match found for commitment: 0xf8f82cf969717a1a3622f14927ea7dcbbb05e49be12f147ed424e9ae069549d2
2025-06-13 14:55:34.534	[2025-06-13T13:55:34Z INFO  cartesi_prt_core::strategy::player] clock paused, 50541 blocks left