Skip to main content

FileWave Automation Scripts

This article contains the scripts used by the Downloads page. The scripts are here for documentation purposes.

Scripts

FileWave Server Upgrade

fwxserver_upgrade.sh - This script is used by the Download page fro FileWave Server upgrades on Debian. Some details;

# To run this script, use the following 1-liner:
# wget -qO- https://kb.filewave.com/attachments/411 | sudo bash -s -- -v <version> -r <revision> [-b for beta] -y
# Example for version 15.5.0 with revision 1 in production:
# wget -qO- https://kb.filewave.com/attachments/411 | sudo bash -s -- -v 15.5.0 -r 1 -p -y

fwxserver_upgrade.sh
#!/bin/bash
# Documentation
# To run this script, use the following 1-liner:
# curl -fsSL https://kb.filewave.com/attachments/411 | sudo bash -s -- -v <version> -r <revision> [-b for beta] -y
# Example for version 15.5.0 with revision 1 in production:
# curl -fsSL https://kb.filewave.com/attachments/411 | sudo bash -s -- -v 15.5.0 -r 1 -p -y

# Ensure script is run with sudo/root privileges
if [ "$EUID" -ne 0 ]; then
    die "This script must be run with sudo or as root."
fi

# Ensure script is running on a Debian-based system
if ! grep -iq "debian" /etc/os-release; then
    die "This script must be run on a Debian-based system."
fi

# Set default values for version, revision, and server type
VERSION="15.5.0"
REVISION="1"
SERVER_TYPE="prod"
BASE_URL="https://fwdl.filewave.com"
auto_yes=false

if [ "$#" -eq 0 ]; then
    echo "Usage: curl -fsSL https://kb.filewave.com/attachments/409 | sudo bash -s -- -v <version> -r <revision> [-b for beta | -p for prod] [-y for auto-yes]"
    echo "
Options:"
    echo "  -v, --version    Specify the version of FileWave Server to install (e.g., 15.5.0)"
    echo "  -r, --revision   Specify the revision number (e.g., 1)"
    echo "  -d, --dev		 Use Dev server for downloads (default is production)"
    echo "  -b, --beta       Use beta server for downloads (default is production)"
    echo "  -p, --prod       Use production server for downloads"
    echo "  -y, --yes        Automatically answer 'yes' to all prompts"
    exit 1
fi

# Function to handle errors and display messages
die() {
    echo "[ERROR] $1" >&2
    exit 1
}

# Log all actions to syslog for audit purposes
LOG_FILE="/var/log/filewave_server_update.log"
touch "$LOG_FILE" || die "Failed to create log file $LOG_FILE. Check permissions."
chmod 644 "$LOG_FILE" || die "Failed to set permissions on log file $LOG_FILE."
if [[ ! -w "$LOG_FILE" ]]; then
    die "Cannot write to log file $LOG_FILE. Please check permissions."
fi
exec > >(stdbuf -oL tee -a "$LOG_FILE") 2>&1
echo "Logging to $LOG_FILE"

# Parse input arguments
while [[ "$#" -gt 0 ]]; do
    case $1 in
        -v|--version)
            VERSION="$2"
            shift 2
            ;;
        -r|--revision)
            REVISION="$2"
            shift 2
            ;;
		-d|--dev)
			SERVER_TYPE="dev"
			shift
			;;
        -b|--beta)
            SERVER_TYPE="beta"
            shift
            ;;
        -p|--prod)
            SERVER_TYPE="prod"
            shift
            ;;
        -y|--yes)
            auto_yes=true
            shift
            ;;          
        *)
            echo "Unknown option: $1"
            exit 1
            ;;
    esac
done

# Confirm actions with the user
echo "This script will update your OS and install/upgrade the FileWave Server packages."
echo "Version: $VERSION, Revision: $REVISION, Server Type: $SERVER_TYPE"
if [[ "$auto_yes" == "true" ]]; then
    confirm="yes"
else
    read -p "Do you wish to proceed? (yes/no): " confirm < /dev/tty
fi
if [[ ! "$confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "Aborting installation as requested."
    exit 0
fi

# Set the appropriate URL based on server type
if [ "$SERVER_TYPE" = "beta" ]; then
    BASE_URL="https://fwbetas.filewave.com"
elif [ "$SERVER_TYPE" = "dev" ]; then
    BASE_URL="https://fwdevdl.filewave.com"
else
    # Default to production download server
    BASE_URL="https://fwdl.filewave.com"
fi

# 1. Install Essential Tools
echo "Installing essential tools..."
apt-get clean || die "Failed to clean apt cache."
apt-get update -y || die "Failed to update package list."
apt-get --fix-broken install -y || die "Failed to fix broken installs from apt."
apt-get autoremove -y || die "Failed to autoremove from apt."

for dep in "curl" "zip" "gdebi"; do
    if ! command -v $dep &> /dev/null; then
        echo "$dep not found. Installing $dep..."
        apt-get install -y $dep || die "Failed to install $dep."
    fi
done

if ! dpkg-query -W -f='${Status}' net-tools 2>/dev/null | grep -q "install ok installed"; then
    echo "net-tools not found. Installing net-tools..."
    apt-get install -y net-tools || die "Failed to install net-tools."
fi

# Check the current version of FileWave Server
INSTALLED_VERSION=$(dpkg-query -W -f='${Version}' fwxserver 2>/dev/null || true)
# If no FileWave Server package is installed, set the version to 1.0.0 for comparison purposes
if [[ -z "$INSTALLED_VERSION" || "$INSTALLED_VERSION" == "none" ]]; then
    echo "No FileWave Server packages are installed. Proceeding with initial installation of version $VERSION..."
    INSTALLED_VERSION="1.0.0"
fi

install_packages() {
    echo "Downloading and installing FileWave Server package..."
    PACKAGE="fwxserver_${VERSION}_amd64.deb"
    DOWNLOAD_DIR="/tmp/filewave_install_$$"
    mkdir -p "$DOWNLOAD_DIR" || die "Failed to create download directory."
    trap 'rm -rf "$DOWNLOAD_DIR"' EXIT
    echo "Downloading $PACKAGE..."
    for i in {1..3}; do
        curl -fSL "$BASE_URL/$VERSION/$PACKAGE" -o "$DOWNLOAD_DIR/$PACKAGE" && break
        echo "Retrying download ($i/3)..."
        sleep 5
    done
    if [[ ! -f "$DOWNLOAD_DIR/$PACKAGE" ]]; then
        die "Failed to download $PACKAGE after multiple attempts."
    fi
    echo "Installing $PACKAGE..."
    gdebi -n "$DOWNLOAD_DIR/$PACKAGE" || die "Failed to install $PACKAGE"

    # Clean up the download directory
    if [[ -d "$DOWNLOAD_DIR" ]]; then
        rm -rf "$DOWNLOAD_DIR" || echo "Warning: Failed to remove download directory $DOWNLOAD_DIR"
    fi
}

# This is the meat of the script.
# The actions to take based on version.
if dpkg --compare-versions "$INSTALLED_VERSION" lt "$VERSION"; then
    echo "Upgrading to FileWave Server version $VERSION..."
    install_packages
elif dpkg --compare-versions "$INSTALLED_VERSION" eq "$VERSION"; then
    echo "FileWave Server is already at version $VERSION, no further installation required."
else
    echo "FileWave Server is newer than $VERSION and downgrade is not possible with this script."
fi

# Clean up the download directory
if [[ -d "$DOWNLOAD_DIR" ]]; then
    rm -rf "$DOWNLOAD_DIR" || echo "Warning: Failed to remove download directory $DOWNLOAD_DIR"
fi

# 4. OS Upgrade
echo "Warning: This script will upgrade the entire OS. This is required for security."
if [[ "$auto_yes" == "true" ]]; then
    upgrade_confirm="yes"
else
    read -p "Do you wish to proceed with the OS upgrade? (yes/no): " upgrade_confirm < /dev/tty
fi
if [[ ! "$upgrade_confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "Skipping OS upgrade."
else
    echo "Upgrading the system..."
    apt-get update -y || die "Failed to update package list."
    DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -o Dpkg::Options::="--force-confold" || die "System upgrade failed."
fi

# 5. Reboot the system to complete the installation
echo "The system will reboot in 15 seconds to complete the installation."
if [[ "$auto_yes" == "true" ]]; then
    reboot_confirm="yes"
else
    read -p "Do you want to reboot now? (yes/no): " reboot_confirm < /dev/tty
fi
if [[ "$reboot_confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "Rebooting system in 15 seconds... Please remember that you can check the log file at $LOG_FILE after the reboot to see the full details of the update."
    sleep 15
    reboot
else
    echo "Skipping reboot. Please remember to reboot manually to apply all changes."
fi

# The end

 


FileWave Booster Upgrade

fwbooster_upgrade.sh - This script is used by the Download page fro FileWave Booster upgrades on Debian. Some details;

# To run this script, use the following 1-liner:
# wget -qO- https://kb.filewave.com/attachments/412 | sudo bash -s -- -v <version> -r <revision> [-b for beta] -y
# Example for version 15.5.0 with revision 1 in production:
# wget -qO- https://kb.filewave.com/attachments/412 | sudo bash -s -- -v 15.5.0 -r 1 -p -y

fwbooster_upgrade.sh
#!/bin/bash
# Documentation
# To run this script, use the following 1-liner:
# curl -fsSL https://kb.filewave.com/attachments/412 | sudo bash -s -- -v <version> -r <revision> [-b for beta] -y
# Example for version 15.5.0 with revision 1 in production:
# curl -fsSL https://kb.filewave.com/attachments/412 | sudo bash -s -- -v 15.5.0 -r 1 -p -y

# Ensure script is run with sudo/root privileges
if [ "$EUID" -ne 0 ]; then
    die "This script must be run with sudo or as root."
fi

# Ensure script is running on a Debian-based system
if ! grep -iq "debian" /etc/os-release; then
    die "This script must be run on a Debian-based system."
fi

# Set default values for version, revision, and server type
VERSION="15.5.0"
REVISION="1"
SERVER_TYPE="prod"
BASE_URL="https://fwdl.filewave.com"
auto_yes=false

if [ "$#" -eq 0 ]; then
    echo "Usage: curl -fsSL https://kb.filewave.com/attachments/409 | sudo bash -s -- -v <version> -r <revision> [-b for beta | -p for prod] [-y for auto-yes]"
    echo "\nOptions:"
    echo "  -v, --version    Specify the version of FileWave Booster to install (e.g., 15.5.0)"
    echo "  -r, --revision   Specify the revision number (e.g., 1)"
    echo "  -d, --dev		 Use Dev server for downloads (default is production)"
    echo "  -b, --beta       Use beta server for downloads (default is production)"
    echo "  -p, --prod       Use production server for downloads"
    echo "  -y, --yes        Automatically answer 'yes' to all prompts"
    exit 1
fi

# Function to handle errors and display messages
die() {
    echo "[ERROR] $1" >&2
    exit 1
}

# Log all actions to syslog for audit purposes
LOG_FILE="/var/log/filewave_booster_update.log"
touch "$LOG_FILE" || die "Failed to create log file $LOG_FILE. Check permissions."
chmod 644 "$LOG_FILE" || die "Failed to set permissions on log file $LOG_FILE."
if [[ ! -w "$LOG_FILE" ]]; then
    die "Cannot write to log file $LOG_FILE. Please check permissions."
fi
exec > >(stdbuf -oL tee -a "$LOG_FILE") 2>&1
echo "Logging to $LOG_FILE"

# Parse input arguments
while [[ "$#" -gt 0 ]]; do
    case $1 in
        -v|--version)
            VERSION="$2"
            shift 2
            ;;
        -r|--revision)
            REVISION="$2"
            shift 2
            ;;
		-d|--dev)
			SERVER_TYPE="dev"
			shift
			;;
        -b|--beta)
            SERVER_TYPE="beta"
            shift
            ;;
        -p|--prod)
            SERVER_TYPE="prod"
            shift
            ;;
        -y|--yes)
            auto_yes=true
            shift
            ;;          
        *)
            echo "Unknown option: $1"
            exit 1
            ;;
    esac
done

# Confirm actions with the user
echo "This script will update your OS and install/upgrade the FileWave Booster packages."
echo "Version: $VERSION, Revision: $REVISION, Server Type: $SERVER_TYPE"
if [[ "$auto_yes" == "true" ]]; then
    confirm="yes"
else
    read -p "Do you wish to proceed? (yes/no): " confirm < /dev/tty
fi
if [[ ! "$confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "Aborting installation as requested."
    exit 0
fi

# Set the appropriate URL based on server type
if [ "$SERVER_TYPE" = "beta" ]; then
    BASE_URL="https://fwbetas.filewave.com"
elif [ "$SERVER_TYPE" = "dev" ]; then
    BASE_URL="https://fwdevdl.filewave.com"
else
    # Default to production download server
    BASE_URL="https://fwdl.filewave.com"
fi

# 1. Install Essential Tools
echo "Installing essential tools..."
apt-get clean || die "Failed to clean apt cache."
apt-get update -y || die "Failed to update package list."
apt-get --fix-broken install -y || die "Failed to fix broken installs from apt."
apt-get autoremove -y || die "Failed to autoremove from apt."

for dep in "curl" "zip" "gdebi"; do
    if ! command -v $dep &> /dev/null; then
        echo "$dep not found. Installing $dep..."
        apt-get install -y $dep || die "Failed to install $dep."
    fi
done

if ! dpkg-query -W -f='${Status}' net-tools 2>/dev/null | grep -q "install ok installed"; then
    echo "net-tools not found. Installing net-tools..."
    apt-get install -y net-tools || die "Failed to install net-tools."
fi

# Check the current version of FileWave Booster
INSTALLED_VERSION=$(dpkg-query -W -f='${Version}' fwbooster 2>/dev/null || true)
# If no FileWave Booster package is installed, set the version to 1.0.0 for comparison purposes
if [[ -z "$INSTALLED_VERSION" || "$INSTALLED_VERSION" == "none" ]]; then
    echo "No FileWave Booster packages are installed. Proceeding with initial installation of version $VERSION..."
    INSTALLED_VERSION="1.0.0"
fi

install_packages() {
    echo "Downloading and installing FileWave Booster package..."
    PACKAGE="fwbooster_${VERSION}_amd64.deb"
    DOWNLOAD_DIR="/tmp/filewave_install_$$"
    mkdir -p "$DOWNLOAD_DIR" || die "Failed to create download directory."
    trap 'rm -rf "$DOWNLOAD_DIR"' EXIT
    echo "Downloading $PACKAGE..."
    for i in {1..3}; do
        curl -fSL "$BASE_URL/$VERSION/$PACKAGE" -o "$DOWNLOAD_DIR/$PACKAGE" && break
        echo "Retrying download ($i/3)..."
        sleep 5
    done
    if [[ ! -f "$DOWNLOAD_DIR/$PACKAGE" ]]; then
        die "Failed to download $PACKAGE after multiple attempts."
    fi
    echo "Installing $PACKAGE..."
    gdebi -n "$DOWNLOAD_DIR/$PACKAGE" || die "Failed to install $PACKAGE"

    # Clean up the download directory
    if [[ -d "$DOWNLOAD_DIR" ]]; then
        rm -rf "$DOWNLOAD_DIR" || echo "Warning: Failed to remove download directory $DOWNLOAD_DIR"
    fi
}

# This is the meat of the script.
# The actions to take based on version.
if dpkg --compare-versions "$INSTALLED_VERSION" lt "$VERSION"; then
    echo "Upgrading to FileWave Booster version $VERSION..."
    install_packages
elif dpkg --compare-versions "$INSTALLED_VERSION" eq "$VERSION"; then
    echo "FileWave Booster is already at version $VERSION, no further installation required."
else
    echo "FileWave Booster is newer than $VERSION and downgrade is not possible with this script."
fi

# Clean up the download directory
if [[ -d "$DOWNLOAD_DIR" ]]; then
    rm -rf "$DOWNLOAD_DIR" || echo "Warning: Failed to remove download directory $DOWNLOAD_DIR"
fi

# 4. OS Upgrade
echo "Warning: This script will upgrade the entire OS. This is required for security."
if [[ "$auto_yes" == "true" ]]; then
    upgrade_confirm="yes"
else
    read -p "Do you wish to proceed with the OS upgrade? (yes/no): " upgrade_confirm < /dev/tty
fi
if [[ ! "$upgrade_confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "Skipping OS upgrade."
else
    echo "Upgrading the system..."
    apt-get update -y || die "Failed to update package list."
    DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -o Dpkg::Options::="--force-confold" || die "System upgrade failed."
fi

# 5. Reboot the system to complete the installation
echo "The system will reboot in 15 seconds to complete the installation."
if [[ "$auto_yes" == "true" ]]; then
    reboot_confirm="yes"
else
    read -p "Do you want to reboot now? (yes/no): " reboot_confirm < /dev/tty
fi
if [[ "$reboot_confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "Rebooting system in 15 seconds... Please remember that you can check the log file at $LOG_FILE after the reboot to see the full details of the update."
    sleep 15
    reboot
else
    echo "Skipping reboot. Please remember to reboot manually to apply all changes."
fi

# The end

 


FileWave IVS Upgrade

ivs_upgrade.sh - This script is used by the Download page for IVS upgrades on Debian. Some details;

# To run this script, use the following 1-liner:
# wget -qO- https://kb.filewave.com/attachments/408 | sudo bash -s -- -v <version> -r <revision> [-b for beta] -y
# Example for version 15.5.0 with revision 1 in production:
# wget -qO-  https://kb.filewave.com/attachments/408 | sudo bash -s -- -v 15.5.0 -r 1 -p -y
# Optional: safer usage inside a 'screen' session to protect against SSH disconnects (single-line example):
#  sudo DEBIAN_FRONTEND=noninteractive bash -c 'apt-get update -y && apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" screen && screen -S fw_upgrade bash -c "wget -qO- https://kb.filewave.com/attachments/408 | bash -s -- -v 16.3.0 -r 1 -p -y"'

ivs_upgrade.sh
#!/bin/bash
# Version: 20251205.01

# FileWave IVS Upgrade Script
# Usage (example 1-liner):
#   wget -qO- https://kb.filewave.com/attachments/408 | sudo bash -s -- -v <version> -r <revision> [-d|--dev | -b|--beta | -p|--prod] [-y|--yes] [-yy|--yesyes]
# Example:
#   wget -qO- https://kb.filewave.com/attachments/408 | sudo bash -s -- -v 16.3.0 -r 1 -p -y
# Supports Debian 12 and 13. Newer FileWave versions may require Debian 13.
# Optional: safer usage inside a 'screen' session to protect against SSH disconnects (single-line example):
#   sudo DEBIAN_FRONTEND=noninteractive bash -c 'apt-get update -y && apt-get install -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" screen && screen -S fw_upgrade bash -c "wget -qO- https://kb.filewave.com/attachments/408 | bash -s -- -v 16.3.0 -r 1 -p -y"'

#################### VARIABLES / LOGS ##################

# Set default values for target FileWave version, revision, and download server type
VERSION="16.3.0"
REVISION="1"
SERVER_TYPE="prod"
BASE_URL="https://fwdl.filewave.com"
auto_yes=false
auto_risky_yes=false
OS_UPGRADED=false

# Function to handle errors and display messages
die() {
    echo "[ERROR] $1" >&2
    exit 1
}

# Ensure script is run with sudo/root privileges
if [ "$EUID" -ne 0 ]; then
    die "This script must be run with sudo or as root."
fi

# Log all actions to a dedicated log file for audit and troubleshooting
LOG_FILE="/var/log/filewave_ivs_update.log"
touch "$LOG_FILE" || die "Failed to create log file $LOG_FILE. Check permissions."
chmod 644 "$LOG_FILE" || die "Failed to set permissions on log file $LOG_FILE."
if [[ ! -w "$LOG_FILE" ]]; then
    die "Cannot write to log file $LOG_FILE. Please check permissions."
fi
exec > >(stdbuf -oL tee -a "$LOG_FILE") 2>&1
echo "Logging to $LOG_FILE"



################# OS Check ###############

# Validate Debian version (must be 12 or 13)
if ! grep -iq "^ID=debian" /etc/os-release; then
    die "Unsupported operating system. This script must be run on Debian 12 or Debian 13."
fi

# Extract major version number (e.g., 12 from 12.5)
DEBIAN_VERSION=$(grep -E '^VERSION_ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
DEBIAN_MAJOR=${DEBIAN_VERSION%%.*}

if ! [[ "$DEBIAN_MAJOR" =~ ^[0-9]+$ ]]; then
    die "Unable to determine Debian version. Aborting."
fi

if (( DEBIAN_MAJOR < 12 || DEBIAN_MAJOR > 13 )); then
    die "Unsupported Debian version ($DEBIAN_VERSION). Only Debian 12 and Debian 13 are supported."
fi

is_running_under_multiplexer() {
    # Detect whether this shell is running under a GNU screen session.
    # First, trust STY if present.
    if [[ -n "$STY" ]]; then
        return 0
    fi

    # Fallback: walk up the process tree looking for a 'screen' ancestor.
    # This helps when sudo or other wrappers strip environment variables.
    local pid=$$
    local depth=0
    while [[ "$pid" -gt 1 && $depth -lt 6 ]]; do
        local comm
        comm=$(ps -o comm= -p "$pid" 2>/dev/null | tr -d ' ')
        if [[ "$comm" == "screen" || "$comm" == "SCREEN" ]]; then
            return 0
        fi
        pid=$(ps -o ppid= -p "$pid" 2>/dev/null | tr -d ' ')
        [[ -z "$pid" ]] && break
        depth=$((depth + 1))
    done

    return 1
}


check_ssh_tty_safety() {
    # Safety check: encourage running under GNU screen for long-running upgrades,
    # especially when a major OS upgrade (Debian 12 → 13) is about to be performed.

    # Ensure screen is installed before any messaging
    if ! command -v screen >/dev/null 2>&1; then
        echo "[SESSION] 'screen' is not installed; installing it now to support detachable upgrade sessions..."
        DEBIAN_FRONTEND=noninteractive apt-get install -y -q screen || \
            echo "[SESSION] Warning: Failed to install 'screen'. Continuing without screen support."
    fi

    # --- CASE 1: User IS running inside screen ---
    if is_running_under_multiplexer; then
        echo "[SESSION] Running inside a 'screen' session; this is recommended for long-running upgrades."
        return 0
    fi

    # --- CASE 2: User is NOT running inside screen ---
    echo "[SESSION] This upgrade is not running inside 'screen'."
    echo "[SESSION] Because we are about to perform a major OS upgrade (Debian 12 → 13),"
    echo "[SESSION] it is strongly recommended to run this process inside a 'screen' session."
    echo "[SESSION] This protects you from SSH disconnects during the long upgrade, which"
    echo "[SESSION] could otherwise leave the system in a partially upgraded or unstable state."
    echo ""
    if command -v screen >/dev/null 2>&1; then
        echo "[SESSION] To create a protected session, run the following command in your terminal:"
        echo "[SESSION]   screen -S fw_upgrade"
        echo "[SESSION] After the screen session opens, paste the FileWave IVS upgrade 1-liner"
        echo "[SESSION] again so the entire upgrade runs inside that screen session."
        echo ""
    fi

    if [[ "$auto_risky_yes" == "true" ]]; then
        echo "[SESSION] Risky auto-yes mode enabled; continuing despite not running inside 'screen'."
        return 0
    fi

    read -p "You are NOT running inside 'screen'. Do you still want to continue with this upgrade? (yes/no): " ssh_continue < /dev/tty
    if [[ ! "$ssh_continue" =~ ^[Yy]([Ee][Ss])?$ ]]; then
        die "[SESSION] Aborting at user request because the upgrade is not running inside 'screen'. Please start a 'screen' session and re-run the upgrade."
    fi
}


################ Debian 13 Upgrade Helper ################
# Functions and constants to manage Debian 12 -> 13 release upgrades when required by FileWave version

# Minimum FileWave version that requires Debian 13
MIN_DEBIAN13_FW_VERSION="16.3.0"

# Placeholder for Debian 12 -> Debian 13 in-place upgrade
upgrade_to_debian13() {
    check_ssh_tty_safety
    
    echo "[DEBIAN-UPGRADE] Detected Debian 12 but target FileWave version $VERSION requires Debian 13."
    echo "[DEBIAN-UPGRADE] Newer FileWave versions ($MIN_DEBIAN13_FW_VERSION and above) are only supported on Debian 13 (trixie)."
    echo "[DEBIAN-UPGRADE] This is a long-running, in-place OS upgrade and may take considerable time."

    if is_running_under_multiplexer; then
        echo "[DEBIAN-UPGRADE] You are already running this upgrade under a 'screen' session."
        if command -v screen >/dev/null 2>&1; then
            echo "[DEBIAN-UPGRADE] Current screen sessions:"
            screen -list || true
        fi
        echo "[DEBIAN-UPGRADE] If you disconnect, you can typically reconnect with:"
        echo "[DEBIAN-UPGRADE]   screen -ls"
        echo "[DEBIAN-UPGRADE]   screen -r <session_id>"
    else
        echo "[DEBIAN-UPGRADE] It is strongly recommended that you run this under 'screen' to protect against disconnects."
        echo "[DEBIAN-UPGRADE] If you disconnect from an SSH session, you can later run: screen -ls"
        echo "[DEBIAN-UPGRADE] This will show something like: 'There is a screen on: 1234.pts-0.servername'"
        echo "[DEBIAN-UPGRADE] You can reconnect with: screen -r 1234"
    fi

    # Confirm with the admin before performing the Debian 12 -> 13 upgrade
    if [[ "$auto_risky_yes" == "true" ]]; then
        deb13_confirm="yes"
        echo "[DEBIAN-UPGRADE] Risky auto-yes mode enabled; proceeding with Debian 12 -> 13 upgrade without interactive confirmation."
    else
        read -p "Do you wish to proceed with the Debian 12 -> 13 OS upgrade now? (yes/no): " deb13_confirm < /dev/tty
    fi
    if [[ ! "$deb13_confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
        die "[DEBIAN-UPGRADE] Aborting Debian 12 -> 13 upgrade at user request. FileWave version $VERSION requires Debian 13. Please re-run and allow the OS upgrade, or choose an older FileWave version supported on Debian 12."
    fi

    # Ensure screen is available (do not forcibly attach to a screen session here)
    if ! command -v screen >/dev/null 2>&1; then
        echo "[DEBIAN-UPGRADE] Installing 'screen' to support detachable sessions..."
        DEBIAN_FRONTEND=noninteractive apt-get install -y -q screen || echo "[DEBIAN-UPGRADE] Warning: Failed to install 'screen'. Continuing without screen."
    fi

    # Check for at least 5 GiB free on the root filesystem
    REQUIRED_GIB=5
    avail_gib=$(df -BG / | awk 'NR==2 {gsub(/G/,"",$4); print $4}')
    if [[ -z "$avail_gib" ]]; then
        die "[DEBIAN-UPGRADE] Unable to determine free disk space on root filesystem. Aborting Debian upgrade."
    fi
    if (( avail_gib < REQUIRED_GIB )); then
        die "[DEBIAN-UPGRADE] Not enough free disk space for Debian 12 -> 13 upgrade. ${avail_gib} GiB available, but at least ${REQUIRED_GIB} GiB is required."
    fi

    echo "[DEBIAN-UPGRADE] Disk space check passed: ${avail_gib} GiB available. Proceeding with Debian upgrade..."

    # Clean up legacy FileWave APT lists to avoid stale suites
    rm -f /etc/apt/sources.list.d/filewave-beta.list > /dev/null 2>&1 || true
    rm -f /etc/apt/sources.list.d/filewave-dev.list > /dev/null 2>&1 || true
    rm -f /etc/apt/sources.list.d/filewave-release.list > /dev/null 2>&1 || true

    # Ensure current Debian 12 system is fully upgraded before changing suites
    echo "[DEBIAN-UPGRADE] Bringing Debian 12 (bookworm) fully up to date before release upgrade..."
    apt-get update -y || die "[DEBIAN-UPGRADE] Failed to update package list on Debian 12."
    DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y \
        -o Dpkg::Options::="--force-confdef" \
        -o Dpkg::Options::="--force-confold" \
        --autoremove || die "[DEBIAN-UPGRADE] Failed to fully upgrade Debian 12 prior to release upgrade."

    # Switch APT sources from bookworm to trixie
    echo "[DEBIAN-UPGRADE] Updating APT sources from bookworm to trixie..."
    sed -i 's/bookworm/trixie/g' /etc/apt/sources.list || die "[DEBIAN-UPGRADE] Failed to update /etc/apt/sources.list to trixie."
    find /etc/apt/sources.list.d -maxdepth 1 -type f -exec sed -i 's/bookworm/trixie/g' {} \; 2>/dev/null || true

    # Upgrade to Debian 13 (trixie)
    echo "[DEBIAN-UPGRADE] Running dist-upgrade to Debian 13 (trixie)..."
    apt-get update -y || die "[DEBIAN-UPGRADE] Failed to update package list after switching to trixie."
    DEBIAN_FRONTEND=noninteractive apt-get dist-upgrade -y \
        -o Dpkg::Options::="--force-confdef" \
        -o Dpkg::Options::="--force-confold" \
        --autoremove || die "[DEBIAN-UPGRADE] Debian 12 -> 13 release upgrade failed."

    # Optional: modernize APT sources to deb822 format on Debian 13
    if command -v apt >/dev/null 2>&1; then
        if apt modernize-sources --help >/dev/null 2>&1; then
            echo "[DEBIAN-UPGRADE] Modernizing APT sources to deb822 format on Debian 13..."
            apt modernize-sources --assume-yes || echo "[DEBIAN-UPGRADE] Warning: 'apt modernize-sources' failed. You may want to run it manually later."
        else
            echo "[DEBIAN-UPGRADE] This version of apt does not support 'apt modernize-sources'; skipping sources modernization."
        fi
    fi

    # Refresh Debian version info after upgrade
    DEBIAN_VERSION=$(grep -E '^VERSION_ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
    DEBIAN_MAJOR=${DEBIAN_VERSION%%.*}
    if (( DEBIAN_MAJOR != 13 )); then
        die "[DEBIAN-UPGRADE] Debian upgrade appears incomplete. Current VERSION_ID=$DEBIAN_VERSION (expected major version 13)."
    fi

    echo "[DEBIAN-UPGRADE] Debian upgrade to 13 (trixie) completed successfully. Continuing with FileWave $VERSION installation..."
    OS_UPGRADED=true
}

#################### SWITCHES ##################

if [ "$#" -eq 0 ]; then
    echo "Usage: wget -qO- https://kb.filewave.com/attachments/408 | sudo bash -s -- -v <version> -r <revision> [-d|--dev | -b|--beta | -p|--prod] [-y|--yes] [-yy|--yesyes]"
    echo "
Options:"
    echo "  -v, --version    Specify the version of FileWave IVS to install (e.g., 15.5.0)"
    echo "  -r, --revision   Specify the revision number (e.g., 1)"
    echo "  -d, --dev		 Use Dev server for downloads (default is production)"
    echo "  -b, --beta       Use beta server for downloads (default is production)"
    echo "  -p, --prod       Use production server for downloads"
    echo "  -y, --yes        Automatically answer yes to routine prompts (installation, OS patch upgrade, reboot). Does NOT auto-approve SSH-without-screen or Debian 12 -> 13 release upgrades."
    echo "  -yy, --yesyes    Automatically answer yes to all prompts, including SSH-without-screen warnings and Debian 12 -> 13 OS release upgrades."
    exit 1
fi

# Parse input arguments (-v/-r/-d/-b/-p/-y/-yy) and override defaults
while [[ "$#" -gt 0 ]]; do
    case $1 in
        -v|--version)
            VERSION="$2"
            shift 2
            ;;
        -r|--revision)
            REVISION="$2"
            shift 2
            ;;
		-d|--dev)
			SERVER_TYPE="dev"
			shift
			;;
        -b|--beta)
            SERVER_TYPE="beta"
            shift
            ;;
        -p|--prod)
            SERVER_TYPE="prod"
            shift
            ;;
        -y|--yes)
            auto_yes=true
            shift
            ;;
        -yy|--yesyes)
            auto_yes=true
            auto_risky_yes=true
            shift
            ;;          
        *)
            echo "Unknown option: $1"
            exit 1
            ;;
    esac
done

# ===================== SUMMARY TAG BLOCK =====================
DETECTED_DEBIAN_VERSION=$(grep -E '^VERSION_ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
DETECTED_DEBIAN_MAJOR=${DETECTED_DEBIAN_VERSION%%.*}
INSTALLED_IVS_VERSION=$(dpkg-query -W -f='${Version}' ivs-kernel 2>/dev/null || echo "unknown")

PLANNED_DEBIAN_BEHAVIOR="Unknown"
if dpkg --compare-versions "$VERSION" ge "$MIN_DEBIAN13_FW_VERSION"; then
    if (( DETECTED_DEBIAN_MAJOR == 12 )); then
        PLANNED_DEBIAN_BEHAVIOR="Upgrade Debian 12 -> 13 (trixie) before FileWave upgrade"
    elif (( DETECTED_DEBIAN_MAJOR == 13 )); then
        PLANNED_DEBIAN_BEHAVIOR="Stay on Debian 13 (trixie) for this upgrade"
    else
        PLANNED_DEBIAN_BEHAVIOR="Unsupported Debian major $DETECTED_DEBIAN_MAJOR for this FileWave version"
    fi
else
    if (( DETECTED_DEBIAN_MAJOR == 12 )); then
        PLANNED_DEBIAN_BEHAVIOR="Stay on Debian 12 (bookworm); no release upgrade"
    elif (( DETECTED_DEBIAN_MAJOR == 13 )); then
        PLANNED_DEBIAN_BEHAVIOR="Blocked combination: FileWave $VERSION is supported only on Debian 12"
    else
        PLANNED_DEBIAN_BEHAVIOR="Unsupported Debian major $DETECTED_DEBIAN_MAJOR for this FileWave version"
    fi
fi

echo "[SUMMARY] Detected Debian Version: $DETECTED_DEBIAN_VERSION"
echo "[SUMMARY] Installed FileWave IVS Version: $INSTALLED_IVS_VERSION"
if [[ "$INSTALLED_IVS_VERSION" == "unknown" || -z "$INSTALLED_IVS_VERSION" ]]; then
    echo "[SUMMARY] IVS Presence Check: NO — this system does not appear to have an existing FileWave IVS installation"
else
    echo "[SUMMARY] IVS Presence Check: YES — existing FileWave IVS installation detected"
fi
echo "[SUMMARY] Target FileWave Version: $VERSION-$REVISION"
echo "[SUMMARY] Server Type: $SERVER_TYPE"
echo "[SUMMARY] Auto-Yes Mode: $auto_yes"
echo "[SUMMARY] Risky Auto-Yes Mode (yesyes): $auto_risky_yes"
echo "[SUMMARY] Planned Debian behavior: $PLANNED_DEBIAN_BEHAVIOR"
echo "[SUMMARY] Beginning validation and upgrade process..."
# =============================================================


################ Debian / FileWave Version Matrix ################
# Enforce supported Debian major versions (12 vs 13) based on the requested FileWave version

# Enforce supported Debian version based on target FileWave version
if dpkg --compare-versions "$VERSION" ge "$MIN_DEBIAN13_FW_VERSION"; then
    # For FileWave 16.3.0 and newer, require Debian 13
    if (( DEBIAN_MAJOR == 12 )); then
        upgrade_to_debian13
    elif (( DEBIAN_MAJOR == 13 )); then
        echo "Debian 13 detected; proceeding with FileWave $VERSION."
    else
        die "Unsupported Debian major version $DEBIAN_MAJOR for FileWave $VERSION. Debian 13 is required."
    fi
else
    # For FileWave versions older than 16.3.0, require Debian 12 and do not upgrade to Debian 13
    if (( DEBIAN_MAJOR != 12 )); then
        die "FileWave $VERSION is only supported on Debian 12. Current Debian version is $DEBIAN_VERSION."
    fi
fi

#################### MAIN ##################

# Confirm high-level IVS upgrade action with the operator (unless auto-yes mode applies)
echo "This script will update your OS and install/upgrade the FileWave IVS packages."
echo "Version: $VERSION, Revision: $REVISION, Server Type: $SERVER_TYPE"
if [[ "$auto_yes" == "true" ]]; then
    confirm="yes"
else
    read -p "Do you wish to proceed? (yes/no): " confirm < /dev/tty
fi
if [[ ! "$confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "Aborting installation as requested."
    exit 0
fi

# Resolve the base download URL according to server type (prod/beta/dev)
if [ "$SERVER_TYPE" = "beta" ]; then
    BASE_URL="https://fwbetas.filewave.com"
elif [ "$SERVER_TYPE" = "dev" ]; then
    BASE_URL="https://fwdevdl.filewave.com"
else
    # Default to production download server
    BASE_URL="https://fwdl.filewave.com"
fi

###################################################
# 0. Remove legacy FileWave APT sources that were shipped with older IVS images
#    (avoids stale or conflicting repository entries during OS/FileWave upgrades)
rm -f /etc/apt/sources.list.d/filewave-beta.list > /dev/null || true
rm -f /etc/apt/sources.list.d/filewave-dev.list > /dev/null || true
rm -f /etc/apt/sources.list.d/filewave-release.list > /dev/null || true

###################################################
# 1. Ensure essential tools (python3, curl, zip, gdebi) are present for the upgrade process
echo "Installing essential tools..."
apt-get clean || die "Failed to clean apt cache."
apt-get update -y || die "Failed to update package list."
apt-get --fix-broken install -y || die "Failed to fix broken installs from apt."
apt-get autoremove -y || die "Failed to autoremove from apt."

for dep in "python3" "curl" "zip" "gdebi"; do
    if ! command -v $dep &> /dev/null; then
        echo "$dep not found. Installing $dep..."
        apt-get update -qq 
        DEBIAN_FRONTEND=noninteractive apt-get install -y -q "$dep" || die "Failed to install $dep."
        #apt-get install -y $dep || die "Failed to install $dep."
    fi
done

# Handle iperf3 separately because it prompts to start a systemd service; preseed and enable non-interactively
if ! command -v iperf3 &>/dev/null; then
    echo "iperf3 not found. Installing iperf3 and enabling service..."
    
    # Preseed debconf to automatically accept starting the service
    echo "iperf3 iperf3/start_daemon boolean true" | debconf-set-selections
    
    # Install non-interactively
    DEBIAN_FRONTEND=noninteractive apt-get install -y -q iperf3 || die "Failed to install iperf3."
    
    # Ensure the systemd service is enabled and started
    systemctl enable --now iperf3 || die "Failed to enable/start iperf3 service."
    
    # If UFW is installed and active, open TCP 5201 (iperf3). Do nothing otherwise.
    if command -v ufw >/dev/null 2>&1; then
        if ufw status | grep -q "Status: active"; then
            if ! ufw status | grep -q "5201/tcp"; then
                echo "UFW detected and active; allowing TCP 5201 for iperf3..."
                ufw allow 5201/tcp
            else
                echo "UFW rule for 5201/tcp already present; skipping."
            fi
        else
            echo "UFW installed but not active; not adding firewall rule."
        fi
    else
        echo "UFW not installed; skipping firewall configuration."
    fi
fi

if ! dpkg-query -W -f='${Status}' net-tools 2>/dev/null | grep -q "install ok installed"; then
    echo "net-tools not found. Installing net-tools..."
    apt-get install -y net-tools || die "Failed to install net-tools."
fi

# Check current version
INSTALLED_VERSION=$(dpkg-query -W -f='${Version}' ivs-kernel 2>/dev/null || true)
if [[ -z "$INSTALLED_VERSION" || "$INSTALLED_VERSION" == "none" ]]; then
    die "No FileWave IVS packages are installed. This script only supports upgrading an existing FileWave IVS appliance and cannot perform a fresh installation. Please deploy a supported FileWave IVS appliance image first, then re-run this script for upgrades."
fi

# Extract installed main version and revision
INSTALLED_MAIN_VERSION=$(echo "$INSTALLED_VERSION" | cut -d'-' -f1)
INSTALLED_REVISION=$(echo "$INSTALLED_VERSION" | cut -d'-' -f2)

if [[ -z "$INSTALLED_REVISION" ]]; then
    INSTALLED_REVISION=0
fi

# Prevent installing FileWave IVS 15.5.0 (known unsupported release); require 15.5.1 or newer
if dpkg --compare-versions "$VERSION" eq "15.5.0"; then
    echo "Installing FileWave IVS 15.5.0 is not supported. Please install version 15.5.1 or newer."
    exit 1
fi

# Prevent downgrades (but allow reinstalling the same version)
if dpkg --compare-versions "$INSTALLED_MAIN_VERSION" gt "$VERSION" || \
   ( dpkg --compare-versions "$INSTALLED_MAIN_VERSION" eq "$VERSION" && [[ "$INSTALLED_REVISION" -gt "$REVISION" ]] ); then
    echo "Installed version ($INSTALLED_VERSION) is newer than the requested version ($VERSION-$REVISION)."
    echo "Aborting to prevent a downgrade of the FileWave IVS server."
    exit 1
fi

if dpkg --compare-versions "$INSTALLED_MAIN_VERSION" eq "$VERSION" && [[ "$INSTALLED_REVISION" -eq "$REVISION" ]]; then
    echo "Requested version ($VERSION-$REVISION) matches the currently installed version ($INSTALLED_VERSION)."
    echo "Proceeding with a reinstall of the same FileWave IVS version."
fi


install_packages() {
    echo "Downloading and installing FileWave IVS packages..."
    PACKAGE_ORDER=(
        "filewave-admin_${VERSION}_amd64.deb"
        "filewave-imaging-client_${VERSION}_amd64.deb"
        "ivs-kernel-${VERSION}-${REVISION}.x86_64.deb"
        "filewave-ivs_${VERSION}_amd64.deb"
    )
    DOWNLOAD_DIR="/tmp/filewave_install_$$"
    mkdir -p "$DOWNLOAD_DIR" || die "Failed to create download directory."
    trap 'rm -rf "$DOWNLOAD_DIR"' EXIT
    for package in "${PACKAGE_ORDER[@]}"; do
        echo "Downloading $package..."
        for i in {1..3}; do
            wget -q -O "$DOWNLOAD_DIR/$package" "$BASE_URL/$VERSION/$package" && break
            echo "Retrying download ($i/3)..."
            sleep 5
        done
        if [[ ! -f "$DOWNLOAD_DIR/$package" ]]; then
            die "Failed to download $package after multiple attempts."
        fi
        echo "Installing $package..."
        gdebi -n "$DOWNLOAD_DIR/$package" || die "Failed to install $package"
    done

    trap 'rm -rf "$DOWNLOAD_DIR"' EXIT
}


# If we reach this point, the requested version is newer than the installed version.
echo "Upgrading from $INSTALLED_VERSION to $VERSION-$REVISION..."
install_packages


###################################################
# 4. OS Upgrade
#    - If a full Debian 12 → 13 upgrade already occurred, skip.
#    - Otherwise, update the current Debian release to the latest patches.
if [[ "$OS_UPGRADED" == "true" ]]; then
    echo "[OS-UPGRADE] Skipping generic OS upgrade step because a full Debian upgrade to 13 has already been performed in this run."
else
    echo "Warning: This script will upgrade the entire OS. This is required for security."
    if [[ "$auto_yes" == "true" ]]; then
        upgrade_confirm="yes"
    else
        read -p "Do you wish to proceed with the OS upgrade? (yes/no): " upgrade_confirm < /dev/tty
    fi
    if [[ ! "$upgrade_confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
        echo "[OS-UPGRADE] Skipping OS upgrade at user request."
    else
        echo "[OS-UPGRADE] Upgrading the system..."
        apt-get update -y || die "[OS-UPGRADE] Failed to update package list."
        DEBIAN_FRONTEND=noninteractive apt-get upgrade -y \
            -o Dpkg::Options::="--force-confdef" \
            -o Dpkg::Options::="--force-confold" \
            --autoremove || die "[OS-UPGRADE] System upgrade failed."
    fi
fi

###################################################
# 5. Reboot to complete OS and FileWave IVS updates
echo "The system will reboot in 15 seconds to complete the installation."
if [[ "$auto_yes" == "true" ]]; then
    reboot_confirm="yes"
else
    read -p "Do you want to reboot now? (yes/no): " reboot_confirm < /dev/tty
fi
if [[ "$reboot_confirm" =~ ^[Yy]([Ee][Ss])?$ ]]; then
    echo "[SUMMARY-END] Finalizing upgrade..."
    echo "[SUMMARY-END] Debian Version After Upgrade: $DEBIAN_VERSION"
    echo "[SUMMARY-END] FileWave IVS Version Installed: $VERSION-$REVISION"
    echo "[SUMMARY-END] Major OS Upgrade Performed (Debian 12 -> 13): $OS_UPGRADED"
    echo "[SUMMARY-END] Log File: $LOG_FILE"

echo "Rebooting system in 15 seconds... Please remember that you can check the log file at $LOG_FILE after the reboot to see the full details of the update."
    sleep 15
    reboot
else
    echo "Skipping reboot. Please remember to reboot manually to apply all changes."
fi

# The end