Skip to content

Configuration -- Environment Variable Reference


Generating Your Environment File

Use the provided script to generate a .env.operator file with unique secrets:

bash
./generate-operator-env.sh <registry-name> > .env.operator

Example:

bash
./generate-operator-env.sh acme-labs > .env.operator

This generates:

  • A unique OPERATOR_DID (e.g., did:theprotocol:operator-a1b2c3d4e5f6g7h8)
  • Cryptographically random database passwords (48-char hex)
  • Cryptographically random signing keys (64-char hex)
  • Sensible defaults for all feature flags

IMPORTANT: The .env.operator file contains secrets. Never commit it to version control.


Environment Variables by Category

Identity

VariableExampleDescription
REGISTRY_NAMEacme-labsUnique name for your registry. Used as container name prefix.
OPERATOR_DIDdid:theprotocol:operator-<hex>Auto-generated. Your cryptographic operator identity.
FEDERATION_OPERATOR_ID(same as OPERATOR_DID)Identifies your events in the mainframe EventStore.

Database Passwords

VariableGeneratedDescription
PG_PASS_REGISTRY48-char hexPostgreSQL password for the registry database.
PG_PASS_TEG48-char hexPostgreSQL password for the TEG database.

These are generated randomly by generate-operator-env.sh. Never share or reuse them.

Security Keys

VariableLengthDescription
SECRET_KEY64-char hexApplication-level secret for session signing.
JWT_SECRET_KEY64-char hexJWT token signing key for developer and agent auth.
API_KEY_SECRET64-char hexAPI key signing secret. Must match TEG_REGISTRY_JWT_SECRET -- the generator handles this automatically.
TEG_REGISTRY_JWT_SECRET(same as API_KEY_SECRET)TEG uses this to validate registry-issued JWTs.
TEG_ADMIN_API_KEY64-char hexAdmin key for TEG internal operations. Used by registry to proxy TEG admin calls.
TEG_AVTP_SYSTEM_API_KEY64-char hexSystem-level API key for TEG protocol operations.
TEG_TOKEN_SIGNING_KEY64-char hexSigning key for TEG-issued tokens.
EVENT_STORE_INTERNAL_API_KEY64-char hexAPI key for EventStore event submission (fallback; mTLS is primary in federated mode).

Federation

VariableDefaultDescription
EVENT_STORE_URLhttps://events.example.comMainframe EventStore URL. Set automatically in compose for federated mode.
EVENT_STORE_ENABLEDtrueEnable EventStore event submission. Set to false for standalone mode (legacy).
EVENTSTORE_MTLS_REQUIREDtrueRequire mTLS for EventStore writes. Must be true in federated mode. API key fallback is disabled.
FEDERATION_BASE_URLhttps://nginx-federation:8443Internal URL for federation mTLS sidecar. Do not change unless customizing nginx.
CORS_ALLOW_ALL_ORIGINSfalseSet to true to allow cross-origin requests for federation discovery. Required if other registries or frontends need to query your /api/v1/public/registry-config or federation endpoints directly.
KAFKA_ENABLEDfalseEnable Kafka event bus (for high-throughput deployments).
KAFKA_BOOTSTRAP_SERVERS(empty)Kafka broker address. Only needed if KAFKA_ENABLED=true.

Note: FEDERATION_LICENSE_KEY is a legacy variable that is no longer used for authentication. All federation auth uses mTLS via SPIRE. You can safely remove it from your .env.operator.

Token Economy

VariableDefaultDescription
MINTING_AUTHORITYdisabledSet to disabled for federated mode (no local minting). Set to teg-layer for standalone mode (legacy).
DEFAULT_FEE_RATE0.5Base fee percentage on intra-registry transfers. Federation bounds: 0.5% -- 5.0%.
MAX_FEE_RATE5.0Maximum fee percentage (velocity-scaled ceiling).
GENESIS_GRANT_ENABLEDtrueWhen true, new agents receive a genesis AVT grant on creation.
GENESIS_GRANT_AMOUNT1000.0AVT amount granted to new agents. Set to 0 to disable.

Email (SMTP)

VariableDefaultDescription
MAIL_SERVERsmtp.example.comSMTP server hostname. Configure before production use.
MAIL_PORT587SMTP port (587 for STARTTLS, 465 for SSL).
MAIL_USERNAME(empty)SMTP authentication username.
MAIL_PASSWORDCHANGE_MESMTP authentication password.
MAIL_FROMnoreply@example.comSender email address for verification emails.
MAIL_FROM_NAME<registry-name>Display name in email "From" field.
MAIL_STARTTLSTrueUse STARTTLS encryption.
MAIL_SSL_TLSFalseUse direct SSL/TLS. Set to True and MAIL_STARTTLS=False for port 465.

Email is used for developer account verification. If unconfigured, set REQUIRE_EMAIL_VERIFICATION=false in your env file to allow immediate registration (not recommended for production).

Monitoring

VariableGeneratedDescription
GRAFANA_ADMIN_PASSWORD32-char hexGrafana admin password (if you add a Grafana container).

Feature Flags

VariableDefaultDescription
ENABLE_PROJECTION_SNAPSHOTStrueEnable TEG-to-EventStore projection snapshots (balance baseline).
GENESIS_GRANT_ENABLEDtrueEnable automatic AVT grant for new agents.
BETA_INVITE_REQUIREDfalseWhen true, developer registration requires an invite code.
AUDITED_BALANCE_ENABLEDtrueEnable balance auditing against EventStore projections.
CORS_ALLOW_ALL_ORIGINSfalseAllow all CORS origins for federation discovery endpoints.
EVENT_STORE_ENABLEDtrueEnable EventStore event submission (federated mode).
EVENTSTORE_MTLS_REQUIREDtrueRequire mTLS for EventStore (federated mode).

PgBouncer Configuration

The pgbouncer.ini file configures connection pooling for the registry database:

ini
[databases]
agentvault_registry = host=db port=5432 dbname=agentvault_registry user=registry password=<PG_PASS_REGISTRY>

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = any
pool_mode = transaction
max_client_conn = 200
default_pool_size = 20
ignore_startup_parameters = extra_float_digits,options
SettingValueDescription
pool_modetransactionConnections returned to pool after each transaction. Required for multi-worker FastAPI.
max_client_conn200Maximum simultaneous client connections (4 workers x ~50 each).
default_pool_size20Active connections to PostgreSQL per database.

IMPORTANT: Update the password value in pgbouncer.ini to match the PG_PASS_REGISTRY value generated in your .env.operator file.


Redis Configuration

Redis runs as a single instance with LRU eviction:

redis-server --maxmemory 128mb --maxmemory-policy allkeys-lru
SettingValueDescription
maxmemory128mbMaximum memory before eviction. Sufficient for leader election, rate limiting, and session state.
maxmemory-policyallkeys-lruEvict least-recently-used keys when memory is full.
Database0Single database (unlike the mainframe which uses DB 0-3 for multiple registries).

Redis is used for:

  • Leader election: Ensures only one worker runs each background task
  • Rate limiting: Shared counters across 4 uvicorn workers
  • WebSocket pub/sub: Cross-worker message broadcasting
  • Session state: Temporary cross-worker data sharing

Registry Service Configuration

These environment variables are set automatically in docker-compose.operator.yml and generally do not need manual changes:

VariableValueDescription
DATABASE_URLpostgresql+asyncpg://registry:<pass>@pgbouncer:6432/agentvault_registryAsync DB URL via PgBouncer.
DATABASE_URL_SYNCpostgresql://registry:<pass>@pgbouncer:6432/agentvault_registrySync DB URL for migrations.
TEG_LAYER_URLhttp://teg-layer:8080Internal TEG endpoint.
REDIS_URLredis://redis:6379/0Redis connection.
SPIFFE_ENDPOINT_SOCKETunix:///opt/spire/sockets/agent.sockSPIRE agent socket.
UVICORN_WORKERS4Number of FastAPI worker processes.

TEG Layer Configuration

These are set automatically in docker-compose.operator.yml:

VariableValueDescription
DATABASE_URLpostgresql://teg:<pass>@teg-db:5432/teg_layerTEG database (synchronous psycopg).
REGISTRY_URLhttp://registry:8000Registry URL for TEG to fetch emission policies.
ADMIN_API_KEY<TEG_ADMIN_API_KEY>Admin API key (from .env.operator).
MINTING_AUTHORITYdisabledFederated mode: no local minting.
UVICORN_WORKERS4Number of TEG worker processes.

Authentication Configuration

VariableDefaultDescription
ACCESS_TOKEN_EXPIRE_MINUTES90JWT access token lifetime in minutes (cluster default; env-overridable).
BOOTSTRAP_TOKEN_LIFETIME300Bootstrap token lifetime in seconds (5 minutes).
EMAIL_VERIFICATION_TOKEN_EXPIRE_HOURS24Email verification link expiry.
REQUIRE_EMAIL_VERIFICATIONtrueWhen false, new developers are verified immediately.

Rate Limiting

VariableDefaultDescription
RATE_LIMIT_PUBLIC60/minuteUnauthenticated requests.
RATE_LIMIT_DEVELOPER300/minuteDeveloper JWT-authenticated requests.
RATE_LIMIT_AGENT300/minuteAgent JWT-authenticated requests.
RATE_LIMIT_ADMIN(none)No rate limit for admin accounts.
RATE_LIMIT_BYPASS_KEYS(empty)Comma-separated API keys that bypass rate limiting.

Secret Rotation Guidance

When to Rotate

TriggerAction
Suspected compromiseRotate ALL keys immediately
Personnel changeRotate TEG_ADMIN_API_KEY and JWT_SECRET_KEY
Routine (quarterly)Rotate SECRET_KEY and JWT_SECRET_KEY

How to Rotate

  1. Generate a new value: openssl rand -hex 32
  2. Update the value in .env.operator
  3. Restart affected containers:
    bash
    docker compose -f docker-compose.operator.yml --env-file .env.operator up -d registry teg-layer
  4. For PG_PASS_REGISTRY or PG_PASS_TEG: you must also update the database user password inside the container before changing the env var, or re-create the database volumes.

Keys That Must Match

Key AKey BReason
API_KEY_SECRETTEG_REGISTRY_JWT_SECRETTEG validates JWTs signed by the registry. The generator sets both to the same value.

If these diverge, agent authentication will fail on TEG proxy calls.


Complete .env.operator Template

bash
# .env.operator -- Generated by generate-operator-env.sh
# DO NOT COMMIT -- contains secrets

# -- Identity
REGISTRY_NAME="<your-registry-name>"
OPERATOR_DID=did:theprotocol:operator-<auto-generated>

# -- Database passwords
PG_PASS_REGISTRY=<auto-generated-48-char-hex>
PG_PASS_TEG=<auto-generated-48-char-hex>

# -- Security keys
SECRET_KEY=<auto-generated-64-char-hex>
JWT_SECRET_KEY=<auto-generated-64-char-hex>
API_KEY_SECRET=<auto-generated-64-char-hex>
TEG_REGISTRY_JWT_SECRET=<must-match-API_KEY_SECRET>
TEG_ADMIN_API_KEY=<auto-generated-64-char-hex>
TEG_AVTP_SYSTEM_API_KEY=<auto-generated-64-char-hex>
TEG_TOKEN_SIGNING_KEY=<auto-generated-64-char-hex>
EVENT_STORE_INTERNAL_API_KEY=<auto-generated-64-char-hex>

# -- Token economy
MINTING_AUTHORITY=disabled
DEFAULT_FEE_RATE=0.5
MAX_FEE_RATE=5.0

# -- Federation
EVENT_STORE_ENABLED=true
EVENTSTORE_MTLS_REQUIRED=true
CORS_ALLOW_ALL_ORIGINS=false
KAFKA_BOOTSTRAP_SERVERS=
KAFKA_ENABLED=false

# -- Email (CONFIGURE BEFORE DEPLOY)
MAIL_SERVER=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=<your-smtp-username>
MAIL_PASSWORD=<your-smtp-password>
MAIL_FROM=noreply@example.com
MAIL_FROM_NAME="<your-registry-name>"
MAIL_STARTTLS=True
MAIL_SSL_TLS=False

# -- Monitoring
GRAFANA_ADMIN_PASSWORD=<auto-generated-32-char-hex>

# -- Features
ENABLE_PROJECTION_SNAPSHOTS=true
GENESIS_GRANT_ENABLED=true
GENESIS_GRANT_AMOUNT=1000.0
BETA_INVITE_REQUIRED=false
AUDITED_BALANCE_ENABLED=true

See also: Quickstart (Section 00) | Architecture (Section 01) | Federation (Section 03)

Server components AGPL-v3 · client SDK Apache-2.0. If a doc and the running stack disagree, trust the stack.