Host an Epicenter

An Epicenter is an always-on host for a community’s presence and history. Choose Railway for the shortest path, Docker/Compose for a portable deployment, or systemd for a direct VPS install.

Before you start

Use one persistent /data directory for the Epicenter database, identity key, and local attachment data. Back it up. Losing server-identity.key changes the host’s identity; losing the database loses the Epicenter’s stored history.

For a public Internet deployment, put HTTPS and WebSocket termination in front of the HTTP port and set --public-address to the public multiaddr. For example, a domain served on port 443 is /dns4/epicenter.example.com/tcp/443. The health endpoint is /health.

One Epicenter process per community. SQLite is the default and simplest choice. Postgres shares storage but does not make multiple Epicenter processes a supported high-availability setup.

Railway: Epicenter only

Railway is a good fit for an Epicenter’s HTTP and WebSocket surface. It is not a supported home for the libp2p relay: its TCP proxy address and port are allocated only after deployment, while a relay needs a stable public address that can be configured and advertised from startup.

  1. Create a service from the Tremor repository. Keep the root directory at the repository root so the Docker build can include the workspace.
  2. Set the Dockerfile path to crates/tremor-server/Dockerfile.
  3. Attach a persistent volume at /data, generate a public domain, and leave Railway’s sleeping/serverless option off.
  4. Set the healthcheck path to /health.
  5. Use the service’s assigned PORT in the start command. After the first deploy, replace the example domain with the generated Railway domain or your custom domain.
tremor-server --role epicenter --mode private --port "$PORT" \
  --db-path /data/epicenter.db \
  --identity-file /data/server-identity.key \
  --bootstrap-url https://bootstrap.example.com \
  --public-address /dns4/epicenter.example.com/tcp/443

Choose --mode public only when you want the Epicenter advertised in the Bootstrap discovery listing. Private is the default and remains adoptable by its connection details; it is simply not browseable in the public listing.

Do not add --role all or --relay-port on Railway. Put the optional relay on a VPS or bare-metal box instead.

Docker and Compose

The repository includes a Compose example for a single-node all-in-one deployment and split services at crates/tremor-server/docker-compose.yml. Build from the repository root, because the server Dockerfile copies both tremor-server and tremor-core.

git clone https://github.com/darrynhoskingluna/tremor.git
cd tremor
docker compose -f crates/tremor-server/docker-compose.yml up -d tremor-all
curl -fsS http://127.0.0.1:9090/health

For a public Epicenter, make a local copy of that Compose file and add the stable public multiaddr to the Epicenter command. Keep the /data volume intact across recreates and upgrades.

--public-address /dns4/epicenter.example.com/tcp/443

The tremor-all service exposes HTTP on 9090 and relay TCP on 4002. If you only need the Epicenter, use the split profile and run the Bootstrap service it references, or deploy the Epicenter against an existing Bootstrap URL with --bootstrap-url.

Bare metal with systemd

For a direct VPS install, place a released tremor-server binary at /usr/local/bin/tremor-server, create a dedicated unprivileged tremor user, and give it a durable data directory.

sudo useradd --system --home /var/lib/tremor --shell /usr/sbin/nologin tremor
sudo install -d -o tremor -g tremor /var/lib/tremor

Create /etc/systemd/system/tremor-epicenter.service:

[Unit]
Description=Tremor Epicenter
After=network-online.target
Wants=network-online.target

[Service]
User=tremor
Group=tremor
WorkingDirectory=/var/lib/tremor
ExecStart=/usr/local/bin/tremor-server --role epicenter --mode private --port 9090 --db-path /var/lib/tremor/epicenter.db --identity-file /var/lib/tremor/server-identity.key --bootstrap-url https://bootstrap.example.com --public-address /dns4/epicenter.example.com/tcp/443
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now tremor-epicenter
curl -fsS http://127.0.0.1:9090/health
sudo journalctl -u tremor-epicenter -f

Replace bootstrap.example.com with the Bootstrap host for your deployment. Terminate TLS in a reverse proxy; Caddy forwards WebSocket upgrades automatically:

epicenter.example.com {
  reverse_proxy 127.0.0.1:9090
}

Allow HTTPS and, when running a relay, TCP 4002 in both the host firewall and your VPS provider’s firewall. Keep port 9090 and any database port private behind the proxy.

Optional: run a libp2p relay separately

A relay helps peers behind NATs connect to The Grid. It is not required to host an Epicenter, has no Epicenter database, and is best run on a VPS or bare-metal host with a stable public TCP port. Keep its identity key persistent too.

tremor-server --role relay --relay-port 4002 \
  --identity-file /var/lib/tremor/relay-identity.key \
  --bootstrap-url https://bootstrap.example.com \
  --public-address /dns4/relay.example.com/tcp/4002

Open TCP 4002 and use the externally reachable DNS name and port in --public-address. Supplying --bootstrap-url lets the relay register itself for discovery; without it, the relay runs but is not advertised through Bootstrap.

To keep the relay running under systemd, use a separate unit with the same dedicated user and durable directory:

[Service]
User=tremor
Group=tremor
WorkingDirectory=/var/lib/tremor
ExecStart=/usr/local/bin/tremor-server --role relay --relay-port 4002 --identity-file /var/lib/tremor/relay-identity.key --bootstrap-url https://bootstrap.example.com --public-address /dns4/relay.example.com/tcp/4002
Restart=on-failure

[Install]
WantedBy=multi-user.target
Keep the concerns separate. An Epicenter provides community availability. A relay provides NAT traversal. On a normal VPS they may share a machine, but they use different ports and durable identity files; Railway supports the former, not the latter.

Verify and adopt

  1. Check the local health endpoint: curl -fsS http://127.0.0.1:9090/health.
  2. Check the same endpoint through the public HTTPS domain.
  3. Use the Tremor hosting flow to verify the reachable Epicenter and adopt it for your community. Do not publish a connection string until the public health check succeeds.
Keep persistentWhy
epicenter.dbEpicenter, MLS Delivery Service, and mailbox state when using SQLite.
server-identity.keyStable identity for the Epicenter or all-in-one host.
relay-identity.keyStable relay identity when relay runs separately.
Attachment storageLocal attachment blobs when using the local blob store.