Skip to main content
This deploys two relayers (one also runs the token issuer) on Railway and the demo site on Vercel. About 30 minutes. The demo site needs no relayer URLs: it finds the relayers through their heartbeat entities on Arkiv as soon as they are up with https URLs.

Before you start

Get these through a password manager or another private channel, never in chat, an issue or the repository:
  • RELAYER_1_PRIVATE_KEY, RELAYER_2_PRIVATE_KEY, ISSUER_WALLET_PRIVATE_KEY: three funded testnet wallets
  • ISSUER_WALLET_ADDRESS: the issuer wallet’s public address
  • ISSUER_RSA_SEED: 32 bytes of hex
  • ARKIV_ACCESS_KEY (optional): an Arkiv Hub key for higher RPC rate limits
Or create your own with npm run setup and fund them from the faucet.
One wallet, one place. Once a relayer wallet runs on Railway, do not also run it on a laptop. Two processes on one wallet make each other’s transactions fail.

relay-1: relayer and issuer

1

Create the service

In Railway: New Project → Deploy from GitHub repo → soumyacodes007/Arkognito. Railway reads railway.json: Dockerfile build, /healthz health check, restart always. Rename the service relay-1.
2

Add a domain and a volume

Settings → Networking → Generate Domain with target port 8787. Then Volumes → New Volume with mount path /data.
3

Set variables

4

Deploy and check

https://<relay-1 domain>/healthz returns "ok": true and a heartbeat entity key. https://<relay-1 domain>/v1/info shows "tokensRequired": true and an issuerUrl equal to its own URL.
  • PORT must equal the domain’s target port, or Railway answers 502.
  • RELAYER_PUBLIC_URL must be the https domain: it is announced on Arkiv, and browsers only use https relayers.
  • RAILWAY_RUN_UID=0: Railway mounts volumes as root and the image runs as a normal user; without it the quota file cannot be written. Skip the volume, this variable and ISSUER_QUOTA_FILE if you accept quotas resetting on restart.
  • MAX_WAIT_MS=20000: a private save waits at most 20 s for other users (default 60 s). Raise it for more privacy once there is real traffic.
  • TOKENS_PER_DAY=20: writes per wallet per day (default 5).

relay-2

Same repository, a second service named relay-2, domain with target port 8788, no volume:
ISSUER_WALLET_ADDRESS and ISSUER_URL make relay-2 accept relay-1’s tokens. Never give relay-2 relay-1’s key.

OHTTP relay (optional)

Only needed once the app uses ohttpRelay, and ideally run by someone else:
Domain with target port 8790; no keys, no volume. /healthz shows how many relayers it has verified.

Demo site on Vercel

1

Import the repository

Add New → Project → soumyacodes007/Arkognito. Leave Root Directory at the repository root: the demo builds the SDK from source. The repository’s vercel.json sets the install command (npm ci), build command (npm run build -w arkognito-demo) and output (apps/demo/dist).
2

Deploy

No environment variables. Node.js 22.
3

Try it

  • /observer.html reads straight from Arkiv.
  • /sketch-private.html → Connect MetaMask: add the Tiramisu network, sign three times (two for the key, one for tokens), draw, save. About 20–30 s later the sketch appears under My sketches.

Final checklist

  • Both relayers’ /healthz return "ok": true.
  • In a private window on another device the demo loads and the observer view shows data.
  • A private sketch saves and appears in My sketches after a reload.
  • The observer’s owner query on your MetaMask address shows only your public sketches.
  • Railway logs show batch N: … record(s) lines and no LOW BALANCE.
Problems: see troubleshooting.
Last modified on October 12, 2026