Menü schliessen
Created: November 10th 2024
Last updated: November 10th 2024
Categories: Docker,  Jitsi,  Linux
Author: Marcus Fleuti

[solved] Automated Jitsi Meet Docker Update Bash Script. Work smarter, not harder

Donation Section: Background
Monero Badge: QR-Code
Monero Badge: Logo Icon Donate with Monero Badge: Logo Text
82uymVXLkvVbB4c4JpTd1tYm1yj1cKPKR2wqmw3XF8YXKTmY7JrTriP4pVwp2EJYBnCFdXhLq4zfFA6ic7VAWCFX5wfQbCC

Introduction

Maintaining a Jitsi Meet installation can be challenging, especially when dealing with Docker containers and regular updates. In this comprehensive guide, we'll explore a powerful bash script that automates the entire Jitsi Meet update process, including backup creation, service management, and Docker image cleanup.

Why Automate Jitsi Meet Updates?

Jitsi Meet is a popular open-source video conferencing solution that many organizations rely on for their communication needs. When deployed using Docker, it requires regular updates to maintain security, stability, and access to new features. Manual updates can be time-consuming and error-prone, making automation essential for system administrators.

Key Features of the Update Script

  • Automated backup creation before updates
  • Graceful service shutdown and startup
  • Latest release download from GitHub
  • Interactive Docker image cleanup
  • Comprehensive error handling and logging
  • User-friendly progress updates

Script Components and Functionality

1. Utility Functions

The script begins with several utility functions that handle logging and error checking:

log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

check_error() {
    if [ $? -ne 0 ]; then
        log_message "ERROR: $1"
        exit 1
    fi
}

These functions ensure proper logging with timestamps and immediate error detection, making troubleshooting much easier.

2. Docker Image Management

One of the script's standout features is its sophisticated Docker image management system:

list_images() {
    echo "Current Docker Images:"
    echo "----------------------"
    docker image ls
    echo "----------------------"
}

The script includes interactive cleanup functionality that allows administrators to remove old images easily. Please be aware that the script DOES NOT create any backups of the repository images before deleting them. It asks the user for delete confirmation though:

Feature This Script Manual Updates Basic Scripts
Automated Backup Yes No Limited
Interactive Cleanup Yes No No
Error Handling Comprehensive Manual Basic

3. Update Process

The main update process follows these steps:

  1. Service shutdown using Docker Compose
  2. Complete system backup
  3. Latest release download and extraction
  4. File updates and cleanup
  5. Service restart with new images

Prerequisites

Before using the script, ensure your system meets these requirements:

  • Docker and Docker Compose installed
  • Existing Jitsi Meet installation in /opt/jitsi
    • The script is currently hardcoded to /opt/jitsi.
  • wget and unzip utilities
  • Sufficient disk space for backups
  • Root or sudo access

Implementation Guide

1. Script Installation

Script code

#!/bin/bash

# Function for timestamped echo
log_message() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

# Function to check if a command was successful
check_error() {
    if [ $? -ne 0 ]; then
        log_message "ERROR: $1"
        exit 1
    fi
}

# Function to handle cleanup on script exit
cleanup() {
    if [ ! -z "$SAVED_STTY" ]; then
        stty "$SAVED_STTY" 2>/dev/null || true
    fi
    tput cnorm  # Show cursor
}

# Function to list all docker images
list_images() {
    echo "Current Docker Images:"
    echo "----------------------"
    docker image ls
    echo "----------------------"
}

# Function to remove images by tag
remove_images() {
    local tags=("$@")
    
    if [ ${#tags[@]} -eq 0 ]; then
        log_message "No tags specified. Skipping cleanup..."
        return
    fi

    echo "The following images will be removed:"
    echo "------------------------------------"
    for tag in "${tags[@]}"; do
        docker image ls | grep "$tag" || true
    done
    echo "------------------------------------"

    read -p "Are you sure you want to proceed? (y/n): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        for tag in "${tags[@]}"; do
            log_message "Processing images with tag: $tag"
            # Get all image IDs matching the tag
            image_ids=$(docker images | grep "$tag" | awk '{print $3}')
            
            for id in $image_ids; do
                log_message "Stopping containers using image: $id"
                # Find and stop containers using this image
                containers=$(docker ps -a --filter ancestor="$id" -q)
                if [ ! -z "$containers" ]; then
                    docker stop $containers
                    docker rm $containers
                fi
                
                log_message "Removing image: $id"
                docker rmi -f "$id"
            done
        done
        log_message "Cleanup completed!"
    else
        log_message "Cleanup cancelled."
    fi
}

# Function to handle docker image cleanup
handle_image_cleanup() {
    # Save current terminal settings
    SAVED_STTY=$(stty -g)

    # Set up trap to handle cleanup on script exit
    trap cleanup EXIT

    # Hide cursor during tag input
    tput civis

    clear
    list_images

    echo "Enter one or more tags to remove (space-separated)"
    echo "Press ESC to cancel, or ENTER to confirm"

    # Initialize variables
    input=""
    char=""

    # Configure terminal for immediate input without requiring Enter
    stty -echo raw

    while true; do
        char=$(dd bs=1 count=1 2>/dev/null)
        
        # Check for ESC key (ASCII 27)
        if [ "$char" = $'\e' ]; then
            echo
            log_message "Cleanup cancelled."
            return
        fi
        
        # Check for Enter key
        if [ "$char" = $'\r' ] || [ "$char" = $'\n' ]; then
            echo
            break
        fi
        
        # Check for backspace (ASCII 127)
        if [ "$char" = $'\177' ]; then
            if [ ! -z "$input" ]; then
                input="${input%?}"
                echo -ne "\b \b"
            fi
        else
            # Add character to input and echo it
            input="${input}${char}"
            echo -n "$char"
        fi
    done

    # Reset terminal settings
    stty "$SAVED_STTY"

    # Show cursor again
    tput cnorm

    # Convert input string to array and remove images
    if [ ! -z "$input" ]; then
        read -ra tags <<< "$input"
        remove_images "${tags[@]}"
    else
        log_message "No tags entered. Skipping cleanup..."
    fi
}

# Main script starts here
log_message "Starting Jitsi update process..."

# Check if /opt/jitsi exists and is accessible
if [ ! -d "/opt/jitsi" ]; then
    log_message "ERROR: Directory /opt/jitsi does not exist"
    exit 1
fi

# Change to Jitsi directory and stop services
log_message "Changing to Jitsi directory and stopping services..."
cd /opt/jitsi || {
    log_message "ERROR: Failed to change to /opt/jitsi directory"
    exit 1
}

log_message "Stopping Jitsi services..."
docker compose down
check_error "Failed to stop Jitsi services"

# Create backup directory if it doesn't exist
log_message "Creating backup directory /opt/backup.latest"
mkdir -p /opt/backup.latest
check_error "Failed to create backup directory"

# Backup existing files (including hidden ones)
log_message "Backing up current Jitsi installation (including hidden files)..."
cd /opt/jitsi && cp -af . /opt/backup.latest/
check_error "Failed to create backup"
log_message "Backup completed successfully"

# Download the latest release
log_message "Downloading latest Jitsi release..."
wget -O jitsi-latest.zip $(curl -s https://api.github.com/repos/jitsi/docker-jitsi-meet/releases/latest | grep 'zip' | cut -d\" -f4)
check_error "Failed to download latest release"

# Create a temporary directory for extraction
log_message "Creating temporary directory for extraction..."
temp_dir=$(mktemp -d)
check_error "Failed to create temporary directory"

# Extract the zip file
log_message "Extracting files..."
unzip -q jitsi-latest.zip -d "$temp_dir"
check_error "Failed to extract zip file"

# Find the extracted directory name
extracted_dir=$(find "$temp_dir" -mindepth 1 -maxdepth 1 -type d)
check_error "Failed to find extracted directory"

# Copy all contents to /opt/jitsi
log_message "Updating Jitsi installation..."
cp -af "$extracted_dir/"* /opt/jitsi/
check_error "Failed to copy new files to installation directory"

# Clean up
log_message "Cleaning up temporary files..."
rm -rf "$temp_dir"
rm jitsi-latest.zip
check_error "Failed to clean up temporary files"

log_message "Jitsi update completed successfully!"

# Start Jitsi services with latest images
log_message "Starting Jitsi services with latest images..."
cd /opt/jitsi || {
    log_message "ERROR: Failed to change to /opt/jitsi directory"
    exit 1
}
docker compose up -d
check_error "Failed to start Jitsi services"

log_message "Jitsi services started successfully"

# Ask user if they want to clean up old images
read -p "Would you like to clean up old Docker images? (y/n): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    handle_image_cleanup
fi

log_message "All operations completed!"

Save the script to a suitable location and make it executable:

nano /opt/update-jitsi-sh  ### <-- paste the above code into this file
chmod +x /opt/update-jitsi.sh

2. Running the Update

Execute the script with appropriate privileges:

sudo /opt/update-jitsi.sh

Advanced Features

Terminal Handling

The script includes sophisticated terminal handling for the image cleanup process:

cleanup() {
    if [ ! -z "$SAVED_STTY" ]; then
        stty "$SAVED_STTY" 2>/dev/null || true
    fi
    tput cnorm  # Show cursor
}

This ensures a clean terminal state even if the script exits unexpectedly.

Error Handling and Recovery

The script implements robust error handling throughout:

  • Checks for required directories and permissions
  • Validates backup creation
  • Ensures clean service shutdown
  • Verifies successful updates

Best Practices and Tips

Backup Management

While the script automatically creates backups in /opt/backup.latest, consider implementing these additional practices:

  • Regularly archive old backups to separate storage
  • Implement backup rotation to manage disk space
  • Test backup restoration periodically

Security Considerations

When implementing this script, keep these security aspects in mind:

  • Restrict script access to authorized administrators
  • Review Docker image sources before updates
  • Maintain secure backup storage
  • Monitor script execution logs

Troubleshooting Common Issues

1. Service Startup Failures

If services fail to start after update:

cd /opt/jitsi
docker compose logs

2. Backup Issues

For backup-related problems:

  • Check available disk space
  • Verify backup directory permissions
  • Review backup contents before update

Conclusion

This automated Jitsi Meet update script significantly simplifies system maintenance while providing robust error handling and backup features. By implementing this solution, administrators can maintain their Jitsi Meet installations with confidence and efficiency.

Future Enhancements

Consider these potential improvements for the script:

  • Make the script more dynamic in terms backup location and Jitsi source folder
  • Email notifications for update status - e.g. if the script is being called by CRON
  • Automatic backup rotation
  • Custom configuration preservation

Remember to always test updates in a staging environment first and maintain current backups before running system updates.