Skip to content

Configuration

AlphOne is configured through environment variables. The binary also loads a .env file from its working directory at startup, so the same variables can live in a file next to it. Real environment variables take precedence over .env entries, which is how the container setup in Install works. The repository ships .env.example as a commented template.

Database migrations for the core, the auth layer, and every plugin run automatically at startup, so pointing a new version at an existing database is all an upgrade takes.

VariableRequiredDefaultPurpose
ALPHONE_DATABASE_URLyesnonePostgreSQL connection string, e.g. postgres://user:pass@host:5432/alphone?sslmode=disable.
ALPHONE_ADDRnolocalhost:8080Listen address. The container image sets 0.0.0.0:8080.
ALPHONE_WEB_DIRnounsetDirectory holding the built frontend, served for all non-API paths. The container image sets /web. Unset, only the API is served, which suits development behind Vite.
ALPHONE_TRUSTED_PROXIESnounsetComma-separated CIDR ranges allowed to set X-Forwarded-For, e.g. 172.18.0.0/16. Only addresses in these ranges are trusted when the login rate limiter resolves the client IP. Unset, the direct peer address is used. Set this whenever AlphOne runs behind a reverse proxy, or all visitors share one rate-limit bucket. Each entry must be CIDR notation. A bare IP is rejected at startup.
ALPHONE_DEV_GRAPHIQLnounsetAny non-empty value serves the interactive GraphiQL page on GET /api/graphql. Development only.

All optional. Without them the plugin runs inert: screens exist, but no webhook verifies and no message sends. Values come from your Meta app, see Meta setup.

VariablePurpose
ALPHONE_WHATSAPP_VERIFY_TOKENThe token Meta echoes during webhook verification. You invent it and paste the same value on both sides.
ALPHONE_WHATSAPP_APP_SECRETThe app secret, used to check the signature Meta sends with every webhook delivery.
ALPHONE_WHATSAPP_ACCESS_TOKENBearer token for sending messages through the Graph API.
ALPHONE_WHATSAPP_PHONE_NUMBER_IDThe phone number ID (not the phone number itself) messages are sent from.
ALPHONE_WHATSAPP_GRAPH_URLGraph API base URL. Defaults to https://graph.facebook.com/v23.0. Only override it for testing.
ALPHONE_WHATSAPP_MEDIA_MAX_BYTESLargest inbound attachment stored, in bytes. Defaults to 26214400 (25 MiB), enough for every WhatsApp media type except large documents. Attachments over the cap appear in the thread as a named chip without a download.
  • Sessions last 30 days, are stored server-side, and expired ones are garbage-collected hourly. Disabling a user revokes all of their sessions immediately.
  • Media attachments (photos, voice notes, videos, documents, stickers) are downloaded from Meta shortly after each message arrives and stored in the PostgreSQL database, so a database backup contains the complete conversation history including attachments. Expect backup size to grow with media traffic.
  • Delivery status for outbound replies (sent, delivered, read) is updated live from Meta’s status webhooks and shown as ticks on each message. Failed deliveries, such as replying outside WhatsApp’s 24-hour customer service window, are surfaced on the message with an explanation. Statuses arrive through the same messages webhook field, so no extra Meta configuration is needed.
  • Login rate limiting allows 10 failed attempts per client address per minute. Successful logins never consume the budget. Over the limit login answers with an error whose extensions.code is RATE_LIMITED and whose extensions.retryAfter is the wait in seconds, see errors. The limit is per address and there is no per-account lockout, so an attacker spreading guesses across many addresses is bounded only by password strength and the argon2id hashing cost. Passwords must be at least 12 characters. Until multi-factor authentication ships, a long unique password is the account-side defense.
  • The session cookie is HttpOnly, Secure, SameSite=Lax, with the __Host- prefix. This is why HTTPS is mandatory in production.