diff --git a/CHANGELOG.md b/CHANGELOG.md index 089aa68d..6688e676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,49 @@ CHANGELOG ========= +v0.43 (September 1, 2019) +------------------------- + +Security fixes: + +* A security issue was discovered in rsync backups. If you have enabled rsync backups, the file `id_rsa_miab` may have been copied to your backup destination. This file can be used to access your backup destination. If the file was copied to your backup destination, we recommend that you delete the file on your backup destination, delete `/root/.ssh/id_rsa_miab` on your Mail-in-a-Box, then re-run Mail-in-a-Box setup, and re-configure your SSH public key at your backup destination according to the instructions in the Mail-in-a-Box control panel. +* Brute force attack prevention was missing for the managesieve service. + +Setup: + +* Nextcloud was not upgraded properly after restoring Mail-in-a-Box from a backup from v0.40 or earlier. + +Mail: + +* Upgraded Roundcube to 1.3.10. +* Fetch an updated whitelist for greylisting on a monthly basis to reduce the number of delayed incoming emails. + +Control panel: + +* When using secondary DNS, it is now possible to specify a subnet range with the `xfr:` option. +* Fixed an issue when the secondary DNS option is used and the secondary DNS hostname resolves to multiple IP addresses. +* Fix a bug in how a backup configuration error is shown. + +v0.42b (August 3, 2019) +----------------------- + +Changes: + +* Decreased the minimum supported RAM to 502 Mb. +* Improved mail client autoconfiguration. +* Added support for S3-compatible backup services besides Amazon S3. +* Fixed the control panel login page to let LastPass save passwords. +* Fixed an error in the user privileges API. +* Silenced some spurrious messages. + +Software updates: + +* Upgraded Roundcube from 1.3.8 to 1.3.9. +* Upgraded Nextcloud from 14.0.6 to 15.0.8 (with Contacts from 2.1.8 to 3.1.1 and Calendar from 1.6.4 to 1.6.5). +* Upgraded Z-Push from 2.4.4 to 2.5.0. + +Note that v0.42 (July 4, 2019) was pulled shortly after it was released to fix a Nextcloud upgrade issue. + v0.41 (February 26, 2019) ------------------------- diff --git a/README.md b/README.md index df90886e..fbe25549 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ by him: $ curl -s https://keybase.io/joshdata/key.asc | gpg --import gpg: key C10BDD81: public key "Joshua Tauberer " imported - $ git verify-tag v0.41 + $ git verify-tag v0.43 gpg: Signature made ..... using RSA key ID C10BDD81 gpg: Good signature from "Joshua Tauberer " gpg: WARNING: This key is not certified with a trusted signature! @@ -211,7 +211,7 @@ and on his [personal homepage](https://razor.occams.info/). (Of course, if this Checkout the tag corresponding to the most recent release: - $ git checkout v0.41 + $ git checkout v0.43 Begin the installation. diff --git a/conf/fail2ban/filter.d/dovecotimap.conf b/conf/fail2ban/filter.d/dovecotimap.conf index 64b8d944..40fa87a4 100644 --- a/conf/fail2ban/filter.d/dovecotimap.conf +++ b/conf/fail2ban/filter.d/dovecotimap.conf @@ -1,4 +1,4 @@ -# Fail2Ban filter Dovecot authentication and pop3/imap server +# Fail2Ban filter Dovecot authentication and pop3/imap/managesieve server # For Mail-in-a-Box [INCLUDES] @@ -9,7 +9,7 @@ before = common.conf _daemon = (auth|dovecot(-auth)?|auth-worker) -failregex = ^%(__prefix_line)s(pop3|imap)-login: (Info: )?(Aborted login|Disconnected)(: Inactivity)? \(((no auth attempts|auth failed, \d+ attempts)( in \d+ secs)?|tried to use (disabled|disallowed) \S+ auth)\):( user=<\S*>,)?( method=\S+,)? rip=, lip=(\d{1,3}\.){3}\d{1,3}(, TLS( handshaking)?(: Disconnected)?)?(, session=<\S+>)?\s*$ +failregex = ^%(__prefix_line)s(pop3|imap|managesieve)-login: (Info: )?(Aborted login|Disconnected)(: Inactivity)? \(((no auth attempts|auth failed, \d+ attempts)( in \d+ secs)?|tried to use (disabled|disallowed) \S+ auth)\):( user=<\S*>,)?( method=\S+,)? rip=, lip=(\d{1,3}\.){3}\d{1,3}(, TLS( handshaking)?(: Disconnected)?)?(, session=<\S+>)?\s*$ ignoreregex = diff --git a/conf/nginx-alldomains.conf b/conf/nginx-alldomains.conf index 1db7606c..1b3ad5a9 100644 --- a/conf/nginx-alldomains.conf +++ b/conf/nginx-alldomains.conf @@ -18,6 +18,9 @@ location = /.well-known/autoconfig/mail/config-v1.1.xml { alias /var/lib/mailinabox/mozilla-autoconfig.xml; } + location = /mail/config-v1.1.xml { + alias /var/lib/mailinabox/mozilla-autoconfig.xml; + } # Roundcube Webmail configuration. rewrite ^/mail$ /mail/ redirect; diff --git a/conf/nginx-primaryonly.conf b/conf/nginx-primaryonly.conf index d8d912ca..288fce40 100644 --- a/conf/nginx-primaryonly.conf +++ b/conf/nginx-primaryonly.conf @@ -19,6 +19,7 @@ rewrite ^/cloud/$ /cloud/index.php; rewrite ^/cloud/(contacts|calendar|files)$ /cloud/index.php/apps/$1/ redirect; rewrite ^(/cloud/core/doc/[^\/]+/)$ $1/index.html; + rewrite ^(/cloud/oc[sm]-provider)/$ $1/index.php redirect; location /cloud/ { alias /usr/local/lib/owncloud/; location ~ ^/cloud/(build|tests|config|lib|3rdparty|templates|data|README)/ { @@ -27,6 +28,14 @@ location ~ ^/cloud/(?:\.|autotest|occ|issue|indie|db_|console) { deny all; } + # Enable paths for service and cloud federation discovery + # Resolves warning in Nextcloud Settings panel + location ~ ^/cloud/(oc[sm]-provider)?/([^/]+\.php)$ { + index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME /usr/local/lib/owncloud/$1/$2; + fastcgi_pass php-fpm; + } } location ~ ^(/cloud)((?:/ocs)?/[^/]+\.php)(/.*)?$ { # note: ~ has precendence over a regular location block diff --git a/management/backup.py b/management/backup.py index e15fbbbf..11cdbb8a 100755 --- a/management/backup.py +++ b/management/backup.py @@ -15,8 +15,8 @@ from exclusiveprocess import Lock from utils import load_environment, shell, wait_for_service, fix_boto rsync_ssh_options = [ - "--ssh-options='-i /root/.ssh/id_rsa_miab'", - "--rsync-options=-e \"/usr/bin/ssh -oStrictHostKeyChecking=no -oBatchMode=yes -p 22 -i /root/.ssh/id_rsa_miab\"", + "--ssh-options= -i /root/.ssh/id_rsa_miab", + "--rsync-options= -e \"/usr/bin/ssh -oStrictHostKeyChecking=no -oBatchMode=yes -p 22 -i /root/.ssh/id_rsa_miab\"", ] def backup_status(env): @@ -406,7 +406,7 @@ def list_target_files(config): reason = "Provided path {} is invalid.".format(target_path) elif 'Network is unreachable' in listing: reason = "The IP address {} is unreachable.".format(target.hostname) - elif 'Could not resolve hostname': + elif 'Could not resolve hostname' in listing: reason = "The hostname {} cannot be resolved.".format(target.hostname) else: reason = "Unknown error." \ @@ -419,15 +419,22 @@ def list_target_files(config): fix_boto() # must call prior to importing boto import boto.s3 from boto.exception import BotoServerError + custom_region = False for region in boto.s3.regions(): if region.endpoint == target.hostname: break else: - raise ValueError("Invalid S3 region/host.") + # If region is not found this is a custom region + custom_region = True bucket = target.path[1:].split('/')[0] path = '/'.join(target.path[1:].split('/')[1:]) + '/' + # Create a custom region with custom endpoint + if custom_region: + from boto.s3.connection import S3Connection + region = boto.s3.S3RegionInfo(name=bucket, endpoint=target.hostname, connection_cls=S3Connection) + # If no prefix is specified, set the path to '', otherwise boto won't list the files if path == '/': path = '' diff --git a/management/dns_update.py b/management/dns_update.py index 5c1969d7..dba6dbc1 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -288,6 +288,21 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en if not has_rec(qname, "SRV"): records.append((qname, "SRV", "0 0 443 " + env["PRIMARY_HOSTNAME"] + ".", "Recommended. Specifies the hostname of the server that handles CardDAV/CalDAV services for email addresses on this domain.")) + # Adds autoconfiguration A records for all domains. + # This allows the following clients to automatically configure email addresses in the respective applications. + # autodiscover.* - Z-Push ActiveSync Autodiscover + # autoconfig.* - Thunderbird Autoconfig + autodiscover_records = [ + ("autodiscover", "A", env["PUBLIC_IP"], "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover."), + ("autodiscover", "AAAA", env["PUBLIC_IPV6"], "Provides email configuration autodiscovery support for Z-Push ActiveSync Autodiscover."), + ("autoconfig", "A", env["PUBLIC_IP"], "Provides email configuration autodiscovery support for Thunderbird Autoconfig."), + ("autoconfig", "AAAA", env["PUBLIC_IPV6"], "Provides email configuration autodiscovery support for Thunderbird Autoconfig.") + ] + for qname, rtype, value, explanation in autodiscover_records: + if value is None or value.strip() == "": continue # skip IPV6 if not set + if not has_rec(qname, rtype): + records.append((qname, rtype, value, explanation)) + # Sort the records. The None records *must* go first in the nsd zone file. Otherwise it doesn't matter. records.sort(key = lambda rec : list(reversed(rec[0].split(".")) if rec[0] is not None else "")) @@ -888,10 +903,14 @@ def set_secondary_dns(hostnames, env): else: # Validate IP address. try: - v = ipaddress.ip_address(item[4:]) # raises a ValueError if there's a problem - if not isinstance(v, ipaddress.IPv4Address): raise ValueError("That's an IPv6 address.") + if "/" in item[4:]: + v = ipaddress.ip_network(item[4:]) # raises a ValueError if there's a problem + if not isinstance(v, ipaddress.IPv4Network): raise ValueError("That's an IPv6 subnet.") + else: + v = ipaddress.ip_address(item[4:]) # raises a ValueError if there's a problem + if not isinstance(v, ipaddress.IPv4Address): raise ValueError("That's an IPv6 address.") except ValueError: - raise ValueError("'%s' is not an IPv4 address." % item[4:]) + raise ValueError("'%s' is not an IPv4 address or subnet." % item[4:]) # Set. set_custom_dns_record("_secondary_nameserver", "A", " ".join(hostnames), "set", env) diff --git a/management/mailconfig.py b/management/mailconfig.py index 0bca7b2a..ee4bef2c 100755 --- a/management/mailconfig.py +++ b/management/mailconfig.py @@ -195,7 +195,7 @@ def get_mail_users_ex(env, with_archived=False): if email in active_accounts: continue user = { "email": email, - "privileges": "", + "privileges": [], "status": "inactive", "mailbox": mbox, } diff --git a/management/status_checks.py b/management/status_checks.py index 5b724bee..9c1cc6c9 100755 --- a/management/status_checks.py +++ b/management/status_checks.py @@ -488,10 +488,12 @@ def check_dns_zone(domain, env, output, dns_zonefiles): if custom_secondary_ns and not probably_external_dns: for ns in custom_secondary_ns: # We must first resolve the nameserver to an IP address so we can query it. - ns_ip = query_dns(ns, "A") - if not ns_ip: + ns_ips = query_dns(ns, "A") + if not ns_ips: output.print_error("Secondary nameserver %s is not valid (it doesn't resolve to an IP address)." % ns) continue + # Choose the first IP if nameserver returns multiple + ns_ip = ns_ips.split('; ')[0] # Now query it to see what it says about this domain. ip = query_dns(domain, "A", at=ns_ip, nxdomain=None) diff --git a/management/templates/custom-dns.html b/management/templates/custom-dns.html index c838d32a..56facdc9 100644 --- a/management/templates/custom-dns.html +++ b/management/templates/custom-dns.html @@ -90,7 +90,7 @@

Multiple secondary servers can be separated with commas or spaces (i.e., ns2.hostingcompany.com ns3.hostingcompany.com). - To enable zone transfers to additional servers without listing them as secondary nameservers, add xfr:IPADDRESS. + To enable zone transfers to additional servers without listing them as secondary nameservers, add an IP address or subnet using xfr:10.20.30.40 or xfr:10.20.30.40/24.


- + {% endif %}

Log in here for your Mail-in-a-Box control panel.

-
+
@@ -76,7 +76,7 @@ function do_login() { "/me", "GET", { }, - function(response){ + function(response){ // This API call always succeeds. It returns a JSON object indicating // whether the request was authenticated or not. if (response.status != "ok") { diff --git a/management/templates/system-backup.html b/management/templates/system-backup.html index be528f19..3860edb7 100644 --- a/management/templates/system-backup.html +++ b/management/templates/system-backup.html @@ -77,15 +77,22 @@
- +
- {% for name, host in backup_s3_hosts %} {% endfor %} +
+
+ +
+ +
+
@@ -139,6 +146,8 @@ function toggle_form() { var target_type = $("#backup-target-type").val(); $(".backup-target-local, .backup-target-rsync, .backup-target-s3").hide(); $(".backup-target-" + target_type).show(); + + init_inputs(target_type); } function nice_size(bytes) { @@ -278,4 +287,20 @@ function set_custom_backup() { }); return false; } + +function init_inputs(target_type) { + function set_host(host) { + if(host !== 'other') { + $("#backup-target-s3-host").val(host); + } else { + $("#backup-target-s3-host").val(''); + } + } + if (target_type == "s3") { + $('#backup-target-s3-host-select').off('change').on('change', function() { + set_host($('#backup-target-s3-host-select').val()); + }); + set_host($('#backup-target-s3-host-select').val()); + } +} diff --git a/management/web_update.py b/management/web_update.py index 616698ba..1d8da03f 100644 --- a/management/web_update.py +++ b/management/web_update.py @@ -29,6 +29,12 @@ def get_web_domains(env, include_www_redirects=True, exclude_dns_elsewhere=True) # IP address than this box. Remove those domains from our list. domains -= get_domains_with_a_records(env) + # Add Autoconfiguration domains, allowing us to serve correct SSL certs. + # 'autoconfig.' for Mozilla Thunderbird auto setup. + # 'autodiscover.' for Activesync autodiscovery. + domains |= set('autoconfig.' + maildomain for maildomain in get_mail_domains(env)) + domains |= set('autodiscover.' + maildomain for maildomain in get_mail_domains(env)) + # Ensure the PRIMARY_HOSTNAME is in the list so we can serve webmail # as well as Z-Push for Exchange ActiveSync. This can't be removed # by a custom A/AAAA record and is never a 'www.' redirect. diff --git a/setup/bootstrap.sh b/setup/bootstrap.sh index 498c02df..3d020225 100644 --- a/setup/bootstrap.sh +++ b/setup/bootstrap.sh @@ -20,7 +20,7 @@ if [ -z "$TAG" ]; then # want to display in status checks. if [ "`lsb_release -d | sed 's/.*:\s*//' | sed 's/18\.04\.[0-9]/18.04/' `" == "Ubuntu 18.04 LTS" ]; then # This machine is running Ubuntu 18.04. - TAG=v0.41-quota-0.18-beta + TAG=v0.43-quota-0.18-beta elif [ "`lsb_release -d | sed 's/.*:\s*//' | sed 's/14\.04\.[0-9]/14.04/' `" == "Ubuntu 14.04 LTS" ]; then # This machine is running Ubuntu 14.04. diff --git a/setup/functions.sh b/setup/functions.sh index 1a74edfd..3bb96b7a 100644 --- a/setup/functions.sh +++ b/setup/functions.sh @@ -1,7 +1,7 @@ # Turn on "strict mode." See http://redsymbol.net/articles/unofficial-bash-strict-mode/. # -e: exit if any command unexpectedly fails. # -u: exit if we have a variable typo. -# -o pipefail: don't ignore errors in the non-last command in a pipeline +# -o pipefail: don't ignore errors in the non-last command in a pipeline set -euo pipefail function hide_output { @@ -127,7 +127,7 @@ function get_default_privateip { if [ "$1" == "6" ]; then target=2001:4860:4860::8888; fi # Get the route information. - route=$(ip -$1 -o route get $target | grep -v unreachable) + route=$(ip -$1 -o route get $target 2>/dev/null | grep -v unreachable) # Parse the address out of the route information. address=$(echo $route | sed "s/.* src \([^ ]*\).*/\1/") diff --git a/setup/mail-dovecot.sh b/setup/mail-dovecot.sh index ac18adfd..f3ef753f 100755 --- a/setup/mail-dovecot.sh +++ b/setup/mail-dovecot.sh @@ -82,11 +82,12 @@ tools/editconf.py /etc/dovecot/conf.d/10-auth.conf \ # Enable SSL, specify the location of the SSL certificate and private key files. # Disable obsolete SSL protocols and allow only good ciphers per http://baldric.net/2013/12/07/tls-ciphers-in-postfix-and-dovecot/. # Enable strong ssl dh parameters + tools/editconf.py /etc/dovecot/conf.d/10-ssl.conf \ ssl=required \ "ssl_cert=<$STORAGE_ROOT/ssl/ssl_certificate.pem" \ "ssl_key=<$STORAGE_ROOT/ssl/ssl_private_key.pem" \ - "ssl_protocols=!SSLv3 !SSLv2" \ + "ssl_protocols=!SSLv3" \ "ssl_cipher_list=ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS" \ "ssl_prefer_server_ciphers = yes" \ "ssl_dh_parameters_length = 2048" @@ -137,6 +138,14 @@ service lmtp { } } +# Enable imap-login on localhost to allow the user_external plugin +# for Nextcloud to do imap authentication. (See #1577) +service imap-login { + inet_listener imap { + address = 127.0.0.1 + port = 143 + } +} protocol imap { mail_max_userip_connections = 20 } diff --git a/setup/mail-postfix.sh b/setup/mail-postfix.sh index 33d6fab3..e3ba3422 100755 --- a/setup/mail-postfix.sh +++ b/setup/mail-postfix.sh @@ -225,7 +225,34 @@ postconf -e smtpd_recipient_restrictions="$RECIPIENT_RESTRICTIONS" # e-mails really latter, delay of greylisting has been set to # 180 seconds (default is 300 seconds). tools/editconf.py /etc/default/postgrey \ - POSTGREY_OPTS=\"'--inet=127.0.0.1:10023 --delay=180'\" + POSTGREY_OPTS=\"'--inet=127.0.0.1:10023 --delay=180 --whitelist-recipients=/etc/postgrey/whitelist_clients'\" + + +# We are going to setup a newer whitelist for postgrey, the version included in the distribution is old +cat > /etc/cron.daily/mailinabox-postgrey-whitelist << EOF; +#!/bin/bash + +# Mail-in-a-Box + +# check we have a postgrey_whitelist_clients file and that it is not older than 28 days +if [ ! -f /etc/postgrey/whitelist_clients ] || find /etc/postgrey/whitelist_clients -mtime +28 > /dev/null ; then + # ok we need to update the file, so lets try to fetch it + if curl https://postgrey.schweikert.ch/pub/postgrey_whitelist_clients --output /tmp/postgrey_whitelist_clients -sS --fail > /dev/null 2>&1 ; then + # if fetching hasn't failed yet then check it is a plain text file + # curl manual states that --fail sometimes still produces output + # this final check will at least check the output is not html + # before moving it into place + if [ "\$(file -b --mime-type /tmp/postgrey_whitelist_clients)" == "text/plain" ]; then + mv /tmp/postgrey_whitelist_clients /etc/postgrey/whitelist_clients + service postgrey restart + else + rm /tmp/postgrey_whitelist_clients + fi + fi +fi +EOF +chmod +x /etc/cron.daily/mailinabox-postgrey-whitelist +/etc/cron.daily/mailinabox-postgrey-whitelist # Increase the message size limit from 10MB to 128MB. # The same limit is specified in nginx.conf for mail submitted via webmail and Z-Push. diff --git a/setup/management.sh b/setup/management.sh index f7621a8b..3a6e187b 100755 --- a/setup/management.sh +++ b/setup/management.sh @@ -38,7 +38,7 @@ inst_dir=/usr/local/lib/mailinabox mkdir -p $inst_dir venv=$inst_dir/env if [ ! -d $venv ]; then - virtualenv -ppython3 $venv + hide_output virtualenv -ppython3 $venv fi # Upgrade pip because the Ubuntu-packaged version is out of date. diff --git a/setup/munin.sh b/setup/munin.sh index 3cb1cd9d..df7af601 100755 --- a/setup/munin.sh +++ b/setup/munin.sh @@ -76,4 +76,8 @@ restart_service munin-node # generate initial statistics so the directory isn't empty # (We get "Pango-WARNING **: error opening config file '/root/.config/pango/pangorc': Permission denied" # if we don't explicitly set the HOME directory when sudo'ing.) -sudo -H -u munin munin-cron +# We check to see if munin-cron is already running, if it is, there is no need to run it simultaneously +# generating an error. +if [ ! -f /var/run/munin/munin-update.lock ]; then + sudo -H -u munin munin-cron +fi diff --git a/setup/nextcloud.sh b/setup/nextcloud.sh index 9476bbf8..d5a8e7c5 100755 --- a/setup/nextcloud.sh +++ b/setup/nextcloud.sh @@ -13,7 +13,8 @@ apt-get purge -qq -y owncloud* # we used to use the package manager apt_install php php-fpm \ php-cli php-sqlite3 php-gd php-imap php-curl php-pear curl \ - php-dev php-gd php-xml php-mbstring php-zip php-apcu php-json php-intl + php-dev php-gd php-xml php-mbstring php-zip php-apcu php-json \ + php-intl php-imagick InstallNextcloud() { @@ -24,12 +25,12 @@ InstallNextcloud() { echo "Upgrading to Nextcloud version $version" echo + # Download and verify + wget_verify https://download.nextcloud.com/server/releases/nextcloud-$version.zip $hash /tmp/nextcloud.zip + # Remove the current owncloud/Nextcloud rm -rf /usr/local/lib/owncloud - # Download and verify - wget_verify https://download.nextcloud.com/server/releases/nextcloud-$version.zip $hash /tmp/nextcloud.zip - # Extract ownCloud/Nextcloud unzip -q /tmp/nextcloud.zip -d /usr/local/lib mv /usr/local/lib/nextcloud /usr/local/lib/owncloud @@ -39,14 +40,22 @@ InstallNextcloud() { # their github repositories. mkdir -p /usr/local/lib/owncloud/apps - wget_verify https://github.com/nextcloud/contacts/releases/download/v2.1.8/contacts.tar.gz b5d5bbee33f0c32b124b46cb6aaab90c695ac170 /tmp/contacts.tgz + wget_verify https://github.com/nextcloud/contacts/releases/download/v3.1.1/contacts.tar.gz a06bd967197dcb03c94ec1dbd698c037018669e5 /tmp/contacts.tgz tar xf /tmp/contacts.tgz -C /usr/local/lib/owncloud/apps/ rm /tmp/contacts.tgz - wget_verify https://github.com/nextcloud/calendar/releases/download/v1.6.4/calendar.tar.gz d8a7950dba14803472b6c19625a8ceb23d6fd4ef /tmp/calendar.tgz + wget_verify https://github.com/nextcloud/calendar/releases/download/v1.6.5/calendar.tar.gz 79941255521a5172f7e4ce42dc7773838b5ede2f /tmp/calendar.tgz tar xf /tmp/calendar.tgz -C /usr/local/lib/owncloud/apps/ rm /tmp/calendar.tgz + # Starting with Nextcloud 15, the app user_external is no longer included in Nextcloud core, + # we will install from their github repository. + if [[ $version =~ ^15 ]]; then + wget_verify https://github.com/nextcloud/user_external/releases/download/v0.6.3/user_external-0.6.3.tar.gz 0f756d35fef6b64a177d6a16020486b76ea5799c /tmp/user_external.tgz + tar -xf /tmp/user_external.tgz -C /usr/local/lib/owncloud/apps/ + rm /tmp/user_external.tgz + fi + # Fix weird permissions. chmod 750 /usr/local/lib/owncloud/{apps,config} @@ -75,15 +84,32 @@ InstallNextcloud() { # Add missing indices. NextCloud didn't include this in the normal upgrade because it might take some time. sudo -u www-data php /usr/local/lib/owncloud/occ db:add-missing-indices + + # Run conversion to BigInt identifiers, this process may take some time on large tables. + sudo -u www-data php /usr/local/lib/owncloud/occ db:convert-filecache-bigint --no-interaction fi } -nextcloud_ver=14.0.6 -nextcloud_hash=4e43a57340f04c2da306c8eea98e30040399ae5a +# Nextcloud Version to install. Checks are done down below to step through intermediate versions. +nextcloud_ver=15.0.8 +nextcloud_hash=4129d8d4021c435f2e86876225fb7f15adf764a3 -# Check if Nextcloud dir exist, and check if version matches nextcloud_ver (if either doesn't - install/upgrade) -if [ ! -d /usr/local/lib/owncloud/ ] \ - || ! grep -q $nextcloud_ver /usr/local/lib/owncloud/version.php; then +# Current Nextcloud Version, #1623 +# Checking /usr/local/lib/owncloud/version.php shows version of the Nextcloud application, not the DB +# $STORAGE_ROOT/owncloud is kept together even during a backup. It is better to rely on config.php than +# version.php since the restore procedure can leave the system in a state where you have a newer Nextcloud +# application version than the database. + +# If config.php exists, get version number, otherwise CURRENT_NEXTCLOUD_VER is empty. +if [ -f "$STORAGE_ROOT/owncloud/config.php" ]; then + CURRENT_NEXTCLOUD_VER=$(php -r "include(\"$STORAGE_ROOT/owncloud/config.php\"); echo(\$CONFIG['version']);") +else + CURRENT_NEXTCLOUD_VER="" +fi + +# If the Nextcloud directory is missing (never been installed before, or the nextcloud version to be installed is different +# from the version currently installed, do the install/upgrade +if [ ! -d /usr/local/lib/owncloud/ ] || [[ ! ${CURRENT_NEXTCLOUD_VER} =~ ^$nextcloud_ver ]]; then # Stop php-fpm if running. If theyre not running (which happens on a previously failed install), dont bail. service php7.2-fpm stop &> /dev/null || /bin/true @@ -104,16 +130,22 @@ if [ ! -d /usr/local/lib/owncloud/ ] \ fi # If ownCloud or Nextcloud was previously installed.... - if [ -e /usr/local/lib/owncloud/version.php ]; then + if [ ! -z ${CURRENT_NEXTCLOUD_VER} ]; then # Database migrations from ownCloud are no longer possible because ownCloud cannot be run under # PHP 7. - if grep -q "OC_VersionString = '[89]\." /usr/local/lib/owncloud/version.php; then + if [[ ${CURRENT_NEXTCLOUD_VER} =~ ^[89] ]]; then echo "Upgrades from Mail-in-a-Box prior to v0.28 (dated July 30, 2018) with Nextcloud < 13.0.6 (you have ownCloud 8 or 9) are not supported. Upgrade to Mail-in-a-Box version v0.30 first. Setup aborting." exit 1 - fi - if grep -q "OC_VersionString = '1[012]\." /usr/local/lib/owncloud/version.php; then + elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^1[012] ]]; then echo "Upgrades from Mail-in-a-Box prior to v0.28 (dated July 30, 2018) with Nextcloud < 13.0.6 (you have ownCloud 10, 11 or 12) are not supported. Upgrade to Mail-in-a-Box version v0.30 first. Setup aborting." exit 1 + elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^13 ]]; then + # If we are running Nextcloud 13, upgrade to Nextcloud 14 + InstallNextcloud 14.0.6 4e43a57340f04c2da306c8eea98e30040399ae5a + elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^14 ]]; then + # During the upgrade from Nextcloud 14 to 15, user_external may cause the upgrade to fail. + # We will disable it here before the upgrade and install it again after the upgrade. + hide_output sudo -u www-data php /usr/local/lib/owncloud/console.php app:disable user_external fi fi @@ -142,10 +174,12 @@ if [ ! -f $STORAGE_ROOT/owncloud/owncloud.db ]; then 'overwritewebroot' => '/cloud', 'overwrite.cli.url' => '/cloud', 'user_backends' => array( - array( - 'class'=>'OC_User_IMAP', - 'arguments'=>array('{127.0.0.1:993/imap/ssl/novalidate-cert}') - ) + array( + 'class' => 'OC_User_IMAP', + 'arguments' => array( + '127.0.0.1', 143, null + ), + ), ), 'memcache.local' => '\OC\Memcache\APCu', 'mail_smtpmode' => 'sendmail', @@ -217,6 +251,8 @@ include("$STORAGE_ROOT/owncloud/config.php"); \$CONFIG['mail_domain'] = '$PRIMARY_HOSTNAME'; +\$CONFIG['user_backends'] = array(array('class' => 'OC_User_IMAP','arguments' => array('127.0.0.1', 143, null),),); + echo "