Skip to navigation

Self-hosting

Self-hosting

The same api.route surface the managed Lambda serves ships in gate/selfhost.py. Run it anywhere Python 3.12 runs, pointed at a DynamoDB-compatible endpoint — real AWS inside your VPC, or DynamoDB-Local for development. Tables are created on boot (idempotent, missing tables only), and metered billing is off by design: on your infrastructure the gate never talks to a Stripe price you don’t control.

Docker (fastest)

git clone https://github.com/AvenueDAdmin/writ
cd writ
WRIT_TOKEN_SECRET=$(python3 -c 'import secrets;print(secrets.token_urlsafe(48))') docker compose up

That boots writ-gate on http://localhost:8787 plus the amazon/dynamodb-local container. Agents, the CLI, and the portal hit it exactly like the managed gate:

WRIT_BASE=http://localhost:8787 writ check \
--key writ_yourKey \
--sponsor ops \
--agent billing-bot \
--verb db.write --target db!orders --purpose "place order"

Configuration

EnvMeaning
WRIT_DYNAMODB_ENDPOINT_URLPoint the gate’s state at a different endpoint: a DynamoDB-compatible store inside your VPC, or the compose dynamodb service (http://dynamodb:8000).
WRIT_TOKEN_SECRETRequired. Boot refuses without it (self-hosting a gate whose tokens anyone could forge is worse than a down one).
WRIT_CHAIN_SECRETAudit-hash chain key. Falls back to WRIT_TOKEN_SECRET.
WRIT_SELFHOST1 (default) forces metered billing off; WRIT_FORCE_BILLING=1 on a staging clone re-enables the billing paths.
WRIT_CHECK_FAILURE_MODEfailopen (default) or failclosed — same semantics as the managed gate.
WRIT_POLICY_CACHE_TTL_SECONDSIn-process policy cache TTL, default 5 (0 disables).
WRIT_DYNAMODB_READ_TIMEOUT_SECONDSSouthbound DynamoDB read budget, default 2 — the check decision deadline.

What is the same, what is different

  • Same: every /v1 endpoint, receipts + audit hash chain, principals, policies and overrides, kill switch, GitHub App flow, and the infrastructure-failure envelopes.
  • Different: metered billing (off), the managed portal login (portal routes serve, but Stripe wiring is absent), and the async GitHub scan worker — scans on a self-hosted gate run in-process rather than through a Lambda self-invocation.

When to self-host rather than use the managed gate

  • Compliance requires receipts and code never to transit Writ’s AWS account.
  • The gate must live on caller-side networking (VPC peering, private links) so the check decision never leaves your network.
  • You want the metering contract replaced: your tenant rows, your quotas.