Amarnai
Self-Hosting

Configuration

Full environment variable reference for self-hosting Amarnai.

All configuration is done through environment variables in a single .env file at the monorepo root. For self-hosting, copy .env.selfhost.example as a starting point (.env.example is the local-development template and defaults to mock AI).

Postgres

VariableDefaultDescription
DATABASE_URLpostgresql://amarnai:amarnai@localhost:5432/amarnaiFull Postgres connection string
POSTGRES_USERamarnaiPostgres username
POSTGRES_PASSWORDamarnaiPostgres password
POSTGRES_DBamarnaiPostgres database name

Redis

VariableDefaultDescription
REDIS_URLredis://localhost:6379Redis connection string

Application

VariableDefaultDescription
API_PORT3001Port the API server listens on
WORKER_PORT3002Reserved port value for the worker process. The worker runs jobs and does not bind an HTTP server, so nothing needs to be exposed
INBOX_SYNC_INTERVAL_MS300000How often the worker polls each connected inbox, in milliseconds (fallback when push is not configured)
CORS_ORIGINhttp://localhost:3000Allowed CORS origin. Set to your web app domain in production

Auth

VariableRequiredDescription
AUTH_SECRETYesRandom secret for NextAuth. Generate with openssl rand -base64 32
AUTH_URLYesPublic URL of the web app (e.g. https://mail.yourdomain.com)
AUTH_GOOGLE_IDYesGoogle OAuth Client ID
AUTH_GOOGLE_SECRETYesGoogle OAuth Client Secret
INTERNAL_API_SECRETYesShared secret for server-action to API calls. Generate with openssl rand -hex 32
AUTH_JWT_SECRETYesSigns per-user access tokens for native clients (browser extension, mobile). Generate with openssl rand -hex 32

Gmail

VariableRequiredDescription
GMAIL_OAUTH_CALLBACK_URLYesRedirect URI registered in Google Cloud Console (e.g. https://mail.yourdomain.com/api/gmail/callback)
TOKEN_ENCRYPTION_KEYYes64-char hex string (32 bytes) for AES-256-GCM encryption of stored OAuth refresh tokens (Gmail + Outlook share it). No fallback; startup fails without it. openssl rand -hex 32

Gmail push (optional, real-time)

Enables real-time inbox sync via Google Cloud Pub/Sub instead of polling. Leave unset to rely on polling.

VariableRequiredDescription
GMAIL_PUBSUB_TOPICNoPub/Sub topic, format projects/<project-id>/topics/<topic-name>. When set, Gmail pushes on new mail
GMAIL_PUBSUB_WEBHOOK_SECRETIf topic setSecret included as ?token= on the push endpoint and verified on each request. openssl rand -hex 32
GMAIL_PUBSUB_SUBSCRIPTIONNoSubscription name that receives push notifications. Default amarnai-gmail-sub

Mail providers

VariableDefaultDescription
MAIL_PROVIDERSgmailProviders offered in the connect flow, comma-separated (e.g. gmail,outlook). Only gates onboarding; the adapter is chosen per connection

Outlook / Microsoft Graph (optional, beta, read-only)

Setting MS_GRAPH_CLIENT_ID and MS_GRAPH_CLIENT_SECRET together enables the Outlook provider. See Prerequisites for the Microsoft Entra app registration.

VariableRequiredDescription
MS_GRAPH_CLIENT_IDFor OutlookMicrosoft Entra confidential Web app client ID
MS_GRAPH_CLIENT_SECRETFor OutlookClient secret for the same app registration
MS_GRAPH_TENANTFor OutlookAuthority/tenant. Use the literal common for multitenant + personal accounts (not a GUID). Default common
MS_GRAPH_SUBSCRIPTION_SECRETFor pushclientState echoed on every Graph change-notification so the webhook can verify it. openssl rand -hex 32
MS_GRAPH_NOTIFICATION_URLFor pushPublic HTTPS URL Graph posts change notifications to (e.g. https://api.yourdomain.com/webhooks/outlook). Unset means polling-only
OUTLOOK_OAUTH_CALLBACK_URLFor OutlookRedirect URI registered for the app (e.g. https://mail.yourdomain.com/api/outlook/callback)

AI

Set AI_PROVIDER=frontier and EMBEDDING_PROVIDER=frontier for production. The default AI_PROVIDER=mock (with EMBEDDING_PROVIDER=mock) is for tests; ollama is for local development.

The recommended production configuration is Gemini through its OpenAI-compatible endpoint (cheap and free within Google's quota):

AI_PROVIDER=frontier
FRONTIER_LLM_PROVIDER=gemini
FRONTIER_LLM_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/
FRONTIER_LLM_MODEL=gemini-2.5-flash-lite
FRONTIER_LLM_API_KEY=<Google AI Studio key>

EMBEDDING_PROVIDER=frontier
FRONTIER_EMBEDDING_PROVIDER=gemini
FRONTIER_EMBEDDING_MODEL=gemini-embedding-001
FRONTIER_EMBEDDING_DIMENSIONS=768
FRONTIER_EMBEDDING_API_KEY=<Google AI Studio key>

OpenAI (or any OpenAI-compatible endpoint) is a supported alternative: set FRONTIER_LLM_PROVIDER=openai, FRONTIER_LLM_MODEL=gpt-4o-mini, and for embeddings FRONTIER_EMBEDDING_PROVIDER=openai, FRONTIER_EMBEDDING_MODEL=text-embedding-3-small.

VariableDefaultDescription
AI_PROVIDERmockfrontier for production, ollama for local dev, mock for tests
FRONTIER_LLM_PROVIDERopenaiLLM backend: gemini, openai, or any OpenAI-compatible provider
FRONTIER_LLM_API_KEYAPI key for the LLM provider
FRONTIER_LLM_MODELgpt-4o-miniModel name (production: gemini-2.5-flash-lite)
FRONTIER_LLM_BASE_URLBase URL for the provider. For Gemini: https://generativelanguage.googleapis.com/v1beta/openai/
ROUTING_LLM_MODELfalls back to LLM modelOptional cheaper model for routing decisions
DRAFT_LLM_MODELfalls back to LLM modelOptional model for draft generation
TAXONOMY_LLM_MODELfalls back to LLM modelOptional model for taxonomy generation. Keep on a capable tier (the cheapest tiers are the most throttled)
EMBEDDING_PROVIDERfrontierfrontier for production, ollama for local dev, mock for tests
FRONTIER_EMBEDDING_PROVIDERgeminiEmbedding backend: gemini or any OpenAI-compatible provider
FRONTIER_EMBEDDING_API_KEYAPI key for the embedding provider
FRONTIER_EMBEDDING_MODELgemini-embedding-001Embedding model name (e.g. text-embedding-3-small for OpenAI)
FRONTIER_EMBEDDING_BASE_URLOverride base URL for OpenAI-compatible embedding endpoints
FRONTIER_EMBEDDING_DIMENSIONS768Output vector size. Use the same model and dimensions everywhere you embed

Email

Amarnai sends verification and password-reset emails via Resend (recommended) or SMTP. If RESEND_API_KEY is set, the SMTP variables are ignored.

VariableDefaultDescription
EMAIL_FROMSender address for verification and reset emails
RESEND_API_KEYResend HTTP API key. When set, SMTP is ignored. Get one at resend.com
SMTP_HOST127.0.0.1SMTP server hostname (dev default points at Mailpit)
SMTP_PORT1025SMTP server port (production typically 587)
SMTP_USERSMTP username (required for production SMTP)
SMTP_PASSSMTP password (required for production SMTP)
SMTP_SECURESet true for port 465 (direct SSL). Leave unset for 587 (STARTTLS)

Web app and CSP (optional)

These NEXT_PUBLIC_* and CSP variables are read by the web app and site. All are optional and config-gated.

VariableDescription
NEXT_PUBLIC_ANALYTICS_URLURL of a private analytics script server. Blank disables analytics
NEXT_PUBLIC_PLAY_STORE_URLPlay Store URL. When set, an Android-only download banner shows
NEXT_PUBLIC_EXTENSION_STORE_URLChrome Web Store listing URL for the extension nudge
NEXT_PUBLIC_EXTENSION_STORE_URL_FIREFOXAMO listing URL for the extension nudge on Firefox
CSP_REPORT_ONLYSet true to send the CSP as report-only instead of enforcing it
CSP_REPORT_URIOptional endpoint that receives CSP violation reports

Stripe (optional)

Stripe is only needed if you are running the hosted SaaS offering with paid plans. Self-hosters can leave these unset.

VariableDescription
STRIPE_SECRET_KEYStripe secret key
STRIPE_WEBHOOK_SECRETStripe webhook signing secret
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYStripe publishable key
STRIPE_PRICE_PRO_MONTHLYStripe Price ID for the Pro monthly plan
STRIPE_PRICE_PRO_ANNUALStripe Price ID for the Pro annual plan
STRIPE_PRICE_BUSINESS_MONTHLYStripe Price ID for Business monthly
STRIPE_PRICE_BUSINESS_ANNUALStripe Price ID for Business annual

On this page