ctmd node with the deploy.sh lifecycle script. For hosted deployment scripts and peer-list resources, see Deployment Scripts. Validator nodes need dedicated signing-key, TMKMS, sentry, and double-sign protection procedures.
Network defaults
Use this table as an operator quick reference. For the canonical network records, see Network Information - Mainnet Beta and Network Information - Testnet.Operating model
On Linux,
deploy.sh install creates a ctmd service user/group, installs a hardened ctmd.service, enables the service, and leaves it stopped until you run deploy.sh state-sync or deploy.sh start. On macOS, it installs the binary and bootstraps the user-managed $HOME/.ctmd home without installing a service.
Recommended operational configuration
Use the node profile that matches the workload. A normal application node should prioritize fast bootstrap, protected RPC surfaces, and bounded historical reads. An exchange, custodian, or indexer that must rebuild history from first principles should run archive infrastructure or consume a dedicated indexer.
Recommended baseline:
- Install Linux production nodes with
deploy.sh install --moniker <your-node-moniker>and manage them withdeploy.sh start,deploy.sh stop, andsystemd. - Bootstrap new non-archive nodes with State Sync; replay archive nodes from genesis.
- Keep RPC, REST, gRPC, WebSocket, and metrics endpoints on localhost or private interfaces unless a reverse proxy enforces TLS, authentication, rate limits, request size limits, and IP allowlists.
- Use the default public EVM namespace shape
eth,net,web3for externally exposed RPC. Enabletxpoolordebugonly on private archive or operations nodes. - For archive nodes, follow Archive Data Setup: set
pruning = "nothing", keep ABCI responses, enable the transaction index, and enable the EVM indexer. - Monitor local height, catching-up state, peer count, process restarts, disk growth, RPC latency, HTTP
429rates, and WebSocket reconnect storms.
Deploy script
To install or updatectmd, run the deploy.sh script. You can download and run the script manually:
Install from release
Recommended Linux install:deploy.sh install reads metadata.json, resolves .ctmd.latest_version, selects the current artifact and SHA-256 URL for the host platform, downloads the tarball, verifies SHA-256, and installs the ctmd binary with bundled shared libraries. It then initializes the node home, downloads genesis, repairs chain ID settings, and patches seeds and persistent peers from https://resources.c8ntinuum.io/peers.json.
For mainnet, the downloaded and local genesis.json files are verified against metadata.json field mainnet_genesis_sha256. If you pass a non-default --chain-id, the script skips the mainnet SHA-256 check.
The installer creates these managed paths:
Linux service unit
deploy.sh install generates /etc/systemd/system/ctmd.service. The file carries a do not edit header, and both install and state-sync rewrite it, so local changes belong in a drop-in:
systemctl edit writes /etc/systemd/system/ctmd.service.d/override.conf and reloads systemd; a drop-in you place by hand needs systemctl daemon-reload. Drop-ins survive reinstall and state sync, but deploy.sh reset deletes the unit and the entire ctmd.service.d directory, so keep overrides in configuration management rather than only on the host.
Read the unit on the host you are working on rather than from documentation:
/usr/local install carries a different unit at the same path: a non-versioned LD_LIBRARY_PATH, and a real binary at /usr/local/bin/ctmd instead of a symlink. Use one deployment model per host and do not mix them.
deploy.sh start and deploy.sh stop drive this unit through systemctl. Logs go to the journal under the ctmd-node syslog identifier.
The fields that matter to an operator:
Two hardening settings are load-bearing.
CapabilityBoundingSet= and AmbientCapabilities= are both empty, so the service runs with no capabilities. That is correct only while every listener binds above 1024, as the Ports table below shows. If you move a listener below 1024, add CAP_NET_BIND_SERVICE to both directives in a drop-in; setting one without the other still fails the bind. Prefer a reverse proxy or a firewall redirect over lowering the node’s own bind ports. MemoryDenyWriteExecute must stay no, because libwasmvm JIT-compiles CosmWasm contracts and needs writable and executable pages; setting it to yes crashes the node on contract execution.
macOS installs no service. deploy.sh start runs ctmd in the background under your own user, records the PID in $HOME/.ctmd/ctmd.pid, and writes $HOME/.ctmd/node.log; deploy.sh stop sends SIGINT to that PID. There is no unit, no drop-in, and no journal.
To return a host to a previously installed version, repoint the active symlink as described in Rollback. The unit does not change, so no daemon-reload is needed.
Build from source
If you are building locally instead of using a release, follow Build the Node, then verify the binary:Start sync
State sync is recommended for new nodes because it avoids replaying from genesis:Ports
Do not expose RPC, REST, gRPC, or EVM JSON-RPC directly to the public internet without a reverse proxy, firewall, and rate limiting.
Health checks
Check local status:status reports the active install, binary version, node home, service state when present, latest height, catching-up state, and peer count.
Monitoring
Enable CometBFT metrics inconfig.toml:
--metrics on startup and this app config:
http://127.0.0.1:26660/metrics for CometBFT metrics and http://127.0.0.1:6065/debug/metrics/prometheus for EVM JSON-RPC metrics. Run node_exporter alongside ctmd for disk, CPU, memory, and network metrics.
Common recovery
Use the managed lifecycle commands for normal start, stop, and inspection:reset deletes the managed install, node home, service, cache, and Linux system user/group so a later install --moniker <name> can start from scratch. Do not run it unless you intend to delete local chain data and key material in the managed node home.
On macOS: