Menü schliessen
Created: May 1st 2025
Last updated: April 30th 2025
Categories: Linux,  Mattermost
Author: Marcus Fleuti

Mattermost Self-Hosting - Automated Update (Bash) Script

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

Why Automate Mattermost Updates?

Mattermost, a popular open-source alternative to proprietary messaging platforms like Slack, requires regular updates to maintain security patches and access new features. While the update process isn't particularly complex, it involves several steps that can be error-prone when performed manually:

  1. Downloading the latest version
  2. Stopping the Mattermost service
  3. Backing up existing files
  4. Extracting and replacing files
  5. Setting proper permissions
  6. Restarting the service

Our script automates this entire workflow while adding intelligent features such as disk space verification, backup controls, and edition selection.

Script Features and Benefits

Before diving into the code, let's explore the key features that make this script valuable for system administrators:

  • Edition Selection: Support for both Enterprise and Team editions
  • Intelligent Backup Control: Option to enable/disable backups
  • Customizable Backup Location: Store backups wherever you want
  • Disk Space Verification: Prevents failed backups due to insufficient space
  • Color-Coded Output: Clear, readable status messages
  • Comprehensive Error Handling: Detailed error messages and checks
  • Configurable Variables: Easy customization without modifying core logic
  • Self-Documenting: Clear comments and instructions

These features make the script suitable for both production environments and personal servers, regardless of the administrator's experience level.

Dependencies and Requirements

To use this script effectively, you'll need:

  • A Linux server running Mattermost
  • Root or sudo privileges
  • Basic bash utilities: curl, wget, tar, systemctl
  • Sufficient disk space for backups (script will verify this)

Most Linux distributions include these tools by default, but the script checks for their presence and will notify you if anything is missing.

The Complete Mattermost Update Script

Here's the full script with detailed comments explaining each section:

#!/bin/bash

# =================================================================
# Mattermost Automatic Update Script
# =================================================================
# Configuration variables - modify these to match your installation
# =================================================================

# Base installation directory
MATTERMOST_BASE_DIR="/opt"
MATTERMOST_DIR="${MATTERMOST_BASE_DIR}/mattermost"

# Temporary directory for downloads and extraction
TEMP_DIR="/tmp"

# User and group that should own the Mattermost installation
MATTERMOST_USER="mattermost"
MATTERMOST_GROUP="mattermost"

# Mattermost service name
MATTERMOST_SERVICE="mattermost"

# Mattermost edition - "enterprise" or "team"
MATTERMOST_EDITION="enterprise"   # Set to "team" if you're using the Team Edition

# Backup settings
CREATE_BACKUP=true                # Set to false to skip backup creation
BACKUP_DIR_PREFIX="mattermost-backup"  # Prefix for backup directory name - will be appended with date/time (e.g., mattermost-backup-20240430-120135)
BACKUP_STORAGE_PATH="${MATTERMOST_BASE_DIR}"  # Where backups will be stored (defaults to same as installation directory)

# Directories to preserve during update
PRESERVE_DIRS=(
    "client"
    "client/plugins"
    "config"
    "logs"
    "plugins"
    "data"
)

# Number of log lines to show after restart
LOG_LINES=20

# Set to true to follow logs, false to just display the last LOG_LINES
FOLLOW_LOGS=true

# =================================================================
# Script logic - You shouldn't need to modify below this line
# =================================================================

# Enable exit on error
set -e

# Color codes for better readability
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

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

info() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1${NC}"
}

debug() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [DEBUG] $1${NC}"
}

warn() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1${NC}" >&2
}

error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1${NC}" >&2
}

# Function to check command status
check_status() {
    if [ $? -ne 0 ]; then
        error "$1"
        exit 1
    fi
}

# Function to check if running as root
check_root() {
    if [ "$(id -u)" != "0" ]; then
        error "This script must be run as root or with sudo"
        exit 1
    fi
}

# Check for required commands
check_dependencies() {
    local missing_deps=()
    
    for cmd in curl wget tar systemctl; do
        if ! command -v $cmd &> /dev/null; then
            missing_deps+=($cmd)
        fi
    done
    
    if [ ${#missing_deps[@]} -ne 0 ]; then
        error "Missing required dependencies: ${missing_deps[*]}"
        echo "Please install the missing dependencies and try again."
        exit 1
    fi
}

# Check if Mattermost is installed
check_mattermost_installed() {
    if [ ! -d "$MATTERMOST_DIR" ]; then
        error "Mattermost installation not found at $MATTERMOST_DIR"
        exit 1
    fi
    
    if ! systemctl status $MATTERMOST_SERVICE &> /dev/null; then
        error "Mattermost service ($MATTERMOST_SERVICE) not found"
        exit 1
    fi
}

# Function to check Mattermost edition validity
check_edition() {
    if [[ ! "$MATTERMOST_EDITION" =~ ^(enterprise|team)$ ]]; then
        error "Invalid MATTERMOST_EDITION value: $MATTERMOST_EDITION"
        echo "MATTERMOST_EDITION must be either 'enterprise' or 'team'"
        exit 1
    fi
}

# Function to check available disk space
check_disk_space() {
    local source_dir="$1"
    local target_dir="$2"
    
    # Get size of source directory in KB
    local source_size=$(du -sk "$source_dir" | cut -f1)
    
    # Get available space on target device in KB
    local target_avail=$(df -kP "$target_dir" | tail -1 | awk '{print $4}')
    
    # Convert to MB for display
    local source_size_mb=$(($source_size / 1024))
    local target_avail_mb=$(($target_avail / 1024))
    
    # Return values via global variables
    DISK_CHECK_SOURCE_SIZE_MB=$source_size_mb
    DISK_CHECK_TARGET_AVAIL_MB=$target_avail_mb
    
    # Check if there's enough space (plus 10% buffer)
    local required_space=$(($source_size * 110 / 100))
    if [ $target_avail -lt $required_space ]; then
        return 1
    else
        return 0
    fi
}

# Initialize the script
initialize() {
    log "Initializing Mattermost update script"
    check_root
    check_dependencies
    check_mattermost_installed
    check_edition
}

# Main script
initialize

# Create the upgrade directory name
UPGRADE_DIR="mattermost-upgrade"
TEMP_UPGRADE_DIR="${TEMP_DIR}/${UPGRADE_DIR}"

# Fetch latest version URL based on selected edition
log "Fetching Mattermost ${MATTERMOST_EDITION} edition release information..."
DOWNLOAD_URL=$(curl -s https://releases.mattermost.com/ | grep -o "https://.*${MATTERMOST_EDITION}.*linux-amd64\.tar\.gz" | sort -V | tail -n1)
check_status "Failed to fetch release information"

if [ -z "$DOWNLOAD_URL" ]; then
    error "Could not find ${MATTERMOST_EDITION} edition Linux release URL"
    exit 1
fi

VERSION=$(basename "$DOWNLOAD_URL")
echo
echo -e "${YELLOW}---------------------------------------------------------------${NC}"
echo -e "${YELLOW}Found latest Mattermost ${MATTERMOST_EDITION^} edition version: ${GREEN}$VERSION${NC}"
echo -e "${YELLOW}---------------------------------------------------------------${NC}"
echo -n "Do you want to upgrade Mattermost to this version? (y/n): "
read -r REPLY

if [[ ! $REPLY =~ ^[Yy]$ ]]; then
    log "Upgrade cancelled by user"
    exit 0
fi

# Change to temporary directory
log "Changing to temporary directory ($TEMP_DIR)..."
cd $TEMP_DIR || {
    error "Failed to change to temporary directory"
    exit 1
}

# Clean up any previous failed attempts
if [ -d "$TEMP_UPGRADE_DIR" ]; then
    info "Cleaning up previous upgrade directory..."
    rm -rf "$TEMP_UPGRADE_DIR"
fi
if [ -f "${TEMP_DIR}/mattermost*.gz" ]; then
    info "Cleaning up previous downloaded archive..."
    rm -f ${TEMP_DIR}/mattermost*.gz
fi

# Download the release
log "Downloading Mattermost from $DOWNLOAD_URL..."
wget -q --show-progress "$DOWNLOAD_URL"
check_status "Failed to download Mattermost"

ARCHIVE_FILE=$(basename "$DOWNLOAD_URL")
log "Downloaded $ARCHIVE_FILE successfully"

# Extract the archive
log "Extracting archive..."
tar -xf "$ARCHIVE_FILE" --transform="s,^[^/]\+,${UPGRADE_DIR}," || {
    error "Failed to extract archive"
    exit 1
}

# Stop Mattermost service
log "Stopping Mattermost service..."
systemctl stop $MATTERMOST_SERVICE || {
    error "Failed to stop Mattermost service"
    exit 1
}

# Backup current version - if enabled
if [ "$CREATE_BACKUP" = true ]; then
    # Check if backup path exists, create if it doesn't
    if [ ! -d "$BACKUP_STORAGE_PATH" ]; then
        log "Creating backup storage directory $BACKUP_STORAGE_PATH..."
        mkdir -p "$BACKUP_STORAGE_PATH" || {
            error "Failed to create backup storage directory"
            exit 1
        }
    fi
    
    # Check available disk space
    log "Checking available disk space for backup..."
    if ! check_disk_space "$MATTERMOST_DIR" "$BACKUP_STORAGE_PATH"; then
        warn "WARNING: Not enough disk space for backup!"
        echo -e "${YELLOW}The Mattermost directory is ${DISK_CHECK_SOURCE_SIZE_MB} MB in size${NC}"
        echo -e "${YELLOW}Available space at backup location is only ${DISK_CHECK_TARGET_AVAIL_MB} MB${NC}"
        echo -e "${YELLOW}Recommended space (with 10% buffer): $((DISK_CHECK_SOURCE_SIZE_MB * 110 / 100)) MB${NC}"
        echo
        echo -n "Do you want to proceed with the backup anyway? (y/n): "
        read -r REPLY_BACKUP
        
        if [[ ! $REPLY_BACKUP =~ ^[Yy]$ ]]; then
            log "Backup cancelled due to insufficient space"
            echo -n "Do you want to continue with the update without creating a backup? (y/n): "
            read -r REPLY_UPDATE
            
            if [[ ! $REPLY_UPDATE =~ ^[Yy]$ ]]; then
                log "Update cancelled by user"
                exit 0
            else
                info "Proceeding with update without backup"
                CREATE_BACKUP=false
            fi
        else
            info "Proceeding with backup despite space warning"
        fi
    else
        info "Sufficient disk space available (${DISK_CHECK_SOURCE_SIZE_MB} MB needed, ${DISK_CHECK_TARGET_AVAIL_MB} MB available)"
    fi
    
    if [ "$CREATE_BACKUP" = true ]; then
        BACKUP_DIR="${BACKUP_STORAGE_PATH}/${BACKUP_DIR_PREFIX}-$(date +%Y%m%d-%H%M%S)"
        log "Creating backup at $BACKUP_DIR..."
        cp -a "$MATTERMOST_DIR" "$BACKUP_DIR" || {
            error "Failed to create backup"
            exit 1
        }
        info "Backup created successfully at $BACKUP_DIR"
    fi
else
    info "Backup creation skipped (CREATE_BACKUP=$CREATE_BACKUP)"
fi

# Change to base directory
log "Changing to Mattermost base directory ($MATTERMOST_BASE_DIR)..."
cd $MATTERMOST_BASE_DIR || {
    error "Failed to change to Mattermost base directory"
    exit 1
}

# Create preserve paths list for removal exclusion
PRESERVE_PATHS=""
for dir in "${PRESERVE_DIRS[@]}"; do
    PRESERVE_PATHS+=" -o -path $MATTERMOST_DIR/$dir"
done
PRESERVE_PATHS=${PRESERVE_PATHS:3}  # Remove the first " -o"

# Remove old files but preserve specific directories
log "Removing old files (preserving data directories)..."
find $MATTERMOST_DIR/ $MATTERMOST_DIR/client/ -mindepth 1 -maxdepth 1 \! \( -type d \( $PRESERVE_PATHS \) -prune \) | sort | xargs rm -rf || {
    error "Failed to remove old files"
    exit 1
}

# Copy new files
log "Copying new files..."
cp -a --update=none "${TEMP_DIR}/${UPGRADE_DIR}/." $MATTERMOST_DIR/ || {
    error "Failed to copy new files"
    exit 1
}

# Set ownership
log "Setting ownership to $MATTERMOST_USER:$MATTERMOST_GROUP..."
chown -R $MATTERMOST_USER:$MATTERMOST_GROUP $MATTERMOST_DIR || {
    error "Failed to set ownership"
    exit 1
}

# Set capabilities
log "Setting required capabilities..."
setcap cap_net_bind_service=+ep $MATTERMOST_DIR/bin/mattermost || {
    error "Failed to set capabilities"
    exit 1
}

# Cleanup
log "Cleaning up temporary files..."
rm -rf "${TEMP_DIR}/${UPGRADE_DIR}/" || {
    error "Failed to remove temporary upgrade directory"
    exit 1
}

log "Removing downloaded archive..."
rm -rf "${TEMP_DIR}/${ARCHIVE_FILE}" || {
    error "Failed to remove downloaded archive"
    exit 1
}

# Reminder for plugin updates
echo
echo -e "${YELLOW}---------------------------------------------------------------${NC}"
echo -e "${YELLOW}REMINDER: Update Mattermost Boards plugin if needed${NC}"
echo -e "${YELLOW}https://github.com/mattermost/mattermost-plugin-boards/releases/${NC}"
echo -e "${YELLOW}---------------------------------------------------------------${NC}"
echo

# Start Mattermost service
log "Starting Mattermost service..."
systemctl start $MATTERMOST_SERVICE || {
    error "Failed to start Mattermost service"
    exit 1
}

# Wait a moment for the service to start
sleep 3

# Display logs
log "Mattermost updated successfully to version $VERSION"
log "Displaying Mattermost logs..."

if [ "$FOLLOW_LOGS" = true ]; then
    tail -n $LOG_LINES -F $MATTERMOST_DIR/logs/mattermost.log || {
        error "Failed to display logs"
        exit 1
    }
else
    tail -n $LOG_LINES $MATTERMOST_DIR/logs/mattermost.log || {
        error "Failed to display logs"
        exit 1
    }
fi

exit 0

 

Understanding the Script Components

Let's break down the key components of the script to understand how it works:

Configuration Section

The top section contains all customizable variables:

# Base installation directory
MATTERMOST_BASE_DIR="/opt"
MATTERMOST_DIR="${MATTERMOST_BASE_DIR}/mattermost"

# User and group that should own the Mattermost installation
MATTERMOST_USER="mattermost"
MATTERMOST_GROUP="mattermost"

# Mattermost edition - "enterprise" or "team"
MATTERMOST_EDITION="enterprise"

# Backup settings
CREATE_BACKUP=true
BACKUP_DIR_PREFIX="mattermost-backup"
BACKUP_STORAGE_PATH="${MATTERMOST_BASE_DIR}"

These variables make the script highly adaptable to different server configurations without modifying the core logic.

Intelligent Logging Functions

The script includes several logging functions that provide clear, color-coded output:

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

info() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1${NC}"
}

warn() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1${NC}" >&2
}

error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1${NC}" >&2
}

These functions make it easy to distinguish between different types of messages and quickly identify problems.

Pre-Update Checks

Before performing any actions, the script verifies:

  1. It's running with proper privileges
  2. All required dependencies are available
  3. Mattermost is properly installed
  4. The selected edition (Enterprise or Team) is valid

This prevents common issues before they occur.

Disk Space Verification

One of the most useful features is the disk space verification:

# Check available disk space
log "Checking available disk space for backup..."
if ! check_disk_space "$MATTERMOST_DIR" "$BACKUP_STORAGE_PATH"; then
    warn "WARNING: Not enough disk space for backup!"
    # ...warning details and user prompt...
fi

This prevents the frustrating scenario of a backup failing midway due to insufficient space, potentially leaving your server in an inconsistent state.

Update Process

The actual update process follows these steps:

  1. Download the latest version based on edition selection
  2. Extract files to a temporary location
  3. Stop the Mattermost service
  4. Create a backup (if enabled and space allows)
  5. Remove old files while preserving data directories
  6. Copy new files
  7. Set proper ownership and capabilities
  8. Clean up temporary files
  9. Restart the Mattermost service
  10. Display recent logs

Customizing the Script for Your Environment

Before using the script, you should adjust the following variables to match your environment:

  1. Installation Paths:
    • MATTERMOST_BASE_DIR: The base directory where Mattermost is installed
    • MATTERMOST_DIR: The specific Mattermost directory
  2. User and Group:
    • MATTERMOST_USER: The user that owns Mattermost files
    • MATTERMOST_GROUP: The group that owns Mattermost files
  3. Service Name:
    • MATTERMOST_SERVICE: The name of your Mattermost systemd service
  4. Edition:
    • MATTERMOST_EDITION: Choose "enterprise" or "team" based on your installation
  5. Backup Settings:
    • CREATE_BACKUP: Set to true/false to enable/disable backups
    • BACKUP_DIR_PREFIX: Customize the backup directory naming
    • BACKUP_STORAGE_PATH: Specify where backups should be stored

Comparison with Other Update Methods

When it comes to updating Mattermost, administrators have several options. Let's compare this script with other common methods:

Feature This Script Manual Update Docker Update Package Manager
Automation Full None Partial Full
Backup Creation Configurable Manual Manual Limited
Disk Space Check Yes Manual No Limited
Edition Selection Yes Manual Tag-based Package-specific
Customization High Complete Limited Very Limited
Error Handling Comprehensive Manual Limited Varies
Data Preservation Configurable Manual Volume-based Package Rules

 

As the comparison shows, this script offers the highest level of automation while maintaining flexibility and adding safety features like disk space verification that aren't available in other methods.

Common Use Cases

This script is particularly valuable in the following scenarios:

1. Regular Maintenance Windows

For organizations with scheduled maintenance windows, the script can be triggered at the appropriate time to perform updates efficiently and consistently.

2. Multiple Server Deployments

If you manage multiple Mattermost instances (e.g., for different departments or environments), the script ensures a consistent update process across all servers.

3. Resource-Constrained Environments

The disk space verification is especially valuable in environments with limited storage, preventing failed updates due to insufficient space.

4. High-Availability Requirements

For servers with high uptime requirements, the script's error handling and backup capabilities minimize the risk of prolonged downtime during updates.

Best Practices for Using the Script

To get the most out of this script, consider the following best practices:

1. Test in a Non-Production Environment First

Before running the script on your production server, test it in a staging environment to ensure it works correctly with your specific configuration.

2. Schedule Regular Updates

Set up a regular schedule for updates to ensure you receive security patches and bug fixes promptly.

3. Manage Your Backups

While the script creates backups automatically, you should implement a rotation policy to prevent filling up your disk with old backups. Consider adding a step to move older backups to archival storage.

4. Monitor Logs After Updates

Even with automated updates, it's important to check the Mattermost logs after an update to ensure everything is functioning correctly. The script automatically issues a TAIL command on the Mattermost Log right after restarting the service: