Zmanda Pro Client Installation

This guide provides clear instructions for installing, upgrading, and uninstalling the software, ensuring your data remains secure throughout the process.

Windows Installation

Watch our YouTube video to learn how to download and set up Zmanda Pro on your Windows devices.

System Requirements

  • Processor: x86 or x86-64 processor (minimum 4 cores/threads), Recommended: 8+ cores/threads

  • Memory: Minimum: 8 GB, Recommended: 16 GB

  • Operating System: Windows 7 or newer, Windows Server 2008 R2 or newer

Installation

  1. Log in to the admin account and create a new user.

  2. Go to the download section and download the client software for Windows.

  3. Choose the "Any CPU" option.

  4. Locate the downloaded file, unzip it, and run it to start the installation.

  5. Follow the on-screen instructions to complete the installation.

  6. Open the application and log in with your user account details created in step 1.

Zmanda Provides Powershell scripts for silent installation and remote registration. These scripts can be used in tandem with MDM/RMM software to automatically install the agent and start jobs on remote systems. Click here for more information about deploying devices in bulk with ZPAT.

Upgrading

Manual Upgrade: Download and run the updated installer. Configurations and active jobs will be preserved.

Remote Upgrade: If you are using the SaaS version of Zmanda, client upgrades are automatic and non-disruptive to any running jobs.

If a device does not get upgraded automatically, or if you are using the on-premise version of Zmanda Pro, you can manually upgrade individual devices by going to the Devices menu > Select the device > Actions > Update software.

Uninstalling

You can manually uninstall Zmanda Pro from Windows systems through the Control Panel.

You can also uninstall remotely by clicking the Uninstall Software button in the screenshot above and following the prompts to preserve/remove user settings.

macOS Installation

This guide simplifies installation, upgrades, and uninstallation, ensuring a smooth experience.

Installation:

  1. Log in to the admin account and create a new backup user

  2. Navigate to the download section and select the client software for macOS.

  3. Initiate the download process by choosing the appropriate option.

  4. Once the download is complete, locate the file in your Downloads folder and double-click to start the installation.

  5. Follow the on-screen instructions to complete the installation.

  6. Launch the application and log in using the user account credentials.

Upgrading:

Simply run the downloaded update file. It will safely remove the previous version and install the new one, keeping your configuration intact.

Uninstalling:

  1. Start the terminal: Open the Terminal program by selecting it from the Applications folder.

  2. Run the command: Copy and paste the provided uninstallation command into the Terminal window and press Enter.

/sudo -u root "/Applications/Zmanda Pro.app/Contents/Resources/uninstall"

You can manually remove the saved credentials prior to uninstallation by running the following command:

/Applications/Zmanda Pro.app/Contents/MacOS/backup-tool login disconnect
  1. Observe instructions: Once the uninstallation has been established, wait for the procedure to finish.

System requirements:

  • CPU: x86-64 or Apple Silicon processor (minimum 4 cores/threads)

  • RAM: Minimum: 8 GB, Recommended: 16 GB

  • OS: macOS 10.13 "High Sierra" or newer

  • Hard Drive: SSD or NVME Drive recommended

Linux Installation

This guide provides detailed installation instructions for Zmanda Pro across different Linux distributions and NAS systems.

Check out this video tutorial on How to Install Zmanda Pro on Linux Client: Installing Zmanda Pro on Linux Client (youtube.com)

System Requirements

Ensure your systems meet these minimum specifications:

  • CPU: x86 with SSE2, x86-64, or ARM processor, minimum 4 cores/threads

  • Memory: 8 GB minimum, 16 GB recommended

  • Operating System: Various Linux distributions, as specified

  • Storage: SSD or NVME Drive recommended

  • Network: Stable internet connection with at least 1 Mbps download/upload speed

Installation on Debian and Ubuntu

Standard Installation

  1. Download:

    • Download the .deb package from the Zmanda Pro website.

    • Ensure you have sudo or root access to install packages.

  2. Installation:

    • Install using the Debian package manager:

      sudo apt install ./ZmandaPro_Backup-xx.x.x.deb

    • The installer will install the software into the /opt/ZmandaPro/ subdirectory.

    • During installation, you'll be prompted to enter the server URL, username, and password to register the device with Zmanda Pro's central management.

  3. Managing the Service: Use systemctl to start, stop, and check the status of the Zmanda Pro service:

    sudo systemctl start zmanda-pro 
    sudo systemctl stop zmanda-pro 
    sudo systemctl status zmanda-pro

Silent Installation

  • Debconf Pre-seeding:

    • Pre-seed answers to installation prompts for a non-interactive setup:

      echo 'zmanda-pro zmanda-pro/server string your-server.com' | debconf-set-selections sudo DEBIAN_FRONTEND=noninteractive apt-get install zmanda-pro

Package Compatibility

  • Upgrading:

    • Install the .deb package over an existing "Other distribution" .run package. The installer will convert settings appropriately.

  • Reinstallation:

    • Installing an older .run package over a newer .deb installation could result in a mixed installation. Safely uninstall the .deb package first to avoid this.

Installation on Red Hat Enterprise Linux (RHEL) and CentOS

Installation Process

  1. Download:

    • Download the .rpm package from the Zmanda Pro website.

  2. Installation:

    • Install using the RPM package manager:

      sudo rpm -i ZmandaPro_Backup-xx.x.x.rpm

    • Follow the prompts to configure the software.

Installation on Synology NAS

Installation Steps

  1. Preparation:

    • Ensure your Synology NAS is running DSM 6 or later.

    • Download the appropriate SPK file from the Zmanda Pro website.

  2. Package Center:

    • Navigate to the Package Center on your Synology dashboard.

    • Select "Manual Install" and upload the SPK file.

  3. Setup:

    • If on DSM 6, ensure "Any publisher" is selected under Trust Level.

    • For DSM 7, accept the third-party package prompt.

    • Enter credentials for the Zmanda Pro Server and user.

Permissions on DSM 7

  • User Permissions:

    • Zmanda Pro runs under a package-specific user named backuptool.

    • Grant backuptool access to Shared Folders via the Control Panel to perform backups and restores.

Limitations

  • Package User Restrictions:

    • Remote upgrades/uninstalls are not supported. Manual installation of new versions is required.

    • Restore operations may not correctly restore permissions due to user restrictions.

Restarting at Boot

  • Startup Scripts:

    • Configure the system to run the backup-daemon-start.sh at boot using methods like rc.local, systemd, or cron.

After Installation

  • Testing:

    • Perform backup and restore tests to ensure the system is configured correctly.

  • Documentation:

    • Maintain documentation of the installation process and configurations for compliance and troubleshooting.

Troubleshooting and Support

  • Common Issues:

    • Ensure all dependencies are met, particularly for network and storage configurations.

    • Check the firewall settings that might block Zmanda Pro's operations.

Client CLI Commands

The Linux agent provides a simple CLI for tasks like seeing the client version, logging in and out, and displaying simple client info.

To see a list of all options, run /opt/ZmandaPro/backup-tool help

To show the login status, run /opt/ZmandaPro/backup-tool login status

To show the login prompt (to login for the first time, to use different login credentials, or to re-login), run /opt/ZmandaPro/backup-tool login prompt

To disconnect the agent from the Zmanda Pro server, run /opt/ZmandaPro/backup-tool login disconnect

To join the client to a server using lobby mode (for remote installation) run /opt/ZmandaPro/backup-tool join-lobby [your-server-url

Silent Installation Scripts

These scripts can be used for one-off installations or bulk installations with ZPAT to register 1000+ devices at once.

Windows

When using the script with ZPAT ansible scripts, leave variables as-is.

If not using ZPAT, follow these steps:

  1. Replace @@ZP_SERVER_FQDN@@ in the $downloadUrl variable at the top of the file with your FQDN. Make sure to include the /dl/1 endpoint.

  2. Replace @@ZP_CA_CERT@@ in the $certContent variable at the top of the file with your cert.

  3. Run the script with administrator privileges. The device will appear in the Zmanda Pro console in an Unregistered state. You can use ZPAT to automatically create a unique user and register the device, or register the device to an existing user manually.

# NOTE: download URL will be automatically set from the defaults file
# or the command line argument when the packaged ansible playbooks are run with
# the specific configurations.

# Replace this download URL with the required one.
param (
    [switch]$uninstall,
    [switch]$certs
)

$downloadUrl = "https://@@ZP_SERVER_FQDN@@/dl/1"

$certContent = "@@ZP_CA_CERT@@"

function Install-Certificate {
    param (
        [Parameter(Mandatory = $true)]
        [string]$certContent
    )
    try {
        # Convert the certificate content to a byte array
        $certBytes = [System.Text.Encoding]::UTF8.GetBytes($certContent)

        # Create a certificate object from the byte array
        $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($certBytes)

        # Get the root store for Trusted Root Certification Authorities
        $rootStore = Get-Item "Cert:\LocalMachine\Root"

        # Add the certificate to the root store
        $rootStore.Open("ReadWrite")
        $rootStore.Add($cert)
        $rootStore.Close()

        # Write success message to standard output
        Write-Output "Certificate installed successfully."
    }
    catch {
        # Write error message to standard error
        Write-Error "An error occurred: $_"
        throw
    }
}

function Uninstall-ZmandaPro {
    $zproUninstallExec = "C:\Program Files\Zmanda Pro\Uninstall.exe"
    # Define registry key for existing installation check
    $registryKeyPath = "HKLM:\SOFTWARE\backup-tool"
    $installDirectoryValue = "InstallDirectory"

    # Check if the registry key exists
    if (Test-Path -Path $registryKeyPath) {
        # Get the install directory from the registry
        $installDirectory = (Get-ItemProperty -Path $registryKeyPath -Name $installDirectoryValue).$installDirectoryValue

        # Check if the install directory exists
        if (Test-Path -Path $installDirectory -PathType Container) {
            # Set the current location to the install directory
            Set-Location -Path $installDirectory

            # Construct the uninstall command
            $uninstallCommand = ".\backup-tool.exe login disconnect"

            # Run the uninstall command using Invoke-Expression
            try {
                Invoke-Expression -Command $uninstallCommand
                Write-Output "Disconnected from Zmanda Pro Server"
            }
            catch {
                Write-Error "Error executing uninstall command: $_"
            }
        }
    }
    else {
        Write-Output "Zmanda Pro is not installed or registry key not found."
    }
    if (Test-Path -Path $zproUninstallExec) {
        try {
            Start-Process -FilePath $zproUninstallExec -ArgumentList "/S", "/ISDELETECREDENTIAL=yes" -Wait -NoNewWindow
            Write-Output "Successfully uninstalled Zmanda Pro"
        }
        catch {
            Write-Error "Error executing Zmanda Pro uninstall command: $_"
        }
    }
    else {
        Write-Output "Zmanda Pro uninstaller not found at $zproUninstallExec"
    }
}

function Install-ZmandaPro {
    try {
        [Net.ServicePointManager]::SecurityProtocol = "tls13, tls12"
    }
    catch {
        Write-Error "Falling back to tls12"
        [Net.ServicePointManager]::SecurityProtocol = "tls12"
    }

    # Set the ZONEINFO environment variable
    $zoneInfoPath = "C:\Program Files\Zmanda Pro\vendor\tzdata\zoneinfo.zip"
    [System.Environment]::SetEnvironmentVariable("ZONEINFO", $zoneInfoPath, [System.EnvironmentVariableTarget]::Machine)

    # Verify the ZONEINFO environment variable
    $env:ZONEINFO = [System.Environment]::GetEnvironmentVariable("ZONEINFO", [System.EnvironmentVariableTarget]::Machine)
    Write-Output "ZONEINFO is set to: $env:ZONEINFO"

    # Define registry key for existing installation check
    $registryKeyPath = "HKLM:\SOFTWARE\backup-tool"
    $installDirectoryValue = "InstallDirectory"

    # Check if the registry key exists
    if (Test-Path -Path $registryKeyPath) {
        # Get the install directory from the registry
        $installDirectory = (Get-ItemProperty -Path $registryKeyPath -Name $installDirectoryValue).$installDirectoryValue

        # Check if the install directory exists
        if (Test-Path -Path $installDirectory -PathType Container) {
            # Set the current location to the install directory
            Set-Location -Path $installDirectory

            # Construct the uninstall command
            $uninstallCommand = ".\backup-tool.exe login disconnect"

            # Run the uninstall command using Invoke-Expression
            try {
                Invoke-Expression -Command $uninstallCommand
                Write-Output "Uninstall command executed successfully"
            }
            catch {
                Write-Error "Error executing uninstall command: $_"
            }
        }
    }

    $temporaryFolder = [System.IO.Path]::Combine($env:USERPROFILE, "AppData\Local\Temp\ZmandaPro")

    try {
        # Step 0: Clear temporary locations if they exist
        if (Test-Path -Path $temporaryFolder -PathType Container) {
            Remove-Item -Path $temporaryFolder -Recurse -Force
            Write-Output "Temporary folder cleared"
        }

        # Step 1: Create a temporary directory
        New-Item -Path $temporaryFolder -ItemType Directory -Force
        Write-Output "Temporary directory created: $temporaryFolder"

        # Step 2: Go inside the temporary directory
        Set-Location -Path $temporaryFolder
        Write-Output "Current location set to: $temporaryFolder"

        # Step 3: Download the zip file with custom User-Agent header
        $zipFileName = "Zmanda Pro.zip"
        $headers = @{
            "User-Agent" = "zmandapro-installer"
        }
        Invoke-WebRequest -Uri $downloadUrl -OutFile $zipFileName -Headers $headers
        Write-Output "Zip file downloaded: $zipFileName"

        # Step 4: Extract the zip file
        Expand-Archive -Path $zipFileName -DestinationPath $temporaryFolder
        Write-Output "Zip file extracted"

        # Step 5: Check for .exe files in the extracted folder and rename to 'install.exe'
        $extractedFolder = Get-ChildItem -Path $temporaryFolder | Where-Object { $_.PSIsContainer } | Select-Object -ExpandProperty Name
        $exeFiles = Get-ChildItem -Path (Join-Path -Path $temporaryFolder -ChildPath $extractedFolder) -Filter *.exe

        foreach ($exeFile in $exeFiles) {
            $newName = Join-Path -Path $exeFile.Directory.FullName -ChildPath "install.exe"
            Rename-Item -Path $exeFile.FullName -NewName $newName -Force
            Write-Output "Renamed $($exeFile.Name) to install.exe"
        }

        # Step 6: Go into the extracted folder
        Set-Location -Path (Join-Path -Path $temporaryFolder -ChildPath $extractedFolder)
        Write-Output "Current location set to extracted folder"

        # Step 7: Create a batch file with the install command
        $batchFile = Join-Path -Path $temporaryFolder -ChildPath "install.bat"
        Set-Content -Path $batchFile -Value ".\install.exe /ISLOCALSYSTEM=yes /S /LOBBY"
        Write-Output "Batch file created: $batchFile"

        # Step 8: Run the batch file
        Start-Process -FilePath $batchFile -Wait
        Write-Output "Installation batch file executed"

    }
    catch {
        Write-Error "An error occurred: $_"
    }
    finally {
        Set-Location ~\Downloads
        Write-Output "Script execution completed. Current location set to Downloads folder."
    }
}

if ($uninstall) {
    Uninstall-ZmandaPro
}
elseif ($certs) {
    if ($certContent -eq "@@ZP_CA_CERT@@") {
        Write-Error "CA Certificate content is not set. Please set the CA Certificate content in the Zmanda Pro Windows Client Install Script."
        exit 1
    }
    Install-Certificate -certContent $certContent
}
else {
    # Run the default installation flow
    if ($certContent -eq "@@ZP_CA_CERT@@") {
        Write-Output "CA Certificate content is not set. Skipping certificate installation."
    }
    else {
        Install-Certificate -certContent $certContent
    }
    Install-ZmandaPro
}

Linux

When using the script with ZPAT ansible scripts, leave variables as-is.

If not using ZPAT, follow these steps:

  1. Replace @@ZP_SERVER_FQDN@@ in the DOWNLOAD_URL variable at the top of the file with your FQDN. Make sure to include the /dl/1 endpoint.

  2. Replace @@ZP_CA_CERT@@ in the CA_CERT_CONTENT variable at the top of the file with your cert content.

  3. OPTIONAL - Replace the content within the DISTRO variable with your Linux Distribution

  4. Run the script with administrator privileges. The device will appear in the Zmanda Pro console in an Unregistered state. You can use ZPAT to automatically create a unique user and register the device, or register the device to an existing user manually.

#!/bin/bash
# Replace this download URL with the required one
# NOTE: Download URL will be automatically replaced with the actual URL
# when the packaged ansible playbooks are run with the specific configurations 
DOWNLOAD_URL="https://@@ZP_SERVER_FQDN@@/dl/7"

CA_CERT_CONTENT="@@ZP_CA_CERT@@"

DISTRO=""

# Define the temporary folder
temporary_folder="$(mktemp -d)"

# Copy the certificate content to a temporary file
echo "$CA_CERT_CONTENT" > /tmp/ZmandaProCA.crt

#-------------------------------------------------------
# Install Prerequisites
#-------------------------------------------------------
function install_prerequisites() {
    case "$DISTRO" in
        rhel|centos|fedora|rocky|almalinux|ol)
            if ! command -v wget > /dev/null 2>&1; then
                echo "Installing wget package..."
                sudo yum install -y wget
            fi
            ;;
        arch)
            if ! command -v wget > /dev/null 2>&1; then
                echo "Installing wget package..."
                sudo pacman -S --noconfirm wget
            fi
            ;;
        debian|ubuntu|linuxmint)
            if ! command -v wget > /dev/null 2>&1; then
                echo "Installing wget package..."
                sudo apt-get install -y wget
            fi
            ;;
        suse)
            if ! command -v wget > /dev/null 2>&1; then
                echo "Installing wget package..."
                sudo zypper install -y wget
            fi
            ;;
        alpine)
            if ! command -v wget > /dev/null 2>&1; then
                echo "Installing wget package..."
                sudo apk add --no-cache wget
            fi
            ;;
        gentoo)
            if ! command -v wget > /dev/null 2>&1; then
                echo "Installing wget package..."
                sudo emerge -v net-misc/wget
            fi
            ;;
        *)
            echo "Error: Unsupported distribution for prerequisites installation."
            return 1
            ;;
    esac
}

#-------------------------------------------------------
# Perform Linux Distribution Compatibility Check
#-------------------------------------------------------
function distrocheck() {
    echo "Performing Linux distribution check..."

    # Check for /etc/os-release file
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        DISTRO="${ID,,}" # Using bash parameter expansion to convert to lowercase
    # Check for legacy files
    elif [ -f /etc/redhat-release ]; then
        DISTRO=$(awk '{print tolower($1)}' /etc/redhat-release)
    elif [ -f /etc/debian_version ]; then
        DISTRO="debian"
    elif [ -f /etc/alpine-release ]; then
        DISTRO="alpine"
    elif [ -f /etc/arch-release ]; then
        DISTRO="arch"
    elif [ -f /etc/gentoo-release ]; then
        DISTRO="gentoo"
    elif [ -f /etc/SuSE-release ]; then
        DISTRO="suse"
        if grep -qi "enterprise" /etc/SuSE-release; then
            DISTRO_TYPE="sles"
        elif grep -qi "opensuse" /etc/SuSE-release; then
            DISTRO_TYPE="opensuse"
        fi
    elif [ -f /etc/linuxmint/info ]; then
        DISTRO="linuxmint"
    else
        DISTRO="unknown"
    fi

    # Additional checks to differentiate similar distributions
    if [ "$DISTRO" = "rhel" ] || [ "$DISTRO" = "centos" ] || [ "$DISTRO" = "fedora" ] || [ "$DISTRO" = "rocky" ] || [ "$DISTRO" = "almalinux" ] || [ "$DISTRO" = "ol" ]; then
        if [ -f /etc/fedora-release ]; then
            DISTRO="fedora"
        elif [ -f /etc/centos-release ]; then
            DISTRO="centos"
        elif [ -f /etc/rocky-release ]; then
            DISTRO="rocky"
        elif [ -f /etc/almalinux-release ]; then
            DISTRO="almalinux"
        elif [ -f /etc/oracle-release ]; then
            DISTRO="ol"
        else
            DISTRO="rhel"
        fi
    elif [ "$DISTRO" = "debian" ] && [ -f /etc/lsb-release ]; then
        . /etc/lsb-release
        if [ "${DISTRIB_ID,,}" = "ubuntu" ]; then
            DISTRO="ubuntu"
        fi
    elif [ "$DISTRO" = "ubuntu" ] && [ -f /etc/linuxmint/info ]; then
        DISTRO="linuxmint"
    fi

    # Output additional system information for logging purposes
    echo "Detected distribution: $DISTRO"
}

#-------------------------------------------------------
# Install CA Certificate
#-------------------------------------------------------
function install_ca_certificate() {
    distrocheck

    echo "Proceeding with CA certificate update for $DISTRO"

    # Update CA certificates based on the distribution
    case "$DISTRO" in
        rhel|centos|fedora|rocky|almalinux|ol)
            if ! command -v update-ca-trust > /dev/null 2>&1; then
                echo "Installing ca-certificates package..."
                sudo yum install -y ca-certificates
            fi
            sudo cp -f /tmp/ZmandaProCA.crt /etc/pki/ca-trust/source/anchors/ZmandaProCA.crt
            sudo update-ca-trust
            echo "Certificates updated and placed in the system trust store."
            ;;
        arch)
            if ! command -v update-ca-trust > /dev/null 2>&1; then
                echo "Installing ca-certificates package..."
                sudo pacman -S --noconfirm ca-certificates
            fi
            sudo cp -f /tmp/ZmandaProCA.crt /etc/ca-certificates/trust-source/anchors/ZmandaProCA.crt
            sudo update-ca-trust
            echo "Certificates updated and placed in the system trust store."
            ;;
        debian|ubuntu|linuxmint)
            if ! command -v update-ca-certificates > /dev/null 2>&1; then
                echo "Installing ca-certificates package..."
                sudo apt-get install -y ca-certificates
            fi

            sudo cp -f /tmp/ZmandaProCA.crt /usr/local/share/ca-certificates/ZmandaProCA.crt
            sudo update-ca-certificates
            echo "Certificates updated and placed in /etc/ssl/certs/"
            ;;
        suse)
            if ! command -v update-ca-certificates > /dev/null 2>&1; then
                echo "Installing ca-certificates package..."
                sudo zypper install -y ca-certificates
            fi

            sudo cp -f /tmp/ZmandaProCA.crt /usr/share/pki/trust/anchors/ZmandaProCA.crt
            sudo update-ca-certificates
            echo "Certificates updated and placed in /etc/ssl/certs/"
            ;;
        alpine)
            if ! command -v update-ca-certificates > /dev/null 2>&1; then
                echo "Installing ca-certificates package..."
                sudo apk add --no-cache ca-certificates
            fi

            sudo cp -f /tmp/ZmandaProCA.crt /usr/local/share/ca-certificates/ZmandaProCA.crt
            sudo update-ca-certificates
            echo "Certificates updated and placed in /etc/ssl/certs/"
            ;;
        gentoo)
            if ! command -v update-ca-certificates > /dev/null 2>&1; then
                echo "Installing ca-certificates package..."
                sudo emerge -v app-misc/ca-certificates
            fi

            sudo cp -f /tmp/ZmandaProCA.crt /usr/share/ca-certificates/ZmandaProCA.crt
            sudo update-ca-certificates
            echo "Certificates updated and placed in /etc/ssl/certs/"
            ;;
        *)
            echo "Error: Unsupported distribution for CA certificate installation."
            return 1
            ;;
    esac
    rm -f /tmp/ZmandaProCA.crt
    echo "Certficate installation complete."
}

#-------------------------------------------------------
# Perform Zmanda Pro Client Architecture Compatibility Check
#-------------------------------------------------------
function check_cpu_requirements() {
    echo "Checking CPU requirements..."
    
    # Get CPU architecture
    cpu_arch=$(uname -m)
    
    # Check for SSE2 support on x86 architectures
    if [[ "$cpu_arch" == "i686" || "$cpu_arch" == "i386" ]]; then
        if ! grep -q sse2 /proc/cpuinfo; then
            echo "Error: x86 32-bit CPU detected without SSE2 support. This system does not meet the minimum requirements."
            exit 1
        fi
    fi
    
    # Check ARM version if applicable
    if [[ "$cpu_arch" == arm* ]]; then
        arm_version=$(readelf -A /proc/self/exe | grep Tag_CPU_arch | awk '{print $2}')
        if [[ "$cpu_arch" == "armv7l" && "$arm_version" -lt 7 ]]; then
            echo "Error: ARM 32-bit v7l or higher is required. This system does not meet the minimum requirements."
            exit 1
        elif [[ "$cpu_arch" == "armv6l" && "$arm_version" -lt 6 ]]; then
            echo "Error: ARM 32-bit v6l or higher is required. This system does not meet the minimum requirements."
            exit 1
        fi
        
        # Check for VFP support on ARM 32-bit
        if [[ "$cpu_arch" == "armv6l" || "$cpu_arch" == "armv7l" ]]; then
            if ! grep -q vfp /proc/cpuinfo; then
                echo "Error: ARM 32-bit CPU detected without VFP support. This system does not meet the minimum requirements."
                exit 1
            fi
        fi
    fi
    
    # Check if the architecture meets the requirements
    case "$cpu_arch" in
        x86_64|amd64)
            echo "CPU architecture: x86_64 (64-bit)"
            ;;
        i686|i386)
            echo "CPU architecture: x86_32 (32-bit) with SSE2 support"
            ;;
        armv6l|armv7l)
            echo "CPU architecture: ARM 32-bit (v6l/v7l) with VFP support"
            ;;
        aarch64|arm64)
            echo "CPU architecture: ARM 64-bit"
            ;;
        *)
            echo "Error: Unsupported CPU architecture: $cpu_arch. This system does not meet the minimum requirements."
            exit 1
            ;;
    esac
}

#-------------------------------------------------------
# Function to uninstall Zmanda Pro
#-------------------------------------------------------
function uninstall_zmanda_pro() {
    echo "Uninstalling Zmanda Pro..."
    # Disconnect the current instance of Zmanda Pro
    if [ -f "/opt/ZmandaPro/backup-tool" ]; then
        /opt/ZmandaPro/backup-tool login disconnect
    else
        echo "Zmanda Pro backup tool not found. Skipping disconnect."
    fi
    # Wait for the ZmandaPro Backup processes to terminate
    echo "Waiting for ZmandaPro processes to terminate"
    max_attempts=3
    attempt=1
    while pgrep -f '/opt/ZmandaPro' > /dev/null && [ $attempt -le $max_attempts ]; do
        ((attempt++))
        sleep 1
    done

    # Get the process IDs of ZmandaPro Backup processes
    echo "Checking for existing ZmandaPro processes"
    zp_pids=$(pgrep -f '/opt/ZmandaPro')

    # Print the process IDs for troubleshooting
    echo "Existing ZmandaPro process IDs: $zp_pids"

    # Send the SIGTERM signal to each process
    echo "Sending SIGTERM signal to ZmandaPro processes"
    for pid in $zp_pids; do
        echo "Killing process ID: $pid"
        if ! kill -15 "$pid" 2>/dev/null; then
            echo "Could not kill process ID: $pid"
        fi
    done

    # Remove Zmanda Pro directory
    echo "Removing Zmanda Pro directory"
    rm -rf /opt/ZmandaPro
    return 0
}

#-------------------------------------------------------
# Function to run Zmanda_Pro installer with '--lobby' option
#-------------------------------------------------------
function run_zmanda_pro_installer() {
    echo "Running Zmanda_Pro installer with '--lobby' option"
    output=$(./Zmanda_Pro.run --lobby 2>&1)
    exit_code=$?
    echo "$output"
    if echo "$output" | grep -q "ERROR_BAD_STATE"; then
        echo "ERROR_BAD_STATE detected. Forcing reinstallation."
        uninstall_zmanda_pro
        output=$(./Zmanda_Pro.run --lobby 2>&1)
        exit_code=$?
        echo "$output"
    fi
    return $exit_code
}

#-------------------------------------------------------
# Function to check if installation was successful
#-------------------------------------------------------
function check_installation() {
    if [ -d "/opt/ZmandaPro" ] && [ -f "/opt/ZmandaPro/backup-daemon-start-background.sh" ]; then
        echo "Installation appears to be successful."
        return 0
    else
        echo "Installation seems to have failed. ZmandaPro directory or startup script not found."
        return 1
    fi
}

# Attempt to run Zmanda_Pro installer
max_installer_attempts=3
installer_attempt=1

while [[ "$#" -gt 0 ]]; do
    case $1 in
        --uninstall)
            if check_installation; then
                if uninstall_zmanda_pro; then
                    echo "Zmanda Pro has been uninstalled successfully" >&1
                else
                    echo "Failed to uninstall Zmanda Pro" >&2
                    exit 1
                fi
            else
                echo "No installation of Zmanda Pro found" >&1
            fi
            exit 0
            ;;
        --certs)
            if [[ $CA_CERT_CONTENT == "@@ZP_CA_CERT@@" ]]; then
                echo "CA Certificate content is not set. Please set the CA Certificate content in the Zmanda Pro Linux Client Install Script." >&2
                exit 1
            fi

            if install_ca_certificate; then
                echo "Zmanda Pro Certificate installed successfully" >&1
            else
                echo "Failed to install Zmanda Pro Certificate" >&2
                exit 1
            fi
            exit 0
            ;;
        *)
            echo "Unknown parameter: $1" >&2
            exit 1
            ;;
    esac
    shift
done

#-------------------------------------------------------
# Function to start Zmanda Pro services
#-------------------------------------------------------
function start_zmanda_pro() {
    echo "Starting Zmanda Pro services..."
    # Change to a known directory before running the script
    cd /tmp || return 1
    /opt/ZmandaPro/backup-daemon-start-background.sh
    local exit_code=$?
    if [ $exit_code -eq 0 ]; then
        echo "Zmanda Pro services started successfully."
    else
        echo "Failed to start Zmanda Pro services. Exit code: $exit_code"
    fi
    return $exit_code
}

#-------------------------------------------------------
# Function to install Zmanda Pro
#-------------------------------------------------------
function install_zmanda_pro() {
    check_cpu_requirements

    distrocheck

    install_prerequisites

    # Print information for troubleshooting
    echo "Temporary folder created: $temporary_folder"
    echo "Changing directory to: $temporary_folder"

    # Change directory to the temporary folder
    cd "$temporary_folder" || exit

    # Download the Zmanda_Pro file with custom User-Agent header
    echo "Downloading Zmanda_Pro from: $DOWNLOAD_URL"
    
    ## Set AUTOMATED_INSTALL environment variable to true when running from an automation like 
    ## Ansible or MDM so that the download progress does not get logged in the output.
    
    # Check if script is running in an interactive terminal
    wget_options="--header=\"User-Agent: zmandapro-installer\" \"$DOWNLOAD_URL\" -O Zmanda_Pro.run"
    if [ "$AUTOMATED_INSTALL" = "true" ]; then
            # Running in automated mode, suppress output
            wget_options+=" -q > /dev/null 2>&1"
    else
            # Running in terminal, show progress
            wget_options+=" --show-progress"
    fi

    if eval wget $wget_options; then
        echo "Download completed successfully."
    else
        echo "Failed to download Zmanda_Pro.run" >&2
        exit 1
    fi

    # Make the downloaded file executable
    echo "Making Zmanda_Pro.run executable"
    chmod +x Zmanda_Pro.run

    uninstall_zmanda_pro

    while [ $installer_attempt -le $max_installer_attempts ]; do
        echo "Attempt $installer_attempt to run Zmanda_Pro installer..."
        run_zmanda_pro_installer
        installer_exit_code=$?
        
        if [ $installer_exit_code -eq 0 ]; then
            echo "Zmanda_Pro installer completed on attempt $installer_attempt."
            if check_installation; then
                echo "Installation verified successfully."
                break
            else
                echo "Installation verification failed."
            fi
        else
            echo "Zmanda_Pro installer failed with exit code $installer_exit_code on attempt $installer_attempt."
        fi
        
        if [ $installer_attempt -eq $max_installer_attempts ]; then
            echo "Failed to run Zmanda_Pro installer after $max_installer_attempts attempts."
            exit 1
        else
            echo "Retrying Zmanda_Pro installer in 30 seconds..."
            sleep 30
        fi
        ((installer_attempt++))
    done

    # Remove the temporary folder and its contents
    echo "Removing temporary folder and its contents: $temporary_folder"
    rm -rf "$temporary_folder"

    # Attempt to start Zmanda Pro services
    max_attempts=3
    attempt=1

    while [ $attempt -le $max_attempts ]; do
        echo "Attempt $attempt to start Zmanda Pro services..."
        start_zmanda_pro
        if [ $? -eq 0 ]; then
            echo "Zmanda Pro services started successfully on attempt $attempt."
            break
        else
            if [ $attempt -eq $max_attempts ]; then
                echo "Failed to start Zmanda Pro services after $max_attempts attempts."
            else
                echo "Retrying in 30 seconds..."
                sleep 30
            fi
        fi
        ((attempt++))
    done

    # Restart Zmanda Pro Services at Boot using cron script code
    CRON_ENTRY="@reboot cd /tmp && HOME=/root/ /opt/ZmandaPro/backup-daemon-start-background.sh &"

    # Remove existing cron entries for this job
    crontab -l -u root | grep -v "$CRON_ENTRY" | crontab -u root -

    # Add the new cron entry to root's crontab
    (crontab -l -u root; echo "$CRON_ENTRY") | crontab -u root -

    echo "Script execution completed successfully"
}

if [[ $CA_CERT_CONTENT == "@@ZP_CA_CERT@@" ]]; then
    echo "CA Certificate content is not set. Skipping certificate installation." >&2
else    
    install_ca_certificate
fi

install_zmanda_pro

macOS

When using the script with ZPAT ansible scripts, leave variables as-is.

If not using ZPAT, follow these steps:

  1. Replace @@ZP_SERVER_FQDN@@ in the DOWNLOAD_URL variable at the top of the file with your FQDN.

  2. Replace @@ZP_CA_CERT@@ in the CA_CERT_CONTENT variable at the top of the file with your cert content.

  3. Run the script with administrator privileges. The device will appear in the Zmanda Pro console in an Unregistered state. You can use ZPAT to automatically create a unique user and register the device, or register the device to an existing user manually.

#!/bin/bash

# Zmanda Pro tenant URL
zmanda_tenant_url="https://@@ZP_SERVER_FQDN@@"

CA_CERT_CONTENT="@@ZP_CA_CERT@@"

# Define the download URLs based on the architecture
download_url_x86_64="$zmanda_tenant_url/dl/8"
download_url_arm64="$zmanda_tenant_url/dl/20"

# Define the temporary folder
temporary_folder="$(mktemp -d)"

# Print information for troubleshooting
echo "Temporary folder created: $temporary_folder"
echo "Changing directory to: $temporary_folder"

# Change directory to the temporary folder
cd "$temporary_folder" || exit

# Get the current architecture
current_arch=$(uname -m)

# Download the Zmanda_Pro file with custom User-Agent header
if [ "$current_arch" == "arm64" ]; then
    # Apple Silicon
    download_url="$download_url_arm64"
else
    # x86_64
    download_url="$download_url_x86_64"
fi

echo "Downloading Zmanda_Pro from: $download_url"
curl -A "zmandapro-installer" -L "$download_url" -o Zmanda_Pro.pkg

# Detect the installation path based on the architecture
if [ "$current_arch" == "arm64" ]; then
    # Apple Silicon
    installation_path="/Applications/Zmanda Pro.app"
else
    # x86_64
    installation_path="/Applications/Zmanda Pro.app"
fi

# Check if Zmanda Pro is installed
if [ -d "$installation_path" ]; then
    echo "Zmanda Pro is already installed at $installation_path"

    # Disconnect the current instance of Zmanda Pro
    "$installation_path/Contents/MacOS/backup-tool" login disconnect || echo "Failed to disconnect Zmanda Pro instance"

    # Get the process IDs of ZmandaPro Backup processes
    echo "Checking for existing ZmandaPro processes"
    zp_pids=$(ps aux | grep "$installation_path" | awk '{print $2}')

    # Print the process IDs for troubleshooting
    echo "Existing ZmandaPro process IDs: $zp_pids"

    # Send the SIGTERM signal to each process
    echo "Sending SIGTERM signal to ZmandaPro processes"
    for pid in $zp_pids; do
        echo "Killing process ID: $pid"
        kill -15 "$pid" 2>/dev/null || echo "Failed to kill process $pid"
    done

    # Uninstall existing Zmanda Pro
    echo "Uninstalling existing Zmanda Pro"
    rm -rf "$installation_path"
fi

# Install the new Zmanda Pro package
echo "Installing new Zmanda Pro package"
sudo installer -allowUntrusted -pkg Zmanda_Pro.pkg -target /

# Remove the temporary folder and its contents
echo "Removing temporary folder and its contents: $temporary_folder"
rm -rf "$temporary_folder"

# Join the remote registration lobby -
# This is not a persistent connection and will NOT auto reconnect after a client restart
"$installation_path/Contents/MacOS/backup-tool" login join-lobby "$zmanda_tenant_url"

# Restart Zmanda Pro Services at Boot using launchd
PLIST_FILE="/Library/LaunchDaemons/com.zmanda.backup-daemon.plist"

# Create the plist file
cat << EOF | sudo tee "$PLIST_FILE" > /dev/null
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.zmanda.backup-daemon</string>
    <key>ProgramArguments</key>
    <array>
        <string>"$installation_path/Contents/MacOS/backup-daemon-start-background.sh"</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>
EOF

# Unload the launchd plist if it's already loaded
sudo launchctl unload "$PLIST_FILE" 2>/dev/null

# Load the launchd plist
sudo launchctl load "$PLIST_FILE"

echo "Script execution completed successfully"

Last updated

Was this helpful?