Skip to content

Environment Variables ​

All variables live in a single .env file at the repo root. The VITE_* ones are inlined into the frontend bundle at build time; the rest are read at runtime by the API and worker.

Frontend (VITE_*) ​

Read by Vite at build time and inlined into the JavaScript bundle. They are publicly visible.

VariableRequiredDefaultDescription
VITE_APP_VERSIONNo0.0.0Version string displayed in the UI

The client reaches the API over a relative /api path (same-origin, reverse-proxied), so no API-URL variable is needed.

Backend ​

Read at runtime by both services/api and services/worker. Never exposed to the browser.

Database ​

VariableRequiredDefaultDescription
DATABASE_URLYes—PostgreSQL connection string
POSTGRES_USERYesttPostgreSQL username (Docker Compose)
POSTGRES_PASSWORDYes—PostgreSQL password — change from default in production
POSTGRES_DBYesttPostgreSQL database name

Redis ​

VariableRequiredDefaultDescription
REDIS_URLYesredis://localhost:6379Redis connection string for BullMQ

Authentication ​

VariableRequiredDefaultDescription
BETTER_AUTH_SECRETYes—Session signing secret. Generate with openssl rand -base64 32. Minimum 32 characters.
BETTER_AUTH_URLYeshttp://localhost:3000Public URL of the API, used for OAuth redirect URIs

Google OAuth ​

VariableRequiredDescription
GOOGLE_CLIENT_IDFor loginOAuth client ID from Google Cloud Console
GOOGLE_CLIENT_SECRETFor loginOAuth client secret
VariableRequiredDefaultDescription
CORS_ORIGINSYes—Comma-separated list of allowed frontend origins. Include capacitor://localhost (iOS) and https://localhost (Android) for the native mobile app, which calls the API from its own origin
GOOGLE_IOS_CLIENT_IDNo—OAuth client ID of the iOS app, accepted as audience of Google ID tokens the native app signs in with. Unset: no Google button on iOS

Native push (mobile app) ​

Each channel is optional and independent; an unset channel delivers nothing to devices of that platform.

VariableRequiredDefaultDescription
FCM_SERVICE_ACCOUNTNo—Android: base64 of the Firebase service-account JSON (FCM HTTP v1)
APNS_KEY_IDNo—iOS: the APNs key ID from the Apple developer portal
APNS_TEAM_IDNo—iOS: the Apple team ID
APNS_KEY_P8No—iOS: base64 of the AuthKey_<id>.p8 file
APNS_BUNDLE_IDNoovh.tim.appiOS: the app's bundle ID (apns-topic)
APNS_ENVIRONMENTNoproductionsandbox for Xcode debug builds, production for TestFlight / App Store
APP_URLNohttp://localhost:5173Frontend URL used in transactional email links

File Storage ​

VariableRequiredDefaultDescription
RUSTFS_ENDPOINTYeshttp://localhost:9000S3-compatible storage endpoint
RUSTFS_BUCKETYestt-invoicesBucket for invoice files
RUSTFS_ACCESS_KEYYesminioadminStorage access key
RUSTFS_SECRET_KEYYesminioadminStorage secret key

AI / OCR ​

VariableRequiredDescription
OPENROUTER_KEYWorkerOpenRouter API key for AI invoice extraction. Required by the worker (it refuses to boot without it).
EXTRACTION_MODELNoOpenRouter model slug for invoice extraction. Default: google/gemini-2.5-flash.
EXTRACTION_FALLBACK_MODELNoFallback model used when the primary model's providers are unavailable. Default: openai/gpt-5-mini.

Secret encryption ​

VariableRequiredDescription
INTEGRATION_ENCRYPTION_KEYFor email sync / integrationsAES-256-GCM key (base64, 32 bytes) encrypting accounting-integration credentials and IMAP email-sync passwords at rest. Must match between API and worker. Generate with openssl rand -base64 32.

Transactional email (all optional) ​

Leave SMTP_HOST empty to disable email — user creation still works, mail just isn't sent.

VariableDefaultDescription
SMTP_HOST—SMTP server host
SMTP_PORT587SMTP server port
SMTP_USER—SMTP username
SMTP_PASS—SMTP password
SMTP_FROMnoreply@tt-tracker.appFrom address for outgoing mail

Web push notifications (all optional) ​

Leave the VAPID keys empty to disable push delivery — the in-app notification center keeps working. Generate a key pair with npx web-push generate-vapid-keys.

VariableDefaultDescription
VAPID_PUBLIC_KEY—VAPID public key, served to browsers subscribing to push
VAPID_PRIVATE_KEY—VAPID private key used to sign push deliveries
VAPID_SUBJECTmailto:noreply@tt-tracker.appmailto: or https: contact for the push service operator

API Server ​

VariableRequiredDefaultDescription
PORTNo3000Port the NestJS API listens on

Observability (all optional) ​

VariableDescription
SENTRY_DSNSentry DSN for API + worker error tracking
SENTRY_DSN_FRONTENDSentry DSN for frontend error tracking (served to the browser via /config)
UMAMI_WEBSITE_IDUmami analytics website id (served to the browser via /config)

Database backup variables (BACKUP_*, BACKUP2_*) are documented in ops/backup/README.md and the Docker Compose reference.

TT Time Tracker — Internal Documentation