Skip to content

mescon/Healarr

Repository files navigation

Healarr Logo 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.

License Go Version React CodeRabbit PR Reviews codecov Snyk Security Quality Gate Status

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

  1. Download healarr-windows-amd64.zip from Releases
  2. Extract to a folder (e.g., C:\Healarr)
  3. 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
  4. Run healarr.exe (or double-click)
  5. 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

Cross-compile for different platforms:

# 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
- HEALARR_SCANNER_WORKERS auto Files scanned in parallel per scan. Default is tuned to available memory; set explicitly to override (1-32). env only
- HEALARR_SCANNER_SHUTDOWN_TIMEOUT 30s Grace period for in-flight scans to finish on shutdown (env only)
- HEALARR_SCANNER_ENUMERATION_TIMEOUT 30m Max time for the directory-walk phase before a scan aborts. Bounds a hang on a slow/unresponsive network mount; raise it for very large libraries on slow-but-working storage (env only)
--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

  1. Go to Config*arr Instances
  2. Click Add Instance
  3. Enter:
    • Type: Sonarr / Radarr / Whisparr v2 / Whisparr v3
    • Name: Friendly name
    • URL: e.g., http://sonarr:8989
    • API Key: From *arr Settings → General
  4. Click Test Connection, then Save

Setting Up Scan Paths

  1. Go to ConfigScan Paths
  2. Click Add Path
  3. 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
  4. 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.

🪟 Windows hosts: If your Sonarr/Radarr runs on Windows, it reports paths with backslashes and UNC roots (e.g. \\server\media\TV Shows). Set the *arr Path to that UNC form exactly as the *arr reports it, and the Local Path to wherever Healarr sees the same files (e.g. /media/TV Shows inside a Linux container). Healarr normalizes the separators between the two, so webhook scans, path matching, and auto-remediation all work across the \/ boundary — no manual conversion needed.

Webhook Integration (Recommended)

For instant scanning when downloads complete:

  1. In Healarr: Config → copy the webhook URL for your instance
  2. In Sonarr/Radarr: SettingsConnectAddWebhook
  3. Paste the URL, enable "On Import" and "On Upgrade"
  4. 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 jellyfin-ffmpeg 8, MediaInfo, and HandBrake CLI from Debian packages (the image base switched from Alpine to Debian-slim in v1.3.5 so the NVIDIA Container Toolkit's library injection works out of the box). If you need newer versions or a different build, you have two options:

Option 1: Tools Directory (Recommended)

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 (Debian Bookworm slim) includes jellyfin-ffmpeg 8.1, HandBrake CLI, and MediaInfo. Custom binaries are only needed for specific requirements.

Hardware Acceleration

Thorough scans decode video to detect mid-file corruption. By default that work runs on the CPU and pins one core per scan worker. For AV1, VP9, HEVC and H.264 you can offload the decode to your GPU and dramatically reduce scan time — a Fast triage preset against a 7,000-file AV1 library on an RTX 4070 finishes in minutes rather than hours.

Quick mode (the default for new paths) only reads container headers and does not benefit from hardware decode.

Codec coverage

Codec Hardware decode? Setup notes
H.264, HEVC, MPEG2, VC-1 yes Work via ffmpeg's -hwaccel flag alone on every vendor
AV1, VP9, VP8 yes (v1.3.5+) Healarr auto-selects the vendor-specific decoder (av1_cuvid / av1_qsv / VAAPI internal) because the software defaults (libdav1d, libvpx) have no hwaccel hooks

Healarr probes each file's codec with ffprobe and adds the correct -c:v override at scan time. You do not need to configure decoders per codec — just enable hardware acceleration globally or per scan path.

NVIDIA (CUDA / NVDEC)

Prerequisite: NVIDIA Container Toolkit installed on the host.

services:
  healarr:
    image: ghcr.io/mescon/healarr:latest
    runtime: nvidia
    environment:
      - NVIDIA_DRIVER_CAPABILITIES=all
      - NVIDIA_VISIBLE_DEVICES=all
      - HEALARR_HEALTH_CHECK_HWACCEL=auto   # auto-detects nvidia
    devices:
      - /dev/dri:/dev/dri
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    volumes:
      - ./config:/config
      - /path/to/media:/media:ro

Verify:

# Inside the container, cuda should be listed
docker exec healarr ffmpeg -hwaccels

# During a thorough scan, Healarr's ffmpeg should appear here
nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv

Intel iGPU (Quick Sync — QSV)

services:
  healarr:
    image: ghcr.io/mescon/healarr:latest
    environment:
      - HEALARR_HEALTH_CHECK_HWACCEL=qsv
    devices:
      - /dev/dri:/dev/dri
    volumes:
      - ./config:/config
      - /path/to/media:/media:ro

AV1 hardware decode on Intel iGPUs requires 12th-gen Core (Alder Lake) or later, or Intel Arc. Older iGPUs handle HEVC / H.264 / VP9 fine via QSV.

Intel iGPU and AMD GPU (VAAPI)

The universal Linux GPU decode path. Works on Intel HD Graphics, Intel Arc, and AMD RDNA GPUs.

services:
  healarr:
    image: ghcr.io/mescon/healarr:latest
    environment:
      - HEALARR_HEALTH_CHECK_HWACCEL=auto   # auto-detects vaapi when no NVIDIA card is present
    devices:
      - /dev/dri:/dev/dri
    volumes:
      - ./config:/config
      - /path/to/media:/media:ro

AV1 hardware decode on AMD requires RDNA 2 (RX 6000 series) or later. Older AMD GPUs handle HEVC / H.264 fine via VAAPI.

Per-scan-path overrides

The HEALARR_HEALTH_CHECK_HWACCEL env var is the global default. The Scan Paths panel under /config lets each path override the global with its own setting (auto, off, cuda, vaapi, qsv, or any specific accelerator). This is useful for mixed setups:

  • A local 4K AV1 library on a CUDA host: cuda with Fast triage preset
  • A remote SMB share scanned by the same Healarr instance: off with a longer timeout

Set HW accel per path in the UI under Settings → Scan Paths → expand row → Override scanning defaults.

Recommended presets

Preset Decodes Best for
Quick (default) container headers only Fast pre-screen, no GPU benefit
Fast triage first 60 seconds The killer preset when HW decode is enabled — most files scan in milliseconds
Deep scan full file, 30-min timeout Catches mid-file corruption, practical only with HW decode
Paranoid full file via HandBrake, software only When you don't trust ffmpeg's tolerance

Set the preset per scan path in Settings → Scan Paths → Apply preset.

Safety net

If a hardware decoder fails in a way that suggests the GPU runtime is broken (SIGSEGV, Cannot load libcuda, "Failed to setup hwaccel", etc.) Healarr automatically retries the same file with hardware acceleration disabled. A broken driver / missing library / decoder crash can never trigger a false-positive corruption flag, so no file gets routed to remediation because of a GPU issue. The retry costs one extra ffmpeg invocation per affected file in the worst case.

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.

ffprobe/MediaInfo Not Found

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

About

Health Evaluation And Library Auto-Recovery for *arr - Media library corruption detection and automatic remediation

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors