Notice: This project is a work in progress and not all features are available yet. Please test out the setup if you use this setup
Holochain Environment & Agent Runtime Toolkit
A toolkit for quickly setting up and managing Holochain nodes. HEART provides automated setup, configuration, and testing for Holochain environments.
HEART is a toolkit for quickly setting up and managing Holochain nodes. It provides automated setup, configuration, and testing for Holochain environments.
- A Pulumi program for deploying Holochain nodes to DigitalOcean
- Nodes are Ubuntu 22.04 servers provisioned via cloud-init
- Pre-configured to run a specified version of Holochain and Lair Keystore
- Use
hcto install the apps you want to run
- Deploying a New Release Fleet - Stand up a dedicated set of servers for a new unyt version (one Pulumi stack per release)
- Setup an Always-On Node - Complete guide for setting up a production-ready Holochain node
- Setup A DO that is running a Holochain conductor - Technical details for server setup
- Setup Progenitor - Setting up progenitor nodes specifically
- Install Agents - Additional agent installation examples
Work inside the dev shell so pulumi and go are on PATH:
nix develop
make help # list build + deploy targets
make build # compile the Pulumi program
make vet # go vetSee Deploying a New Release Fleet for the deploy workflow.
- Basic Ubuntu setup with Holochain
- Version-specific Holochain installations
- Automated testing environment
- Comprehensive setup documentation
- Agent key management documentation
- Monitoring setup (Telegraf host metrics + Holochain metrics → InfluxDB)
- Piecework app installation automation
- App version management
- Backup procedures
- Snapshot-based rapid deployment
For a release fleet you don't run these by hand:
make new-release RELEASE=<v>readsDIGITALOCEAN_TOKENandINFLUX_TOKENfrom a gitignoredheart/.env(copyheart/.env.example) and setsdigitalocean:token,heart:influx-token,heart:project-nameandheart:releasefor you. The commands below are the underlying config keys, for reference or one-off overrides.
Configure the digital ocean token using:
pulumi config set --secret digitalocean:tokenSet the InfluxDB token using:
pulumi config set --secret heart:influx-tokenConfigure the project to use on Digital Ocean:
pulumi config set heart:project-name HoloEach release fleet runs in its own stack, identified by heart:release (this
namespaces every droplet name and adds a release:<x> tag):
pulumi config set heart:release v0-7-0Configure the number of nodes, of each type:
pulumi config set heart:blockchain-bridging-count 1
pulumi config set heart:notary-count 2 # e.g. give one release a notary pair
pulumi config set heart:always-online-count 2 # disabled role — defaults to 0, see defaults.yamlRaising a count above its default only takes effect end to end when the matching automation config exists: the disabled roles (heart-always-online, unyt-bridging — default 0) and a second notary (notary-2) have theirs parked in automation/config/disabled/ — move it back under automation/config/<server>/ and restore its automation/Makefile targets alongside the count bump.
All other per-release values (Holochain version, network endpoints, InfluxDB
bucket, droplet sizes) are optional config keys whose defaults live in
defaults.yaml — edit that file to change a default for all
releases. Metrics ship to the shared unyt bucket by default; override
heart:influx-bucket (with a bucket that already exists in InfluxDB) to isolate
a release's metrics. See
Pulumi.release.yaml.example for the full set
of keys.
This section describes where things live on a provisioned droplet. Use it as a reference when connecting to a node to install or manage apps.
All binaries are on PATH at /usr/local/bin/:
| Binary | Purpose |
|---|---|
holochain |
Holochain conductor |
lair-keystore |
Lair keystore |
hc |
Holochain CLI — use this to install apps and manage the conductor |
holo-keyutil |
Key utilities (sign, extract-pubkey) used during registration |
| Path | Purpose |
|---|---|
/etc/holochain/conductor-config.yaml |
Conductor configuration |
Everything lives under /var/lib/holochain/:
| Path | Purpose |
|---|---|
data/ |
Conductor databases and state |
lair/ |
Lair keystore data |
lair-passphrase |
Passphrase used to unlock the lair keystore (root:lair, mode 640 — the lair group lets co-located non-root services read it to sign via lair). Needed if you ever have to inspect the keystore directly. |
agent-pub-key |
The node's agent key in raw ed25519 form, base64url — the 32 bytes holo-keyutil extract-pubkey produced for the auth server. This is the key itself, not a fingerprint of it: the uhCAk… AgentPubKey is those 32 bytes re-encoded (u + base64url of a 3-byte type prefix that prints as hCAk, the key, and a 4-byte DHT location derived from it), so this file identifies the node's agent. It is not directly an --agent-key value, though — that wants the uhCAk… form, and nothing on the droplet re-encodes back to it. |
| Service | Purpose |
|---|---|
telegraf.service |
Collects host metrics (CPU, memory, disk, network) and ships to InfluxDB |
lair-keystore.service |
Lair keystore daemon |
holochain.service |
Holochain conductor daemon (also ships Holochain metrics directly to InfluxDB) |
holochain-register.service |
Registration service — runs on every boot to register the node and refresh auth credentials. On first boot it polls until an admin approves the key; on subsequent boots it refreshes credentials directly. |
Once the node is registered (check systemctl status holochain-register.service):
--agent-key takes the uhCAk… AgentPubKey. The node's own key is on disk in raw form and in lair (see the table above), but nothing here re-encodes it to uhCAk…, so mint a key to install under — or omit --agent-key entirely and let install-app generate one:
# awk END{} because hc's tracing subscriber prints to stdout when RUST_LOG is set
AGENT_KEY=$(hc client call --port 8800 new-agent | awk 'END{print $NF}' | tr -d '"')
hc client call --port 8800 install-app \
--app-id "your-app-id" \
--agent-key "${AGENT_KEY}" \
/path/to/your-app.happholo-keyutil provides two subcommands used during node registration:
holo-keyutil sign— signs data via lair IPCholo-keyutil extract-pubkey— parses a HolochainAgentPubKeyand extracts the raw ed25519 bytes
It is built and published by the release-holo-keyutil GitHub Actions workflow when a
v* tag is pushed — the tag names the release, so bump holo-keyutil/Cargo.toml's
version to match it. Droplets download the binary directly from that release at first
boot; the version is controlled by the heart:holo-keyutil-version config key (default
v0.2.0).
The pinned version must already have a published release before any pulumi up. First boot curl -fsSLs the binary from it under set -eo pipefail, so a tag that does not exist yet 404s, kills the whole first-boot script before it enables a single service, and the droplet arrives with no conductor, lair, telegraf or registration.
To use a new build, cut a release and point a stack at it:
git tag v0.3.0 && git push origin v0.3.0 # wait for the Actions workflow to finish
pulumi config set heart:holo-keyutil-version v0.3.0