Skip to content
Migration Tool

Migration Tool

Overview

Watchtower includes a notify-upgrade command to help convert legacy notification configurations to Shoutrrr URLs for use with the NOTIFICATION URL.

It parses legacy Watchtower notification configurations and outputs Shoutrrr URLs to a temporary file inside the Watchtower container.

Usage

The notify-upgrade command converts legacy Watchtower notification configurations into Shoutrrr URLs and writes them to a temporary file inside the container.

Running the Command

The notify-upgrade can be run either against a Watchtower container that is already running or as a single-run instance that allows you to convert a Docker Compose configuration or Docker CLI flag / environment variable configuration.

Existing Deployment

If Watchtower is already deployed and running with your legacy notification configuration, you can execute notify-upgrade directly inside the container:

docker exec watchtower /watchtower notify-upgrade

This works because the Watchtower binary is installed at /watchtower and notify-upgrade is a built-in subcommand. The common mistake is running docker exec watchtower notify-upgrade, which fails because notify-upgrade is not a standalone executable in $PATH.

Running notify-upgrade inside an existing container does not stop or restart the main Watchtower process. docker exec runs a separate, short-lived process. The only side effect is that the notify-upgrade process will stay alive for up to 5 minutes while waiting for you to retrieve the temporary file, after which it cleans up and exits.

Single-Use Run

If you have not yet deployed Watchtower or if you want to run notify-upgrade as a one-off command without starting the persistent Watchtower update loop, then run a temporary container configured with notify-upgrade as the command.

services:
  watchtower:
    image: nickfedor/watchtower:latest
    command: notify-upgrade
    environment:
      WATCHTOWER_NOTIFICATIONS: email
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER: smtp.example.com
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: 587
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: user@example.com
      WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: secret
      WATCHTOWER_NOTIFICATION_EMAIL_FROM: sender@example.com
      WATCHTOWER_NOTIFICATION_EMAIL_TO: recipient@example.com
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
Replace the example environment variables with your own legacy notification configuration. The notify-upgrade command inspects the container’s current configuration, so it must be started with your legacy notification settings.

Retrieving the Generated File

After running notify-upgrade, the converted Shoutrrr URL is written to a temporary file in the container’s working directory, with a filename like watchtower-notif-urls-XXXXXX.

The command logs the exact container path and prints a copy command, for example:

INFO To get the environment file, use: docker cp abc123:watchtower-notif-urls-123456789 ./watchtower-notifications.env

Copy it to your local machine with:

docker cp <CONTAINER>:<FILE_PATH> ./watchtower-notifications.env

The temporary file is automatically removed after 5 minutes or when the container stops, so copy it promptly after generation. If you are running notify-upgrade as a one-off command (docker run --rm ...), the process will wait up to 5 minutes before exiting.

Migration Walkthrough

Select the tab that matches your legacy notification service.

  1. Run the following Docker Compose configuration / Docker CLI command:
services:
    watchtower:
        image: nickfedor/watchtower:latest
        environment:
            WATCHTOWER_NOTIFICATIONS: email
            WATCHTOWER_NOTIFICATION_EMAIL_SERVER: smtp.example.com
            WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT: 587
            WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER: user@example.com
            WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD: secret
            WATCHTOWER_NOTIFICATION_EMAIL_FROM: sender@example.com
            WATCHTOWER_NOTIFICATION_EMAIL_TO: recipient@example.com
        volumes:
        - /var/run/docker.sock:/var/run/docker.sock
  1. With the container running, execute the notify-upgrade command:
docker exec watchtower /watchtower notify-upgrade

Then copy the resulting file out of the container:

docker cp <CONTAINER>:<FILE_PATH> ./watchtower-notifications.env
  1. The following converted Shoutrrr URL should be produced:
smtp://user@example.com:secret@smtp.example.com:587/?fromaddress=sender@example.com&toaddresses=recipient@example.com&encryption=ExplicitTLS&usestarttls=yes
  1. Replace the deprecated configuration with the coverted Shoutrrr URL:
services:
    watchtower:
        image: nickfedor/watchtower:latest
        environment:
            WATCHTOWER_NOTIFICATION_URL: smtp://user@example.com:secret@smtp.example.com:587/?fromaddress=sender@example.com&toaddresses=recipient@example.com&encryption=ExplicitTLS&usestarttls=yes
            WATCHTOWER_NOTIFICATIONS_DELAY: "10"
            WATCHTOWER_NOTIFICATION_TITLE_TAG: Watchtower
        volumes:
        - /var/run/docker.sock:/var/run/docker.sock
  • Avoid using unrecognized flags like WATCHTOWER_NOTIFICATION_EMAIL_SERVER_SSL, as they are ignored and may cause confusion.
  • Use the encryption and usestarttls URL parameters in the smtp:// URL to control TLS behavior rather than deprecated flags.

Automated Migration Script

If you have a docker-compose.yaml with a watchtower service configured for legacy notifications, you can use the script below to run the entire migration process end-to-end. It starts the container, executes notify-upgrade, extracts the generated file, prints its contents, and cleans up.

#!/usr/bin/env bash
set -euo pipefail

SERVICE="${1:-watchtower}"
OUTPUT="${2:-./watchtower-notifications.env}"

CONTAINER=$(docker compose run -d "${SERVICE}" notify-upgrade)

trap 'docker rm -f "${CONTAINER}" >/dev/null 2>&1 || true' EXIT

if ! docker ps -q --filter "id=${CONTAINER}" | grep -q .; then
    echo "notify-upgrade container exited before producing output. Logs:" >&2
    docker logs "${CONTAINER}" >&2 || true

    exit 1
fi

FILE=""
TIMEOUT=300
INTERVAL=2
ELAPSED=0

while [[ ${ELAPSED} -lt ${TIMEOUT} ]]; do
    FILE=$(docker logs "${CONTAINER}" 2>&1 | grep -oE 'watchtower-notif-urls-[^ ]+' | tail -1 || true)

    if [[ -n "${FILE}" ]]; then
        break
    fi

    sleep "${INTERVAL}"

    ELAPSED=$((ELAPSED + INTERVAL))
done

if [[ -z "${FILE}" ]]; then
    echo "Timed out waiting for notify-upgrade output. Logs:" >&2
    docker logs "${CONTAINER}" >/dev/null 2>&1 || true

    exit 1
fi

docker cp "${CONTAINER}:${FILE}" "${OUTPUT}"

echo "=== Generated Shoutrrr URL ==="
cat "${OUTPUT}"
  • The service must already be defined in docker-compose.yaml with your legacy notification environment variables. The script assumes the service name defaults to watchtower.
  • The command will self-cleanup after 5 minutes or when the script exits.
  • Slack channel customization is not preserved by notify-upgrade. The generated URL always uses the default webhook channel. If you need a custom channel, then manually edit the resulting Shoutrrr URL after migration.
Last updated on