Montara Pass
Getting started

Configuration

Every setting of the API, the web app and the extension.

API

Each setting of apps/server is an environment variable, or the command-line flag of the same name in kebab-case (go run ./cmd/api -h).

VariableDefaultPurpose
ENVproductiondevelopment, staging or production. Only development relaxes the session cookie and exempts loopback from the rate limit.
DEBUGfalseLogs every auth query with its values. Refused when ENV=production.
PORT8080Port the API listens on.
APP_NAMEmontara-passName used in auth emails.
APP_SECRETnoneRequired, at least 32 characters. Signs sessions and tokens.
DB_DSNnoneRequired. PostgreSQL 18 connection string.
DB_MAX_OPEN_CONNS25Connection pool size.
DB_MAX_IDLE_CONNS25Idle connections kept.
DB_MAX_IDLE_TIME15mHow long an idle connection is kept.
MIGRATE_ON_BOOTfalseApply the embedded migrations before serving.
SEED_ON_BOOTfalseRun the idempotent seeders before serving. Needs SUPER_USER.
SUPER_USERnoneemail:password of the super user to seed.
CORS_ALLOWED_ORIGINSnoneComma-separated browser origins. Empty means same-origin only, which is enough when the API serves the web app.
RATE_LIMIT_EXEMPT_IPSnoneComma-separated client IPs the rate limiter and the IP block skip. An IP that fails 20 times in a row (a wrong password or code, or a rate limit hit), each within 15 minutes of the last, is shut out of the API for an hour.
TRUSTED_PROXIESnoneIPs or CIDRs trusted to supply X-Forwarded-For. Set it behind a reverse proxy, or the rate limit and the IP block count the proxy instead of the visitor, and one visitor's failures block everyone.
AUTH_BASE_URLhttp://localhost:$PORTPublic URL of the API, used in email links and the Google callback.
FROM_ADDRESSnoneSender of auth emails. Must be a domain verified in Resend. Required in the Cloud Edition; the Community Edition may leave it and RESEND_API_KEY empty, which turns off password reset and magic-link sign-in (change SUPER_USER to reset the password).
RESEND_API_KEYnoneResend API key. Required with FROM_ADDRESS.
GOOGLE_CLIENT_IDnoneGoogle OAuth client. Empty disables Google sign-in.
GOOGLE_CLIENT_SECRETnoneGoogle OAuth secret.
LEMONSQUEEZY_API_KEYnoneCloud Edition: the Lemon Squeezy API key that takes payments for plans (a test-mode key for the store's test mode). Empty leaves checkout off. The API reads the store when it starts and refuses to start if it cannot.
LEMONSQUEEZY_STORE_IDnoneThe numeric id of the store that sells the plans. Its catalog is the plans: one per variant, at the variant's price, synced when the API starts, every 15 minutes, and when a super user calls POST /api/v1/plans/sync. Each new account is saved as one of its customers. Required with LEMONSQUEEZY_API_KEY.
LEMONSQUEEZY_WEBHOOK_SECRETnoneThe signing secret of the store's webhook, pointed at $AUTH_BASE_URL/api/v1/billing/lemonsqueezy/webhook with order_created, order_refunded, subscription_created and subscription_updated. Required with LEMONSQUEEZY_API_KEY.
REQUIRE_PAID_SHARINGfalseCloud Edition: sharing an item needs a paid plan. Needs LEMONSQUEEZY_API_KEY; the API refuses to start without it, so a missing key never makes sharing free unnoticed.
REDIS_URLnoneRedis for what replicas must share: rate limit counts and idempotent answers, e.g. redis://redis:6379/0 (rediss:// for TLS). Empty keeps them in the process's memory, which is enough for one instance. The API refuses to start when it is set and Redis does not answer.
SENTRY_DSNnoneSentry DSN for error reports.

The Google redirect URI to register is $AUTH_BASE_URL/api/v1/auth/oauth2/callback/google.

Browser extensions are a special case of CORS: the API accepts requests whose origin starts with chrome-extension:// or moz-extension:// without listing them.

Web app

apps/app reads its variables at build time: Vite inlines them into the bundle.

VariableDefaultPurpose
VITE_API_URLthe page's own originOrigin of the API. Leave it empty unless the app is hosted somewhere else than the API.
VITE_APP_NAMEMontara PassName shown in the UI.
VITE_API_PROXY_TARGEThttp://localhost:8080Development only: where the Vite dev server proxies /api.

Browser extension

apps/extension reads its defaults at build time from apps/extension/.env. Without that file a development build (watch) uses the local servers and a production build uses https://app.montarapass.com for both.

VariableDevelopmentPurpose
VITE_DEFAULT_API_URLhttp://localhost:8080Origin of the API.
VITE_DEFAULT_APP_URLhttp://localhost:5173The web app that "Open web app" links to.

A production build's Settings offer one Server URL behind a Self-hosted switch; a development build's show both URLs.

On this page