Files
sharper.ly/.env.example
T
IllusionandClaude Opus 5.5 709a978da5 feat(web): add Cloudflare Turnstile to the public forms
Render the widget on the contact, event registration and both application
forms, and verify the token with Siteverify in each action before anything
is written to the CMS. Verification fails closed. The check is off unless
both TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY are set.

Allow challenges.cloudflare.com in script-src and frame-src.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-24 12:05:51 +02:00

128 lines
5.7 KiB
Bash

# ============================================================================
# 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