Configuration Reference

Enzyme is configured through a YAML config file, environment variables, or CLI flags. Settings are loaded in the following order, where later sources override earlier ones:

  1. Built-in defaults
  2. Config file (config.yaml or --config <path>)
  3. Environment variables (ENZYME_ prefix)
  4. CLI flags

Config File

Enzyme looks for config.yaml or config.yml in the current working directory. You can specify a custom path:

./enzyme --config /etc/enzyme/config.yaml

Environment Variables

All settings can be set via environment variables with the ENZYME_ prefix. Nested keys use underscores:

ENZYME_SERVER_PORT=9090
ENZYME_DATABASE_PATH=/var/lib/enzyme/enzyme.db
ENZYME_EMAIL_ENABLED=true
ENZYME_STORAGE_TYPE=s3
ENZYME_STORAGE_S3_BUCKET=my-enzyme-bucket

CLI Flags

./enzyme --server.port 9090 --database.path /var/lib/enzyme/enzyme.db

Run ./enzyme --help for all available flags.


Logging

Key Env Var CLI Flag Default Description
log.level ENZYME_LOG_LEVEL --log.level info Minimum log level: debug, info, warn, error.
log.format ENZYME_LOG_FORMAT --log.format text Log output format: text (human-readable) or json (structured).

Server

Key Env Var CLI Flag Default Description
server.host ENZYME_SERVER_HOST --server.host 0.0.0.0 Address to bind the HTTP server to.
server.port ENZYME_SERVER_PORT --server.port 8080 Port to listen on.
server.public_url ENZYME_SERVER_PUBLIC_URL --server.public_url http://localhost:8080 Public-facing URL. Used in emails (invite links, password resets). Must include the scheme.
server.allowed_origins ENZYME_SERVER_ALLOWED_ORIGINS --server.allowed_origins ["http://localhost:3000"] CORS allowed origins. Set to [] for production (same-origin with embedded frontend). Each origin must include a scheme.
server.read_timeout ENZYME_SERVER_READ_TIMEOUT 30s Max duration for reading the entire request (including body). Minimum: 1s.
server.write_timeout ENZYME_SERVER_WRITE_TIMEOUT 60s Max duration for writing the response. SSE connections override this per-connection. Minimum: 1s.
server.idle_timeout ENZYME_SERVER_IDLE_TIMEOUT 120s Max duration to wait for the next request on a keep-alive connection. Minimum: 1s.

TLS

Key Env Var CLI Flag Default Description
server.tls.mode ENZYME_SERVER_TLS_MODE --server.tls.mode off TLS mode: off, auto (Let's Encrypt), or manual.
server.tls.cert_file ENZYME_SERVER_TLS_CERT_FILE --server.tls.cert_file Path to TLS certificate file. Required for manual mode.
server.tls.key_file ENZYME_SERVER_TLS_KEY_FILE --server.tls.key_file Path to TLS private key file. Required for manual mode.
server.tls.auto.domain ENZYME_SERVER_TLS_AUTO_DOMAIN --server.tls.auto.domain Domain for automatic certificate provisioning. Required for auto mode.
server.tls.auto.email ENZYME_SERVER_TLS_AUTO_EMAIL --server.tls.auto.email Contact email for Let's Encrypt. Required for auto mode.
server.tls.auto.cache_dir ENZYME_SERVER_TLS_AUTO_CACHE_DIR --server.tls.auto.cache_dir ./data/certs Directory to cache TLS certificates.

Database

Key Env Var CLI Flag Default Description
database.path ENZYME_DATABASE_PATH --database.path ./data/enzyme.db Path to the SQLite database file. The directory must exist.
database.max_open_conns ENZYME_DATABASE_MAX_OPEN_CONNS 2 Max open database connections. Allows concurrent reads with WAL mode. Minimum: 1.
database.busy_timeout ENZYME_DATABASE_BUSY_TIMEOUT 5000 Milliseconds to wait when the database is locked before returning SQLITE_BUSY. Minimum: 0.
database.cache_size ENZYME_DATABASE_CACHE_SIZE -2000 SQLite page cache size. Negative values = KB (e.g., -2000 = ~2 MB). Positive values = number of pages.
database.mmap_size ENZYME_DATABASE_MMAP_SIZE 0 Memory-mapped I/O size in bytes. 0 disables mmap. Set higher for large databases on capable hardware.

Enzyme uses SQLite in WAL mode. No external database server is needed. See Scaling Guide for tuning guidance.

Authentication

Key Env Var CLI Flag Default Description
auth.session_duration ENZYME_AUTH_SESSION_DURATION --auth.session_duration 720h How long bearer tokens remain valid. Uses Go duration format (e.g., 720h = 30 days, 24h, 168h).
auth.bcrypt_cost ENZYME_AUTH_BCRYPT_COST 12 bcrypt hashing cost for passwords. Higher is more secure but slower. Range: 4-31.

Storage

Storage controls where uploaded files (attachments, avatars, workspace icons, custom emoji) are stored. Three backends are available:

  • local (default) — Files stored on the local filesystem.
  • s3 — Files stored in any S3-compatible object store (AWS S3, MinIO, DigitalOcean Spaces, Backblaze B2, etc.).
  • off — File uploads disabled. Upload endpoints return 403 and upload UI is hidden.
Key Env Var CLI Flag Default Description
storage.type ENZYME_STORAGE_TYPE --storage.type local Storage backend: off, local, or s3.
storage.max_upload_size ENZYME_STORAGE_MAX_UPLOAD_SIZE --storage.max_upload_size 10485760 Maximum upload file size in bytes. Default is 10 MB. Minimum: 1 KB.

Local Storage

Key Env Var CLI Flag Default Description
storage.local.path ENZYME_STORAGE_LOCAL_PATH --storage.local.path ./data/uploads Directory for uploaded files.
storage.local.signing_secret ENZYME_STORAGE_LOCAL_SIGNING_SECRET HMAC secret for signing file download URLs. If empty, a random secret is auto-generated and saved to .signing_secret in the database directory for persistence across restarts. You can also set this explicitly.

S3 Storage

Key Env Var Default Description
storage.s3.endpoint ENZYME_STORAGE_S3_ENDPOINT S3 endpoint (e.g., s3.amazonaws.com, nyc3.digitaloceanspaces.com). Required.
storage.s3.bucket ENZYME_STORAGE_S3_BUCKET S3 bucket name. Required. The bucket must already exist.
storage.s3.access_key ENZYME_STORAGE_S3_ACCESS_KEY S3 access key. Required.
storage.s3.secret_key ENZYME_STORAGE_S3_SECRET_KEY S3 secret key. Required.
storage.s3.region ENZYME_STORAGE_S3_REGION S3 region (e.g., us-east-1).
storage.s3.path_style ENZYME_STORAGE_S3_PATH_STYLE false Use path-style addressing. Set true for MinIO.
storage.s3.use_ssl ENZYME_STORAGE_S3_USE_SSL true Use HTTPS for S3 connections. Set false for local MinIO without TLS.

With S3 storage, file downloads use S3 pre-signed URLs — the browser downloads directly from S3 rather than proxying through the Enzyme server. No public-read ACLs are required on the bucket.

Email

Email is optional. When disabled, password reset, email verification, and notification digest features are unavailable and their UI is hidden. Invite links will still work.

Key Env Var CLI Flag Default Description
email.enabled ENZYME_EMAIL_ENABLED --email.enabled false Enable SMTP email sending.
email.host ENZYME_EMAIL_HOST SMTP server hostname.
email.port ENZYME_EMAIL_PORT 587 SMTP server port.
email.username ENZYME_EMAIL_USERNAME SMTP username.
email.password ENZYME_EMAIL_PASSWORD SMTP password.
email.from ENZYME_EMAIL_FROM Sender email address (e.g., Enzyme <noreply@example.com>).

Rate Limiting

Rate limiting protects authentication endpoints from brute-force attacks. Limits are per IP address.

Key Env Var Default Description
rate_limit.enabled ENZYME_RATE_LIMIT_ENABLED true Enable rate limiting.
rate_limit.login.limit ENZYME_RATE_LIMIT_LOGIN_LIMIT 10 Max login attempts per window.
rate_limit.login.window ENZYME_RATE_LIMIT_LOGIN_WINDOW 1m Login rate limit window.
rate_limit.register.limit ENZYME_RATE_LIMIT_REGISTER_LIMIT 5 Max registration attempts per window.
rate_limit.register.window ENZYME_RATE_LIMIT_REGISTER_WINDOW 1h Registration rate limit window.
rate_limit.forgot_password.limit ENZYME_RATE_LIMIT_FORGOT_PASSWORD_LIMIT 5 Max password reset requests per window.
rate_limit.forgot_password.window ENZYME_RATE_LIMIT_FORGOT_PASSWORD_WINDOW 15m Password reset request window.
rate_limit.reset_password.limit ENZYME_RATE_LIMIT_RESET_PASSWORD_LIMIT 10 Max password reset attempts per window.
rate_limit.reset_password.window ENZYME_RATE_LIMIT_RESET_PASSWORD_WINDOW 15m Password reset attempt window.

SSE (Real-Time Events)

Key Env Var Default Description
sse.event_retention ENZYME_SSE_EVENT_RETENTION 24h How long SSE events are stored for reconnection catch-up.
sse.cleanup_interval ENZYME_SSE_CLEANUP_INTERVAL 1h How often old SSE events are purged from the database.
sse.heartbeat_interval ENZYME_SSE_HEARTBEAT_INTERVAL 30s How often heartbeat events are sent to keep SSE connections alive. Minimum: 5s.
sse.client_buffer_size ENZYME_SSE_CLIENT_BUFFER_SIZE 256 Channel buffer size per SSE client. Increase for high-traffic workspaces. Minimum: 16.

Push Notifications

Push notifications deliver alerts to mobile devices when users are offline. Notifications are forwarded to a push relay service that holds FCM/APNs credentials and dispatches to devices.

Key Env Var CLI Flag Default Description
push_notifications.enabled ENZYME_PUSH_NOTIFICATIONS_ENABLED --push_notifications.enabled false Enable push notifications. Requires a reachable relay service.
push_notifications.relay_url ENZYME_PUSH_NOTIFICATIONS_RELAY_URL --push_notifications.relay_url https://push.enzyme.im URL of the push relay service. Must use HTTPS (except for localhost).
push_notifications.include_preview ENZYME_PUSH_NOTIFICATIONS_INCLUDE_PREVIEW --push_notifications.include_preview true Include a short message preview in the push notification body. Set false for privacy.

The default relay (push.enzyme.im) is operated by Enzyme and works out of the box. By default, the relay receives metadata (sender name, channel name) and a short message preview. Set include_preview to false to send only metadata — the mobile app will fetch message content directly from your server. See Notifications for details on the delivery pipeline and privacy model.

Telemetry (OpenTelemetry)

Optional observability via OpenTelemetry. When enabled, Enzyme exports traces and metrics to any OTLP-compatible collector (Jaeger, Grafana Alloy, Datadog Agent, etc.). Disabled by default with zero overhead.

Key Env Var CLI Flag Default Description
telemetry.enabled ENZYME_TELEMETRY_ENABLED --telemetry.enabled false Enable OpenTelemetry instrumentation.
telemetry.endpoint ENZYME_TELEMETRY_ENDPOINT --telemetry.endpoint localhost:4317 OTLP collector endpoint (host:port).
telemetry.protocol ENZYME_TELEMETRY_PROTOCOL --telemetry.protocol grpc Export protocol: grpc or http.
telemetry.insecure ENZYME_TELEMETRY_INSECURE --telemetry.insecure true Use plaintext (no TLS) for OTLP export.
telemetry.sample_rate ENZYME_TELEMETRY_SAMPLE_RATE --telemetry.sample_rate 1.0 Trace sampling rate. 1.0 = sample everything, 0.1 = sample 10%.
telemetry.service_name ENZYME_TELEMETRY_SERVICE_NAME --telemetry.service_name enzyme Service name reported to the collector. Useful for multi-instance deployments.
telemetry.headers Map of headers sent with every OTLP export request. Use for backend auth (e.g., x-honeycomb-team).
telemetry.traces ENZYME_TELEMETRY_TRACES --telemetry.traces true Export traces. Set to false to disable trace export while keeping other signals.
telemetry.metrics ENZYME_TELEMETRY_METRICS --telemetry.metrics true Export metrics. Set to false to disable metric export while keeping other signals.
telemetry.logs ENZYME_TELEMETRY_LOGS --telemetry.logs true Export logs via OTLP. Set to false to disable log export while keeping other signals.
telemetry.frontend_endpoint ENZYME_TELEMETRY_FRONTEND_ENDPOINT --telemetry.frontend_endpoint OTLP/HTTP endpoint for the browser trace proxy. Auto-derived from endpoint if empty.

See the Observability Guide for details on what's captured (traces, metrics, log correlation) and setup examples.

Example: Local development with Jaeger

# Start Jaeger all-in-one
docker run -d --name jaeger \
  -p 4317:4317 \
  -p 16686:16686 \
  jaegertracing/all-in-one:latest

# Start Enzyme with telemetry
ENZYME_TELEMETRY_ENABLED=true ./enzyme

Then open http://localhost:16686 to view traces.

Full Example

log:
  level: 'info'
  format: 'text'

server:
  host: '0.0.0.0'
  port: 443
  public_url: 'https://chat.example.com'
  allowed_origins: [] # Same-origin (embedded frontend)
  tls:
    mode: 'auto'
    auto:
      domain: 'chat.example.com'
      email: 'admin@example.com'
      cache_dir: './data/certs'
  read_timeout: '30s'
  write_timeout: '60s'
  idle_timeout: '120s'

database:
  path: '/var/lib/enzyme/enzyme.db'
  max_open_conns: 2
  busy_timeout: 5000
  cache_size: -2000
  mmap_size: 0

auth:
  session_duration: '720h'
  bcrypt_cost: 12

storage:
  type: 'local'
  max_upload_size: 26214400 # 25 MB
  local:
    path: '/var/lib/enzyme/uploads'
    signing_secret: 'your-random-secret-here'
  # To use S3 instead:
  # type: 's3'
  # s3:
  #   endpoint: 's3.amazonaws.com'
  #   bucket: 'enzyme-uploads'
  #   access_key: 'AKIA...'
  #   secret_key: '...'
  #   region: 'us-east-1'

email:
  enabled: true
  host: 'smtp.postmarkapp.com'
  port: 587
  username: 'your-api-key'
  password: 'your-api-key'
  from: 'Enzyme <notifications@example.com>'

rate_limit:
  enabled: true
  login:
    limit: 10
    window: '1m'
  register:
    limit: 5
    window: '1h'
  forgot_password:
    limit: 5
    window: '15m'
  reset_password:
    limit: 10
    window: '15m'

sse:
  event_retention: '24h'
  cleanup_interval: '1h'
  heartbeat_interval: '30s'
  client_buffer_size: 256

push_notifications:
  enabled: true
  relay_url: 'https://push.enzyme.im'
  include_preview: true

telemetry:
  enabled: false
  endpoint: 'localhost:4317'
  protocol: 'grpc'
  insecure: true
  sample_rate: 1.0
  service_name: 'enzyme'
  traces: true
  metrics: true
  logs: true