Maintainerr Setup Guide - ajgillis04/GillisDockerDepot GitHub Wiki
Maintainerr is an automated media cleanup tool that integrates with Plex, Sonarr, Radarr, and Seerr/Overseerr. It uses rule-based logic to identify stale or unwatched content and supports dry-run auditing, tagging, and safe deletion workflows.
- Copy the
maintainerr.yamltemplate into your active server compose directory:
cp compose/templates/maintainerr.yaml compose/server1/maintainerr.yaml- Ensure your root
.envincludes your designated port setting:
MAINTAINERR_PORT=6246
- Create host storage directories and set proper non-root ownership permissions (
1000:100or your host user UID:GID):
sudo mkdir -p ${DOCKERDIR}/maintainerr/data ${DOCKERDIR}/logs/maintainerr
sudo chown -R 1000:100 ${DOCKERDIR}/maintainerr ${DOCKERDIR}/logs/maintainerr- Launch the container:
docker compose -p mediaserver -f docker-compose-server1.yaml up -d maintainerr
⚠️ Important Permission Notice: SetPUIDandPGIDto match a valid user/group on the host. Runid <your-user>to confirm, andchown -Rthe mounted volumes accordingly. Maintainerr v2+ does not run as root and will crash-loop without proper volume permissions.
# Maintainerr - Automated media cleanup and maintenance
services:
maintainerr:
container_name: maintainerr.${HOST_NAME}
hostname: maintainerr.${HOST_NAME}.lan
image: ghcr.io/jorenn92/maintainerr:latest
environment:
PUID: ${PUID}
PGID: ${PGID}
TZ: ${TZ}
DOMAINNAME: ${DOMAINNAME}
HOST_NAME: ${HOST_NAME}.lan
networks:
- mediaserver
ports:
- "${MAINTAINERR_PORT}:6246"
volumes:
- ${DOCKERDIR}/maintainerr/data:/opt/data
- ${DOCKERDIR}/logs/maintainerr:/var/log
restart: unless-stopped
security_opt:
- no-new-privileges:true
labels:
- "com.centurylinklabs.watchtower.enable=true"
- "homepage.group=Media"
- "homepage.name=Maintainerr"
- "homepage.icon=maintainerr.png"
- "homepage.href=https://maintainerr.${DOMAINNAME}/"
- "homepage.description=Automated media cleanup and maintenance"- Open your browser and navigate to
http://<your-ip-address>:6246. - Authenticate with your credentials if enabled.
- Navigate to Settings to begin integration setup.
Maintainerr supports direct integration with your media stack. Ensure all services are connected and authenticated.
- Go to Settings -> Plex.
- Enter your Plex server IP/hostname and port (
32400). - Paste your Plex token (found via
Settings -> Account -> Show Advanced). - Click Test Connection then Save.

- Go to Settings -> Radarr.
- Enter your Radarr host, port (
7878), and API key. - Click Test Connection then Save.

- Go to Settings -> Sonarr.
- Enter your Sonarr host, port (
8989), and API key. - Click Test Connection then Save.

- Go to Settings -> Overseerr.
- Enter your Seerr/Overseerr host, port (
5055), and API key. - Click Test Connection then Save.

- Go to Settings -> Tautulli.
- Enter your Tautulli host, port (
8181), and API key. - Click Test Connection then Save.

- Go to Settings -> Notifications.
- Choose your preferred service (e.g., Discord, Telegram, Gotify).
- Enter webhook or token details.
- Click Test Notification then Save.

Navigate to Rules in the left menu.
You can add tags in Radarr or Sonarr to ensure media is protected or included in rules:
- Use
list-importfor items imported from lists (add to your Import List settings). - Use
saveto protect specific items from deletion.


mediaType: SHOWS
rules:
- "0":
- firstValue: Overseerr.isRequested
action: EQUALS
customValue:
type: boolean
value: "true"
- operator: AND
firstValue: Sonarr.tags
action: NOT_CONTAINS_PARTIAL
customValue:
type: text
value: save
- "1":
- firstValue: Overseerr.isRequested
action: EQUALS
customValue:
type: boolean
value: "true"
- operator: AND
firstValue: Sonarr.status
action: EQUALS
customValue:
type: text
value: ended
- operator: AND
firstValue: Plex.sw_allEpisodesSeenBy
action: CONTAINS
lastValue: Overseerr.addUser
- operator: AND
firstValue: Plex.sw_lastWatched
action: BEFORE
customValue:
type: custom_days
value: "182"
- "2":
- firstValue: Overseerr.isRequested
action: EQUALS
customValue:
type: boolean
value: "true"
- operator: AND
firstValue: Plex.sw_viewedEpisodes
action: EQUALS
customValue:
type: number
value: 0
- operator: AND
firstValue: Plex.sw_lastEpisodeAddedAt
action: BEFORE
customValue:
type: custom_days
value: "182"
mediaType: MOVIES
rules:
- "0":
- firstValue: Overseerr.isRequested
action: EQUALS
customValue:
type: boolean
value: "true"
- operator: AND
firstValue: Plex.seenBy
action: CONTAINS
lastValue: Overseerr.addUser
- operator: AND
firstValue: Plex.lastViewedAt
action: BEFORE
customValue:
type: custom_days
value: "182"
- operator: AND
firstValue: Radarr.tags
action: NOT_CONTAINS_PARTIAL
customValue:
type: text
value: save
- "1":
- operator: OR
firstValue: Overseerr.isRequested
action: EQUALS
customValue:
type: boolean
value: "true"
- operator: AND
firstValue: Plex.viewCount
action: EQUALS
customValue:
type: number
value: 0
- operator: AND
firstValue: Plex.addDate
action: BEFORE
customValue:
type: custom_days
value: "730"
- operator: AND
firstValue: Radarr.tags
action: NOT_CONTAINS_PARTIAL
customValue:
type: text
value: save
- "2":
- operator: OR
firstValue: Radarr.tags
action: CONTAINS
customValue:
type: text
value: list-import
- operator: AND
firstValue: Plex.viewCount
action: EQUALS
customValue:
type: number
value: 0
- operator: AND
firstValue: Radarr.addDate
action: BEFORE
customValue:
type: custom_days
value: "730"
- operator: OR
firstValue: Plex.addDate
action: BEFORE
customValue:
type: custom_days
value: "730"
- operator: AND
firstValue: Radarr.tags
action: NOT_CONTAINS_PARTIAL
customValue:
type: text
value: save
- "3":
- operator: OR
firstValue: Radarr.tags
action: CONTAINS
customValue:
type: text
value: list-import
- operator: AND
firstValue: Plex.lastViewedAt
action: BEFORE
customValue:
type: custom_days
value: "730"
- operator: AND
firstValue: Radarr.tags
action: NOT_CONTAINS_PARTIAL
customValue:
type: text
value: saveUse cron expressions in Maintainerr settings to control execution times:
| Job Type | Cron Expression | Description |
|---|---|---|
| Rule Handler | 0 3 * * * |
Identifies media matching rules overnight |
| Collection Handler | 0 4 * * * |
Processes collections & safe deletions |
- Back up
${DOCKERDIR}/maintainerr/dataand${DOCKERDIR}/logs/maintainerrperiodically. - Ensure
maintainerr.dbandconfig.yamlare included.
- Deploy a new container using
maintainerr.yaml. - Copy backup files into the data folder:
sudo cp /path/to/backup/config.yaml ${DOCKERDIR}/maintainerr/data/config.yaml sudo cp /path/to/backup/maintainerr.db ${DOCKERDIR}/maintainerr/data/maintainerr.db
- Restart the container and verify rule integrity.
- Dry-run first: Test rules in Maintainerr before enabling live deletion.
-
Logs: Check
${DOCKERDIR}/logs/maintainerrfor rule execution and errors. - Permissions: Double-check UID/GID permissions if the container crashes on startup.