Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
3bb4b76
feat: named instance config for Radarr and Sonarr
sbcrumb Aug 18, 2026
fbc8454
feat: build one Radarr/Sonarr client per configured instance
sbcrumb Aug 18, 2026
7f61762
ci: add v3 Docker build workflow — pushes sbcrumb/chronarr:v3 on feat…
sbcrumb Aug 21, 2026
de001dc
feat: add instance column to Chronarr DB
sbcrumb Aug 25, 2026
6e21bdb
refactor: per-instance PathMapper, simplify file_utils path dispatch
sbcrumb Aug 25, 2026
49fc08d
feat: wire instance through webhook routing and processors
sbcrumb Aug 25, 2026
94ca201
Merge pull request #101 from sbcrumb/feature/v3-phase2
sbcrumb Aug 25, 2026
244fe48
chore: thread instance through remaining non-webhook processors, regi…
sbcrumb Aug 26, 2026
07d0374
feat: per-instance startup connection status stored on registry
sbcrumb Aug 26, 2026
140ec48
feat: /setup page — instance webhook URLs and connection status
sbcrumb Aug 26, 2026
301cb25
feat: instance dropdown and combined view on content pages
sbcrumb Aug 26, 2026
fbfd9a7
feat: add Emby plugin changelog file and /emby/changelog API endpoint
sbcrumb Aug 26, 2026
d4f2ec1
Merge pull request #102 from sbcrumb/feature/v3-phase3
sbcrumb Aug 26, 2026
d316b32
fix: thread instance through edit and smart-fix flows — movie and epi…
sbcrumb Aug 27, 2026
c4edb8a
fix: strip media-manager ID suffixes from series folder titles
sbcrumb Aug 27, 2026
b3cebe3
feat: sidebar nav with expandable instance sub-items, instance badges…
sbcrumb Aug 27, 2026
b012cd5
feat: add delete series endpoint and button (removes series row and a…
sbcrumb Aug 27, 2026
ca1955c
fix: cold start populate now iterates all configured Radarr/Sonarr in…
sbcrumb Aug 27, 2026
3cbbe83
docs: update README, CHANGELOG, and QUICKSTART for v3
sbcrumb Aug 27, 2026
adce399
docs: fix stale references in README and QUICKSTART
sbcrumb Aug 27, 2026
90a4e7c
docs: fix stale and sensitive content in env examples and compose
sbcrumb Aug 27, 2026
6baff93
Merge pull request #104 from sbcrumb/feat/sidebar-nav-instances
sbcrumb Aug 27, 2026
21524d9
fix: sync sidebar nav static files to chronarr-web/static
sbcrumb Aug 27, 2026
df7a8d6
Merge pull request #105 from sbcrumb/feat/sidebar-nav-instances
sbcrumb Aug 27, 2026
0b6b527
fix: restore skipped items card and fix chart container layout
sbcrumb Aug 27, 2026
786bf6d
fix: escape double quotes in delete series onclick attribute
sbcrumb Aug 27, 2026
65c703e
Merge pull request #106 from sbcrumb/feat/sidebar-nav-instances
sbcrumb Aug 27, 2026
4c89903
fix: per-instance paths — remove global MOVIE_PATHS/TV_PATHS requirement
sbcrumb Aug 28, 2026
e09eb00
Merge pull request #107 from sbcrumb/fix/per-instance-paths
sbcrumb Aug 28, 2026
cf95368
fix: hard-fail Radarr/Sonarr populate on misconfigured SQLite path
sbcrumb Aug 29, 2026
d02e7e8
fix: tag per-movie and per-episode populate log lines with instance name
sbcrumb Aug 29, 2026
7ba61d9
docs: clarify multi-instance NAME segment naming rules
sbcrumb Aug 29, 2026
a71f691
docs: add multi-instance SQLite mount examples to quickstart and compose
sbcrumb Aug 29, 2026
bf1388f
Merge pull request #108 from sbcrumb/fix/populate-hardfail-and-instan…
sbcrumb Aug 29, 2026
edc18c1
fix: cast SQLite hasFile to bool before episode insert
sbcrumb Aug 29, 2026
57ecf87
Merge pull request #109 from sbcrumb/fix/sqlite-hasfile-boolean-cast
sbcrumb Aug 29, 2026
01f9ab0
feat: setup wizard, per-instance health, and multi-instance webhook f…
sbcrumb Aug 30, 2026
a207951
Merge pull request #111 from sbcrumb/feature/v3-squashed
sbcrumb Aug 30, 2026
8073faf
fix: instance-scoped episodes/delete, orphaned-cleanup, and setup page
sbcrumb Aug 31, 2026
d419ea0
Merge pull request #112 from sbcrumb/feature/v3-squashed-2
sbcrumb Aug 31, 2026
e664d4f
fix: Emby plugin date lookup and cross-instance path-scan isolation
sbcrumb Aug 31, 2026
05757c2
Merge pull request #113 from sbcrumb/feature/v3-squashed-3
sbcrumb Aug 31, 2026
0400a3a
fix: movie delete and debug-data lookup ignored instance
sbcrumb Aug 31, 2026
7184d85
Merge pull request #114 from sbcrumb/fix/movie-delete-debug-instance-…
sbcrumb Aug 31, 2026
096959b
fix: retry on transient filesystem errors during webhook processing
sbcrumb Sep 5, 2026
6b6d20f
Merge pull request #117 from sbcrumb/fix/retry-transient-fs-errors
sbcrumb Sep 5, 2026
04c36c0
feat: more readable logs, per-webhook request ids, and a log viewer i…
sbcrumb Sep 5, 2026
ad12ae6
Merge pull request #118 from sbcrumb/feat/readable-logs-and-log-viewer
sbcrumb Sep 15, 2026
abdc674
feat: split Tools into its own sidebar dropdown, one page per tool
sbcrumb Sep 15, 2026
23d6e97
Merge pull request #119 from sbcrumb/feat/tools-nav-split
sbcrumb Sep 15, 2026
4c8cc90
fix: log tail auto-refresh yanked the viewer back to bottom every cycle
sbcrumb Sep 15, 2026
c706cd4
Merge pull request #120 from sbcrumb/feat/tools-nav-split
sbcrumb Sep 15, 2026
f3b9368
fix: two log-visibility gaps found while testing the log viewer
sbcrumb Sep 16, 2026
3c866ec
Merge pull request #121 from sbcrumb/fix/log-visibility-gaps
sbcrumb Sep 16, 2026
85a5f35
feat: title and reason on plugin lookup misses, unresolved lookups page
sbcrumb Sep 30, 2026
7870077
Merge pull request #126 from sbcrumb/fix/plugin-lookup-log-detail
sbcrumb Sep 30, 2026
a6cdece
fix: series title was always null, series.metadata is never populated
sbcrumb Sep 30, 2026
8253c30
fix: bump app.js cache-buster so the unresolved-lookups JS actually l…
sbcrumb Sep 30, 2026
dd3825c
Merge pull request #127 from sbcrumb/fix/unresolved-lookups-ui
sbcrumb Sep 30, 2026
60cfa33
feat: populate-run added/skipped item lists, movie title fallback, bu…
sbcrumb Sep 30, 2026
5be172c
fix: emby plugin 2.0.21 - library exclusions were never actually applied
sbcrumb Sep 30, 2026
8581236
Merge pull request #128 from sbcrumb/fix/unresolved-lookups-ui
sbcrumb Sep 30, 2026
7adf47d
feat: auto-detect and merge a series' IMDb ID changing between syncs
sbcrumb Oct 1, 2026
fb554bd
fix: update bundled Emby plugin DLL to the verified 2.0.22 fix
sbcrumb Oct 1, 2026
bea0886
Merge pull request #129 from sbcrumb/fix/series-imdb-auto-migrate-and…
sbcrumb Oct 1, 2026
f72a1ac
fix: update bundled Emby plugin DLL - license checksum fix included
sbcrumb Oct 1, 2026
52d64e3
Merge pull request #130 from sbcrumb/fix/emby-dll-license-key-prefix
sbcrumb Oct 1, 2026
ff1b114
Merge remote-tracking branch 'origin/dev' into feature/v3
sbcrumb Oct 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
286 changes: 188 additions & 98 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,172 +1,262 @@
# ===========================================
# Chronarr Configuration - CORRECTED VERSION
# Chronarr Configuration
# ===========================================
# Main configuration file - safe to share for debugging
# Sensitive data (API keys, passwords) are in .env.secrets
# Copy this file to .env and fill in your values.
# Sensitive values (API keys, passwords) belong in .env.secrets — keep that file out of git.
#
# WEBHOOK URLS for your Radarr/Sonarr instances:
# Single instance (default): http://chronarr:8080/radarr/webhook
# http://chronarr:8080/sonarr/webhook
# Named instances: http://chronarr:8080/radarr_4k/webhook
# http://chronarr:8080/sonarr_4k/webhook
# (Webhook URLs are built automatically from instance names in this file)

# ===========================================
# MEDIA PATHS (REQUIRED) - FIXED
# CHRONARR DATABASE
# ===========================================
# Container paths (what Chronarr sees inside container)
MOVIE_PATHS=/media/Movies/movies,/media/Movies/movies6
TV_PATHS=/media/TV/tv,/media/TV/tv6
# Internal Chronarr database — stores your media dates and metadata.
# PostgreSQL is strongly recommended for production.

# Radarr paths (what Radarr sees on the host system)
RADARR_ROOT_FOLDERS=/mnt/unionfs/Media/Movies/movies,/mnt/unionfs/Media/Movies/movies6

# Sonarr paths (what Sonarr sees on the host system) - FIXED VARIABLE NAME AND PATHS
SONARR_ROOT_FOLDERS=/mnt/unionfs/Media/TV/tv,/mnt/unionfs/Media/TV/tv6
DB_TYPE=postgresql
DB_HOST=chronarr-db
DB_PORT=5432
DB_NAME=chronarr
DB_USER=chronarr
# DB_PASSWORD= → set in .env.secrets

# Download detection paths (for identifying downloads vs existing files)
DOWNLOAD_PATH_INDICATORS=/downloads/,/nzbget/,/completed/,/sabnzbd/,/torrents/
# SQLite alternative (not recommended for production):
# DB_TYPE=sqlite
# DB_PATH=/app/data/media_dates.db

# ===========================================
# SERVER CONFIGURATION
# ===========================================
# Timezone for container logging and timestamps
TZ=America/New_York

# Chronarr Core API (webhooks, processing, database management)
# Core API — handles webhooks and processing
# This is the interface Chronarr's own core container listens ON. Leave it
# at 0.0.0.0 unless you have a specific reason to change it — setting this
# to a hostname will stop core listening on the addresses Docker healthchecks
# and the web container's other internal calls use, breaking both.
CORE_API_HOST=0.0.0.0
CORE_API_PORT=8080

# Chronarr Web Interface (dashboard, series/movie management)
WEB_API_HOST=0.0.0.0
WEB_API_PORT=8081

# External port where web interface is accessible (for dynamic port reference)
# Where the WEB container reaches CORE internally — a different setting from
# the pair above. Only needed if the default hostname "chronarr" is
# ambiguous, e.g. running more than one Chronarr deployment on the same
# Docker network (a production stack and a local-test stack, say) — point
# this at your core container's actual name/service in that situation.
# CORE_INTERNAL_HOST=chronarr
# CORE_INTERNAL_PORT=8080

# Web dashboard
WEB_HOST=0.0.0.0
WEB_PORT=8081
WEB_WORKERS=1
WEB_EXTERNAL_PORT=8081

# ===========================================
# DATABASE CONFIGURATION
# RADARR — MAIN INSTANCE
# ===========================================
# Chronarr Database Configuration (PostgreSQL - v2.6+)
# NOTE: For new installations, PostgreSQL is strongly recommended
# Set these values in .env.secrets for security:
# - DB_PASSWORD=your_secure_password
# - DB_USER=chronarr (default)

# PostgreSQL Database Settings
DB_TYPE=postgresql
DB_HOST=chronarr-db # Container name from docker-compose
DB_PORT=5432
DB_NAME=chronarr
DB_USER=chronarr

# Legacy SQLite Configuration (Deprecated in v2.6+)
# Only use for existing SQLite installations
# DB_PATH=/app/data/media_dates.db
# Paths: RADARR_ROOT_FOLDERS is what Radarr sees on the host (or UNC path on Windows).
# RADARR_MOVIE_PATHS is what Chronarr sees inside the container.
# Both are comma-separated.
#
# IMPORTANT — multi-instance users:
# Define paths per-instance (RADARR_MOVIE_PATHS, RADARR_4K_MOVIE_PATHS, etc.)
# Do NOT use the global MOVIE_PATHS key when running multiple instances —
# if it appears more than once in your env file, Docker only keeps the last
# definition and silently drops the others.

# Log file directory
LOG_DIR=/app/data/logs
RADARR_URL=http://radarr:7878
# RADARR_API_KEY= → set in .env.secrets
# RADARR_WEBHOOK_SECRET= → set in .env.secrets (optional, for webhook validation)
RADARR_ROOT_FOLDERS=/mnt/unionfs/Media/Movies/movies
RADARR_MOVIE_PATHS=/media/movies

# ===========================================
# RADARR DATABASE CONNECTION (RECOMMENDED)
# ===========================================
# Direct database access for better performance
# Radarr database (direct DB access — faster than API for large libraries)
RADARR_DB_TYPE=postgresql
RADARR_DB_HOST=192.168.255.50
RADARR_DB_HOST=your-radarr-db-host
RADARR_DB_PORT=5432
RADARR_DB_NAME=radarr-main
RADARR_DB_USER=postgres
# RADARR_DB_PASSWORD= → set in .env.secrets

# Alternative: SQLite (if Radarr uses SQLite)
# SQLite alternative:
# RADARR_DB_TYPE=sqlite
# RADARR_DB_PATH=/path/to/radarr.db

# ===========================================
# SONARR DATABASE CONNECTION (RECOMMENDED)
# RADARR — ADDITIONAL INSTANCES (OPTIONAL)
# ===========================================
# Add a block per extra Radarr instance. The name between RADARR_ and _URL
# becomes part of the webhook URL: RADARR_4K_URL → /radarr_4k/webhook
# Names must be uppercase letters, digits, and underscores only — no hyphens
# (a shell/env-var limitation). RADARR_4K and RADARR_STRM_BOX are fine;
# RADARR-4K is not. The URL *value* has no such restriction — it can contain
# hyphens and a full domain name, e.g. RADARR_STRM_URL=http://radarr-strm.yourdomain.com:7878
#
# Each instance defines ALL of its own settings here — URL, API key, paths,
# and database access. Do NOT set MOVIE_PATHS again in this block; use
# RADARR_4K_MOVIE_PATHS instead. If MOVIE_PATHS appears twice in your env
# file, Docker only keeps the last value and silently drops the first.
#
# After configuring instances, visit http://your-server:8081/setup
# for the exact webhook URLs to paste into each Radarr instance.

# RADARR_4K_URL=http://radarr4k:7878
# RADARR_4K_API_KEY= → set in .env.secrets
# RADARR_4K_WEBHOOK_SECRET= → set in .env.secrets (optional)
# RADARR_4K_ROOT_FOLDERS=/mnt/unionfs/Media/Movies/movies4k
# RADARR_4K_MOVIE_PATHS=/media/movies4k ← per-instance paths, NOT MOVIE_PATHS
# RADARR_4K_DB_TYPE=postgresql
# RADARR_4K_DB_HOST=your-radarr-4k-db-host
# RADARR_4K_DB_PORT=5432
# RADARR_4K_DB_NAME=radarr-4k
# RADARR_4K_DB_USER=postgres
# RADARR_4K_DB_PASSWORD= → set in .env.secrets
# SQLite: RADARR_4K_DB_TYPE=sqlite / RADARR_4K_DB_PATH=/radarr-4k-data/radarr.db

# ===========================================
# SONARR — MAIN INSTANCE
# ===========================================
# Direct database access for better performance
# Phase 7: High-performance TV episode import date detection
# Same paths rule as Radarr: use SONARR_TV_PATHS here, not the global TV_PATHS,
# so each instance's paths stay self-contained.
SONARR_URL=http://sonarr:8989
# SONARR_API_KEY= → set in .env.secrets
# SONARR_WEBHOOK_SECRET= → set in .env.secrets (optional)
SONARR_ROOT_FOLDERS=/mnt/unionfs/Media/TV/tv
SONARR_TV_PATHS=/media/tv

# Sonarr database
SONARR_DB_TYPE=postgresql
SONARR_DB_HOST=192.168.255.50
SONARR_DB_HOST=your-sonarr-db-host
SONARR_DB_PORT=5432
SONARR_DB_NAME=sonarr-main
SONARR_DB_USER=postgres
# SONARR_DB_PASSWORD= → set in .env.secrets

# Alternative: SQLite (if Sonarr uses SQLite)
# SQLite alternative:
# SONARR_DB_TYPE=sqlite
# SONARR_DB_PATH=/path/to/sonarr.db

# ===========================================
# API CONNECTIONS (OPTIONAL)
# SONARR — ADDITIONAL INSTANCES (OPTIONAL)
# ===========================================
# API keys are stored in .env.secrets for security
RADARR_URL=http://radarr:7878
SONARR_URL=http://sonarr:8989
# Same rule: use SONARR_4K_TV_PATHS, NOT TV_PATHS, in additional instance blocks.
# SONARR_4K_URL=http://sonarr4k:8989
# SONARR_4K_API_KEY= → set in .env.secrets
# SONARR_4K_WEBHOOK_SECRET= → set in .env.secrets (optional)
# SONARR_4K_ROOT_FOLDERS=/mnt/unionfs/Media/TV/tv4k
# SONARR_4K_TV_PATHS=/media/tv4k ← per-instance paths, NOT TV_PATHS
# SONARR_4K_DB_TYPE=postgresql
# SONARR_4K_DB_HOST=your-sonarr-4k-db-host
# SONARR_4K_DB_PORT=5432
# SONARR_4K_DB_NAME=sonarr-4k
# SONARR_4K_DB_USER=postgres
# SONARR_4K_DB_PASSWORD= → set in .env.secrets

# ===========================================
# EXTERNAL APIs (OPTIONAL)
# ===========================================
# Jellyseerr — for request tracking
# JELLYSEERR_URL=http://jellyseerr:5055
# JELLYSEERR_API_KEY= → set in .env.secrets

# TMDB — for release date and metadata lookup
# TMDB_API_KEY= → set in .env.secrets
TMDB_COUNTRY=US
# TMDB_TYPE_PRIORITY=movie,tv

# TVDB — for TV episode air dates
# TVDB_API_KEY= → set in .env.secrets
# DISABLE_TVDB=false

# OMDB — fallback metadata source
# OMDB_API_KEY= → set in .env.secrets

# ===========================================
# RELEASE DATE PROCESSING
# MOVIE PROCESSING
# ===========================================
# Priority order for release date fallbacks (digital, physical, theatrical)
# Priority for determining which date to use
# Options: import_then_digital, digital_only, theatrical_only
MOVIE_PRIORITY=import_then_digital

# Order to check release date types
RELEASE_DATE_PRIORITY=digital,physical,theatrical
#RELEASE_DATE_PRIORITY=digital,theatrical,physical
ENABLE_SMART_DATE_VALIDATION=true
MAX_RELEASE_DATE_GAP_YEARS=10

# Prefer API release dates over file modification dates for manual imports
# Prefer API release dates over file modification dates
PREFER_RELEASE_DATES_OVER_FILE_DATES=true

# Disable file date fallback completely (recommended for clean imports)
# Allow file modification date as a last-resort fallback
ALLOW_FILE_DATE_FALLBACK=false

# TMDB country for regional release date preferences
TMDB_COUNTRY=US
# How to handle existing dates in the database
# Options: backfill_only (fill missing), overwrite (always update)
MOVIE_DATE_UPDATE_MODE=backfill_only

# When to poll for movie date data
# Options: always, missing_only, never
MOVIE_POLL_MODE=always

# Smart date validation — rejects dates that seem implausible
ENABLE_SMART_DATE_VALIDATION=true
MAX_RELEASE_DATE_GAP_YEARS=10

# Remove movies from DB that have been missing for N days (0 = disabled)
PURGE_MISSING_MOVIES_DAYS=0

# ===========================================
# PROCESSING BEHAVIOR
# TV PROCESSING
# ===========================================
# Movie date update strategy
MOVIE_DATE_UPDATE_MODE=overwrite
MOVIE_PRESERVE_EXISTING=false

# When to update existing dates (always, missing_only, never)
UPDATE_MODE=always
TV_WEBHOOK_PROCESSING_MODE=targeted

# File modification time behavior (update, leave_alone)
MTIME_BEHAVIOR=update
# Season directory naming — must match your actual folder names
TV_SEASON_DIR_FORMAT=Season {season:02d}
TV_SEASON_DIR_PATTERN=season

# Manual scan priority: use existing NFO dates for speed vs check APIs for accuracy
# false (default) = Check external APIs first, use NFO as fallback (slower but accurate)
# true = Use NFO dates immediately without API checks (faster but may use wrong dates)
MANUAL_SCAN_PRIORITIZE_NFO=false
# Remove TV shows from DB that have been missing for N days (0 = disabled)
PURGE_MISSING_TV_DAYS=0

# ===========================================
# PERFORMANCE & BATCHING
# ===========================================
# Delay before processing batched events (seconds)
BATCH_DELAY=5.0

# Maximum concurrent series processing
MAX_CONCURRENT_SERIES=3

# Sequential processing delay for bulk downloads (seconds)
# When multiple episodes are downloaded at once, process them one by one with this delay
# Set to 0 to disable sequential processing (parallel mode)
SEQUENTIAL_DELAY=20.0

# API timeout in seconds
TIMEOUT_SECONDS=45

# ===========================================
# WEB INTERFACE
# ===========================================
WEB_AUTH_ENABLED=false
# WEB_AUTH_USERNAME=admin
# WEB_AUTH_PASSWORD= → set in .env.secrets
WEB_AUTH_SESSION_TIMEOUT=3600

# Dashboard display
# APP_TITLE=Chronarr
# APP_SUBTITLE=Database Management & Reporting
PAGINATION_LIMIT=50
REFRESH_INTERVAL=30

# ===========================================
# DEBUGGING
# ===========================================
# Enable verbose logging (true/false)
DEBUG=false

# Enable path mapping debug output (true/false)
PATH_DEBUG=false

# Suppress TVDB API warnings (true/false) - TVDB failures are common and non-critical
SUPPRESS_TVDB_WARNINGS=true
LOG_DIR=/app/data/logs

# ===========================================
# WEB INTERFACE AUTHENTICATION
# LEGACY — PENDING REMOVAL
# ===========================================
# Enable web interface authentication (default: false)
WEB_AUTH_ENABLED=false

# Session timeout in seconds (default: 3600 = 1 hour)
WEB_AUTH_SESSION_TIMEOUT=3600
# These settings controlled NFO file writing, which was the original mechanism
# for pushing dates into Emby/Jellyfin. The Emby/Jellyfin plugins now read
# directly from Chronarr's database, making this code path obsolete.
# These vars and the code behind them will be removed in a future release.
# Changing these values currently has no meaningful effect.
#
# MANAGE_NFO=true
# FIX_DIR_MTIMES=true
# LOCK_METADATA=true
# MANUAL_SCAN_PRIORITIZE_NFO=false
Loading
Loading