Files
2026-08-17 16:35:14 -04:00

197 lines
8.3 KiB
Bash

# =============================================================================
# Beenvoice web workspace — environment template
# =============================================================================
#
# Quick start (local dev):
# cp .env.example .env.local
# docker compose -f docker-compose.dev.yml up -d # Postgres + Garage
# bun run db:push # or: bun run db:migrate
# bun run dev
# Garage S3 API: http://localhost:3900
#
# Quick start (Docker app + Postgres):
# cp .env.example .env
# # edit AUTH_SECRET + public URLs below
# ./scripts/docker-deploy.sh
#
# -----------------------------------------------------------------------------
# Build-time vs runtime (Docker)
# -----------------------------------------------------------------------------
#
# Baked into the image at `docker compose build` (rebuild after changes):
# NEXT_PUBLIC_APP_URL
# NEXT_PUBLIC_* branding / theme defaults
# NEXT_PUBLIC_AUTHENTIK_ENABLED
# NEXT_PUBLIC_UMAMI_*
#
# Read from .env when the container starts (restart app after changes):
# AUTH_SECRET, BETTER_AUTH_URL, DATABASE_URL (compose overrides host),
# RESEND_*, DISABLE_SIGNUPS, AUTHENTIK_* secrets, CRON_SECRET
#
# `NEXT_PUBLIC_APP_URL` should still match your public browser URL for SSR,
# emails, and MCP links. In the browser, sign-in uses the current page origin
# automatically so dev works when Next picks another port (e.g. 3002).
#
# Updating production: git pull && ./scripts/docker-deploy.sh
# (or: docker compose up -d --build). Plain `docker compose up -d` does NOT rebuild.
# Migrations run on every app start (idempotent — only pending SQL is applied).
# =============================================================================
# Core — required
# =============================================================================
# PostgreSQL connection string.
# Local dev (docker-compose.dev.yml): host is localhost
DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres
# Session signing secret. Required in production.
# Generate: openssl rand -base64 32
AUTH_SECRET=change-me-generate-a-real-secret
# Public URL users open in the browser (scheme + host + port if non-standard).
# Must match how you access the app for cookies, OAuth callbacks, and email links.
BETTER_AUTH_URL=http://localhost:3000
# Same as BETTER_AUTH_URL in most setups. Embedded in the client bundle at build.
NEXT_PUBLIC_APP_URL=http://localhost:3000
# =============================================================================
# Local development
# =============================================================================
NODE_ENV=development
# Set true when connecting to local Postgres without SSL (default for compose).
DB_DISABLE_SSL=true
# Dev-only: host ports for `docker compose -f docker-compose.dev.yml`.
POSTGRES_PORT=5432
GARAGE_API_PORT=3900
# Coolify Compose container listener ports. APP_PORT is Coolify-only;
# POSTGRES_PORT and GARAGE_API_PORT are reused from above. The regular/dev
# compose files keep the database and Garage container ports at 5432/3900 and
# use those variables only for host-side mappings.
APP_PORT=3000
GARAGE_RPC_PORT=3901
GARAGE_WEB_PORT=3902
GARAGE_ADMIN_PORT=3903
# Garage requires a 64-character hexadecimal RPC secret. Generate with:
# openssl rand -hex 32
# GARAGE_RPC_SECRET=
# GARAGE_ADMIN_TOKEN=
# GARAGE_METRICS_TOKEN=
# Optional: if Next dev picks another port, you do not need to change URLs for
# sign-in — the auth client uses window.location.origin in the browser.
# =============================================================================
# Docker Compose (app + database)
# =============================================================================
# Host port mapped to container :3000 (WEB_PORT, then PORT, then 3000).
WEB_PORT=3000
# App image tag for docker-compose.yml (optional). docker-deploy.sh sets
# beenvoice:<git-sha> automatically; default without it is beenvoice:local.
# BEENVOICE_IMAGE=beenvoice:local
# Postgres credentials for docker-compose.yml `db` service.
# DATABASE_URL inside the app container is set by compose (host `db`, not localhost).
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=postgres
# =============================================================================
# White-label defaults (optional)
# =============================================================================
# Baked in at Docker build. After first deploy, admins can override many of
# Optional white-label defaults (build-time). Users choose light/dark in Settings.
NEXT_PUBLIC_BRAND_NAME=beenvoice
NEXT_PUBLIC_BRAND_TAGLINE=Simple and efficient invoicing for freelancers and small businesses
NEXT_PUBLIC_BRAND_LOGO_TEXT=beenvoice
NEXT_PUBLIC_BRAND_ICON=$
# =============================================================================
# Email — Mailpit locally, Resend in production
# =============================================================================
# Start local dependencies, then inspect messages at http://localhost:8028.
# Production must use EMAIL_PROVIDER=resend (Mailpit is rejected in production).
EMAIL_PROVIDER=mailpit
EMAIL_FROM=beenvoice <noreply@beenvoice.test>
SMTP_HOST=127.0.0.1
SMTP_PORT=1028
SMTP_SECURE=false
RESEND_API_KEY=
RESEND_DOMAIN=
RESEND_FROM=
# =============================================================================
# Analytics — Umami (optional)
# =============================================================================
# Leave website ID blank to disable.
NEXT_PUBLIC_UMAMI_WEBSITE_ID=
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.umami.is/script.js
# =============================================================================
# Access control (optional)
# =============================================================================
# Block new email/password registrations (default: true / signups off).
# Set DISABLE_SIGNUPS=false to allow new email/password signups.
# DISABLE_SIGNUPS=false
# Bearer token for POST /api/cron/generate-recurring (recurring invoice cron).
# CRON_SECRET=
# =============================================================================
# Receipt storage — S3-compatible (optional)
# =============================================================================
# When S3_BUCKET + S3_ACCESS_KEY + S3_SECRET_KEY are unset, receipts land in
# .data/receipts/ (dev-friendly). Works with AWS S3, Garage, Cloudflare R2, etc.
#
# S3_ENDPOINT — who can reach Garage?
# • Host dev (bun dev + docker-compose.dev.yml Garage on the host): localhost:3900
# • App in Docker (docker-compose.yml): http://garage:3900 (Compose service name)
# • Coolify — see docs/COOLIFY.md. Summary:
# - Best: one Compose resource with docker-compose.coolify.yml (app+db+garage).
# - Application + separate Garage: ENOTFOUND garage → set S3_ENDPOINT to
# SERVICE_URL_GARAGE (public domain) OR
# http://garage-<resource-uuid>:<GARAGE_API_PORT>
# with Connect to Predefined Network on both resources. Never bare "garage".
# - NEVER use localhost in production — inside the app container that is the app, not Garage.
#
# Local dev with docker-compose.dev.yml Garage (host `bun dev`):
S3_ENDPOINT=http://localhost:3900
S3_BUCKET=beenvoice-receipts
S3_ACCESS_KEY=GK3515373e4c851ebaad366558
S3_SECRET_KEY=7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34
S3_REGION=garage
# S3_FORCE_PATH_STYLE=true # default on when S3_ENDPOINT is set; required for Garage/HTTPS proxy
#
# docker-compose.yml uses http://garage:3900 internally. The Coolify compose
# derives the internal URL from GARAGE_API_PORT. Credentials must match Garage.
# =============================================================================
# SSO — Authentik OIDC (optional)
# =============================================================================
# Set NEXT_PUBLIC_AUTHENTIK_ENABLED=true and rebuild the image to show SSO on
# sign-in. Server secrets are runtime-only (no rebuild needed for secrets).
NEXT_PUBLIC_AUTHENTIK_ENABLED=false
AUTHENTIK_ISSUER=
AUTHENTIK_CLIENT_ID=
AUTHENTIK_CLIENT_SECRET=
# Optional extra trusted origin for better-auth (defaults derived from issuer).
AUTHENTIK_ORIGIN=
# =============================================================================
# Advanced / CI (usually unset)
# =============================================================================
# Skip Zod env validation during `next build` (set automatically in Dockerfile).
# SKIP_ENV_VALIDATION=1