├── screenshots ├── ui.png └── license.png ├── 10-answer-file.txt ├── 10.1 Answer File ├── Zimbra 9.0 Answer File.txt ├── LICENSE ├── zim-install-config ├── README.md ├── supported-os-installer.sh ├── z9installer └── zinstaller-10.1 /screenshots/ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zimbra/zinstaller/HEAD/screenshots/ui.png -------------------------------------------------------------------------------- /screenshots/license.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zimbra/zinstaller/HEAD/screenshots/license.png -------------------------------------------------------------------------------- /10-answer-file.txt: -------------------------------------------------------------------------------- 1 | Z10 Answer File 2 | --------------- 3 | y --> EULA 4 | y --> Repo 5 | y --> LDAP 6 | y --> Logger 7 | y --> MTA 8 | n --> DNS Cache 9 | n --> SNMP 10 | y --> Store 11 | n --> Apache 12 | n --> Spell 13 | y --> Convertd 14 | y --> Memcache 15 | y --> Proxy 16 | y --> Archiving 17 | y --> OnlyOffice 18 | y --> chat/video 19 | y --> Continue (y/n) 20 | -------------------------------------------------------------------------------- /10.1 Answer File: -------------------------------------------------------------------------------- 1 | Z10.1 Answer File 2 | --------------- 3 | y --> EULA 4 | y --> Repo 5 | y --> LDAP 6 | y --> Logger 7 | y --> MTA 8 | n --> DNS Cache 9 | n --> SNMP 10 | y --> License Daemon 11 | y --> Store 12 | n --> Apache 13 | n --> Spell 14 | y --> Convertd 15 | y --> Memcache 16 | y --> Proxy 17 | y --> Archiving 18 | y --> OnlyOffice 19 | y --> Continue (y/n) -------------------------------------------------------------------------------- /Zimbra 9.0 Answer File.txt: -------------------------------------------------------------------------------- 1 | Zimbra 9.0 Answer File 2 | ---------------------- 3 | y --> EULA 4 | y --> EULA 5 | y --> Repo 6 | y --> LDAP 7 | y --> Logger 8 | y --> MTA 9 | n --> DNS Cache 10 | y --> SNMP 11 | y --> Store 12 | y --> Apache 13 | y --> Spell 14 | y --> Convertd 15 | y --> Memcache 16 | y --> Proxy 17 | n --> Archiving 18 | n --> Drive 19 | n --> IMAP Beta 20 | y --> NG 21 | n --> Connect 22 | y --> Continue (y/n) 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2022, 2023, 2024 Zimbra 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /zim-install-config: -------------------------------------------------------------------------------- 1 | # Example configuration file for Zimbra Automated Installation. 2 | # The placeholder_domainname, placeholder_hostname and other strings starting with word 'placeholder' 3 | # -> Get replaced with actual hostname, domain name and other params later. 4 | 5 | AVDOMAIN="placeholder_domainname" 6 | AVUSER="admin@placeholder_domainname" 7 | CREATEADMIN="admin@placeholder_domainname" 8 | CREATEADMINPASS="placeholder_adminpass" 9 | CREATEDOMAIN="placeholder_domainname" 10 | DOCREATEADMIN="yes" 11 | DOCREATEDOMAIN="yes" 12 | DOTRAINSA="yes" 13 | ENABLEDEFAULTBACKUP="yes" 14 | EXPANDMENU="no" 15 | HOSTNAME="placeholder_hostname" 16 | HTTPPORT="8080" 17 | HTTPPROXY="TRUE" 18 | HTTPPROXYPORT="80" 19 | HTTPSPORT="8443" 20 | HTTPSPROXYPORT="443" 21 | IMAPPORT="7143" 22 | IMAPPROXYPORT="143" 23 | IMAPSSLPORT="7993" 24 | IMAPSSLPROXYPORT="993" 25 | INSTALL_WEBAPPS="service zimlet zimbra zimbraAdmin" 26 | JAVAHOME="/opt/zimbra/common/lib/jvm/java" 27 | LDAPBESSEARCHSET="set" 28 | LDAPAMAVISPASS="placeholder_adminpass" 29 | LDAPPOSTPASS="placeholder_adminpass" 30 | LDAPROOTPASS="placeholder_adminpass" 31 | LDAPADMINPASS="placeholder_adminpass" 32 | LDAPREPPASS="placeholder_adminpass" 33 | LDAPBESSEARCHSET="set" 34 | LDAPDEFAULTSLOADED="1" 35 | LDAPHOST="placeholder_hostname" 36 | LDAPPORT="389" 37 | LDAPREPLICATIONTYPE="master" 38 | LDAPSERVERID="2" 39 | LICENSEFILE="/tmp/zcs/ZCSLicense.xml" 40 | MAILBOXDMEMORY="1920" 41 | MAILPROXY="TRUE" 42 | MODE="https" 43 | MYSQLMEMORYPERCENT="30" 44 | POPPORT="7110" 45 | POPPROXYPORT="110" 46 | POPSSLPORT="7995" 47 | POPSSLPROXYPORT="995" 48 | PROXYMODE="https" 49 | REMOVE="no" 50 | RUNARCHIVING="no" 51 | RUNAV="yes" 52 | RUNCBPOLICYD="no" 53 | RUNDKIM="yes" 54 | RUNSA="yes" 55 | RUNVMHA="no" 56 | SERVICEWEBAPP="yes" 57 | SMTPDEST="admin@placeholder_domainname" 58 | SMTPHOST="placeholder_hostname" 59 | SMTPNOTIFY="yes" 60 | SMTPSOURCE="admin@placeholder_domainname" 61 | SNMPNOTIFY="yes" 62 | SNMPTRAPHOST="placeholder_hostname" 63 | SPELLURL="http://placeholder_hostname:7780/aspell.php" 64 | STARTSERVERS="yes" 65 | SYSTEMMEMORY="placeholder_systemmem" 66 | TRAINSAHAM="ham.account@placeholder_domainname" 67 | TRAINSASPAM="spam.account@placeholder_domainname" 68 | UIWEBAPPS="yes" 69 | UPGRADE="yes" 70 | USEKBSHORTCUTS="TRUE" 71 | USESPELL="yes" 72 | VERSIONUPDATECHECKS="TRUE" 73 | VIRUSQUARANTINE="virus-quarantine.account@placeholder_domainname" 74 | ZIMBRA_REQ_SECURITY="yes" 75 | ldap_bes_searcher_password="placeholder_adminpass" 76 | ldap_dit_base_dn_config="cn=zimbra" 77 | ldap_nginx_password="placeholder_adminpass" 78 | mailboxd_directory="/opt/zimbra/mailboxd" 79 | mailboxd_keystore="/opt/zimbra/mailboxd/etc/keystore" 80 | mailboxd_keystore_password="placeholder_adminpass" 81 | mailboxd_server="jetty" 82 | mailboxd_truststore="/opt/zimbra/common/lib/jvm/java/lib/security/cacerts" 83 | mailboxd_truststore_password="changeit" 84 | postfix_mail_owner="postfix" 85 | postfix_setgid_group="postdrop" 86 | ssl_default_digest="sha256" 87 | zimbraDNSMasterIP="8.8.4.4" 88 | zimbraDNSTCPUpstream="no" 89 | zimbraDNSUseTCP="yes" 90 | zimbraDNSUseUDP="yes" 91 | zimbraDefaultDomainName="placeholder_domainname" 92 | zimbraFeatureBriefcasesEnabled="Enabled" 93 | zimbraFeatureTasksEnabled="Enabled" 94 | zimbraIPMode="ipv4" 95 | zimbraMailProxy="FALSE" 96 | zimbraMtaMyNetworks="127.0.0.0/8 placeholder_hostip/32 [::1]/128 [fe80::]/64" 97 | zimbraPrefTimeZoneId="placeholder_timezone" 98 | zimbraReverseProxyLookupTarget="TRUE" 99 | zimbraVersionCheckInterval="1d" 100 | zimbraVersionCheckNotificationEmail="admin@placeholder_domainname" 101 | zimbraVersionCheckNotificationEmailFrom="admin@placeholder_domainname" 102 | zimbraVersionCheckSendNotifications="TRUE" 103 | zimbraWebProxy="TRUE" 104 | zimbra_ldap_userdn="uid=zimbra,cn=admins,cn=zimbra" 105 | zimbra_require_interprocess_security="1" 106 | zimbra_server_hostname="placeholder_hostname" 107 | 108 | UPGRADE="no" 109 | USE_ZIMBRA_PACKAGE_SERVER="yes" 110 | PACKAGE_SERVER="repo.zimbra.com" 111 | INSTALL_PACKAGES="placeholder_install_pkgs" 112 | # Do not remove the new line 113 | 114 | 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zimbra automated installer 2 | 3 | ## Automated installation of Zimbra and Lets Encrypt 4 | 5 | This article introduces the `zinstaller` script that can be used for automating the installation of Zimbra. The `zinstaller` script will install a Zimbra 10 single server on Ubuntu 20 and will also obtain and install a 60-day trial license. 6 | 7 | If you are new to Zimbra, the `zinstaller` script makes it easy to evaluate Zimbra on premise. If you already run Zimbra you can use `zinstaller` to preview the latest features. Developers can use `zinstaller` as an easy way to set-up a development server. 8 | 9 | ### Running the old zinstaller script 10 | 11 | If your mail server is reachable under mail.example.com and you want your email addresses to look like info@example.com, you can run `zinstaller` as follows: 12 | 13 | ``` 14 | wget https://raw.githubusercontent.com/Zimbra/zinstaller/master/zinstaller -O /root/zinstaller 15 | chmod +x /root/zinstaller 16 | /root/zinstaller -p put-a-password-here -n mail -t 'Europe/London' -a n --letsencrypt y example.com 17 | 18 | ``` 19 | 20 | ## Running the new automated install script 21 | 22 | - The `supported-os-installer.sh` is new install script to support installs with new license server and all supported OS versions. 23 | - New script is an attempt to create a new unified auto install script which can be used across test/dev platforms. 24 | - Its a wrapper script around manual install process of installing Zimbra. (`supported-os-installer.sh`) 25 | - This script should support installing all version of zimbra for all zimbra supported OS versions. 26 | - Tested on ubuntu20, ubuntu18, rhel7, rhel8 OS versions. 27 | - This script should also support installation of new 10.1.0 version which requires license key instead of license.xml. 28 | 29 | **Run as follows** 30 | - Currently, this script can be used to install zimbra on a SINGLE NODE ONLY. 31 | - License xml or License key is required argument depending on which ZCS version you are trying to install. 32 | - You can provide both License key or License xml file path with `--license` option 33 | - Download follwing files for the script to work - 34 | ``` 35 | wget https://raw.githubusercontent.com/Zimbra/zinstaller/master/supported-os-installer.sh 36 | wget https://raw.githubusercontent.com/Zimbra/zinstaller/master/zim-install-config 37 | ``` 38 | - The file `zim-install-config` should serve as a default install config file. You can also modify it according to your own needs. But make sure not to replace any string that start with `placeholder_xxxx`. 39 | - Run following for help - 40 | ``` 41 | supported-os-installer.sh --help 42 | ``` 43 | - For 10.0.0 / 9.0.0 / 8.8.15 versions - 44 | ``` 45 | supported-os-installer.sh -l /path/to/license.xml --optional-pkg --optional-pkg 46 | ``` 47 | - For versions 10.1x.xx 48 | ``` 49 | supported-os-installer.sh -l --optional-pkg --optional-pkg 50 | ``` 51 | - If the ZCS binary tgz file path is not provided the by-default the script will download the `10.0.0_GA` build based on the currrent operating system. 52 | - The new automated install script does not have letsencrypt support yet. 53 | 54 | 55 | **Having a poor connection over SSH? Try using `screen`:** 56 | 57 | ``` 58 | apt -y install screen 59 | screen 60 | wget https://raw.githubusercontent.com/Zimbra/zinstaller/master/zinstaller -O /root/zinstaller 61 | chmod +x /root/zinstaller 62 | /root/zinstaller -p put-a-password-here -n mail -t 'Europe/London' -a n --letsencrypt y example.com 63 | ``` 64 | Should your connection drop, you can use the ssh command like normal and resume your session using: 65 | 66 | ``` 67 | screen -r 68 | ``` 69 | 70 | ## Certificate renewal 71 | 72 | The `zinstaller` set's up a daily cron job to renew and deploy the Let's Encrypt certificate on Zimbra, you must however restart Zimbra manually at a suitable time for the new certificate to be used. To do this issue `sudo su zimbra -c "/opt/zimbra/bin/zmcontrol restart"` on the command line. 73 | 74 | ## Screenshots 75 | 76 | ![](screenshots/license.png) 77 | *Installed trial license.* 78 | 79 | ![](screenshots/ui.png) 80 | *Modern UI after installation.* 81 | -------------------------------------------------------------------------------- /supported-os-installer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function display_options { 4 | cat << HELP_EOF 5 | "$0" -i -l -t -a --optional-pkg --optional-pkg 6 | options: 7 | -h, --help Help 8 | -p, --admin-pass Admin account password to set. (Default: Random) 9 | -l, --license License key or License file to be activated on the zimbra server. (Required) (No default) 10 | -i, --install-config The default install config to configure zimbra server. (Default = $(pwd)/zim-install-config) 11 | -b, --zcs-binary-tgz Build artifact / Tar file path (Default = 10.0.0_GA Build will be downloaded) 12 | -n, --hostname Hostname for the server. (Default = $(hostname -f)) 13 | -d, --domain-name Domain name for zimbra installation. (Default: DOMAIN_NAME = HOSTNAME) 14 | -t, --time-zone Time zone required to install. (Default: Asia/Singapore) 15 | --optional-pkg Additional package apart from default packages to install 16 | Default pkgs: zimbra-ldap zimbra-logger zimbra-mta zimbra-snmp zimbra-store zimbra-apache zimbra-spell 17 | zimbra-convertd zimbra-memcached zimbra-proxy zimbra-archiving zimbra-onlyoffice zimbra-license-daemon" 18 | Optional pkgs: zimbra-modern-ui zimbra-modern-zimlets zimbra-zimlet-document-editor zimbra-zimlet-classic-document-editor 19 | zimbra-patch zimbra-mta-patch zimbra-proxy-patch zimbra-ldap-patch 20 | HELP_EOF 21 | } 22 | 23 | function main { 24 | set -x 25 | dir_script="$(cd "$(dirname "$0")" && pwd)" 26 | 27 | ZCS_BINARY_TGZ="$(find $dir_script -name "zcs-*.tgz")" 28 | WORK_DIR="$(ls "$ZCS_BINARY_TGZ" | sed s/.tgz//g)" 29 | INSTALL_CONFIG="$dir_script/zim-install-config" 30 | 31 | HOSTNAME="$(hostname -f)" 32 | HOST_IP="$(curl -s api.ipify.org)" 33 | # HOST_IP="$(hostname -I | cut -f1 -d" " | tr -d '[:space:]')" 34 | DOMAIN_NAME="$HOSTNAME" 35 | ADMIN_PASS="$(openssl rand -base64 48 | cut -c1-12)" 36 | TIMEZONE="Asia/Singapore" 37 | CURRENT_USER="$(whoami)" 38 | sys_mem_kb="$(cat /proc/meminfo | grep MemAvailable | awk '{print $2}')" 39 | SYSTEM_MEMORY_AVAIL="$(expr $sys_mem_kb / 1024 / 1024)" 40 | # get version from tar file 10.0.0/8.0.0/9.0.0 41 | ZCS_VERSION="$(echo $ZCS_BINARY_TGZ | grep -oP "(?<=-)\d+(\.\d+)+")" 42 | ver_pattern="10\.\([1-9]\|[1-9][0-9]\)\.*" # matches 10.1x.xx 43 | INSTALL_PKGS=( 44 | zimbra-ldap 45 | zimbra-logger 46 | zimbra-mta 47 | zimbra-snmp 48 | zimbra-store 49 | zimbra-apache 50 | zimbra-spell 51 | zimbra-convertd 52 | zimbra-memcached 53 | zimbra-proxy 54 | zimbra-archiving 55 | zimbra-onlyoffice 56 | ) 57 | if echo "$ZCS_VERSION" | grep $ver_pattern >> /dev/null; then 58 | INSTALL_PKGS+=("zimbra-license-daemon") 59 | fi 60 | 61 | redhat_release="false" 62 | command -v yum &>/dev/null 63 | if [[ "$?" -eq 0 ]]; then 64 | redhat_release="true"; 65 | fi 66 | 67 | # Processing input 68 | while [ $# -gt 0 ]; do 69 | key="$1" 70 | case $key in 71 | -h|--help) 72 | display_options 73 | exit 74 | ;; 75 | -d|--domain-name) 76 | DOMAIN_NAME="$2" 77 | shift 78 | shift 79 | ;; 80 | -i|--install-config) 81 | INSTALL_CONFIG="$2" 82 | shift 83 | shift 84 | ;; 85 | -b|--build-artifact) 86 | ZCS_BINARY_TGZ="$2" 87 | shift 88 | shift 89 | ;; 90 | -l|--license) 91 | LICENSE="$2" 92 | shift 93 | shift 94 | ;; 95 | -p|--admin-pass) 96 | ADMIN_PASS="$2" 97 | shift 98 | shift 99 | ;; 100 | -t|--time-zone) 101 | TIMEZONE="$2" 102 | shift 103 | shift 104 | ;; 105 | --optional-pkg) 106 | INSTALL_PKGS+=("$2") 107 | shift 108 | shift 109 | ;; 110 | *) 111 | echo "Invalid argument(s): $2" 112 | echo -e "\n\n\n" 113 | display_options && exit 1 114 | ;; 115 | esac 116 | done 117 | 118 | # Functions 119 | check_vars 120 | check_sudoer 121 | 122 | # Install zimbra by injecting the config values. 123 | install_zimbra 124 | } 125 | 126 | 127 | function check_vars { 128 | [[ -z "$INSTALL_CONFIG" ]] && echo "Install defaults file path not defined." && exit 1; 129 | 130 | # Check if license key of file is given, validate format 131 | if [[ -f "$LICENSE" ]]; then 132 | echo "License file is provided" 133 | # Check if version is 10.1x.xx 134 | if echo "$ZCS_VERSION" | grep $ver_pattern >> /dev/null; then 135 | echo "$ZCS_VERSION Does not support license in file format. Use license key instead." 136 | exit 1; 137 | else 138 | license_file="$LICENSE" 139 | fi 140 | else 141 | echo "License key is provided" 142 | # Check if version is 10.1x.xx 143 | if echo "$ZCS_VERSION" | grep $ver_pattern >> /dev/null; then 144 | # Check if license key is in valid format 145 | if echo "$LICENSE" | grep '^[0-9]\+$' >> /dev/null; then 146 | license_key="$LICENSE" 147 | else 148 | echo "Invalid key format: $LICENSE License key must only contain numbers." 149 | exit 1; 150 | fi 151 | else 152 | echo "$ZCS_VERSION Does not support license key. Use license xml file format." 153 | exit 1; 154 | fi 155 | fi 156 | 157 | [[ ! -f "$ZCS_BINARY_TGZ" ]] && download_zcs_binary 158 | [[ -z "$HOSTNAME" ]] && echo "Cannot find \$HOSTNAME." && exit 1; 159 | [[ -z "$ADMIN_PASS " ]] && echo "Admin password is empty. Using default password." 160 | [[ -z "$TIMEZONE " ]] && echo "Time-zone provided is empty. Setting default Time-zone." && TIMEZONE="Asia/Singapore" 161 | } 162 | 163 | function download_zcs_binary { 164 | # Download the latest zcs binary from the zimbra downloads page. 165 | local zcs_download_page="https://www.zimbra.com/product/download/zimbra-collaboration-network-edition/" 166 | local files_zimbra="https://files.zimbra.com/downloads" 167 | local default_zcs_version="10.0.0_GA" 168 | local platform_os="$(curl -s https://raw.githubusercontent.com/Zimbra/zm-build/develop/rpmconf/Build/get_plat_tag.sh | sudo bash)" 169 | ZCS_BINARY_TGZ="$(curl -s $zcs_download_page | \ 170 | grep -o '["'\''][^"'\''>]*\.tgz["'\'']' | \ 171 | grep -Eo "zcs-NETWORK-${default_zcs_version}_[0-9]+\.${platform_os}\.[0-9]+\.tgz" | \ 172 | head -n 1)" 173 | cd $dir_script && echo "Downloading $zcs_download_page/$ZCS_BINARY_TGZ" 174 | wget "$files_zimbra/$default_zcs_version/$ZCS_BINARY_TGZ" || exit 1; 175 | } 176 | 177 | function check_sudoer { 178 | # Check if the user has sudo privilages. 179 | if [[ "$redhat_release" == "true" ]]; then 180 | if [[ -z "$(groups $CURRENT_USER | grep 'wheel')" ]]; then 181 | echo -e "User $CURRENT_USER does not have sudo privilages. \n 182 | Provide sudo privilages to $CURRENT_USER user or run as root." && exit 255; 183 | fi 184 | else 185 | if [[ -z "$(groups $CURRENT_USER | grep 'sudo')" ]]; then 186 | echo -e "User $CURRENT_USER does not have sudo privilages. \n 187 | Provide sudo privilages to $CURRENT_USER user or run as root." && exit 255; 188 | fi 189 | fi 190 | 191 | } 192 | 193 | function install_zimbra { 194 | # Uninstall existing installation if present. 195 | extract_build 196 | uninstall_zimbra 197 | 198 | # Prepare the server 199 | install_essential 200 | # Not mandetory on fresh servers / machines 201 | # disable_servs 202 | install_dns 203 | enable_ports 204 | 205 | # Update zimbra config file. 206 | update_zimbra_config 207 | 208 | # checkRequired function checks if the /etc/hosts file contains entry => 127.0.0.1 localhost.localdomain localhost 209 | # Some servers might not allow to manually edit the /etc/hosts file. 210 | # Commenting this function out. 211 | sed -i.bak 's/checkRequired/# checkRequired/' install.sh 212 | 213 | # Auto-install with config file. 214 | # Not using the install responses since they vary more often than never. 215 | # install.sh -l option is removed for 10.1.+ versions. 216 | if echo "$ZCS_VERSION" | grep $ver_pattern >> /dev/null; then 217 | sudo ./install.sh "$WORK_DIR/install.conf" 218 | local ret_code="$(echo $?)" 219 | else 220 | sudo ./install.sh -l "$LICENSE" "$WORK_DIR/install.conf" 221 | local ret_code="$(echo $?)" 222 | fi 223 | 224 | if [[ "$ret_code" -eq 0 ]]; then 225 | echo "Zimbra installation and setup completed." 226 | echo "Activating License" 227 | # Need a logic to activate or skip licence activation here 228 | if echo "$ZCS_VERSION" | grep $ver_pattern >> /dev/null; then 229 | # Version 10.1x.xx, use license key 230 | sudo su - zimbra -c "zmlicense -a $license_key" || \ 231 | echo "Licence activation failed, check logs." 232 | else 233 | # Version 8815/900/1000, Use license file 234 | sudo su - zimbra -c "zmlicense -a $license_file" || \ 235 | echo "Licence activation failed, check logs." 236 | fi 237 | # Run post install config and print information. 238 | postinstall && print_install_complete 239 | else 240 | echo "Error: installation failed." && exit 1 241 | fi 242 | } 243 | 244 | function extract_build { 245 | # Extract build artifact. 246 | echo "Extracting the build artifact..." 247 | tar -xzvf "$ZCS_BINARY_TGZ" 248 | [[ "$?" -ne "0" ]] && echo "Cannot extract the build artifact." && exit 1; 249 | } 250 | 251 | function uninstall_zimbra { 252 | # Uninstall existing installation if present. 253 | cd "$WORK_DIR" && echo "Checking if zimbra is already installed" 254 | sudo su - zimbra -c 'zmcontrol -v' 255 | if [[ $? -eq 0 ]]; then 256 | echo "Warning: $HOSTNAME has following version of zimbra already installed -" 257 | sudo su - zimbra -c 'zmcontrol -v' 258 | else 259 | echo "Already installed zimbra version not found" 260 | fi 261 | echo "Preparing to uninstall irrespective of zimbra is installed or not. \n 262 | This will clear the /opt/zimbra and other settings if present." 263 | # 'yes' answers to the confirm uninstallation question if asked. 264 | sudo ./install.sh -u << 'EOF' 265 | Yes 266 | EOF 267 | zimbra_dir="/opt/zimbra" 268 | echo " Checking if the zimbra is uninstalled properly..." 269 | if [[ -d "$zimbra_dir" ]]; then 270 | command -v zmcontrol >> /dev/null 271 | if [[ "$?" -ne 0 ]]; then 272 | echo -e "Warning: The 'zmcontrol' command and directory still \"$zimbra_dir\" still exists.\nZimbra might not be completely uninstalled.\n This could affect the new installation." 273 | fi 274 | echo "Zimbra Uninstall is successful." 275 | fi 276 | } 277 | 278 | function disable_servs { 279 | # Disable all non essential services for installing zimbra. 280 | echo "Disabling some of the non-essential services for Zimbra ..." 281 | services_arr=( 282 | postfix httpd exim named apache2 sendmail mysqld mariadb 283 | ) 284 | 285 | # Disable services one by one. 286 | for i in ${services_arr[@]}; do 287 | echo "Processing service $i" 288 | sudo systemctl stop "$i" || echo "Warning: Cannot stop the service $i. Installation may get affected." 289 | sudo systemctl disable "$i" || echo "Warning: Cannot Disable the service $i. Installation may get affected." 290 | sudo systemctl mask "$i" || echo "Warning: Cannot Mask the service $i. Installation may get affected." 291 | done 292 | } 293 | 294 | function install_essential { 295 | echo "Updating system and installing some essential packages ..." 296 | 297 | if [[ "$redhat_release" == "true" ]]; then 298 | sudo yum update -q -y < /dev/null > /dev/null 299 | sudo yum upgrade -q -y < /dev/null > /dev/null 300 | else 301 | sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq -y < /dev/null > /dev/null 302 | sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -qq -y < /dev/null > /dev/null 303 | fi 304 | 305 | list_essentials_ubuntu=( 306 | apt-utils netcat-openbsd sudo libidn11 libpcre3 libgmp10 \ 307 | libexpat1 libstdc++6 libaio1 resolvconf \ 308 | unzip pax sysstat sqlite3 dnsmasq lsb-release net-tools \ 309 | netfilter-persistent dnsutils iptables sed wget rsyslog ldapscripts 310 | ) 311 | list_essentials_redhat=( 312 | nmap-ncat sudo libidn pcre gmp expat libstdc++ libaio unzip \ 313 | sysstat sqlite dnsmasq redhat-lsb-core net-tools iptables \ 314 | bind-utils wget rsyslog openldap-clients 315 | ) 316 | 317 | # Prints all package names in a single line to trigger install. 318 | all_pkgs_ubuntu="$(echo ${list_essentials_ubuntu[*]})" 319 | all_pkgs_redhat="$(echo ${list_essentials_redhat[*]})" 320 | if [[ "$redhat_release" == "true" ]]; then 321 | sudo yum install -q -y $all_pkgs_redhat< /dev/null > /dev/null 322 | else 323 | sudo DEBIAN_FRONTEND=noninteractive apt-get install -qq -y $all_pkgs_ubuntu< /dev/null > /dev/null 324 | fi 325 | [[ "$?" -ne "0" ]] && echo "Cannot get some of essential packages. Installation may fail." || \ 326 | echo "Essential packages installed successfully." 327 | } 328 | 329 | function install_dns { 330 | # Install a DNS Server 331 | echo "Configuring dnsmasq ..." 332 | sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.old || true 333 | 334 | #create the conf file 335 | nsentry="$(printf "server=8.8.8.8\nserver=8.8.4.4\nserver=9.9.9.9\nserver=149.112.112.112\nserver=1.1.1.1\nserver=1.0.0.1\nlisten-address=127.0.0.1\ndomain='$DOMAIN_NAME'\nmx-host='$DOMAIN_NAME','$HOSTNAME',0\naddress=/$HOSTNAME/$HOST_IP\n")" 336 | echo "$nsentry" | sudo tee /etc/dnsmasq.conf 337 | local resolv_file="/etc/resolv.conf" 338 | grep 'nameserver 8.8.8.8' /etc/resolv.conf >> /dev/null 339 | local ret="$(echo $?)" 340 | if [[ "$ret" -eq 0 ]]; then 341 | echo "Nameserver is correct in $resolv_file" 342 | else 343 | # Edit resolve.conf 344 | sudo cp /etc/resolv.conf /etc/resolv.conf.old 345 | sudo sed -i 's/^nameserver [0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/nameserver 8.8.8.8/' "$resolv_file" 346 | echo "Replacement completed!" 347 | fi 348 | 349 | # restart dns services 350 | sudo systemctl enable dnsmasq.service > /dev/null 2>&1 \ 351 | && sudo systemctl restart dnsmasq.service 352 | if [[ "$?" -eq 0 ]]; then 353 | echo "dnsmasq.service started successfully." 354 | else 355 | echo "Failed to start service -> dnsmasq.service" && exit 1; 356 | fi 357 | 358 | # Check DNS 359 | echo "Checking DNS ..." 360 | name="$(host license.zimbra.com)" 361 | if [[ "$name" == *"not found"* ]]; then 362 | echo -e "DNS resolution failed! Check your resolve.conf file." && exit 1 363 | else 364 | echo -e "DNS resolution done." 365 | fi 366 | } 367 | 368 | function enable_ports { 369 | # Enable all required ports using iptables. 370 | echo "Enabling firewall for Zimbra ports ..." 371 | echo "Ports 22 / 25 / 143 / 80 / 443 / 465 / 587 / 995 / 993 / 9071 will be opened to the internet." 372 | echo "Please check your iptables for more info." 373 | 374 | # Array of all ports required. 375 | ports_arr=("25" "80" "110" "143" "443" "465" "587" "993" "995" "9071") 376 | 377 | echo "Opening the ports with iptables..." 378 | for port in ${ports_arr}; do 379 | echo -e "Allowing incoming traffic on port $port ...\n" 380 | sudo iptables -A INPUT -p tcp --dport "$port" -j ACCEPT 381 | done 382 | 383 | #Allow ports 384 | for p in ${ports_arr[@]}; do 385 | sudo lsof -i tcp:"$p" 386 | if [[ "$?" -eq 0 ]]; then 387 | # Kill all proccesses on that port using PID's 388 | sudo kill "$(sudo lsof -t -i tcp:"$p")" 389 | # Alternate option - permissions not propagated towards the end of the pipeline. 390 | # sudo lsof -i tcp:"$p" | awk 'NR!=1 {print $2}' | xargs sudo kill 391 | echo "Killed all processes on Port $p for installation." 392 | else 393 | echo "Warning: Failed to Kill all processes on Port $p" 394 | echo "Port conflicts may occur." 395 | fi 396 | done 397 | 398 | #Check Firewall -- Commented out for testing purposes. 399 | # response=$(curl --write-out '%{http_code}' --silent --output /dev/null https://license.zimbra.com) 400 | # if [[ "$response" == "200" ]]; then 401 | # echo "Zimbra servers reachable ..." 402 | # else 403 | # echo "Issue with firewall ... Please check." && exit 1 404 | # fi 405 | } 406 | 407 | function update_zimbra_config { 408 | # Edit zimbra config files to inject and trigger automated install 409 | install_pkgs_string="$(echo ${INSTALL_PKGS[*]})" 410 | sed -e "s|placeholder_hostname|$HOSTNAME|g" \ 411 | -e "s|placeholder_hostip|$HOST_IP|g" \ 412 | -e "s|placeholder_domainname|$DOMAIN_NAME|g" \ 413 | -e "s|placeholder_adminpass|$ADMIN_PASS|g" \ 414 | -e "s|placeholder_timezone|$TIMEZONE|g" \ 415 | -e "s|placeholder_systemmem|$SYSTEM_MEMORY_AVAIL|g" \ 416 | -e "s|placeholder_install_pkgs|$install_pkgs_string|g" $INSTALL_CONFIG >> $WORK_DIR/install.conf 417 | # Add License key if version => 10.1x.xx 418 | if echo "$ZCS_VERSION" | grep $ver_pattern >> /dev/null; then 419 | echo -e "\n\n" 420 | echo "LICENSEACTIVATIONOPTION=1" >> $WORK_DIR/install.conf 421 | echo "LICENSEKEY=$license_key" >> $WORK_DIR/install.conf 422 | fi 423 | } 424 | 425 | function postinstall { 426 | # Checks LICENSE and service status 427 | echo "Running post installation checks and settings..." 428 | echo "Adding Admin console proxy" && \ 429 | sudo su - zimbra -c "zmcontrol -v" || exit 1; 430 | sudo su - zimbra -c "/opt/zimbra/libexec/zmproxyconfig -e -w -C -H $HOSTNAME" 431 | local status="$(sudo su - zimbra -c "zmcontrol status")" 432 | if echo "$status" | grep "not running" >> /dev/null; then 433 | echo "Error: Some services are not running. Please check logs." && exit 1 434 | else 435 | echo "All services are up and running. ZCS auto installation is complete." 436 | echo "Check the service status on $HOSTNAME " 437 | do_settings 438 | fi 439 | } 440 | 441 | function do_settings { 442 | # Do Optimal security settings 443 | echo "Setting optimal security settings" 444 | rm -Rf /tmp/provfile 445 | 446 | cat >> /tmp/provfile << EOF 447 | mcf zimbraPublicServiceProtocol https 448 | mcf zimbraPublicServicePort 443 449 | mcf zimbraPublicServiceHostname $HOSTNAME 450 | mcf zimbraReverseProxySSLProtocols TLSv1.2 451 | mcf +zimbraReverseProxySSLProtocols TLSv1.3 452 | mcf zimbraReverseProxySSLCiphers "" 453 | mcf +zimbraResponseHeader "Strict-Transport-Security: max-age=31536000; includeSubDomains" 454 | mcf +zimbraResponseHeader "X-Content-Type-Options: nosniff" 455 | mcf +zimbraResponseHeader "X-Robots-Tag: noindex" 456 | mcf +zimbraResponseHeader "Referrer-Policy: no-referrer" 457 | mcf zimbraMailKeepOutWebCrawlers TRUE 458 | mcf zimbraSmtpSendAddMailer FALSE 459 | 460 | mcf zimbraSSLDHParam /etc/ffdhe4096.pem 461 | 462 | mcf zimbraMtaSmtpdTlsCiphers medium 463 | mcf zimbraMtaSmtpdTlsMandatoryCiphers medium 464 | mcf zimbraMtaSmtpdTlsProtocols '>=TLSv1.2' 465 | mcf zimbraMtaTlsSecurityLevel may 466 | 467 | ms $HOSTNAME zimbraPop3CleartextLoginEnabled FALSE 468 | ms $HOSTNAME zimbraImapCleartextLoginEnabled FALSE 469 | 470 | mcf zimbraLastLogonTimestampFrequency 1s 471 | mc default zimbraPrefShortEmailAddress FALSE 472 | mc default zimbraFeatureTwoFactorAuthAvailable TRUE 473 | 474 | mcf +zimbraMailTrustedIP 127.0.0.1 475 | mcf +zimbraMailTrustedIP $HOST_IP 476 | mcf +zimbraGalLdapAttrMap manager=manager 477 | mcf zimbraBackupReportEmailSender admin@$DOMAIN_NAME zimbraBackupReportEmailRecipients admin@$DOMAIN_NAME 478 | 479 | ms $HOSTNAME zimbraFileUploadMaxSize 80000000 480 | ms $HOSTNAME zimbraMailContentMaxSize 80000000 481 | mcf zimbraMtaMaxMessageSize 80000000 482 | mcf zimbraFileUploadMaxSize 80000000 483 | mcf zimbraMailContentMaxSize 80000000 484 | EOF 485 | 486 | # Update Authkeys and Syslog 487 | sudo su - zimbra -c '/opt/zimbra/bin/postconf -e fast_flush_domains=""' 488 | sudo su - zimbra -c '/opt/zimbra/bin/postconf -e smtpd_etrn_restrictions=reject' 489 | sudo su - zimbra -c '/opt/zimbra/bin/postconf -e disable_vrfy_command=yes' 490 | sudo su - zimbra -c '/opt/zimbra/bin/postconf -e tls_medium_cipherlist=$(/opt/zimbra/common/bin/openssl ciphers)' 491 | sudo su - zimbra -c '/opt/zimbra/bin/postconf -e tls_preempt_cipherlist=no' 492 | 493 | sudo su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_common_tlsprotocolmin="3.3"' 494 | sudo su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_common_tlsciphersuite="HIGH"' 495 | sudo su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_starttls_supported=1' 496 | sudo su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e zimbra_require_interprocess_security=1' 497 | sudo su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_starttls_required=true' 498 | 499 | sudo su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e alias_login_enabled=false' 500 | sudo su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e zimbra_same_site_cookie="Strict"' 501 | 502 | sudo su - zimbra -c '/opt/zimbra/bin/zmprov < /tmp/provfile' 503 | 504 | #https://wiki.zimbra.com/wiki/Enabling_Admin_Console_Proxy 505 | sudo su - zimbra -c "/opt/zimbra/libexec/zmproxyconfig -e -w -C -H $HOSTNAME" 506 | 507 | # Update Authkeys and Syslog 508 | sudo su - zimbra -c '/opt/zimbra/bin/zmupdateauthkeys' 509 | sudo /opt/zimbra/libexec/zmsyslogsetup 510 | 511 | sudo su - zimbra -c '/opt/zimbra/bin/zmzimletctl undeploy com_zimbra_clientuploader' 512 | sudo rm -Rf /opt/zimbra/lib/ext/com_zimbra_clientuploader 513 | 514 | sudo su - zimbra -c '/opt/zimbra/bin/zmcontrol restart' || exit 1; 515 | } 516 | 517 | function print_install_complete { 518 | # Info about new installation 519 | cat << here 520 | Your new Zimbra installation details are: 521 | - Webmail Login: https://${HOSTNAME} 522 | - Admin Console: https://${HOSTNAME}:9071 523 | - Admin Username: admin@${HOSTNAME} 524 | - Admin Password: $ADMIN_PASS 525 | here 526 | } 527 | 528 | # ######################### 529 | main "$@" 530 | # ######################### 531 | -------------------------------------------------------------------------------- /z9installer: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if (lsb_release -d) | grep -q "Ubuntu 20"; then 4 | echo $(lsb_release -d) is supported 5 | else 6 | echo $(lsb_release -d) is not supported 7 | exit 8 | fi 9 | 10 | # Argbash - see https://argbash.io for more info 11 | die() { 12 | local _ret="${2:-1}" 13 | test "${_PRINT_HELP:-no}" = yes && print_help >&2 14 | echo "$1" >&2 15 | exit "${_ret}" 16 | } 17 | 18 | u=`id -un` 19 | if [ x$u != "xroot" ]; then 20 | echo "Error: must be run as root user" 21 | exit 1 22 | fi 23 | 24 | print_help() { 25 | printf '%s\n' 26 | printf '%s\n' "Install and configure Zimbra 9.0 ..." 27 | printf 'Usage: %s [-p|--password ] [-t|--timezone ] [-l|--letsencypt ] [-h|--help] \n' "$(basename $0)" 28 | printf '\t%s\n' ": Domain to install Zimbra for" 29 | printf '\t%s\n' "-p, --password: Admin password to use (no default)" 30 | printf '\t%s\n' "-n, --hostname: Hostname to use for the server (default: mail)" 31 | printf '\t%s\n' "-t, --timezone: Timezone to set the server to user (optional) (default: 'Singapore')" 32 | printf '\t%s\n' "-l, --letsencypt: Use Let's Encrypt for providing TLS certificates (optional y/n) (default: 'n')" 33 | printf '\t%s\n' "-a, --apache: Add support for spell check and convertd (optional y/n) (default: 'n')" 34 | printf '\t%s\n' "-h, --help: Prints help" 35 | printf '%s\n' 36 | printf '%s\n' "Usage: $(basename $0) [-p mypassword] [-t 'TimeZone'] [-n Server-Name] [-a n] [-l y] Domain-Name" 37 | printf '%s\n' "Example: $(basename $0) -p alRTFGmn1 -n zmail -t 'Europe/London' -a n -l y myorg.co.uk" 38 | exit 1 39 | } 40 | 41 | parse_commandline() { 42 | _positionals_count=0 43 | while test $# -gt 0; do 44 | _key="$1" 45 | case "$_key" in 46 | -p|--password) 47 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 48 | _arg_password="$2" 49 | shift 50 | ;; 51 | --password=*) 52 | _arg_password="${_key##--password=}" 53 | ;; 54 | -p*) 55 | _arg_password="${_key##-p}" 56 | ;; 57 | -n|--hostname) 58 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 59 | _arg_hostname="$2" 60 | shift 61 | ;; 62 | --hostname=*) 63 | _arg_hostname="${_key##--hostname=}" 64 | ;; 65 | -n) 66 | _arg_hostname="${_key##-t}" 67 | ;; 68 | -t|--timezone) 69 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 70 | _arg_timezone="$2" 71 | shift 72 | ;; 73 | --timezone=*) 74 | _arg_timezone="${_key##--timezone=}" 75 | ;; 76 | -t*) 77 | _arg_timezone="${_key##-t}" 78 | ;; 79 | -a|--apache) 80 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 81 | _arg_apace="$2" 82 | shift 83 | ;; 84 | --apache=*) 85 | _arg_apache="${_key##--timezone=}" 86 | ;; 87 | -a*) 88 | _arg_apache="${_key##-t}" 89 | ;; 90 | -l|--letsencrypt) 91 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 92 | _arg_letsencrypt="$2" 93 | shift 94 | ;; 95 | --letsencrypt=*) 96 | _arg_letsencrypt="${_key##--letsencrypt=}" 97 | ;; 98 | -l*) 99 | _arg_letsencrypt="${_key##-l}" 100 | ;; 101 | -h|--help) 102 | print_help 103 | exit 0 104 | ;; 105 | -h*) 106 | print_help 107 | exit 0 108 | ;; 109 | *) 110 | _last_positional="$1" 111 | _positionals+=("$_last_positional") 112 | _positionals_count=$((_positionals_count + 1)) 113 | ;; 114 | esac 115 | shift 116 | done 117 | } 118 | 119 | handle_passed_args_count() { 120 | local _required_args_string="'domain'" 121 | test "${_positionals_count}" -ge 1 || _PRINT_HELP=yes die "FATAL ERROR: Not enough positional arguments - we require exactly 1 (namely: $_required_args_string), but got only ${_positionals_count}." 1 122 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect exactly 1 (namely: $_required_args_string), but got ${_positionals_count} (the last one was: '${_last_positional}')." 1 123 | } 124 | 125 | assign_positional_args() { 126 | local _positional_name _shift_for=$1 127 | _positional_names="_arg_domain " 128 | 129 | shift "$_shift_for" 130 | for _positional_name in ${_positional_names} 131 | do 132 | test $# -gt 0 || break 133 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1 134 | shift 135 | done 136 | } 137 | 138 | parse_commandline "$@" 139 | handle_passed_args_count 140 | assign_positional_args 1 "${_positionals[@]}" 141 | 142 | MYIP=$(hostname -I | cut -f1 -d" " | tr -d '[:space:]') 143 | DOMAIN="$_arg_domain" 144 | HOSTONLY="${_arg_hostname:="mail"}" 145 | HOSTNAME="${_arg_hostname:="mail"}"."$DOMAIN" 146 | TIMEZONE="${_arg_timezone:-"Asia/Singapore"}" 147 | LETSENCRYPT="${_arg_letsencrypt:-"n"}" 148 | APACHE="${_arg_apache:-"n"}" 149 | MYPASSWORD="${_arg_password:-$(openssl rand -base64 9)}" 150 | GREEN='\033[0;32m' 151 | RED='\033[0;31m' 152 | NC='\033[0m' # No Color 153 | SYSTEMMEMORY=$(($(grep MemAvailable /proc/meminfo | awk '{print $2}')/1024/1024)) 154 | 155 | echo "Updating system and installing some essential packages ..." 156 | #What are the other essential packages? 157 | DEBIAN_FRONTEND=noninteractive apt-get update -qq -y < /dev/null > /dev/null 158 | DEBIAN_FRONTEND=noninteractive apt-get upgrade -qq -y < /dev/null > /dev/null 159 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y apt-utils< /dev/null > /dev/null 160 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y netcat-openbsd sudo libidn11 libpcre3 libgmp10 libexpat1 libstdc++6 libperl5.30 libaio1 resolvconf unzip pax sysstat sqlite3< /dev/null > /dev/null 161 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y dnsmasq lsb-release net-tools netfilter-persistent dnsutils iptables sed wget rsyslog ldapscripts< /dev/null > /dev/null 162 | 163 | echo "Disabling some of the non-essential services for Zimbra ..." 164 | systemctl stop postfix 165 | systemctl disable postfix 166 | systemctl mask postfix 167 | 168 | systemctl stop iptables 169 | systemctl disable iptables 170 | systemctl mask iptables 171 | 172 | systemctl stop httpd 173 | systemctl disable httpd 174 | systemctl mask httpd 175 | 176 | systemctl stop exim 177 | systemctl disable exim 178 | systemctl mask exim 179 | 180 | systemctl stop named 181 | systemctl disable named 182 | systemctl mask named 183 | 184 | systemctl stop apache2 185 | systemctl disable apache2 186 | systemctl mask apache2 187 | 188 | systemctl stop sendmail 189 | systemctl disable sendmail 190 | systemctl mask sendmail 191 | 192 | systemctl stop mysqld 193 | systemctl disable mysqld 194 | systemctl mask mysqld 195 | 196 | systemctl stop mariadb 197 | systemctl disable mariadb 198 | systemctl mask mariadb 199 | 200 | systemctl stop systemd-resolved 201 | systemctl disable systemd-resolved 202 | systemctl mask systemd-resolved 203 | 204 | systemctl stop ufw 205 | systemctl disable ufw 206 | systemctl mask ufw 207 | 208 | #Install a DNS Server 209 | echo "Configuring dnsmasq ..." 210 | mv /etc/dnsmasq.conf /etc/dnsmasq.conf.old 211 | #create the conf file 212 | printf 'server=8.8.8.8\nserver=8.8.4.4\nserver=9.9.9.9\nserver=149.112.112.112\nserver=1.1.1.1\nserver=1.0.0.1\nlisten-address=127.0.0.1\ndomain='$DOMAIN'\nmx-host='$DOMAIN','$HOSTNAME',0\naddress=/'$HOSTNAME'/'$MYIP'\n' | tee -a /etc/dnsmasq.conf >/dev/null 213 | mv /etc/resolv.conf {,.old} 214 | echo "nameserver 127.0.0.1" > /etc/resolv.conf 215 | # restart dns services 216 | systemctl enable dnsmasq.service > /dev/null 2>&1 && systemctl restart dnsmasq.service 217 | echo -e "${GREEN}... Done.${NC}" 218 | 219 | # Check DNS 220 | echo "Checking DNS ..." 221 | name=`host license.zimbra.com` 222 | if [[ "$name" == *"not found"* ]]; then 223 | echo -e "${RED}DNS resolution failed! Check your resolve.conf file.${NC}" 224 | exit 1 225 | else 226 | echo -e "${GREEN}... Done.${NC}" 227 | fi 228 | 229 | # Update firewall 230 | echo "Enabling firewall for Zimbra ports ..." 231 | echo "Ports 22/25/143/80/443/465/587/995/993/9071 will be opened to the internet." 232 | echo "Please check your iptables for more info." 233 | 234 | #flushing iptables while having INPUT=DROP policy will terminate ssh connection 235 | iptables -P INPUT ACCEPT 236 | 237 | iptables --flush 238 | #block null packets 239 | iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP 240 | #block syn flood 241 | iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP 242 | #block XMAS packets 243 | iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP 244 | 245 | #accept all traffic on your loopback interface 246 | iptables -A INPUT -i lo -j ACCEPT 247 | iptables -A OUTPUT -o lo -j ACCEPT 248 | 249 | #Allow Established and Related Incoming Connections 250 | iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 251 | 252 | #Allow ports 253 | iptables -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT 254 | iptables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT 255 | iptables -A INPUT -p tcp -m tcp --dport 995 -j ACCEPT 256 | iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT 257 | iptables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT 258 | iptables -A INPUT -p tcp -m tcp --dport 587 -j ACCEPT 259 | iptables -A INPUT -p tcp -m tcp --dport 9071 -j ACCEPT 260 | iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 261 | iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT 262 | iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT 263 | 264 | #enable ping 265 | iptables -A INPUT -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT 266 | iptables -A OUTPUT -p icmp --icmp-type 0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT 267 | 268 | #Set policy defaults 269 | iptables -P OUTPUT ACCEPT 270 | iptables -P FORWARD ACCEPT 271 | iptables -P INPUT DROP 272 | 273 | #IPv6 closed for now 274 | /usr/sbin/ip6tables -P OUTPUT ACCEPT 275 | /usr/sbin/ip6tables -P FORWARD ACCEPT 276 | /usr/sbin/ip6tables -P INPUT DROP 277 | 278 | netfilter-persistent save 279 | 280 | #Check Firewall 281 | response=$(curl --write-out '%{http_code}' --silent --output /dev/null https://license.zimbra.com) 282 | if [[ "$response" == "200" ]]; then 283 | echo "Zimbra License server reachable ..." 284 | echo -e "${GREEN}... Done.${NC}" 285 | else 286 | echo -e "${RED} Issue with firewall ... Please check!${NC}" 287 | exit 1 288 | fi 289 | 290 | # Reset the hosts file 291 | echo "Rewriting the /etc/hosts file ..." 292 | mv /etc/hosts /etc/hosts.old 293 | printf '127.0.0.1\tlocalhost.localdomain\tlocalhost\n127.0.1.1\tubuntu\n'$MYIP'\t'$HOSTNAME'\t'$HOSTONLY'\t' | tee -a /etc/hosts >/dev/null 2>&1 294 | echo -e "${GREEN}... Done.${NC}" 295 | echo "Setting hostname ($HOSTNAME) and timezone ($TIMEZONE) ..." 296 | hostnamectl set-hostname $HOSTNAME >/dev/null 2>&1 297 | timedatectl set-timezone $TIMEZONE >/dev/null 2>&1 298 | echo -e "${GREEN}... Done.${NC}" 299 | apt-get -qq update 300 | 301 | # Get Ubuntu Version 302 | version=$(lsb_release -d | awk -F" " '{print $3}' | cut -c 1-5) 303 | 304 | if [ "$LETSENCRYPT" != "${LETSENCRYPT#[Yy]}" ] ;then # this grammar (the #[] operator) means that the variable $answer where any Y or y in 1st position will be dropped if they exist. 305 | if [ $(dig +short type257 $(hostname --d) | grep "letsencrypt.org" | grep -v "issuewild" | grep "issue" | wc -l) -eq 1 ]; then 306 | echo "Installing certbot" 307 | apt install -y python3 python3-venv libaugeas0 python3-venv 308 | python3 -m venv /opt/certbot/ 309 | /opt/certbot/bin/pip install --upgrade pip 310 | /opt/certbot/bin/pip install certbot 311 | ln -s /opt/certbot/bin/certbot /usr/local/sbin/certbot 312 | /usr/local/sbin/certbot certonly -d $(hostname --fqdn) --standalone --preferred-chain "ISRG Root X2" --agree-tos --register-unsafely-without-email 313 | cat >> /usr/local/sbin/letsencrypt-zimbra << EOF 314 | #!/bin/bash 315 | MAILTO="" 316 | /usr/local/sbin/certbot certonly -d $(hostname --fqdn) --standalone -n --preferred-chain "ISRG Root X2" --agree-tos --register-unsafely-without-email 317 | 318 | cp "/etc/letsencrypt/live/$(hostname --fqdn)/privkey.pem" /opt/zimbra/ssl/zimbra/commercial/commercial.key 319 | chown zimbra:zimbra /opt/zimbra/ssl/zimbra/commercial/commercial.key 320 | wget -O /tmp/ISRG-X2.pem https://letsencrypt.org/certs/isrg-root-x2.pem 321 | rm -f "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 322 | cp "/etc/letsencrypt/live/$(hostname --fqdn)/chain.pem" "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 323 | cat /tmp/ISRG-X2.pem >> "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 324 | chown zimbra:zimbra /etc/letsencrypt -R 325 | cd /tmp 326 | su - zimbra -c '/opt/zimbra/bin/zmcertmgr deploycrt comm "/etc/letsencrypt/live/$(hostname --fqdn)/cert.pem" "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem"' 327 | rm -f "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 328 | EOF 329 | chmod +rx /usr/local/sbin/letsencrypt-zimbra 330 | else 331 | echo "CAA record for your domain cannot be found, you should add it first, example for bind:" 332 | echo "@ CAA 0 issue \"letsencrypt.org\"" 333 | exit 1 334 | fi 335 | fi 336 | 337 | #other updates 338 | DEBIAN_FRONTEND=noninteractive apt install -y locales 339 | locale-gen "en_US.UTF-8" 340 | update-locale LC_ALL="en_US.UTF-8" 341 | 342 | #Preparing the config files to inject 343 | if [ ! -d "/tmp/zcs" ]; then 344 | mkdir /tmp/zcs 345 | else 346 | rm -rf /tmp/zcs/* #Dangerous Command 347 | fi 348 | 349 | #Download binaries 350 | echo "Downloading Zimbra 9.0 for Ubuntu $version ..." 351 | if [[ "$version" == "20.04" ]]; then 352 | wget -P /tmp/ https://files.zimbra.com/downloads/9.0.0_GA/zcs-NETWORK-9.0.0_GA_4178.UBUNTU20_64.20211112031526.tgz > /dev/null 2>&1 353 | elif [[ "$version" == "18.04" ]]; then 354 | wget -P /tmp/ https://files.zimbra.com/downloads/9.0.0_GA/zcs-NETWORK-9.0.0_GA_3924.UBUNTU18_64.20200331010312.tgz > /dev/null 2>&1 355 | fi 356 | echo -e "${GREEN}... Done.${NC}" 357 | 358 | echo "Extracting the files ..." 359 | cd /tmp/zcs && tar xzf /tmp/zcs-NETWORK-9.0.0*.tgz 360 | 361 | echo "Creating the auto-install input files ..." 362 | > /tmp/zcs/zconfig 363 | cat </tmp/zcs/zconfig 364 | AVDOMAIN="$DOMAIN" 365 | AVUSER="admin@$DOMAIN" 366 | CREATEADMIN="admin@$DOMAIN" 367 | CREATEADMINPASS="$MYPASSWORD" 368 | CREATEDOMAIN="$DOMAIN" 369 | DOCREATEADMIN="yes" 370 | DOCREATEDOMAIN="yes" 371 | DOTRAINSA="yes" 372 | ENABLEDEFAULTBACKUP="yes" 373 | EXPANDMENU="no" 374 | HOSTNAME="$HOSTNAME" 375 | HTTPPORT="8080" 376 | HTTPPROXY="TRUE" 377 | HTTPPROXYPORT="80" 378 | HTTPSPORT="8443" 379 | HTTPSPROXYPORT="443" 380 | IMAPPORT="7143" 381 | IMAPPROXYPORT="143" 382 | IMAPSSLPORT="7993" 383 | IMAPSSLPROXYPORT="993" 384 | INSTALL_WEBAPPS="service zimlet zimbra zimbraAdmin" 385 | JAVAHOME="/opt/zimbra/common/lib/jvm/java" 386 | LDAPBESSEARCHSET="set" 387 | LDAPAMAVISPASS="$MYPASSWORD" 388 | LDAPPOSTPASS="$MYPASSWORD" 389 | LDAPROOTPASS="$MYPASSWORD" 390 | LDAPADMINPASS="$MYPASSWORD" 391 | LDAPREPPASS="$MYPASSWORD" 392 | LDAPBESSEARCHSET="set" 393 | LDAPDEFAULTSLOADED="1" 394 | LDAPHOST="$HOSTNAME" 395 | LDAPPORT="389" 396 | LDAPREPLICATIONTYPE="master" 397 | LDAPSERVERID="2" 398 | LICENSEFILE="/tmp/zcs/ZCSLicense.xml" 399 | MAILBOXDMEMORY="1920" 400 | MAILPROXY="TRUE" 401 | MODE="https" 402 | MYSQLMEMORYPERCENT="30" 403 | POPPORT="7110" 404 | POPPROXYPORT="110" 405 | POPSSLPORT="7995" 406 | POPSSLPROXYPORT="995" 407 | PROXYMODE="https" 408 | REMOVE="no" 409 | RUNARCHIVING="no" 410 | RUNAV="yes" 411 | RUNCBPOLICYD="no" 412 | RUNDKIM="yes" 413 | RUNSA="yes" 414 | RUNVMHA="no" 415 | SERVICEWEBAPP="yes" 416 | SMTPDEST="admin@$DOMAIN" 417 | SMTPHOST="$HOSTNAME" 418 | SMTPNOTIFY="yes" 419 | SMTPSOURCE="admin@$DOMAIN" 420 | SNMPNOTIFY="yes" 421 | SNMPTRAPHOST="$HOSTNAME" 422 | SPELLURL="http://$HOSTNAME:7780/aspell.php" 423 | STARTSERVERS="yes" 424 | SYSTEMMEMORY="$SYSTEMMEMORY" 425 | TRAINSAHAM="ham.account@$DOMAIN" 426 | TRAINSASPAM="spam.account@$DOMAIN" 427 | UIWEBAPPS="yes" 428 | UPGRADE="yes" 429 | USEKBSHORTCUTS="TRUE" 430 | USESPELL="yes" 431 | VERSIONUPDATECHECKS="TRUE" 432 | VIRUSQUARANTINE="virus-quarantine.account@$DOMAIN" 433 | ZIMBRA_REQ_SECURITY="yes" 434 | ldap_bes_searcher_password="$MYPASSWORD" 435 | ldap_dit_base_dn_config="cn=zimbra" 436 | ldap_nginx_password="$MYPASSWORD" 437 | mailboxd_directory="/opt/zimbra/mailboxd" 438 | mailboxd_keystore="/opt/zimbra/mailboxd/etc/keystore" 439 | mailboxd_keystore_password="$MYPASSWORD" 440 | mailboxd_server="jetty" 441 | mailboxd_truststore="/opt/zimbra/common/lib/jvm/java/lib/security/cacerts" 442 | mailboxd_truststore_password="changeit" 443 | postfix_mail_owner="postfix" 444 | postfix_setgid_group="postdrop" 445 | ssl_default_digest="sha256" 446 | zimbraDNSMasterIP="8.8.4.4" 447 | zimbraDNSTCPUpstream="no" 448 | zimbraDNSUseTCP="yes" 449 | zimbraDNSUseUDP="yes" 450 | zimbraDefaultDomainName="$DOMAIN" 451 | zimbraFeatureBriefcasesEnabled="Enabled" 452 | zimbraFeatureTasksEnabled="Enabled" 453 | zimbraIPMode="ipv4" 454 | zimbraMailProxy="FALSE" 455 | zimbraMtaMyNetworks="127.0.0.0/8 $MYIP/32 [::1]/128 [fe80::]/64" 456 | zimbraPrefTimeZoneId="$TIMEZONE" 457 | zimbraReverseProxyLookupTarget="TRUE" 458 | zimbraVersionCheckInterval="1d" 459 | zimbraVersionCheckNotificationEmail="admin@$DOMAIN" 460 | zimbraVersionCheckNotificationEmailFrom="admin@$DOMAIN" 461 | zimbraVersionCheckSendNotifications="TRUE" 462 | zimbraWebProxy="TRUE" 463 | zimbra_ldap_userdn="uid=zimbra,cn=admins,cn=zimbra" 464 | zimbra_require_interprocess_security="1" 465 | zimbra_server_hostname="$HOSTNAME" 466 | EOF 467 | 468 | if [[ "$APACHE" == "y" ]]; then 469 | echo 'INSTALL_PACKAGES="zimbra-core zimbra-ldap zimbra-logger zimbra-mta zimbra-snmp zimbra-store zimbra-apache zimbra-spell zimbra-convertd zimbra-memcached zimbra-proxy"' >>/tmp/zcs/zconfig 470 | else 471 | echo 'INSTALL_PACKAGES="zimbra-core zimbra-ldap zimbra-logger zimbra-mta zimbra-store zimbra-memcached zimbra-proxy"' >>/tmp/zcs/zconfig 472 | fi 473 | 474 | > /tmp/zcs/zkeys 475 | if [[ "$APACHE" == "y" ]]; then 476 | cat </tmp/zcs/zkeys 477 | y 478 | y 479 | y 480 | y 481 | y 482 | y 483 | n 484 | y 485 | y 486 | y 487 | y 488 | y 489 | y 490 | y 491 | n 492 | n 493 | n 494 | y 495 | n 496 | y 497 | EOF 498 | else 499 | cat </tmp/zcs/zkeys 500 | y 501 | y 502 | y 503 | y 504 | y 505 | y 506 | n 507 | n 508 | y 509 | n 510 | n 511 | n 512 | y 513 | y 514 | n 515 | n 516 | n 517 | y 518 | n 519 | y 520 | EOF 521 | fi 522 | 523 | D=`date +%s` 524 | echo "Download the trial license ..." 525 | wget -q --no-check-certificate --no-proxy -O /tmp/zcs/ZCSLicense.xml "https://license.zimbra.com/zimbraLicensePortal/public/STLicense?IssuedToName=MyCompany&IssuedToEmail=noone@$DOMAIN" 526 | if [ ! -s "/tmp/zcs/ZCSLicense.xml" ]; then 527 | echo -e "${RED}License file could not be downloaded. Please check and re-run $(basename $0).${NC}" 528 | exit 1 529 | fi 530 | echo -e "${GREEN}... Done.${NC}" 531 | echo "Installing the Zimbra binaries ..." 532 | echo -e "For more details you can open a new terminal and run ${GREEN}tail -f /tmp/install.log.*${NC}." 533 | cd /tmp/zcs/zcs-* && ./install.sh -l /tmp/zcs/ZCSLicense.xml -s < /tmp/zcs/zkeys >> /tmp/zcs/install-$D.log 2>&1 534 | echo -e "${GREEN}... Done.${NC}" 535 | 536 | echo "Setting up your Zimbra configuration, this can take up to 20 minutes or slightly more." 537 | echo -e "For more details you can open a new terminal and run ${GREEN}tail -f /tmp/zmsetup.log${NC}." 538 | /opt/zimbra/libexec/zmsetup.pl -c /tmp/zcs/zconfig >> /tmp/zcs/install-$D.log 2>&1 539 | echo "Allow mailbox service to start ..." 540 | for i in {15..0}; do echo -ne "${RED}$i${NC}\033[0K\r"; sleep 1; done; echo 541 | echo "Activating license ..." 542 | su - zimbra -c "zmlicense -a" 543 | echo -e "${GREEN}... Done.${NC}" 544 | 545 | if [ "$LETSENCRYPT" != "${LETSENCRYPT#[Yy]}" ] ;then # this grammar (the #[] operator) means that the variable $answer where any Y or y in 1st position will be dropped if they exist. 546 | echo "Deploying Let's Encrypt on Zimbra" 547 | ln -s /usr/local/sbin/letsencrypt-zimbra /etc/cron.daily/letsencrypt-zimbra 548 | ip=$(dig +short @8.8.4.4 $(hostname)) # Ensure local IP resolution does not happen 549 | if [ -n "$ip" ]; then 550 | /etc/cron.daily/letsencrypt-zimbra 551 | else 552 | echo -e "${RED}Could not resolve hostname ...${NC}." 553 | echo -e "${RED}Correct your nameserver entries and run the command ${GREEN}/etc/cron.daily/letsencrypt-zimbra${NC}." 554 | fi 555 | fi 556 | 557 | echo "Deploying additional Zimlets" 558 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y zimbra-zimlet-user-sessions-management< /dev/null > /dev/null 559 | 560 | if [[ $(hostname --fqdn) == *"barrydegraaff"* ]] || [[ $(hostname --fqdn) == *"zimbra.tech"* ]]; then 561 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y zimbra-zimlet-sideloader< /dev/null > /dev/null 562 | fi 563 | 564 | echo "Setting optimal security settings" 565 | rm -Rf /tmp/provfile 566 | ZIMBRAIP=$(netstat -tulpn | grep slapd | awk '{print $4}' | awk -F ':' '{print $1}') 567 | 568 | cat >> /tmp/provfile << EOF 569 | mcf zimbraPublicServiceProtocol https 570 | mcf zimbraPublicServicePort 443 571 | mcf zimbraPublicServiceHostname $HOSTNAME 572 | mcf zimbraReverseProxySSLProtocols TLSv1.2 573 | mcf +zimbraReverseProxySSLProtocols TLSv1.3 574 | mcf zimbraReverseProxySSLCiphers "" 575 | mcf +zimbraResponseHeader "Strict-Transport-Security: max-age=31536000; includeSubDomains" 576 | mcf +zimbraResponseHeader "X-Content-Type-Options: nosniff" 577 | mcf +zimbraResponseHeader "X-Robots-Tag: noindex" 578 | mcf +zimbraResponseHeader "Referrer-Policy: no-referrer" 579 | mcf zimbraMailKeepOutWebCrawlers TRUE 580 | mcf zimbraSmtpSendAddMailer FALSE 581 | 582 | mcf zimbraSSLDHParam /etc/ffdhe4096.pem 583 | 584 | mcf zimbraMtaSmtpdTlsCiphers medium 585 | mcf zimbraMtaSmtpdTlsMandatoryCiphers medium 586 | mcf zimbraMtaSmtpdTlsProtocols '>=TLSv1.2' 587 | mcf zimbraMtaTlsSecurityLevel may 588 | 589 | ms $HOSTNAME zimbraPop3CleartextLoginEnabled FALSE 590 | ms $HOSTNAME zimbraImapCleartextLoginEnabled FALSE 591 | 592 | mcf zimbraLastLogonTimestampFrequency 1s 593 | mc default zimbraPrefShortEmailAddress FALSE 594 | mc default zimbraFeatureTwoFactorAuthAvailable TRUE 595 | mc default zimbraFeatureTrustedDevicesEnabled FALSE 596 | 597 | mcf +zimbraMailTrustedIP 127.0.0.1 598 | mcf +zimbraMailTrustedIP $ZIMBRAIP 599 | mcf +zimbraGalLdapAttrMap manager=manager 600 | mcf zimbraBackupReportEmailSender admin@$DOMAIN zimbraBackupReportEmailRecipients admin@$DOMAIN 601 | 602 | ms `zmhostname` zimbraFileUploadMaxSize 80000000 603 | ms `zmhostname` zimbraMailContentMaxSize 80000000 604 | mcf zimbraMtaMaxMessageSize 80000000 605 | mcf zimbraFileUploadMaxSize 80000000 606 | mcf zimbraMailContentMaxSize 80000000 607 | EOF 608 | 609 | sed -i 's/-server -Dhttps.protocols=TLSv1.2 -Djdk.tls.client.protocols=TLSv1.2/-server -Dhttps.protocols=TLSv1.2,TLSv1.3 -Djdk.tls.client.protocols=TLSv1.2,TLSv1.3/g' /opt/zimbra/conf/localconfig.xml 610 | wget https://raw.githubusercontent.com/internetstandards/dhe_groups/master/ffdhe4096.pem -O /etc/ffdhe4096.pem 611 | 612 | su - zimbra -c '/opt/zimbra/bin/postconf -e fast_flush_domains=""' 613 | su - zimbra -c '/opt/zimbra/bin/postconf -e smtpd_etrn_restrictions=reject' 614 | su - zimbra -c '/opt/zimbra/bin/postconf -e disable_vrfy_command=yes' 615 | su - zimbra -c '/opt/zimbra/bin/postconf -e tls_medium_cipherlist=$(/opt/zimbra/common/bin/openssl ciphers)' 616 | su - zimbra -c '/opt/zimbra/bin/postconf -e tls_preempt_cipherlist=no' 617 | 618 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_common_tlsprotocolmin="3.3"' 619 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_common_tlsciphersuite="HIGH"' 620 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_starttls_supported=1' 621 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e zimbra_require_interprocess_security=1' 622 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_starttls_required=true' 623 | 624 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e alias_login_enabled=false' 625 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e zimbra_same_site_cookie="Strict"' 626 | 627 | su - zimbra -c '/opt/zimbra/bin/zmprov < /tmp/provfile' 628 | 629 | #https://wiki.zimbra.com/wiki/Enabling_Admin_Console_Proxy 630 | su - zimbra -c "/opt/zimbra/libexec/zmproxyconfig -e -w -C -H $HOSTNAME" 631 | 632 | # Update Authkeys and Syslog 633 | su - zimbra -c '/opt/zimbra/bin/zmupdateauthkeys' 634 | /opt/zimbra/libexec/zmsyslogsetup 635 | 636 | su - zimbra -c '/opt/zimbra/bin/zmzimletctl undeploy com_zimbra_clientuploader' 637 | rm -Rf /opt/zimbra/lib/ext/com_zimbra_clientuploader 638 | 639 | su - zimbra -c '/opt/zimbra/bin/zmcontrol restart' 640 | 641 | echo 642 | echo 643 | echo "Zimbra installation details:" 644 | echo 645 | echo " - Webmail Login: https://${HOSTNAME}" 646 | echo " - Admin Console: https://${HOSTNAME}:9071" 647 | echo " - Admin Username: admin" 648 | echo " - Admin Password: ${MYPASSWORD}" 649 | echo "" 650 | -------------------------------------------------------------------------------- /zinstaller-10.1: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | UVER=$(lsb_release -d) 4 | if (echo $UVER) | grep -q "Ubuntu 22"; then 5 | echo $UVER is supported 6 | else 7 | echo $UVER is not supported 8 | exit 9 | fi 10 | 11 | # Argbash - see https://argbash.io for more info 12 | die() { 13 | local _ret="${2:-1}" 14 | test "${_PRINT_HELP:-no}" = yes && print_help >&2 15 | echo "$1" >&2 16 | exit "${_ret}" 17 | } 18 | 19 | u=`id -un` 20 | if [ x$u != "xroot" ]; then 21 | echo "Error: must be run as root user" 22 | exit 1 23 | fi 24 | 25 | print_help() { 26 | printf '%s\n' 27 | printf '%s\n' "Install and configure Zimbra 10.1 ..." 28 | printf 'Usage: %s [-l|--license ] [-p|--password ] [-t|--timezone ] [-le|--letsencypt ] [-h|--help] \n' "$(basename $0)" 29 | printf '\t%s\n' ": Domain to install Zimbra for" 30 | printf '\t%s\n' "-l, --license: License file to use (mandatory key required)" 31 | printf '\t%s\n' "-p, --password: Admin password to use (no default)" 32 | printf '\t%s\n' "-n, --hostname: Hostname to use for the server (default: mail)" 33 | printf '\t%s\n' "-t, --timezone: Timezone to set the server to user (optional) (default: 'Singapore')" 34 | printf '\t%s\n' "-e, --letsencypt: Use Let's Encrypt for providing TLS certificates (optional y/n) (default: 'n')" 35 | printf '\t%s\n' "-a, --apache: Add support for spell check and convertd (optional y/n) (default: 'n')" 36 | printf '\t%s\n' "-h, --help: Prints help" 37 | printf '%s\n' 38 | printf '%s\n' "Usage: $(basename $0) [-l license-key] [-p mypassword] [-t 'TimeZone'] [-n Server-Name] [-a n] [-le y] Domain-Name" 39 | printf '%s\n' "Example: $(basename $0) -l xxx-alpha-numeric-xxx -p alRTFGmn1 -n zmail -t 'Europe/London' -a n -le y myorg.co.uk" 40 | exit 1 41 | } 42 | 43 | parse_commandline() { 44 | _positionals_count=0 45 | while test $# -gt 0; do 46 | _key="$1" 47 | case "$_key" in 48 | -l|--license) 49 | test $# -lt 2 && die "Missing value for the mandatory argument '$_key'." 1 50 | _arg_license="$2" 51 | shift 52 | ;; 53 | --license=*) 54 | _arg_license="${_key##--license=}" 55 | ;; 56 | -l*) 57 | _arg_license="${_key##-l}" 58 | ;; 59 | -p|--password) 60 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 61 | _arg_password="$2" 62 | shift 63 | ;; 64 | --password=*) 65 | _arg_password="${_key##--password=}" 66 | ;; 67 | -p*) 68 | _arg_password="${_key##-p}" 69 | ;; 70 | -n|--hostname) 71 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 72 | _arg_hostname="$2" 73 | shift 74 | ;; 75 | --hostname=*) 76 | _arg_hostname="${_key##--hostname=}" 77 | ;; 78 | -n*) 79 | _arg_hostname="${_key##-n}" 80 | ;; 81 | -t|--timezone) 82 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 83 | _arg_timezone="$2" 84 | shift 85 | ;; 86 | --timezone=*) 87 | _arg_timezone="${_key##--timezone=}" 88 | ;; 89 | -t*) 90 | _arg_timezone="${_key##-t}" 91 | ;; 92 | -a|--apache) 93 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 94 | _arg_apache="$2" 95 | shift 96 | ;; 97 | --apache=*) 98 | _arg_apache="${_key##--apache=}" 99 | ;; 100 | -a*) 101 | _arg_apache="${_key##-a}" 102 | ;; 103 | -e|--letsencrypt) 104 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 105 | _arg_letsencrypt="$2" 106 | shift 107 | ;; 108 | --letsencrypt=*) 109 | _arg_letsencrypt="${_key##--letsencrypt=}" 110 | ;; 111 | -e*) 112 | _arg_letsencrypt="${_key##-e=}" 113 | ;; 114 | -h|--help) 115 | print_help 116 | exit 0 117 | ;; 118 | -h*) 119 | print_help 120 | exit 0 121 | ;; 122 | *) 123 | _last_positional="$1" 124 | _positionals+=("$_last_positional") 125 | _positionals_count=$((_positionals_count + 1)) 126 | ;; 127 | esac 128 | shift 129 | done 130 | } 131 | 132 | handle_passed_args_count() { 133 | local _required_args_string="'domain'" 134 | test "${_positionals_count}" -ge 1 || _PRINT_HELP=yes die "FATAL ERROR: Not enough positional arguments - we require exactly 1 (namely: $_required_args_string), but got only ${_positionals_count}." 1 135 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect exactly 1 (namely: $_required_args_string), but got ${_positionals_count} (the last one was: '${_last_positional}')." 1 136 | } 137 | 138 | assign_positional_args() { 139 | local _positional_name _shift_for=$1 140 | _positional_names="_arg_domain" 141 | 142 | shift "$_shift_for" 143 | for _positional_name in ${_positional_names} 144 | do 145 | test $# -gt 0 || break 146 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1 147 | shift 148 | done 149 | } 150 | 151 | parse_commandline "$@" 152 | handle_passed_args_count 153 | assign_positional_args 1 "${_positionals[@]}" 154 | 155 | if [ -z "$_arg_license" ] 156 | then 157 | printf '%s\n' "License Key is missing ... Please check and re-run $(basename $0).\n" 158 | print_help 159 | fi 160 | 161 | MYIP=$(hostname -I | cut -f1 -d" " | tr -d '[:space:]') 162 | LICENSE="$_arg_license" 163 | DOMAIN="$_arg_domain" 164 | HOSTONLY="${_arg_hostname:="mail"}" 165 | HOSTNAME="${_arg_hostname:-"mail"}"."$DOMAIN" 166 | TIMEZONE="${_arg_timezone:-"Asia/Kolkata"}" 167 | LETSENCRYPT="${_arg_letsencrypt:-"n"}" 168 | APACHE="${_arg_apache:-"n"}" 169 | MYPASSWORD="${_arg_password:-$(openssl rand -base64 9)}" 170 | GREEN='\033[0;32m' 171 | RED='\033[0;31m' 172 | NC='\033[0m' # No Color 173 | SYSTEMMEMORY=$(($(grep MemAvailable /proc/meminfo | awk '{print $2}')/1024/1024)) 174 | 175 | # Only-Office repo is added by the installer 176 | #rm -f /etc/apt/sources.list.d/zimbra-onlyoffice.list 177 | #cat > /etc/apt/sources.list.d/zimbra-onlyoffice.list << EOF 178 | #deb [arch=amd64] https://repo.zimbra.com/apt/onlyoffice-1010 focal zimbra 179 | #EOF 180 | 181 | echo "Updating system and installing some essential packages ..." 182 | #What are the other essential packages? 183 | DEBIAN_FRONTEND=noninteractive apt-get update -qq -y < /dev/null > /dev/null 184 | DEBIAN_FRONTEND=noninteractive apt-get upgrade -qq -y < /dev/null > /dev/null 185 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y apt-utils< /dev/null > /dev/null 186 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y netcat-openbsd sudo libidn11 libpcre3 libgmp10 libexpat1 libstdc++6 libperl5.30 libaio1 resolvconf unzip pax sysstat sqlite3< /dev/null > /dev/null 187 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y dnsmasq lsb-release net-tools netfilter-persistent dnsutils iptables sed wget rsyslog ldapscripts< /dev/null > /dev/null 188 | 189 | #Make sure to enable PAM 190 | cat /etc/ssh/sshd_config | grep -v -i usepam > /tmp/sshd_config 191 | echo "UsePAM yes" >>/tmp/sshd_config 192 | mv /tmp/sshd_config /etc/ssh/sshd_config 193 | systemctl restart sshd 194 | 195 | echo "Disabling some of the non-essential services for Zimbra ..." 196 | systemctl stop postfix 197 | systemctl disable postfix 198 | systemctl mask postfix 199 | 200 | systemctl stop iptables 201 | systemctl disable iptables 202 | systemctl mask iptables 203 | 204 | systemctl stop httpd 205 | systemctl disable httpd 206 | systemctl mask httpd 207 | 208 | systemctl stop exim 209 | systemctl disable exim 210 | systemctl mask exim 211 | 212 | systemctl stop named 213 | systemctl disable named 214 | systemctl mask named 215 | 216 | systemctl stop apache2 217 | systemctl disable apache2 218 | systemctl mask apache2 219 | 220 | systemctl stop sendmail 221 | systemctl disable sendmail 222 | systemctl mask sendmail 223 | 224 | systemctl stop mysqld 225 | systemctl disable mysqld 226 | systemctl mask mysqld 227 | 228 | systemctl stop mariadb 229 | systemctl disable mariadb 230 | systemctl mask mariadb 231 | 232 | systemctl stop systemd-resolved 233 | systemctl disable systemd-resolved 234 | systemctl mask systemd-resolved 235 | 236 | systemctl stop ufw 237 | systemctl disable ufw 238 | systemctl mask ufw 239 | 240 | systemctl enable rsyslog 241 | systemctl restart rsyslog 242 | 243 | #Install a DNS Server 244 | echo "Configuring dnsmasq ..." 245 | mv /etc/dnsmasq.conf /etc/dnsmasq.conf.old 246 | #create the conf file 247 | printf 'server=8.8.8.8\nserver=8.8.4.4\nserver=9.9.9.9\nserver=149.112.112.112\nserver=1.1.1.1\nserver=1.0.0.1\nlisten-address=127.0.0.1\ndomain='$DOMAIN'\nmx-host='$DOMAIN','$HOSTNAME',0\naddress=/'$HOSTNAME'/'$MYIP'\n' | tee -a /etc/dnsmasq.conf >/dev/null 248 | mv /etc/resolv.conf {,.old} 249 | echo "nameserver 127.0.0.1" > /etc/resolv.conf 250 | # restart dns services 251 | systemctl enable dnsmasq.service > /dev/null 2>&1 && systemctl restart dnsmasq.service 252 | echo -e "${GREEN}... Done.${NC}" 253 | 254 | # Check DNS 255 | echo "Checking DNS ..." 256 | name=`host license.zimbra.com` 257 | if [[ "$name" == *"not found"* ]]; then 258 | echo -e "${RED}DNS resolution failed! Check your resolve.conf file.${NC}" 259 | exit 1 260 | else 261 | echo -e "${GREEN}... Done.${NC}" 262 | fi 263 | 264 | # Update firewall 265 | echo "Enabling firewall for Zimbra ports ..." 266 | echo "Ports 22/25/143/80/443/465/587/995/993/9071 will be opened to the internet." 267 | echo "Please check your iptables for more info." 268 | 269 | #flushing iptables while having INPUT=DROP policy will terminate ssh connection 270 | iptables -P INPUT ACCEPT 271 | 272 | iptables --flush 273 | #block null packets 274 | iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP 275 | #block syn flood 276 | iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP 277 | #block XMAS packets 278 | iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP 279 | 280 | #accept all traffic on your loopback interface 281 | iptables -A INPUT -i lo -j ACCEPT 282 | iptables -A OUTPUT -o lo -j ACCEPT 283 | 284 | #Allow Established and Related Incoming Connections 285 | iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 286 | 287 | #Allow ports 288 | iptables -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT 289 | iptables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT 290 | iptables -A INPUT -p tcp -m tcp --dport 995 -j ACCEPT 291 | iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT 292 | iptables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT 293 | iptables -A INPUT -p tcp -m tcp --dport 587 -j ACCEPT 294 | iptables -A INPUT -p tcp -m tcp --dport 9071 -j ACCEPT 295 | iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT 296 | iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT 297 | iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT 298 | 299 | #enable ping 300 | iptables -A INPUT -p icmp --icmp-type 8 -s 0/0 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT 301 | iptables -A OUTPUT -p icmp --icmp-type 0 -d 0/0 -m state --state ESTABLISHED,RELATED -j ACCEPT 302 | 303 | #Set policy defaults 304 | iptables -P OUTPUT ACCEPT 305 | iptables -P FORWARD ACCEPT 306 | iptables -P INPUT DROP 307 | 308 | #IPv6 closed for now 309 | /usr/sbin/ip6tables -P OUTPUT ACCEPT 310 | /usr/sbin/ip6tables -P FORWARD ACCEPT 311 | /usr/sbin/ip6tables -P INPUT DROP 312 | 313 | netfilter-persistent save 314 | 315 | #Check Firewall 316 | response=$(curl --write-out '%{http_code}' --silent --output /dev/null https://license.zimbra.com/actuator/health) 317 | if [[ "$response" == "200" ]]; then 318 | echo "Zimbra License server reachable ..." 319 | echo -e "${GREEN}... Done.${NC}" 320 | else 321 | echo -e "${RED} Issue with firewall ... Please check!${NC}" 322 | exit 1 323 | fi 324 | 325 | # Reset the hosts file 326 | echo "Rewriting the /etc/hosts file ..." 327 | mv /etc/hosts /etc/hosts.old 328 | printf '127.0.0.1\tlocalhost.localdomain\tlocalhost\n127.0.1.1\tubuntu\n'$MYIP'\t'$HOSTNAME'\t'$HOSTONLY'\t' | tee -a /etc/hosts >/dev/null 2>&1 329 | echo -e "${GREEN}... Done.${NC}" 330 | echo "Setting hostname ($HOSTNAME) and timezone ($TIMEZONE) ..." 331 | hostnamectl set-hostname $HOSTNAME >/dev/null 2>&1 332 | timedatectl set-timezone $TIMEZONE >/dev/null 2>&1 333 | echo -e "${GREEN}... Done.${NC}" 334 | apt-get -qq update < /dev/null > /dev/null 335 | 336 | #other updates 337 | echo "Updating locale ..." 338 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y locales < /dev/null > /dev/null 339 | locale-gen "en_US.UTF-8" > /dev/null 340 | update-locale LC_ALL="en_US.UTF-8" 341 | 342 | # Get Ubuntu Version 343 | version=$(lsb_release -d | awk -F" " '{print $3}' | cut -c 1-5) 344 | 345 | if [ "$LETSENCRYPT" != "${LETSENCRYPT#[Yy]}" ] ;then # this grammar (the #[] operator) means that the variable $answer where any Y or y in 1st position will be dropped if they exist. 346 | if [ $(dig +short type257 $(hostname --d) | grep "letsencrypt.org" | grep "issue" | wc -l) -ge 1 ]; then 347 | echo "Installing certbot" 348 | apt-get install -y -qq python3 python3-venv libaugeas0 python3-venv > /dev/null 349 | python3 -m venv /opt/certbot/ 350 | /opt/certbot/bin/pip install --upgrade pip 351 | /opt/certbot/bin/pip install certbot 352 | ln -s /opt/certbot/bin/certbot /usr/local/sbin/certbot 353 | /usr/local/sbin/certbot certonly -d $(hostname --fqdn) --standalone --preferred-chain "ISRG Root X2" --agree-tos --register-unsafely-without-email 354 | cat >> /usr/local/sbin/letsencrypt-zimbra << EOF 355 | #!/bin/bash 356 | MAILTO="" 357 | /usr/local/sbin/certbot certonly -d $(hostname --fqdn) --standalone -n --preferred-chain "ISRG Root X2" --agree-tos --register-unsafely-without-email 358 | 359 | cp "/etc/letsencrypt/live/$(hostname --fqdn)/privkey.pem" /opt/zimbra/ssl/zimbra/commercial/commercial.key 360 | chown zimbra:zimbra /opt/zimbra/ssl/zimbra/commercial/commercial.key 361 | wget -O /tmp/ISRG-X2.pem https://letsencrypt.org/certs/isrg-root-x2.pem 362 | rm -f "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 363 | cp "/etc/letsencrypt/live/$(hostname --fqdn)/chain.pem" "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 364 | cat /tmp/ISRG-X2.pem >> "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 365 | chown zimbra:zimbra /etc/letsencrypt -R 366 | cd /tmp 367 | su - zimbra -c '/opt/zimbra/bin/zmcertmgr deploycrt comm "/etc/letsencrypt/live/$(hostname --fqdn)/cert.pem" "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem"' 368 | rm -f "/etc/letsencrypt/live/$(hostname --fqdn)/chainZimbra.pem" 369 | EOF 370 | chmod +rx /usr/local/sbin/letsencrypt-zimbra 371 | else 372 | echo "CAA record for your domain cannot be found, you should add it first, example for bind:" 373 | echo "@ CAA 0 issue \"letsencrypt.org\"" 374 | exit 1 375 | fi 376 | fi 377 | 378 | #Preparing the config files to inject 379 | if [ ! -d "/tmp/zcs" ]; then 380 | mkdir /tmp/zcs 381 | else 382 | rm -rf /tmp/zcs/* #Dangerous Command 383 | fi 384 | 385 | #Download binaries 386 | echo "Downloading Zimbra 10 for Ubuntu $version ..." 387 | wget -P /tmp/ https://files.zimbra.com/downloads/10.1.0_GA/zcs-NETWORK-10.1.0_GA_4655.UBUNTU22_64.20240819064312.tgz > /dev/null 2>&1 388 | 389 | echo "Extracting the files ..." 390 | cd /tmp/zcs && tar xzf /tmp/zcs-NETWORK-10.1.0_GA_4655.UBUNTU22_64.20240819064312.tgz 391 | 392 | echo "Creating the auto-install input files ..." 393 | > /tmp/zcs/zconfig 394 | cat </tmp/zcs/zconfig 395 | AVDOMAIN="$DOMAIN" 396 | AVUSER="super-admin@$DOMAIN" 397 | CREATEADMIN="super-admin@$DOMAIN" 398 | CREATEADMINPASS="$MYPASSWORD" 399 | CREATEDOMAIN="$DOMAIN" 400 | DOCREATEADMIN="yes" 401 | DOCREATEDOMAIN="yes" 402 | DOTRAINSA="yes" 403 | ENABLEDEFAULTBACKUP="yes" 404 | EXPANDMENU="no" 405 | HOSTNAME="$HOSTNAME" 406 | HTTPPORT="8080" 407 | HTTPPROXY="TRUE" 408 | HTTPPROXYPORT="80" 409 | HTTPSPORT="8443" 410 | HTTPSPROXYPORT="443" 411 | IMAPPORT="7143" 412 | IMAPPROXYPORT="143" 413 | IMAPSSLPORT="7993" 414 | IMAPSSLPROXYPORT="993" 415 | INSTALL_WEBAPPS="service zimlet zimbra zimbraAdmin" 416 | JAVAHOME="/opt/zimbra/common/lib/jvm/java" 417 | LDAPBESSEARCHSET="set" 418 | LDAPAMAVISPASS="$MYPASSWORD" 419 | LDAPPOSTPASS="$MYPASSWORD" 420 | LDAPROOTPASS="$MYPASSWORD" 421 | LDAPADMINPASS="$MYPASSWORD" 422 | LDAPREPPASS="$MYPASSWORD" 423 | LDAPBESSEARCHSET="set" 424 | LDAPDEFAULTSLOADED="1" 425 | LDAPHOST="$HOSTNAME" 426 | LDAPPORT="389" 427 | LDAPREPLICATIONTYPE="master" 428 | LDAPSERVERID="2" 429 | LICENSEACTIVATIONOPTION="1" 430 | LICENSEACTIVATIONOPTIONMSG="Activate license after installation" 431 | LICENSEKEY="$LICENSE" 432 | MAILBOXDMEMORY="1920" 433 | MAILPROXY="TRUE" 434 | MODE="https" 435 | MYSQLMEMORYPERCENT="30" 436 | ONLYOFFICEHOSTNAME="$HOSTNAME" 437 | ONLYOFFICESTANDALONE="no" 438 | POPPORT="7110" 439 | POPPROXYPORT="110" 440 | POPSSLPORT="7995" 441 | POPSSLPROXYPORT="995" 442 | PROXYMODE="https" 443 | REMOVE="no" 444 | RUNARCHIVING="no" 445 | RUNAV="yes" 446 | RUNCBPOLICYD="no" 447 | RUNDKIM="yes" 448 | RUNSA="yes" 449 | RUNVMHA="no" 450 | SERVICEWEBAPP="yes" 451 | SMTPDEST="super-admin@$DOMAIN" 452 | SMTPHOST="$HOSTNAME" 453 | SMTPNOTIFY="yes" 454 | SMTPSOURCE="super-admin@$DOMAIN" 455 | SNMPNOTIFY="yes" 456 | SNMPTRAPHOST="$HOSTNAME" 457 | SPELLURL="http://$HOSTNAME:7780/aspell.php" 458 | STARTSERVERS="yes" 459 | STRICTSERVERNAMEENABLED="TRUE" 460 | SYSTEMMEMORY="$SYSTEMMEMORY" 461 | TRAINSAHAM="ham.account@$DOMAIN" 462 | TRAINSASPAM="spam.account@$DOMAIN" 463 | UIWEBAPPS="yes" 464 | UPGRADE="yes" 465 | USEKBSHORTCUTS="TRUE" 466 | USESPELL="yes" 467 | VERSIONUPDATECHECKS="TRUE" 468 | VIRUSQUARANTINE="virus-quarantine.account@$DOMAIN" 469 | ZIMBRA_REQ_SECURITY="yes" 470 | ldap_bes_searcher_password="$MYPASSWORD" 471 | ldap_dit_base_dn_config="cn=zimbra" 472 | ldap_nginx_password="$MYPASSWORD" 473 | mailboxd_directory="/opt/zimbra/mailboxd" 474 | mailboxd_keystore="/opt/zimbra/mailboxd/etc/keystore" 475 | mailboxd_keystore_password="$MYPASSWORD" 476 | mailboxd_server="jetty" 477 | mailboxd_truststore="/opt/zimbra/common/lib/jvm/java/lib/security/cacerts" 478 | mailboxd_truststore_password="changeit" 479 | postfix_mail_owner="postfix" 480 | postfix_setgid_group="postdrop" 481 | ssl_default_digest="sha256" 482 | zimbraDNSMasterIP="8.8.4.4" 483 | zimbraDNSTCPUpstream="no" 484 | zimbraDNSUseTCP="yes" 485 | zimbraDNSUseUDP="yes" 486 | zimbraDefaultDomainName="$DOMAIN" 487 | zimbraFeatureBriefcasesEnabled="Enabled" 488 | zimbraFeatureTasksEnabled="Enabled" 489 | zimbraIPMode="ipv4" 490 | zimbraMailProxy="FALSE" 491 | zimbraMtaMyNetworks="127.0.0.0/8 $MYIP/32 [::1]/128 [fe80::]/64" 492 | zimbraPrefTimeZoneId="$TIMEZONE" 493 | zimbraReverseProxyLookupTarget="TRUE" 494 | zimbraVersionCheckInterval="1d" 495 | zimbraVersionCheckNotificationEmail="super-admin@$DOMAIN" 496 | zimbraVersionCheckNotificationEmailFrom="super-admin@$DOMAIN" 497 | zimbraVersionCheckSendNotifications="TRUE" 498 | zimbraWebProxy="TRUE" 499 | zimbra_ldap_userdn="uid=zimbra,cn=admins,cn=zimbra" 500 | zimbra_require_interprocess_security="1" 501 | zimbra_server_hostname="$HOSTNAME" 502 | EOF 503 | 504 | if [[ "$APACHE" == "y" ]]; then 505 | echo 'INSTALL_PACKAGES="zimbra-core zimbra-ldap zimbra-logger zimbra-mta zimbra-store zimbra-apache zimbra-spell zimbra-convertd zimbra-memcached zimbra-proxy zimbra-archiving zimbra-onlyoffice zimbra-license-daemon"' >>/tmp/zcs/zconfig 506 | else 507 | echo 'INSTALL_PACKAGES="zimbra-core zimbra-ldap zimbra-logger zimbra-mta zimbra-store zimbra-convertd zimbra-memcached zimbra-proxy zimbra-archiving zimbra-onlyoffice zimbra-license-daemon"' >>/tmp/zcs/zconfig 508 | fi 509 | 510 | > /tmp/zcs/zkeys 511 | cat </tmp/zcs/zkeys 512 | y 513 | y 514 | y 515 | y 516 | y 517 | n 518 | n 519 | y 520 | y 521 | $APACHE 522 | $APACHE 523 | y 524 | y 525 | y 526 | y 527 | y 528 | y 529 | EOF 530 | 531 | D=`date +%s` 532 | echo -e "${GREEN}... Done.${NC}" 533 | echo "Installing the Zimbra binaries ..." 534 | echo -e "For more details you can open a new terminal and run ${GREEN}tail -f /tmp/install.log.*${NC}" 535 | cd /tmp/zcs/zcs-* && ./install.sh -l $LICENSE -s < /tmp/zcs/zkeys >> /tmp/zcs/install-$D.log 2>&1 536 | echo -e "${GREEN}... Done.${NC}" 537 | 538 | echo "Setting up your Zimbra configuration, this can take up to 20 minutes or slightly more." 539 | echo -e "For more details you can open a new terminal and run ${GREEN}tail -f /tmp/zmsetup.log${NC}." 540 | /opt/zimbra/libexec/zmsetup.pl -c /tmp/zcs/zconfig >> /tmp/zcs/install-$D.log 2>&1 541 | echo "Allow mailbox service to start ..." 542 | for i in {15..0}; do echo -ne "${RED}$i${NC}\033[0K\r"; sleep 1; done; echo 543 | echo "Activating license ..." 544 | su - zimbra -c "zmlicense -a $LICENSE" 545 | echo -e "${GREEN}... Done.${NC}" 546 | 547 | if [ "$LETSENCRYPT" != "${LETSENCRYPT#[Yy]}" ] ;then # this grammar (the #[] operator) means that the variable $answer where any Y or y in 1st position will be dropped if they exist. 548 | echo "Deploying Let's Encrypt on Zimbra" 549 | ln -s /usr/local/sbin/letsencrypt-zimbra /etc/cron.daily/letsencrypt-zimbra 550 | ip=$(dig +short @8.8.4.4 $(hostname)) # Ensure local IP resolution does not happen 551 | if [ -n "$ip" ]; then 552 | /etc/cron.daily/letsencrypt-zimbra 553 | else 554 | echo -e "${RED}Could not resolve hostname ...${NC}." 555 | echo -e "${RED}Correct your nameserver entries and run the command ${GREEN}/etc/cron.daily/letsencrypt-zimbra${NC}." 556 | fi 557 | fi 558 | 559 | echo "Deploying additional Zimlets" 560 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y zimbra-zimlet-user-sessions-management zimbra-zimlet-slack zimbra-zimlet-zoom zimbra-zimlet-dropbox zimbra-zimlet-google-drive zimbra-zimlet-onedrive zimbra-zimlet-jitsi zimbra-zimlet-video-call-preferences zimbra-zimlet-nextcloud zimbra-zimlet-voice-message zimbra-zimlet-sideloader zimbra-zimlet-org-chart zimbra-zimlet-privacy-protector zimbra-zimlet-custom-fonts zimbra-zimlet-download-email zimbra-zimlet-import-export-ics < /dev/null > /dev/null 561 | 562 | if [[ $(hostname --fqdn) == *"barrydegraaff"* ]] || [[ $(hostname --fqdn) == *"zimbra.tech"* ]]; then 563 | DEBIAN_FRONTEND=noninteractive apt-get install -qq -y zimbra-zimlet-sideloader< /dev/null > /dev/null 564 | fi 565 | 566 | echo "Setting optimal security settings" 567 | rm -Rf /tmp/provfile 568 | 569 | cat >> /tmp/provfile << EOF 570 | mcf zimbraPublicServiceProtocol https 571 | mcf zimbraPublicServicePort 443 572 | mcf zimbraPublicServiceHostname $HOSTNAME 573 | mcf zimbraReverseProxySSLProtocols TLSv1.2 574 | mcf +zimbraReverseProxySSLProtocols TLSv1.3 575 | mcf zimbraReverseProxySSLCiphers "" 576 | mcf +zimbraResponseHeader "Strict-Transport-Security: max-age=31536000; includeSubDomains" 577 | mcf +zimbraResponseHeader "X-Content-Type-Options: nosniff" 578 | mcf +zimbraResponseHeader "X-Robots-Tag: noindex" 579 | mcf +zimbraResponseHeader "Referrer-Policy: no-referrer" 580 | mcf zimbraMailKeepOutWebCrawlers TRUE 581 | mcf zimbraSmtpSendAddMailer FALSE 582 | 583 | mcf zimbraSSLDHParam /etc/ffdhe4096.pem 584 | 585 | mcf zimbraMtaSmtpdTlsCiphers medium 586 | mcf zimbraMtaSmtpdTlsMandatoryCiphers medium 587 | mcf zimbraMtaSmtpdTlsProtocols '>=TLSv1.2' 588 | mcf zimbraMtaTlsSecurityLevel may 589 | 590 | ms $HOSTNAME zimbraPop3CleartextLoginEnabled FALSE 591 | ms $HOSTNAME zimbraImapCleartextLoginEnabled FALSE 592 | 593 | mcf zimbraLastLogonTimestampFrequency 1s 594 | mc default zimbraPrefShortEmailAddress FALSE 595 | mc default zimbraFeatureTwoFactorAuthAvailable TRUE 596 | mc default zimbraFeatureTrustedDevicesEnabled FALSE 597 | 598 | mcf +zimbraMailTrustedIP 127.0.0.1 599 | mcf +zimbraMailTrustedIP $MYIP 600 | mcf +zimbraGalLdapAttrMap manager=manager 601 | mcf zimbraBackupReportEmailSender super-admin@$DOMAIN zimbraBackupReportEmailRecipients super-admin@$DOMAIN 602 | 603 | ms $HOSTNAME zimbraFileUploadMaxSize 80000000 604 | ms $HOSTNAME zimbraMailContentMaxSize 80000000 605 | mcf zimbraMtaMaxMessageSize 80000000 606 | mcf zimbraFileUploadMaxSize 80000000 607 | mcf zimbraMailContentMaxSize 80000000 608 | EOF 609 | 610 | su - zimbra -c '/opt/zimbra/bin/postconf -e fast_flush_domains=""' 611 | su - zimbra -c '/opt/zimbra/bin/postconf -e smtpd_etrn_restrictions=reject' 612 | su - zimbra -c '/opt/zimbra/bin/postconf -e disable_vrfy_command=yes' 613 | su - zimbra -c '/opt/zimbra/bin/postconf -e tls_medium_cipherlist=$(/opt/zimbra/common/bin/openssl ciphers)' 614 | su - zimbra -c '/opt/zimbra/bin/postconf -e tls_preempt_cipherlist=no' 615 | 616 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_common_tlsprotocolmin="3.3"' 617 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_common_tlsciphersuite="HIGH"' 618 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_starttls_supported=1' 619 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e zimbra_require_interprocess_security=1' 620 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e ldap_starttls_required=true' 621 | 622 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e alias_login_enabled=false' 623 | su - zimbra -c '/opt/zimbra/bin/zmlocalconfig -e zimbra_same_site_cookie="Strict"' 624 | 625 | su - zimbra -c '/opt/zimbra/bin/zmprov < /tmp/provfile' 626 | 627 | #https://wiki.zimbra.com/wiki/Enabling_Admin_Console_Proxy 628 | su - zimbra -c "/opt/zimbra/libexec/zmproxyconfig -e -w -C -H $HOSTNAME" 629 | 630 | # Update Authkeys and Syslog 631 | su - zimbra -c '/opt/zimbra/bin/zmupdateauthkeys' 632 | /opt/zimbra/libexec/zmsyslogsetup 633 | 634 | su - zimbra -c '/opt/zimbra/bin/zmzimletctl undeploy com_zimbra_clientuploader' 635 | rm -Rf /opt/zimbra/lib/ext/com_zimbra_clientuploader 636 | 637 | su - zimbra -c '/opt/zimbra/bin/zmcontrol restart' 638 | 639 | echo 640 | echo -e "${GREEN}Login to the admin console and activate your license before trying any other feature!${NC}" 641 | echo "Zimbra installation details:" 642 | echo 643 | echo " - Webmail Login: https://${HOSTNAME}" 644 | echo " - Admin Console: https://${HOSTNAME}:9071" 645 | echo " - Admin Username: super-admin" 646 | echo " - Admin Password: ${MYPASSWORD}" 647 | echo "" 648 | --------------------------------------------------------------------------------