-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
CHUB reads a single YAML file on startup: config.yml, kept under ${CONFIG_DIR} (inside the Docker container, that's /config/config.yml).
The easiest way to edit is the web UI — every Settings page writes back through a validated API. If you hand-edit the file:
- Keep permissions at
0600. It contains API keys. - CHUB revalidates the whole file on startup. If validation fails, the container log tells you which field is wrong and CHUB refuses to start.
Per-module config lives on the Modules page, next to each module's description. This page covers the top-level blocks only.
Jump to:
- 🧭 At a glance — top-level layout
- 📝 Full example config.yml
- ⚙️ general
- 🔐 auth
- 🔌 instances
- ⏰ schedule
- 📣 notifications
- 🎨 user_interface
- 🔒 Secret handling
- 🚨 If CHUB won't start
general: {} # global toggles
auth: {} # admin user (managed by the UI)
instances: {} # Radarr / Sonarr / Lidarr / Plex connections
schedule: {} # when each module runs
notifications: {} # Discord / Email / Apprise per module
user_interface: {} # theme
# one section per module — see the Modules page for fields
poster_renamerr: {}
border_replacerr: {}
poster_cleanarr: {}
labelarr: {}
jduparr: {}
nohl: {}
unmatched_assets: {}
upgradinatorr: {}
renameinatorr: {}
health_checkarr: {}
nestarr: {}
sync_gdrive: {}
plex_maintenance: {}Anything you omit falls back to safe defaults.
A complete, working example with every top-level block populated and each module enabled minimally. Copy this as a starting point and trim or extend as needed.
general:
log_level: info
update_notifications: false
max_logs: 9
webhook_initial_delay: 30
webhook_retry_delay: 60
webhook_max_retries: 3
webhook_secret: "" # set to require shared secret on inbound webhooks
duplicate_exclude_groups: []
auth:
username: admin # managed by the UI; leave the rest to CHUB
password_hash: ""
jwt_secret: ""
token_expiry_hours: 24
instances:
radarr:
radarr_main:
url: http://radarr:7878
api: <radarr-api-key>
enabled: true
sonarr:
sonarr_main:
url: http://sonarr:8989
api: <sonarr-api-key>
enabled: true
lidarr:
lidarr_main:
url: http://lidarr:8686
api: <lidarr-api-key>
enabled: true
plex:
plex_main:
url: http://plex:32400
api: <x-plex-token>
enabled: true
schedule:
poster_renamerr:
type: cron
expression: "0 */4 * * *" # every 4 hours
jduparr:
type: interval
minutes: 720 # every 12 hours
upgradinatorr:
type: cron
expression: "15 3 * * *" # daily at 03:15
notifications:
main:
discord:
enabled: true
webhook: https://discord.com/api/webhooks/...
health_checkarr:
email:
enabled: true
from: chub@example.com
to: [you@example.com]
smtp_host: smtp.example.com
smtp_port: 587
username: chub
password: <smtp-password>
user_interface:
theme: dark # light | dark
# --- Modules ---
# See the Modules page for every field. Examples below are a minimal subset.
poster_renamerr:
dry_run: false
action_type: hardlink
asset_folders: true
source_dirs: [/kometa]
destination_dir: /posters
instances:
- radarr_main
- sonarr_main
- plex_main:
library_names: ["Movies", "TV Shows"]
add_posters: true
border_replacerr:
dry_run: false
source_dirs: [/posters]
destination_dir: /posters
border_width: 26 # crops & re-applies this much; matches the TPDB 26 px standard
skip: false # holiday-only mode: when true, only runs on active-holiday days
border_colors: ["#ff7300"]
holidays:
- name: halloween
schedule: "range(10/01-10/31)"
colors: ["#FF6600", "#000000"]
poster_cleanarr:
mode: report
plex_path: "/plex-config/Library/Application Support/Plex Media Server/Metadata"
instances: [plex_main]
labelarr:
mappings:
- app_instance: sonarr_main
labels: [watched, favorite]
plex_instances:
- instance: plex_main
library_names: ["TV Shows"]
jduparr:
hash_database: /config/jduparr.db
source_dirs: [/media/movies, /media/tv]
nohl:
searches: 10
source_dirs:
- { path: /media/movies, mode: movie }
- { path: /media/tv, mode: series }
instances: [radarr_main, sonarr_main]
unmatched_assets:
instances: [radarr_main, sonarr_main, plex_main]
upgradinatorr:
instances_list:
- instance: radarr_main
count: 10
tag_name: chub-upgradinatorr
ignore_tag: ignore
search_mode: upgrade
renameinatorr:
rename_folders: true
count: 100
tag_name: chub-renameinatorr
instances: [radarr_main, sonarr_main]
health_checkarr:
report_only: false
instances: [radarr_main, sonarr_main, lidarr_main]
nestarr:
library_mappings:
- arr_instance: radarr_main
plex_instances:
- { instance: plex_main, library_names: [Movies] }
sync_gdrive:
gdrive_sa_location: /config/gdrive-sa.json
gdrive_list:
- id: "<google-drive-folder-id>"
location: /posters/gdrive-pullGlobal toggles. All editable from Settings → General.
general:
log_level: info # debug | info | warning | error
update_notifications: false # banner when a new CHUB release is out
max_logs: 9 # rotated log files kept per module
webhook_initial_delay: 30 # seconds to wait after an inbound webhook before acting
webhook_retry_delay: 60 # seconds between retries
webhook_max_retries: 3
webhook_secret: "" # empty = unauthenticated; set to require a shared secret
duplicate_exclude_groups: [] # duplicate group IDs the UI should hideIf webhook_secret is set, every inbound webhook must send X-Webhook-Secret: <secret> (or ?secret=<secret>). See Webhooks.
Managed by the web UI. Don't edit unless you're resetting things.
auth:
username: admin
password_hash: "$2b$12$..."
jwt_secret: "<random>"
token_expiry_hours: 24To reset the admin password, see First Run → Resetting the admin password.
Your Radarr, Sonarr, Lidarr, and Plex connections. The key under each service is the name you'll reference elsewhere in config.yml (radarr_main, sonarr_4k, etc.).
instances:
radarr:
radarr_main:
url: http://radarr:7878
api: <api_key>
enabled: true
sonarr:
sonarr_main:
url: http://sonarr:8989
api: <api_key>
lidarr:
lidarr_main:
url: http://lidarr:8686
api: <api_key>
plex:
plex_main:
url: http://plex:32400
api: <x_plex_token>Plex: the api field is the X-Plex-Token, not a Plex login. Finding your token.
About URLs: CHUB refuses to connect to cloud-metadata addresses or unrouteable ranges as a safety check. Use a normal IP or hostname your container can resolve — http://radarr:7878 works if CHUB and Radarr share a Docker network.
Testing: in Settings → Instances, each row has a Test button. Run it after adding or editing an entry.
One entry per module that should run on a schedule. Anything not listed here is manual-only (triggered by you from the dashboard, or by a webhook).
schedule:
poster_renamerr:
type: cron
expression: "0 */4 * * *" # every 4 hours
jduparr:
type: interval
minutes: 720 # every 12 hourstype is either cron (with expression) or interval (with minutes). Settings → Schedule has a form that writes this for you.
A built-in system health probe runs every 6 hours on its own; you don't configure it.
One entry per module that should send notifications, plus an optional main entry for global notifications.
notifications:
main:
discord:
enabled: true
webhook: https://discord.com/api/webhooks/...
poster_renamerr:
discord:
enabled: true
webhook: https://discord.com/api/webhooks/...
mention_role: "123456789"
upgradinatorr:
apprise:
enabled: true
url: "discord://..."
health_checkarr:
email:
enabled: true
from: chub@example.com
to: [you@example.com]
smtp_host: smtp.example.com
smtp_port: 587
username: chub
password: <smtp_password>Discord, Email, and Apprise are supported. Apprise's URL format covers dozens of other services — see the Apprise README for the catalog.
user_interface:
theme: dark # light | darkServer-wide default. Each browser also remembers its own choice, so toggling the theme in the header sticks on that device.
When CHUB returns your config to the UI, it replaces these fields with ******** so they don't leak into browser storage or screenshots:
-
api,api_key -
access_token,refresh_token,token,client_secret -
password_hash,jwt_secret,webhook_secret
When you save config back through the UI, any field still equal to ******** is kept as-is — so editing non-sensitive fields won't wipe your API keys.
The container log prints which field failed validation. Either fix the field or remove the bad section and restart — CHUB falls back to defaults for anything missing.
docker compose logs chubSee Troubleshooting for common failures.