update-n8n is a bash script that safely updates a self-hosted n8n instance running in Docker Compose. It backs up the current state, pulls the latest images, restarts services, and verifies everything is healthy before finishing.
n8n is an open-source workflow automation platform. Self-hosting gives you full control over your data and integrations. This tool keeps your instance up to date.
Learn about n8nThe problem
Updating a Docker Compose service is straightforward in theory: pull the new image, restart the container. In practice, you want to back up first, verify the new container is healthy, and clean up old images. Doing this manually every time means remembering the right sequence of commands and hoping you don’t skip a step when you’re in a hurry.
n8n releases frequently. If you’re self-hosting, falling behind on updates means missing bug fixes, security patches, and new node types. A repeatable update process removes the friction and makes it easy to stay current.
How it works
The script runs from the directory containing your docker-compose.yml. It follows a strict sequence: verify prerequisites, back up, stop, pull, start, verify health. If any step fails, the script exits immediately (set -e) so you can investigate before things get worse.
Before doing anything, it checks that Docker and Docker Compose are installed and that the compose file exists. It then asks for confirmation before proceeding.
Backups are timestamped tar archives stored in a ./backups/ directory. After the backup, the script stops all services, pulls the latest images from the registry, and starts everything back up. It waits for containers to initialize and then checks that they report as running. It also attempts to print the new n8n version for confirmation.
Usage
# Navigate to your n8n Docker Compose directory
cd /path/to/n8n-docker-caddy
# Run the update script
./update-n8n.sh
The script is interactive. It prompts for confirmation before updating, and optionally offers to show recent logs and clean up old Docker images when finished.
What it does step by step
- Verifies
docker-compose.ymlexists in the current directory - Checks that
dockeranddocker composeare available - Asks for user confirmation
- Creates
./backups/directory if it doesn’t exist - Backs up
docker-compose.ymlto a timestamped tar archive - Stops all services with
docker compose down - Pulls latest images with
docker compose pull - Starts services with
docker compose up -d - Waits 10 seconds for initialization
- Verifies containers are running and prints n8n version
- (Optional) Displays the last 20 lines of logs
- (Optional) Prunes old Docker images
Configuration
Two variables at the top of the script control its behavior:
| Variable | Default | Description |
|---|---|---|
COMPOSE_FILE | docker-compose.yml | Path to your Docker Compose file |
BACKUP_DIR | ./backups | Directory for storing timestamped backups |
The script also includes commented-out lines for backing up local n8n data volumes. Uncomment and adjust the paths if your setup stores data in a local directory rather than a Docker volume.
Error handling
- set -e — the script exits immediately if any command fails, preventing partial updates
- Pre-flight checks — validates Docker, Docker Compose, and the compose file before starting
- Trap handler — catches
SIGINTandSIGTERM(Ctrl+C) and exits cleanly - Health verification — checks container status after restart and exits with an error if services aren’t running
Why we built it
We self-host n8n to keep full control over our automation workflows and data. Updates are important but easy to put off when the process is manual. This script reduces the whole update to a single command with built-in safety checks, so there’s no excuse to fall behind on releases.
It’s intentionally simple. No package manager, no external dependencies beyond Docker. Copy the script into your n8n directory and run it when a new version drops.