Healarr
*Health Evaluation And Library Auto-Recovery for aRR
Healarr monitors your media library for corrupted files and automatically triggers re-downloads through Sonarr, Radarr, or Whisparr. It detects issues using ffprobe, MediaInfo, or HandBrake, then orchestrates the complete remediation workflow.

Features
- π Multi-Method Detection - ffprobe, MediaInfo, or HandBrake-based health checks
- π Automatic Remediation - Deletes corrupt files and triggers *arr search
- β
Verification - Confirms new downloads are healthy before marking resolved
- π Dashboard - Real-time stats, charts, and corruption type breakdown
- π Notifications - Discord, Slack, Telegram, Pushover, Gotify, ntfy, Email, webhooks
- π
Scheduled Scans - Cron-based automatic scanning
- π Webhook Integration - Scan files immediately when *arr downloads complete
- π¨ Modern UI - Dark/light themes, responsive design
- ποΈ Database Maintenance - Automatic pruning, integrity checks, and optimization
- βΏ Accessible UI - WCAG 2.1 AA compliant with keyboard navigation and screen reader support
- π‘οΈ Form Validation - Client-side validation with clear inline error messages
- π Observability - Prometheus metrics, request tracing, and database performance monitoring
Supported *arr Applications
| App |
Version |
API Style |
| Sonarr |
v3+ |
Series/Episodes |
| Radarr |
v3+ |
Movies |
| Whisparr |
v2 |
Series/Episodes (Sonarr-based) |
| Whisparr |
v3 |
Movies (Radarr-based) |
Installation
Option 1: Docker (Recommended)
Docker is the easiest way to run Healarr - all dependencies are included.
Docker Compose
services:
healarr:
image: ghcr.io/mescon/healarr:latest
container_name: healarr
restart: unless-stopped
init: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
ports:
- "3090:3090"
environment:
- TZ=Europe/London
volumes:
- /path/to/config:/config
- /path/to/media:/media:ro # Read-only access to your media
*π‘ Tip: Matching paths with your arr apps
If you mount media using the same internal path that Sonarr/Radarr uses, you won't need to configure path translation. For example, if Sonarr sees /tv, mount your media as -v /path/to/tv:/tv:ro and Healarr will see the same paths as Sonarr.
docker compose up -d
Docker Run
docker run -d \
--name healarr \
-p 3090:3090 \
-v /path/to/config:/config \
-v /path/to/media:/media:ro \
-e TZ=Europe/London \
ghcr.io/mescon/healarr:latest
Then open http://localhost:3090 and set up your password.
Option 2: Pre-built Binaries (Linux/Windows/macOS)
Download the latest release from GitHub Releases.
Prerequisites
You need at least one of these tools installed for health checking:
| Tool |
Linux |
Windows |
macOS |
| ffprobe (recommended) |
apt install ffmpeg |
ffmpeg.org |
brew install ffmpeg |
| MediaInfo |
apt install mediainfo |
mediaarea.net |
brew install mediainfo |
| HandBrakeCLI |
apt install handbrake-cli |
handbrake.fr |
brew install handbrake |
Linux
# Download and extract
wget https://github.com/mescon/Healarr/releases/latest/download/healarr-linux-amd64.tar.gz
tar -xzf healarr-linux-amd64.tar.gz
cd healarr
# Run (config directory created automatically)
./healarr
Run as a systemd service:
# Create service file
sudo tee /etc/systemd/system/healarr.service << 'EOF'
[Unit]
Description=Healarr Media Health Monitor
After=network.target
[Service]
Type=simple
User=healarr
Group=healarr
WorkingDirectory=/opt/healarr
ExecStart=/opt/healarr/healarr
Environment=HEALARR_DATA_DIR=/opt/healarr/config
Environment=HEALARR_LOG_LEVEL=info
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable --now healarr
Windows
- Download
healarr-windows-amd64.zip from Releases
- Extract to a folder (e.g.,
C:\Healarr)
- Install ffmpeg:
- Download from ffmpeg.org
- Extract and add the
bin folder to your PATH, or place ffprobe.exe in the same folder as healarr.exe
- Run
healarr.exe (or double-click)
- Open
http://localhost:3090 in your browser
Run as a Windows Service (optional):
Using NSSM:
nssm install Healarr C:\Healarr\healarr.exe
nssm set Healarr AppDirectory C:\Healarr
nssm set Healarr AppEnvironmentExtra HEALARR_DATA_DIR=C:\Healarr\config
nssm start Healarr
macOS
# Download and extract
curl -LO https://github.com/mescon/Healarr/releases/latest/download/healarr-darwin-amd64.tar.gz
tar -xzf healarr-darwin-amd64.tar.gz
cd healarr
# Install ffmpeg if not already installed
brew install ffmpeg
# Run
./healarr
For Apple Silicon (M1/M2/M3), download healarr-darwin-arm64.tar.gz instead.
Option 3: Build from Source
# Prerequisites: Go 1.25+, Node.js 22+
git clone https://github.com/mescon/Healarr.git
cd Healarr
# Build frontend
cd frontend && npm ci && npm run build && cd ..
# Build backend
go build -o healarr ./cmd/server
# Run
./healarr
# Linux AMD64
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o healarr-linux-amd64 ./cmd/server
# Linux ARM64 (Raspberry Pi 4, etc.)
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -o healarr-linux-arm64 ./cmd/server
# Windows AMD64
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -o healarr-windows-amd64.exe ./cmd/server
# macOS AMD64
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -o healarr-darwin-amd64 ./cmd/server
# macOS ARM64 (Apple Silicon)
GOOS=darwin GOARCH=arm64 CGO_ENABLED=0 go build -o healarr-darwin-arm64 ./cmd/server
Note: Building with CGO_ENABLED=0 uses pure-Go SQLite which is slightly slower but fully portable. The Docker image uses CGO for better performance.
Configuration
All configuration options can be set via environment variables or command-line flags. Command-line flags take precedence over environment variables.
Command-Line Flags
./healarr --help
| Flag |
Environment Variable |
Default |
Description |
--port |
HEALARR_PORT |
3090 |
HTTP server port |
--data-dir |
HEALARR_DATA_DIR |
./config |
Base directory for persistent data |
--database-path |
HEALARR_DATABASE_PATH |
{data-dir}/healarr.db |
Database file path |
--log-level |
HEALARR_LOG_LEVEL |
info |
Log level: debug, info, error |
--base-path |
HEALARR_BASE_PATH |
/ |
URL base path for reverse proxy |
--web-dir |
HEALARR_WEB_DIR |
auto-detect |
Web assets directory |
--dry-run |
HEALARR_DRY_RUN |
false |
Dry run mode (no files deleted) |
--retention-days |
HEALARR_RETENTION_DAYS |
90 |
Days to keep old data (0 = disable pruning) |
--max-retries |
HEALARR_DEFAULT_MAX_RETRIES |
3 |
Default max remediation attempts |
--verification-timeout |
HEALARR_VERIFICATION_TIMEOUT |
72h |
Max time to wait for file replacement |
--verification-interval |
HEALARR_VERIFICATION_INTERVAL |
30s |
Polling interval for verification |
--stale-threshold |
HEALARR_STALE_THRESHOLD |
24h |
Auto-fix items Healarr lost track of |
--arr-rate-limit |
HEALARR_ARR_RATE_LIMIT_RPS |
5 |
Max requests/second to *arr APIs |
--arr-rate-burst |
HEALARR_ARR_RATE_LIMIT_BURST |
10 |
Burst size for rate limiting |
--version / -v |
- |
- |
Print version and exit |
Examples:
# Run with custom port and debug logging
./healarr --port 8080 --log-level debug
# Disable automatic data pruning
./healarr --retention-days 0
# Run in dry-run mode (no files deleted)
./healarr --dry-run
Environment Variables (Docker)
For Docker deployments, environment variables are typically more convenient:
services:
healarr:
image: ghcr.io/mescon/healarr:latest
environment:
- TZ=Europe/London
- HEALARR_LOG_LEVEL=info
- HEALARR_RETENTION_DAYS=90
- HEALARR_DRY_RUN=false
Data Directory Structure
Healarr stores all persistent data in a config directory, making it easy to back up and mount as a Docker volume:
./config (or /config in Docker)
βββ healarr.db # SQLite database
βββ backups/ # Automatic database backups (every 6 hours, last 5 kept)
βββ logs/
βββ healarr.log # Application logs (auto-rotated, 100MB max, 7 days retention)
Database Maintenance
Healarr automatically maintains the SQLite database for optimal performance:
On Startup:
- Configures WAL mode for better concurrent access
- Enables incremental auto-vacuum to reclaim space
- Runs integrity check to detect corruption early
Daily Maintenance (3 AM local time):
- Prunes old events and scan history (configurable via
-retention-days)
- Removes orphaned corruption records
- Runs incremental vacuum to defragment
- Updates query planner statistics
- Checkpoints WAL to main database
Automatic Backups:
- Creates backup on startup
- Scheduled backups every 6 hours
- Keeps last 5 backups (older ones automatically deleted)
Docker: Mount a volume to /config:
volumes:
- ./config:/config
Bare-metal: The config directory is created next to the executable. Override with:
HEALARR_DATA_DIR=/opt/healarr/config ./healarr
Setting Up *arr Instances
- Go to Config β *arr Instances
- Click Add Instance
- Enter:
- Type: Sonarr / Radarr / Whisparr v2 / Whisparr v3
- Name: Friendly name
- URL: e.g.,
http://sonarr:8989
- API Key: From *arr Settings β General
- Click Test Connection, then Save
Setting Up Scan Paths
- Go to Config β Scan Paths
- Click Add Path
- Enter:
- Local Path: Path as Healarr sees it (e.g.,
/media/tv or /tv if you use the same paths as *arr)
- *arr Path: Path as your *arr sees it (e.g.,
/tv)
- *arr Instance: Select the matching instance
- Save and run your first scan!
π‘ Pro tip: If you mount media with the same path as your *arr apps (e.g., Sonarr sees /tv and you mount -v /host/tv:/tv:ro), set both Local Path and *arr Path to the same value. This eliminates path translation issues.
Webhook Integration (Recommended)
For instant scanning when downloads complete:
- In Healarr: Config β copy the webhook URL for your instance
- In Sonarr/Radarr: Settings β Connect β Add β Webhook
- Paste the URL, enable "On Import" and "On Upgrade"
- Save and test
Detection Methods
| Method |
Speed |
Accuracy |
Best For |
| ffprobe (default) |
Fast |
Good |
General use |
| MediaInfo |
Fast |
Good |
Metadata issues |
| HandBrake |
Slow |
Excellent |
Deep analysis |
Configure per scan path in Config.
Using Custom Binary Versions
The Docker image includes ffmpeg, MediaInfo, and HandBrake from Alpine packages. If you need newer versions (e.g., for specific codec support), you have two options:
Place custom binaries in a tools subdirectory of your config volume. You can either:
- Create a
tools folder inside your existing config directory, or
- Mount a separate directory containing your custom binaries:
volumes:
- /path/to/config:/config
# Mount a directory containing custom binaries (ffmpeg, ffprobe, etc.)
- /path/to/custom-binaries-folder:/config/tools
The mounted directory should contain the executable files directly (e.g., ffmpeg, ffprobe, mediainfo). Any executables in this directory automatically take precedence over system binaries.
Example: Using static ffmpeg builds
# Download static ffmpeg (includes ffprobe)
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
tar -xf ffmpeg-release-amd64-static.tar.xz
# Copy to your tools directory
mkdir -p /path/to/config/tools
cp ffmpeg-*-static/ffmpeg ffmpeg-*-static/ffprobe /path/to/config/tools/
Option 2: Environment Variables
Specify exact paths to binaries:
environment:
- HEALARR_FFPROBE_PATH=/custom/path/ffprobe
- HEALARR_FFMPEG_PATH=/custom/path/ffmpeg
- HEALARR_MEDIAINFO_PATH=/custom/path/mediainfo
- HEALARR_HANDBRAKE_PATH=/custom/path/HandBrakeCLI
| Variable |
Default |
Description |
HEALARR_FFPROBE_PATH |
ffprobe |
Path to ffprobe binary |
HEALARR_FFMPEG_PATH |
ffmpeg |
Path to ffmpeg binary |
HEALARR_MEDIAINFO_PATH |
mediainfo |
Path to mediainfo binary |
HEALARR_HANDBRAKE_PATH |
HandBrakeCLI |
Path to HandBrakeCLI binary |
Note: The Docker image (Alpine 3.23) includes ffmpeg 8.0.1, HandBrake 1.10.2, and MediaInfo 25.09. Custom binaries are only needed for specific requirements.
Notifications
Healarr can notify you about:
- New corruptions detected
- Remediation started/completed/failed
- Verification success/failure
- Scan completed
- *arr instance health changes (unhealthy/recovered)
- Stuck remediations that need attention
- User actions (corruption ignored)
Supported providers: Discord, Slack, Telegram, Pushover, Gotify, ntfy, Email (SMTP), Custom webhooks
Configure per-event filtering so you only receive the notifications that matter to you.
Reverse Proxy
Caddy
healarr.example.com {
reverse_proxy healarr:3090
}
nginx
location /healarr/ {
proxy_pass http://healarr:3090/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
Set HEALARR_BASE_PATH=/healarr when using a subpath.
Troubleshooting
Forgot Password
# Linux/macOS (adjust path as needed)
sqlite3 ./config/healarr.db "DELETE FROM settings WHERE key = 'password_hash';"
# Windows (using sqlite3.exe or DB Browser for SQLite)
sqlite3.exe C:\Healarr\config\healarr.db "DELETE FROM settings WHERE key = 'password_hash';"
Restart Healarr - you'll be prompted to set a new password.
Tip: Healarr displays tool availability in Config β About and Help β About. A warning banner appears when required tools are missing.
Linux: Install via package manager:
# Debian/Ubuntu
sudo apt install ffmpeg mediainfo
# RHEL/Fedora
sudo dnf install ffmpeg mediainfo
# Arch
sudo pacman -S ffmpeg mediainfo
Windows: Ensure the tools are in your PATH or in the same directory as healarr.exe.
macOS:
brew install ffmpeg mediainfo
Whisparr Version Mismatch
If you get API errors with Whisparr, check your version:
- Whisparr v2.x β Select "Whisparr v2 (Sonarr-based)"
- Whisparr v3.x β Select "Whisparr v3 (Radarr-based)"
Path Not Found
Ensure your scan path's "Local Path" matches how Healarr sees the files (check your volume mounts).
License
GNU General Public License v3.0 - see LICENSE
Acknowledgments