user_query = SELECT CONCAT(JSON_UNQUOTE(JSON_EXTRACT(attributes, '$.mailbox_format')), mailbox_path_prefix, '%d/%n/:VOLATILEDIR=/var/volatile/%u') AS mail, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1'
iterate_query = SELECT username FROM mailbox WHERE active='1';
password_query = SELECT password FROM mailbox WHERE active = '1' AND username = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1') AND JSON_EXTRACT(attributes, '$.force_pw_update') NOT LIKE '%%1%%'
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "DELETE FROM _sogo_static_view WHERE c_uid NOT IN (SELECT username FROM mailbox WHERE active = '1')"
else
echo "Waiting for database initialization..."
sleep 3
fi
done
# Recreate password update trigger
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password"
while [[ ${TRIGGER_OK} != 'OK' ]]; do
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
DELIMITER -
CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view
FOR EACH ROW
BEGIN
UPDATE mailbox SET password = NEW.c_password WHERE NEW.c_uid = username;
END;
-
DELIMITER ;
EOF
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'sogo_update_password'") ]]; then
TRIGGER_OK=OK
else
echo "Will retry to setup SOGo password update trigger in 3s"
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`send_as` SEPARATOR ', '), '✘') AS `send_as` FROM `sender_acl` WHERE `logged_in_as` = :username AND `send_as` NOT LIKE '@%';");
$stmt->execute(array(':username' => $username));
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($run)) {
$data['aliases_also_send_as'] = $row['send_as'];
}
$stmt = $pdo->prepare("SELECT IFNULL(CONCAT(GROUP_CONCAT(DISTINCT `send_as` SEPARATOR ', '), ', ', GROUP_CONCAT(DISTINCT CONCAT('@',`alias_domain`) SEPARATOR ', ')), '✘') AS `send_as` FROM `sender_acl` LEFT JOIN `alias_domain` ON `alias_domain`.`target_domain` = TRIM(LEADING '@' FROM `send_as`) WHERE `logged_in_as` = :username AND `send_as` LIKE '@%';");
$stmt->execute(array(':username' => $username));
$run = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($run)) {
$data['aliases_send_as_all'] = $row['send_as'];
}
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '✘') as `address` FROM `alias` WHERE `goto` REGEXP :username AND `address` LIKE '@%';");
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = '{}' WHERE `attributes` = '' OR `attributes` IS NULL;");
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.force_pw_update', \"0\") WHERE JSON_EXTRACT(`attributes`, '$.force_pw_update') IS NULL;");
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sogo_access', \"1\") WHERE JSON_EXTRACT(`attributes`, '$.sogo_access') IS NULL;");
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.mailbox_format', \"maildir:\") WHERE JSON_EXTRACT(`attributes`, '$.mailbox_format') IS NULL;");
foreach($tls_options as $tls_user => $tls_options) {
$stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_enforce_in),
// Set tls_enforce_* if still missing (due to deleted attrs for example)
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', \"1\") WHERE JSON_EXTRACT(`attributes`, '$.tls_enforce_out') IS NULL;");
$stmt = $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', \"1\") WHERE JSON_EXTRACT(`attributes`, '$.tls_enforce_in') IS NULL;");
// Fix ACL
$stmt = $pdo->query("INSERT INTO `user_acl` (`username`) SELECT `username` FROM `mailbox` WHERE `kind` = '' AND NOT EXISTS (SELECT `username` FROM `user_acl`);");
$stmt = $pdo->query("INSERT INTO `da_acl` (`username`) SELECT DISTINCT `username` FROM `domain_admins` WHERE `username` != 'admin' AND NOT EXISTS (SELECT `username` FROM `da_acl`);");
// Fix domain_admins
$stmt = $pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';");
+ echo "Installed memory is less than 1.5 GiB. It is recommended to disable ClamAV to prevent out-of-memory situations."
+ read -r -p "Do you want to disable ClamAV now? ClamAV can be re-enabled by setting SKIP_CLAMD=n in mailcow.conf. [Y/n] " response
+ case $response in
+ [nN][oO]|[nN])
+ SKIP_CLAMD=n
+ ;;
+ *)
+ SKIP_CLAMD=y
+ ;;
+ esac
+else
+ SKIP_CLAMD=n
+fi
+
+if [ ${MEM_TOTAL} -le "6815744" ]; then
+ echo "Installed memory is less than 6.5 GiB. It is highly recommended to disable Solr to prevent out-of-memory situations."
+ echo "Solr is a prone to run OOM and should be monitored. The default Solr heap size is 1024 MiB and should be set according to your expected load in mailcow.conf."
+ read -r -p "Do you want to disable Solr now (recommended)? Solr can be re-enabled by setting SKIP_SOLR=n in mailcow.conf. [Y/n] " response
echo "Found deprecated label \"latest\" for repository $REPOSITORY, it should be deleted."
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
elif [[ $V_MAIN_EXISTING -lt $V_MAIN ]]; then
echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted."
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
elif [[ $V_SUB_EXISTING -lt $V_SUB ]]; then
echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted."
IMGS_TO_DELETE+=($REPOSITORY:$existing_tag)
fi
done
done
if [[ ! -z ${IMGS_TO_DELETE[*]} ]]; then
echo "Run the following command to delete unused image tags:"
echo
echo " docker rmi ${IMGS_TO_DELETE[*]}"
echo
read -r -p "Do you want to delete old image tags right now? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
docker rmi ${IMGS_TO_DELETE[*]}
else
echo "OK, skipped."
fi
fi
echo -e "\e[32mFurther cleanup...\e[0m"
echo "If you want to cleanup further garbage collected by Docker, please make sure all containers are up and running before cleaning your system by executing \"docker system prune\""
}
while (($#)); do
case "${1}" in
--check|-c)
echo "Checking remote code for updates..."
git fetch origin #${BRANCH}
if [[ -z $(git log HEAD --pretty=format:"%H" | grep $(git rev-parse origin/${BRANCH})) ]]; then
git commit -am "Before update on ${DATE}" > /dev/null
echo -e "\e[32mFetching updated code from remote...\e[0m"
git fetch origin #${BRANCH}
echo -e "\e[32mMerging local with remote code (recursive, strategy: \"${MERGE_STRATEGY:-theirs}\", options: \"patience\"...\e[0m"
git config merge.defaultToUpstream true
git merge -X${MERGE_STRATEGY:-theirs} -Xpatience -m "After update on ${DATE}"
# Need to use a variable to not pass return codes of if checks
MERGE_RETURN=$?
if [[ ${MERGE_RETURN} == 128 ]]; then
echo -e "\e[31m\nOh no, what happened?\n=> You most likely added files to your local mailcow instance that were now added to the official mailcow repository. Please move them to another location before updating mailcow.\e[0m"
exit 1
elif [[ ${MERGE_RETURN} == 1 ]]; then
echo -e "\e[93mPotenial conflict, trying to fix...\e[0m"
if grep -q 'SYSCTL_IPV6_DISABLED=1' mailcow.conf; then
echo
echo '!! IMPORTANT !!'
echo
echo 'SYSCTL_IPV6_DISABLED was removed due to complications. IPv6 can be disabled by editing "docker-compose.yml" and setting "enabled_ipv6: true" to "enabled_ipv6: false".'
echo 'This setting will only be active after a complete shutdown of mailcow by running "docker-compose down" followed by "docker-compose up -d".'
echo
echo '!! IMPORTANT !!'
echo
read -p "Press any key to continue..." < /dev/tty
fi
echo -e "Fixing project name... "
sed -i 's#COMPOSEPROJECT_NAME#COMPOSE_PROJECT_NAME#g' mailcow.conf
sed -i '/COMPOSE_PROJECT_NAME=/s/-//g' mailcow.conf
echo -e "Fixing PHP-FPM worker ports for Nginx sites..."
sed -i 's#phpfpm:9000#phpfpm:9002#g' data/conf/nginx/*.conf
if ls data/conf/nginx/*.custom 1> /dev/null 2>&1; then
sed -i 's#phpfpm:9000#phpfpm:9002#g' data/conf/nginx/*.custom