Deploy an instance of alto.
To run a deploy, you must first install Rust.
To configure local indexer upload, add --indexers '<url>:<count>[;<url>:<count>...]' to the generate local command. For example, http://localhost:8080:1 assigns one validator to upload to that indexer.
Generated validator configs use:
indexer: http://localhost:8080cargo run --bin deploy -- generate --peers 5 --bootstrappers 1 --worker-threads 3 --log-level info --message-backlog 16384 --mailbox-size 16384 --deque-size 10 --signature-threads 2 --output test local --start-port 3000 --indexers 'http://localhost:8080:1'If the command succeeds, you should see the following output:
2025-12-23T13:41:54.034863Z INFO setup: generated network key identity=8b2c34e0356beb83874317f8f04fb211e4d3ed34640631a36ff191cb3fcd9768403b8749824b41ff770a92e40885174b15516db966816870ba9619a64b4d5b79ea7b4a73240710169ecc44da0951cdd60e2db65544cba5647f81ab19ca50cf4e
2025-12-23T13:41:54.037106Z INFO setup: wrote peer configuration file path="04dc128c6fc22cb93a9eb785c48d4251346eb7b387cd2a66599cc59a3ce47a37.yaml"
2025-12-23T13:41:54.037417Z INFO setup: wrote peer configuration file path="0b2412d7eb2238b319920504f19b28447c7dbb3c58059c97d22cc0d27ea31e81.yaml"
2025-12-23T13:41:54.037690Z INFO setup: wrote peer configuration file path="71943989f39d485eb8a1f7c8f9909673caaa658d12a586c93f37575dae44438f.yaml"
2025-12-23T13:41:54.037966Z INFO setup: wrote peer configuration file path="c58244243f263ebc975640d5bb4e43e8e78e4b41361e4e7984cd8b027480558a.yaml"
2025-12-23T13:41:54.038228Z INFO setup: wrote peer configuration file path="f26a6d4f52c4d595b6cb659b643968b0e1fc9931b460c6407be10cebe4eeff2d.yaml"
2025-12-23T13:41:54.038232Z INFO setup: setup complete bootstrappers=["71943989f39d485eb8a1f7c8f9909673caaa658d12a586c93f37575dae44438f"]
To start local indexers, run:
http://localhost:8080: cargo run --bin indexer -- --port 8080 --identity 8b2c34e0356beb83874317f8f04fb211e4d3ed34640631a36ff191cb3fcd9768403b8749824b41ff770a92e40885174b15516db966816870ba9619a64b4d5b79ea7b4a73240710169ecc44da0951cdd60e2db65544cba5647f81ab19ca50cf4e
To start validators, run:
04dc128c6fc22cb93a9eb785c48d4251346eb7b387cd2a66599cc59a3ce47a37: cargo run --bin validator -- --peers=<your-path>/test/peers.yaml --config=<your-path>/test/04dc128c6fc22cb93a9eb785c48d4251346eb7b387cd2a66599cc59a3ce47a37.yaml
0b2412d7eb2238b319920504f19b28447c7dbb3c58059c97d22cc0d27ea31e81: cargo run --bin validator -- --peers=<your-path>/test/peers.yaml --config=<your-path>/test/0b2412d7eb2238b319920504f19b28447c7dbb3c58059c97d22cc0d27ea31e81.yaml
71943989f39d485eb8a1f7c8f9909673caaa658d12a586c93f37575dae44438f: cargo run --bin validator -- --peers=<your-path>/test/peers.yaml --config=<your-path>/test/71943989f39d485eb8a1f7c8f9909673caaa658d12a586c93f37575dae44438f.yaml
c58244243f263ebc975640d5bb4e43e8e78e4b41361e4e7984cd8b027480558a: cargo run --bin validator -- --peers=<your-path>/test/peers.yaml --config=<your-path>/test/c58244243f263ebc975640d5bb4e43e8e78e4b41361e4e7984cd8b027480558a.yaml
f26a6d4f52c4d595b6cb659b643968b0e1fc9931b460c6407be10cebe4eeff2d: cargo run --bin validator -- --peers=<your-path>/test/peers.yaml --config=<your-path>/test/f26a6d4f52c4d595b6cb659b643968b0e1fc9931b460c6407be10cebe4eeff2d.yaml
Configured indexers:
04dc128c6fc22cb93a9eb785c48d4251346eb7b387cd2a66599cc59a3ce47a37: http://localhost:8080
To view metrics, run:
04dc128c6fc22cb93a9eb785c48d4251346eb7b387cd2a66599cc59a3ce47a37: curl http://localhost:3001/metrics
0b2412d7eb2238b319920504f19b28447c7dbb3c58059c97d22cc0d27ea31e81: curl http://localhost:3003/metrics
71943989f39d485eb8a1f7c8f9909673caaa658d12a586c93f37575dae44438f: curl http://localhost:3005/metrics
c58244243f263ebc975640d5bb4e43e8e78e4b41361e4e7984cd8b027480558a: curl http://localhost:3007/metrics
f26a6d4f52c4d595b6cb659b643968b0e1fc9931b460c6407be10cebe4eeff2d: curl http://localhost:3009/metrics
Run the emitted start commands in separate terminals:
cargo run --bin validator -- --peers=<your-path>/test/peers.yaml --config=<your-path>/test/10cf8d03daca2332213981adee2a4bfffe4a1782bb5cce036c1d5689c6090997.yamlIt is necessary to start at least one bootstrapper for any other peers to connect (used to exchange IPs to dial, not as a relay).
cargo run --bin deploy -- explorer --dir test --backend-url <backend URL> localIf you see an error like unable to append to journal: Runtime(BlobOpenFailed("engine-consensus", "00000000000000ee", Os { code: 24, kind: Uncategorized, message: "Too many open files" })), you may need to increase the maximum number of open files. You can do this by running:
ulimit -n 65536MacOS defaults to 256 open files, which is too low for the default settings (where 1 journal file is maintained per recent view).
To run a deploy, you must first install Rust and Docker.
cargo install commonware-deployerTo configure remote indexer upload, add --indexers '<url>:<count>[;<url>:<count>...]' to the generate remote command. For example, https://idx-a.example.com:2;https://idx-b.example.com:1. Indexers are selected in round-robin fashion across regions.
Each selected validator config will contain:
indexer: https://your-indexer.example.comcargo run --bin deploy -- generate --peers 50 --bootstrappers 5 --worker-threads 2 --log-level info --message-backlog 16384 --mailbox-size 16384 --deque-size 10 --signature-threads 2 --output assets remote --regions us-west-1,us-east-1,eu-west-1,ap-northeast-1,eu-north-1,ap-south-1,sa-east-1,eu-central-1,ap-northeast-2,ap-southeast-2 --monitoring-instance-type c8g.4xlarge --monitoring-storage-size 100 --instance-type c8g.large --storage-size 25 --dashboard deploy/dashboard.jsonThis configuration consumes ~10MB of disk space per hour per validator (~5 views per second). With 25GB of storage allocated, validators will exhaust available storage in ~3 months.
cargo run --bin deploy -- generate --peers 50 --bootstrappers 5 --worker-threads 2 --log-level info --message-backlog 16384 --mailbox-size 16384 --deque-size 10 --signature-threads 2 --output assets remote --regions us-east-1,us-east-2,us-west-1,us-west-2 --monitoring-instance-type c8g.4xlarge --monitoring-storage-size 100 --instance-type c8g.large --storage-size 75 --dashboard deploy/dashboard.jsonThis configuration consumes ~30MB of disk space per hour per validator (~13 views per second). With 75GB of storage allocated, validators will exhaust available storage in ~3 months.
cargo run --bin deploy -- explorer --dir assets --backend-url <backend URL> remoteAfter redeploying a cluster, update the identity (BLS12-381 threshold public key) across example configs and the inspector default:
# Global cluster:
OLD_KEY=$(sed -nE 's/^identity: "(.*)"$/\1/p' follower/examples/global.yml)
NEW_KEY="<new-key-hex>"
sed -i '' "s/$OLD_KEY/$NEW_KEY/g" follower/examples/global.yml
sed -i '' -E "s|^const DEFAULT_IDENTITY: &str = \".*\";|const DEFAULT_IDENTITY: &str = \"$NEW_KEY\";|" inspector/src/main.rs
# USA cluster:
OLD_KEY=$(sed -nE 's/^identity: "(.*)"$/\1/p' follower/examples/usa.yml)
NEW_KEY="<new-key-hex>"
sed -i '' "s/$OLD_KEY/$NEW_KEY/g" follower/examples/usa.ymldocker build -t validator-builder deploy/docker run -it -v ${PWD}:/alto validator-builderBefore running this command, ensure you change any version dependencies you'd like to compile locally to path dependencies in Cargo.toml.
docker run -it -v ${PWD}:/alto -v ${PWD}/../monorepo:/monorepo validator-builderEmitted binary validator is placed in assets/.
cd assets
deployer aws create --config config.yamlVisit http://<monitoring-ip>:3000/d/chain
This dashboard is only accessible from the IP used to deploy the infrastructure.
docker run -it -v ${PWD}:/alto validator-builderdeployer aws update --config config.yamlCollect a CPU profile from a running validator using samply:
deployer aws profile --config config.yaml --instance <instance-name> --binary validator-debugThe validator-debug binary contains debug symbols for symbolication. The profile will be saved locally and can be viewed in the Firefox Profiler.
deployer aws destroy --config config.yamlIf commonware-deployer can't detect your AWS credentials, you'll see a "Request has expired." error:
2025-03-05T01:36:47.550105Z INFO deployer::ec2::create: created EC2 client region="eu-west-1"
2025-03-05T01:36:48.268330Z ERROR deployer: failed to create EC2 deployment error=AwsEc2(Unhandled(Unhandled { source: ErrorMetadata { code: Some("RequestExpired"), message: Some("Request has expired."), extras: Some({"aws_request_id": "006f6b92-4965-470d-8eac-7c9644744bdf"}) }, meta: ErrorMetadata { code: Some("RequestExpired"), message: Some("Request has expired."), extras: Some({"aws_request_id": "006f6b92-4965-470d-8eac-7c9644744bdf"}) } }))
EC2 instances may throttle network traffic if a workload exceeds the allocation for a particular instance type. To check if an instance is throttled, SSH into the instance and run:
ethtool -S ens5 | grep "allowance"If throttled, you'll see a non-zero value for some "allowance" item:
bw_in_allowance_exceeded: 0
bw_out_allowance_exceeded: 14368
pps_allowance_exceeded: 0
conntrack_allowance_exceeded: 0
linklocal_allowance_exceeded: 0