PlunkPlunk
Self-Hosting

Environment Variables

Configuration reference

Security & Database

VariableRequiredDescriptionExample
JWT_SECRETYesSecret key used to sign JWT tokens. Generate with openssl rand -base64 32.s3cr3t...
DB_PASSWORDYesPostgreSQL database password. Used by the Docker Compose setup.changeme123
DATABASE_URLYesFull PostgreSQL connection string used by the application at runtime (typically through PgBouncer). Auto-configured in Docker.postgresql://plunk:password@postgres:5432/plunk
DIRECT_DATABASE_URLYesDirect PostgreSQL connection string used by Prisma migrations. Must bypass any connection pooler. Auto-configured in Docker.postgresql://plunk:password@postgres:5432/plunk
REDIS_URLYesRedis connection string.redis://redis:6379
NODE_ENVNoApplication environment. Set to production for production deployments.production
PORTNoPort the API server listens on.8080 (default)

URLs & Domains

Set your subdomains here. The application automatically derives all internal and client-side URLs from these at container startup — you don't need to set *_URI or NEXT_PUBLIC_* variables manually.

VariableRequiredDescriptionExample
API_DOMAINYesSubdomain for the API server.api.yourdomain.com
DASHBOARD_DOMAINYesSubdomain for the dashboard app.app.yourdomain.com
LANDING_DOMAINYesSubdomain for the landing page.www.yourdomain.com
WIKI_DOMAINYesSubdomain for the documentation site.docs.yourdomain.com
USE_HTTPSNoSet to true when running behind a TLS-terminating reverse proxy. Used to construct URLs with the correct protocol.false (default)

AWS SES

VariableRequiredDescriptionExample
AWS_SES_REGIONYesAWS region where SES is configured.us-east-1
AWS_SES_ACCESS_KEY_IDYesAWS access key ID with SES send permissions.AKIA...
AWS_SES_SECRET_ACCESS_KEYYesAWS secret access key for SES.wJalr...
SES_CONFIGURATION_SETNoSES configuration set name used for open/click tracking.plunk-configuration-set (default)
SES_CONFIGURATION_SET_NO_TRACKINGNoA second SES configuration set without tracking. When set, projects can toggle email tracking on/off. If omitted, the tracking toggle is hidden.plunk-no-tracking-configuration-set (default)
MAIL_FROM_SUBDOMAINNoSubdomain prefix used when constructing the MAIL FROM hostname for a verified domain (e.g. with default plunk and domain yourdomain.com, the MAIL FROM is plunk.yourdomain.com). Override when the default subdomain is already in use (e.g. by an R2/CDN custom domain), since the MAIL FROM hostname needs MX + TXT records that can't coexist with a CNAME.plunk

Storage (Minio)

The bundled Docker setup includes Minio with defaults that work out of the box. Only change these when connecting to an external S3-compatible bucket.

VariableRequiredDescriptionDefault
MINIO_ROOT_USERNoMinio root username (Docker Compose only).plunk
MINIO_ROOT_PASSWORDNoMinio root password (Docker Compose only).plunkminiopass
MINIO_API_PORTNoPort for the Minio API (Docker Compose only).9000
MINIO_CONSOLE_PORTNoPort for the Minio console UI (Docker Compose only).9001
S3_ENDPOINTNoS3 or Minio endpoint URL.http://minio:9000
S3_ACCESS_KEY_IDNoS3 or Minio access key.
S3_ACCESS_KEY_SECRETNoS3 or Minio secret key.
S3_BUCKETNoBucket name for file uploads.uploads
S3_PUBLIC_URLNoPublicly accessible base URL for stored files.
S3_FORCE_PATH_STYLENoUse path-style URLs instead of virtual-hosted. Required for Minio.true

Attachments

Plunk supports attachments on transactional emails. AWS SES caps total message size at 40 MB; the defaults below leave headroom but can be tuned for your use case.

VariableRequiredDescriptionDefault
MAX_ATTACHMENT_SIZE_MBNoMaximum total attachment size in megabytes per email. Hard upper bound enforced by AWS SES is 40 MB.10
MAX_ATTACHMENTS_COUNTNoMaximum number of attachments per email.10

SMTP Server

The optional SMTP relay lets you send emails through Plunk via the SMTP protocol.

VariableRequiredDescriptionDefault
SMTP_DOMAINNoSMTP relay domain. Required when using Traefik's acme.json with multiple certificates so the correct cert can be selected.localhost
SMTP_ENABLEDNoExplicitly enable SMTP features in the UI. Automatically enabled when SMTP_DOMAIN is set to a non-localhost value in production.false
PORT_SECURENoSMTPS port (implicit TLS).465
PORT_SUBMISSIONNoSMTP submission port (STARTTLS).587
MAX_RECIPIENTSNoMaximum number of recipients per email.5

OAuth

Enables social login. Register an OAuth app with each provider and add the credentials here.

VariableRequiredDescription
GITHUB_OAUTH_CLIENTNoGitHub OAuth app client ID.
GITHUB_OAUTH_SECRETNoGitHub OAuth app client secret.
GOOGLE_OAUTH_CLIENTNoGoogle OAuth app client ID.
GOOGLE_OAUTH_SECRETNoGoogle OAuth app client secret.

Stripe

Required if you want to enable billing features. All Stripe variables must be set together for billing to activate.

| Variable | Required | Description | | -------------------------- | -------- | --------------------------------------------------- | ------------------ | | STRIPE_SK | No | Stripe secret key. | | STRIPE_WEBHOOK_SECRET | No | Stripe webhook signing secret for verifying events. | | STRIPE_PRICE_ONBOARDING | No | Stripe price ID for the one-time onboarding fee. | | STRIPE_PRICE_EMAIL_USAGE | No | Stripe price ID for metered pay-per-email usage. | | STRIPE_METER_EVENT_NAME | No | Stripe meter event name. | emails (default) |

Platform Emails

When configured, Plunk will send email notifications to users for critical events (e.g. project disabled, billing limits reached). Without these, only ntfy notifications are sent.

VariableRequiredDescriptionExample
PLUNK_API_KEYNoAPI key for a Plunk instance to send transactional emails.pk_...
PLUNK_FROM_ADDRESSNoFrom address used for platform notification emails.noreply@yourdomain.com

Notifications (ntfy)

Plunk bundles a self-hosted ntfy server for internal system notifications.

VariableRequiredDescriptionDefault
NTFY_PORTNoPort for the ntfy web UI (Docker Compose only).8080
NTFY_URLNontfy topic URL. Change this to use an external ntfy.sh server or your own instance.http://ntfy/plunk-notifications

User Management

VariableRequiredDescriptionDefault
DISABLE_SIGNUPSNoWhen true, the signup endpoint rejects new registrations. Useful for private instances.false
VERIFY_EMAIL_ON_SIGNUPNoWhen true, validates emails on signup — checks for disposable domains, plus-addressing, domain existence, and MX records.false

Security

VariableRequiredDescriptionDefault
AUTO_PROJECT_DISABLENoWhen true, projects are automatically suspended when bounce or complaint rate thresholds are exceeded. Set to false to manage project status manually.true
EMAIL_RATE_LIMIT_PER_SECONDNoOverride the email sending rate limit. If not set, Plunk automatically fetches the quota from your AWS SES account.
EMAIL_WORKER_CONCURRENCYNoNumber of emails the worker processes in parallel. When unset, derived from the effective rate limit so a higher SES quota scales throughput automatically.
EMAIL_WORKER_MAX_CONCURRENCYNoUpper bound applied to the auto-derived worker concurrency. Raise this only after sizing the Prisma connection pool accordingly.50

Advanced

Variables for unusual deployments. The defaults work for the standard Docker Compose setup — only change these if you know you need to.

VariableRequiredDescriptionDefault
NGINX_PORTNoHost port the bundled Nginx reverse proxy binds to. Override when port 80/443 is already in use on the host (e.g. running behind another reverse proxy that forwards to a different port).80

Phishing Detection

Plunk can use AI to detect and block phishing emails before they're sent. Requires an OpenRouter API key.

VariableRequiredDescriptionDefault
OPENROUTER_API_KEYNoOpenRouter API key. When set, enables AI-powered phishing detection.
OPENROUTER_MODELNoLLM model to use for content analysis. See OpenRouter models.anthropic/claude-3-haiku
PHISHING_DETECTION_SAMPLE_RATENoPercentage of emails to check (0.0-1.0). For example, 0.1 means 10% of emails are analyzed.0.1 (10%)
PHISHING_CONFIDENCE_THRESHOLDNoMinimum confidence percentage (0-100) required to auto-disable a project from a single detection.95
PHISHING_CUMULATIVE_THRESHOLDNoNumber of phishing detections within the time window required to auto-disable a project.3
PHISHING_CUMULATIVE_WINDOW_MSNoTime window in milliseconds for cumulative phishing tracking.3600000 (1 hour)

How it works:

  • A random sample of emails (controlled by PHISHING_DETECTION_SAMPLE_RATE) are analyzed by the LLM for phishing content.
  • Projects are automatically disabled if either:
    1. A single email is detected with confidence ≥ PHISHING_CONFIDENCE_THRESHOLD, or
    2. PHISHING_CUMULATIVE_THRESHOLD or more emails are flagged within the PHISHING_CUMULATIVE_WINDOW_MS time window.
  • Detection history is stored in Redis and shared across all worker instances.