Configuration
Use the source .env.example for the complete comments and defaults. This page identifies the major boundaries and values required by each deployment shape.
Core application
| Variable | Required | Purpose |
|---|---|---|
NUXT_DATABASE_URL | Yes | Postgres owner URL. The app creates and migrates its own app schema here at boot |
NUXT_PUBLIC_APP_URL | Yes | Public origin used to build connector URLs |
NUXT_ALLOW_PRIVATE_TARGETS | No | Permit user-supplied private targets in trusted single-tenant installs. Defaults to off |
NUXT_SIGNUP | No | open or invite-only. Defaults to invite-only. See Who can sign up |
NUXT_SIGNUP_CODE | No | Invite-only mode: a shared code that lets its holder create their own organization |
NUXT_EMAIL_VERIFICATION | No | auto, required, or off. Defaults to auto. See Email verification |
POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB | Local compose | Values for the bundled Postgres container |
The app schema holds users, sessions, organizations, connections, invitations, connector-token hashes, and two-factor credentials. Connection credentials in it are not encrypted, so treat this database and its backups as holding every connected account.
Everything in this section is optional. Without a default Evolution server, users can still create WhatsApp connections by supplying their own server URL and key.
| Variable | Required when enabled | Purpose |
|---|---|---|
EVOLUTION_API_KEY | For bundled Evolution | Global Evolution administrator key |
NUXT_EVOLUTION_URL | For a default server | Evolution origin reached by web |
NUXT_EVOLUTION_ADMIN_KEY | For a default server | Must match EVOLUTION_API_KEY |
NUXT_EVOLUTION_DATABASE_URL | For reads and search | The Evolution Postgres. The owner URL works; a SELECT-only role is optional hardening |
WEBHOOK_URL | Local compose | Compose fallback webhook URL |
NUXT_WEBHOOK_URL | Yes for fast Evolution alerts | Per-connection webhook registered by web |
NUXT_WEBHOOK_SECRET | Strongly recommended | Shared x-webhook-secret value, also used by Telegram webhooks |
Set Evolution DATABASE_SAVE_DATA_HISTORIC=true before pairing if full history matters.
Telegram
| Variable | Required when enabled | Purpose |
|---|---|---|
TELEGRAM_API_ID, TELEGRAM_API_HASH | Both or neither | Credentials from my.telegram.org. With neither, the bridge starts and reports Telegram as unconfigured |
TELEGRAM_BRIDGE_ADMIN_KEY | Yes | Creates and deletes bridge sessions |
TELEGRAM_SESSION_ENCRYPTION_KEY | Yes | Seals stored account sessions |
TELEGRAM_BRIDGE_DATABASE_URL | Yes | Same Postgres as Evolution; the bridge keeps to its telegram schema |
TELEGRAM_READER_ROLE | No | A LOGIN-only role the bridge grants column-level SELECT to at every start |
NUXT_TELEGRAM_URL | For a default bridge | Bridge origin reached by web |
NUXT_TELEGRAM_ADMIN_KEY | For a default bridge | Matches the bridge administrator key |
NUXT_TELEGRAM_DATABASE_URL | For reads and search | Read access to the telegram schema |
NUXT_TELEGRAM_WEBHOOK_URL | Local development | Bridge-to-web callback; production derives it from the app URL |
TELEGRAM_TEST_SERVERS | No | Use Telegram's separate test environment |
Backfill is tuned by TELEGRAM_BACKFILL_MAX_PER_CHAT, TELEGRAM_BACKFILL_DAYS, TELEGRAM_BACKFILL_BROADCAST, and TELEGRAM_BACKFILL_PAGE_DELAY_MS.
Alerts and mail
The web server sends connection alerts, invitation emails, and verification codes over SMTP. Configure NUXT_SMTP_HOST, NUXT_SMTP_PORT, NUXT_SMTP_USERNAME, NUXT_SMTP_PASSWORD, NUXT_SMTP_TLS, NUXT_MAIL_FROM, and NUXT_MAIL_FROM_NAME.
NUXT_SMTP_TLS=false uses STARTTLS on port 587; set it to true for implicit TLS on 465. With NUXT_SMTP_HOST empty, alerts are computed and stay queued, and invitation links can still be copied by hand. NUXT_MAIL_FROM must be an address the provider accepts.
Who can sign up
Each self-signup creates a new organization, and its administrator can start connections on your Evolution server and Telegram bridge. So by default nobody can sign up without an invitation:
NUXT_SIGNUP | NUXT_SIGNUP_CODE | Who can sign up without an invitation |
|---|---|---|
Unset or invite-only | Unset | Only the first account on an empty database, which becomes the administrator |
Unset or invite-only | Set | Anyone who enters the code, the first account included |
open | Ignored | Anyone who finds the URL |
Invitation links work in every mode, and neither variable is required: a new install with both unset lets you sign up first, then you invite everyone else from the Team page. An unrecognized NUXT_SIGNUP value is read as invite-only, so a typo cannot open sign-up.
Until that first signup, a fresh install on a public address belongs to whoever opens it first. If that window matters, set NUXT_SIGNUP_CODE before starting the stack (openssl rand -base64 24) and give the code only to people who should get their own organization. Wrong codes are throttled per client address.
With NUXT_SIGNUP=open and NUXT_ALLOW_PRIVATE_TARGETS=true, any stranger who signs up can paste a database or Evolution address such as postgres://…@192.168.1.20:5432/…, and the server connects to it for them. Keep private targets for deployments where everyone with an account is trusted, and keep sign-up closed there.
Email verification
Without verification, anyone can register someone@yourcompany.com before its owner does, and the owner can then neither sign up nor accept an invitation sent to that address. With it, signing up (with or without an invitation) and changing an account's email both send a six-digit code and a link, and nothing is created or changed until one comes back. An unconfirmed signup holds no claim on the address and expires after 30 minutes.
NUXT_EMAIL_VERIFICATION | Behavior |
|---|---|
Unset or auto | On when NUXT_SMTP_HOST is set, off otherwise |
required | Always on. Without SMTP, signups and email changes are refused |
off | Never. The password alone proves an email change |
Any other value is read as required. The link is built from NUXT_PUBLIC_APP_URL only, never from the request, so a forged Host header cannot redirect it; without that URL the email carries only the code. A link only proves the address: it signs in only the browser that started the signup. Existing accounts are not asked to verify.
Docker Compose
The Docker Compose deployment reads a single .env created from .env.selfhost.example. It sets WEB_PORT for the published web port, the same NUXT_* and connector variables described above, and every secret that must be generated before first start. Sign-up settings use the short names SIGNUP, SIGNUP_CODE, and EMAIL_VERIFICATION. The single container reads the same names with --env-file, and generates any blank secret on first boot. Unlike local development, the web app runs in a container, so NUXT_DATABASE_URL points at the bundled Postgres service rather than localhost.
Production settings
- Do not ship
.env; use platform variables and secret references. - Set
NUXT_WEBHOOK_SECRET. - Keep
NUXT_ALLOW_PRIVATE_TARGETSunset for shared deployments. - Leave sign-up invite-only unless strangers should be able to create organizations.
- Set
NUXT_PUBLIC_APP_URLto the exact address people open; email verification links and passkeys depend on it. - Keep the web service at one replica so the five-minute alert sweep runs once.
- Keep Evolution global keys, bridge keys, and database URLs out of client code and logs.
- Back up Postgres, and restrict access to those backups.
- Preserve
TELEGRAM_SESSION_ENCRYPTION_KEYoutside the deployment platform.
NUXT_EVOLUTION_ADMIN_KEY can create, inspect, and delete every WhatsApp instance on the default Evolution server. Treat it as one of the highest-impact credentials in the deployment.