diff --git a/conf/fail2ban/jails.conf b/conf/fail2ban/jails.conf index ce957f41..dccfcf5d 100644 --- a/conf/fail2ban/jails.conf +++ b/conf/fail2ban/jails.conf @@ -5,7 +5,7 @@ # Whitelist our own IP addresses. 127.0.0.1/8 is the default. But our status checks # ping services over the public interface so we should whitelist that address of # ours too. The string is substituted during installation. -ignoreip = 127.0.0.1/8 PUBLIC_IP +ignoreip = 127.0.0.1/8 ::1/128 PUBLIC_IP PUBLIC_IPV6/64 [dovecot] enabled = true diff --git a/conf/nginx-top.conf b/conf/nginx-top.conf index c3f4c0d6..85d056cf 100644 --- a/conf/nginx-top.conf +++ b/conf/nginx-top.conf @@ -7,6 +7,5 @@ ## your own --- please do not ask for help from us. upstream php-fpm { - server unix:/var/run/php/php8.0-fpm.sock; + server unix:/var/run/php/php{{phpver}}-fpm.sock; } - diff --git a/management/backup.py b/management/backup.py index 9011eda8..a211210d 100755 --- a/management/backup.py +++ b/management/backup.py @@ -12,7 +12,7 @@ import dateutil.parser, dateutil.relativedelta, dateutil.tz import rtyaml from exclusiveprocess import Lock -from utils import load_environment, shell, wait_for_service, fix_boto +from utils import load_environment, shell, wait_for_service, fix_boto, get_php_version rsync_ssh_options = [ "--ssh-options= -i /root/.ssh/id_rsa_miab", @@ -20,7 +20,7 @@ rsync_ssh_options = [ ] def backup_status(env): - # If backups are dissbled, return no status. + # If backups are disabled, return no status. config = get_backup_config(env) if config["target"] == "off": return { } @@ -212,9 +212,10 @@ def get_target_type(config): def perform_backup(full_backup): env = load_environment() + php_fpm = f"php{get_php_version()}-fpm" # Create an global exclusive lock so that the backup script - # cannot be run more than one. + # cannot be run more than once. Lock(die=True).forever() config = get_backup_config(env) @@ -247,7 +248,7 @@ def perform_backup(full_backup): if quit: sys.exit(code) - service_command("php8.0-fpm", "stop", quit=True) + service_command(php_fpm, "stop", quit=True) service_command("postfix", "stop", quit=True) service_command("dovecot", "stop", quit=True) @@ -281,7 +282,7 @@ def perform_backup(full_backup): # Start services again. service_command("dovecot", "start", quit=False) service_command("postfix", "start", quit=False) - service_command("php8.0-fpm", "start", quit=False) + service_command(php_fpm, "start", quit=False) # Remove old backups. This deletes all backup data no longer needed # from more than 3 days ago. diff --git a/management/ssl_certificates.py b/management/ssl_certificates.py index 3e1b5856..96959425 100755 --- a/management/ssl_certificates.py +++ b/management/ssl_certificates.py @@ -346,6 +346,8 @@ def provision_certificates(env, limit_domains): "certonly", #"-v", # just enough to see ACME errors "--non-interactive", # will fail if user hasn't registered during Mail-in-a-Box setup + "--agree-tos", # Automatically agrees to Let's Encrypt TOS + "--register-unsafely-without-email", # The daemon takes care of renewals "-d", ",".join(domain_list), # first will be main domain diff --git a/management/status_checks.py b/management/status_checks.py index 2c2180a3..cb8097f7 100755 --- a/management/status_checks.py +++ b/management/status_checks.py @@ -135,13 +135,15 @@ def check_service(i, service, env): # IPv4 ok but IPv6 failed. Try the PRIVATE_IPV6 address to see if the service is bound to the interface. elif service["port"] != 53 and try_connect(env["PRIVATE_IPV6"]): - output.print_error("%s is running (and available over IPv4 and the local IPv6 address), but it is not publicly accessible at %s:%d." % (service['name'], env['PUBLIC_IP'], service['port'])) + output.print_error("%s is running (and available over IPv4 and the local IPv6 address), but it is not publicly accessible at %s:%d." % (service['name'], env['PUBLIC_IPV6'], service['port'])) else: output.print_error("%s is running and available over IPv4 but is not accessible over IPv6 at %s port %d." % (service['name'], env['PUBLIC_IPV6'], service['port'])) # IPv4 failed. Try the private IP to see if the service is running but not accessible (except DNS because a different service runs on the private IP). elif service["port"] != 53 and try_connect("127.0.0.1"): output.print_error("%s is running but is not publicly accessible at %s:%d." % (service['name'], env['PUBLIC_IP'], service['port'])) + elif try_connect(env["PUBLIC_IPV6"]): + output.print_warning("%s is only running on ipv6 (port %d)." % (service['name'], service['port'])) else: output.print_error("%s is not running (port %d)." % (service['name'], service['port'])) diff --git a/management/utils.py b/management/utils.py index 652b48f6..bc357040 100644 --- a/management/utils.py +++ b/management/utils.py @@ -182,6 +182,9 @@ def fix_boto(): import os os.environ["BOTO_CONFIG"] = "/etc/boto3.cfg" +def get_php_version(): + # Gets the version of PHP installed in the system. + return shell("check_output", ["/usr/bin/php", "-v"])[4:7] if __name__ == "__main__": from web_update import get_web_domains diff --git a/management/web_update.py b/management/web_update.py index 7230182b..18e98e71 100644 --- a/management/web_update.py +++ b/management/web_update.py @@ -7,7 +7,7 @@ import os.path, re, rtyaml from mailconfig import get_mail_domains from dns_update import get_custom_dns_config, get_dns_zones from ssl_certificates import get_ssl_certificates, get_domain_ssl_files, check_certificate -from utils import shell, safe_domain_name, sort_domains +from utils import shell, safe_domain_name, sort_domains, get_php_version def get_web_domains(env, include_www_redirects=True, include_auto=True, exclude_dns_elsewhere=True): # What domains should we serve HTTP(S) for? @@ -77,6 +77,7 @@ def do_web_update(env): # Build an nginx configuration file. nginx_conf = open(os.path.join(os.path.dirname(__file__), "../conf/nginx-top.conf")).read() + nginx_conf = re.sub("{{phpver}}", get_php_version(), nginx_conf) # Load the templates. template0 = open(os.path.join(os.path.dirname(__file__), "../conf/nginx.conf")).read() diff --git a/setup/functions.sh b/setup/functions.sh index 718a2283..f026e13c 100644 --- a/setup/functions.sh +++ b/setup/functions.sh @@ -220,3 +220,7 @@ function git_clone { mv $TMPPATH/$SUBDIR $TARGETPATH rm -rf $TMPPATH } + +function php_version { + php --version | head -n 1 | cut -d " " -f 2 | cut -c 1-3 +} diff --git a/setup/munin.sh b/setup/munin.sh index 6799cad6..4a25bf2a 100755 --- a/setup/munin.sh +++ b/setup/munin.sh @@ -23,14 +23,15 @@ includedir /etc/munin/munin-conf.d # path dynazoom uses for requests cgiurl_graph /admin/munin/cgi-graph +# send alerts to the following address +contact.admin.command mail -s "Munin notification \${var:host}" administrator@$PRIMARY_HOSTNAME +contact.admin.always_send warning critical + # a simple host tree [$PRIMARY_HOSTNAME] address 127.0.0.1 -# send alerts to the following address contacts admin -contact.admin.command mail -s "Munin notification \${var:host}" administrator@$PRIMARY_HOSTNAME -contact.admin.always_send warning critical EOF # The Debian installer touches these files and chowns them to www-data:adm for use with spawn-fcgi diff --git a/setup/nextcloud.sh b/setup/nextcloud.sh index 331023dc..bb32a4c7 100755 --- a/setup/nextcloud.sh +++ b/setup/nextcloud.sh @@ -21,8 +21,8 @@ echo "Installing Nextcloud (contacts/calendar)..." # we automatically install intermediate versions as needed. # * The hash is the SHA1 hash of the ZIP package, which you can find by just running this script and # copying it from the error message when it doesn't match what is below. -nextcloud_ver=23.0.0 -nextcloud_hash=0d496eb0808c292502479e93cd37fe2daf95786a +nextcloud_ver=24.0.0 +nextcloud_hash=f072f5863a15cefe577b47f72bb3e41d2a339335 # Nextcloud apps # -------------- @@ -33,12 +33,12 @@ nextcloud_hash=0d496eb0808c292502479e93cd37fe2daf95786a # https://github.com/nextcloud/user_external/blob/master/appinfo/info.xml # * The hash is the SHA1 hash of the ZIP package, which you can find by just running this script and # copying it from the error message when it doesn't match what is below. -contacts_ver=4.0.7 -contacts_hash=8ab31d205408e4f12067d8a4daa3595d46b513e3 -calendar_ver=3.0.4 -calendar_hash=6fb1e998d307c53245faf1c37a96eb982bbee8ba -user_external_ver=1.0.0 -user_external_hash=3bf2609061d7214e7f0f69dd8883e55c4ec8f50a +contacts_ver=4.0.8 +contacts_hash=fc626ec02732da13a4c600baae64ab40557afdca +calendar_ver=3.0.6 +calendar_hash=e40d919b4b7988b46671a78cb32a43d8c7cba332 +user_external_ver=3.0.0 +user_external_hash=9e7aaf7288032bd463c480bc368ff91869122950 # Clear prior packages and install dependencies from apt. @@ -64,8 +64,8 @@ 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 + # 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 @@ -79,18 +79,18 @@ InstallNextcloud() { # their github repositories. mkdir -p /usr/local/lib/owncloud/apps - wget_verify https://github.com/nextcloud-releases/contacts/releases/download/v$version_contacts/contacts-v$version_contacts.tar.gz $hash_contacts /tmp/contacts.tgz + wget_verify https://github.com/nextcloud-releases/contacts/archive/refs/tags/v$version_contacts.tar.gz $hash_contacts /tmp/contacts.tgz tar xf /tmp/contacts.tgz -C /usr/local/lib/owncloud/apps/ rm /tmp/contacts.tgz - wget_verify https://github.com/nextcloud-releases/calendar/releases/download/v$version_calendar/calendar-v$version_calendar.tar.gz $hash_calendar /tmp/calendar.tgz + wget_verify https://github.com/nextcloud-releases/calendar/archive/refs/tags/v$version_calendar.tar.gz $hash_calendar /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 [ -n "$version_user_external" ]; then - wget_verify https://github.com/nextcloud/user_external/releases/download/v$version_user_external/user_external-$version_user_external.tar.gz $hash_user_external /tmp/user_external.tgz + wget_verify https://github.com/nextcloud/user_external/archive/refs/tags/v$version_user_external.tar.gz $hash_user_external /tmp/user_external.tgz tar -xf /tmp/user_external.tgz -C /usr/local/lib/owncloud/apps/ rm /tmp/user_external.tgz fi @@ -147,7 +147,7 @@ fi if [ ! -d /usr/local/lib/owncloud/ ] || [[ ! ${CURRENT_NEXTCLOUD_VER} =~ ^$nextcloud_ver ]]; then # Stop php-fpm if running. If they are not running (which happens on a previously failed install), dont bail. - service php8.0-fpm stop &> /dev/null || /bin/true + service php$(php_version)-fpm stop &> /dev/null || /bin/true # Backup the existing ownCloud/Nextcloud. # Create a backup directory to store the current installation and database to @@ -177,13 +177,16 @@ if [ ! -d /usr/local/lib/owncloud/ ] || [[ ! ${CURRENT_NEXTCLOUD_VER} =~ ^$nextc elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^1[3456789] ]]; then echo "Upgrades from Mail-in-a-Box prior to v60 with Nextcloud 19 or earlier are not supported. Upgrade to the latest Mail-in-a-Box version supported on your machine first. Setup will continue, but skip the Nextcloud migration." return 0 - elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^20 ]]; then - InstallNextcloud 21.0.7 f5c7079c5b56ce1e301c6a27c0d975d608bb01c9 4.0.7 8ab31d205408e4f12067d8a4daa3595d46b513e3 3.0.4 6fb1e998d307c53245faf1c37a96eb982bbee8ba 1.0.0 3bf2609061d7214e7f0f69dd8883e55c4ec8f50a - CURRENT_NEXTCLOUD_VER="21.0.7" - elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^21 ]]; then - InstallNextcloud 22.2.2 489eaf4147ad1b59385847b7d7db293712cced88 4.0.7 8ab31d205408e4f12067d8a4daa3595d46b513e3 3.0.4 6fb1e998d307c53245faf1c37a96eb982bbee8ba 1.0.0 3bf2609061d7214e7f0f69dd8883e55c4ec8f50a - CURRENT_NEXTCLOUD_VER="22.2.2" - fi + elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^20 ]]; then + InstallNextcloud 21.0.7 f5c7079c5b56ce1e301c6a27c0d975d608bb01c9 4.0.7 8ab31d205408e4f12067d8a4daa3595d46b513e3 3.0.4 6fb1e998d307c53245faf1c37a96eb982bbee8ba 1.0.0 3bf2609061d7214e7f0f69dd8883e55c4ec8f50a + CURRENT_NEXTCLOUD_VER="21.0.7" + elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^21 ]]; then + InstallNextcloud 22.2.2 489eaf4147ad1b59385847b7d7db293712cced88 4.0.7 8ab31d205408e4f12067d8a4daa3595d46b513e3 3.0.4 6fb1e998d307c53245faf1c37a96eb982bbee8ba 1.0.0 3bf2609061d7214e7f0f69dd8883e55c4ec8f50a + CURRENT_NEXTCLOUD_VER="22.2.2" + elif [[ ${CURRENT_NEXTCLOUD_VER} =~ ^22 ]]; then + InstallNextcloud 23.0.2 645cba42cab57029ebe29fb93906f58f7abea5f8 4.0.8 9f368bb2be98c5555b7118648f4cc9fa51e8cb30 3.0.6 ca49bb1ce23f20e10911e39055fd59d7f7a84c30 2.1.0 6e5afe7f36f398f864bfdce9cad72200e70322aa + CURRENT_NEXTCLOUD_VER="23.0.2" + fi fi InstallNextcloud $nextcloud_ver $nextcloud_hash $contacts_ver $contacts_hash $calendar_ver $calendar_hash $user_external_ver $user_external_hash @@ -212,8 +215,8 @@ if [ ! -f $STORAGE_ROOT/owncloud/owncloud.db ]; then 'overwrite.cli.url' => '/cloud', 'user_backends' => array( array( - 'class' => 'OC_User_IMAP', - 'arguments' => array( + 'class' => '\OCA\UserExternal\IMAP', + 'arguments' => array( '127.0.0.1', 143, null ), ), @@ -290,7 +293,7 @@ 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),),); +\$CONFIG['user_backends'] = array(array('class' => '\OCA\UserExternal\IMAP','arguments' => array('127.0.0.1', 143, null),),); echo " ${RCM_PLUGIN_DIR}/carddav/config.inc.php < 'ownCloud', 'username' => '%u', // login username 'password' => '%p', // login password - 'url' => 'https://${PRIMARY_HOSTNAME}/cloud/remote.php/carddav/addressbooks/%u/contacts', + 'url' => 'https://${PRIMARY_HOSTNAME}/cloud/remote.php/dav/addressbooks/users/%u/contacts', 'active' => true, 'readonly' => false, 'refresh_time' => '02:00:00', @@ -208,4 +208,4 @@ chmod 664 $STORAGE_ROOT/mail/roundcube/roundcube.sqlite # Enable PHP modules. phpenmod -v php mcrypt imap -restart_service php8.0-fpm +restart_service php$(php_version)-fpm diff --git a/tools/owncloud-restore.sh b/tools/owncloud-restore.sh index 9cdf5dbe..99bd6648 100755 --- a/tools/owncloud-restore.sh +++ b/tools/owncloud-restore.sh @@ -1,6 +1,7 @@ #!/bin/bash # # This script will restore the backup made during an installation +source setup/functions.sh # load our functions source /etc/mailinabox.conf # load global vars if [ -z "$1" ]; then @@ -26,7 +27,7 @@ if [ ! -f $1/config.php ]; then fi echo "Restoring backup from $1" -service php8.0-fpm stop +service php$(php_version)-fpm stop # remove the current ownCloud/Nextcloud installation rm -rf /usr/local/lib/owncloud/ @@ -45,5 +46,5 @@ chown www-data.www-data $STORAGE_ROOT/owncloud/config.php sudo -u www-data php /usr/local/lib/owncloud/occ maintenance:mode --off -service php8.0-fpm start +service php$(php_version)-fpm start echo "Done" diff --git a/tools/owncloud-unlockadmin.sh b/tools/owncloud-unlockadmin.sh index 50e3b010..84bfc2e6 100755 --- a/tools/owncloud-unlockadmin.sh +++ b/tools/owncloud-unlockadmin.sh @@ -8,7 +8,7 @@ source /etc/mailinabox.conf # load global vars -ADMIN=$(./mail.py user admins | head -n 1) +ADMIN=$(./management/cli.py user admins | head -n 1) test -z "$1" || ADMIN=$1 echo I am going to unlock admin features for $ADMIN.