Skip to main content

Faucet operator guide

This guide is for running a testnet-only faucet service (backend + web UI + infra).

Canonical references (read these first):

warning

Operational risk:

  • A faucet runs a hot wallet. Assume it will be attacked.
  • Treat secrets as production-grade (secret manager, rotation, audit).
  • Never run the faucet against mainnet unless you have a dedicated security plan.

You will need

  • A Catalyst RPC URL (HTTPS recommended)
  • A funded faucet hot-wallet private key (keep it in a secret manager)
  • Redis + Postgres (for cooldowns + claim logging)
  • Cloudflare Turnstile keys (captcha)

Steps

Option A: Local dev (no Docker)

Backend:

cd Faucet/catalyst-faucet
cp .env.example .env
# edit .env (RPC_URL, CHAIN_ID, FAUCET_PRIVATE_KEY, REDIS_URL, DATABASE_URL, TURNSTILE_SECRET_KEY, ...)

npm install
npm run prisma:generate
npm run prisma:migrate:dev
npm run dev

Web:

cd ../catalyst-faucet-web
cp .env.example .env.local
# edit env (NEXT_PUBLIC_FAUCET_API_BASE_URL, NEXT_PUBLIC_TURNSTILE_SITE_KEY, ...)

npm install
npm run dev

Option B: Production VM (Docker Compose + TLS proxy)

Use the infra repo, which includes:

  • docker-compose.prod.yml (backend + web + redis + postgres + caddy)
  • example env files and runbooks

High-level flow (see repo README for full details):

cd Faucet/catalyst-faucet-infra

sudo mkdir -p /opt/catalyst-faucet/{env,data,backups}
sudo chown -R "$USER":"$USER" /opt/catalyst-faucet
chmod 700 /opt/catalyst-faucet

cp env/backend.env.example /opt/catalyst-faucet/env/backend.env
cp env/web.env.example /opt/catalyst-faucet/env/web.env
cp env/postgres.env.example /opt/catalyst-faucet/env/postgres.env
cp env/caddy.env.example /opt/catalyst-faucet/env/caddy.env

# edit env files (backend.env contains secrets)
chmod 600 /opt/catalyst-faucet/env/*.env

cp /opt/catalyst-faucet/env/caddy.env ./.env
docker-compose -f docker-compose.prod.yml up -d --build

Verify

Backend health:

curl -sS http://127.0.0.1:8080/health | jq

Backend info:

curl -sS http://127.0.0.1:8080/v1/info | jq

Abuse mitigation checklist (minimum)

From the backend implementation:

  • captcha (Turnstile) before any on-chain action
  • per-address cooldown
  • per-IP cooldown (store only salted hash)
  • optional per-country / per-ASN cooldown (when behind Cloudflare)
  • global RPM cap
  • admin pause switch
  • chain id allowlist (testnet-only)

See Faucet/catalyst-faucet/README.md (“Threat model / abuse mitigation”).

Troubleshooting

  • Service refuses to start: chain id allowlist mismatch (CHAIN_ID must match testnet).
  • High error rate / timeouts: your RPC endpoint is slow or rate-limiting; add failover or run your own node.