Skip to main content
Arkognito needs no hosted service from us. Every piece is open source, and all shared state lives on Arkiv, so there is no database to run. Run the whole network, or run one piece and use other people’s for the rest.

Docker Compose

One image serves every role; the ROLE variable picks what each container runs.
1

Clone and install

2

Create wallets

Creates the relay-1, relay-2 and issuer wallets and the issuer seed in .env, and prints each address and balance. It never prints a key and never replaces a value that is already set. Fund the three addresses from the faucet.
3

Start the network

OHTTP_ALLOW_LOCAL=on lets the OHTTP relay forward to http://localhost relayers. Use it only locally.
4

Check health

Each returns "ok": true. The relayers also report their queue, batches written, balance and heartbeat entity.
Point an app at it:

Public deployment with HTTPS

Browsers and OHTTP relays only use https relayers on public hosts.
  1. Point DNS for your hostnames (for example relay-1.example.com, relay-2.example.com) at the machine.
  2. Put those hostnames in deploy/Caddyfile.
  3. Set the public URLs in .env:
    .env
  4. Start with the TLS overlay:
Caddy obtains certificates automatically, and the services stop exposing ports directly.
Run the OHTTP relay under a different operator than the relayers. If the same people run both, OHTTP protects nothing.

Without Docker

Node.js 22 or newer:
Use a process manager (systemd, pm2) to restart them on failure. They keep no local state except the optional issuer quota file.

Platforms (Railway, Fly, Render)

Every service is the same Dockerfile; create one service per role and set ROLE. The repository’s railway.json configures the Dockerfile build, the /healthz health check and restart-always. The Railway + Vercel guide has the exact variables.

Run only part of it

  • Only a relayer, no tokens: REQUIRE_TOKENS=off. A per-address rate limit protects your gas.
  • A relayer that accepts another team’s tokens: REQUIRE_TOKENS=on, ISSUER_WALLET_ADDRESS and ISSUER_URL of their issuer.
  • Only an OHTTP relay for someone else’s relayers: ROLE=ohttp-relay, nothing else to set.

Operating it

  • Gas. Every batch and every heartbeat costs gas. Across all our test runs (several hundred records plus heartbeats) one relayer spent about 0.1 GLM. Watch balanceGlm on /healthz; the relayer logs LOW BALANCE below LOW_BALANCE_GLM. The faucet gives 0.1 GLM a day per wallet.
  • One wallet, one process. Never run two processes on the same relayer wallet: their transactions collide.
  • Restarts are safe. Queued requests are lost and clients retry elsewhere; a record that was already written is recognised by its client, so nothing is written twice. The heartbeat and the OHTTP gateway key survive restarts.
  • Issuer keys rotate daily and derive from ISSUER_RSA_SEED. Never change the seed during a day: clients would see two keys and refuse the issuer.
  • Logs contain batch summaries only, never IPs or request bodies. Keep your proxy the same.
All variables are in the configuration reference.
Last modified on October 12, 2026