Repository navigation
Expand file tree
/
Copy pathexample.env
More file actions
451 lines (363 loc) · 16.6 KB
/
Copy pathexample.env
File metadata and controls
451 lines (363 loc) · 16.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# Copy to .env and fill in. Every variable is described in docs/environment.md;
# the block between the GENERATED markers below is written from lib/env.ts by
# `npm run env:docs`, so edit the descriptions there, not here.
# Docker Compose
# Both compose files (docker-compose.yml for development, deploy/docker-compose.yml
# for production) refuse to start without these two, and bind Postgres and Redis
# to the compose network or 127.0.0.1 only. Generate each with: openssl rand -hex 16
# Use the same passwords in DATABASE_URL and REDIS_URL below.
# A database volume created before this setting keeps the password it was
# created with ("postgres"): set POSTGRES_PASSWORD to that, or change it with
# ALTER USER postgres PASSWORD '...'.
POSTGRES_PASSWORD=""
REDIS_PASSWORD=""
# deploy/docker-compose.yml only: the image tag to run (default latest, which
# tracks main). Pin a release in production, for example 0.2.0.
# PLEX_MANAGER_VERSION=""
# BEGIN GENERATED by `npm run env:docs` from lib/env.ts; edit the descriptions there
# -----------------------------------------------------------------------------
# Core
# -----------------------------------------------------------------------------
# The app's URL, for NextAuth callbacks and session cookies. https in
# production; cookies are Secure exactly when it is https.
NEXTAUTH_URL="http://localhost:3000"
# Public URL for share links and OG images; same origin as NEXTAUTH_URL. A
# bare-metal install rebuilds after changing it, because Next inlines it at
# build time.
# Default: NEXTAUTH_URL
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# Signs session cookies. At least 32 random characters: openssl rand -base64
# 32.
# Required in production: the server refuses to start without it.
NEXTAUTH_SECRET=""
# Unique id this install reports to Plex: openssl rand -hex 16. Keep it stable;
# Jellyfin's default device id is derived from it.
# Required in production: the server refuses to start without it.
PLEX_CLIENT_IDENTIFIER=""
# Keyring for secrets stored at rest: comma-separated kid:base64 entries of 32
# bytes each (openssl rand -base64 32). The first encrypts new writes; the
# others only read. Production also starts with ENCRYPTION_KEY alone, or with
# ALLOW_PLAINTEXT_SECRETS=true. Keep every key in a password manager, never
# beside a database dump; rotation and lost-key recovery are in
# docs/operations.md.
# Required in production: the server refuses to start without it.
# ENCRYPTION_KEYS=""
# Older single key for stored secrets, at least 32 characters: openssl rand
# -hex 32. Never reuse NEXTAUTH_SECRET. It still reads what it wrote. Without
# ENCRYPTION_KEYS, it encrypts new writes as kid legacy. To move to
# ENCRYPTION_KEYS, see docs/operations.md.
# ENCRYPTION_KEY=""
# UNSAFE. "true" lets production start without a strong encryption key; every
# boot warns and secrets are stored as plain text.
# Default: false
# ALLOW_PLAINTEXT_SECRETS=""
# Claims first-run setup instead of the code printed in the log. At least 16
# characters: openssl rand -hex 16.
# SETUP_TOKEN=""
# "true" lets production run on plain http (LAN only). Cookies are then not
# Secure; never set it on an install reachable from the internet.
# Default: false
# ALLOW_INSECURE_HTTP=""
# Strict-Transport-Security max-age in seconds, sent only when NEXTAUTH_URL is
# https. The boot check refuses anything but a whole number.
# Default: 31536000
# HSTS_MAX_AGE=""
# "true" adds includeSubDomains to Strict-Transport-Security. Set it only when
# every subdomain serves https.
# Default: false
# HSTS_INCLUDE_SUBDOMAINS=""
# "true" adds preload to Strict-Transport-Security, for the browsers' preload
# list. Hard to undo: read hstspreload.org first.
# Default: false
# HSTS_PRELOAD=""
# "true" sends the Content Security Policy as
# Content-Security-Policy-Report-Only: violations reach /api/csp-report but are
# not blocked. For a rollout or a suspected policy fault only.
# Default: false
# CSP_REPORT_ONLY=""
# Reverse proxies that append to X-Forwarded-For: 1 for one proxy, 2 for a CDN
# in front of it, 0 for none. A wrong value lets clients pick their rate-limit
# address.
# Default: 1
# TRUSTED_PROXY_HOPS=""
# Server time zone (IANA name) until one is saved in Admin settings, which
# overrides it.
# Default: UTC
# TZ=""
# -----------------------------------------------------------------------------
# Database
# -----------------------------------------------------------------------------
# PostgreSQL connection string. ?schema= picks the Postgres schema for
# migrations and the app alike; change it only before the first migration.
DATABASE_URL="postgresql://postgres:your-postgres-password@localhost:5432/plex_wrapped?schema=public"
# Docker image only: "true" starts without applying migrations; the entrypoint
# still logs prisma migrate status.
# Default: false
# SKIP_MIGRATIONS=""
# web, worker or all: what this container runs, and the database pool defaults
# below. web serves pages only; worker runs the queues, schedulers and Discord
# bot and serves only /api/health and /api/metrics; all does both in one
# container (docs/examples/docker-compose.workers.yml). The boot check refuses
# any other value.
# Default: all
# PROCESS_ROLE=""
# Database pool size. The Prisma 7 pg adapter ignores ?connection_limit= in
# DATABASE_URL.
# Default: 10 web, 5 worker, 12 all
# DB_POOL_MAX=""
# How long a query waits for a free database connection.
# Default: 10000
# DB_CONNECTION_TIMEOUT_MS=""
# Statement timeout in milliseconds.
# Default: 15000 web, 120000 worker, 60000 all
# DB_STATEMENT_TIMEOUT_MS=""
# -----------------------------------------------------------------------------
# Background work
# -----------------------------------------------------------------------------
# Redis for the job queue and rate limits, redis://:password@host:6379. Rewind
# and Stripe need it.
# REDIS_URL=""
# "false" turns the BullMQ worker off in this process (on by default when
# REDIS_URL is set).
# Default: true
# ENABLE_QUEUE_WORKER=""
# Jobs the worker runs at once.
# Default: 5
# QUEUE_WORKER_CONCURRENCY=""
# "false" opts this process out of the Discord bot. Otherwise it starts once
# Admin, Discord, "Bot enabled" is on and a token exists, with no restart. One
# process runs it, under a database lock.
# Default: true
# ENABLE_DISCORD_BOT=""
# How often to try for the bot lock and re-check settings.
# Default: 10000
# DISCORD_BOT_POLL_INTERVAL_MS=""
# "false" turns the polling watchlist sync off when Redis is not set.
# Default: true
# ENABLE_WATCHLIST_SYNC=""
# How often the polling watchlist sync checks its lock.
# Default: 60000
# WATCHLIST_SYNC_POLL_INTERVAL_MS=""
# How long SIGTERM waits for jobs, the bot and connections before exiting
# (below Docker's 10 s stop timeout).
# Default: 8000
# SHUTDOWN_GRACE_MS=""
# -----------------------------------------------------------------------------
# Observability
# -----------------------------------------------------------------------------
# error, warn, info, verbose, debug or silly.
# Default: info in production, else debug
# LOG_LEVEL=""
# Bearer token for /api/metrics; without it the route answers 404: openssl rand
# -hex 32.
# METRICS_TOKEN=""
# Git commit /api/metrics reports in build_info (the image sets it at build
# time).
# BUILD_COMMIT=""
# -----------------------------------------------------------------------------
# Data retention
# -----------------------------------------------------------------------------
# Days Rewind AI prompts and replies keep their text.
# Default: 120
# RETENTION_REWIND_LLM_TEXT_DAYS=""
# Days assistant prompts and replies keep their text.
# Default: 90
# RETENTION_ASSISTANT_LLM_TEXT_DAYS=""
# Idle days before an assistant page conversation leaves its owner's history.
# Default: 90
# RETENTION_ASSISTANT_CHAT_DAYS=""
# Days an ended assistant conversation is kept.
# Default: 180
# RETENTION_CHAT_CONVERSATION_DAYS=""
# Idle days before a Discord chat's stored turns are emptied.
# Default: 1
# RETENTION_DISCORD_CHAT_MESSAGES_DAYS=""
# Idle days before a Discord chat session is deleted.
# Default: 30
# RETENTION_DISCORD_CHAT_SESSION_DAYS=""
# Days Discord command arguments are kept.
# Default: 7
# RETENTION_DISCORD_COMMAND_ARGS_DAYS=""
# Days Discord command log rows are kept.
# Default: 90
# RETENTION_DISCORD_COMMAND_LOG_DAYS=""
# Days Rewind share-link daily visit counts are kept.
# Default: 90
# RETENTION_SHARE_VISITS_DAYS=""
# Days Rewind reading records are kept.
# Default: 120
# RETENTION_REWIND_VIEW_DAYS=""
# Days a title removed from a watchlist stays in sync history.
# Default: 30
# RETENTION_WATCHLIST_REMOVED_DAYS=""
# Days an expired Discord link attempt is kept.
# Default: 1
# RETENTION_DISCORD_OAUTH_STATE_DAYS=""
# Days audit log rows are kept.
# Default: 400
# RETENTION_AUDIT_LOG_DAYS=""
# Days refused, revoked and closed affiliate applications and unused affiliate
# invites are kept.
# Default: 365
# RETENTION_AFFILIATE_DAYS=""
# -----------------------------------------------------------------------------
# Integrations
# -----------------------------------------------------------------------------
# Discord bot token, used when none is stored in Admin settings.
# DISCORD_BOT_TOKEN=""
# Discord application id for the slash-command and metadata scripts.
# DISCORD_CLIENT_ID=""
# Discord application id the scripts fall back to.
# NEXT_PUBLIC_DISCORD_CLIENT_ID=""
# Registers slash commands in one Discord server, instantly, instead of
# globally.
# DISCORD_GUILD_ID=""
# Support channel id, used when none is stored in Admin settings.
# DISCORD_SUPPORT_CHANNEL_ID=""
# Comma-separated support thread ids, used when none are stored in Admin
# settings.
# DISCORD_SUPPORT_THREAD_IDS=""
# Account-linking URL in Discord nudges.
# Default: <base>/discord/link
# DISCORD_PORTAL_URL=""
# First choice for the Discord portal base URL, before NEXT_PUBLIC_APP_URL and
# NEXTAUTH_URL.
# PLEX_WRAPPED_BASE_URL=""
# DeviceId reported to Jellyfin at sign-in. Leave unset: the default is derived
# from PLEX_CLIENT_IDENTIFIER.
# Default: plex-manager-<16 hex characters>
# JELLYFIN_DEVICE_ID=""
# LLM request timeout in milliseconds.
# Default: 300000
# LLM_REQUEST_TIMEOUT_MS=""
# -----------------------------------------------------------------------------
# Rewind
# -----------------------------------------------------------------------------
# Rewind poster, card and font cache, resolved against the working directory.
# It can be rebuilt, so it needs no backup.
# Default: .next/cache/rewind
# REWIND_CACHE_DIR=""
# Staging only: "1" lets the season-open rehearsal run (npm run
# rewind:season-open -- --rehearse). Never set in production.
# REWIND_STAGING=""
# =============================================================================
# TEST ONLY - NEVER IN PRODUCTION
# =============================================================================
# Test only: "true" arms the seed outside production. Never set it in .env;
# pass it inline.
# E2E_TEST_MODE=""
# Test only: the Playwright database; its name must end in _test, and the suite
# wipes it.
E2E_DATABASE_URL="postgresql://postgres:your-postgres-password@localhost:5433/plex_manager_test?schema=public"
# Test only: the Playwright web server port.
# Default: 3100
# E2E_PORT=""
# Test only: "true" skips live Plex checks.
# SKIP_CONNECTION_TESTS=""
# Development only: "1" serves the /dev/ui primitives sheet (Playwright sets
# it).
# ENABLE_DEV_UI=""
# END GENERATED
# -----------------------------------------------------------------------------
# Notes
# -----------------------------------------------------------------------------
# Stripe: there are intentionally NO STRIPE_* environment variables. The secret
# key, webhook signing secret and price ids are stored encrypted and configured
# in Admin -> Settings -> Stripe Subscriptions; Stripe needs REDIS_URL. For
# local development, forward events with the Stripe CLI:
# stripe listen --forward-to localhost:3000/api/stripe/webhook
# See docs/stripe.md.
#
# E2E: the suite wipes users, Rewinds and service configs, and refuses to run
# unless E2E_DATABASE_URL names a database ending in _test. Start it with:
# docker compose up -d db-playwright
# DATABASE_URL=$E2E_DATABASE_URL npx prisma migrate deploy
# Seed it (never on a host that serves production):
# DATABASE_URL=$E2E_DATABASE_URL E2E_TEST_MODE=true npm run db:seed
# Set E2E_REUSE_SERVER=1 to reuse a running server that uses E2E_DATABASE_URL.
# E2E_REUSE_SERVER="1"
# =============================================================================
# DEVELOPMENT DEFAULTS FOR SETUP WIZARD
# =============================================================================
#
# SECURITY WARNING: These DEV_* variables are ONLY read when NODE_ENV=development
# AND DEV_SETUP_PREFILL=true, and only until setup is complete. They are completely
# ignored in production. Until setup completes, anyone who can reach the dev
# server can read them, including tokens and API keys.
#
# IMPORTANT SECURITY NOTES:
# - Never commit real API keys or tokens to version control
# - These values are stored in plaintext and may appear in logs
# - For production, always use the setup wizard UI to configure services
# - If you use these for local development, ensure your .env is in .gitignore
#
# HOW IT WORKS:
# - DEV_* variables pre-populate the setup wizard forms
# - Set DEV_SETUP_AUTO_SUBMIT=true for zero-click setup (forms auto-submit)
# - A warning banner appears in the UI when dev defaults are active
# =============================================================================
# Prefill: required for any DEV_* value below to reach the setup wizard
# DEV_SETUP_PREFILL="true"
# Auto-submit: Enable zero-click setup wizard (requires all fields populated)
# DEV_SETUP_AUTO_SUBMIT="true"
# -----------------------------------------------------------------------------
# Service Configuration Defaults
# -----------------------------------------------------------------------------
# URL format: include protocol and port (e.g., https://localhost:32400)
# Plex Server
DEV_PLEX_NAME="My Plex Server"
DEV_PLEX_URL="https://localhost:32400"
DEV_PLEX_TOKEN=""
# DEV_PLEX_PUBLIC_URL="" # Optional: public-facing URL for links
# Tautulli
DEV_TAUTULLI_NAME="My Tautulli Server"
DEV_TAUTULLI_URL="http://localhost:8181"
DEV_TAUTULLI_API_KEY=""
# DEV_TAUTULLI_PUBLIC_URL="" # Optional: public-facing URL for links
# Overseerr
DEV_OVERSEERR_NAME="My Overseerr Server"
DEV_OVERSEERR_URL="http://localhost:5055"
DEV_OVERSEERR_API_KEY=""
# DEV_OVERSEERR_PUBLIC_URL="" # Optional: public-facing URL for links
# Sonarr
DEV_SONARR_NAME="My Sonarr Server"
DEV_SONARR_URL="http://localhost:8989"
DEV_SONARR_API_KEY=""
# DEV_SONARR_PUBLIC_URL="" # Optional: public-facing URL for links
# Radarr
DEV_RADARR_NAME="My Radarr Server"
DEV_RADARR_URL="http://localhost:7878"
DEV_RADARR_API_KEY=""
# DEV_RADARR_PUBLIC_URL="" # Optional: public-facing URL for links
# -----------------------------------------------------------------------------
# Discord Integration Defaults
# -----------------------------------------------------------------------------
# DEV_DISCORD_ENABLED="false" # Enable Discord linked roles
# DEV_DISCORD_BOT_ENABLED="false" # Enable Discord bot functionality
# DEV_DISCORD_CLIENT_ID="" # Discord application client ID
# DEV_DISCORD_CLIENT_SECRET="" # Discord application client secret
# DEV_DISCORD_GUILD_ID="" # Restrict to specific Discord server
# DEV_DISCORD_SERVER_INVITE_CODE="" # Discord server invite code
# DEV_DISCORD_PLATFORM_NAME="" # Display name (default: "Plex Wrapped")
# DEV_DISCORD_INSTRUCTIONS="" # Internal admin notes
# -----------------------------------------------------------------------------
# LLM Provider Defaults
# -----------------------------------------------------------------------------
# Generic LLM settings (used as fallback for both Chat and Wrapped)
DEV_LLM_PROVIDER="openai"
DEV_LLM_API_KEY=""
DEV_LLM_MODEL=""
# Chat Assistant AI (admin troubleshooting chatbot)
# These override the generic DEV_LLM_* settings for the chat purpose
# DEV_CHAT_LLM_PROVIDER="openai"
# DEV_CHAT_LLM_API_KEY=""
# DEV_CHAT_LLM_MODEL="gpt-4o-mini"
# DEV_CHAT_LLM_TEMPERATURE="0.7" # 0.0-2.0, controls randomness
# DEV_CHAT_LLM_MAX_TOKENS="1000" # Max tokens in response
# Wrapped Generation AI (Plex Wrapped story generation)
# These override the generic DEV_LLM_* settings for the wrapped purpose
# DEV_WRAPPED_LLM_PROVIDER="openai"
# DEV_WRAPPED_LLM_API_KEY=""
# DEV_WRAPPED_LLM_MODEL="gpt-4o"
# DEV_WRAPPED_LLM_TEMPERATURE="0.8" # 0.0-2.0, controls randomness
# DEV_WRAPPED_LLM_MAX_TOKENS="6000" # Max tokens in response