Environment Variables

Complete reference for all Quackback configuration options.

DU
Demo User
Written By Demo UserLast updated 2 months ago

Complete reference for all Quackback configuration options. Copy .env.example to .env and fill in your values.

Required Variables

Warning:
These variables must be set for Quackback to run.

Variable

Description

Example

DATABASE_URL

PostgreSQL connection string

postgresql://postgres:password@localhost:5432/quackback

BASE_URL

Public URL for your instance (used for auth, emails, and OAuth callbacks)

https://feedback.example.com

PORT

Port the application server listens on

3000

SECRET_KEY

Secret key for authentication and encryption (32+ chars). Used for session signing and deriving encryption keys.

openssl rand -base64 32

REDIS_URL

Redis/Dragonfly connection for background job queue (BullMQ). Dragonfly is included in docker-compose.

redis://localhost:6379

Database connection tuning

Note:
These are optional. The defaults work for most deployments. Tune them only if you've measured a connection-pool bottleneck.

Variable

Default

Description

DB_POOL_MAX

10 (web/all), 20 (worker)

Max Postgres connections this process opens. The default is role-aware: worker replicas get a larger pool since they run more concurrent jobs.

DB_IDLE_TIMEOUT

20

Seconds an idle pooled connection stays open before closing (1-3600).

Reverse proxy

Variable

Default

Description

TRUSTED_PROXY_HOPS

0

Number of trusted reverse-proxy hops allowed to supply client-IP headers (X-Forwarded-For). Set to 1 behind a single proxy (Nginx, Caddy, Railway). 0 means no proxy headers are trusted.

Server Roles

Tip:
Single-container self-hosters can skip this. The default already does what you want. Read Scale with multiple replicas before splitting roles.

Variable

Default

Description

QUACKBACK_ROLE

all

Controls whether this process runs background workers. all serves HTTP and runs queue workers/sweepers (single-container default). web serves HTTP only and enqueues jobs without consuming them. worker runs queue workers/sweepers and still serves HTTP (for health probes), but shouldn't receive user traffic.

Email Configuration

Configure email delivery for OTP codes, notifications, and invitations.

Tip:
If email is not configured, OTP codes and other emails are printed to the console. This is useful for local development.

Priority order: SMTP (if configured) > Resend (if configured) > Console logging.

SMTP

Variable

Description

Example

EMAIL_SMTP_HOST

SMTP server hostname

smtp.sendgrid.net

EMAIL_SMTP_PORT

SMTP port

587

EMAIL_SMTP_USER

SMTP username

apikey

EMAIL_SMTP_PASS

SMTP password

SG.xxxx

EMAIL_SMTP_SECURE

Use TLS (for port 465)

true

EMAIL_FROM

Sender email address

Quackback <[email protected]>

Resend

Variable

Description

Example

EMAIL_RESEND_API_KEY

Resend API key

re_xxxxxxxxxxxx

EMAIL_FROM

Sender email address

Quackback <[email protected]>

Inbound Email

Lets a visitor's email reply thread back into their conversation. Two independent ways to receive inbound mail: configure the one that fits your deployment, or both.

Provider webhook

Variable

Description

EMAIL_INBOUND_DOMAIN

Receiving domain (e.g. a Resend inbound domain). Agent replies use reply+<conversationId>@<domain>.

EMAIL_INBOUND_SIGNING_SECRET

The provider's webhook signing secret (Svix whsec_...).

Both must be set together. Point the provider's inbound webhook at <BASE_URL>/api/chat/email/inbound.

IMAP polling

Self-hosted alternative that needs no public webhook endpoint. See Receive email over IMAP for the full guide.

Variable

Default

Description

EMAIL_INBOUND_PROVIDER

unset

Set to imap to enable the poller. Leave unset to disable it entirely.

IMAP_HOST

required

IMAP server hostname

IMAP_PORT

993 (TLS) or 143 (plaintext)

IMAP server port

IMAP_USER

required

Mailbox username

IMAP_PASSWORD

required

Mailbox password

IMAP_TLS

true

Set to false for a plaintext connection

IMAP_MAILBOX

INBOX

Mailbox to poll

Note:
EMAIL_INBOUND_PROVIDER, IMAP_HOST, IMAP_USER, and IMAP_PASSWORD are required together. The poller never connects unless all four are set.

OAuth Providers

Enable social login for portal users and team members.

GitHub

Variable

Description

GITHUB_CLIENT_ID

GitHub OAuth App client ID

GITHUB_CLIENT_SECRET

GitHub OAuth App client secret

Create at: GitHub Developer Settings

Callback URL: https://your-domain.com/api/auth/callback/github

Google

Variable

Description

GOOGLE_CLIENT_ID

Google OAuth client ID

GOOGLE_CLIENT_SECRET

Google OAuth client secret

Create at: Google Cloud Console

Callback URL: https://your-domain.com/api/auth/callback/google

Note:
Integration credentials (Slack, Microsoft Teams, Linear, etc.) are configured through the admin UI and stored securely in the database, not as environment variables.

Realtime Chat Transport

Variable

Default

Description

CHAT_TRANSPORT_MODE

live

live streams chat over SSE (/api/chat/stream). Set to poll to force the widget and portal onto the polling fallback if you're behind a reverse proxy that buffers or drops long-lived event streams.

AI

Enable AI features: post summaries, duplicate detection, feedback extraction, and help center semantic search. AI is off unless you set the key, the endpoint, and a model for each role -- Quackback works with any OpenAI-compatible endpoint but never assumes one.

Variable

Description

Example

OPENAI_API_KEY

API key for your AI endpoint

sk-...

OPENAI_BASE_URL

OpenAI-compatible endpoint. Required -- there is no default

https://api.openai.com/v1

AI_CHAT_MODEL

Default model for chat features (summaries, suggestions, merge verification)

gpt-4o-mini

AI_EMBEDDING_MODEL

Model for embeddings (duplicate detection, semantic search)

text-embedding-3-small

AI_SUMMARY_MODEL

Per-feature override of AI_CHAT_MODEL for post summaries

off

AI_SENTIMENT_MODEL

Per-feature override for sentiment analysis

gpt-4o-mini

AI_EXTRACTION_MODEL

Per-feature override for suggestion extraction

gpt-4o-mini

AI_QUALITY_GATE_MODEL

Per-feature override for the suggestion quality gate

gpt-4o-mini

AI_INTERPRETATION_MODEL

Per-feature override for feedback interpretation

gpt-4o-mini

AI_MERGE_MODEL

Per-feature override for merge verification

gpt-4o

AI_HELP_CENTER_MODEL

Per-feature override for help center Ask AI

gpt-4o-mini

AI_HELP_CENTER_TRANSLATE_MODEL

Per-feature override for help center article auto-translation

gpt-4o-mini

AI_ASSISTANT_MODEL

Per-feature override for the Quinn AI assistant

gpt-4o

AI_INBOX_TRANSLATION_MODEL

Per-feature override for inbox message translation

gpt-4o-mini

AI_CLASSIFICATION_MODEL

Per-feature override for ticket/message classification

gpt-4o-mini

Per-feature overrides fall back to AI_CHAT_MODEL when unset. Set an override to off to disable just that feature. Use model ids your endpoint accepts -- gateways typically want provider-prefixed ids like google/gemini-3.1-flash-lite-preview.

Note:
Before v0.12.0, OPENAI_API_KEY alone enabled AI with an implicit OpenAI endpoint and built-in model names. If you upgraded and AI features turned off, add OPENAI_BASE_URL, AI_CHAT_MODEL, and AI_EMBEDDING_MODEL.

File Storage

S3-compatible storage for image uploads in changelogs and rich text content. Supports AWS S3, Cloudflare R2, Backblaze B2, MinIO, and other S3-compatible services.

Note:
If not configured, image upload is disabled in the rich text editor. For local development, MinIO is included in docker-compose and configured by default. Run bun run setup to start it.

Variable

Description

Example

S3_ENDPOINT

S3 endpoint URL (leave empty for AWS S3)

http://localhost:9000

S3_BUCKET

S3 bucket name

quackback

S3_REGION

S3 region

us-east-1

S3_ACCESS_KEY_ID

S3 access key

minioadmin

S3_SECRET_ACCESS_KEY

S3 secret key

minioadmin

S3_FORCE_PATH_STYLE

Use path-style URLs (required for MinIO, R2)

true

S3_PUBLIC_URL

Public URL for uploaded files (optional)

https://cdn.example.com

Telemetry

Anonymous usage statistics help improve Quackback. Telemetry is enabled by default and can be disabled via environment variable.

Variable

Description

Example

DISABLE_TELEMETRY

Set to "true" to disable anonymous usage statistics

true

Logging

The server emits structured JSON logs to stdout, one object per line, ready for any log shipper (Grafana Alloy, Promtail, Fluent Bit, Vector).

Variable

Default

Description

Example

LOG_LEVEL

info in production, debug otherwise

Verbosity: trace | debug | info | warn | error | fatal | silent

info

Docker Startup

Note:
Both variables below are read by the container's entrypoint script, not the Zod-validated app config. They apply to any Docker deployment (Compose or docker run).

Variable

Default

Description

SKIP_MIGRATIONS

false

Set to true to skip the automatic startup migration, e.g. when a Kubernetes pre-upgrade hook runs migrations out-of-band.

SEED_DATABASE

false

Set to true to populate demo data on startup. Don't enable this in production.

Docker Compose Variables

Note:
These variables configure the compose stack (docker-compose.prod.yml) itself, not the application. The app never reads them directly. Compose uses them to name containers and to fill in values like POSTGRES_PASSWORD that the stack then wires into DATABASE_URL for you. See Deploy with Docker.

Variable

Default

Description

QUACKBACK_TAG

latest

Image tag to run. Pin to a specific release in production.

APP_PORT

3000

Host port the app is published on. The container always listens on 3000 internally.

COMPOSE_PROJECT_NAME

quackback

Name Compose uses for the project's containers, network, and volumes.

POSTGRES_USER

quackback

Bundled PostgreSQL username.

POSTGRES_PASSWORD

required

Bundled PostgreSQL password.

POSTGRES_DB

quackback

Bundled PostgreSQL database name.

MINIO_ROOT_USER

quackback

Bundled MinIO root user. Doubles as the app's S3_ACCESS_KEY_ID.

MINIO_ROOT_PASSWORD

required

Bundled MinIO root password. Doubles as the app's S3_SECRET_ACCESS_KEY.

MINIO_IMAGE_TAG

RELEASE.2025-04-22T22-12-26Z

Pinned MinIO image tag.

MC_IMAGE_TAG

RELEASE.2025-04-16T18-13-26Z

Pinned MinIO client (mc) image tag, used by the bucket-init step.

Complete Example

# ===================
# Required
# ===================
DATABASE_URL="postgresql://postgres:password@localhost:5432/quackback"
SECRET_KEY="your-32-character-minimum-secret-key-here"
BASE_URL="https://feedback.yourcompany.com"
REDIS_URL="redis://localhost:6379"

# ===================
# Email (choose one)
# ===================
# SMTP
EMAIL_SMTP_HOST="smtp.sendgrid.net"
EMAIL_SMTP_PORT="587"
EMAIL_SMTP_USER="apikey"
EMAIL_SMTP_PASS="SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
EMAIL_FROM="Quackback <[email protected]>"

# Or Resend
# EMAIL_RESEND_API_KEY="re_xxxxxxxxxxxx"
# EMAIL_FROM="Quackback <[email protected]>"

# ===================
# OAuth (optional)
# ===================
GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"

GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"

# ===================
# Telemetry (optional)
# ===================
# DISABLE_TELEMETRY="true"

Validation

Note:
Quackback validates required variables on startup. Missing variables will cause the application to fail with a clear error message indicating which variables are missing.

Was this helpful?

Your feedback shapes what we write next.