Dockerized setup for running HyperBEAM AO mainnet nodes. Builds HyperBEAM from source with all dependencies (Erlang 27, Rebar3, Rust 1.95) using the default rebar3 profile, where the lua device (~lua@5.3a) is the AO compute method.
Builds are pinned to the v0.11 tag of HyperBEAM by default (see the VERSION build arg).
Legacy: the previous genesis_wasm-based setup (for legacy
ao.TN.1wasm processes) is deprecated and lives in legacy/ as a known-working config base.
- Docker/Podman and Compose
- An Arweave wallet file (JSON keyfile)
Set the WALLET_FILE environment variable to the path of your Arweave wallet (or with .env, see .env.example):
export WALLET_FILE=/path/to/wallet.jsonRun a node with persistent cache:
docker compose up hyperbeamThe node will be available on port 8734.
| Service | Mode | Cache | Description |
|---|---|---|---|
hyperbeam |
Dev shell | Persistent | Development node with a named volume for cache-mainnet |
hyperbeam-ephemeral |
Dev shell | Ephemeral | Development node with no persistent cache |
hyperbeam-release |
Release | Persistent | Production release build with a named volume |
hyperbeam-release-ephemeral |
Release | Ephemeral | Production release build with no persistent cache |
- Dev shell services run via
rebar3 shell— useful for development, debugging, and live interaction with the Erlang shell. - Release services use a compiled OTP release (
./bin/hb foreground) — suitable for production deployments.
Configuration is provided via .flat files mounted into the container:
- config.flat — used by dev shell services
- config.release.flat — used by release services
Both files set priv_key_location to the path where the wallet is mounted inside the container. Note that typed config values (booleans/lists) must come from a JSON config (config.release.json) via HB_CONFIG; .flat coerces values to strings.
A .flat file holds one key: value per line and nothing else. From v0.11 any other line, comments included, stops the node at boot with failed_to_load_config ... invalid_line; older versions skipped such lines silently.
config.release.flat sets scheduler-default-commitment-spec: ans104@1.0 because aoconnect spawns processes with signing-format: ans104. With the stock httpsig@1.0 default the scheduler rejects them with process_not_verified.
This image does not include the genesis_wasm server, so it will not compute legacy ao.TN.1 (wasm) processes. Mainnet processes must declare their own execution-device — spawn with execution-device: lua@5.3a and a lua module (lua source published to Arweave, not a wasm binary) to run AO processes on this node. For legacy wasm processes, use the legacy image.
The image ships an entrypoint that hardens how a bare hb foreground
container picks its identity and stops:
- Identity is fail-closed. HyperBEAM silently mints a fresh wallet when
none exists. The entrypoint refuses to start unless a keyfile exists at
HB_WALLET_PATH(defaults to the path the bundled configs use), then exportsHB_KEYwith the same path, so a node whose config does not setpriv_key_locationloads the file that was checked. This matters from v0.11, whose release no longer ships aconfig.flat: without it, a container started with no mounted config would minthyperbeam-key.jsoninstead. SetHB_ALLOW_EPHEMERAL_WALLET=trueto explicitly opt into a throwaway identity (e.g. for scratch containers). - SIGTERM stops the node. On SIGTERM the entrypoint initiates
hb stop, waitsHB_SHUTDOWN_GRACEseconds (default 30) for a clean exit, then hard-kills and exits 0 for the orchestrated stop. v0.11 stops cleanly within a few seconds, so the hard kill is a fallback. It is there for older versions: on v0.9-FINAL the bare BEAM (PID 1, relxforeground) ignores SIGTERM andbin/hb stop(init:stop()) wedges partway through app shutdown, so the node only ever died by SIGKILL. The elmdb cache is LMDB (transactionally crash-safe), so the hard kill loses at most uncommitted work.
Nomad: set kill_timeout comfortably above HB_SHUTDOWN_GRACE
(e.g. 45s over a 30s grace) so the entrypoint's escalation runs instead of
the runtime's.
ao-test/ contains bun + aoconnect smoke tests that spawn lua-device processes against a running node: Arweave- and EVM-signed interactions, revert-on-error semantics, and a comparison of read paths for nested process state. See its README for setup (the lua module must be published once).
To build the image without starting a service:
docker compose build hyperbeamThe Dockerfile builds the v0.11 tag of HyperBEAM by default. To build a different version, set the VERSION build arg:
docker compose build --build-arg VERSION=edge hyperbeamPersistent services use named volumes to retain cache-mainnet data across restarts:
hyperbeam— dev shell cachehyperbeam-release— release cache
To reset the cache, remove the volume:
docker volume rm hyperbeam-docker_hyperbeam