This page covers deployment of a non-validator c8ntinuum 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. 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 with deploy.sh start, deploy.sh stop, and systemd.
  • 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,web3 for externally exposed RPC. Enable txpool or debug only 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 429 rates, and WebSocket reconnect storms.

Deploy script

To install or update ctmd, run the deploy.sh script. You can download and run the script manually:
This download-first flow is the preferred operator path because it gives you a local script to inspect, rerun, and use for lifecycle commands.

Install from release

Recommended Linux install:
Recommended macOS 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:
A host built by hand from a flat /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:
On macOS:
To replay from genesis instead:
On macOS:

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:
Check install and sync 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 in config.toml:
Optional EVM JSON-RPC metrics require --metrics on startup and this app config:
Scrape 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:
For a clean reinstall, use the destructive reset command:
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: