homelab-blueprint/docs/WATCHTOWER.md
Claude 785f9d53c4 fix: resolve Emby/Bazarr health checks and Watchtower notification errors
Fixed three critical issues reported by user:

1. Emby health check failing:
   - Changed from non-existent /health endpoint to /web/index.html
   - Increased retries to 5 and start_period to 120s
   - Using wget --spider for lightweight check

2. Bazarr health check failing:
   - Changed from /api/system/status (requires auth) to root path /
   - Increased retries to 5 and start_period to 90s
   - Using wget --spider for lightweight check

3. Watchtower Discord notification error:
   - Error: "unknown service 'https'" when using Discord webhooks
   - Added comprehensive Discord setup guide (docs/WATCHTOWER.md)
   - Updated .env.sample with proper Shoutrrr URL format examples
   - Documented conversion from Discord webhook to Shoutrrr format:
     * Wrong: https://discord.com/api/webhooks/ID/TOKEN
     * Correct: discord://TOKEN@ID

Documentation updates:
- Created docs/WATCHTOWER.md (comprehensive guide)
  * Discord webhook setup with step-by-step instructions
  * Other notification services (Slack, Email, Telegram, etc.)
  * Troubleshooting common notification errors
  * Advanced configuration examples
- Updated README.md with Watchtower troubleshooting section
- Added WATCHTOWER.md to documentation index

Health check improvements:
- Both services now use wget instead of curl for consistency
- Increased start_period to allow proper initialization
- Increased retries for better resilience
- Using lightweight --spider checks

Fixes: Emby/Bazarr containers unhealthy despite running correctly
Fixes: Watchtower crashes with Discord notification URL format error
Tested: YAML validation passed, health check endpoints verified
2025-11-23 15:19:24 +00:00

6.7 KiB

Watchtower Configuration Guide

Watchtower automatically updates your Docker containers when new images are available.

Table of Contents

Basic Configuration

Schedule

Set update schedule in .env using cron format:

# Daily at 4 AM
WATCHTOWER_SCHEDULE=0 0 4 * * *

# Every Sunday at 3 AM
WATCHTOWER_SCHEDULE=0 0 3 * * SUN

# Every 6 hours
WATCHTOWER_SCHEDULE=0 0 */6 * * *

Cron format: second minute hour day month weekday

Disable Notifications

Leave the notification URL empty to run without notifications:

WATCHTOWER_NOTIFICATION_URL=

Discord Notifications

Step 1: Create Discord Webhook

  1. Open Discord and go to your server
  2. Click Server Settings (gear icon)
  3. Go to IntegrationsWebhooks
  4. Click New Webhook or Create Webhook
  5. Configure:
    • Name: Watchtower
    • Channel: Select where notifications should go
  6. Click Copy Webhook URL

You'll get a URL like:

https://discord.com/api/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN

Step 2: Convert to Shoutrrr Format

IMPORTANT: Do NOT use the Discord URL directly. You must convert it to Shoutrrr format.

Discord webhook URL format:

https://discord.com/api/webhooks/WEBHOOK_ID/TOKEN

Convert to Shoutrrr format:

discord://TOKEN@WEBHOOK_ID

Example:

Discord webhook:

https://discord.com/api/webhooks/WEBHOOK_ID/WEBHOOK_TOKEN

Shoutrrr format (what you put in .env):

WATCHTOWER_NOTIFICATION_URL=discord://abcdefghijklmnopqrstuvwxyz-ABCDEFGHIJKLMNOPQRSTUVWXYZ@1234567890

Step 3: Update .env File

Edit your .env file:

WATCHTOWER_NOTIFICATION_URL=discord://YOUR_TOKEN@YOUR_WEBHOOK_ID
WATCHTOWER_SCHEDULE=0 0 4 * * *

Step 4: Restart Watchtower

docker-compose down watchtower
docker-compose up -d watchtower

Check logs to verify:

docker logs watchtower

You should see:

Watchtower 1.x.x
Using notifications: discord

Discord Notification Customization

Add parameters to customize notifications:

# Add username
discord://TOKEN@WEBHOOK_ID?username=Watchtower

# Add avatar
discord://TOKEN@WEBHOOK_ID?avatar=https://i.imgur.com/xyz.png

# Combine parameters
discord://TOKEN@WEBHOOK_ID?username=Watchtower&avatar=https://i.imgur.com/xyz.png

Other Notification Services

Slack

WATCHTOWER_NOTIFICATION_URL=slack://TOKEN@CHANNEL

Email (SMTP)

WATCHTOWER_NOTIFICATION_URL=smtp://username:password@host:port/?fromAddress=from@example.com&toAddresses=to@example.com

Telegram

WATCHTOWER_NOTIFICATION_URL=telegram://TOKEN@telegram?channels=CHANNEL_ID

Pushover

WATCHTOWER_NOTIFICATION_URL=pushover://shoutrrr:TOKEN@USER_KEY/?devices=DEVICE1,DEVICE2

Multiple Services

Send to multiple services by separating with space:

WATCHTOWER_NOTIFICATION_URL=discord://TOKEN@WEBHOOK_ID slack://TOKEN@CHANNEL

For complete list: https://containrrr.dev/shoutrrr/v0.8/services/overview/

Troubleshooting

Error: "unknown service 'https'"

Problem: You're using the Discord webhook URL directly instead of converting to Shoutrrr format.

Wrong:

WATCHTOWER_NOTIFICATION_URL=https://discord.com/api/webhooks/1234567890/abcdefg

Correct:

WATCHTOWER_NOTIFICATION_URL=discord://abcdefg@1234567890

Error: "Failed to initialize Shoutrrr notifications"

Possible causes:

  1. Wrong URL format
  2. Invalid token or webhook ID
  3. Webhook was deleted in Discord

Solution:

  1. Verify webhook still exists in Discord
  2. Double-check the format: discord://TOKEN@WEBHOOK_ID
  3. Ensure no extra spaces or quotes
  4. Check logs: docker logs watchtower

Notifications Not Arriving

Check:

  1. Watchtower is actually running: docker ps | grep watchtower
  2. Webhook URL is correct in .env
  3. Discord webhook is active (test in Discord settings)
  4. Check Watchtower logs for errors: docker logs watchtower

Test Notifications

Watchtower only sends notifications when:

  • Container updates are found
  • Updates are applied
  • Errors occur during updates

To test, you can:

  1. Pull an older image version: docker pull image:old-tag
  2. Tag it as latest: docker tag image:old-tag image:latest
  3. Wait for Watchtower to run
  4. It should detect and update, sending notification

Or trigger manual run:

docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e WATCHTOWER_NOTIFICATION_URL="discord://TOKEN@WEBHOOK_ID" \
  containrrr/watchtower \
  --run-once \
  --cleanup

Advanced Configuration

Scope to Specific Containers

Only monitor containers matching scope:

WATCHTOWER_SCOPE=media-stack

Then label containers:

labels:
  - "com.centurylinklabs.watchtower.scope=media-stack"

Label-Based Filtering

Only monitor containers with specific label:

WATCHTOWER_LABEL_ENABLE=com.centurylinklabs.watchtower.enable

Then add to containers you want monitored:

labels:
  - "com.centurylinklabs.watchtower.enable=true"

Monitor-Only Mode

Check for updates without applying them:

environment:
  WATCHTOWER_MONITOR_ONLY: "true"

You'll get notifications about available updates, but containers won't be updated automatically.

Security Best Practices

  1. Use socket-proxy (already configured in arr-stack)

    • Limits Watchtower's Docker API access
    • Only grants necessary permissions
  2. Scope or label filtering

    • Prevent Watchtower from updating critical services
    • Use WATCHTOWER_SCOPE or WATCHTOWER_LABEL_ENABLE
  3. Exclude critical containers

    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    
  4. Run at off-peak hours

    WATCHTOWER_SCHEDULE=0 0 3 * * *  # 3 AM daily
    
  5. Enable notifications

    • Know when updates happen
    • Get alerts on failures

Examples

Minimal Setup (No Notifications)

WATCHTOWER_SCHEDULE=0 0 4 * * *
WATCHTOWER_NOTIFICATION_URL=

Production Setup (Discord + Scoped)

WATCHTOWER_SCHEDULE=0 0 3 * * SUN
WATCHTOWER_NOTIFICATION_URL=discord://TOKEN@WEBHOOK_ID?username=Watchtower
WATCHTOWER_SCOPE=media-stack

Monitor-Only (Test Updates)

WATCHTOWER_SCHEDULE=0 0 4 * * *
WATCHTOWER_NOTIFICATION_URL=discord://TOKEN@WEBHOOK_ID
WATCHTOWER_MONITOR_ONLY=true

References