J2897 icon

update_n8n_mega

J2897 | PRO | 09/11/24 02:18:57 AM UTC (Edited) | 0 ⭐ | 978 👁️ | Never ⏰ | []
Bash |

6.8 KB

|

None

|

0 👍

/

0 👎

#!/usr/bin/bash
 
# Automatic Update and Backup Script for n8n
# ==========================================
# This script checks for updates to the n8n Docker image and updates it if a newer version is available.
# It also performs a backup of critical n8n data files before updating and uploads the backup to a MEGA cloud storage.
#
# The script uses Docker to compare the latest image digest from Docker Hub with the currently running image.
# If an update is available, it stops the running container, backs up the database and configuration files,
# uploads these backups to a local directory and MEGA, and then starts a new container with the updated image.
#
# Dependencies:
#   - Docker
#   - MEGA Command-Line Interface (mega-put)
#
# Usage:
#   Simply run the script to check for updates, back up data, and update the n8n container if a newer version is available.
#
# To automate this script to run weekly, you can add it as a cron job. Here's how:
#   1. Open the crontab editor by running the command `crontab -e` in your terminal.
#   2. Add the following line to the end of the file: `0 18 * * 1 /path/to/update_n8n.sh`
#   3. Replace `/path/to/update_n8n.sh` with the actual path to this script.
#   4. Save and exit the editor.
#
# This will schedule the script to run every Monday at 6pm. You can adjust the schedule as needed by modifying the cron expression.
#
# Here's a breakdown of the cron expression:
#   - `0 18 * * 1`: This means "run at minute 0, hour 18 (6pm), every day of the month, every month, on Monday (day of the week 1)".
#
# Backup Details:
#   - Backups are stored locally in the specified directory and also uploaded to MEGA cloud storage.
#   - Ensure that the MEGA CLI is set up and authenticated on your system before running the script.
 
# Variables
IMAGE='n8nio/n8n'  # The Docker image
CONTAINER_NAME='n8n'
 
# Backup locations
BACKUP_DIR="/home/J2897/Backups/n8n"   # Local backup directory (ensure this exists)
MEGA_REMOTE_DIR="/Backups/n8n"  # Remote MEGA backup directory
 
# Volume name (ensure this matches your Docker volume name)
VOLUME_NAME='n8n_data'
 
# Temporary mount point for the volume within the user's home directory
TEMP_MOUNT="/home/J2897/n8n_data_temp"
 
# Function to check if the container is running
is_container_running() {
  docker ps -q --filter "name=$CONTAINER_NAME" | grep -q .
}
 
# Function to check if the container exists
is_container_exist() {
  docker ps -a -q --filter "name=$CONTAINER_NAME" | grep -q .
}
 
# Function to get the latest image digest from Docker Hub
get_latest_image_digest() {
  docker pull $IMAGE > /dev/null 2>&1
  docker inspect --format='{{index .RepoDigests 0}}' $IMAGE | awk -F@ '{print $2}'
}
 
# Function to get the current running image's digest
get_current_image_digest() {
  if is_container_running; then
    docker inspect --format='{{.Image}}' $(docker ps -q --filter "name=$CONTAINER_NAME") | xargs docker inspect --format='{{index .RepoDigests 0}}' | awk -F@ '{print $2}'
  else
    echo ""
  fi
}
 
# Function to back up n8n's database and config files from the volume
backup_n8n_data() {
  echo "$(date) - Starting backup of n8n data..."
 
  # Create the mount point with proper permissions
  mkdir -p $TEMP_MOUNT || { echo "$(date) - Error: Could not create temporary mount directory." >&2; exit 1; }
 
  # Stop the running n8n container if it's running
  if is_container_running; then
    echo "$(date) - Stopping n8n container..."
    docker stop $CONTAINER_NAME || { echo "$(date) - Error: Failed to stop n8n container." >&2; exit 1; }
  else
    echo "$(date) - Container $CONTAINER_NAME is not running; proceeding without stopping."
  fi
 
  # Mount the n8n volume to the temporary directory with user permissions
  echo "$(date) - Mounting n8n volume and copying data..."
  docker run --rm -v $VOLUME_NAME:/data -v $TEMP_MOUNT:/mnt --user $(id -u):$(id -g) busybox sh -c "cp -r /data/. /mnt/" || { echo "$(date) - Error: Failed to copy data from volume." >&2; docker start $CONTAINER_NAME; exit 1; }
 
  # Check for existence and try copying the specific files to the backup directory
  if [ -f "$TEMP_MOUNT/database.sqlite" ] && [ -f "$TEMP_MOUNT/config" ]; then
    echo "$(date) - Copying database.sqlite and config to backup directory..."
    cp $TEMP_MOUNT/database.sqlite $BACKUP_DIR/database.sqlite || { echo "$(date) - Error: Failed to copy database.sqlite." >&2; }
    cp $TEMP_MOUNT/config $BACKUP_DIR/config || { echo "$(date) - Error: Failed to copy config." >&2; }
    echo "$(date) - Files copied successfully."
 
    # Backup the files to MEGA
    echo "$(date) - Uploading files to MEGA..."
    mega-put -c $BACKUP_DIR/database.sqlite $MEGA_REMOTE_DIR/ || { echo "$(date) - Error: Failed to upload database.sqlite to MEGA." >&2; }
    mega-put -c $BACKUP_DIR/config $MEGA_REMOTE_DIR/ || { echo "$(date) - Error: Failed to upload config to MEGA." >&2; }
    echo "$(date) - Files uploaded to MEGA successfully."
  else
    echo "$(date) - Error: Backup files not found in the mounted directory. Aborting backup." >&2
    ls -l $TEMP_MOUNT # List contents to debug
    rm -rf $TEMP_MOUNT
    docker start $CONTAINER_NAME
    exit 1
  fi
 
  # Clean up the temporary mount point
  echo "$(date) - Cleaning up temporary mount directory..."
  rm -rf $TEMP_MOUNT || { echo "$(date) - Error: Could not remove temporary mount directory." >&2; }
 
  # # Check if a stopped container exists with the same name, remove it
  if is_container_exist; then
    echo "$(date) - Removing existing stopped n8n container..."
    docker rm $CONTAINER_NAME || { echo "$(date) - Error: Failed to remove existing stopped container." >&2; exit 1; }
  fi
}
 
# Get the latest digest from the repository
LATEST_DIGEST=$(get_latest_image_digest)
 
# Get the currently running image's digest
CURRENT_DIGEST=$(get_current_image_digest)
 
# Check if the digests are different, indicating an update is needed
if [ -n "$CURRENT_DIGEST" ] && [ "$LATEST_DIGEST" != "$CURRENT_DIGEST" ]; then
  echo "$(date) - A newer version of n8n is available. Updating..."
 
  # Backup n8n data before updating
  backup_n8n_data
 
  # Pull the latest image and start the updated container
  docker pull $IMAGE || { echo "$(date) - Error: Failed to pull the latest n8n image." >&2; exit 1; }
  
  # Start a new instance of the n8n container
  echo "$(date) - Starting new n8n container..."
  docker run -d --name $CONTAINER_NAME -p 5678:5678 \
    -e GENERIC_TIMEZONE="Europe/London" -e TZ="Europe/London" \
    -v $VOLUME_NAME:/home/node/.n8n $IMAGE || { echo "$(date) - Error: Failed to start a new n8n container." >&2; exit 1; }
  
  echo "$(date) - Update complete."
else
  echo "$(date) - n8n is up to date."
fi
 
# Optional: Clean up unused Docker resources
# docker image prune -f
# docker volume prune -f
# docker container prune -f
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎