mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 08:01:16 +00:00
168 lines
7.2 KiB
Plaintext
168 lines
7.2 KiB
Plaintext
# ============================================
|
|
# Warmbly environment reference
|
|
# ============================================
|
|
# Defaults are no-cloud: with just the four secrets in the "Required" block set,
|
|
# Warmbly runs with no AWS, GCP, Stripe, or Kafka. Each subsystem is a provider
|
|
# switch — flip one to opt into a cloud service.
|
|
#
|
|
# Config priority: env var first, then AWS SSM/Secrets Manager (only when
|
|
# AWS_CONFIG_ENABLED=true).
|
|
# ============================================
|
|
|
|
# === Required ===
|
|
APP_ENV=dev # dev | production
|
|
# JWT / session signing. Min 32 chars. MUST match the realtime service JWT_SECRET.
|
|
AUTH_SECRET=change-me-min-32-characters-long
|
|
# 64 hex chars (32 bytes). Seals mailbox SMTP/IMAP credentials at rest.
|
|
# BACK IT UP — losing it makes connected mailboxes unrecoverable. `openssl rand -hex 32`
|
|
CREDENTIALS_ENCRYPTION_KEY=
|
|
# Shared token for the backend internal API (workers + tracking use it).
|
|
INTERNAL_API_TOKEN=change-me-internal-token
|
|
PRIMARY_DB=postgres://warmbly:warmbly@localhost:5432/warmbly_dev?sslmode=disable
|
|
REDIS=redis://localhost:6379
|
|
|
|
# === Provider switches (no-cloud defaults) ===
|
|
AWS_CONFIG_ENABLED=false # true => read secrets from AWS SSM/Secrets Manager
|
|
|
|
# Event bus. nats (default): one small JetStream binary. kafka: build the images
|
|
# with GO_TAGS=kafka / CARGO_FEATURES=kafka and set KAFKA_* below.
|
|
EVENTBUS_PROVIDER=nats
|
|
NATS_URL=nats://localhost:4222
|
|
# NATS_STREAM_NAME=warmbly
|
|
# NATS_SUBJECT_PREFIX=warmbly
|
|
|
|
# Serialization. json is required with NATS and wherever workers run. avro is
|
|
# only for a Kafka + Schema Registry deployment.
|
|
CODEC_PROVIDER=json
|
|
|
|
# Encryption root key. local (default): AES master key below. aws: AWS KMS.
|
|
KMS_PROVIDER=local
|
|
# base64 32 bytes. BACK IT UP — losing it is unrecoverable. `make gen-key`
|
|
KMS_LOCAL_MASTER_KEY=
|
|
# KMS_LOCAL_MASTER_KEY_FILE=/run/secrets/kms_master_key # alternative to the inline key
|
|
# KMS_AWS_KEY_ID=alias/warmbly # when KMS_PROVIDER=aws
|
|
|
|
# Blob storage. filesystem (default): a local dir. s3: any S3-compatible store.
|
|
BLOB_PROVIDER=filesystem
|
|
BLOB_FS_ROOT=/data/blobs # shared between backend + workers (same host / shared volume)
|
|
# Public URL base for avatars/logos served by the backend's /public route.
|
|
BLOB_PUBLIC_BASE_URL=http://localhost:8080/public
|
|
# For BLOB_PROVIDER=s3 (AWS / MinIO / R2 / B2):
|
|
# BLOB_BUCKET=warmbly
|
|
# AWS_ENDPOINT_URL_S3=http://minio:9000 # non-AWS endpoint
|
|
# AWS_REGION=us-east-1
|
|
# AWS_ACCESS_KEY_ID=
|
|
# AWS_SECRET_ACCESS_KEY=
|
|
|
|
# Delayed tasks (campaign ticks, scheduled sends). local (default): an in-process
|
|
# Postgres poller — no external service. gcloud: GCP Cloud Tasks.
|
|
TASKS_PROVIDER=local
|
|
# TASKS_LOCAL_POLL_INTERVAL=1s
|
|
# When TASKS_PROVIDER=gcloud, also set:
|
|
# CLOUD_TASKS_QUEUE_NAME=projects/<p>/locations/<l>/queues/<q>
|
|
# CLOUD_TASKS_WEBHOOK_URL=https://<api-host>/webhook/email
|
|
# GOOGLE_APPLICATION_CREDENTIALS_JSON=<service-account-email>
|
|
|
|
# Billing. none (default): no Stripe, every feature unlocked, no trial expiry.
|
|
# stripe: wire the Stripe integration (keys below required).
|
|
BILLING_PROVIDER=none
|
|
# STRIPE_SECRET_KEY=
|
|
# STRIPE_WEBHOOK_SECRET=
|
|
# STRIPE_PUBLISHABLE_KEY=
|
|
|
|
# Captcha. Auto-off when TURNSTILE_SECRET is unset; set CAPTCHA_PROVIDER=turnstile
|
|
# + TURNSTILE_SECRET to require Cloudflare Turnstile on auth endpoints.
|
|
# CAPTCHA_PROVIDER=none
|
|
# TURNSTILE_SECRET=
|
|
|
|
# === Backend API ===
|
|
API_HOST=0.0.0.0:8080 # binds all interfaces already
|
|
GIN_MODE=release # debug | release
|
|
# With the shipped docker-compose.yml, set PUBLIC_HOST to your LAN IP or domain
|
|
# and APP_URL / CORS_ALLOW_ORIGINS / WEBSOCKET_URL / TRACKING_DOMAIN / the VITE_*
|
|
# frontend URLs all derive from it. Set them explicitly if you're not using that
|
|
# compose (e.g. behind a reverse proxy on https://your-domain).
|
|
# PUBLIC_HOST=192.168.1.50
|
|
APP_URL=http://localhost:5173
|
|
CORS_ALLOW_ORIGINS=http://localhost:5173,http://localhost:5174
|
|
WEBSOCKET_URL=ws://localhost:4000/socket/websocket
|
|
ENCRYPTED_KEYS_PROVIDER=postgres # backend/consumer: postgres; workers: http (below)
|
|
GEODB_PATH=/app/data/GeoLite2-City.mmdb # optional in dev
|
|
|
|
# === Mailbox connections ===
|
|
# Gmail mailboxes need YOUR Google Cloud OAuth client (a "Web application" client)
|
|
# with authorized redirect URI <API_HOST>/addresses/google/callback. Set on the
|
|
# backend AND every worker. Leave unset to connect mailboxes only via SMTP/IMAP.
|
|
BOX_GOOGLE_CLIENT_ID=
|
|
BOX_GOOGLE_CLIENT_SECRET=
|
|
# Microsoft 365 / Outlook OAuth client (redirect <API_HOST>/addresses/outlook/callback):
|
|
BOX_OUTLOOK_CLIENT_ID=
|
|
BOX_OUTLOOK_CLIENT_SECRET=
|
|
|
|
# === Social sign-in (all optional; email+password / passkeys work standalone) ===
|
|
# GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_REDIRECT_URI are the LOGIN client,
|
|
# separate from the BOX_GOOGLE_* mailbox client above.
|
|
# GOOGLE_CLIENT_ID=
|
|
# GOOGLE_CLIENT_SECRET=
|
|
# GOOGLE_REDIRECT_URI=
|
|
# GOOGLE_IOS_CLIENT_ID=
|
|
# APPLE_APP_ID=
|
|
# APPLE_TEAM_ID=
|
|
# APPLE_KEY_ID=
|
|
# APPLE_KEY_SECRET=
|
|
# Passkeys (WebAuthn): derived from APP_URL when unset. Changing the RP ID
|
|
# invalidates enrolled passkeys, so keep it stable per deployment.
|
|
# WEBAUTHN_RP_ID=app.example.com
|
|
# WEBAUTHN_RP_ORIGINS=https://app.example.com
|
|
|
|
# === Worker (each worker process) ===
|
|
# Workers hold no relational DB; they reach DEKs over the backend internal API.
|
|
# ENCRYPTED_KEYS_PROVIDER=http
|
|
# ENCRYPTED_KEYS_BACKEND_URL=http://backend:8080
|
|
# ENCRYPTED_KEYS_WORKER_TOKEN=<same as INTERNAL_API_TOKEN>
|
|
# WORKER_ID=<uuid> # stable identity; otherwise derived from hostname
|
|
|
|
# === Notification email (outbound platform mail) ===
|
|
EMAIL_NAME=Warmbly
|
|
EMAIL_ADDRESS=noreply@example.com
|
|
TRACKING_DOMAIN=localhost:3000
|
|
SMTP_HOST=mailpit # a real SMTP relay in production
|
|
SMTP_PORT=1025
|
|
|
|
# === Tracking service (open/click) ===
|
|
TRACKING_HOST=0.0.0.0
|
|
TRACKING_PORT=3000
|
|
# Resolves opaque /c/<id> click tickets via the backend internal API.
|
|
# BACKEND_INTERNAL_URL=http://backend:8080
|
|
TRACKING_RATE_LIMIT_PER_MIN=300
|
|
|
|
# === Realtime service (Elixir/Phoenix) ===
|
|
PHX_HOST=localhost
|
|
PORT=4000
|
|
JWT_SECRET=change-me-min-32-characters-long # MUST equal the backend AUTH_SECRET
|
|
SECRET_KEY_BASE=change-me-phoenix-secret-key-base-min-64-characters-long
|
|
DATABASE_URL=postgres://warmbly:warmbly@localhost:5432/warmbly_dev?sslmode=disable
|
|
REDIS_URL=redis://localhost:6379
|
|
# Realtime transport. false (default): Redis bridge, no cloud. Read identically by
|
|
# backend, consumer, and realtime — never set true on one side only.
|
|
PUBSUB_ENABLED=false
|
|
CHECK_ORIGIN=false
|
|
# When PUBSUB_ENABLED=true (Google Pub/Sub): also set GCP_PROJECT_ID +
|
|
# GOOGLE_APPLICATION_CREDENTIALS_JSON on every service.
|
|
# GCP_PROJECT_ID=
|
|
|
|
# === AI provider (optional; omit all to run with AI features off) ===
|
|
# Set on the backend AND consumer. Self-host bills your provider directly, so the
|
|
# credit ledger is bypassed (unlimited) when BILLING_PROVIDER=none.
|
|
# AI_PROVIDER= # openai | openrouter | groq | ollama | anthropic | custom
|
|
# AI_API_KEY=
|
|
# AI_MODEL=
|
|
# AI_BASE_URL= # required for custom
|
|
# SEARCH_PROVIDER= # optional web-search tool
|
|
# SEARCH_API_URL=
|
|
# SEARCH_API_KEY=
|
|
|
|
# === Observability (all optional) ===
|
|
# SENTRY_DSN=
|
|
# LOG_DISCORD_WEBHOOK_URL=
|