Run a validator
A Zentalk validator runs the relay binary, routing encrypted messages through the network. Install it with Homebrew or the installer script, then manage it as a system service.
Install with Homebrew (macOS and Linux)
Section titled “Install with Homebrew (macOS and Linux)”brew tap ZentaChain/tapbrew install zentalk-validatorThis installs the relay binary (currently v1.2.1) as zentalk-validator — the binary only; key, configuration, and service setup are separate steps (see below). Upgrade with brew upgrade zentalk-validator; remove with brew uninstall zentalk-validator && brew untap ZentaChain/tap. The tap also provides a zentalk-api formula (currently v1.0.0) for the API server binary.
Install with the installer script (Linux, systemd)
Section titled “Install with the installer script (Linux, systemd)”The install.sh script in the zentalk-validator repository performs a full installation as root:
sudo OPERATOR_ADDRESS=0xYourEthereumAddress bash install.shWhat it does:
- Creates a dedicated system user
zentalk(no home directory, no login shell). - Creates
/opt/zentalk-validator/{keys,data,logs}withkeys/at mode 700. - Downloads the release binary for your architecture (amd64, arm64, armv7) to
/usr/local/bin/relay. - Verifies the SHA256 checksum against the release
checksums.txtand aborts on mismatch. - Verifies the GPG signature on
checksums.txtwhen a.ascsignature is published (see below). - Prompts for (or reads) your Ethereum operator address and writes
/opt/zentalk-validator/config.env. - Generates an RSA key at
/opt/zentalk-validator/keys/relay.pem(mode 600) if none exists — existing keys are preserved. - Installs and starts the
zentalk-validatorsystemd service (hardened:NoNewPrivileges,PrivateTmp,ProtectSystem=strict,ProtectHome), plus a detect-only update-check timer.
Installer environment variables:
| Variable | Default | Description |
|---|---|---|
OPERATOR_ADDRESS |
prompted | Your Ethereum wallet address (0x + 40 hex chars) |
ZENTALK_VERSION |
latest |
Release to install (semver, e.g. v1.2.1) |
RELAY_PORT |
8080 |
Relay port written to config.env |
HEALTH_PORT |
8170 |
Health/monitoring port written to config.env |
NETWORK |
mainnet |
mainnet or testnet |
UPDATE_CHECK_INTERVAL |
6h |
Update-check timer interval |
Release signature verification
Section titled “Release signature verification”Checksum files can be GPG-signed (checksums.txt.asc). The installer and updater auto-detect the signature and verify it when gpg is installed:
| Variable | Default | Behavior |
|---|---|---|
ZENTALK_GPG_SIG_FINGERPRINT |
unpinned | Expected signing-key fingerprint; verification fails on any other key |
ZENTALK_GPG_SIG_FAIL_ON_UNPINNED |
true |
Abort when a signature exists but no fingerprint is pinned (set false to fall back to SHA256-only — not recommended) |
ZENTALK_GPG_SIG_REQUIRED |
false |
Hard-fail unless the checksums file was GPG-verified |
See the release-key details in the zentalk-validator repository (docs/RELEASE_SIGNING.md).
Install on macOS (LaunchAgent)
Section titled “Install on macOS (LaunchAgent)”install-macos.sh installs to ~/zentalk-validator/ (binary, keys/private.pem, config.env, logs/) and registers a LaunchAgent labeled io.zentalk.validator at ~/Library/LaunchAgents/io.zentalk.validator.plist. Manage it with launchctl load/unload on that plist; logs go to ~/zentalk-validator/logs/validator.log. Checksum and GPG verification match the Linux installer.
Configure the relay
Section titled “Configure the relay”The validator relay binary accepts:
| Flag | Required | Default | Description |
|---|---|---|---|
-operator |
Yes | — | Ethereum wallet address (0x...) |
-network |
No | mainnet |
mainnet or testnet |
-port |
No | 9001 |
Relay port (message routing) |
-health-port |
No | relay port + 90 (9091) |
Health check and monitoring port |
-key |
No | — | Path to the RSA key file (PEM) |
-genkey |
No | false |
Generate a new RSA key pair |
-version |
No | — | Print version and exit |
These are the binary’s built-in defaults; install.sh installations instead run with ports 8080/8170, set by the RELAY_PORT and HEALTH_PORT values the installer writes to config.env (below).
relay \ -operator 0xYourEthereumAddress \ -network mainnet \ -port 8080 \ -health-port 8170 \ -key /opt/zentalk-validator/keys/relay.pemConfiguration lives in /opt/zentalk-validator/config.env (Linux) and is loaded by the systemd unit:
| Variable | Default | Description |
|---|---|---|
OPERATOR_ADDRESS |
— | Operator wallet address (required) |
RELAY_PORT |
8080 |
Relay port |
HEALTH_PORT |
8170 |
Health port — bound on all interfaces; close it yourself |
DHT_PORT |
8180 |
libp2p port. Derived as RELAY_PORT + 100; recorded, not configurable |
NETWORK |
mainnet |
Network selection |
ZENTALK_LOG_LEVEL |
info |
debug, info, warn, error |
ZENTALK_LOG_FORMAT |
text |
text or json |
Edit the file and sudo systemctl restart zentalk-validator to apply.
| Port | Direction | Purpose |
|---|---|---|
8080 |
Inbound | Relay server (message routing) |
8180 |
Inbound | libp2p — peering depends on this port |
8170 |
Must not be reachable | Health and metrics — nothing closes it for you |
Three points, each of which has been got wrong in production:
8180 is not optional and not configurable. The relay opens its libp2p host
on RELAY_PORT + 100 and reads no flag or variable for it. Set -port 9000 and
libp2p moves to 9100.
A validator with only 8080 open looks healthy. It starts, serves /health,
reports active, and still dials out — so it appears in the DHT. It just cannot
be dialled back, and a network whose nodes can only connect outbound forms no
connections at all. Five validators were once deployed exactly that way: all
green, none peered.
8170 must not be reachable — and it is not closed for you. It serves the
operator’s ETH address, the peer list, message counts, the update window and an
unauthenticated Prometheus registry. The relay binary binds it on all
interfaces (pkg/network/health.go calls ListenAndServe on ":8170"). The
127.0.0.1:8170 you may have read elsewhere is the port mapping in
docker-compose.yml, so only the Docker path has it: after install.sh
(systemd) or install-macos.sh (LaunchAgent) the endpoint answers on every
address the host has, until your firewall says otherwise. Reach it from the host
or through an SSH tunnel.
sudo ufw allow 8080/tcpsudo ufw allow 8180/tcpsudo ufw deny 8170/tcp # not merely "not allowed" — actively closedThe installer does not run these for you: it prints the three port numbers,
including the derived one for your RELAY_PORT, and leaves the policy to you —
it cannot see whether yours lives in a cloud security group, a host firewall or
a NAT device.
Manage the service
Section titled “Manage the service”| Task | Command |
|---|---|
| Status | sudo systemctl status zentalk-validator |
| Follow logs | sudo journalctl -u zentalk-validator -f |
| Restart | sudo systemctl restart zentalk-validator |
| Stop | sudo systemctl stop zentalk-validator |
| Health check | curl http://localhost:8170/health |
| Runtime stats | curl -H "Authorization: Bearer $ZENTALK_HEALTH_TOKEN" http://localhost:8170/stats |
/stats, /metrics, /topology, /updates and /version require
Authorization: Bearer $ZENTALK_HEALTH_TOKEN; only /health is open. With no
token set they answer 401 to everyone, including on localhost — the gate is
fail-closed. /stats returns local operational metrics — messages_relayed, uptime, route-cache hit ratio — not on-chain claims. The status.sh script in the validator repository renders a status dashboard from the same endpoints and the local config, key, and log paths on Linux and macOS.
Update
Section titled “Update”Update detection is detect-only: a systemd timer polls GitHub every 6 hours and writes the flag file /opt/zentalk-validator/data/update-available when a newer release exists. Nothing is auto-applied. To update:
sudo bash update.sh # latest releasesudo ZENTALK_VERSION=v1.2.1 bash update.sh # specific versionupdate.sh stops the service, backs up the current binary, downloads and verifies the new one (SHA256 + optional GPG, same rules as install), restarts the service, and waits up to 30 seconds for http://localhost:8170/health to pass. If the health check fails, it automatically rolls back to the previous binary. Keys, configuration, and data are always preserved.
Uninstall
Section titled “Uninstall”sudo bash uninstall.shThe script prompts for confirmation, offers to back up your keys and config.env to ~/zentalk-validator-backup/ first, then removes the service, update-check timer, binaries, data directory, and the zentalk system user.
See also
Section titled “See also”- Node binaries and ports — running the full node stack (relay, mesh, bootstrap) from source
- CLI reference — operator command-line tools
- Federation overview — how validators fit into the federated network
