Run a gateway
The gateway accepts hash submissions, persists jobs in SQLite, collects and verifies witness signatures, and exposes attestations and proofs. It is the public-facing component and should be treated as an untrusted network boundary around the witness services.
Build and start
Build from the workspace root:
cargo build --release -p witness-gateway
The gateway's relevant flags are:
| Flag | Default | Purpose |
|---|---|---|
--config |
network.json |
Network configuration |
--host |
127.0.0.1 |
Listen interface |
--port |
8080 |
HTTP listen port |
--database |
gateway.db |
SQLite path |
--admin-ui |
disabled | Enable /admin |
--admin-api-key |
environment | Admin credential |
--ws-auth-token |
environment | WebSocket credential |
--metrics-token |
environment | Metrics credential |
--behind-proxy |
disabled | Trust forwarded client IPs |
Example with persistent local storage:
target/release/witness-gateway \
--config /etc/witness/network.json \
--host 127.0.0.1 \
--port 8080 \
--database /var/lib/witness/gateway.db
The gateway speaks plain HTTP. For an internet-exposed service, terminate TLS
at a trusted reverse proxy or load balancer, restrict operational routes
there, and set WITNESS_BEHIND_PROXY=true (or --behind-proxy) only when the
proxy is authoritative for X-Forwarded-For.
Network and witness configuration
network.json defines the network ID, signature scheme, threshold, witness
public keys and endpoints, and optional federation/anchor settings. Every
witness entry must have a non-empty auth_token; startup aborts otherwise.
Treat the file as a secret because the operational form contains bearer
tokens. The public verification configuration is a different, secret-free
artifact.
Witnesses should be reachable only over trusted/private network paths. Keep their signing endpoints out of the public route unless the deployment has an explicit, reviewed boundary for them.
Public routes and admission
New requests arrive at POST /v1/attestations; clients retrieve jobs and
proofs through the documented /v1/... routes. Job creation is asynchronous,
and a confirmed result has passed the gateway's threshold verification before
being persisted. The gateway has a 30 requests/minute/IP admission limit, but
this is only defense in depth. See abuse and rate limiting.
The timestamp is reserved once, at job creation, and is not refreshed on retry.
If an outage lasts beyond the witnesses' max_clock_skew window (300 seconds
by default), the old reservation cannot be signed when services return. Treat
that retry as terminal in effect; do not expect the gateway to create a new
timestamp for the same canonical job.
Configure admin, metrics, WebSocket, and federation authentication before
exposure. With no WebSocket token, /ws/events is unauthenticated and
immediately broadcasts the lowercase digest and reservation timestamp for each
new reservation, before confirmation. The hardened outbound client is used for
witness, federation, Freebird, and Internet Archive requests; Trillian and DNS
use unrestricted reqwest, and Ethereum has URL preflight validation only.
Review every configured outbound URL and treat provider-specific SSRF exposure
as an operational risk.
Use a persistent local filesystem for SQLite. Do not place the database on a network filesystem or run multiple gateway processes against one database.