# Client St0r — environment configuration template # # Copy this file to `.env` (same directory) and fill in real values: # cp .env.example .env # # `.env` is gitignored — never commit it. Every secret in this file # is a placeholder; do not ship these defaults to production. # ─── Core ───────────────────────────────────────────────────────────── # Generate with: python -c "import secrets; print(secrets.token_urlsafe(64))" SECRET_KEY=replace-me-with-a-long-random-string # Set to False in production. Leave True ONLY for local dev. DEBUG=False # Comma-separated list of host headers Django will accept. Wildcards # are supported (*.example.com). When DEBUG=True, ALL hosts are # implicitly allowed. # Examples: # ALLOWED_HOSTS=clientst0r.example.com,*.example.com # ALLOWED_HOSTS=localhost,127.0.0.1 ALLOWED_HOSTS=localhost,127.0.0.1 # CSRF_TRUSTED_ORIGINS — required for HTTPS POST requests on Django # 4+. Auto-derived from ALLOWED_HOSTS when blank. Must include the # scheme (https:// or http://). # CSRF_TRUSTED_ORIGINS=https://clientst0r.example.com # Full base URL of the deployed app. Used by email templates, the # updater, and a few absolute-URL surfaces. BASE_URL=http://localhost:8000 # ─── Database ───────────────────────────────────────────────────────── # Engine: `mysql` (MariaDB / MySQL) or `sqlite3`. Default is mysql so # the docker-compose stack works out of the box. DB_ENGINE=mysql # Used by both the `db` container and the `app` container. Pick strong # values BEFORE the first `docker compose up`. DB_ROOT_PASSWORD=replace-me-strong-root-password DB_NAME=clientst0r DB_USER=clientst0r DB_PASSWORD=replace-me-strong-app-password # Inside docker-compose, DB_HOST=db points at the MariaDB service. # To use an EXTERNAL database, set DB_HOST/DB_PORT to your DB's # address and `docker compose stop db` after first start. DB_HOST=db DB_PORT=3306 # ─── Web port ───────────────────────────────────────────────────────── # Host port the `app` container publishes 8000 on. Change to avoid # conflicts with other services on the host. WEB_PORT=8000 # If you run the optional nginx profile (`docker compose --profile proxy up`): NGINX_HTTP_PORT=80 NGINX_HTTPS_PORT=443 # ─── Bootstrap superuser (optional) ─────────────────────────────────── # If all three are set, the entrypoint creates this user on first # boot. Idempotent — won't re-create on subsequent boots. # Leave blank to skip; you can also create a superuser later with: # docker compose exec app python manage.py createsuperuser DJANGO_SUPERUSER_USERNAME= DJANGO_SUPERUSER_EMAIL= DJANGO_SUPERUSER_PASSWORD= # ─── Email / SMTP ───────────────────────────────────────────────────── # Used by notification flows (PSA replies, beta signups, etc.). # Leave blank to disable outbound email — signups still work, you # just won't receive notifications. EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend EMAIL_HOST= EMAIL_PORT=587 EMAIL_USE_TLS=True EMAIL_HOST_USER= EMAIL_HOST_PASSWORD= DEFAULT_FROM_EMAIL=clientst0r@example.com # ─── External API tokens (optional) ─────────────────────────────────── # GitHub PAT for the Settings → Updates poll. Anonymous limit is # 60/hr; with a token it's 5000/hr. Generate at github.com/settings/tokens # Scope: `public_repo` is enough. GITHUB_TOKEN= # Anthropic API key for optional AI-assisted PSA features (psa_ai). # Leave blank if you don't use AI suggestions. ANTHROPIC_API_KEY= # ─── Storage paths ──────────────────────────────────────────────────── # These are the in-container paths. They're backed by docker volumes # in docker-compose.yml — you usually don't need to change them. UPLOAD_ROOT=/var/lib/itdocs/uploads MEDIA_ROOT=/app/media # ─── Beta-tester signup (operator-side) ────────────────────────────── # Address that receives notifications when someone fills the public # /core/beta-test/ form. Leave the default to forward upstream to the # canonical maintainer. BETA_ADMIN_EMAIL=agit8or@agit8or.net # Upstream forwarder. On the canonical install set BETA_UPSTREAM_URL='' # to disable self-forwarding. On any OTHER install leave this UNSET — # the default points at the canonical server so signups land there. # BETA_UPSTREAM_URL= # ─── Security ───────────────────────────────────────────────────────── REQUIRE_2FA=True SESSION_COOKIE_SECURE=True CSRF_COOKIE_SECURE=True SECURE_HSTS_SECONDS=31536000 SECURE_SSL_REDIRECT=True # Axes (brute force protection) AXES_FAILURE_LIMIT=5 AXES_COOLOFF_TIME=1 # WARNING: enabling private IPs disables SSRF protection. Only set # True if you need to connect to self-hosted services on your LAN. # ALLOW_PRIVATE_IP_INTEGRATIONS=False # ─── Encryption (vault) ─────────────────────────────────────────────── # 32-byte URL-safe base64 key used to encrypt vault secrets at rest. # CRITICAL: do NOT change this after any vault data has been written — # all existing ciphertext becomes unreadable. Generate ONCE with: # python -c "import secrets, base64; print(base64.urlsafe_b64encode(secrets.token_bytes(32)).decode())" APP_MASTER_KEY= # Symmetric HMAC secret for API key signatures. API_KEY_SECRET=replace-me-with-a-random-string # ─── Optional Docker image override ─────────────────────────────────── # If set, docker-compose uses this image instead of building locally. # Useful for production where you pull a pre-built tag. # CLIENTST0R_IMAGE=ghcr.io/agit8or1/clientst0r:latest # Reverse proxies allowed to supply X-Forwarded-For. Use exact proxy CIDRs. # The default suits nginx on the same host (TCP loopback or gunicorn's unix # socket, which is always treated as local). With docker compose's "proxy" # profile, add the nginx container's address (e.g. its fixed IP on # clientst0r-net); otherwise every request appears to come from that container. # Never use 0.0.0.0/0 or ::/0. TRUSTED_PROXY_CIDRS=127.0.0.1/32,::1/128 # ─── Emergency restart webhook ──────────────────────────────────────── # Enables POST /emergency-restart/ (header X-Emergency-Secret) for remote # self-healing via scripts/heal_all_servers.sh. Leave blank to disable. # EMERGENCY_RESTART_SECRET=