JDunphy-install.sh-guide

Revision as of 14:29, 8 April 2025 by JDunphy (talk | contribs) (→‎Tools)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
   KB 24654        Last updated on 2025-04-8  




1.00
(one vote)

Zimbra install.sh Installation Script – Technical Overview

Overview:
The Zimbra install.sh script is a Bash deployment script used for both fresh installations and in-place upgrades of the Zimbra Collaboration Suite. It orchestrates the installation process (package deployment, config preservation) and then hands off to a Perl setup script (zmsetup.pl) for final system configuration. This document provides an in-depth breakdown of the script’s logic and structure, targeting experienced Perl/shell developers and system administrators who may need to understand or modify the installer’s behavior.

Script Structure and Flow Summary

The install.sh script executes in distinct stages, each handling specific tasks and decision points. At a high level, the flow is:

  • Pre-Installation Checks: Verify the script is run as root and that required system components (like Perl) are available. Load necessary shell utility modules.
  • Argument Parsing: Process command-line options to set installation modes (standard install vs. upgrade vs. uninstall, etc.) and flags (e.g. license key, config restore directory, skipping checks).
  • Environment Initialization: Set up global variables, environment settings, and log files. Perform platform detection and prepare for installation (including cleaning up any previous installer state like leftover license files).
  • Existing Installation Detection: Determine if Zimbra is already installed. This influences whether the script proceeds with an upgrade or a new installation, or triggers an uninstall routine if requested.
  • Interactive vs. Automated Mode: If a defaults configuration file is provided, the script runs in auto-install (silent) mode; otherwise, it operates in interactive mode, prompting the admin for input (such as package selection and confirmations).
  • Prerequisite Validation: Ensure required system conditions (disk space, OS compatibility, etc.) are met. The script may halt with errors or warnings if conditions are not satisfied (unless overridden by flags).
  • Package Installation Phase: Install or upgrade the Zimbra software packages. This includes logging the installation start/completion and handling any platform-specific package repository setup.
  • Post-Install Restoration (Upgrade path): If upgrading, restore the previously saved configuration and SSL certificates so the new version retains the old settings. If a config backup was provided via --restore, merge those defaults for use in configuration.
  • Final Configuration (zmsetup.pl): Unless running in software-only mode, call the zmsetup.pl Perl script to perform post-install configuration (such as service setup, data import, applying license, etc.). The script passes along any provided config file for automated setup or enters an interactive configuration if not.
  • Error Handling & Exit: At each major step, the script checks for errors or user aborts (e.g. unsupported OS, version mismatches, user cancellations) and exits with informative messages. Upon finishing, it exits with a success or propagates any setup error codes.

The following sections describe these stages in detail, with key logic and branching explained.

Argument Parsing and Modes

The script begins by parsing command-line arguments in a loop, using a case statement to handle each supported option. This setup influences whether the script runs a fresh install, an upgrade, or an uninstall, and toggles various safety checks. The usage() function defines the available flags and is invoked for -h (help) or on invalid input. Key options include:

  • -h / --help: Display usage help and exit immediately (no installation occurs).
  • -u / --uninstall: Triggers uninstall mode – the script will remove an existing Zimbra installation instead of installing/upgrading.
  • -s / --softwareonly: Software-only install. Only packages are installed; the script will not run the final configuration (zmsetup.pl). This allows installing the software without immediate configuration (useful for staging or custom setups).
  • -r <dir> / --restore <dir>: Provide a directory containing a saved Zimbra config (from a previous install or backup). The installer will restore settings from this directory (by later seeding defaults from it) before configuration.
  • -l <key> / --licensekey <key>: Provide a ZCS license key (for Network Edition). The script validates the format of the key and, if valid, will install this license into the Zimbra config directory.
  • -x / --skipspacecheck: Skip the disk space check. By default, the installer checks for adequate filesystem capacity; this flag bypasses that safety check.
  • --platform-override: Bypass platform verification. Use this if installing on an OS that is not officially recognized by the package (the script would normally refuse if the OS differs from the build target). Warning: Using this sets an internal override flag and allows continuing on an unsupported platform, which might result in an unusable install if incompatible.
  • --skip-activation-check: In an upgrade scenario (Network Edition), skip the license activation validation. The script will not halt if the license activation would normally be required or checked.
  • --skip-upgrade-check: Skip certain upgrade validation checks. For instance, the script normally validates that the existing installation can be upgraded to this version (correct edition, no incompatible versions); this flag forces the script to bypass those checks.
  • --skip-ng-check: Skip “NG modules” check. If the installer detects add-on Network modules (NG modules) that might block an upgrade, this flag allows the upgrade by planning to remove or ignore those modules and related data.
  • --beta-support: Allow upgrade of a beta release (used to permit upgrading from a Network Edition beta version which is normally blocked).
  • --force-upgrade: Force the upgrade flag to “yes.” This is used in edge cases where an upgrade should proceed even if some package installation steps failed or in scenarios with remote package installation issues. It essentially tells the script to treat the operation as an upgrade no matter what, attempting to proceed with configuration.
  • [defaultsfile] (positional argument): If a filename is provided without a flag, the script treats it as a defaults configuration file. This puts the installer into automated mode (non-interactive). The file should contain predefined installation answers (default values for config prompts). When this is used, AUTOINSTALL is set to “yes” internally, and the script will later auto-load this file to avoid interactive prompts.

During parsing, the script sets internal variables for each flag (e.g. UNINSTALL="yes", SOFTWAREONLY="yes", ALLOW_PLATFORM_OVERRIDE="yes", etc.). It also calls helper functions for certain options: for example, on --licensekey it invokes validateLicensekey() to ensure the provided key string is a non-blank alphanumeric string of the expected length, otherwise it prints an error and calls usage() to exit. Unknown options also trigger usage() and termination.

Result of Parsing: By the end of this stage, the script knows what mode to operate in (upgrade vs. new install vs. uninstall), whether it should run interactively or not, and which safety checks to enforce or skip. If a defaults file was given, AUTOINSTALL is set to “yes”; otherwise “no” for interactive mode. If -u was provided, UNINSTALL="yes". Additionally, if --force-upgrade was used, it explicitly sets UPGRADE="yes" (ensuring the script treats the process as an upgrade). All other flags similarly influence internal state for later logic.

Environment Validation and Setup

After parsing arguments, install.sh performs critical environment checks and initializes the installation context:

  • Root User Check: Immediately at start, the script checks if it’s running as the root user (id -u must equal 0). If not, it prints “Run as root!” and exits. This prevents non-root users from running the installer (since installation requires root privileges).
  • System Perl Check: It verifies that /usr/bin/perl exists and is executable. If the system’s Perl interpreter is missing, the script aborts with an error: “ERROR: System perl at /usr/bin/perl must be present before installation.” This is because parts of Zimbra (like zmsetup.pl) rely on Perl.

Assuming those checks pass, the script proceeds to load required shell libraries and set up global variables:

  • Loading Utility Functions: The script sources util/utilfunc.sh and all ./util/modules/*.sh scripts. These included files contain reusable functions and definitions used throughout the installer (for example, functions to check prerequisites, manage packages, prompt the user, etc.). By splitting logic into these modules, the main script remains organized. Key functions later used (like checkExistingInstall, setRemove, installPackages, verifyExecute, etc.) are defined in these sourced files.
  • Global Variables: Next, it sources util/globals.sh which sets up global variables (such as LOGFILE for logging, SAVEDIR for saving configs, the current PLATFORM identifier, etc.). A function getPlatformVars is invoked to detect the operating system/platform details and Zimbra version info. This populates variables like the OS name or package type, and will help determine if the current platform matches the package’s intended platform.
  • Log and Temp Directory Prep: The script ensures the directory for saving configuration ($SAVEDIR) exists (creating it if necessary) and sets appropriate permissions (likely /tmp/zmsetup or similar by default, or a path under /opt/zimbra for upgrades). It then prints a message to the console indicating that operations will be logged to $LOGFILE (the installer log path, e.g. /tmp/install.log or similar defined in globals). It also preemptively deletes any old license-related files that might interfere with the new installation. Specifically, it removes files like ZCSLicense-activated.xml, ZCSLicensekey, and skip_activation_check from any previous install attempt in /opt/zimbra/conf to start with a clean slate.
  • License Key Initialization: If a license key was provided via -l, at this point the script creates /opt/zimbra/conf (if not already present) and writes the license key into a file ZCSLicensekey within that directory. Ownership is set to the Zimbra user and permissions to 644. (Notably, the script does this both now and again after package installation to ensure the license key is preserved through the install. Writing it now ensures the key is on disk for any steps during installation that might require it.)
  • Activation Check Flag: If --skip-activation-check was specified, the script creates a marker file /opt/zimbra/conf/skip_activation_check with appropriate permissions. This flag file will later inform the system (particularly zmsetup.pl) to skip any license activation enforcement.

At this stage, the installer prints the Zimbra End-User License Agreement (EULA) or license terms via displayLicense (especially for Network Edition, it typically prompts the user to accept the EULA). In automated mode, this might be skipped or auto-accepted by virtue of using a defaults file, but in interactive mode the admin may need to scroll through or acknowledge it.

Finally, the script calls checkUser root – an extra validation to ensure the script is indeed running as root. Since the script already exited if not root at the very start, checkUser here is mostly a safeguard (possibly defined in utilfunc.sh to double-check effective user or to prevent running as the Zimbra user). It’s a minimal sanity check before proceeding to the main installation logic.

New Install vs. Upgrade Logic

One of the script’s key decisions is identifying if the current run is a new installation or an upgrade of an existing Zimbra instance. This context is determined by scanning the system for an existing installation and by user-provided flags:

  • Existing Installation Detection: The function checkExistingInstall is called to detect if Zimbra is already installed on the server. This likely checks for the existence of Zimbra directories (like /opt/zimbra) or Zimbra services/users. If an existing installation is found, the script will prepare to perform an upgrade rather than a fresh install. Internally, it may set a flag (e.g. an installedVersion variable or directly UPGRADE="yes") indicating an upgrade scenario. If no existing Zimbra is found, it’s treated as a new install.

  • Uninstall Mode: If the -u/--uninstall flag was set, the script enters uninstall routine instead of installing anything. In this mode, after detecting any existing installation, it will prompt: “Completely remove existing installation? [Y/N]”. This confirmation (handled by an askYN function) ensures the admin really intends to wipe Zimbra.

    • If the response is “yes,” the script sets REMOVE="yes" and proceeds to systematically remove Zimbra: it first calls findUbuntuExternalPackageDependencies (specific to Ubuntu/Debian, perhaps to list or remove any Zimbra-related system packages installed via APT), then saveExistingConfig (to backup configuration, if needed, before removal), and then removeExistingInstall which stops services and removes all Zimbra packages and data from the system. After completing uninstall, the script exits.
    • If the confirmation is “no” (or if no existing install was found to remove), the script will also exit without proceeding to any installation. (In other words, when -u is used, the script does not fall back to installation – it either uninstalls and quits or just quits if nothing to do. The admin must re-run without -u to install fresh.)
    • Important: The uninstall path is a one-way branch that ends execution (marked by an exit after the removal steps). It will not continue on to package installation or configuration.
  • Upgrade vs Fresh Install Path: If not in uninstall mode, the installer decides whether it’s performing an upgrade or a new install:

    • For an upgrade (existing install detected), the script will preserve settings and data. It does not explicitly ask the user “Upgrade or new?” – it assumes if Zimbra is already present and the user didn’t choose uninstall, an in-place upgrade is intended. In interactive mode, the presence of an existing installation will influence default choices (for example, the set of packages to install may default to those already installed, and configuration steps will pick up existing defaults). Internally, UPGRADE="yes" is set either by checkExistingInstall or later when restoring config.
    • For a new installation, the script proceeds with fresh defaults. It will prompt for necessary configuration details later (via zmsetup.pl) since no existing config is available.
  • Auto-Install Config Load: If AUTOINSTALL is “yes” (meaning a defaults file was provided), this is typically used for unattended upgrades or installs. The script at this point calls loadConfig <defaultsfile>, which reads the provided config file and pre-loads all installation variables (like hostnames, passwords, package selections, etc.) into memory. This bypasses interactive prompts later on. In an upgrade scenario, the defaults file might be one previously generated by zmsetup.pl from an earlier install (or crafted by an admin) so that the upgrade can apply the same settings. After loading the config, the script will not prompt the user for any choices about which packages to install or other preferences – it will use the loaded values.

  • Interactive Package Selection: If not in auto mode, the script enters an interactive phase for a new install or upgrade:

    • It calls setRemove and getInstallPackages. These functions likely present a menu of Zimbra components (LDAP, MTA, Store, etc.) and allow the admin to select which packages to install. In an upgrade, the menu would show currently installed components and typically mark them for upgrade. If the admin chooses to exclude a component that is currently installed, the installer would interpret that as a removal of that component (this is where setRemove might mark certain packages for removal if they are de-selected). By the end of getInstallPackages, the script has a list of packages to install/upgrade and possibly flags for any components to remove.
    • After package selection, the script reads the build’s supported platform from an internal file ( .BUILD_PLATFORM in the installer directory, which contains the OS identifier the packages were built for) and compares it to the current system’s platform ($PLATFORM determined earlier).
      • If the current OS does not match the build’s target and the user did not set --platform-override, the script treats this as a potential error. In interactive mode, it prints a warning: “You appear to be installing packages on a platform different than the platform for which they were built… This may or may not work.” It then requires confirmation to continue. If the admin does not confirm (answers “No” to “Install anyway?”), the script will print “Exiting…” and terminate. Without the override, the script will not attempt to install on an unknown platform.
      • If --platform-override was used (ALLOW_PLATFORM_OVERRIDE=“yes”), the script will allow proceeding despite the mismatch. In interactive mode it still issues a caution message about the risks of using packages on an unsupported OS. If the user agrees to continue, it moves forward; if they decline, it exits. In automated mode, using --platform-override simply bypasses the OS check (there is no prompt). Note: If the platform does match, or once an override is accepted, the script sets ALLOW_PLATFORM_OVERRIDE="no" to disable any special handling and continues normally. If no override was given on an unsupported platform, the installer will abort at this point with an error, preventing installation.
    • Skipping Platform Repository Setup: If the platform is officially supported (or the override flag was turned off after confirming), the script calls configurePackageServer. This likely configures the package repository for Zimbra’s third-party or OS-specific packages if needed (for example, enabling Zimbra’s package repo or syncing package lists). If the override flag remained “yes” (meaning the OS was different but user insisted), it might skip automatic repository configuration, since in that case the admin is expected to handle any missing dependencies manually.
    • The script then calls checkPackages, which verifies that all required package files are available for installation. In a bundled installer, this ensures the .deb/.rpm files for the selected components are present. If any are missing or if there are dependency issues, it can flag an error here (the script may prompt or exit if something critical is missing).
    • Finally, verifyExecute is invoked just before actual installation. This function likely performs last-minute validations (ensuring no other installs are running, that all selections are valid, and maybe re-checking disk space or other prerequisites if not skipped). It is essentially a gatekeeper that must succeed for the installation to proceed. If verifyExecute encounters a problem, it will report it and exit the script to prevent a faulty installation.
  • Upgrade Version Compatibility Check: In automated mode, there is an additional safety step: the script runs checkVersionMatches if an upgrade is being performed. This function checks for any version/schema incompatibility between the existing installation and the new packages. For example, it might compare the currently installed Zimbra LDAP/SQL schema versions or index versions with those expected by the new version. If it finds a mismatch and UPGRADE="yes", it will output an error:

    “###ERROR###
    There is a mismatch in the versions of the installed schema or index and the version included in this package
    Automatic upgrade cancelled”

    and then immediately exit. This prevents continuing with an upgrade that could corrupt data due to version inconsistencies (perhaps if someone attempted to skip too many versions or mix editions without proper path). If checkVersionMatches passes (or if it’s a new install where VERSIONMATCH is not applicable), the script proceeds. (In interactive mode, such a check might also occur, but the code specifically performs it in the non-interactive branch to avoid silently upgrading in dangerous cases.)

At this point, whether new install or upgrade, the script has made all decisions regarding what to install and has confirmed the environment is acceptable. The next phase is performing the actual software installation.

Package Installation Phase

After passing all checks, install.sh moves on to install the Zimbra software packages:

  • Logging Installation Start: The script records a timestamped “INSTALL SESSION START” in the Zimbra installation history log (/opt/zimbra/.install_history). This is an audit trail file tracking installation sessions.
  • Executing Package Installation: The function installPackages is called. This is a critical function (defined in the utility modules) that installs all selected Zimbra packages onto the system. Under the hood, it may use the system package manager (rpm/dpkg or apt/yum) to install each component (LDAP server, mailbox, MTA, etc.), or if running from a tarball, it might directly invoke package installation commands. It streams output to the console and to the log file. If any package fails to install, this function should detect it and possibly exit with an error (unless --force-upgrade was used, which would force continuation).
  • Logging Installation Completion: After installPackages returns, the script logs an “INSTALL SESSION COMPLETE” with a timestamp to /opt/zimbra/.install_history. This indicates that the package deployment phase finished (successfully, in terms of running to completion). At this stage, all Zimbra binaries and files are in place on the system.

The script now performs post-install tasks, especially important for upgrades:

  • Restoring Configuration Defaults: If the admin provided a restore directory via -r/--restore, the script assigns that path to SAVEDIR. Also, even in upgrades without an explicit -r, the script might have internally set SAVEDIR to a temporary directory where it saved the existing config (via saveExistingConfig earlier). If SAVEDIR is non-empty and the installation was not a removal (REMOVE="no"), the script calls setDefaultsFromExistingConfig. This function takes the saved configuration data (from the previous install) and pre-populates the new installation’s default configuration with those values. In essence, it carries over settings like admin passwords, domain names, LDAP configs, etc., so that the upcoming configuration step will use these as defaults. This is crucial for making an upgrade seamless – the administrator won’t have to re-enter all settings.
  • Upgrade Data Restoration: If this run is an upgrade (UPGRADE="yes"), additional restoration steps take place:
    • restoreExistingConfig is invoked to apply the saved config data into the new system. This likely updates Zimbra’s local configuration store (localconfig or LDAP entries) with values from the old installation (for example, re-injecting stored settings such as installed services, previous tuning parameters, etc.).
    • restoreCerts is called to restore the SSL/TLS certificates from the old installation into the new one. Zimbra’s certificates (for mail server, etc.) are preserved so that after upgrade, the server can continue using the same certs without requiring re-generation or reinstallation by the admin. This function copies the backed-up keystores or certificate files into the new /opt/zimbra directories and ensures proper permissions.
    • (In older versions, there was a restoreZimlets step to re-deploy any custom Zimlets from the old system. In this script, that call is present but commented out, indicating it’s deprecated – likely because modern Zimlets are stored in a location that isn’t removed during upgrade, so they persist without special handling.)
  • Applying License Key: After installation, the script once again handles the license key (Network Edition scenarios). If a license key was provided ($LICENSEKEY is set), it ensures that the license key file exists in the new installation’s config directory. It creates /opt/zimbra/conf if needed (should already exist by now) and writes the license key string to ZCSLicensekey, with correct ownership and permissions. This second write is possibly to guarantee the license is in place after any config restores (which might overwrite or remove that file). By doing it at this stage, the subsequent configuration step (zmsetup) can detect and install the license properly.
  • Marking Activation Skip: The checkSkipActivation function is called again post-install. If the SKIP_ACTIVATION_CHECK flag was “yes”, this double-checks that the skip_activation_check file exists in the config (creating it if for some reason it’s missing) with the right owner/perms. This ensures that if zmsetup.pl tries to verify license activation (for Network Edition upgrades), it will find the flag and bypass any enforcement, as the user requested.

At this point, all software is installed and initial data restoration is done. The script now decides whether to finalize the setup or exit:

  • Software-only Mode Exit: If the script was run in software-only mode (SOFTWAREONLY="yes"), it will not proceed to run zmsetup.pl. Instead, it prints a message such as: “Software Installation complete! Operations logged to [logfile]” and exits with code 0. This allows the admin to perform custom configuration later or on a separate system. In this mode, Zimbra services are installed but not configured/enabled. The script stops here intentionally when -s is used.

For all other cases (normal install/upgrade where configuration should continue), the script proceeds to the final configuration stage.

Integration with zmsetup.pl (Post-Installation Configuration)

After successfully installing the packages, install.sh hands off the remaining setup to the Zimbra configuration script, zmsetup.pl:

  • Log File Handling: Before calling zmsetup.pl, the script ensures the installation log is stored in a proper location. It checks if the $LOGFILE (installer log, e.g., /tmp/install.log) exists. If so, it copies this log into Zimbra’s log directory (typically /opt/zimbra/log/) for permanent keeping, and sets ownership to the Zimbra user. This way, the full record of installation actions is saved with the Zimbra installation (helpful for support or troubleshooting). The console output already went there, but this copies the transient log file to the well-known log directory.
  • Running Zimbra Setup: The script then invokes the Perl configuration script:
    • If a defaults file was used ($DEFAULTFILE is set, i.e., auto-install mode), it calls:

/opt/zimbra/libexec/zmsetup.pl -c $DEFAULTFILE
This passes the configuration file to zmsetup.pl so that it runs in non-interactive mode, reading all required answers from that file. This is typical for automated installs/upgrades.

    • If no defaults file was provided (interactive mode), it calls zmsetup.pl without arguments:

/opt/zimbra/libexec/zmsetup.pl
In this case, zmsetup.pl will run interactively. It detects the newly installed packages and, for a fresh install, will prompt the administrator for configuration details (such as setting the domain name, admin user password, enabling or disabling certain services, time zone, etc.). For an upgrade, zmsetup.pl will usually detect the existing configuration (from the restored defaults) and either silently upgrade the necessary components or prompt for any new information needed for the new version. It also might handle tasks like upgrading the database schema, reindexing if required, and starting the services.

  • Function of zmsetup.pl: It’s important to note that zmsetup.pl is where most post-installation customization happens. This Perl script configures the Zimbra server components using the installed packages. It applies the config values (from the defaults file or interactive input), performs system checks (DNS, hostname resolution), sets up LDAP data, initializes databases, and starts Zimbra services. It also handles license activation for Network Edition (unless skipped) and finalizes the installation (writing a configuration complete marker). Essentially, install.sh prepares the ground (installing files and prepping config), and zmsetup.pl does the heavy lifting of configuring those files into a working server.
  • Handling zmsetup.pl Outcome: The installer script captures the exit code ($RC) from the zmsetup.pl invocation. If zmsetup.pl returns a non-zero exit status (indicating an error during configuration), install.sh will exit with that same code (exit $RC). This means that if the setup failed (for example, due to a configuration error, unsatisfied prerequisite discovered late, or admin abort during configuration), the overall script will signal failure. All changes up to that point remain (packages installed, etc.), but the installation isn’t fully configured. The administrator can troubleshoot (using logs) and re-run configuration if needed. If zmsetup.pl succeeds (exit code 0), the script simply ends with a 0 status, indicating a successful installation and configuration.

At this stage, if all went well, Zimbra is installed and configured on the system. The services should be up and running (mailbox, MTA, etc.), and the server is ready for use. The install.sh script’s role is complete.

Error Handling and Exit Conditions

The install.sh script contains numerous checks and will abort safely if certain conditions are not met, to avoid corrupting the system or leaving a partially configured installation. Below are key error-handling behaviors:

  • Invalid Execution Environment: As noted, not running as root or missing system Perl causes an immediate exit (with an error message). These are non-negotiable requirements.
  • Unsupported OS Platform: If the installer detects that the operating system is not the expected platform for the Zimbra package, it will refuse to continue unless the --platform-override is used. In interactive mode, even with override, it requires a manual confirmation (and aborts if the user declines). Without override, the script prints a warning and exits to prevent an unsupported install. This protects users from accidentally installing on an OS that hasn’t been tested, which could fail unpredictably.
  • Unknown Options / Help: If an unrecognized argument is passed or --help is invoked, the script prints the usage and exits. This is a graceful exit providing guidance. Similarly, if the license key validation fails (malformed key), it calls usage() which terminates execution after showing the error.
  • Prerequisite Failures: During checkRequired or verifyExecute, if any mandatory prerequisite is missing (for example, insufficient disk space, missing dependencies, inadequate memory, etc.), the script will typically alert the user and exit. For instance, without -x, if disk space is low on the target volumes, the script would catch that here and stop rather than attempting an install that could run out of space. These checks are meant to ensure a stable installation environment.
  • User Abort Actions: There are points where the script asks for user input to continue:
    • The license/EULA display might prompt for acceptance (in some versions, user must press “Y” to agree; if they decline, the install would abort).
    • Uninstall confirmation: saying “No” to removal causes the script to exit (without changing anything).
    • Platform override confirmation: saying “No” to proceeding on an unsupported platform triggers an exit. In all these cases, the script exits cleanly with a message (and often a specific exit code) when the user chooses not to continue.
  • Version Mismatch on Upgrade: The checkVersionMatches guard prevents proceeding with an upgrade if it detects version incompatibilities (for example, if the existing installation’s database schema is newer than expected, or other mismatch). In that scenario, it logs an error message (“Automatic upgrade cancelled”) and exits. This leaves the existing installation untouched so the admin can resolve the version issue (perhaps by upgrading to an intermediate version first or consulting Zimbra support) rather than attempt a possibly destructive upgrade.
  • Package Installation Errors: If any package fails to install properly, installPackages is expected to handle or propagate that error. Without special flags, a critical failure (like a corrupted package or missing dependency) would likely cause the script to exit with an error at that point. The --force-upgrade can override some of these failures, but using it implies the admin will handle any fallout manually. Error messaging during package install is logged to the console and log file for troubleshooting.
  • zmsetup.pl Failures: As mentioned, if zmsetup.pl returns a failure code, install.sh will exit with that code. zmsetup.pl itself provides detailed output and logs (in /opt/zimbra/log/zmsetup.log) which the admin can review. By propagating the error code, install.sh ensures that any automation or parent process is aware the installation did not fully succeed. For example, a configuration failure might yield a non-zero exit which a deployment script can catch to trigger rollback or alert the admin.
  • Logging and History: Throughout the process, the script appends events to the install history and uses the log file. Even if an error occurs and the script exits, the actions up to that point are recorded. This is helpful for error handling after the fact, as one can inspect /opt/zimbra/.install_history to see if an upgrade started and at what point it ended, or check the installer log for error details.

In summary, the script is designed to fail fast and safely if conditions aren’t right, rather than risk a broken installation. Each conditional branch for errors provides a message to inform the administrator of the issue. By the time install.sh exits (successfully or not), the system is either left unchanged (on failure) or fully configured (on success), with no ambiguous half-installed state.

Execution Flowchart

Below is a flowchart that illustrates the execution flow of install.sh, highlighting key decision points and stages such as environment checks, branching between install/upgrade/uninstall, package installation, and configuration:

flowchart TB
    Start([Start]) --> ECheck{Root user and system Perl present?}
    ECheck -- "No" --> AbortEnv["Exit: Must run as root / have Perl"]
    ECheck -- "Yes" --> ParseArgs[Parse command-line arguments]
    ParseArgs -->|"Help flag or invalid arg"| Usage["Show usage and exit"]
    ParseArgs -->|"Proceed"| InitEnv["Initialize environment (source scripts, set variables, prepare logs)"] 
    InitEnv --> CheckExist["Check for existing Zimbra installation"]
    CheckExist --> UninstallFlag{Uninstall mode (-u)?}
    UninstallFlag -- "Yes" --> ConfirmRem{Confirm removal of existing install?}
    ConfirmRem -- "Yes" --> Uninstall["Backup config & remove installation"]
    ConfirmRem -- "No" --> ExitNoRem["Exit (no changes)"]
    Uninstall --> End1([End]) 
    ExitNoRem --> End2([End])
    UninstallFlag -- "No" --> License["Display license agreement"]
    License --> UserCheck["Verify running as root user (checkUser)"] 
    UserCheck --> Mode{Autoinstall (defaults file provided)?}
    Mode -- "Yes" --> LoadCfg["Load configuration from defaults file"]
    Mode -- "No" --> SelPkgs["Interactive package selection"]
    SelPkgs --> PlatComp{Platform supported or override used?}
    PlatComp -- "No" --> AbortPlat["Abort: unsupported platform"]
    PlatComp -- "Yes" --> Ready["Verify prerequisites and system readiness"]
    Ready --> Install["Install all Zimbra packages"]
    LoadCfg --> VerCheck{Upgrade version compatible?}
    VerCheck -- "No" --> AbortVer["Abort: incompatible versions"]
    VerCheck -- "Yes" --> Install
    Install --> PostInstall["Installation complete (packages installed)"]
    PostInstall --> UpgradeCheck{Upgrading existing installation?}
    UpgradeCheck -- "Yes" --> Restore["Restore previous config and certificates"]
    UpgradeCheck -- "No" --> ConfigPrep["Proceed to configuration"]
    Restore --> ConfigPrep
    ConfigPrep --> SoftOnly{Software-only mode?}
    SoftOnly -- "Yes" --> EndSW(["End (software-only installation)"])
    SoftOnly -- "No" --> ZMSetup["Run zmsetup.pl for post-install configuration"]
    ZMSetup --> Success{Configuration successful?}
    Success -- "No" --> AbortSetup["Exit with error (configuration failed)"]
    Success -- "Yes" --> Complete(["Installation & setup complete"])

Flowchart: Key steps and decision points in install.sh. Dashed lines indicate an exit/abort path when conditions are not met or the user chooses not to proceed. This covers initial checks (root, Perl), argument-driven branches (uninstall vs install), interactive confirmations for license and platform support, the installation of packages, and the final configuration step via zmsetup.pl.

Conclusion

The install.sh script for Zimbra is a comprehensive installer that handles a variety of scenarios (new install, upgrade, uninstall, automated or interactive) in a robust way. It ensures the system is ready for Zimbra, guides the flow based on user input and existing state, and delegates final setup to the zmsetup.pl Perl script for configuring the collaboration suite. By understanding each section of this script – from argument parsing to environment setup, through package installation and into post-install configuration – an experienced developer or administrator can modify or troubleshoot the installer as needed. The flowchart and explanations above serve as a roadmap to the script’s logic, helping in pinpointing where to adjust behaviors or how to interpret the installer’s output during a Zimbra deployment. With this knowledge, one can confidently navigate the installation process or tailor it for custom deployment requirements.

Tools

A docker image and build tool was created to test and observe these scripts in various operational modes. It can quickly be brought up and down (< 1 second) to test and investigate various install scenarios or to debug parts of the toolchains.


More articles written by me, https://wiki.zimbra.com/wiki/JDunphy-Notes

Jump to: navigation, search