mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-06-17 12:00:35 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d8a856d1cb | |||
| 11356674ba | |||
| 8c5f6c0321 | |||
| 6a16a4886c | |||
| ad5f07f077 | |||
| 91c82e8a67 | |||
| 4222f73ea0 | |||
| 463e3ab78c | |||
| 2a15914324 | |||
| 062539b7d7 | |||
| 18acbc7a4c | |||
| 2f93f1d0c5 | |||
| 0860a7503e | |||
| 86df78255d | |||
| 03565df48d | |||
| 0435766c17 | |||
| 79f4cf4021 | |||
| 81803836f0 | |||
| 4bd267515a |
@@ -30,7 +30,7 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
|
|
||||||
RUN apk upgrade --no-cache \
|
RUN apk upgrade --no-cache \
|
||||||
&& apk add --update --no-cache \
|
&& apk add --update --no-cache \
|
||||||
bash \
|
bash \
|
||||||
@@ -15,7 +14,7 @@ RUN apk upgrade --no-cache \
|
|||||||
tini \
|
tini \
|
||||||
tzdata \
|
tzdata \
|
||||||
python3 \
|
python3 \
|
||||||
acme-tiny --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community/
|
acme-tiny
|
||||||
|
|
||||||
COPY acme.sh /srv/acme.sh
|
COPY acme.sh /srv/acme.sh
|
||||||
COPY functions.sh /srv/functions.sh
|
COPY functions.sh /srv/functions.sh
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ log_f "Resolver OK"
|
|||||||
log_f "Waiting for domain table..."
|
log_f "Waiting for domain table..."
|
||||||
while [[ -z ${DOMAIN_TABLE} ]]; do
|
while [[ -z ${DOMAIN_TABLE} ]]; do
|
||||||
curl --silent http://nginx.${COMPOSE_PROJECT_NAME}_mailcow-network/ >/dev/null 2>&1
|
curl --silent http://nginx.${COMPOSE_PROJECT_NAME}_mailcow-network/ >/dev/null 2>&1
|
||||||
DOMAIN_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs)
|
DOMAIN_TABLE=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs)
|
||||||
[[ -z ${DOMAIN_TABLE} ]] && sleep 10
|
[[ -z ${DOMAIN_TABLE} ]] && sleep 10
|
||||||
done
|
done
|
||||||
log_f "OK" no_date
|
log_f "OK" no_date
|
||||||
@@ -231,7 +231,7 @@ while true; do
|
|||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
# IP and webroot challenge verification #
|
# IP and webroot challenge verification #
|
||||||
SQL_DOMAINS=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain WHERE backupmx=0 and active=1" -Bs)
|
SQL_DOMAINS=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain WHERE backupmx=0 and active=1" -Bs)
|
||||||
if [[ ! $? -eq 0 ]]; then
|
if [[ ! $? -eq 0 ]]; then
|
||||||
log_f "Failed to read SQL domains, retrying in 1 minute..."
|
log_f "Failed to read SQL domains, retrying in 1 minute..."
|
||||||
sleep 1m
|
sleep 1m
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ RUN addgroup -g 5000 vmail \
|
|||||||
perl-par-packer \
|
perl-par-packer \
|
||||||
perl-parse-recdescent \
|
perl-parse-recdescent \
|
||||||
perl-lockfile-simple \
|
perl-lockfile-simple \
|
||||||
libproc \
|
libproc2 \
|
||||||
perl-readonly \
|
perl-readonly \
|
||||||
perl-regexp-common \
|
perl-regexp-common \
|
||||||
perl-sys-meminfo \
|
perl-sys-meminfo \
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ if ! [[ ${MAX_AGE} =~ ${NUM_REGEXP} ]] ; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TO_DELETE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT COUNT(id) FROM quarantine WHERE created < NOW() - INTERVAL ${MAX_AGE//[!0-9]/} DAY" -BN)
|
TO_DELETE=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT COUNT(id) FROM quarantine WHERE created < NOW() - INTERVAL ${MAX_AGE//[!0-9]/} DAY" -BN)
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM quarantine WHERE created < NOW() - INTERVAL ${MAX_AGE//[!0-9]/} DAY"
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM quarantine WHERE created < NOW() - INTERVAL ${MAX_AGE//[!0-9]/} DAY"
|
||||||
echo "Deleted ${TO_DELETE} items from quarantine table (max age is ${MAX_AGE//[!0-9]/} days)"
|
echo "Deleted ${TO_DELETE} items from quarantine table (max age is ${MAX_AGE//[!0-9]/} days)"
|
||||||
|
|||||||
@@ -414,15 +414,15 @@ printenv | sed 's/^\(.*\)$/export \1/g' > /source_env.sh
|
|||||||
|
|
||||||
# Clean stopped imapsync jobs
|
# Clean stopped imapsync jobs
|
||||||
rm -f /tmp/imapsync_busy.lock
|
rm -f /tmp/imapsync_busy.lock
|
||||||
IMAPSYNC_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'imapsync'" -Bs)
|
IMAPSYNC_TABLE=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'imapsync'" -Bs)
|
||||||
[[ ! -z ${IMAPSYNC_TABLE} ]] && mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "UPDATE imapsync SET is_running='0'"
|
[[ ! -z ${IMAPSYNC_TABLE} ]] && mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "UPDATE imapsync SET is_running='0'"
|
||||||
|
|
||||||
# Envsubst maildir_gc
|
# Envsubst maildir_gc
|
||||||
echo "$(envsubst < /usr/local/bin/maildir_gc.sh)" > /usr/local/bin/maildir_gc.sh
|
echo "$(envsubst < /usr/local/bin/maildir_gc.sh)" > /usr/local/bin/maildir_gc.sh
|
||||||
|
|
||||||
# GUID generation
|
# GUID generation
|
||||||
while [[ ${VERSIONS_OK} != 'OK' ]]; do
|
while [[ ${VERSIONS_OK} != 'OK' ]]; do
|
||||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = \"${DBNAME}\" AND TABLE_NAME = 'versions'") ]]; then
|
if [[ ! -z $(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = \"${DBNAME}\" AND TABLE_NAME = 'versions'") ]]; then
|
||||||
VERSIONS_OK=OK
|
VERSIONS_OK=OK
|
||||||
else
|
else
|
||||||
echo "Waiting for versions table to be created..."
|
echo "Waiting for versions table to be created..."
|
||||||
@@ -433,11 +433,11 @@ PUBKEY_MCRYPT=$(doveconf -P 2> /dev/null | grep -i mail_crypt_global_public_key
|
|||||||
if [ -f ${PUBKEY_MCRYPT} ]; then
|
if [ -f ${PUBKEY_MCRYPT} ]; then
|
||||||
GUID=$(cat <(echo ${MAILCOW_HOSTNAME}) /mail_crypt/ecpubkey.pem | sha256sum | cut -d ' ' -f1 | tr -cd "[a-fA-F0-9.:/] ")
|
GUID=$(cat <(echo ${MAILCOW_HOSTNAME}) /mail_crypt/ecpubkey.pem | sha256sum | cut -d ' ' -f1 | tr -cd "[a-fA-F0-9.:/] ")
|
||||||
if [ ${#GUID} -eq 64 ]; then
|
if [ ${#GUID} -eq 64 ]; then
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||||
REPLACE INTO versions (application, version) VALUES ("GUID", "${GUID}");
|
REPLACE INTO versions (application, version) VALUES ("GUID", "${GUID}");
|
||||||
EOF
|
EOF
|
||||||
else
|
else
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||||
REPLACE INTO versions (application, version) VALUES ("GUID", "INVALID");
|
REPLACE INTO versions (application, version) VALUES ("GUID", "INVALID");
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ from email.mime.multipart import MIMEMultipart
|
|||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.utils import COMMASPACE, formatdate
|
from email.utils import COMMASPACE, formatdate
|
||||||
import jinja2
|
import jinja2
|
||||||
from jinja2 import Template
|
from jinja2 import TemplateError
|
||||||
|
from jinja2.sandbox import SandboxedEnvironment
|
||||||
import json
|
import json
|
||||||
import redis
|
import redis
|
||||||
import time
|
import time
|
||||||
@@ -80,17 +81,22 @@ try:
|
|||||||
if len(meta_query) == 0:
|
if len(meta_query) == 0:
|
||||||
return
|
return
|
||||||
msg_count = len(meta_query)
|
msg_count = len(meta_query)
|
||||||
|
env = SandboxedEnvironment()
|
||||||
if r.get('Q_HTML'):
|
if r.get('Q_HTML'):
|
||||||
try:
|
try:
|
||||||
template = Template(r.get('Q_HTML'))
|
template = env.from_string(r.get('Q_HTML'))
|
||||||
except:
|
except Exception:
|
||||||
print("Error: Cannot parse quarantine template, falling back to default template.")
|
print("Error: Cannot parse quarantine template, falling back to default template.")
|
||||||
with open('/templates/quarantine.tpl') as file_:
|
with open('/templates/quarantine.tpl') as file_:
|
||||||
template = Template(file_.read())
|
template = env.from_string(file_.read())
|
||||||
else:
|
else:
|
||||||
with open('/templates/quarantine.tpl') as file_:
|
with open('/templates/quarantine.tpl') as file_:
|
||||||
template = Template(file_.read())
|
template = env.from_string(file_.read())
|
||||||
html = template.render(meta=meta_query, username=rcpt, counter=msg_count, hostname=mailcow_hostname, quarantine_acl=quarantine_acl)
|
try:
|
||||||
|
html = template.render(meta=meta_query, username=rcpt, counter=msg_count, hostname=mailcow_hostname, quarantine_acl=quarantine_acl)
|
||||||
|
except (jinja2.exceptions.SecurityError, TemplateError) as ex:
|
||||||
|
print(f"SecurityError or TemplateError in template rendering: {ex}")
|
||||||
|
return
|
||||||
text = html2text.html2text(html)
|
text = html2text.html2text(html)
|
||||||
count = 0
|
count = 0
|
||||||
while count < 15:
|
while count < 15:
|
||||||
@@ -165,4 +171,4 @@ try:
|
|||||||
notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl'], attrs['quarantine_category'])
|
notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl'], attrs['quarantine_category'])
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
os.unlink(pidfile)
|
os.unlink(pidfile)
|
||||||
@@ -6,7 +6,7 @@ from email.mime.multipart import MIMEMultipart
|
|||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.utils import COMMASPACE, formatdate
|
from email.utils import COMMASPACE, formatdate
|
||||||
import jinja2
|
import jinja2
|
||||||
from jinja2 import Template
|
from jinja2.sandbox import SandboxedEnvironment
|
||||||
import redis
|
import redis
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
@@ -33,16 +33,24 @@ while True:
|
|||||||
|
|
||||||
if r.get('QW_HTML'):
|
if r.get('QW_HTML'):
|
||||||
try:
|
try:
|
||||||
template = Template(r.get('QW_HTML'))
|
env = SandboxedEnvironment()
|
||||||
except:
|
template = env.from_string(r.get('QW_HTML'))
|
||||||
print("Error: Cannot parse quarantine template, falling back to default template.")
|
except Exception:
|
||||||
|
print("Error: Cannot parse quota template, falling back to default template.")
|
||||||
with open('/templates/quota.tpl') as file_:
|
with open('/templates/quota.tpl') as file_:
|
||||||
template = Template(file_.read())
|
env = SandboxedEnvironment()
|
||||||
|
template = env.from_string(file_.read())
|
||||||
else:
|
else:
|
||||||
with open('/templates/quota.tpl') as file_:
|
with open('/templates/quota.tpl') as file_:
|
||||||
template = Template(file_.read())
|
env = SandboxedEnvironment()
|
||||||
|
template = env.from_string(file_.read())
|
||||||
|
|
||||||
|
try:
|
||||||
|
html = template.render(username=username, percent=percent)
|
||||||
|
except (jinja2.exceptions.SecurityError, jinja2.TemplateError) as ex:
|
||||||
|
print(f"SecurityError or TemplateError in template rendering: {ex}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
html = template.render(username=username, percent=percent)
|
|
||||||
text = html2text.html2text(html)
|
text = html2text.html2text(html)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -91,4 +99,4 @@ except:
|
|||||||
try:
|
try:
|
||||||
sys.stderr.close()
|
sys.stderr.close()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM php:8.2-fpm-alpine3.20
|
FROM php:8.2-fpm-alpine3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ ARG MEMCACHED_PECL_VERSION=3.2.0
|
|||||||
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$
|
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$
|
||||||
ARG REDIS_PECL_VERSION=6.1.0
|
ARG REDIS_PECL_VERSION=6.1.0
|
||||||
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$
|
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$
|
||||||
ARG COMPOSER_VERSION=2.6.6
|
ARG COMPOSER_VERSION=2.8.6
|
||||||
|
|
||||||
RUN apk add -U --no-cache autoconf \
|
RUN apk add -U --no-cache autoconf \
|
||||||
aspell-dev \
|
aspell-dev \
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ if [ ${SQL_CHANGED} -eq 1 ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Check mysql tz import (master and slave)
|
# Check mysql tz import (master and slave)
|
||||||
TZ_CHECK=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT CONVERT_TZ('2019-11-02 23:33:00','Europe/Berlin','UTC') AS time;" -BN 2> /dev/null)
|
TZ_CHECK=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT CONVERT_TZ('2019-11-02 23:33:00','Europe/Berlin','UTC') AS time;" -BN 2> /dev/null)
|
||||||
if [[ -z ${TZ_CHECK} ]] || [[ "${TZ_CHECK}" == "NULL" ]]; then
|
if [[ -z ${TZ_CHECK} ]] || [[ "${TZ_CHECK}" == "NULL" ]]; then
|
||||||
SQL_FULL_TZINFO_IMPORT_RETURN=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_tzinfo_to_sql"}' --silent -H 'Content-type: application/json')
|
SQL_FULL_TZINFO_IMPORT_RETURN=$(curl --silent --insecure -XPOST https://dockerapi.${COMPOSE_PROJECT_NAME}_mailcow-network/containers/${CONTAINER_ID}/exec -d '{"cmd":"system", "task":"mysql_tzinfo_to_sql"}' --silent -H 'Content-type: application/json')
|
||||||
echo "MySQL mysql_tzinfo_to_sql - debug output:"
|
echo "MySQL mysql_tzinfo_to_sql - debug output:"
|
||||||
@@ -120,11 +120,11 @@ if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
|||||||
while read line
|
while read line
|
||||||
do
|
do
|
||||||
DOMAIN_ARR+=("$line")
|
DOMAIN_ARR+=("$line")
|
||||||
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain" -Bs)
|
done < <(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain" -Bs)
|
||||||
while read line
|
while read line
|
||||||
do
|
do
|
||||||
DOMAIN_ARR+=("$line")
|
DOMAIN_ARR+=("$line")
|
||||||
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT alias_domain FROM alias_domain" -Bs)
|
done < <(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT alias_domain FROM alias_domain" -Bs)
|
||||||
|
|
||||||
if [[ ! -z ${DOMAIN_ARR} ]]; then
|
if [[ ! -z ${DOMAIN_ARR} ]]; then
|
||||||
for domain in "${DOMAIN_ARR[@]}"; do
|
for domain in "${DOMAIN_ARR[@]}"; do
|
||||||
@@ -146,13 +146,13 @@ if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
|||||||
VALIDATED_IPS=$(array_by_comma ${VALIDATED_API_ALLOW_FROM_ARR[*]})
|
VALIDATED_IPS=$(array_by_comma ${VALIDATED_API_ALLOW_FROM_ARR[*]})
|
||||||
if [[ ! -z ${VALIDATED_IPS} ]]; then
|
if [[ ! -z ${VALIDATED_IPS} ]]; then
|
||||||
if [[ ${API_KEY} != "invalid" ]] && [[ ! -z ${API_KEY} ]]; then
|
if [[ ${API_KEY} != "invalid" ]] && [[ ! -z ${API_KEY} ]]; then
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||||
DELETE FROM api WHERE access = 'rw';
|
DELETE FROM api WHERE access = 'rw';
|
||||||
INSERT INTO api (api_key, active, allow_from, access) VALUES ("${API_KEY}", "1", "${VALIDATED_IPS}", "rw");
|
INSERT INTO api (api_key, active, allow_from, access) VALUES ("${API_KEY}", "1", "${VALIDATED_IPS}", "rw");
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
if [[ ${API_KEY_READ_ONLY} != "invalid" ]] && [[ ! -z ${API_KEY_READ_ONLY} ]]; then
|
if [[ ${API_KEY_READ_ONLY} != "invalid" ]] && [[ ! -z ${API_KEY_READ_ONLY} ]]; then
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||||
DELETE FROM api WHERE access = 'ro';
|
DELETE FROM api WHERE access = 'ro';
|
||||||
INSERT INTO api (api_key, active, allow_from, access) VALUES ("${API_KEY_READ_ONLY}", "1", "${VALIDATED_IPS}", "ro");
|
INSERT INTO api (api_key, active, allow_from, access) VALUES ("${API_KEY_READ_ONLY}", "1", "${VALIDATED_IPS}", "ro");
|
||||||
EOF
|
EOF
|
||||||
@@ -161,7 +161,7 @@ EOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Create events (master only, STATUS for event on slave will be SLAVESIDE_DISABLED)
|
# Create events (master only, STATUS for event on slave will be SLAVESIDE_DISABLED)
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||||
DROP EVENT IF EXISTS clean_spamalias;
|
DROP EVENT IF EXISTS clean_spamalias;
|
||||||
DELIMITER //
|
DELIMITER //
|
||||||
CREATE EVENT clean_spamalias
|
CREATE EVENT clean_spamalias
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ FROM debian:bookworm-slim
|
|||||||
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ARG RSPAMD_VER=rspamd_3.11.0-2~90a175b45
|
ARG RSPAMD_VER=rspamd_3.11.1-1~ab0b44951
|
||||||
ARG CODENAME=bookworm
|
ARG CODENAME=bookworm
|
||||||
ENV LC_ALL=C
|
ENV LC_ALL=C
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Wait for updated schema
|
# Wait for updated schema
|
||||||
DBV_NOW=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions WHERE application = 'db_schema';" -BN)
|
DBV_NOW=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions WHERE application = 'db_schema';" -BN)
|
||||||
DBV_NEW=$(grep -oE '\$db_version = .*;' init_db.inc.php | sed 's/$db_version = //g;s/;//g' | cut -d \" -f2)
|
DBV_NEW=$(grep -oE '\$db_version = .*;' init_db.inc.php | sed 's/$db_version = //g;s/;//g' | cut -d \" -f2)
|
||||||
while [[ "${DBV_NOW}" != "${DBV_NEW}" ]]; do
|
while [[ "${DBV_NOW}" != "${DBV_NEW}" ]]; do
|
||||||
echo "Waiting for schema update..."
|
echo "Waiting for schema update..."
|
||||||
DBV_NOW=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions WHERE application = 'db_schema';" -BN)
|
DBV_NOW=$(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions WHERE application = 'db_schema';" -BN)
|
||||||
DBV_NEW=$(grep -oE '\$db_version = .*;' init_db.inc.php | sed 's/$db_version = //g;s/;//g' | cut -d \" -f2)
|
DBV_NEW=$(grep -oE '\$db_version = .*;' init_db.inc.php | sed 's/$db_version = //g;s/;//g' | cut -d \" -f2)
|
||||||
sleep 5
|
sleep 5
|
||||||
done
|
done
|
||||||
@@ -27,9 +27,9 @@ echo "DB schema is ${DBV_NOW}"
|
|||||||
# Recreate view
|
# Recreate view
|
||||||
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||||
echo "We are master, preparing sogo_view..."
|
echo "We are master, preparing sogo_view..."
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
|
||||||
while [[ ${VIEW_OK} != 'OK' ]]; do
|
while [[ ${VIEW_OK} != 'OK' ]]; do
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||||
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) AS
|
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) AS
|
||||||
SELECT
|
SELECT
|
||||||
mailbox.username,
|
mailbox.username,
|
||||||
@@ -59,7 +59,7 @@ WHERE
|
|||||||
GROUP BY
|
GROUP BY
|
||||||
mailbox.username;
|
mailbox.username;
|
||||||
EOF
|
EOF
|
||||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
|
if [[ ! -z $(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
|
||||||
VIEW_OK=OK
|
VIEW_OK=OK
|
||||||
else
|
else
|
||||||
echo "Will retry to setup SOGo view in 3s..."
|
echo "Will retry to setup SOGo view in 3s..."
|
||||||
@@ -68,7 +68,7 @@ EOF
|
|||||||
done
|
done
|
||||||
else
|
else
|
||||||
while [[ ${VIEW_OK} != 'OK' ]]; do
|
while [[ ${VIEW_OK} != 'OK' ]]; do
|
||||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
|
if [[ ! -z $(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
|
||||||
VIEW_OK=OK
|
VIEW_OK=OK
|
||||||
else
|
else
|
||||||
echo "Waiting for SOGo view to be created by master..."
|
echo "Waiting for SOGo view to be created by master..."
|
||||||
@@ -81,12 +81,12 @@ fi
|
|||||||
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||||
echo "We are master, preparing _sogo_static_view..."
|
echo "We are master, preparing _sogo_static_view..."
|
||||||
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do
|
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do
|
||||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
|
if [[ ! -z $(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
|
||||||
STATIC_VIEW_OK=OK
|
STATIC_VIEW_OK=OK
|
||||||
echo "Updating _sogo_static_view content..."
|
echo "Updating _sogo_static_view content..."
|
||||||
# If changed, also update init_db.inc.php
|
# If changed, also update init_db.inc.php
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "REPLACE INTO _sogo_static_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) SELECT c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings from sogo_view;"
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "REPLACE INTO _sogo_static_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) SELECT c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings from sogo_view;"
|
||||||
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')"
|
mariadb --skip-ssl --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
|
else
|
||||||
echo "Waiting for database initialization..."
|
echo "Waiting for database initialization..."
|
||||||
sleep 3
|
sleep 3
|
||||||
@@ -94,7 +94,7 @@ if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
|||||||
done
|
done
|
||||||
else
|
else
|
||||||
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do
|
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do
|
||||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
|
if [[ ! -z $(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
|
||||||
STATIC_VIEW_OK=OK
|
STATIC_VIEW_OK=OK
|
||||||
else
|
else
|
||||||
echo "Waiting for database initialization by master..."
|
echo "Waiting for database initialization by master..."
|
||||||
@@ -107,9 +107,9 @@ fi
|
|||||||
# Recreate password update trigger
|
# Recreate password update trigger
|
||||||
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||||
echo "We are master, preparing update trigger..."
|
echo "We are master, preparing update trigger..."
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password"
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password"
|
||||||
while [[ ${TRIGGER_OK} != 'OK' ]]; do
|
while [[ ${TRIGGER_OK} != 'OK' ]]; do
|
||||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||||
DELIMITER -
|
DELIMITER -
|
||||||
CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view
|
CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
@@ -119,7 +119,7 @@ END;
|
|||||||
-
|
-
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
EOF
|
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
|
if [[ ! -z $(mariadb --skip-ssl --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
|
TRIGGER_OK=OK
|
||||||
else
|
else
|
||||||
echo "Will retry to setup SOGo password update trigger in 3s"
|
echo "Will retry to setup SOGo password update trigger in 3s"
|
||||||
@@ -216,7 +216,7 @@ while read -r line gal
|
|||||||
line=${line} envsubst < /etc/sogo/plist_ldap >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
line=${line} envsubst < /etc/sogo/plist_ldap >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
||||||
echo " </array>
|
echo " </array>
|
||||||
</dict>" >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
</dict>" >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
||||||
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain, CASE gal WHEN '1' THEN 'YES' ELSE 'NO' END AS gal FROM domain;" -B -N)
|
done < <(mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain, CASE gal WHEN '1' THEN 'YES' ELSE 'NO' END AS gal FROM domain;" -B -N)
|
||||||
|
|
||||||
# Generate footer
|
# Generate footer
|
||||||
echo ' </dict>
|
echo ' </dict>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.20
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ fi
|
|||||||
|
|
||||||
# Connect to the DB server and store output in vars
|
# Connect to the DB server and store output in vars
|
||||||
if [[ -n $socket ]]; then
|
if [[ -n $socket ]]; then
|
||||||
ConnectionResult=$(mysql ${optfile} ${socket} ${user} -e "show slave ${connection} status\G" 2>&1)
|
ConnectionResult=$(mariadb --skip-ssl ${optfile} ${socket} ${user} -e "show slave ${connection} status\G" 2>&1)
|
||||||
else
|
else
|
||||||
ConnectionResult=$(mysql ${optfile} ${host} ${port} ${user} -e "show slave ${connection} status\G" 2>&1)
|
ConnectionResult=$(mariadb --skip-ssl ${optfile} ${host} ${port} ${user} -e "show slave ${connection} status\G" 2>&1)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "`echo "${ConnectionResult}" |grep Slave_IO_State`" ]; then
|
if [ -z "`echo "${ConnectionResult}" |grep Slave_IO_State`" ]; then
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ external_checks() {
|
|||||||
diff_c=0
|
diff_c=0
|
||||||
THRESHOLD=${EXTERNAL_CHECKS_THRESHOLD}
|
THRESHOLD=${EXTERNAL_CHECKS_THRESHOLD}
|
||||||
# Reduce error count by 2 after restarting an unhealthy container
|
# Reduce error count by 2 after restarting an unhealthy container
|
||||||
GUID=$(mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions WHERE application = 'GUID'" -BN)
|
GUID=$(mariadb --skip-ssl -u${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT version FROM versions WHERE application = 'GUID'" -BN)
|
||||||
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
||||||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||||
err_c_cur=${err_count}
|
err_c_cur=${err_count}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Whitelist generated by Postwhite v3.4 on Sat Feb 1 00:18:03 UTC 2025
|
# Whitelist generated by Postwhite v3.4 on Sat Mar 1 00:19:29 UTC 2025
|
||||||
# https://github.com/stevejenkins/postwhite/
|
# https://github.com/stevejenkins/postwhite/
|
||||||
# 1984 total rules
|
# 2000 total rules
|
||||||
2a00:1450:4000::/36 permit
|
2a00:1450:4000::/36 permit
|
||||||
2a01:111:f400::/48 permit
|
2a01:111:f400::/48 permit
|
||||||
2a01:111:f403:8000::/50 permit
|
2a01:111:f403:8000::/50 permit
|
||||||
@@ -8,6 +8,13 @@
|
|||||||
2a01:111:f403::/49 permit
|
2a01:111:f403::/49 permit
|
||||||
2a01:111:f403:c000::/51 permit
|
2a01:111:f403:c000::/51 permit
|
||||||
2a01:111:f403:f000::/52 permit
|
2a01:111:f403:f000::/52 permit
|
||||||
|
2a01:b747:3000:200::/56 permit
|
||||||
|
2a01:b747:3001:200::/56 permit
|
||||||
|
2a01:b747:3002:200::/56 permit
|
||||||
|
2a01:b747:3003:200::/56 permit
|
||||||
|
2a01:b747:3004:200::/56 permit
|
||||||
|
2a01:b747:3005:200::/56 permit
|
||||||
|
2a01:b747:3006:200::/56 permit
|
||||||
2a02:a60:0:5::/64 permit
|
2a02:a60:0:5::/64 permit
|
||||||
2c0f:fb50:4000::/36 permit
|
2c0f:fb50:4000::/36 permit
|
||||||
2.207.151.53 permit
|
2.207.151.53 permit
|
||||||
@@ -19,7 +26,6 @@
|
|||||||
8.20.114.31 permit
|
8.20.114.31 permit
|
||||||
8.25.194.0/23 permit
|
8.25.194.0/23 permit
|
||||||
8.25.196.0/23 permit
|
8.25.196.0/23 permit
|
||||||
10.162.0.0/16 permit
|
|
||||||
12.130.86.238 permit
|
12.130.86.238 permit
|
||||||
13.110.208.0/21 permit
|
13.110.208.0/21 permit
|
||||||
13.110.209.0/24 permit
|
13.110.209.0/24 permit
|
||||||
@@ -35,7 +41,9 @@
|
|||||||
17.57.156.0/24 permit
|
17.57.156.0/24 permit
|
||||||
17.58.0.0/16 permit
|
17.58.0.0/16 permit
|
||||||
17.142.0.0/15 permit
|
17.142.0.0/15 permit
|
||||||
17.143.234.140/30 permit
|
18.97.0.8/30 permit
|
||||||
|
18.97.1.184/29 permit
|
||||||
|
18.97.2.64/26 permit
|
||||||
18.156.89.250 permit
|
18.156.89.250 permit
|
||||||
18.157.243.190 permit
|
18.157.243.190 permit
|
||||||
18.194.95.56 permit
|
18.194.95.56 permit
|
||||||
@@ -283,6 +291,9 @@
|
|||||||
64.207.219.13 permit
|
64.207.219.13 permit
|
||||||
64.207.219.14 permit
|
64.207.219.14 permit
|
||||||
64.207.219.15 permit
|
64.207.219.15 permit
|
||||||
|
64.207.219.24 permit
|
||||||
|
64.207.219.25 permit
|
||||||
|
64.207.219.26 permit
|
||||||
64.207.219.71 permit
|
64.207.219.71 permit
|
||||||
64.207.219.72 permit
|
64.207.219.72 permit
|
||||||
64.207.219.73 permit
|
64.207.219.73 permit
|
||||||
@@ -292,6 +303,9 @@
|
|||||||
64.207.219.77 permit
|
64.207.219.77 permit
|
||||||
64.207.219.78 permit
|
64.207.219.78 permit
|
||||||
64.207.219.79 permit
|
64.207.219.79 permit
|
||||||
|
64.207.219.88 permit
|
||||||
|
64.207.219.89 permit
|
||||||
|
64.207.219.90 permit
|
||||||
64.207.219.135 permit
|
64.207.219.135 permit
|
||||||
64.207.219.136 permit
|
64.207.219.136 permit
|
||||||
64.207.219.137 permit
|
64.207.219.137 permit
|
||||||
@@ -1464,6 +1478,8 @@
|
|||||||
159.135.224.0/20 permit
|
159.135.224.0/20 permit
|
||||||
159.135.228.10 permit
|
159.135.228.10 permit
|
||||||
159.183.0.0/16 permit
|
159.183.0.0/16 permit
|
||||||
|
159.183.68.71 permit
|
||||||
|
159.183.79.38 permit
|
||||||
160.1.62.192 permit
|
160.1.62.192 permit
|
||||||
161.38.192.0/20 permit
|
161.38.192.0/20 permit
|
||||||
161.38.204.0/22 permit
|
161.38.204.0/22 permit
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ paths:
|
|||||||
description: a list of domains for which a dkim key should be generated
|
description: a list of domains for which a dkim key should be generated
|
||||||
type: string
|
type: string
|
||||||
key_size:
|
key_size:
|
||||||
description: the key size (1024 or 2048)
|
description: the key size (1024, 2048, 3072 or 4096)
|
||||||
type: number
|
type: number
|
||||||
type: object
|
type: object
|
||||||
summary: Generate DKIM Key
|
summary: Generate DKIM Key
|
||||||
|
|||||||
@@ -240,9 +240,12 @@ function dkim($_action, $_data = null, $privkey = false) {
|
|||||||
if (strlen($dkimdata['pubkey']) < 391) {
|
if (strlen($dkimdata['pubkey']) < 391) {
|
||||||
$dkimdata['length'] = "1024";
|
$dkimdata['length'] = "1024";
|
||||||
}
|
}
|
||||||
elseif (strlen($dkimdata['pubkey']) < 736) {
|
elseif (strlen($dkimdata['pubkey']) < 564) {
|
||||||
$dkimdata['length'] = "2048";
|
$dkimdata['length'] = "2048";
|
||||||
}
|
}
|
||||||
|
elseif (strlen($dkimdata['pubkey']) < 736) {
|
||||||
|
$dkimdata['length'] = "3072";
|
||||||
|
}
|
||||||
elseif (strlen($dkimdata['pubkey']) < 1416) {
|
elseif (strlen($dkimdata['pubkey']) < 1416) {
|
||||||
$dkimdata['length'] = "4096";
|
$dkimdata['length'] = "4096";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,11 @@
|
|||||||
"syncjobs": "동기화 작업",
|
"syncjobs": "동기화 작업",
|
||||||
"tls_policy": "TLS 정책",
|
"tls_policy": "TLS 정책",
|
||||||
"unlimited_quota": "메일에 무제한 할당",
|
"unlimited_quota": "메일에 무제한 할당",
|
||||||
"domain_desc": "도메인 설명 변경"
|
"domain_desc": "도메인 설명 변경",
|
||||||
|
"pw_reset": "mailcow 사용자 비밀번호 재설정 허용",
|
||||||
|
"domain_relayhost": "도메인의 릴레이 호스트 변경",
|
||||||
|
"mailbox_relayhost": "메일함의 릴레이 호스트 변경",
|
||||||
|
"quarantine_category": "검역소 알림 카테고리 변경"
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"activate_filter_warn": "활성화가 체크되어 있으면 모든 다른 필터들은 비활성화됩니다.",
|
"activate_filter_warn": "활성화가 체크되어 있으면 모든 다른 필터들은 비활성화됩니다.",
|
||||||
@@ -101,7 +105,9 @@
|
|||||||
"timeout2": "로컬 호스트 연결 시간 초과",
|
"timeout2": "로컬 호스트 연결 시간 초과",
|
||||||
"username": "사용자명",
|
"username": "사용자명",
|
||||||
"validate": "확인하기",
|
"validate": "확인하기",
|
||||||
"validation_success": "성공적으로 확인됨"
|
"validation_success": "성공적으로 확인됨",
|
||||||
|
"tags": "태그",
|
||||||
|
"app_passwd_protocols": "앱 비밀번호에 대해 허용되는 프로토콜"
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"access": "접근",
|
"access": "접근",
|
||||||
@@ -195,7 +201,7 @@
|
|||||||
"link": "Link",
|
"link": "Link",
|
||||||
"loading": "잠시만 기다려주세요...",
|
"loading": "잠시만 기다려주세요...",
|
||||||
"logo_info": "이미지 크기는 상단 탐색 막대의 경우 40px, 시작 페이지의 경우 최대 너비 250px로 조정됩니다. 확장 가능한 그래픽을 권장합니다.",
|
"logo_info": "이미지 크기는 상단 탐색 막대의 경우 40px, 시작 페이지의 경우 최대 너비 250px로 조정됩니다. 확장 가능한 그래픽을 권장합니다.",
|
||||||
"lookup_mx": "MX와 목적지 일치 (.outlook.com이 홉을 통해서 MX *.outlook.com을 대상으로 하는 모든 메일을 라우트한다.)",
|
"lookup_mx": "목적지가 MX 이름과 일치하는 정규 표현식입니다. (<code>.*\\.google\\.com</code>를 사용하여 이 홉을 통해 google.com으로 끝나는 모든 메일을 대상으로 하는 MX로 라우팅합니다.)",
|
||||||
"main_name": "\"mailcow UI\" 이름",
|
"main_name": "\"mailcow UI\" 이름",
|
||||||
"merged_vars_hint": "회색으로 표시된 행은 <code>vars.(local.)php</code> 에서 병합되었고 이는 수정할 수 없습니다.",
|
"merged_vars_hint": "회색으로 표시된 행은 <code>vars.(local.)php</code> 에서 병합되었고 이는 수정할 수 없습니다.",
|
||||||
"message": "메세지",
|
"message": "메세지",
|
||||||
@@ -301,7 +307,53 @@
|
|||||||
"username": "사용자 이름",
|
"username": "사용자 이름",
|
||||||
"validate_license_now": "라이선스 서버와 GUID 확인",
|
"validate_license_now": "라이선스 서버와 GUID 확인",
|
||||||
"verify": "확인",
|
"verify": "확인",
|
||||||
"yes": "✓"
|
"yes": "✓",
|
||||||
|
"domain_admin": "도메인 관리자",
|
||||||
|
"f2b_filter": "정규식 필터",
|
||||||
|
"f2b_manage_external": "외부에서 Fail2Ban 관리",
|
||||||
|
"f2b_max_ban_time": "최대 차단 시간(초)",
|
||||||
|
"f2b_regex_info": "고려되는 로그: SOGo, Postfix, Dovecot, PHP-FPM.",
|
||||||
|
"html": "HTML",
|
||||||
|
"oauth2_apps": "OAuth2 앱",
|
||||||
|
"oauth2_add_client": "OAuth2 클라이언트 추가",
|
||||||
|
"optional": "선택 사항",
|
||||||
|
"options": "옵션",
|
||||||
|
"password_length": "비밀번호 길이",
|
||||||
|
"password_policy_chars": "하나 이상의 알파벳 문자를 포함해야 합니다.",
|
||||||
|
"password_policy_length": "최소 암호 길이가 %d입니다.",
|
||||||
|
"password_policy_numbers": "숫자 하나 이상을 포함해야 합니다.",
|
||||||
|
"password_policy_special_chars": "특수 문자를 포함해야 합니다.",
|
||||||
|
"password_reset_info": "복구 이메일이 제공되지 않으면 이 기능을 사용할 수 없습니다.",
|
||||||
|
"password_reset_settings": "비밀번호 복구 설정",
|
||||||
|
"password_reset_tmpl_html": "HTML 템플릿",
|
||||||
|
"password_reset_tmpl_text": "Text 템플릿",
|
||||||
|
"password_settings": "비밀번호 설정",
|
||||||
|
"queue_unban": "차단 해제",
|
||||||
|
"restore_template": "기본 템플릿을 복원하려면 비워둡니다.",
|
||||||
|
"service": "서비스",
|
||||||
|
"success": "성공",
|
||||||
|
"dkim_overwrite_key": "기존 DKIM 키 덮어쓰기",
|
||||||
|
"f2b_ban_time_increment": "차단 시간은 차단될 때마다 증가합니다.",
|
||||||
|
"password_policy": "비밀번호 정책",
|
||||||
|
"quarantine_max_score": "메일의 스팸 점수가 이 값보다 높으면 알림을 삭제합니다:<br><small>기본값: 9999.0</small>",
|
||||||
|
"f2b_manage_external_info": "Fail2ban은 차단 목록을 유지하지만 트래픽을 차단하는 규칙을 능동적으로 설정하지는 않습니다. 트래픽을 외부에서 차단하려면 아래 생성된 차단 목록을 사용하세요.",
|
||||||
|
"password_policy_lowerupper": "소문자 및 대문자를 포함해야 합니다.",
|
||||||
|
"transport_test_rcpt_info": "• null@hosted.mailcow.de 을 사용하여 해외 목적지로 릴레이를 테스트하세요.",
|
||||||
|
"ip_check_disabled": "IP 확인이 비활성화됩니다. 아래에서 활성화할 수 있습니다<br> <strong>시스템 > 구성 > 옵션 > 사용자 정의</strong>",
|
||||||
|
"logo_normal_label": "일반",
|
||||||
|
"logo_dark_label": "다크 모드의 경우 반전",
|
||||||
|
"convert_html_to_text": "HTML을 일반 텍스트로 변환",
|
||||||
|
"copy_to_clipboard": "클립보드에 텍스트가 복사되었습니다!",
|
||||||
|
"cors_settings": "CORS 설정",
|
||||||
|
"rsettings_preset_4": "도메인에 대해 Rspamd 비활성화",
|
||||||
|
"ip_check": "IP 확인",
|
||||||
|
"admins": "관리자",
|
||||||
|
"admins_ldap": "LDAP 관리자",
|
||||||
|
"api_read_only": "읽기 전용 액세스",
|
||||||
|
"api_read_write": "읽기-쓰기 액세스",
|
||||||
|
"is_mx_based": "MX 기반",
|
||||||
|
"login_time": "로그인 시간",
|
||||||
|
"ip_check_opt_in": "외부 IP 주소 확인을 위해 타사 서비스 <strong>ipv4.mailcow.email</strong> 및 <strong>ipv6.mailcow.email</strong>을 사용하도록 설정합니다."
|
||||||
},
|
},
|
||||||
"danger": {
|
"danger": {
|
||||||
"access_denied": "접근이 거부되거나 잘못된 데이터 양식",
|
"access_denied": "접근이 거부되거나 잘못된 데이터 양식",
|
||||||
@@ -415,7 +467,30 @@
|
|||||||
"username_invalid": "%s는 사용지 이름으로 사용할 수 없습니다.",
|
"username_invalid": "%s는 사용지 이름으로 사용할 수 없습니다.",
|
||||||
"validity_missing": "유효 기간을 지정해주세요.",
|
"validity_missing": "유효 기간을 지정해주세요.",
|
||||||
"value_missing": "모든 값을 입력해주세요.",
|
"value_missing": "모든 값을 입력해주세요.",
|
||||||
"yotp_verification_failed": "Yubico OTP 검증 실패: %s"
|
"yotp_verification_failed": "Yubico OTP 검증 실패: %s",
|
||||||
|
"dkim_domain_or_sel_exists": "“%s\"에 대한 DKIM 키가 존재하며 덮어쓰지 않습니다.",
|
||||||
|
"img_size_exceeded": "이미지가 최대 파일 크기를 초과합니다.",
|
||||||
|
"invalid_reset_token": "잘못된 리셋 토큰",
|
||||||
|
"nginx_reload_failed": "Nginx 리로드 실패: %s",
|
||||||
|
"password_reset_na": "현재 비밀번호 복구를 사용할 수 없습니다. 관리자에게 문의하세요.",
|
||||||
|
"reset_f2b_regex": "정규식 필터를 제때 재설정하지 못했습니다. 다시 시도하거나 몇 초 더 기다렸다가 웹사이트를 다시 로드하세요.",
|
||||||
|
"template_exists": "템플릿 %s이(가) 이미 존재합니다.",
|
||||||
|
"template_id_invalid": "템플릿 ID %s가 잘못되었습니다.",
|
||||||
|
"template_name_invalid": "템플릿 이름이 잘못되었습니다.",
|
||||||
|
"tfa_token_invalid": "TFA 토큰이 유효하지 않습니다.",
|
||||||
|
"to_invalid": "수신자가 비어 있지 않아야 합니다.",
|
||||||
|
"webauthn_authenticator_failed": "선택한 인증기를 찾을 수 없습니다.",
|
||||||
|
"webauthn_username_failed": "선택한 인증기가 다른 계정에 속해 있습니다.",
|
||||||
|
"demo_mode_enabled": "데모 모드가 활성화됨",
|
||||||
|
"recovery_email_failed": "복구 이메일을 보낼 수 없습니다. 관리자에게 문의하세요.",
|
||||||
|
"password_reset_invalid_user": "사서함을 찾을 수 없거나 복구 이메일이 설정되어 있지 않습니다.",
|
||||||
|
"webauthn_publickey_failed": "선택한 인증기에 대한 공개 키가 저장되지 않았습니다.",
|
||||||
|
"fido2_verification_failed": "FIDO2 인증 실패: %s",
|
||||||
|
"extended_sender_acl_denied": "외부 발신자 주소를 설정하는 ACL 누락",
|
||||||
|
"img_dimensions_exceeded": "이미지가 최대 이미지 크기를 초과합니다.",
|
||||||
|
"reset_token_limit_exceeded": "토큰 재설정 한도를 초과했습니다. 나중에 다시 시도해 주세요.",
|
||||||
|
"cors_invalid_method": "잘못된 허용 메서드를 지정했습니다.",
|
||||||
|
"cors_invalid_origin": "잘못된 허용 원본을 지정했습니다."
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"chart_this_server": "Chart (this server)",
|
"chart_this_server": "Chart (this server)",
|
||||||
@@ -434,7 +509,24 @@
|
|||||||
"uptime": "Uptime",
|
"uptime": "Uptime",
|
||||||
"started_on": "Started on",
|
"started_on": "Started on",
|
||||||
"static_logs": "Static logs",
|
"static_logs": "Static logs",
|
||||||
"system_containers": "System & Containers"
|
"system_containers": "System & Containers",
|
||||||
|
"current_time": "시스템 시간",
|
||||||
|
"no_update_available": "시스템이 최신 버전입니다.",
|
||||||
|
"architecture": "아키텍처",
|
||||||
|
"container_running": "실행 중",
|
||||||
|
"container_disabled": "컨테이너 중지 또는 비활성화",
|
||||||
|
"container_stopped": "중지됨",
|
||||||
|
"online_users": "온라인 사용자",
|
||||||
|
"service": "서비스",
|
||||||
|
"success": "성공",
|
||||||
|
"show_ip": "공인 IP 표시",
|
||||||
|
"timezone": "시간대",
|
||||||
|
"update_available": "사용 가능한 업데이트가 있습니다.",
|
||||||
|
"update_failed": "업데이트를 확인할 수 없습니다",
|
||||||
|
"username": "사용자 이름",
|
||||||
|
"memory": "메모리",
|
||||||
|
"error_show_ip": "공인 IP 주소를 확인할 수 없습니다",
|
||||||
|
"login_time": "시간"
|
||||||
},
|
},
|
||||||
"diagnostics": {
|
"diagnostics": {
|
||||||
"cname_from_a": "Value derived from A/AAAA record. This is supported as long as the record points to the correct resource.",
|
"cname_from_a": "Value derived from A/AAAA record. This is supported as long as the record points to the correct resource.",
|
||||||
@@ -542,7 +634,13 @@
|
|||||||
"title": "Edit object",
|
"title": "Edit object",
|
||||||
"unchanged_if_empty": "If unchanged leave blank",
|
"unchanged_if_empty": "If unchanged leave blank",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"validate_save": "Validate and save"
|
"validate_save": "Validate and save",
|
||||||
|
"allow_from_smtp": "다음 IP만 <b>SMTP</b>를 사용하도록 허용합니다.",
|
||||||
|
"allow_from_smtp_info": "모든 발신자를 허용하려면 비워둡니다.<br>IPv4/IPv6 주소 및 네트워크.",
|
||||||
|
"allowed_protocols": "허용된 프로토콜",
|
||||||
|
"app_passwd_protocols": "앱 비밀번호에 대해 허용되는 프로토콜",
|
||||||
|
"acl": "ACL (권한)",
|
||||||
|
"admin": "관리자 수정"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
@@ -560,13 +658,14 @@
|
|||||||
"header": {
|
"header": {
|
||||||
"administration": "Configuration & Details",
|
"administration": "Configuration & Details",
|
||||||
"apps": "Apps",
|
"apps": "Apps",
|
||||||
"debug": "System Information",
|
"debug": "정보",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"mailcow_config": "Configuration",
|
"mailcow_config": "Configuration",
|
||||||
"quarantine": "Quarantine",
|
"quarantine": "Quarantine",
|
||||||
"restart_netfilter": "Restart netfilter",
|
"restart_netfilter": "Restart netfilter",
|
||||||
"restart_sogo": "Restart SOGo",
|
"restart_sogo": "Restart SOGo",
|
||||||
"user_settings": "User Settings"
|
"user_settings": "User Settings",
|
||||||
|
"mailcow_system": "시스템"
|
||||||
},
|
},
|
||||||
"info": {
|
"info": {
|
||||||
"awaiting_tfa_confirmation": "Awaiting TFA confirmation",
|
"awaiting_tfa_confirmation": "Awaiting TFA confirmation",
|
||||||
@@ -1017,5 +1116,25 @@
|
|||||||
"quota_exceeded_scope": "Domain quota exceeded: Only unlimited mailboxes can be created in this domain scope.",
|
"quota_exceeded_scope": "Domain quota exceeded: Only unlimited mailboxes can be created in this domain scope.",
|
||||||
"session_token": "Form token invalid: Token mismatch",
|
"session_token": "Form token invalid: Token mismatch",
|
||||||
"session_ua": "Form token invalid: User-Agent validation error"
|
"session_ua": "Form token invalid: User-Agent validation error"
|
||||||
|
},
|
||||||
|
"datatables": {
|
||||||
|
"collapse_all": "모두 접기",
|
||||||
|
"decimal": ".",
|
||||||
|
"emptyTable": "테이블에 사용 가능한 데이터가 없습니다.",
|
||||||
|
"expand_all": "모두 펼치기",
|
||||||
|
"infoEmpty": "0개 항목 중 0개부터 0개까지 표시",
|
||||||
|
"infoFiltered": "(_MAX_ 총 항목에서 필터링됨)",
|
||||||
|
"thousands": ",",
|
||||||
|
"lengthMenu": "_MENU_ 항목 표시",
|
||||||
|
"loadingRecords": "로딩 중...",
|
||||||
|
"processing": "잠시만 기다려 주세요...",
|
||||||
|
"search": "검색:",
|
||||||
|
"zeroRecords": "일치하는 레코드가 없습니다.",
|
||||||
|
"paginate": {
|
||||||
|
"first": "처음",
|
||||||
|
"last": "마지막",
|
||||||
|
"next": "다음",
|
||||||
|
"previous": "이전"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,8 @@
|
|||||||
<select data-style="btn btn-light btn-sm" class="form-control" id="key_size" name="key_size" title="{{ lang.admin.dkim_key_length }}" required>
|
<select data-style="btn btn-light btn-sm" class="form-control" id="key_size" name="key_size" title="{{ lang.admin.dkim_key_length }}" required>
|
||||||
<option data-subtext="bits">1024</option>
|
<option data-subtext="bits">1024</option>
|
||||||
<option data-subtext="bits">2048</option>
|
<option data-subtext="bits">2048</option>
|
||||||
|
<option data-subtext="bits">3072</option>
|
||||||
|
<option data-subtext="bits">4096</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
$(".totp-authenticator-selection").click(function(){
|
$(".totp-authenticator-selection").click(function(){
|
||||||
$(".totp-authenticator-selection").removeClass("active");
|
$(".totp-authenticator-selection").removeClass("active");
|
||||||
$(this).addClass("active");
|
$(this).addClass("active");
|
||||||
|
|
||||||
var id = $(this).children('input').first().val();
|
var id = $(this).children('input').first().val();
|
||||||
$("#totp_selected_id").val(id);
|
$("#totp_selected_id").val(id);
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
if ($('.totp-authenticator-selection').length == 1 &&
|
if ($('.totp-authenticator-selection').length == 1 &&
|
||||||
$('#pending_tfa_tab_yubi_otp').length == 0 &&
|
$('#pending_tfa_tab_yubi_otp').length == 0 &&
|
||||||
$('.webauthn-authenticator-selection').length == 0){
|
$('.webauthn-authenticator-selection').length == 0){
|
||||||
|
|
||||||
// select default if only one authenticator exists
|
// select default if only one authenticator exists
|
||||||
$('.totp-authenticator-selection').addClass("active");
|
$('.totp-authenticator-selection').addClass("active");
|
||||||
|
|
||||||
@@ -257,7 +257,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
$('#pending_tfa_tab_totp').on('shown.bs.tab', function() {
|
$('#pending_tfa_tab_totp').on('shown.bs.tab', function() {
|
||||||
// autofocus
|
// autofocus
|
||||||
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 200);
|
setTimeout(function() { $("#collapseTotpTFA").find('input[name="token"]').focus(); }, 200);
|
||||||
});
|
});
|
||||||
// validate Yubi OTP tfa
|
// validate Yubi OTP tfa
|
||||||
if ($('.webauthn-authenticator-selection').length == 0){
|
if ($('.webauthn-authenticator-selection').length == 0){
|
||||||
// autofocus
|
// autofocus
|
||||||
@@ -276,10 +276,10 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
$(".webauthn-authenticator-selection").click(function(){
|
$(".webauthn-authenticator-selection").click(function(){
|
||||||
$(".webauthn-authenticator-selection").removeClass("active");
|
$(".webauthn-authenticator-selection").removeClass("active");
|
||||||
$(this).addClass("active");
|
$(this).addClass("active");
|
||||||
|
|
||||||
var id = $(this).children('input').first().val();
|
var id = $(this).children('input').first().val();
|
||||||
$("#webauthn_selected_id").val(id);
|
$("#webauthn_selected_id").val(id);
|
||||||
|
|
||||||
var webauthn_status_auth = document.getElementById('webauthn_status_auth');
|
var webauthn_status_auth = document.getElementById('webauthn_status_auth');
|
||||||
webauthn_status_auth.style.setProperty('display', 'flex', 'important');
|
webauthn_status_auth.style.setProperty('display', 'flex', 'important');
|
||||||
var webauthn_return_code = document.getElementById('webauthn_return_code');
|
var webauthn_return_code = document.getElementById('webauthn_return_code');
|
||||||
@@ -302,7 +302,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
console.log(json);
|
console.log(json);
|
||||||
if (json.success === false) throw new Error();
|
if (json.success === false) throw new Error();
|
||||||
if (json.type === "error") throw new Error(json.msg);
|
if (json.type === "error") throw new Error(json.msg);
|
||||||
|
|
||||||
recursiveBase64StrToArrayBuffer(json);
|
recursiveBase64StrToArrayBuffer(json);
|
||||||
return json;
|
return json;
|
||||||
}).then(getCredentialArgs => {
|
}).then(getCredentialArgs => {
|
||||||
@@ -329,7 +329,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
webauthn_return_code.style.setProperty('display', 'block', 'important');
|
webauthn_return_code.style.setProperty('display', 'block', 'important');
|
||||||
webauthn_return_code.innerHTML = lang_tfa.error_code + ': ' + err + ' ' + lang_tfa.reload_retry;
|
webauthn_return_code.innerHTML = lang_tfa.error_code + ': ' + err + ' ' + lang_tfa.reload_retry;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('#ConfirmTFAModal').on('hidden.bs.modal', function(){
|
$('#ConfirmTFAModal').on('hidden.bs.modal', function(){
|
||||||
// cancel pending login
|
// cancel pending login
|
||||||
@@ -540,7 +540,7 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
Version: <a href="{{ mailcow_info.git_project_url }}/releases/tag/{{ mailcow_info.version_tag }}" target="_blank">{{ mailcow_info.version_tag }}
|
Version: <a href="{{ mailcow_info.git_project_url }}/releases/tag/{{ mailcow_info.version_tag }}" target="_blank">{{ mailcow_info.version_tag }}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if mailcow_cc_username and mailcow_info.mailcow_branch|lower == "nightly" and mailcow_info.version_tag|default %}
|
{% if mailcow_cc_username and mailcow_info.mailcow_branch|lower == "nightly" and mailcow_info.version_tag|default %}
|
||||||
<span class="version">
|
<span class="version">
|
||||||
🛠️🐮 + 🐋 = 💕
|
🛠️🐮 + 🐋 = 💕
|
||||||
@@ -549,6 +549,14 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
<span style="text-align:right;display:block;">Build: {{ mailcow_info.git_commit_date }}</span>
|
<span style="text-align:right;display:block;">Build: {{ mailcow_info.git_commit_date }}</span>
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if mailcow_cc_username and mailcow_info.mailcow_branch|lower == "legacy" and mailcow_info.version_tag|default %}
|
||||||
|
<span class="version">
|
||||||
|
⚰️🐮 + 🐋 = 💕
|
||||||
|
Legacy: <a href="{{ mailcow_info.git_project_url }}/commit/{{ mailcow_info.git_commit }}" target="_blank">{{ mailcow_info.version_tag }}
|
||||||
|
</a><br>
|
||||||
|
<span style="text-align:right;display:block;">Build: {{ mailcow_info.git_commit_date }}</span>
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -103,6 +103,8 @@
|
|||||||
<select data-style="btn btn-light" class="form-control" id="key_size" name="key_size">
|
<select data-style="btn btn-light" class="form-control" id="key_size" name="key_size">
|
||||||
<option value="1024" data-subtext="bits" {% if template.attributes.key_size == 1024 %} selected{% endif %}>1024</option>
|
<option value="1024" data-subtext="bits" {% if template.attributes.key_size == 1024 %} selected{% endif %}>1024</option>
|
||||||
<option value="2048" data-subtext="bits" {% if template.attributes.key_size == 2048 %} selected{% endif %}>2048</option>
|
<option value="2048" data-subtext="bits" {% if template.attributes.key_size == 2048 %} selected{% endif %}>2048</option>
|
||||||
|
<option value="3072" data-subtext="bits" {% if template.attributes.key_size == 3072 %} selected{% endif %}>3072</option>
|
||||||
|
<option value="4096" data-subtext="bits" {% if template.attributes.key_size == 4096 %} selected{% endif %}>4096</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -490,6 +490,8 @@
|
|||||||
<select data-style="btn btn-light" class="form-control" id="key_size" name="key_size">
|
<select data-style="btn btn-light" class="form-control" id="key_size" name="key_size">
|
||||||
<option data-subtext="bits" value="1024">1024</option>
|
<option data-subtext="bits" value="1024">1024</option>
|
||||||
<option data-subtext="bits" value="2048" selected>2048</option>
|
<option data-subtext="bits" value="2048" selected>2048</option>
|
||||||
|
<option data-subtext="bits" value="3072">3072</option>
|
||||||
|
<option data-subtext="bits" value="4096">4096</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -628,6 +630,8 @@
|
|||||||
<select data-style="btn btn-light" class="form-control" id="key_size" name="key_size">
|
<select data-style="btn btn-light" class="form-control" id="key_size" name="key_size">
|
||||||
<option data-subtext="bits">1024</option>
|
<option data-subtext="bits">1024</option>
|
||||||
<option data-subtext="bits" selected>2048</option>
|
<option data-subtext="bits" selected>2048</option>
|
||||||
|
<option data-subtext="bits">3072</option>
|
||||||
|
<option data-subtext="bits">4096</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -843,6 +847,8 @@
|
|||||||
<select data-style="btn btn-light" class="form-control" id="key_size2" name="key_size">
|
<select data-style="btn btn-light" class="form-control" id="key_size2" name="key_size">
|
||||||
<option data-subtext="bits">1024</option>
|
<option data-subtext="bits">1024</option>
|
||||||
<option data-subtext="bits" selected>2048</option>
|
<option data-subtext="bits" selected>2048</option>
|
||||||
|
<option data-subtext="bits">3072</option>
|
||||||
|
<option data-subtext="bits">4096</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+10
-10
@@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
|
|
||||||
unbound-mailcow:
|
unbound-mailcow:
|
||||||
image: ghcr.io/mailcow/unbound:1.23
|
image: ghcr.io/mailcow/unbound:1.24
|
||||||
environment:
|
environment:
|
||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
- SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
|
- SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
|
||||||
@@ -42,7 +42,7 @@ services:
|
|||||||
- mysql
|
- mysql
|
||||||
|
|
||||||
redis-mailcow:
|
redis-mailcow:
|
||||||
image: redis:7.4.2-alpine
|
image: redis:7.4.6-alpine
|
||||||
entrypoint: ["/bin/sh","/redis-conf.sh"]
|
entrypoint: ["/bin/sh","/redis-conf.sh"]
|
||||||
volumes:
|
volumes:
|
||||||
- redis-vol-1:/data/
|
- redis-vol-1:/data/
|
||||||
@@ -84,7 +84,7 @@ services:
|
|||||||
- clamd
|
- clamd
|
||||||
|
|
||||||
rspamd-mailcow:
|
rspamd-mailcow:
|
||||||
image: ghcr.io/mailcow/rspamd:2.0
|
image: ghcr.io/mailcow/rspamd:2.1
|
||||||
stop_grace_period: 30s
|
stop_grace_period: 30s
|
||||||
depends_on:
|
depends_on:
|
||||||
- dovecot-mailcow
|
- dovecot-mailcow
|
||||||
@@ -117,7 +117,7 @@ services:
|
|||||||
- rspamd
|
- rspamd
|
||||||
|
|
||||||
php-fpm-mailcow:
|
php-fpm-mailcow:
|
||||||
image: ghcr.io/mailcow/phpfpm:1.92
|
image: ghcr.io/mailcow/phpfpm:1.93
|
||||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis-mailcow
|
- redis-mailcow
|
||||||
@@ -234,7 +234,7 @@ services:
|
|||||||
- sogo
|
- sogo
|
||||||
|
|
||||||
dovecot-mailcow:
|
dovecot-mailcow:
|
||||||
image: ghcr.io/mailcow/dovecot:2.31
|
image: ghcr.io/mailcow/dovecot:2.34-legacy
|
||||||
depends_on:
|
depends_on:
|
||||||
- mysql-mailcow
|
- mysql-mailcow
|
||||||
- netfilter-mailcow
|
- netfilter-mailcow
|
||||||
@@ -419,7 +419,7 @@ services:
|
|||||||
condition: service_started
|
condition: service_started
|
||||||
unbound-mailcow:
|
unbound-mailcow:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
image: ghcr.io/mailcow/acme:1.91
|
image: ghcr.io/mailcow/acme:1.92
|
||||||
dns:
|
dns:
|
||||||
- ${IPV4_NETWORK:-172.22.1}.254
|
- ${IPV4_NETWORK:-172.22.1}.254
|
||||||
environment:
|
environment:
|
||||||
@@ -457,7 +457,7 @@ services:
|
|||||||
- acme
|
- acme
|
||||||
|
|
||||||
netfilter-mailcow:
|
netfilter-mailcow:
|
||||||
image: ghcr.io/mailcow/netfilter:1.61
|
image: ghcr.io/mailcow/netfilter:1.62
|
||||||
stop_grace_period: 30s
|
stop_grace_period: 30s
|
||||||
restart: always
|
restart: always
|
||||||
privileged: true
|
privileged: true
|
||||||
@@ -477,7 +477,7 @@ services:
|
|||||||
- /lib/modules:/lib/modules:ro
|
- /lib/modules:/lib/modules:ro
|
||||||
|
|
||||||
watchdog-mailcow:
|
watchdog-mailcow:
|
||||||
image: ghcr.io/mailcow/watchdog:2.06
|
image: ghcr.io/mailcow/watchdog:2.07
|
||||||
dns:
|
dns:
|
||||||
- ${IPV4_NETWORK:-172.22.1}.254
|
- ${IPV4_NETWORK:-172.22.1}.254
|
||||||
tmpfs:
|
tmpfs:
|
||||||
@@ -549,7 +549,7 @@ services:
|
|||||||
- watchdog
|
- watchdog
|
||||||
|
|
||||||
dockerapi-mailcow:
|
dockerapi-mailcow:
|
||||||
image: ghcr.io/mailcow/dockerapi:2.10
|
image: ghcr.io/mailcow/dockerapi:2.11
|
||||||
security_opt:
|
security_opt:
|
||||||
- label=disable
|
- label=disable
|
||||||
restart: always
|
restart: always
|
||||||
@@ -569,7 +569,7 @@ services:
|
|||||||
- dockerapi
|
- dockerapi
|
||||||
|
|
||||||
olefy-mailcow:
|
olefy-mailcow:
|
||||||
image: ghcr.io/mailcow/olefy:1.13
|
image: ghcr.io/mailcow/olefy:1.14
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
|
|||||||
+9
-1
@@ -181,11 +181,15 @@ if [[ ${SKIP_BRANCH} != y ]]; then
|
|||||||
echo "Available Branches:"
|
echo "Available Branches:"
|
||||||
echo "- master branch (stable updates) | default, recommended [1]"
|
echo "- master branch (stable updates) | default, recommended [1]"
|
||||||
echo "- nightly branch (unstable updates, testing) | not-production ready [2]"
|
echo "- nightly branch (unstable updates, testing) | not-production ready [2]"
|
||||||
|
echo "- legacy branch (supported until February 2026) | deprecated, security updates only [3]"
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
while [ -z "${MAILCOW_BRANCH}" ]; do
|
while [ -z "${MAILCOW_BRANCH}" ]; do
|
||||||
read -r -p "Choose the Branch with it's number [1/2] " branch
|
read -r -p "Choose the Branch with it's number [1/2/3] " branch
|
||||||
case $branch in
|
case $branch in
|
||||||
|
[3])
|
||||||
|
MAILCOW_BRANCH="legacy"
|
||||||
|
;;
|
||||||
[2])
|
[2])
|
||||||
MAILCOW_BRANCH="nightly"
|
MAILCOW_BRANCH="nightly"
|
||||||
;;
|
;;
|
||||||
@@ -534,6 +538,10 @@ case ${git_branch} in
|
|||||||
mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
|
mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
|
||||||
mailcow_last_git_version=""
|
mailcow_last_git_version=""
|
||||||
;;
|
;;
|
||||||
|
legacy)
|
||||||
|
mailcow_git_version=$(git rev-parse --short $(git rev-parse @{upstream}))
|
||||||
|
mailcow_last_git_version=""
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
mailcow_git_version=$(git rev-parse --short HEAD)
|
mailcow_git_version=$(git rev-parse --short HEAD)
|
||||||
mailcow_last_git_version=""
|
mailcow_last_git_version=""
|
||||||
|
|||||||
@@ -99,11 +99,11 @@ EOF
|
|||||||
|
|
||||||
if [ $? = 0 ]; then
|
if [ $? = 0 ]; then
|
||||||
COMPOSE_COMMAND="docker compose"
|
COMPOSE_COMMAND="docker compose"
|
||||||
echo "DEBUG: Using native docker compose on remote"
|
echo "INFO: Using native docker compose on remote"
|
||||||
|
|
||||||
elif [ $? = 1 ]; then
|
elif [ $? = 1 ]; then
|
||||||
COMPOSE_COMMAND="docker-compose"
|
COMPOSE_COMMAND="docker-compose"
|
||||||
echo "DEBUG: Using standalone docker compose on remote"
|
echo "INFO: Using standalone docker compose on remote"
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "\e[31mCannot find any Docker Compose on remote, exiting...\e[0m"
|
echo -e "\e[31mCannot find any Docker Compose on remote, exiting...\e[0m"
|
||||||
@@ -284,7 +284,7 @@ echo "OK"
|
|||||||
-i "${REMOTE_SSH_KEY}" \
|
-i "${REMOTE_SSH_KEY}" \
|
||||||
${REMOTE_SSH_HOST} \
|
${REMOTE_SSH_HOST} \
|
||||||
-p ${REMOTE_SSH_PORT} \
|
-p ${REMOTE_SSH_PORT} \
|
||||||
${COMPOSE_COMMAND} -f "${SCRIPT_DIR}/../docker-compose.yml" pull --no-parallel --quiet 2>&1 ; then
|
${COMPOSE_COMMAND} -f "${SCRIPT_DIR}/../docker-compose.yml" pull --quiet 2>&1 ; then
|
||||||
>&2 echo -e "\e[31m[ERR]\e[0m - Could not pull images on remote"
|
>&2 echo -e "\e[31m[ERR]\e[0m - Could not pull images on remote"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ remove_obsolete_nginx_ports() {
|
|||||||
detect_docker_compose_command(){
|
detect_docker_compose_command(){
|
||||||
if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then
|
if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then
|
||||||
if docker compose > /dev/null 2>&1; then
|
if docker compose > /dev/null 2>&1; then
|
||||||
if docker compose version --short | grep -e "^2." -e "^v2." > /dev/null 2>&1; then
|
if docker compose version --short | grep -e "^[2-9]\." -e "^v[2-9]\." -e "^[1-9][0-9]\." -e "^v[1-9][0-9]\." > /dev/null 2>&1; then
|
||||||
DOCKER_COMPOSE_VERSION=native
|
DOCKER_COMPOSE_VERSION=native
|
||||||
COMPOSE_COMMAND="docker compose"
|
COMPOSE_COMMAND="docker compose"
|
||||||
echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m"
|
echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m"
|
||||||
@@ -187,12 +187,12 @@ if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then
|
|||||||
echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m"
|
echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m"
|
||||||
else
|
else
|
||||||
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
||||||
echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m"
|
echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
elif docker-compose > /dev/null 2>&1; then
|
elif docker-compose > /dev/null 2>&1; then
|
||||||
if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then
|
if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then
|
||||||
if docker-compose version --short | grep "^2." > /dev/null 2>&1; then
|
if docker-compose version --short | grep -e "^[2-9]\." -e "^[1-9][0-9]\." > /dev/null 2>&1; then
|
||||||
DOCKER_COMPOSE_VERSION=standalone
|
DOCKER_COMPOSE_VERSION=standalone
|
||||||
COMPOSE_COMMAND="docker-compose"
|
COMPOSE_COMMAND="docker-compose"
|
||||||
echo -e "\e[33mFound Docker Compose Standalone.\e[0m"
|
echo -e "\e[33mFound Docker Compose Standalone.\e[0m"
|
||||||
@@ -202,7 +202,7 @@ if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then
|
|||||||
echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m"
|
echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m"
|
||||||
else
|
else
|
||||||
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
||||||
echo -e "\e[31mPlease update/install regarding to this doc site: https://docs.mailcow.email/install/\e[0m"
|
echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -722,9 +722,16 @@ detect_major_update() {
|
|||||||
# Add major versions here
|
# Add major versions here
|
||||||
MAJOR_VERSIONS=(
|
MAJOR_VERSIONS=(
|
||||||
"2025-02"
|
"2025-02"
|
||||||
|
"2025-03"
|
||||||
)
|
)
|
||||||
|
|
||||||
current_version=$(git describe --tags $(git rev-list --tags --max-count=1))
|
current_version=""
|
||||||
|
if [[ -f "${SCRIPT_DIR}/data/web/inc/app_info.inc.php" ]]; then
|
||||||
|
current_version=$(grep 'MAILCOW_GIT_VERSION' ${SCRIPT_DIR}/data/web/inc/app_info.inc.php | sed -E 's/.*MAILCOW_GIT_VERSION="([^"]+)".*/\1/')
|
||||||
|
fi
|
||||||
|
if [[ -z "$current_version" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
release_url="https://github.com/mailcow/mailcow-dockerized/releases/tag"
|
release_url="https://github.com/mailcow/mailcow-dockerized/releases/tag"
|
||||||
|
|
||||||
updates_to_apply=()
|
updates_to_apply=()
|
||||||
@@ -741,8 +748,7 @@ detect_major_update() {
|
|||||||
echo "$update - $release_url/$update"
|
echo "$update - $release_url/$update"
|
||||||
done
|
done
|
||||||
|
|
||||||
echo -e "\n⚠️ Please read the release notes before proceeding.\n"
|
echo -e "\nPlease read the release notes before proceeding."
|
||||||
|
|
||||||
read -p "Do you want to proceed with the update? [y/n] " response
|
read -p "Do you want to proceed with the update? [y/n] " response
|
||||||
if [[ "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
if [[ "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||||
echo "Proceeding with the update..."
|
echo "Proceeding with the update..."
|
||||||
@@ -889,8 +895,12 @@ while (($#)); do
|
|||||||
echo -e "\e[32mRunning in Developer mode...\e[0m"
|
echo -e "\e[32mRunning in Developer mode...\e[0m"
|
||||||
DEV=y
|
DEV=y
|
||||||
;;
|
;;
|
||||||
|
--legacy)
|
||||||
|
CURRENT_BRANCH="$(cd "${SCRIPT_DIR}"; git rev-parse --abbrev-ref HEAD)"
|
||||||
|
NEW_BRANCH="legacy"
|
||||||
|
;;
|
||||||
--help|-h)
|
--help|-h)
|
||||||
echo './update.sh [-c|--check, --check-tags, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -d|--dev, -h|--help]
|
echo './update.sh [-c|--check, --check-tags, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, --legacy, -f|--force, -d|--dev, -h|--help]
|
||||||
|
|
||||||
-c|--check - Check for updates and exit (exit codes => 0: update available, 3: no updates)
|
-c|--check - Check for updates and exit (exit codes => 0: update available, 3: no updates)
|
||||||
--check-tags - Check for newer tags and exit (exit codes => 0: newer tag available, 3: no newer tag)
|
--check-tags - Check for newer tags and exit (exit codes => 0: newer tag available, 3: no newer tag)
|
||||||
@@ -900,7 +910,8 @@ while (($#)); do
|
|||||||
--prefetch - Only prefetch new images and exit (useful to prepare updates)
|
--prefetch - Only prefetch new images and exit (useful to prepare updates)
|
||||||
--skip-start - Do not start mailcow after update
|
--skip-start - Do not start mailcow after update
|
||||||
--skip-ping-check - Skip ICMP Check to public DNS resolvers (Use it only if you'\''ve blocked any ICMP Connections to your mailcow machine)
|
--skip-ping-check - Skip ICMP Check to public DNS resolvers (Use it only if you'\''ve blocked any ICMP Connections to your mailcow machine)
|
||||||
--stable - Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly.
|
--stable - Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly or --legacy.
|
||||||
|
--legacy - Switch your mailcow updates to the legacy branch. The legacy branch will only recieve security updates until February 2026.
|
||||||
-f|--force - Force update, do not ask questions
|
-f|--force - Force update, do not ask questions
|
||||||
-d|--dev - Enables Developer Mode (No Checkout of update.sh for tests)
|
-d|--dev - Enables Developer Mode (No Checkout of update.sh for tests)
|
||||||
'
|
'
|
||||||
@@ -1306,6 +1317,11 @@ if ! [ "$NEW_BRANCH" ]; then
|
|||||||
sleep 1
|
sleep 1
|
||||||
echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m"
|
echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m"
|
||||||
|
|
||||||
|
elif [ "${BRANCH}" == "legacy" ]; then
|
||||||
|
echo -e "\e[31mYou are receiving legacy updates. The legacy branch will only recieve security updates until February 2026.\e[0m"
|
||||||
|
sleep 1
|
||||||
|
echo -e "\e[33mTo change that run the update.sh Script one time with the --stable parameter to switch to stable builds.\e[0m"
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "\e[33mYou are receiving updates from an unsupported branch.\e[0m"
|
echo -e "\e[33mYou are receiving updates from an unsupported branch.\e[0m"
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -1368,6 +1384,29 @@ elif [ "$NEW_BRANCH" == "nightly" ] && [ "$CURRENT_BRANCH" != "nightly" ]; then
|
|||||||
fi
|
fi
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git checkout -f "${BRANCH}"
|
git checkout -f "${BRANCH}"
|
||||||
|
elif [ "$NEW_BRANCH" == "legacy" ] && [ "$CURRENT_BRANCH" != "legacy" ]; then
|
||||||
|
echo -e "\e[33mYou are about to switch your mailcow Updates to the legacy branch.\e[0m"
|
||||||
|
sleep 1
|
||||||
|
echo -e "\e[33mBefore you do: Please take a backup of all components to ensure that no Data is lost...\e[0m"
|
||||||
|
sleep 1
|
||||||
|
echo -e "\e[31mWARNING: A switch to stable or nightly is possible any time.\e[0m"
|
||||||
|
read -r -p "Are you sure you want to continue upgrading to the legacy branch? [y/N] " response
|
||||||
|
if [[ ! "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||||
|
echo "OK. If you prepared yourself for that please run the update.sh Script with the --legacy parameter again to trigger this process here."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
BRANCH=$NEW_BRANCH
|
||||||
|
DIFF_DIRECTORY=update_diffs
|
||||||
|
DIFF_FILE=${DIFF_DIRECTORY}/diff_before_upgrade_to_legacy_$(date +"%Y-%m-%d-%H-%M-%S")
|
||||||
|
mv diff_before_upgrade* ${DIFF_DIRECTORY}/ 2> /dev/null
|
||||||
|
if ! git diff-index --quiet HEAD; then
|
||||||
|
echo -e "\e[32mSaving diff to ${DIFF_FILE}...\e[0m"
|
||||||
|
mkdir -p ${DIFF_DIRECTORY}
|
||||||
|
git diff "${BRANCH}" --stat > "${DIFF_FILE}"
|
||||||
|
git diff "${BRANCH}" >> "${DIFF_FILE}"
|
||||||
|
fi
|
||||||
|
git fetch origin
|
||||||
|
git checkout -f "${BRANCH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! "$DEV" ]; then
|
if [ ! "$DEV" ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user