# ============================================================================ # SHARP-ER - root environment template # ---------------------------------------------------------------------------- # Copy once, then fill in: cp .env.example .env # Generate the CMS secrets: ./scripts/generate-secrets.sh --write .env # # WHO READS THIS FILE # * docker compose - every ${VARIABLE} in docker-compose.yml is read from # the .env file sitting next to it (this one). # * apps/web - NOT this file. In manual mode the web app reads # apps/web/.env (cp apps/web/.env.example apps/web/.env), # which is where PORT, HOST, SITE_URL, STRAPI_URL and # STRAPI_TOKEN belong. Under Docker the values below are # injected into the container instead. The defaults are # also the code defaults, so a plain `pnpm dev` works # with no .env at all. # * apps/cms - Strapi does NOT read this file. In manual mode it reads # apps/cms/.env (cp apps/cms/.env.example apps/cms/.env). # Under Docker the values below are injected into the # container instead, so apps/cms/.env is not used there. # # Never commit .env. Never paste a real secret back into this template. # ============================================================================ # --------------------------------------------------------------------------- # DATABASE # Manual mode: your local PostgreSQL 16 instance (scripts/setup-db.sh uses # these values). Docker mode: the postgres service is created with them. # --------------------------------------------------------------------------- DATABASE_NAME=sharper_cms DATABASE_USERNAME=postgres DATABASE_PASSWORD=postgres # Manual mode only - where the local server listens. Inside Docker the CMS # always reaches the database as postgres:5432 on the compose network. DATABASE_HOST=127.0.0.1 DATABASE_PORT=5432 # Docker mode only - host port the containerised database is published on. # 5433 by default so it cannot collide with a PostgreSQL you already run on # 5432. Connect with: psql -h 127.0.0.1 -p 5433 -U postgres sharper_cms POSTGRES_PUBLISHED_PORT=5433 # --------------------------------------------------------------------------- # CMS (Strapi 5) SECRETS # Required. Every value must be a fresh random string - generate them with # ./scripts/generate-secrets.sh --write .env # or by hand with `openssl rand -base64 32`. # APP_KEYS is a comma-separated list (at least two, so keys can be rotated). # Rotating APP_KEYS logs everyone out; rotating ENCRYPTION_KEY makes values # already encrypted in the database unreadable. # --------------------------------------------------------------------------- APP_KEYS= API_TOKEN_SALT= ADMIN_JWT_SECRET= JWT_SECRET= TRANSFER_TOKEN_SALT= ENCRYPTION_KEY= # --------------------------------------------------------------------------- # PORTS # Host ports the two applications are published on in Docker mode. The ports # they LISTEN on in manual mode live in each application's own .env # (apps/web/.env, apps/cms/.env), because both servers read a bare PORT. # --------------------------------------------------------------------------- # Docker mode - host port the web container is published on; inside the # container it always listens on 3000, so WEB_PORT=8080 means 8080:3000. # Manual mode has its own PORT in apps/web/.env - never put a bare PORT in # THIS file: both servers would read it and Strapi would land on the website's # port. `pnpm dev:web` uses 5173 either way. WEB_PORT=3000 # Strapi API + admin panel. CMS_PORT=1337 # Docker mode only - the absolute URL the admin panel and Strapi's generated # links use. Change it together with CMS_PORT, and set it to the public origin # in production (e.g. https://cms.sharper.ly). CMS_PUBLIC_URL=http://localhost:1337 # Optional comma-separated recipients for new partner draft notifications. # When empty, notifications go to all active Strapi Super Admin accounts. PARTNER_REVIEW_NOTIFICATION_EMAILS= # --------------------------------------------------------------------------- # WEB APP - Docker mode. In manual mode these live in apps/web/.env. # --------------------------------------------------------------------------- # Public origin of the site. Used for canonical URLs, hreflang alternates and # JSON-LD, so it must match how visitors actually reach the site. # Leave it unset in local development and the request's own host is used. SITE_URL=http://localhost:3000 # Where they fetch from inside Docker, where "cms" is the compose service name. # NOTE: this origin is also prefixed onto uploaded media URLs, which the # browser has to be able to resolve too - see "Images from the CMS" in the # Docker section of README.md. DOCKER_STRAPI_URL=http://cms:1337 # Optional Strapi API token. Only needed to read draft or otherwise protected # content; published content is public. Create it in the admin panel under # Settings -> API Tokens, then paste the value here (it is shown once). STRAPI_TOKEN= # Cloudflare Turnstile on the public forms. Both keys or neither: with either # one empty, the forms are not checked. See apps/web/.env.example. TURNSTILE_SITE_KEY= TURNSTILE_SECRET_KEY= # --------------------------------------------------------------------------- # CMS RUNTIME # --------------------------------------------------------------------------- # Browser origins allowed to call the API, comma separated. localhost:5173 and # 127.0.0.1:5173 are always allowed outside production and need not be listed. CORS_ORIGINS=http://localhost:3000 # Log verbosity: fatal | error | warn | info | http | debug | trace LOG_LEVEL=info