Configuration
Roombarr is configured through a single YAML file at /config/roombarr.yml. It validates the entire config at startup and refuses to start if anything is invalid.
Config file shape
Section titled “Config file shape”dry_run: trueservices: { ... }schedule: "0 3 * * *"performance: { ... }audit: { ... }rules: [...]dry_run
Section titled “dry_run”Defaults to true, making Roombarr safe to deploy out of the box. When true, Roombarr evaluates every rule and logs what it would do, but never calls Radarr or Sonarr APIs to perform actions. Set to false only after reviewing your evaluation results.
dry_run: falseServices
Section titled “Services”The services block tells Roombarr how to connect to your *arr stack. Each service needs a base_url and an api_key.
Required: At least one of radarr or sonarr.
Optional: jellyfin and jellyseerr are enrichment services — only needed if your rules reference their fields.
services: radarr: base_url: http://radarr:7878 # Settings → General → API Key api_key: your-radarr-api-key
sonarr: base_url: http://sonarr:8989 api_key: your-sonarr-api-key
jellyfin: base_url: http://jellyfin:8096 # Dashboard → API Keys api_key: your-jellyfin-api-key
jellyseerr: base_url: http://jellyseerr:5055 # Settings → General → API Key api_key: your-jellyseerr-api-keyIf Roombarr and your services are on the same Docker network, use Docker service names as the URL (e.g., http://radarr:7878). No trailing slash.
If a rule references a field from an unconfigured service, Roombarr will refuse to start and tell you exactly which service is missing.
Schedule
Section titled “Schedule”Required. Standard 5-field cron expression (minute hour day month weekday). Evaluates in the timezone set by the TZ environment variable (defaults to UTC).
schedule: "0 3 * * *" # Daily at 3:00 AMYou can also trigger evaluations manually via the HTTP API.
Performance
Section titled “Performance”Optional. Controls the maximum number of concurrent API requests to external services.
performance: concurrency: 10 # 1–50, default: 10Optional. Every action decision is logged to daily-rotated JSONL files in the /config volume.
audit: retention_days: 90 # 1–3650, default: 90Rules are the core of Roombarr. Each rule targets either radarr or sonarr, defines conditions using a composable AND/OR tree, and specifies an action.
Anatomy of a rule
Section titled “Anatomy of a rule”rules: - name: Delete fully watched old movies target: radarr action: delete conditions: operator: AND children: - field: jellyfin.watched_by_all operator: equals value: true - field: radarr.added operator: older_than value: 6moname— Human-readable label for logs and audit trail.target—radarr(evaluates per-movie) orsonarr(evaluates per-season).action—delete,unmonitor, orkeep. See Actions below.conditions— An AND/OR condition tree.
Targets
Section titled “Targets”| Target | Evaluates | On delete |
|---|---|---|
radarr | Each movie independently | Removes the movie and deletes files from disk |
sonarr | Each season independently | Deletes episode files for that season only |
Condition groups
Section titled “Condition groups”The top-level conditions is always a group with operator (AND/OR) and children.
# All children must matchconditions: operator: AND children: - field: radarr.monitored operator: equals value: false - field: radarr.added operator: older_than value: 1y# At least one child must matchconditions: operator: OR children: - field: jellyfin.watched_by_all operator: equals value: true - field: radarr.added operator: older_than value: 2yLeaf conditions
Section titled “Leaf conditions”- field: radarr.year # Dotted field path operator: less_than # Comparison operator value: 2010 # Value to compare againstThe is_empty and is_not_empty operators must not include a value. All other operators require one.
Nesting groups
Section titled “Nesting groups”Children can be groups or leaves — nest to arbitrary depth for complex logic like “A AND (B OR C)“:
conditions: operator: AND children: - field: radarr.monitored operator: equals value: false - operator: OR children: - field: jellyfin.watched_by_all operator: equals value: true - field: radarr.added operator: older_than value: 2yWhen rules are skipped
Section titled “When rules are skipped”A rule is skipped for an item when the enrichment data it needs is missing — Roombarr won’t act on incomplete information.
- Missing item data — If Jellyfin has no data for a specific movie, rules referencing
jellyfin.*fields are skipped for that movie only. - Unreachable service — If Jellyfin is down, all items have null Jellyfin data and every rule referencing Jellyfin fields is skipped for that run.
Actions
Section titled “Actions”| Action | Description |
|---|---|
delete | Remove from Radarr/Sonarr and delete files from disk |
unmonitor | Stop monitoring for new downloads (files stay) |
keep | Explicitly protect this item from other rules (no-op) |
Conflict resolution
Section titled “Conflict resolution”When multiple rules match the same item, Roombarr uses least-destructive-wins:
keep > unmonitor > delete
This means you can write broad cleanup rules and add targeted keep rules to protect specific items — the keep rules always win. Rule order in the config file does not matter.
Config reload
Section titled “Config reload”Roombarr reads the config once at startup. To apply changes, restart the container. For example, with Docker Compose:
docker compose restart roombarrOther platforms (Unraid, TrueNAS, Portainer) have their own restart mechanisms — consult your platform’s docs.
Environment variables
Section titled “Environment variables”| Variable | Default | Description |
|---|---|---|
PUID | 1000 | User ID for file permissions — see Understanding PUID and PGID |
PGID | 1000 | Group ID for file permissions |
CONFIG_PATH | /config/roombarr.yml | Path to the YAML config file |
PORT | 3000 | HTTP server listen port |
TZ | (UTC) | Timezone for cron schedule evaluation (e.g., America/New_York) |
NODE_ENV | production | Controls log format. Set to development for pretty-printed logs. |
Validation
Section titled “Validation”Roombarr validates the entire config at startup. Beyond schema validation, it checks:
- At least one of
radarrorsonarris configured - Each rule’s
targetmatches a configured service - Enrichment services are configured if rules reference their fields
- Operators are compatible with the field types they’re applied to