Files
civitai__civitai/.env-example
T
briant 2048057ca2 Merge remote-tracking branch 'origin/main' into moderator-app-pages
Two textual conflicts, and three that only the test run found.

`TryItForm.tsx` was a directory-rename artifact: this branch moved
`src/components/Moderator/` into `@civitai/mod-utils`, so git placed main's new
file in the moved location. Kept main's path, which is what
`src/pages/moderator/api.tsx` imports.

`check-writable.mjs` is theirs plus this branch's two extra rules.

Main tightened three convention ledgers while this branch added code that
violates them. None conflicted textually:

- `image.controller.ts` imported `request-ip` directly. The ledger holds one
  entry and names `client-ip.ts` the sanctioned home for the library fallback,
  so a second entry is not the escape hatch. Switched to the attribution
  derivation, `resolveClientIpOrNull` — which changes which address lands on the
  spoke's image-moderation audit row.
- The same file forwarded the spoke's `.message` at a 4xx without `cause`,
  blinding `isDriverAuthoredMessage` to the chain.
- `remove-placement.ts` hand-rolled what `handleEndpointError` already does.
- `moderator-endpoint.test.ts` mocked `~/server/redis/client` itself instead of
  declaring behaviour on the canonical mock.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 12:27:27 -06:00

213 lines
7.1 KiB
Plaintext

# Since .env is gitignored, you can use .env-example to build a new `.env` file when you clone the repo.
# Keep this file up-to-date when you add new variables to `.env`.
# This file will be committed to version control, so make sure not to have any secrets in it.
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.
# When adding additional env variables, the schema in /env/schema.mjs should be updated accordingly
# The default values for Prisma, Redis, S3, and Email are set to work with the docker-compose setup
# Database
DATABASE_SSL=false
DATABASE_URL=postgresql://postgres:postgres@localhost:15432/civitai
DATABASE_REPLICA_URL=postgresql://postgres:postgres@localhost:15432/civitai
NOTIFICATION_DB_URL=postgresql://postgres:postgres@localhost:15434/postgres
NOTIFICATION_DB_REPLICA_URL=postgresql://postgres:postgres@localhost:15434/postgres
DATAPACKET_DATABASE_RO_URL=postgresql://postgres:postgres@localhost:15435/postgres
# Redis
REDIS_URL=redis://:redis@localhost:6379
REDIS_SYS_URL=redis://:redis@localhost:6378
# Optional: switch the `system` redis client to Sentinel mode. When set, REDIS_SYS_URL
# is still parsed for credentials but the connection is established via Sentinel.
# REDIS_SYS_SENTINELS=localhost:26379,localhost:26380,localhost:26381
# REDIS_SYS_SENTINEL_NAME=sysmaster # production uses "sysmaster"; match the master group your Sentinel CR declares
# Logging
LOGGING=prisma:error,prisma:warn,seed-metrics-search
# Next Auth
NEXTAUTH_SECRET=thisisnotasecret
NEXTAUTH_URL=http://localhost:3000
# Next Auth Discord Provider
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
# Next Auth GitHub Provider
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
# Next Auth Google Provider
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# Next Auth Reddit Provider
REDDIT_CLIENT_ID=
REDDIT_CLIENT_SECRET=
# Integrations
DISCORD_BOT_TOKEN=
DISCORD_GUILD_ID=
DISCORD_WEBHOOK_MOD_ALERTS=
# File uploading
S3_UPLOAD_KEY=REFER_TO_README
S3_UPLOAD_SECRET=REFER_TO_README
S3_UPLOAD_BUCKET=modelshare
S3_UPLOAD_REGION=us-east-1
S3_UPLOAD_ENDPOINT=http://127.0.0.1:9000
# Image uploading
S3_IMAGE_UPLOAD_KEY=
S3_IMAGE_UPLOAD_SECRET=
S3_IMAGE_UPLOAD_BUCKET=images
S3_IMAGE_UPLOAD_REGION=us-east-1
S3_IMAGE_UPLOAD_ENDPOINT=http://127.0.0.1:9000
S3_IMAGE_CACHE_BUCKET=cache
S3_IMAGE_UPLOAD_OVERRIDE=
# Client env vars
NEXT_PUBLIC_IMAGE_LOCATION=http://localhost:3000
NEXT_PUBLIC_CIVITAI_LINK=http://localhost:3000
NEXT_PUBLIC_UI_HOMEPAGE_IMAGES=false
# Clickhouse
CLICKHOUSE_HOST=http://localhost:18123
CLICKHOUSE_USERNAME=default
CLICKHOUSE_PASSWORD=
CLICKHOUSE_TRACKER_URL=http://localhost:3000
# Email
EMAIL_HOST=localhost
EMAIL_PORT=1025
EMAIL_USER=
EMAIL_PASS=
EMAIL_FROM=
# Endpoint Protection
JOB_TOKEN=thisisnotatoken
WEBHOOK_TOKEN=thisisnotatoken
# Base URL of the standalone moderator app (apps/moderator). Migrated /moderator/* routes redirect here
# via the moderator catchall page. Defaults to https://moderator.civitai.com if unset.
MODERATOR_APP_URL=https://moderator.civitai.com
# Site Configuration
UNAUTHENTICATED_DOWNLOAD=true
UNAUTHENTICATED_LIST_NSFW=false
SHOW_SFW_IN_NSFW=false
MAINTENANCE_MODE=false
RATE_LIMITING=true
TRPC_ORIGINS=
# Security
SCANNING_ENDPOINT=http://scan-me.civitai.com/enqueue
SCANNING_TOKEN=thisisnotatoken
# Delivery worker
DELIVERY_WORKER_ENDPOINT=https://delivery-worker.civitai.com/download
DELIVERY_WORKER_TOKEN=thisisnotatoken
# Payments
PADDLE_SECRET_KEY=thisisnotasecret
PADDLE_WEBHOOK_SECRET=thisisnotasecret
NEXT_PUBLIC_PADDLE_TOKEN=thisisnotatoken
NEXT_PUBLIC_DEFAULT_PAYMENT_PROVIDER=Paddle
# Features
FEATURE_FLAG_EARLY_ACCESS_MODEL=public
# MeiliSearch
SEARCH_HOST=http://localhost:7700
SEARCH_API_KEY=meilisearch
NEXT_PUBLIC_SEARCH_HOST=http://localhost:7700
NEXT_PUBLIC_SEARCH_CLIENT_KEY=meilisearch
METRICS_SEARCH_HOST=http://localhost:7700
METRICS_SEARCH_API_KEY=meilisearch
# Debounce window (ms) for flushing model-metric-affected ids into the model
# search-index update queue. Widening it collapses more of a hot model's repeated
# metric changes into a single reindex (cost: metric/popularity staleness lags by
# up to the window). Fail-soft: a bad value falls back to the 45m default. Requires
# a restart/rollout to take effect. Default 45m.
# SEARCH_INDEX_MODEL_METRIC_FLUSH_INTERVAL_MS=2700000
# Per-call Meilisearch timeout in ms. Calls wrapped via withMeili() fail fast
# with MeiliCallTimeoutError once exceeded, instead of hanging until Traefik's
# 30s router timeout fires.
MEILI_CALL_TIMEOUT_MS=2500
# Per-pod cap on in-flight Meilisearch calls wrapped via withMeili(). Excess
# calls fail fast with MeiliCallTimeoutError instead of queueing forever.
MEILI_CALL_CONCURRENCY=50
# Per-backend circuit breaker. If MEILI_CIRCUIT_TRIP_THRESHOLD wrapped-call
# timeouts accumulate within MEILI_CIRCUIT_WINDOW_SECONDS on a backend, the
# circuit OPENs and all calls fail at 0ms for MEILI_CIRCUIT_COOLDOWN_SECONDS,
# then HALF_OPEN issues a single trial request. healthProbe is excluded.
MEILI_CIRCUIT_TRIP_THRESHOLD=10
MEILI_CIRCUIT_WINDOW_SECONDS=30
MEILI_CIRCUIT_COOLDOWN_SECONDS=30
# BaseURL
NEXT_PUBLIC_BASE_URL=http://localhost:3000
# Recaptcha
RECAPTCHA_PROJECT_ID=aSampleKey
NEXT_PUBLIC_RECAPTCHA_KEY=aSampleKey
# CF Turnstile
NEXT_PUBLIC_CLOUDFLARE_TURNSTILE_SITEKEY=1x00000000000000000000BB
CLOUDFLARE_TURNSTILE_SECRET=1x0000000000000000000000000000000AA
NEXT_PUBLIC_CF_INVISIBLE_TURNSTILE_SITEKEY=1x00000000000000000000BB
CF_INVISIBLE_TURNSTILE_SECRET=1x0000000000000000000000000000000AA
NEXT_PUBLIC_CF_MANAGED_TURNSTILE_SITEKEY=1x00000000000000000000AA
CF_MANAGED_TURNSTILE_SECRET=1x0000000000000000000000000000000AA
ORCHESTRATOR_ENDPOINT=http://localhost
ORCHESTRATOR_ACCESS_TOKEN=asdf
BUZZ_ENDPOINT=http://localhost
SIGNALS_ENDPOINT=http://localhost
NEXT_PUBLIC_SIGNALS_ENDPOINT=http://localhost
NOW_PAYMENTS_API_URL=http://localhost
NOW_PAYMENTS_API_KEY=key
NOW_PAYMENTS_IPN_KEY=key
COINBASE_API_URL=http://localhost
COINBASE_API_KEY=key
COINBASE_WEBHOOK_SECRET=secret
EMERCHANTPAY_WPF_URL=
EMERCHANTPAY_USERNAME=
EMERCHANTPAY_PASSWORD=
# Shopify merch store — Blue Buzz reward loop
# SHOPIFY_SHOP_DOMAIN = the *.myshopify.com admin domain (e.g. ff1592-5.myshopify.com)
SHOPIFY_SHOP_DOMAIN=
SHOPIFY_WEBHOOK_SECRET=
# Admin auth: client_credentials grant (preferred). Set ADMIN_TOKEN instead only for a static token.
SHOPIFY_CLIENT_ID=
SHOPIFY_CLIENT_SECRET=
SHOPIFY_ADMIN_TOKEN=
FLIPT_URL=""
FLIPT_FETCHER_SECRET=placeholder
IMAGE_SCANNER_NEW=false
# App Blocks — per-app generation spend/velocity ABSOLUTE CEILINGS (incident knobs).
# 🔴 These are UPPER BOUNDS, not the limit an app receives. Each app's actual
# ceilings come from its server-owned `spendTier` (+ any moderator per-app
# override); these clamp the tier table AND any override from above, so setting
# one TIGHTENS every app and can never loosen one. Unset = no extra clamp.
# Formerly BLOCK_APP_SPEND_CAP_BUZZ_PER_DAY / BLOCK_APP_SPEND_VELOCITY_MAX_GENS —
# those names are DEPRECATED but still honoured (with a startup warning).
# BLOCK_APP_SPEND_ABSOLUTE_MAX_BUZZ_PER_DAY=
# BLOCK_APP_SPEND_ABSOLUTE_MAX_GENS_PER_WINDOW=
# Window (seconds) the gens-per-window ceiling is measured over. Default 60.
# BLOCK_APP_SPEND_VELOCITY_WINDOW_SECONDS=