Quick start¶
This quick start runs Freebird as a local Docker Compose development deployment. It is not a production deployment: Compose binds local HTTP ports and does not provide the trusted TLS reverse-proxy boundary, durable production storage, or operational controls required for production. See Production Deployment before deploying a public service.
Docker Compose development flow¶
From the repository root, install Docker with Compose support, then run:
cp .env.example .env
# For the self-contained interface smoke test, set SYBIL_RESISTANCE=none in .env.
# Replace the .env.example V7 placeholder with a real 64-character lowercase
# hexadecimal token key ID before starting Compose.
V7_TOKEN_KEY_ID="$(openssl rand -hex 32)"
sed -i.bak "s|^NATIVE_BEARER_V7_TOKEN_KEY_ID=.*|NATIVE_BEARER_V7_TOKEN_KEY_ID=${V7_TOKEN_KEY_ID}|" .env
rm -f .env.bak
./launch.sh up
launch.sh checks prerequisites, creates .env when needed, can generate an
admin key, starts the images, and waits for both services to become healthy.
The default host bindings are 127.0.0.1:8081 for the issuer and
127.0.0.1:8082 for the verifier.
Check the local services:
curl http://127.0.0.1:8081/.well-known/issuer
curl http://127.0.0.1:8082/.well-known/verifier
curl http://127.0.0.1:8082/health
Run the source client against the Compose services:
cargo run -p freebird-interface -- \
--issuer-url http://127.0.0.1:8081 \
--verifier-url http://127.0.0.1:8082
The expected result is one successful V4 issue-and-verify round trip. To check
replay behavior, run cargo run -p freebird-interface -- --replay; the second
use of the token should be rejected.
Useful lifecycle commands are:
./launch.sh status
./launch.sh logs
./launch.sh stop
The Compose configuration is deliberately for direct local development. Do not
expose these HTTP ports to the public internet or treat an in-memory/restarted
local service as replay-safe. The example .env otherwise selects invitation
admission; use a client that supplies the required proof if you retain that
setting.
Source-only local round trip¶
The following path is also documented and source-backed. It uses an explicitly unsafe development verifier replay store and disables Sybil checks only to make the local interface exercise self-contained. Use three terminals from the repository root.
Issuer (first run in a clean directory):
V7_TOKEN_KEY_ID="$(openssl rand -hex 32)"
ADMIN_API_KEY=local-admin-key-must-be-at-least-32-chars \
FREEBIRD_ENV=development FREEBIRD_UNSAFE_DEVELOPMENT_MODE=true \
AUDIT_LOG_PATH=audit_log.json \
BIND_ADDR=127.0.0.1:8081 ISSUER_ID=issuer:local:v4 \
ISSUER_SK_PATH=issuer_sk.bin KEY_ROTATION_STATE_PATH=key_rotation_state.json \
SYBIL_RESISTANCE=none REQUIRE_TLS=false \
NATIVE_BEARER_V7_ENABLE=true \
NATIVE_BEARER_V7_SK_PATH=native_bearer_v7.der \
NATIVE_BEARER_V7_METADATA_PATH=native_bearer_v7.json \
NATIVE_BEARER_V7_REGISTRY_PATH=native_bearer_v7_registry.json \
NATIVE_BEARER_V7_TOKEN_KEY_ID="$V7_TOKEN_KEY_ID" \
NATIVE_BEARER_V7_ASSET_ID=USD NATIVE_BEARER_V7_AMOUNT_MINOR=1 \
cargo run -p freebird-issuer --bin freebird-issuer
The openssl command supplies a real 64-character lowercase hexadecimal V7
token key ID. Keep that value, along with the generated V7 files, for later
starts. On first startup the issuer supports creating and then managing
native_bearer_v7.der, native_bearer_v7.json, and
native_bearer_v7_registry.json; it reuses the persisted material on restart.
Do not generate a new ID for an existing set of files. These settings are
unsafe development settings only.
Verifier:
ADMIN_API_KEY=local-admin-key-must-be-at-least-32-chars \
BIND_ADDR=127.0.0.1:8082 VERIFIER_ID=verifier:local:v4 \
VERIFIER_AUDIENCE=local VERIFIER_ACCEPTED_TOKEN_VERSIONS=v4 \
VERIFIER_ENV=development IN_MEMORY_REPLAY_STORE=true \
ISSUER_URL=http://127.0.0.1:8081/.well-known/issuer \
VERIFIER_SK_PATH=issuer_sk.bin REFRESH_INTERVAL_MIN=1 REQUIRE_TLS=false \
cargo run -p freebird-verifier --bin freebird-verifier
Then run cargo run -p freebird-interface. These settings are for local
testing only; in particular, REQUIRE_TLS=false, SYBIL_RESISTANCE=none, and
IN_MEMORY_REPLAY_STORE=true are not production settings.