# ============================================================================ # 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 - the React Router server reads STRAPI_URL / STRAPI_TOKEN # / SITE_URL from its process environment. In manual mode # nothing loads this file for you, so export it first: # set -a; . ./.env; set +a # The defaults below are also the code defaults, so a # plain `pnpm dev` works without exporting anything. # * 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, and the # ports they listen on in manual mode. # --------------------------------------------------------------------------- # React Router server (production build / Docker). `pnpm dev:web` uses 5173. # Manual mode: `pnpm --filter web start` binds this port exactly - export it # first (set -a; . ./.env; set +a) or pass it inline (PORT=8080 pnpm ...). # Without it the server would pick the first free port from 3000 upwards, # which a reverse proxy cannot be pointed at. WEB_PORT=3000 # Manual mode only - interface the React Router server binds to. Unset means # every interface. Set it to 127.0.0.1 when a reverse proxy on the same host # is the only thing that should reach it. Leave it unset under Docker, where # the container's own network namespace already isolates it. # HOST=127.0.0.1 # 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 # --------------------------------------------------------------------------- # WEB APP # --------------------------------------------------------------------------- # 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 the server-side loaders fetch content from, MANUAL MODE. STRAPI_URL=http://localhost:1337 # 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= # --------------------------------------------------------------------------- # 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