mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2024-12-21 01:49:22 +02:00
Merge remote-tracking branch 'origin/staging' into nightly
This commit is contained in:
commit
a41bb55c83
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@ -1 +1,2 @@
|
||||
github: mailcow
|
||||
custom: ["https://www.servercow.de/mailcow?lang=en#sal"]
|
||||
|
@ -4,9 +4,9 @@ exec 5>&1
|
||||
|
||||
# Do not attempt to write to slave
|
||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
||||
export REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}"
|
||||
export REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
|
||||
else
|
||||
export REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
||||
export REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||
fi
|
||||
|
||||
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
||||
|
@ -124,7 +124,7 @@ case "$SUCCESS" in
|
||||
;;
|
||||
*) # non-zero is non-fun
|
||||
log_f "Failed to obtain certificate ${CERT} for domains '${CERT_DOMAINS[*]}'"
|
||||
redis-cli -h redis SET ACME_FAIL_TIME "$(date +%s)"
|
||||
redis-cli -h redis -a ${REDISPASS} --no-auth-warning SET ACME_FAIL_TIME "$(date +%s)"
|
||||
exit 100${SUCCESS}
|
||||
;;
|
||||
esac
|
||||
|
@ -34,9 +34,9 @@ async def lifespan(app: FastAPI):
|
||||
|
||||
# Init redis client
|
||||
if os.environ['REDIS_SLAVEOF_IP'] != "":
|
||||
redis_client = redis = await aioredis.from_url(f"redis://{os.environ['REDIS_SLAVEOF_IP']}:{os.environ['REDIS_SLAVEOF_PORT']}/0")
|
||||
redis_client = redis = await aioredis.from_url(f"redis://{os.environ['REDIS_SLAVEOF_IP']}:{os.environ['REDIS_SLAVEOF_PORT']}/0", password=os.environ['REDISPASS'])
|
||||
else:
|
||||
redis_client = redis = await aioredis.from_url("redis://redis-mailcow:6379/0")
|
||||
redis_client = redis = await aioredis.from_url("redis://redis-mailcow:6379/0", password=os.environ['REDISPASS'])
|
||||
|
||||
# Init docker clients
|
||||
sync_docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
source /source_env.sh
|
||||
|
||||
MAX_AGE=$(redis-cli --raw -h redis-mailcow GET Q_MAX_AGE)
|
||||
MAX_AGE=$(redis-cli --raw -h redis-mailcow -a ${REDISPASS} --no-auth-warning GET Q_MAX_AGE)
|
||||
|
||||
if [[ -z ${MAX_AGE} ]]; then
|
||||
echo "Max age for quarantine items not defined"
|
||||
|
@ -14,9 +14,9 @@ done
|
||||
|
||||
# Do not attempt to write to slave
|
||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}"
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
|
||||
else
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||
fi
|
||||
|
||||
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
||||
|
@ -31,7 +31,7 @@ try:
|
||||
|
||||
while True:
|
||||
try:
|
||||
r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0)
|
||||
r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0, password=os.environ['REDISPASS'])
|
||||
r.ping()
|
||||
except Exception as ex:
|
||||
print('%s - trying again...' % (ex))
|
||||
|
@ -23,7 +23,7 @@ else:
|
||||
|
||||
while True:
|
||||
try:
|
||||
r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0)
|
||||
r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0, password=os.environ['REDISPASS'])
|
||||
r.ping()
|
||||
except Exception as ex:
|
||||
print('%s - trying again...' % (ex))
|
||||
|
@ -4,9 +4,9 @@ source /source_env.sh
|
||||
|
||||
# Do not attempt to write to slave
|
||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}"
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
|
||||
else
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||
fi
|
||||
|
||||
# Is replication active?
|
||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
||||
host("`REDIS_SLAVEOF_IP`")
|
||||
persist-name("redis1")
|
||||
port(`REDIS_SLAVEOF_PORT`)
|
||||
auth("`REDISPASS`")
|
||||
command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
||||
);
|
||||
};
|
||||
@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
|
||||
host("`REDIS_SLAVEOF_IP`")
|
||||
persist-name("redis2")
|
||||
port(`REDIS_SLAVEOF_PORT`)
|
||||
auth("`REDISPASS`")
|
||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||
);
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
||||
host("redis-mailcow")
|
||||
persist-name("redis1")
|
||||
port(6379)
|
||||
auth("`REDISPASS`")
|
||||
command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
||||
);
|
||||
};
|
||||
@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
|
||||
host("redis-mailcow")
|
||||
persist-name("redis2")
|
||||
port(6379)
|
||||
auth("`REDISPASS`")
|
||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||
);
|
||||
};
|
||||
|
@ -10,9 +10,9 @@ catch_non_zero() {
|
||||
source /source_env.sh
|
||||
# Do not attempt to write to slave
|
||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}"
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
|
||||
else
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||
fi
|
||||
catch_non_zero "${REDIS_CMDLINE} LTRIM ACME_LOG 0 ${LOG_LINES}"
|
||||
catch_non_zero "${REDIS_CMDLINE} LTRIM POSTFIX_MAILLOG 0 ${LOG_LINES}"
|
||||
|
@ -106,7 +106,7 @@ def get_ip(address):
|
||||
ip = ip.ipv4_mapped
|
||||
if ip.is_private or ip.is_loopback:
|
||||
return False
|
||||
|
||||
|
||||
return ip
|
||||
|
||||
def ban(address):
|
||||
@ -434,9 +434,9 @@ if __name__ == '__main__':
|
||||
redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '')
|
||||
redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '')
|
||||
if "".__eq__(redis_slaveof_ip):
|
||||
r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0)
|
||||
r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0, password=os.environ['REDISPASS'])
|
||||
else:
|
||||
r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0)
|
||||
r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0, password=os.environ['REDISPASS'])
|
||||
r.ping()
|
||||
pubsub = r.pubsub()
|
||||
except Exception as ex:
|
||||
@ -452,7 +452,7 @@ if __name__ == '__main__':
|
||||
# clear bans in redis
|
||||
r.delete('F2B_ACTIVE_BANS')
|
||||
r.delete('F2B_PERM_BANS')
|
||||
|
||||
|
||||
refreshF2boptions()
|
||||
|
||||
watch_thread = Thread(target=watch)
|
||||
|
18
data/Dockerfiles/nginx/Dockerfile
Normal file
18
data/Dockerfiles/nginx/Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM nginx:alpine
|
||||
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ENV PIP_BREAK_SYSTEM_PACKAGES=1
|
||||
|
||||
RUN apk add --no-cache nginx \
|
||||
python3 \
|
||||
py3-pip && \
|
||||
pip install --upgrade pip && \
|
||||
pip install Jinja2
|
||||
|
||||
RUN mkdir -p /etc/nginx/includes
|
||||
|
||||
COPY ./bootstrap.py /
|
||||
COPY ./docker-entrypoint.sh /
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
76
data/Dockerfiles/nginx/bootstrap.py
Normal file
76
data/Dockerfiles/nginx/bootstrap.py
Normal file
@ -0,0 +1,76 @@
|
||||
import os
|
||||
import subprocess
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
|
||||
def sites_default_conf(env, template_vars):
|
||||
config_name = "sites-default.conf"
|
||||
template = env.get_template(f"{config_name}.j2")
|
||||
config = template.render(template_vars)
|
||||
|
||||
with open(f"/etc/nginx/includes/{config_name}", "w") as f:
|
||||
f.write(config)
|
||||
|
||||
def nginx_conf(env, template_vars):
|
||||
config_name = "nginx.conf"
|
||||
template = env.get_template(f"{config_name}.j2")
|
||||
config = template.render(template_vars)
|
||||
|
||||
with open(f"/etc/nginx/{config_name}", "w") as f:
|
||||
f.write(config)
|
||||
|
||||
def prepare_template_vars():
|
||||
template_vars = {
|
||||
'IPV4_NETWORK': os.getenv("IPV4_NETWORK", "172.22.1"),
|
||||
'TRUSTED_NETWORK': os.getenv("TRUSTED_NETWORK", False),
|
||||
'SKIP_RSPAMD': os.getenv("SKIP_RSPAMD", "n").lower() in ("y", "yes"),
|
||||
'SKIP_SOGO': os.getenv("SKIP_SOGO", "n").lower() in ("y", "yes"),
|
||||
'NGINX_USE_PROXY_PROTOCOL': os.getenv("NGINX_USE_PROXY_PROTOCOL", "n").lower() in ("y", "yes"),
|
||||
'MAILCOW_HOSTNAME': os.getenv("MAILCOW_HOSTNAME", ""),
|
||||
'ADDITIONAL_SERVER_NAMES': os.getenv("ADDITIONAL_SERVER_NAMES", "").replace(',', ' '),
|
||||
'HTTP_PORT': os.getenv("HTTP_PORT", "80"),
|
||||
'HTTPS_PORT': os.getenv("HTTPS_PORT", "443"),
|
||||
'SOGOHOST': os.getenv("SOGOHOST", "sogo-mailcow"),
|
||||
'RSPAMDHOST': os.getenv("RSPAMDHOST", "rspamd-mailcow"),
|
||||
'PHPFPMHOST': os.getenv("PHPFPMHOST", "php-fpm-mailcow"),
|
||||
}
|
||||
|
||||
ssl_dir = '/etc/ssl/mail/'
|
||||
template_vars['valid_cert_dirs'] = []
|
||||
for d in os.listdir(ssl_dir):
|
||||
full_path = os.path.join(ssl_dir, d)
|
||||
if not os.path.isdir(full_path):
|
||||
continue
|
||||
|
||||
cert_path = os.path.join(full_path, 'cert.pem')
|
||||
key_path = os.path.join(full_path, 'key.pem')
|
||||
domains_path = os.path.join(full_path, 'domains')
|
||||
|
||||
if os.path.isfile(cert_path) and os.path.isfile(key_path) and os.path.isfile(domains_path):
|
||||
with open(domains_path, 'r') as file:
|
||||
domains = file.read().strip()
|
||||
domains_list = domains.split()
|
||||
if domains_list and template_vars["MAILCOW_HOSTNAME"] not in domains_list:
|
||||
template_vars['valid_cert_dirs'].append({
|
||||
'cert_path': full_path + '/',
|
||||
'domains': domains
|
||||
})
|
||||
|
||||
return template_vars
|
||||
|
||||
def main():
|
||||
env = Environment(loader=FileSystemLoader('./etc/nginx/conf.d'))
|
||||
|
||||
# Render config
|
||||
print("Render config")
|
||||
template_vars = prepare_template_vars()
|
||||
sites_default_conf(env, template_vars)
|
||||
nginx_conf(env, template_vars)
|
||||
|
||||
# Validate config
|
||||
print("Validate config")
|
||||
subprocess.run(["nginx", "-qt"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
26
data/Dockerfiles/nginx/docker-entrypoint.sh
Executable file
26
data/Dockerfiles/nginx/docker-entrypoint.sh
Executable file
@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
|
||||
until ping ${REDISHOST} -c1 > /dev/null; do
|
||||
echo "Waiting for Redis..."
|
||||
sleep 1
|
||||
done
|
||||
until ping ${PHPFPMHOST} -c1 > /dev/null; do
|
||||
echo "Waiting for PHP..."
|
||||
sleep 1
|
||||
done
|
||||
if printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
|
||||
until ping ${SOGOHOST} -c1 > /dev/null; do
|
||||
echo "Waiting for SOGo..."
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
if printf "%s\n" "${SKIP_RSPAMD}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
|
||||
until ping ${RSPAMDHOST} -c1 > /dev/null; do
|
||||
echo "Waiting for Rspamd..."
|
||||
sleep 1
|
||||
done
|
||||
fi
|
||||
|
||||
python3 /bootstrap.py
|
||||
|
||||
exec "$@"
|
@ -16,7 +16,7 @@ else
|
||||
REDIS_HOST="redis"
|
||||
REDIS_PORT="6379"
|
||||
fi
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT}"
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT} -a ${REDISPASS} --no-auth-warning"
|
||||
|
||||
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
||||
echo "Waiting for Redis..."
|
||||
@ -26,7 +26,7 @@ done
|
||||
# Set redis session store
|
||||
echo -n '
|
||||
session.save_handler = redis
|
||||
session.save_path = "tcp://'${REDIS_HOST}':'${REDIS_PORT}'"
|
||||
session.save_path = "tcp://'${REDIS_HOST}':'${REDIS_PORT}'?auth='${REDISPASS}'"
|
||||
' > /usr/local/etc/php/conf.d/session_store.ini
|
||||
|
||||
# Check mysql_upgrade (master and slave)
|
||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
||||
host("`REDIS_SLAVEOF_IP`")
|
||||
persist-name("redis1")
|
||||
port(`REDIS_SLAVEOF_PORT`)
|
||||
auth("`REDISPASS`")
|
||||
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
||||
);
|
||||
};
|
||||
@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
|
||||
host("`REDIS_SLAVEOF_IP`")
|
||||
persist-name("redis2")
|
||||
port(`REDIS_SLAVEOF_PORT`)
|
||||
auth("`REDISPASS`")
|
||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||
);
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
||||
host("redis-mailcow")
|
||||
persist-name("redis1")
|
||||
port(6379)
|
||||
auth("`REDISPASS`")
|
||||
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
||||
);
|
||||
};
|
||||
@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
|
||||
host("redis-mailcow")
|
||||
persist-name("redis2")
|
||||
port(6379)
|
||||
auth("`REDISPASS`")
|
||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||
);
|
||||
};
|
||||
|
@ -56,27 +56,29 @@ if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
||||
cat <<EOF > /etc/rspamd/local.d/redis.conf
|
||||
read_servers = "redis:6379";
|
||||
write_servers = "${REDIS_SLAVEOF_IP}:${REDIS_SLAVEOF_PORT}";
|
||||
password = "${REDISPASS}";
|
||||
timeout = 10;
|
||||
EOF
|
||||
until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do
|
||||
until [[ $(redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning PING) == "PONG" ]]; do
|
||||
echo "Waiting for Redis @redis-mailcow..."
|
||||
sleep 2
|
||||
done
|
||||
until [[ $(redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} PING) == "PONG" ]]; do
|
||||
until [[ $(redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning PING) == "PONG" ]]; do
|
||||
echo "Waiting for Redis @${REDIS_SLAVEOF_IP}..."
|
||||
sleep 2
|
||||
done
|
||||
redis-cli -h redis-mailcow SLAVEOF ${REDIS_SLAVEOF_IP} ${REDIS_SLAVEOF_PORT}
|
||||
redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning SLAVEOF ${REDIS_SLAVEOF_IP} ${REDIS_SLAVEOF_PORT}
|
||||
else
|
||||
cat <<EOF > /etc/rspamd/local.d/redis.conf
|
||||
servers = "redis:6379";
|
||||
password = "${REDISPASS}";
|
||||
timeout = 10;
|
||||
EOF
|
||||
until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do
|
||||
until [[ $(redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning PING) == "PONG" ]]; do
|
||||
echo "Waiting for Redis slave..."
|
||||
sleep 2
|
||||
done
|
||||
redis-cli -h redis-mailcow SLAVEOF NO ONE
|
||||
redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning SLAVEOF NO ONE
|
||||
fi
|
||||
|
||||
# Provide additional lua modules
|
||||
|
@ -22,6 +22,7 @@ destination d_redis_ui_log {
|
||||
host("`REDIS_SLAVEOF_IP`")
|
||||
persist-name("redis1")
|
||||
port(`REDIS_SLAVEOF_PORT`)
|
||||
auth("`REDISPASS`")
|
||||
command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
||||
);
|
||||
};
|
||||
@ -30,6 +31,7 @@ destination d_redis_f2b_channel {
|
||||
host("`REDIS_SLAVEOF_IP`")
|
||||
persist-name("redis2")
|
||||
port(`REDIS_SLAVEOF_PORT`)
|
||||
auth("`REDISPASS`")
|
||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||
);
|
||||
};
|
||||
|
@ -22,6 +22,7 @@ destination d_redis_ui_log {
|
||||
host("redis-mailcow")
|
||||
persist-name("redis1")
|
||||
port(6379)
|
||||
auth("`REDISPASS`")
|
||||
command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
||||
);
|
||||
};
|
||||
@ -30,6 +31,7 @@ destination d_redis_f2b_channel {
|
||||
host("redis-mailcow")
|
||||
persist-name("redis2")
|
||||
port(6379)
|
||||
auth("`REDISPASS`")
|
||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||
);
|
||||
};
|
||||
|
@ -40,9 +40,9 @@ done
|
||||
|
||||
# Do not attempt to write to slave
|
||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}"
|
||||
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
|
||||
else
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
||||
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||
fi
|
||||
|
||||
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
||||
@ -330,7 +330,7 @@ redis_checks() {
|
||||
touch /tmp/redis-mailcow; echo "$(tail -50 /tmp/redis-mailcow)" > /tmp/redis-mailcow
|
||||
host_ip=$(get_container_ip redis-mailcow)
|
||||
err_c_cur=${err_count}
|
||||
/usr/lib/nagios/plugins/check_tcp -4 -H redis-mailcow -p 6379 -E -s "PING\n" -q "QUIT" -e "PONG" 2>> /tmp/redis-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
/usr/lib/nagios/plugins/check_tcp -4 -H redis-mailcow -p 6379 -E -s "AUTH ${REDISPASS}\nPING\n" -q "QUIT" -e "PONG" 2>> /tmp/redis-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
|
||||
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
|
||||
progress "Redis" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c}
|
||||
@ -503,12 +503,12 @@ dovecot_repl_checks() {
|
||||
err_count=0
|
||||
diff_c=0
|
||||
THRESHOLD=${DOVECOT_REPL_THRESHOLD}
|
||||
D_REPL_STATUS=$(redis-cli -h redis -r GET DOVECOT_REPL_HEALTH)
|
||||
D_REPL_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning -r GET DOVECOT_REPL_HEALTH)
|
||||
# Reduce error count by 2 after restarting an unhealthy container
|
||||
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
||||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||
err_c_cur=${err_count}
|
||||
D_REPL_STATUS=$(redis-cli --raw -h redis GET DOVECOT_REPL_HEALTH)
|
||||
D_REPL_STATUS=$(redis-cli --raw -h redis -a ${REDISPASS} --no-auth-warning GET DOVECOT_REPL_HEALTH)
|
||||
if [[ "${D_REPL_STATUS}" != "1" ]]; then
|
||||
err_count=$(( ${err_count} + 1 ))
|
||||
fi
|
||||
@ -578,19 +578,19 @@ ratelimit_checks() {
|
||||
err_count=0
|
||||
diff_c=0
|
||||
THRESHOLD=${RATELIMIT_THRESHOLD}
|
||||
RL_LOG_STATUS=$(redis-cli -h redis LRANGE RL_LOG 0 0 | jq .qid)
|
||||
RL_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning LRANGE RL_LOG 0 0 | jq .qid)
|
||||
# Reduce error count by 2 after restarting an unhealthy container
|
||||
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
||||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||
err_c_cur=${err_count}
|
||||
RL_LOG_STATUS_PREV=${RL_LOG_STATUS}
|
||||
RL_LOG_STATUS=$(redis-cli -h redis LRANGE RL_LOG 0 0 | jq .qid)
|
||||
RL_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning LRANGE RL_LOG 0 0 | jq .qid)
|
||||
if [[ ${RL_LOG_STATUS_PREV} != ${RL_LOG_STATUS} ]]; then
|
||||
err_count=$(( ${err_count} + 1 ))
|
||||
echo 'Last 10 applied ratelimits (may overlap with previous reports).' > /tmp/ratelimit
|
||||
echo 'Full ratelimit buckets can be emptied by deleting the ratelimit hash from within mailcow UI (see /debug -> Protocols -> Ratelimit):' >> /tmp/ratelimit
|
||||
echo >> /tmp/ratelimit
|
||||
redis-cli --raw -h redis LRANGE RL_LOG 0 10 | jq . >> /tmp/ratelimit
|
||||
redis-cli --raw -h redis -a ${REDISPASS} --no-auth-warning LRANGE RL_LOG 0 10 | jq . >> /tmp/ratelimit
|
||||
fi
|
||||
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
|
||||
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
|
||||
@ -673,7 +673,7 @@ acme_checks() {
|
||||
err_count=0
|
||||
diff_c=0
|
||||
THRESHOLD=${ACME_THRESHOLD}
|
||||
ACME_LOG_STATUS=$(redis-cli -h redis GET ACME_FAIL_TIME)
|
||||
ACME_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning GET ACME_FAIL_TIME)
|
||||
if [[ -z "${ACME_LOG_STATUS}" ]]; then
|
||||
${REDIS_CMDLINE} SET ACME_FAIL_TIME 0
|
||||
ACME_LOG_STATUS=0
|
||||
@ -685,7 +685,7 @@ acme_checks() {
|
||||
ACME_LOG_STATUS_PREV=${ACME_LOG_STATUS}
|
||||
ACME_LC=0
|
||||
until [[ ! -z ${ACME_LOG_STATUS} ]] || [ ${ACME_LC} -ge 3 ]; do
|
||||
ACME_LOG_STATUS=$(redis-cli -h redis GET ACME_FAIL_TIME 2> /dev/null)
|
||||
ACME_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning GET ACME_FAIL_TIME 2> /dev/null)
|
||||
sleep 3
|
||||
ACME_LC=$((ACME_LC+1))
|
||||
done
|
||||
|
@ -20,7 +20,7 @@ thread_cache_size = 8
|
||||
query_cache_type = 0
|
||||
query_cache_size = 0
|
||||
max_heap_table_size = 48M
|
||||
thread_stack = 128K
|
||||
thread_stack = 192K
|
||||
skip-host-cache
|
||||
skip-name-resolve
|
||||
log-warnings = 0
|
||||
|
@ -1,3 +0,0 @@
|
||||
map_hash_max_size 256;
|
||||
map_hash_bucket_size 256;
|
||||
|
@ -1,19 +0,0 @@
|
||||
server {
|
||||
listen 8081;
|
||||
listen [::]:8081;
|
||||
index index.php index.html;
|
||||
server_name _;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /dynmaps;
|
||||
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9001;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
}
|
@ -1,242 +0,0 @@
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
charset utf-8;
|
||||
override_charset on;
|
||||
|
||||
server_tokens off;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
|
||||
ssl_ecdh_curve X25519:X448:secp384r1:secp256k1;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_tickets off;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=15768000;";
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Robots-Tag none;
|
||||
add_header X-Download-Options noopen;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
add_header Referrer-Policy strict-origin;
|
||||
|
||||
index index.php index.html;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
|
||||
gzip_vary on;
|
||||
gzip_proxied off;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_min_length 256;
|
||||
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
|
||||
|
||||
location ~ ^/(fonts|js|css|img)/ {
|
||||
expires max;
|
||||
add_header Cache-Control public;
|
||||
}
|
||||
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
absolute_redirect off;
|
||||
root /web;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ @strip-ext;
|
||||
}
|
||||
|
||||
location /qhandler {
|
||||
rewrite ^/qhandler/(.*)/(.*) /qhandler.php?action=$1&hash=$2;
|
||||
}
|
||||
|
||||
location /edit {
|
||||
rewrite ^/edit/(.*)/(.*) /edit.php?$1=$2;
|
||||
}
|
||||
|
||||
location @strip-ext {
|
||||
rewrite ^(.*)$ $1.php last;
|
||||
}
|
||||
|
||||
location ~ ^/api/v1/(.*)$ {
|
||||
try_files $uri $uri/ /json_api.php?query=$1&$args;
|
||||
}
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
default_type "text/plain";
|
||||
}
|
||||
|
||||
# If behind reverse proxy, forwards the correct IP
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
set_real_ip_from fc00::/7;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
rewrite ^/.well-known/caldav$ /SOGo/dav/ permanent;
|
||||
rewrite ^/.well-known/carddav$ /SOGo/dav/ permanent;
|
||||
|
||||
location ^~ /principals {
|
||||
return 301 /SOGo/dav;
|
||||
}
|
||||
|
||||
location ^~ /inc/lib/ {
|
||||
deny all;
|
||||
return 403;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9002;
|
||||
fastcgi_index index.php;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_read_timeout 3600;
|
||||
fastcgi_send_timeout 3600;
|
||||
}
|
||||
|
||||
location /rspamd/ {
|
||||
location /rspamd/auth {
|
||||
# proxy_pass is not inherited
|
||||
proxy_pass http://rspamd:11334/auth;
|
||||
proxy_intercept_errors on;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_redirect off;
|
||||
error_page 401 /_rspamderror.php;
|
||||
}
|
||||
proxy_pass http://rspamd:11334/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location ~* ^/Autodiscover/Autodiscover.xml {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9002;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
try_files /autodiscover.php =404;
|
||||
}
|
||||
|
||||
location ~* ^/Autodiscover/Autodiscover.json {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9002;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
try_files /autodiscover-json.php =404;
|
||||
}
|
||||
|
||||
location ~ /(?:m|M)ail/(?:c|C)onfig-v1.1.xml {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9002;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
try_files /autoconfig.php =404;
|
||||
}
|
||||
|
||||
location /sogo-auth-verify {
|
||||
internal;
|
||||
proxy_set_header X-Original-URI $request_uri;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_pass http://127.0.0.1:65510/sogo-auth;
|
||||
proxy_pass_request_body off;
|
||||
}
|
||||
|
||||
location ^~ /Microsoft-Server-ActiveSync {
|
||||
include /etc/nginx/conf.d/includes/sogo_proxy_auth.conf;
|
||||
include /etc/nginx/conf.d/sogo_eas.active;
|
||||
proxy_connect_timeout 75;
|
||||
proxy_send_timeout 3600;
|
||||
proxy_read_timeout 3600;
|
||||
proxy_buffer_size 128k;
|
||||
proxy_buffers 64 512k;
|
||||
proxy_busy_buffers_size 512k;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
client_body_buffer_size 512k;
|
||||
client_max_body_size 0;
|
||||
}
|
||||
|
||||
location ^~ /SOGo {
|
||||
location ~* ^/SOGo/so/.*\.(xml|js|html|xhtml)$ {
|
||||
include /etc/nginx/conf.d/includes/sogo_proxy_auth.conf;
|
||||
include /etc/nginx/conf.d/sogo.active;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
|
||||
proxy_set_header x-webobjects-remote-host $remote_addr;
|
||||
proxy_set_header x-webobjects-server-name $server_name;
|
||||
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
|
||||
proxy_set_header x-webobjects-server-port $server_port;
|
||||
proxy_hide_header Content-Type;
|
||||
add_header Content-Type text/plain;
|
||||
break;
|
||||
}
|
||||
include /etc/nginx/conf.d/includes/sogo_proxy_auth.conf;
|
||||
include /etc/nginx/conf.d/sogo.active;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
|
||||
proxy_set_header x-webobjects-remote-host $remote_addr;
|
||||
proxy_set_header x-webobjects-server-name $server_name;
|
||||
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
|
||||
proxy_set_header x-webobjects-server-port $server_port;
|
||||
proxy_buffer_size 128k;
|
||||
proxy_buffers 64 512k;
|
||||
proxy_busy_buffers_size 512k;
|
||||
proxy_send_timeout 3600;
|
||||
proxy_read_timeout 3600;
|
||||
client_body_buffer_size 128k;
|
||||
client_max_body_size 0;
|
||||
break;
|
||||
}
|
||||
|
||||
location ~* /sogo$ {
|
||||
return 301 $client_req_scheme://$http_host/SOGo;
|
||||
}
|
||||
|
||||
location /SOGo.woa/WebServerResources/ {
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location /.woa/WebServerResources/ {
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location /SOGo/WebServerResources/ {
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
|
||||
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/site.*.custom;
|
||||
|
||||
error_page 502 @awaitingupstream;
|
||||
|
||||
location @awaitingupstream {
|
||||
rewrite ^(.*)$ /_status.502.html break;
|
||||
}
|
||||
|
||||
location ~ ^/cache/(.*)$ {
|
||||
try_files $uri $uri/ /resource.php?file=$1;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
auth_request /sogo-auth-verify;
|
||||
auth_request_set $user $upstream_http_x_user;
|
||||
auth_request_set $auth $upstream_http_x_auth;
|
||||
auth_request_set $auth_type $upstream_http_x_auth_type;
|
||||
proxy_set_header x-webobjects-remote-user "$user";
|
||||
proxy_set_header Authorization "$auth";
|
||||
proxy_set_header x-webobjects-auth-type "$auth_type";
|
||||
|
@ -1,23 +0,0 @@
|
||||
server {
|
||||
listen 9082 ssl http2;
|
||||
|
||||
ssl_certificate /etc/ssl/mail/cert.pem;
|
||||
ssl_certificate_key /etc/ssl/mail/key.pem;
|
||||
|
||||
index mailcowauth.php;
|
||||
server_name _;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /mailcowauth;
|
||||
client_max_body_size 10M;
|
||||
|
||||
location ~ \.php$ {
|
||||
client_max_body_size 10M;
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9001;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
server {
|
||||
listen 9081;
|
||||
index index.php index.html;
|
||||
server_name _;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /meta_exporter;
|
||||
client_max_body_size 10M;
|
||||
location ~ \.php$ {
|
||||
client_max_body_size 10M;
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9001;
|
||||
fastcgi_index pipe.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
}
|
142
data/conf/nginx/nginx.conf.j2
Normal file
142
data/conf/nginx/nginx.conf.j2
Normal file
@ -0,0 +1,142 @@
|
||||
user nginx;
|
||||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log notice;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
#gzip on;
|
||||
|
||||
# map-size.conf:
|
||||
map_hash_max_size 256;
|
||||
map_hash_bucket_size 256;
|
||||
|
||||
# site.conf:
|
||||
proxy_cache_path /tmp levels=1:2 keys_zone=sogo:10m inactive=24h max_size=1g;
|
||||
server_names_hash_max_size 512;
|
||||
server_names_hash_bucket_size 128;
|
||||
|
||||
map $http_x_forwarded_proto $client_req_scheme {
|
||||
default $scheme;
|
||||
https https;
|
||||
}
|
||||
|
||||
# Default
|
||||
server {
|
||||
listen 127.0.0.1:65510; # sogo-auth verify internal
|
||||
listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
|
||||
listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
|
||||
listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
|
||||
listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
|
||||
http2 on;
|
||||
|
||||
ssl_certificate /etc/ssl/mail/cert.pem;
|
||||
ssl_certificate_key /etc/ssl/mail/key.pem;
|
||||
|
||||
server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.* {{ ADDITIONAL_SERVER_NAMES }};
|
||||
|
||||
include /etc/nginx/includes/sites-default.conf;
|
||||
}
|
||||
|
||||
# rspamd dynmaps:
|
||||
server {
|
||||
listen 8081;
|
||||
listen [::]:8081;
|
||||
index index.php index.html;
|
||||
server_name _;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /dynmaps;
|
||||
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass {{ PHPFPMHOST }}:9001;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
}
|
||||
|
||||
# rspamd meta_exporter:
|
||||
server {
|
||||
listen 9081;
|
||||
index index.php index.html;
|
||||
server_name _;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /meta_exporter;
|
||||
client_max_body_size 10M;
|
||||
location ~ \.php$ {
|
||||
client_max_body_size 10M;
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass {{ PHPFPMHOST }}:9001;
|
||||
fastcgi_index pipe.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 9082 ssl http2;
|
||||
|
||||
ssl_certificate /etc/ssl/mail/cert.pem;
|
||||
ssl_certificate_key /etc/ssl/mail/key.pem;
|
||||
|
||||
index mailcowauth.php;
|
||||
server_name _;
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
root /mailcowauth;
|
||||
client_max_body_size 10M;
|
||||
location ~ \.php$ {
|
||||
client_max_body_size 10M;
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass phpfpm:9001;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
}
|
||||
|
||||
{% for cert in valid_cert_dirs %}
|
||||
server {
|
||||
listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
|
||||
listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
|
||||
listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
|
||||
listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
|
||||
http2 on;
|
||||
|
||||
ssl_certificate {{ cert.cert_path }}cert.pem;
|
||||
ssl_certificate_key {{ cert.cert_path }}key.pem;
|
||||
|
||||
server_name {{ cert.domains }};
|
||||
|
||||
include /etc/nginx/includes/sites-default.conf;
|
||||
}
|
||||
{% endfor %}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
proxy_cache_path /tmp levels=1:2 keys_zone=sogo:10m inactive=24h max_size=1g;
|
||||
server_names_hash_max_size 512;
|
||||
server_names_hash_bucket_size 128;
|
||||
|
||||
map $http_x_forwarded_proto $client_req_scheme {
|
||||
default $scheme;
|
||||
https https;
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/sites.active;
|
276
data/conf/nginx/sites-default.conf.j2
Normal file
276
data/conf/nginx/sites-default.conf.j2
Normal file
@ -0,0 +1,276 @@
|
||||
include /etc/nginx/mime.types;
|
||||
charset utf-8;
|
||||
override_charset on;
|
||||
|
||||
server_tokens off;
|
||||
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_prefer_server_ciphers on;
|
||||
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
|
||||
ssl_ecdh_curve X25519:X448:secp384r1:secp256k1;
|
||||
ssl_session_cache shared:SSL:50m;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_tickets off;
|
||||
|
||||
add_header Strict-Transport-Security "max-age=15768000;";
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
add_header X-Robots-Tag none;
|
||||
add_header X-Download-Options noopen;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Permitted-Cross-Domain-Policies none;
|
||||
add_header Referrer-Policy strict-origin;
|
||||
|
||||
index index.php index.html;
|
||||
|
||||
client_max_body_size 0;
|
||||
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
|
||||
gzip_vary on;
|
||||
gzip_proxied off;
|
||||
gzip_comp_level 6;
|
||||
gzip_buffers 16 8k;
|
||||
gzip_http_version 1.1;
|
||||
gzip_min_length 256;
|
||||
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
|
||||
|
||||
location ~ ^/(fonts|js|css|img)/ {
|
||||
expires max;
|
||||
add_header Cache-Control public;
|
||||
}
|
||||
|
||||
error_log /var/log/nginx/error.log;
|
||||
access_log /var/log/nginx/access.log;
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
absolute_redirect off;
|
||||
root /web;
|
||||
|
||||
# If behind reverse proxy, forwards the correct IP
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
set_real_ip_from fc00::/7;
|
||||
{% if not TRUSTED_NETWORK %}
|
||||
real_ip_header X-Forwarded-For;
|
||||
{% else %}
|
||||
set_real_ip_from {{ TRUSTED_NETWORK }};
|
||||
real_ip_header proxy_protocol;
|
||||
{% endif %}
|
||||
real_ip_recursive on;
|
||||
|
||||
|
||||
location @strip-ext {
|
||||
rewrite ^(.*)$ $1.php last;
|
||||
}
|
||||
|
||||
location ^~ /inc/lib/ {
|
||||
deny all;
|
||||
return 403;
|
||||
}
|
||||
|
||||
location ^~ /.well-known/acme-challenge/ {
|
||||
allow all;
|
||||
default_type "text/plain";
|
||||
}
|
||||
|
||||
rewrite ^/.well-known/caldav$ /SOGo/dav/ permanent;
|
||||
rewrite ^/.well-known/carddav$ /SOGo/dav/ permanent;
|
||||
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ @strip-ext;
|
||||
}
|
||||
|
||||
location /qhandler {
|
||||
rewrite ^/qhandler/(.*)/(.*) /qhandler.php?action=$1&hash=$2;
|
||||
}
|
||||
|
||||
location /edit {
|
||||
rewrite ^/edit/(.*)/(.*) /edit.php?$1=$2;
|
||||
}
|
||||
|
||||
location ~ ^/api/v1/(.*)$ {
|
||||
try_files $uri $uri/ /json_api.php?query=$1&$args;
|
||||
}
|
||||
|
||||
location ~ ^/cache/(.*)$ {
|
||||
try_files $uri $uri/ /resource.php?file=$1;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
try_files $uri =404;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass {{ PHPFPMHOST }}:9002;
|
||||
fastcgi_index index.php;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_read_timeout 3600;
|
||||
fastcgi_send_timeout 3600;
|
||||
}
|
||||
|
||||
location ~* ^/Autodiscover/Autodiscover.xml {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass {{ PHPFPMHOST }}:9002;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
try_files /autodiscover.php =404;
|
||||
}
|
||||
|
||||
location ~* ^/Autodiscover/Autodiscover.json {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass {{ PHPFPMHOST }}:9002;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
try_files /autodiscover-json.php =404;
|
||||
}
|
||||
|
||||
location ~ /(?:m|M)ail/(?:c|C)onfig-v1.1.xml {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass {{ PHPFPMHOST }}:9002;
|
||||
include /etc/nginx/fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
try_files /autoconfig.php =404;
|
||||
}
|
||||
|
||||
{% if not SKIP_RSPAMD %}
|
||||
location /rspamd/ {
|
||||
proxy_pass http://{{ RSPAMDHOST }}:11334/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_redirect off;
|
||||
proxy_intercept_errors on;
|
||||
error_page 401 /_rspamderror.php;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
{% if not SKIP_SOGO %}
|
||||
location ^~ /principals {
|
||||
return 301 /SOGo/dav;
|
||||
}
|
||||
|
||||
location /sogo-auth-verify {
|
||||
internal;
|
||||
proxy_set_header X-Original-URI $request_uri;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_pass http://127.0.0.1:65510/sogo-auth;
|
||||
proxy_pass_request_body off;
|
||||
}
|
||||
|
||||
location ^~ /Microsoft-Server-ActiveSync {
|
||||
auth_request /sogo-auth-verify;
|
||||
auth_request_set $user $upstream_http_x_user;
|
||||
auth_request_set $auth $upstream_http_x_auth;
|
||||
auth_request_set $auth_type $upstream_http_x_auth_type;
|
||||
proxy_set_header x-webobjects-remote-user "$user";
|
||||
proxy_set_header Authorization "$auth";
|
||||
proxy_set_header x-webobjects-auth-type "$auth_type";
|
||||
|
||||
proxy_pass http://{{ SOGOHOST }}:20000/SOGo/Microsoft-Server-ActiveSync;
|
||||
|
||||
proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_connect_timeout 75;
|
||||
proxy_send_timeout 3600;
|
||||
proxy_read_timeout 3600;
|
||||
proxy_buffer_size 128k;
|
||||
proxy_buffers 64 512k;
|
||||
proxy_busy_buffers_size 512k;
|
||||
proxy_set_header Host $http_host;
|
||||
client_body_buffer_size 512k;
|
||||
client_max_body_size 0;
|
||||
}
|
||||
|
||||
location ^~ /SOGo {
|
||||
location ~* ^/SOGo/so/.*\.(xml|js|html|xhtml)$ {
|
||||
auth_request /sogo-auth-verify;
|
||||
auth_request_set $user $upstream_http_x_user;
|
||||
auth_request_set $auth $upstream_http_x_auth;
|
||||
auth_request_set $auth_type $upstream_http_x_auth_type;
|
||||
proxy_set_header x-webobjects-remote-user "$user";
|
||||
proxy_set_header Authorization "$auth";
|
||||
proxy_set_header x-webobjects-auth-type "$auth_type";
|
||||
|
||||
proxy_pass http://{{ SOGOHOST }}:20000;
|
||||
|
||||
proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
|
||||
proxy_set_header x-webobjects-remote-host $remote_addr;
|
||||
proxy_set_header x-webobjects-server-name $server_name;
|
||||
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
|
||||
proxy_set_header x-webobjects-server-port $server_port;
|
||||
proxy_hide_header Content-Type;
|
||||
add_header Content-Type text/plain;
|
||||
break;
|
||||
}
|
||||
auth_request /sogo-auth-verify;
|
||||
auth_request_set $user $upstream_http_x_user;
|
||||
auth_request_set $auth $upstream_http_x_auth;
|
||||
auth_request_set $auth_type $upstream_http_x_auth_type;
|
||||
proxy_set_header x-webobjects-remote-user "$user";
|
||||
proxy_set_header Authorization "$auth";
|
||||
proxy_set_header x-webobjects-auth-type "$auth_type";
|
||||
|
||||
proxy_pass http://{{ SOGOHOST }}:20000;
|
||||
|
||||
proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%};
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
|
||||
proxy_set_header x-webobjects-remote-host $remote_addr;
|
||||
proxy_set_header x-webobjects-server-name $server_name;
|
||||
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
|
||||
proxy_set_header x-webobjects-server-port $server_port;
|
||||
proxy_buffer_size 128k;
|
||||
proxy_buffers 64 512k;
|
||||
proxy_busy_buffers_size 512k;
|
||||
proxy_send_timeout 3600;
|
||||
proxy_read_timeout 3600;
|
||||
client_body_buffer_size 128k;
|
||||
client_max_body_size 0;
|
||||
break;
|
||||
}
|
||||
|
||||
location ~* /sogo$ {
|
||||
return 301 $client_req_scheme://$http_host/SOGo;
|
||||
}
|
||||
|
||||
location /SOGo.woa/WebServerResources/ {
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location /.woa/WebServerResources/ {
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location /SOGo/WebServerResources/ {
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
|
||||
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
|
||||
}
|
||||
{% endif %}
|
||||
|
||||
|
||||
include /etc/nginx/conf.d/site.*.custom;
|
||||
|
||||
error_page 502 @awaitingupstream;
|
||||
|
||||
location @awaitingupstream {
|
||||
rewrite ^(.*)$ /_status.502.html break;
|
||||
}
|
||||
|
||||
location ~* \.php$ {
|
||||
return 404;
|
||||
}
|
||||
location ~* \.twig$ {
|
||||
return 404;
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
listen ${HTTP_PORT};
|
||||
listen [::]:${HTTP_PORT};
|
@ -1,3 +0,0 @@
|
||||
listen ${HTTPS_PORT} ssl;
|
||||
listen [::]:${HTTPS_PORT} ssl;
|
||||
http2 on;
|
@ -1 +0,0 @@
|
||||
echo "server_name ${MAILCOW_HOSTNAME} autodiscover.* autoconfig.* $(echo ${ADDITIONAL_SERVER_NAMES} | tr ',' ' ');"
|
@ -1,38 +0,0 @@
|
||||
echo '
|
||||
server {
|
||||
listen 127.0.0.1:65510;
|
||||
include /etc/nginx/conf.d/listen_plain.active;
|
||||
include /etc/nginx/conf.d/listen_ssl.active;
|
||||
|
||||
ssl_certificate /etc/ssl/mail/cert.pem;
|
||||
ssl_certificate_key /etc/ssl/mail/key.pem;
|
||||
|
||||
include /etc/nginx/conf.d/server_name.active;
|
||||
|
||||
include /etc/nginx/conf.d/includes/site-defaults.conf;
|
||||
}
|
||||
';
|
||||
for cert_dir in /etc/ssl/mail/*/ ; do
|
||||
if [[ ! -f ${cert_dir}domains ]] || [[ ! -f ${cert_dir}cert.pem ]] || [[ ! -f ${cert_dir}key.pem ]]; then
|
||||
continue
|
||||
fi
|
||||
# do not create vhost for default-certificate. the cert is already in the default server listen
|
||||
domains="$(cat ${cert_dir}domains | sed -e 's/^[[:space:]]*//')"
|
||||
case "${domains}" in
|
||||
"") continue;;
|
||||
"${MAILCOW_HOSTNAME}"*) continue;;
|
||||
esac
|
||||
echo -n '
|
||||
server {
|
||||
include /etc/nginx/conf.d/listen_ssl.active;
|
||||
|
||||
ssl_certificate '${cert_dir}'cert.pem;
|
||||
ssl_certificate_key '${cert_dir}'key.pem;
|
||||
';
|
||||
echo -n '
|
||||
server_name '${domains}';
|
||||
|
||||
include /etc/nginx/conf.d/includes/site-defaults.conf;
|
||||
}
|
||||
';
|
||||
done
|
@ -1 +0,0 @@
|
||||
proxy_pass http://${IPV4_NETWORK}.248:20000;
|
@ -1,5 +0,0 @@
|
||||
if printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
|
||||
echo "return 410;"
|
||||
else
|
||||
echo "proxy_pass http://${IPV4_NETWORK}.248:20000/SOGo/Microsoft-Server-ActiveSync;"
|
||||
fi
|
@ -1,6 +1,6 @@
|
||||
# Whitelist generated by Postwhite v3.4 on Fri Nov 1 00:18:49 UTC 2024
|
||||
# Whitelist generated by Postwhite v3.4 on Sun Dec 1 00:21:36 UTC 2024
|
||||
# https://github.com/stevejenkins/postwhite/
|
||||
# 2013 total rules
|
||||
# 1971 total rules
|
||||
2a00:1450:4000::/36 permit
|
||||
2a01:111:f400::/48 permit
|
||||
2a01:111:f403:8000::/50 permit
|
||||
@ -19,8 +19,7 @@
|
||||
8.20.114.31 permit
|
||||
8.25.194.0/23 permit
|
||||
8.25.196.0/23 permit
|
||||
8.39.54.0/23 permit
|
||||
8.40.222.0/23 permit
|
||||
10.162.0.0/16 permit
|
||||
12.130.86.238 permit
|
||||
13.110.208.0/21 permit
|
||||
13.110.209.0/24 permit
|
||||
@ -31,9 +30,11 @@
|
||||
15.200.21.50 permit
|
||||
15.200.44.248 permit
|
||||
15.200.201.185 permit
|
||||
17.41.0.0/16 permit
|
||||
17.57.155.0/24 permit
|
||||
17.57.156.0/24 permit
|
||||
17.58.0.0/16 permit
|
||||
17.142.0.0/15 permit
|
||||
17.143.234.140/30 permit
|
||||
18.156.89.250 permit
|
||||
18.157.243.190 permit
|
||||
@ -116,7 +117,6 @@
|
||||
40.233.64.216 permit
|
||||
40.233.83.78 permit
|
||||
40.233.88.28 permit
|
||||
43.228.184.0/22 permit
|
||||
44.206.138.57 permit
|
||||
44.217.45.156 permit
|
||||
44.236.56.93 permit
|
||||
@ -325,7 +325,6 @@
|
||||
65.110.161.77 permit
|
||||
65.123.29.213 permit
|
||||
65.123.29.220 permit
|
||||
65.154.166.0/24 permit
|
||||
65.212.180.36 permit
|
||||
66.102.0.0/20 permit
|
||||
66.119.150.192/26 permit
|
||||
@ -1114,10 +1113,8 @@
|
||||
98.139.245.212/31 permit
|
||||
99.78.197.208/28 permit
|
||||
99.83.190.102 permit
|
||||
103.2.140.0/22 permit
|
||||
103.9.96.0/22 permit
|
||||
103.28.42.0/24 permit
|
||||
103.47.204.0/22 permit
|
||||
103.151.192.0/23 permit
|
||||
103.168.172.128/27 permit
|
||||
104.43.243.237 permit
|
||||
@ -1285,9 +1282,6 @@
|
||||
117.120.16.0/21 permit
|
||||
119.42.242.52/31 permit
|
||||
119.42.242.156 permit
|
||||
121.244.91.48 permit
|
||||
121.244.91.52 permit
|
||||
122.15.156.182 permit
|
||||
123.126.78.64/29 permit
|
||||
124.108.96.24/31 permit
|
||||
124.108.96.28/31 permit
|
||||
@ -1348,19 +1342,7 @@
|
||||
134.170.141.64/26 permit
|
||||
134.170.143.0/24 permit
|
||||
134.170.174.0/24 permit
|
||||
135.84.80.0/24 permit
|
||||
135.84.81.0/24 permit
|
||||
135.84.82.0/24 permit
|
||||
135.84.83.0/24 permit
|
||||
135.84.216.0/22 permit
|
||||
136.143.160.0/24 permit
|
||||
136.143.161.0/24 permit
|
||||
136.143.162.0/24 permit
|
||||
136.143.178.49 permit
|
||||
136.143.182.0/23 permit
|
||||
136.143.184.0/24 permit
|
||||
136.143.188.0/24 permit
|
||||
136.143.190.0/23 permit
|
||||
136.147.128.0/20 permit
|
||||
136.147.135.0/24 permit
|
||||
136.147.176.0/20 permit
|
||||
@ -1375,7 +1357,6 @@
|
||||
139.138.46.219 permit
|
||||
139.138.57.55 permit
|
||||
139.138.58.119 permit
|
||||
139.167.79.86 permit
|
||||
139.180.17.0/24 permit
|
||||
140.238.148.191 permit
|
||||
141.148.159.229 permit
|
||||
@ -1410,6 +1391,7 @@
|
||||
146.20.215.0/24 permit
|
||||
146.20.215.182 permit
|
||||
146.88.28.0/24 permit
|
||||
147.154.32.0/25 permit
|
||||
147.243.1.47 permit
|
||||
147.243.1.48 permit
|
||||
147.243.1.153 permit
|
||||
@ -1450,7 +1432,6 @@
|
||||
157.151.208.65 permit
|
||||
157.255.1.64/29 permit
|
||||
158.101.211.207 permit
|
||||
158.120.80.0/21 permit
|
||||
158.247.16.0/20 permit
|
||||
159.92.154.0/24 permit
|
||||
159.92.155.0/24 permit
|
||||
@ -1478,6 +1459,11 @@
|
||||
161.38.204.0/22 permit
|
||||
161.71.32.0/19 permit
|
||||
161.71.64.0/20 permit
|
||||
162.88.4.0/23 permit
|
||||
162.88.8.0/24 permit
|
||||
162.88.24.0/24 permit
|
||||
162.88.25.0/24 permit
|
||||
162.88.36.0/24 permit
|
||||
162.247.216.0/22 permit
|
||||
163.47.180.0/22 permit
|
||||
163.114.130.16 permit
|
||||
@ -1486,7 +1472,6 @@
|
||||
163.114.135.16 permit
|
||||
164.152.23.32 permit
|
||||
164.177.132.168/30 permit
|
||||
165.173.128.0/24 permit
|
||||
166.78.68.0/22 permit
|
||||
166.78.68.221 permit
|
||||
166.78.69.169 permit
|
||||
@ -1515,12 +1500,6 @@
|
||||
168.245.12.252 permit
|
||||
168.245.46.9 permit
|
||||
168.245.127.231 permit
|
||||
169.148.129.0/24 permit
|
||||
169.148.131.0/24 permit
|
||||
169.148.142.10 permit
|
||||
169.148.144.0/25 permit
|
||||
169.148.144.10 permit
|
||||
170.10.68.0/22 permit
|
||||
170.10.128.0/24 permit
|
||||
170.10.129.0/24 permit
|
||||
170.10.132.56/29 permit
|
||||
@ -1626,6 +1605,7 @@
|
||||
192.18.139.154 permit
|
||||
192.18.145.36 permit
|
||||
192.18.152.58 permit
|
||||
192.29.103.128/25 permit
|
||||
192.30.252.0/22 permit
|
||||
192.161.144.0/20 permit
|
||||
192.162.87.0/24 permit
|
||||
@ -1651,14 +1631,6 @@
|
||||
195.234.109.226 permit
|
||||
195.245.230.0/23 permit
|
||||
198.2.128.0/18 permit
|
||||
198.2.128.0/24 permit
|
||||
198.2.132.0/22 permit
|
||||
198.2.136.0/23 permit
|
||||
198.2.145.0/24 permit
|
||||
198.2.177.0/24 permit
|
||||
198.2.178.0/23 permit
|
||||
198.2.180.0/24 permit
|
||||
198.2.186.0/23 permit
|
||||
198.21.0.0/21 permit
|
||||
198.37.144.0/20 permit
|
||||
198.37.152.186 permit
|
||||
@ -1678,15 +1650,7 @@
|
||||
199.16.156.0/22 permit
|
||||
199.33.145.1 permit
|
||||
199.33.145.32 permit
|
||||
199.34.22.36 permit
|
||||
199.59.148.0/22 permit
|
||||
199.67.80.2 permit
|
||||
199.67.80.20 permit
|
||||
199.67.82.2 permit
|
||||
199.67.82.20 permit
|
||||
199.67.84.0/24 permit
|
||||
199.67.86.0/24 permit
|
||||
199.67.88.0/24 permit
|
||||
199.101.161.130 permit
|
||||
199.101.162.0/25 permit
|
||||
199.122.120.0/21 permit
|
||||
@ -1698,7 +1662,6 @@
|
||||
202.165.102.47 permit
|
||||
202.177.148.100 permit
|
||||
202.177.148.110 permit
|
||||
203.31.36.0/22 permit
|
||||
203.32.4.25 permit
|
||||
203.55.21.0/24 permit
|
||||
203.81.17.0/24 permit
|
||||
@ -1744,19 +1707,13 @@
|
||||
204.92.114.187 permit
|
||||
204.92.114.203 permit
|
||||
204.92.114.204/31 permit
|
||||
204.141.32.0/23 permit
|
||||
204.141.42.0/23 permit
|
||||
204.220.160.0/21 permit
|
||||
204.220.168.0/21 permit
|
||||
204.220.176.0/20 permit
|
||||
204.232.168.0/24 permit
|
||||
205.139.110.0/24 permit
|
||||
205.201.128.0/20 permit
|
||||
205.201.131.128/25 permit
|
||||
205.201.134.128/25 permit
|
||||
205.201.136.0/23 permit
|
||||
205.201.137.229 permit
|
||||
205.201.139.0/24 permit
|
||||
205.207.104.0/22 permit
|
||||
205.220.167.17 permit
|
||||
205.220.167.98 permit
|
||||
@ -1784,7 +1741,6 @@
|
||||
207.46.132.128/27 permit
|
||||
207.46.198.0/25 permit
|
||||
207.46.200.0/27 permit
|
||||
207.58.147.64/28 permit
|
||||
207.67.38.0/24 permit
|
||||
207.67.98.192/27 permit
|
||||
207.68.176.0/26 permit
|
||||
@ -1831,6 +1787,8 @@
|
||||
208.74.204.5 permit
|
||||
208.74.204.9 permit
|
||||
208.75.120.0/22 permit
|
||||
208.76.62.0/24 permit
|
||||
208.76.63.0/24 permit
|
||||
208.82.237.96/29 permit
|
||||
208.82.237.104/31 permit
|
||||
208.82.238.96/29 permit
|
||||
@ -1930,7 +1888,6 @@
|
||||
213.199.177.0/26 permit
|
||||
216.17.150.242 permit
|
||||
216.17.150.251 permit
|
||||
216.22.15.224/27 permit
|
||||
216.24.224.0/20 permit
|
||||
216.39.60.154/31 permit
|
||||
216.39.60.156/30 permit
|
||||
@ -1973,7 +1930,10 @@
|
||||
216.136.162.65 permit
|
||||
216.136.162.120/29 permit
|
||||
216.136.168.80/28 permit
|
||||
216.139.64.0/19 permit
|
||||
216.145.221.0/24 permit
|
||||
216.146.32.0/24 permit
|
||||
216.146.33.0/24 permit
|
||||
216.198.0.0/18 permit
|
||||
216.203.30.55 permit
|
||||
216.203.33.178/31 permit
|
||||
@ -1999,8 +1959,6 @@
|
||||
2603:1030:20e:3::23c permit
|
||||
2603:1030:b:3::152 permit
|
||||
2603:1030:c02:8::14 permit
|
||||
2607:13c0:0001:0000:0000:0000:0000:7000/116 permit
|
||||
2607:13c0:0002:0000:0000:0000:0000:1000/116 permit
|
||||
2607:f8b0:4000::/36 permit
|
||||
2620:109:c003:104::/64 permit
|
||||
2620:109:c003:104::215 permit
|
||||
|
7
data/conf/redis/redis-conf.sh
Executable file
7
data/conf/redis/redis-conf.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
cat <<EOF > /redis.conf
|
||||
requirepass $REDISPASS
|
||||
EOF
|
||||
|
||||
exec redis-server /redis.conf
|
@ -25,6 +25,7 @@ catch (PDOException $e) {
|
||||
// Init Redis
|
||||
$redis = new Redis();
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
|
||||
function parse_email($email) {
|
||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
|
||||
|
@ -4,6 +4,7 @@ ini_set('error_reporting', 0);
|
||||
|
||||
$redis = new Redis();
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
|
||||
function in_net($addr, $net) {
|
||||
$net = explode('/', $net);
|
||||
|
@ -24,6 +24,7 @@ catch (PDOException $e) {
|
||||
// Init Redis
|
||||
$redis = new Redis();
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
|
||||
// Functions
|
||||
function parse_email($email) {
|
||||
@ -96,10 +97,10 @@ $rcpt_final_mailboxes = array();
|
||||
foreach (json_decode($rcpts, true) as $rcpt) {
|
||||
// Remove tag
|
||||
$rcpt = preg_replace('/^(.*?)\+.*(@.*)$/', '$1$2', $rcpt);
|
||||
|
||||
|
||||
// Break rcpt into local part and domain part
|
||||
$parsed_rcpt = parse_email($rcpt);
|
||||
|
||||
|
||||
// Skip if not a mailcow handled domain
|
||||
try {
|
||||
if (!$redis->hGet('DOMAIN_MAP', $parsed_rcpt['domain'])) {
|
||||
@ -243,7 +244,7 @@ foreach ($rcpt_final_mailboxes as $rcpt_final) {
|
||||
WHERE `rcpt` = :rcpt2
|
||||
ORDER BY id DESC
|
||||
LIMIT :retention_size
|
||||
) x
|
||||
) x
|
||||
);');
|
||||
$stmt->execute(array(
|
||||
':rcpt' => $rcpt_final,
|
||||
|
@ -14,6 +14,7 @@ try {
|
||||
else {
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
}
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
exit;
|
||||
|
@ -24,6 +24,7 @@ catch (PDOException $e) {
|
||||
// Init Redis
|
||||
$redis = new Redis();
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
|
||||
// Functions
|
||||
function parse_email($email) {
|
||||
|
@ -7,6 +7,7 @@ try {
|
||||
else {
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
}
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
exit;
|
||||
|
@ -106,7 +106,7 @@ $template_data = [
|
||||
'all_domains' => $all_domains,
|
||||
'mailboxes' => $mailboxes,
|
||||
'f2b_data' => $f2b_data,
|
||||
'f2b_banlist_url' => getBaseUrl() . "/api/v1/get/fail2ban/banlist/" . $f2b_data['banlist_id'],
|
||||
'f2b_banlist_url' => getBaseUrl() . "/f2b-banlist?id=" . $f2b_data['banlist_id'],
|
||||
'q_data' => quarantine('settings'),
|
||||
'qn_data' => quota_notification('get'),
|
||||
'pw_reset_data' => reset_password('get_notification'),
|
||||
|
@ -19,6 +19,7 @@ try {
|
||||
else {
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
}
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
exit;
|
||||
|
11
data/web/f2b-banlist.php
Normal file
11
data/web/f2b-banlist.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
|
||||
if (isset($_GET['id'])) {
|
||||
header('Content-Type: text/plain');
|
||||
echo fail2ban('banlist', 'get', $_GET['id']);
|
||||
} else {
|
||||
header('HTTP/1.1 404 Not Found');
|
||||
exit;
|
||||
}
|
@ -26,7 +26,7 @@ function dkim($_action, $_data = null, $privkey = false) {
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (!ctype_alnum(str_replace(['-', '_'], '', $dkim_selector))) {
|
||||
if (!ctype_alnum(str_replace(['-', '_', '.'], '', $dkim_selector))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data),
|
||||
@ -188,7 +188,7 @@ function dkim($_action, $_data = null, $privkey = false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!ctype_alnum($dkim_selector)) {
|
||||
if (!ctype_alnum(str_replace(['-', '_', '.'], '', $dkim_selector))) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data),
|
||||
|
@ -2917,6 +2917,8 @@ function reset_password($action, $data = null) {
|
||||
':username' => $username
|
||||
));
|
||||
|
||||
update_sogo_static_view($username);
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||
|
@ -3440,7 +3440,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
'old_maildir' => $domain . '/' . $old_local_part,
|
||||
'new_maildir' => $domain . '/' . $new_local_part
|
||||
);
|
||||
docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
|
||||
if (getenv("CLUSTERMODE") == "replication") {
|
||||
// broadcast to each dovecot container
|
||||
docker('broadcast', 'dovecot-mailcow', 'exec', $exec_fields);
|
||||
} else {
|
||||
docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
|
||||
}
|
||||
|
||||
// rename username in sogo
|
||||
$exec_fields = array(
|
||||
|
@ -3,7 +3,7 @@ function init_db_schema() {
|
||||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "15082024_1212";
|
||||
$db_version = "20112024_1105";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
@ -111,6 +111,10 @@ function init_db_schema() {
|
||||
"c_name" => "VARCHAR(255) NOT NULL",
|
||||
"c_password" => "VARCHAR(255) NOT NULL DEFAULT ''",
|
||||
"c_cn" => "VARCHAR(255)",
|
||||
"c_l" => "VARCHAR(255)",
|
||||
"c_o" => "VARCHAR(255)",
|
||||
"c_ou" => "VARCHAR(255)",
|
||||
"c_telephonenumber" => "VARCHAR(255)",
|
||||
"mail" => "VARCHAR(255) NOT NULL",
|
||||
// TODO -> use TEXT and check if SOGo login breaks on empty aliases
|
||||
"aliases" => "TEXT NOT NULL",
|
||||
@ -1019,7 +1023,7 @@ function init_db_schema() {
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
),
|
||||
"pushover" => array(
|
||||
"cols" => array(
|
||||
"username" => "VARCHAR(255) NOT NULL",
|
||||
@ -1403,7 +1407,7 @@ function init_db_schema() {
|
||||
"key_size" => 2048,
|
||||
"max_quota_for_domain" => 10240 * 1048576,
|
||||
)
|
||||
);
|
||||
);
|
||||
$default_mailbox_template = array(
|
||||
"template" => "Default",
|
||||
"type" => "mailbox",
|
||||
@ -1438,7 +1442,7 @@ function init_db_schema() {
|
||||
"acl_quarantine_category" => 1,
|
||||
"acl_app_passwds" => 1,
|
||||
)
|
||||
);
|
||||
);
|
||||
$stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
|
||||
$stmt->execute(array(
|
||||
":type" => "domain",
|
||||
@ -1452,8 +1456,8 @@ function init_db_schema() {
|
||||
":type" => "domain",
|
||||
":template" => $default_domain_template["template"],
|
||||
":attributes" => json_encode($default_domain_template["attributes"])
|
||||
));
|
||||
}
|
||||
));
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
|
||||
$stmt->execute(array(
|
||||
":type" => "mailbox",
|
||||
@ -1467,8 +1471,8 @@ function init_db_schema() {
|
||||
":type" => "mailbox",
|
||||
":template" => $default_mailbox_template["template"],
|
||||
":attributes" => json_encode($default_mailbox_template["attributes"])
|
||||
));
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
// remove old sogo views and triggers
|
||||
$pdo->query("DROP TRIGGER IF EXISTS sogo_update_password");
|
||||
|
@ -66,6 +66,7 @@ try {
|
||||
else {
|
||||
$redis->connect('redis-mailcow', 6379);
|
||||
}
|
||||
$redis->auth(getenv("REDISPASS"));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Stop when redis is not available
|
||||
|
@ -692,8 +692,8 @@ jQuery(function($){
|
||||
} else if (item.attributes.rl_frame === "d"){
|
||||
item.attributes.rl_frame = lang_rl.day;
|
||||
}
|
||||
item.attributes.rl_value = escapeHtml(item.attributes.rl_value);
|
||||
|
||||
item.attributes.rl_value = (!item.attributes.rl_value) ? "∞" : escapeHtml(item.attributes.rl_value);
|
||||
item.attributes.ratelimit = item.attributes.rl_value + " " + item.attributes.rl_frame;
|
||||
|
||||
if (item.template.toLowerCase() == "default"){
|
||||
item.action = '<div class="btn-group">' +
|
||||
@ -817,14 +817,8 @@ jQuery(function($){
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'rl_frame',
|
||||
data: 'attributes.rl_frame',
|
||||
defaultContent: '',
|
||||
class: 'none',
|
||||
},
|
||||
{
|
||||
title: 'rl_value',
|
||||
data: 'attributes.rl_value',
|
||||
title: lang_edit.ratelimit,
|
||||
data: 'attributes.ratelimit',
|
||||
defaultContent: '',
|
||||
class: 'none',
|
||||
},
|
||||
@ -893,7 +887,10 @@ jQuery(function($){
|
||||
item.quota.value = humanFileSize(item.quota_used) + "/" + item.quota.value;
|
||||
|
||||
item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
|
||||
item.last_mail_login = item.last_imap_login + '/' + item.last_pop3_login + '/' + item.last_smtp_login + '/' + item.last_sso_login;
|
||||
item.last_mail_login = (item.attributes.imap_access == 1 ? '<div class="text-start badge bg-info mb-2" style="min-width: 70px;">IMAP @ ' + unix_time_format(Number(item.last_imap_login)) + '</div><br>' : '') +
|
||||
(item.attributes.pop3_access == 1 ? '<div class="text-start badge bg-info mb-2" style="min-width: 70px;">POP3 @ ' + unix_time_format(Number(item.last_pop3_login)) + '</div><br>' : '') +
|
||||
(item.attributes.smtp_access == 1 ? '<div class="text-start badge bg-info mb-2" style="min-width: 70px;">SMTP @ ' + unix_time_format(Number(item.last_smtp_login)) + '</div><br>' : '') +
|
||||
'<div class="text-start badge bg-info" style="min-width: 70px;">SSO @ ' + unix_time_format(Number(item.last_sso_login)) + '</div>';
|
||||
/*
|
||||
if (!item.rl) {
|
||||
item.rl = '∞';
|
||||
@ -1009,14 +1006,7 @@ jQuery(function($){
|
||||
data: 'last_mail_login',
|
||||
searchable: false,
|
||||
defaultContent: '',
|
||||
responsivePriority: 7,
|
||||
render: function (data, type) {
|
||||
res = data.split("/");
|
||||
return '<div class="text-start badge bg-info mb-2" style="min-width: 70px;">IMAP @ ' + unix_time_format(Number(res[0])) + '</div><br>' +
|
||||
'<div class="text-start badge bg-info mb-2" style="min-width: 70px;">POP3 @ ' + unix_time_format(Number(res[1])) + '</div><br>' +
|
||||
'<div class="text-start badge bg-info mb-2" style="min-width: 70px;">SMTP @ ' + unix_time_format(Number(res[2])) + '</div><br>' +
|
||||
'<div class="text-start badge bg-info" style="min-width: 70px;">SSO @ ' + unix_time_format(Number(res[3])) + '</div>';
|
||||
}
|
||||
responsivePriority: 7
|
||||
},
|
||||
{
|
||||
title: lang.last_pw_change,
|
||||
@ -1191,7 +1181,8 @@ jQuery(function($){
|
||||
} else if (item.attributes.rl_frame === "d"){
|
||||
item.attributes.rl_frame = lang_rl.day;
|
||||
}
|
||||
item.attributes.rl_value = escapeHtml(item.attributes.rl_value);
|
||||
item.attributes.rl_value = (!item.attributes.rl_value) ? "∞" : escapeHtml(item.attributes.rl_value);
|
||||
item.attributes.ratelimit = item.attributes.rl_value + " " + item.attributes.rl_frame;
|
||||
|
||||
item.attributes.quota = humanFileSize(item.attributes.quota);
|
||||
|
||||
@ -1336,14 +1327,8 @@ jQuery(function($){
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "rl_frame",
|
||||
data: 'attributes.rl_frame',
|
||||
defaultContent: '',
|
||||
class: 'none',
|
||||
},
|
||||
{
|
||||
title: 'rl_value',
|
||||
data: 'attributes.rl_value',
|
||||
title: lang_edit.ratelimit,
|
||||
data: 'attributes.ratelimit',
|
||||
defaultContent: '',
|
||||
class: 'none',
|
||||
},
|
||||
|
@ -510,16 +510,6 @@ if (isset($_GET['query'])) {
|
||||
$_SESSION['challenge'] = $WebAuthn->getChallenge();
|
||||
return;
|
||||
break;
|
||||
case "fail2ban":
|
||||
if (!isset($_SESSION['mailcow_cc_role'])){
|
||||
switch ($object) {
|
||||
case 'banlist':
|
||||
header('Content-Type: text/plain');
|
||||
echo fail2ban('banlist', 'get', $extra);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
switch ($category) {
|
||||
@ -1431,10 +1421,6 @@ if (isset($_GET['query'])) {
|
||||
break;
|
||||
case "fail2ban":
|
||||
switch ($object) {
|
||||
case 'banlist':
|
||||
header('Content-Type: text/plain');
|
||||
echo fail2ban('banlist', 'get', $extra);
|
||||
break;
|
||||
default:
|
||||
$data = fail2ban('get');
|
||||
process_get_return($data);
|
||||
|
@ -207,7 +207,7 @@
|
||||
"include_exclude_info": "Par défaut - sans sélection - <b>toutes les boîte de réception</b> sont adressées",
|
||||
"includes": "Inclure ces destinataires",
|
||||
"last_applied": "Dernière application",
|
||||
"license_info": "Une licence n’est pas requise, mais contribue au développement.<br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Enregistrer votre GUID ici</a> or <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Support order\">acheter le support pour votre intallation Mailcow.</a>",
|
||||
"license_info": "Une licence n’est pas requise, mais contribue au développement.<br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Enregistrer votre GUID ici</a> ou <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Support order\">acheter le support pour votre installation Mailcow.</a>",
|
||||
"link": "Lien",
|
||||
"loading": "Veuillez patienter…",
|
||||
"logo_info": "Votre image sera redimensionnée à une hauteur de 40 pixels pour la barre de navigation du haut et à un maximum de 250 pixels en largeur pour la page d'accueil. Un graphique extensible est fortement recommandé.",
|
||||
|
@ -14,6 +14,7 @@
|
||||
"prohibited": "Запрещено правилами ACL",
|
||||
"protocol_access": "Настройка разрешенных протоколов",
|
||||
"pushover": "Pushover API",
|
||||
"pw_reset": "Разрешить пользователям mailcow восстановление паролей",
|
||||
"quarantine": "Карантин - действия",
|
||||
"quarantine_attachments": "Карантин - вложения",
|
||||
"quarantine_category": "Категория уведомлений о спаме",
|
||||
@ -28,8 +29,7 @@
|
||||
"spam_score": "Политика фильтрации спама",
|
||||
"syncjobs": "Задания синхронизации",
|
||||
"tls_policy": "Политика шифрования",
|
||||
"unlimited_quota": "Неограниченная квота для почтовых ящиков",
|
||||
"pw_reset": "Разрешить сброс пароля пользователей mailcow"
|
||||
"unlimited_quota": "Неограниченная квота для почтовых ящиков"
|
||||
},
|
||||
"add": {
|
||||
"activate_filter_warn": "Активация этого фильтра отключит все остальные фильтры этого типа.",
|
||||
@ -42,13 +42,14 @@
|
||||
"alias_domain": "Псевдоним домена",
|
||||
"alias_domain_info": "<small>Действительные имена доменов, раздёленные запятыми.</small>",
|
||||
"app_name": "Название приложения",
|
||||
"app_passwd_protocols": "Разрешенные протоколы для пароля приложения",
|
||||
"app_password": "Добавить пароль приложения",
|
||||
"automap": "Автоматическое слияние папок (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
||||
"backup_mx_options": "Параметры резервного MX",
|
||||
"bcc_dest_format": "Место назначения BCC должно быть единственным действительным адресом электронной почты.<br>Если вам нужно отправить копию на несколько адресов - используйте псевдоним.",
|
||||
"comment_info": "Приватный комментарий не виден пользователям, а публичный - отображается рядом с псевдонимом в личном кабинете пользователя.",
|
||||
"custom_params": "Пользовательские параметры",
|
||||
"custom_params_hint": "Верно: --param=xy, не верно: --param xy",
|
||||
"custom_params_hint": "Верно: --param=xy, неверно: --param xy",
|
||||
"delete1": "Удаление из источника после завершения",
|
||||
"delete2": "Удаление писем по месту назначения, которые не находятся на исходном",
|
||||
"delete2duplicates": "Удаление дубликатов по назначению",
|
||||
@ -58,6 +59,7 @@
|
||||
"domain": "Домен",
|
||||
"domain_matches_hostname": "Домен %s соответствует имени хоста",
|
||||
"domain_quota_m": "Квота домена (MiB)",
|
||||
"dry": "Имитировать синхронизацию",
|
||||
"enc_method": "Метод шифрования",
|
||||
"exclude": "Исключить объекты (regex)",
|
||||
"full_name": "Полное имя",
|
||||
@ -89,7 +91,7 @@
|
||||
"relay_all_info": "↪<small>Если вы решите <b>не</b> ретранслировать всех получателей, вам нужно будет добавить (\"слепой\") почтовый адрес для каждого получателя, которого следует ретранслировать.</small>",
|
||||
"relay_domain": "Ретрансляция этого домена",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Инфо</div> Вы можете настроить собственный транспорт для домена. Если такой настройки нет, то доставка будет выполнена на основе MX записей.",
|
||||
"relay_unknown_only": "Ретрансляция только не существующих почтовых ящиков. Почта к существующим почтовым ящикам будут доставляться локально.",
|
||||
"relay_unknown_only": "Ретрансляция только несуществующих почтовых ящиков. Почта существующих почтовых ящиков будут доставляться локально.",
|
||||
"relayhost_wrapped_tls_info": "Пожалуйста <b>не</b> используйте TLS порты (в основном это 465 порт).<br>\r\nИспользуйте любой <b>не</b> TLS порт который поддерживает STARTTLS. А для защиты от downgrate атак - настройке принудительную политику TLS.",
|
||||
"select": "Пожалуйста, выберите...",
|
||||
"select_domain": "Пожалуйста, сначала выберите домен",
|
||||
@ -99,6 +101,7 @@
|
||||
"subscribeall": "Подписаться на все папки и подпапки",
|
||||
"syncjob": "Добавить задание синхронизации",
|
||||
"syncjob_hint": "Пароли к вашему аккаунту будут сохранены на сервере в виде простого текста!",
|
||||
"tags": "Теги",
|
||||
"target_address": "Владельцы псевдонима",
|
||||
"target_address_info": "<small>Адреса почтовых ящиков, разделенные запятыми.</small>",
|
||||
"target_domain": "Целевой домен",
|
||||
@ -106,10 +109,7 @@
|
||||
"timeout2": "Тайм-аут для подключения к локальному хосту",
|
||||
"username": "Имя пользователя",
|
||||
"validate": "Проверить",
|
||||
"validation_success": "Проверка прошла успешно",
|
||||
"tags": "Теги",
|
||||
"app_passwd_protocols": "Разрешенные протоколы для пароля приложения",
|
||||
"dry": "Имитировать синхронизацию"
|
||||
"validation_success": "Проверка прошла успешно"
|
||||
},
|
||||
"admin": {
|
||||
"access": "Настройки доступа",
|
||||
@ -135,6 +135,8 @@
|
||||
"admins": "Администраторы",
|
||||
"admins_ldap": "Администраторы LDAP",
|
||||
"advanced_settings": "Расширенные настройки",
|
||||
"allowed_methods": "Access-Control-Allow-Methods",
|
||||
"allowed_origins": "Access-Control-Allow-Origin",
|
||||
"api_allow_from": "Список IP-адресов для доступа к API (разделенных запятой или новой строкой)",
|
||||
"api_info": "API находится в стадии разработки. Документация находится по адресу <a href=\"/api\">/api</a>",
|
||||
"api_key": "Ключ API",
|
||||
@ -151,6 +153,8 @@
|
||||
"change_logo": "Изменить логотип",
|
||||
"configuration": "Глобальные настройки",
|
||||
"convert_html_to_text": "Сконвертировать HTML в обычный текст",
|
||||
"copy_to_clipboard": "Текст скопирован в буфер обмена!",
|
||||
"cors_settings": "Настройки CORS",
|
||||
"credentials_transport_warning": "<b>Предупреждение</b>: добавление новой записи перезапишет учетные данные для всех записей с таким же <i>следующим хостом</i>.",
|
||||
"customer_id": "ID клиента",
|
||||
"customize": "Персонализация",
|
||||
@ -179,10 +183,14 @@
|
||||
"empty": "Пусто",
|
||||
"excludes": "Исключает этих получателей",
|
||||
"f2b_ban_time": "Время бана (в секундах)",
|
||||
"f2b_ban_time_increment": "Время бана увеличивается с каждым баном",
|
||||
"f2b_blacklist": "Черный список подсетей/хостов",
|
||||
"f2b_filter": "Правила фильтрации с помощью регулярных выражений",
|
||||
"f2b_list_info": "Хосты или подсети, занесенные в черный список, всегда будут перевешивать объекты из белого списка. <b>Обновление списка займет несколько секунд.</b>",
|
||||
"f2b_manage_external": "Внешнее управление Fail2Ban",
|
||||
"f2b_manage_external_info": "Fail2ban по-прежнему будет вести банлист, но не будет активно устанавливать правила для блокировки трафика. Используйте сгенерированный ниже банлист для внешнего блокирования трафика.",
|
||||
"f2b_max_attempts": "Максимальное количество попыток",
|
||||
"f2b_max_ban_time": "Максимальное время блокировки",
|
||||
"f2b_netban_ipv4": "Размер подсети IPv4 для применения бана (8-32)",
|
||||
"f2b_netban_ipv6": "Размер подсети IPv6 для применения бана (8-128)",
|
||||
"f2b_parameters": "Настройки Fail2ban",
|
||||
@ -208,14 +216,19 @@
|
||||
"include_exclude": "Включить/Исключить",
|
||||
"include_exclude_info": "По умолчанию - без выбора - <b>все почтовые ящики</b> адресованы",
|
||||
"includes": "Включить этих получателей",
|
||||
"ip_check": "Проверить IP",
|
||||
"ip_check_disabled": "Проверка IP-адресов отключена. Вы можете включить её в разделе <br> <strong>Система > Конфигурация > Параметры > Персонализация</strong>.",
|
||||
"ip_check_opt_in": "Согласие на использование сторонних служб <strong>ipv4.mailcow.email</strong> и <strong>ipv6.mailcow.email</strong> для разрешения внешних IP-адресов.",
|
||||
"is_mx_based": "На основе MX",
|
||||
"last_applied": "Посл. применение",
|
||||
"license_info": "Лицензия не обязательна, но её приобретение помогает дальнейшему развитию mailcow.<br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Зарегистрируйте свой GUID здесь</a> или <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Заказать поддержку\">приобретите поддержку для вашей установки mailcow.</a>",
|
||||
"license_info": "Лицензия необязательна, но её приобретение помогает дальнейшему развитию mailcow.<br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Зарегистрируйте свой GUID здесь</a> или <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Заказать поддержку\">приобретите поддержку для вашей установки mailcow.</a>",
|
||||
"link": "Ссылка",
|
||||
"loading": "Пожалуйста, подождите...",
|
||||
"login_time": "Время входа",
|
||||
"logo_info": "Ваше изображение будет масштабироваться до высоты 40px для верхней панели навигации и до 250px ширины для стартовой страницы. <br>Рекомендуется использовать векторную графику, на пример: .svg.",
|
||||
"lookup_mx": "Назначение на основе резовинга MX записи по регулярному выражению (<code>.*\\.example\\.com$</code> для маршрутизации всей почты через этот хост, если MX заканчивающийся на example.com)",
|
||||
"logo_dark_label": "Инвертированный для темного режима",
|
||||
"logo_info": "Ваше изображение будет масштабироваться до высоты 40px для верхней панели навигации и до 250px ширины для стартовой страницы. <br>Рекомендуется использовать векторную графику, например: .svg.",
|
||||
"logo_normal_label": "Обычный",
|
||||
"lookup_mx": "Назначение - регулярное выражение для сопоставления с именем MX (<code>.*\\.google\\.com</code> для направления всей почты, адресованной MX, заканчивающейся на google.com, через этот хоп)",
|
||||
"main_name": "Название для \"mailcow UI\"",
|
||||
"merged_vars_hint": "Серым цветом выделены строки полученные из <code>vars.(local.)inc.php</code>, они не могут быть изменены.",
|
||||
"message": "Сообщение",
|
||||
@ -225,15 +238,16 @@
|
||||
"no_active_bans": "В данный момент нет забаненных подсетей/хостов",
|
||||
"no_new_rows": "Нет доступных строк",
|
||||
"no_record": "Нет записей",
|
||||
"oauth2_client_id": "ID клиента",
|
||||
"oauth2_apps": "Приложения OAuth2",
|
||||
"oauth2_add_client": "Добавить клиента OAuth2",
|
||||
"oauth2_apps": "Приложения OAuth2",
|
||||
"oauth2_client_id": "ID клиента",
|
||||
"oauth2_client_secret": "Секретный ключ пользователя",
|
||||
"oauth2_info": "Реализация OAuth2 поддерживает предоставления кодов авторизации и выдает токены продления сессии.<br>\r\nСервер также автоматически выдает новый токен продления сессии, после того, как предыдущий был использован.<br><br>\r\n• Scope по умолчанию: <i>profile</i>. Только пользователи почтовых аккаунтов могут проходить аутентификацию через OAuth2. Если параметр области не указан, он возвращается к <i>profile</i>.<br>\r\n• Параметр <i>state</i> должен быть отправлен клиентом как часть запроса для авторизации.<br><br>\r\nПути для запросов OAuth2 API: <br>\r\n<ul>\r\n <li>Authorization endpoint: <code>/oauth/authorize</code></li>\r\n <li>Token endpoint: <code>/oauth/token</code></li>\r\n <li>Resource page: <code>/oauth/profile</code></li>\r\n</ul>\r\nГенерирование нового клиентского секрета не приводит к истечению существующих кодов авторизации, но они не смогут обновить свой токен.<br><br>\r\nОтзыв клиентских токенов приведет к немедленному прекращению всех активных сеансов. Все клиенты должны будут пройти повторную аутентификацию.",
|
||||
"oauth2_redirect_uri": "Переадресация URI",
|
||||
"oauth2_renew_secret": "Сгенерировать новый ключ клиента",
|
||||
"oauth2_revoke_tokens": "Отозвать все клиентские токены",
|
||||
"optional": "опционально",
|
||||
"options": "Параметры",
|
||||
"password": "Пароль",
|
||||
"password_length": "Минимальная длина пароля",
|
||||
"password_policy": "Политика паролей",
|
||||
@ -243,6 +257,11 @@
|
||||
"password_policy_numbers": "Должен содержать цифру",
|
||||
"password_policy_special_chars": "Должны содержать специальный символ",
|
||||
"password_repeat": "Подтверждение пароля (повтор)",
|
||||
"password_reset_info": "Если получатель не указан, использование данной функции недоступно.",
|
||||
"password_reset_settings": "Параметры восстановления паролей",
|
||||
"password_reset_tmpl_html": "Шаблон в виде HTML",
|
||||
"password_reset_tmpl_text": "Шаблон в виде обычного текста",
|
||||
"password_settings": "Параметры паролей",
|
||||
"priority": "Приоритет",
|
||||
"private_key": "Закрытый ключ",
|
||||
"quarantine": "Карантин",
|
||||
@ -250,7 +269,7 @@
|
||||
"quarantine_exclude_domains": "Исключить домены и псевдонимы доменов",
|
||||
"quarantine_max_age": "Максимальный период хранения в днях<br><small>Значение должно быть равно или больше 1 дня.</small>",
|
||||
"quarantine_max_score": "Не уведомлять о спаме, если оценка письма выше, чем:<br><small>По умолчанию 9999.0</small>",
|
||||
"quarantine_max_size": "Максимальный размер в MiB (письма большего размера не будет сохранены):<br><small>0 означает, что карантин <b>отключён</b>.</small>",
|
||||
"quarantine_max_size": "Максимальный размер в MiB (письма большего размера не будут сохранены):<br><small>0 означает, что карантин <b>отключён</b>.</small>",
|
||||
"quarantine_notification_html": "Шаблон уведомления:<br><small>Оставьте пустым, чтобы восстановить шаблон по умолчанию.</small>",
|
||||
"quarantine_notification_sender": "Email-адрес для отправки уведомления",
|
||||
"quarantine_notification_subject": "Тема письма",
|
||||
@ -259,6 +278,7 @@
|
||||
"quarantine_release_format_att": "Как вложение",
|
||||
"quarantine_release_format_raw": "Оригинальное письмо",
|
||||
"quarantine_retention_size": "Количество писем, сохраняемых в карантине на аккаунт:<br><small>0 означает, что карантин <b>отключён</b>.</small>",
|
||||
"queue_unban": "разблокировать",
|
||||
"quota_notification_html": "Шаблон уведомления:<br><small>Оставьте пустым, чтобы восстановить шаблон по умолчанию.</small>",
|
||||
"quota_notification_sender": "Email-адрес для отправки уведомления",
|
||||
"quota_notification_subject": "Тема письма",
|
||||
@ -267,7 +287,7 @@
|
||||
"quota_notifications_vars": "{{percent}} равно текущей квоте пользователя<br>{{username}} - имя почтового аккаунта",
|
||||
"r_active": "Включенные ограничения",
|
||||
"r_inactive": "Отключенные ограничения",
|
||||
"r_info": "Не активные (серые) элементы списка ограничений - это не валидные ограничения, и они не могут быть перемещены. <br>Вы можете добавить новые элементы в <code>inc/vars.local.inc.php</code> чтобы иметь возможность настраивать их.",
|
||||
"r_info": "Неактивные (серые) элементы списка ограничений - это некорректные ограничения, и они не могут быть перемещены. <br>Вы можете добавить новые элементы в <code>inc/vars.local.inc.php</code> чтобы иметь возможность настраивать их.",
|
||||
"rate_name": "Название очереди",
|
||||
"recipients": "Получатели",
|
||||
"refresh": "Обновить",
|
||||
@ -282,6 +302,8 @@
|
||||
"remove_row": "Удалить строку",
|
||||
"reset_default": "Восстановить по умолчанию",
|
||||
"reset_limit": "Удалить хэш",
|
||||
"reset_password_vars": "<code>{{link}}</code> Сгенерированная ссылка для восстановление пароля<br><code>{{username}}</code> Имя почтового ящика пользователя, запросившего восстановление пароля<br><code>{{username2}}</code> Имя почтового ящика для восстановления<br><code>{{date}}</code> Дата запроса на восстановление пароля<br><code>{{token_lifetime}}</code> Срок действия токена в минутах<br><code>{{hostname}}</code> Имя хоста mailcow",
|
||||
"restore_template": "Оставьте пустым, чтобы восстановить шаблон по умолчанию.",
|
||||
"routing": "Маршрутизация",
|
||||
"rsetting_add_rule": "Добавить правило",
|
||||
"rsetting_content": "Содержание правила",
|
||||
@ -290,14 +312,14 @@
|
||||
"rsetting_none": "Нет доступных правил",
|
||||
"rsettings_insert_preset": "Вставить пример \"%s\"",
|
||||
"rsettings_preset_1": "Отключить все, кроме DKIM и ограничения скорости для аутентифицированных пользователей",
|
||||
"rsettings_preset_2": "Не проверять письма на спам Postmaster",
|
||||
"rsettings_preset_2": "Не проверять письма Postmaster на спам",
|
||||
"rsettings_preset_3": "Разрешить только определённых отправителей для почтового ящика (использование только в качестве внутреннего почтового ящика)",
|
||||
"rsettings_preset_4": "Отключить Rspamd для домена",
|
||||
"rspamd_com_settings": "Имена правил будут сгенерированы на основе их ID.<br> Инструкция доступна на сайте <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">документация Rspamd user settings</a>, заготовленные шаблоны:",
|
||||
"rspamd_global_filters": "Глобальные правила фильтрации",
|
||||
"rspamd_global_filters_agree": "Я понимаю, что я делаю, и буду осторожен!",
|
||||
"rspamd_global_filters_info": "Глобальные правила фильтрации содержат различные виды глобальных черных и белых списков.",
|
||||
"rspamd_global_filters_regex": "Названия фильтров отражают их предназначение. Все правила должены состоять из регулярных выражений в формате \"/pattern/options\" (на пример: <code>/.+@domain\\.tld/i</code>).<br>\r\nНесмотря на то, что перед сохранением правил выполняется проверка регулярных выражений, функциональность Rspamds может быть нарушена, если будет использован<br>\r\n некорректный синтаксис. Будьте внимательны при написании правил.<br>Электронные письма от адресов электронной почты, проходящие по регулярным выражениям черных списков, будут отклонены без сохранения в карантин.<br>\r\n Rspamd попытается прочитать содержимое правил при их изменении. Но, если что, вы можете <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">перезапустить Rspamd</a>, чтобы принять последние изменения принудительно.",
|
||||
"rspamd_global_filters_regex": "Названия фильтров отражают их предназначение. Все правила должены состоять из регулярных выражений в формате \"/pattern/options\" (например: <code>/.+@domain\\.tld/i</code>).<br>\r\nНесмотря на то, что перед сохранением правил выполняется проверка регулярных выражений, функциональность Rspamds может быть нарушена, если будет использован<br>\r\n некорректный синтаксис. Будьте внимательны при написании правил.<br>Электронные письма от адресов электронной почты, проходящие по регулярным выражениям черных списков, будут отклонены без сохранения в карантин.<br>\r\n Rspamd попытается прочитать содержимое правил при их изменении. Но, если что, вы можете <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">перезапустить Rspamd</a>, чтобы принять последние изменения принудительно.",
|
||||
"rspamd_settings_map": "Правила Rspamd",
|
||||
"sal_level": "Уровень Муу",
|
||||
"save": "Сохранить изменения",
|
||||
@ -337,19 +359,7 @@
|
||||
"username": "Имя пользователя",
|
||||
"validate_license_now": "Получить лицензию на основе GUID с сервера лицензий",
|
||||
"verify": "Проверить",
|
||||
"yes": "✓",
|
||||
"queue_unban": "разблокировать",
|
||||
"f2b_ban_time_increment": "Время бана увеличивается с каждым баном",
|
||||
"f2b_max_ban_time": "Максимальное время блокировки",
|
||||
"allowed_origins": "Access-Control-Allow-Origin",
|
||||
"cors_settings": "Настройки CORS",
|
||||
"allowed_methods": "Access-Control-Allow-Methods",
|
||||
"ip_check": "Проверить IP",
|
||||
"ip_check_disabled": "Проверка IP отключена. Вы можете включить его в разделе <br> <strong>Система > Конфигурация > Параметры > Настроить</strong>.",
|
||||
"ip_check_opt_in": "Согласие на использование сторонних служб <strong>ipv4.mailcow.email</strong> и <strong>ipv6.mailcow.email</strong> для разрешения внешних IP-адресов.",
|
||||
"f2b_manage_external": "Внешнее управление Fail2Ban",
|
||||
"f2b_manage_external_info": "Fail2ban по-прежнему будет вести банлист, но не будет активно устанавливать правила для блокировки трафика. Используйте сгенерированный ниже банлист для внешнего блокирования трафика.",
|
||||
"copy_to_clipboard": "Текст скопирован в буфер обмена!"
|
||||
"yes": "✓"
|
||||
},
|
||||
"danger": {
|
||||
"access_denied": "Доступ запрещён, или указаны неверные данные",
|
||||
@ -365,7 +375,10 @@
|
||||
"bcc_exists": "Для типов %s уже существует карта BCC %s",
|
||||
"bcc_must_be_email": "Назначение BCC %s не является правильным адресом электронной почты",
|
||||
"comment_too_long": "Комментарий слишком длинный, придел 160 символов",
|
||||
"cors_invalid_method": "Указан недопустимый метод разрешения",
|
||||
"cors_invalid_origin": "Указан неверный Allow-Origin",
|
||||
"defquota_empty": "Квота по умолчанию не может быть 0.",
|
||||
"demo_mode_enabled": "Демонстрационный режим включен",
|
||||
"description_invalid": "Недопустимое описание ресурса %s",
|
||||
"dkim_domain_or_sel_exists": "Ключ DKIM для \"%s\" уже существует",
|
||||
"dkim_domain_or_sel_invalid": "DKIM домен или селектор недопустимы для %s",
|
||||
@ -375,20 +388,23 @@
|
||||
"domain_not_empty": "Нельзя удалить непустой домен %s",
|
||||
"domain_not_found": "Домен %s не найден",
|
||||
"domain_quota_m_in_use": "Квота домена должна быть больше или равна %s MiB",
|
||||
"extra_acl_invalid": "Адрес внешнего отправителя \"%s\" не валидный.",
|
||||
"extra_acl_invalid_domain": "Адрес внешнего отправителя \"%s\" не валидный домен",
|
||||
"extended_sender_acl_denied": "отсутствует ACL для установки внешних адресов отправителей",
|
||||
"extra_acl_invalid": "Адрес внешнего отправителя \"%s\" некорректен",
|
||||
"extra_acl_invalid_domain": "Адрес внешнего отправителя \"%s\" содержит некорректный домен",
|
||||
"fido2_verification_failed": "Ошибка валидации FIDO2: %s",
|
||||
"file_open_error": "Файл не может быть открыт на запись",
|
||||
"filter_type": "Неверный тип фильтра",
|
||||
"from_invalid": "Отправитель не может быть пустым",
|
||||
"global_filter_write_error": "Ошибка записи фильтра в файл: %s",
|
||||
"global_map_invalid": "Идентификатор глобального правила %s не валидный",
|
||||
"global_map_invalid": "Недопустимый идентификатор глобального правила %s",
|
||||
"global_map_write_error": "Не удалось создать глобальное правило ID %s: %s",
|
||||
"goto_empty": "Псевдоним должен содержать по крайней мере один валидный адрес владельца",
|
||||
"goto_empty": "Псевдоним должен содержать по крайней мере один действующий адрес владельца",
|
||||
"goto_invalid": "Недопустимый основной адрес %s",
|
||||
"ham_learn_error": "Ошибка при обучении полезной почты: %s",
|
||||
"imagick_exception": "Ошибка в Imagick при чтении изображения",
|
||||
"img_dimensions_exceeded": "Разрешение изображения превышает допустимое значение",
|
||||
"img_invalid": "Невозможно проверить файл изображения",
|
||||
"img_size_exceeded": "Изображение превышает допустимый размер файла",
|
||||
"img_tmp_missing": "Невозможно проверить файл изображения: временный файл не найден",
|
||||
"invalid_bcc_map_type": "Неверный тип правила BCC",
|
||||
"invalid_destination": "Назначение \"%s\" указано неверно",
|
||||
@ -397,8 +413,9 @@
|
||||
"invalid_mime_type": "Неверный mime type",
|
||||
"invalid_nexthop": "Формат следующего хоста неверен",
|
||||
"invalid_nexthop_authenticated": "Следующий хост существует с разными данными авторизации, пожалуйста, обновите существующие данные авторизации сначала для этого хоста.",
|
||||
"invalid_recipient_map_new": "Новый получатель: %s не валидный",
|
||||
"invalid_recipient_map_old": "Первоначальный получатель: %s не валидный",
|
||||
"invalid_recipient_map_new": "Недопустимый новый получатель: %s",
|
||||
"invalid_recipient_map_old": "Недопустимый исходный получатель: %s",
|
||||
"invalid_reset_token": "Неверный токен восстановления",
|
||||
"ip_list_empty": "Список разрешенных IP адресов не может быть пустым",
|
||||
"is_alias": "%s уже известен как псевдоним адреса",
|
||||
"is_alias_or_mailbox": "%s уже известен как псевдоним или почтовый аккаунт",
|
||||
@ -418,7 +435,7 @@
|
||||
"max_quota_in_use": "Квота почтового аккаунта должна быть больше или равна %d MiB",
|
||||
"maxquota_empty": "Максимальная квота почтового аккаунта не должна быть 0.",
|
||||
"mysql_error": "Ошибка в MySQL: %s",
|
||||
"network_host_invalid": "Сеть или хост: %s не валидный",
|
||||
"network_host_invalid": "Недопустимые сеть или хост: %s",
|
||||
"next_hop_interferes": "%s пересекается с %s",
|
||||
"next_hop_interferes_any": "Существующий хост пересекается с %s",
|
||||
"nginx_reload_failed": "Обновление конфигурации Nginx не удалось: %s",
|
||||
@ -428,6 +445,8 @@
|
||||
"password_complexity": "Пароль не соответствует требованиям",
|
||||
"password_empty": "Пароль не может быть пустым",
|
||||
"password_mismatch": "Введенные пароли не совпадают",
|
||||
"password_reset_invalid_user": "Почтовый ящик не найден или не задан адрес электронной почты для восстановления",
|
||||
"password_reset_na": "Восстановление пароля в настоящее время недоступно. Пожалуйста, свяжитесь с вашим администратором.",
|
||||
"policy_list_from_exists": "Запись с указанным именем уже существует",
|
||||
"policy_list_from_invalid": "Запись имеет недопустимый формат",
|
||||
"private_key_error": "Ошибка приватного ключа: %s",
|
||||
@ -436,17 +455,19 @@
|
||||
"pushover_token": "Токен Pushover указан в неверном формате",
|
||||
"quota_not_0_not_numeric": "Размер квоты должен быть больше или равен нулю",
|
||||
"recipient_map_entry_exists": "Правило перезаписи \"%s\" уже существует",
|
||||
"recovery_email_failed": "Не удалось отправить письмо для восстановления. Пожалуйста, свяжитесь с вашим администратором.",
|
||||
"redis_error": "Ошибка в Redis: %s",
|
||||
"relayhost_invalid": "Правило %s не валидное",
|
||||
"relayhost_invalid": "Недопустимое правило %s",
|
||||
"release_send_failed": "Сообщение не может быть восстановлено: %s",
|
||||
"reset_f2b_regex": "Сброс фильтров не был выполнен за отведённый промежуток времени, пожалуйста, повторите попытку или подождите еще несколько секунд и перезагрузите веб страницу.",
|
||||
"reset_token_limit_exceeded": "Превышен лимит запросов на восстановление. Пожалуйста, попробуйте ещё раз позже.",
|
||||
"resource_invalid": "Недопустимое имя ресурса",
|
||||
"rl_timeframe": "Не верный временной интервал для лимита отправки",
|
||||
"rspamd_ui_pw_length": "Длина пароля должна составлять не менее 6 символов для Rspamd UI",
|
||||
"script_empty": "Скрипт не может быть пустым",
|
||||
"sender_acl_invalid": "Недопустимое значение ACL для: %s",
|
||||
"set_acl_failed": "Не удалось установить ACL",
|
||||
"settings_map_invalid": "Правило ID: %s не валидное",
|
||||
"settings_map_invalid": "Недопустимое правило ID %s",
|
||||
"sieve_error": "Ошибка в синтаксисе Sieve: %s",
|
||||
"spam_learn_error": "Ошибка при обучении спам фильтра: %s",
|
||||
"subject_empty": "Тема письма не может быть пустой",
|
||||
@ -454,34 +475,67 @@
|
||||
"targetd_not_found": "Основной домен %s не найден",
|
||||
"targetd_relay_domain": "Целевой домен %s уже является домен ретрансляции",
|
||||
"temp_error": "Временная ошибка",
|
||||
"text_empty": "Текст не должен быть пустым",
|
||||
"template_exists": "Шаблон %s уже существует",
|
||||
"template_id_invalid": "Недопустимое значение ID шаблона: %s",
|
||||
"template_name_invalid": "Недопустимое название шаблона",
|
||||
"text_empty": "Текст не может быть пустым",
|
||||
"tfa_token_invalid": "Неправильный TFA токен",
|
||||
"tls_policy_map_dest_invalid": "Недопустимое значение назначения политики",
|
||||
"tls_policy_map_entry_exists": "Правило политики шифрования \"%s\" уже существует",
|
||||
"tls_policy_map_parameter_invalid": "Недопустимое значение параметра политики",
|
||||
"to_invalid": "Получатель не может быть пустым",
|
||||
"totp_verification_failed": "Ошибка валидации TOTP",
|
||||
"transport_dest_exists": "Назначение для отправки \"%s\" уже существует",
|
||||
"webauthn_verification_failed": "Ошибка валидации WebAuthn: %s",
|
||||
"unknown": "Произошла неизвестная ошибка",
|
||||
"unknown_tfa_method": "Неизвестный метод TFA",
|
||||
"unlimited_quota_acl": "Неограниченная квота запрещена политикой доступа",
|
||||
"username_invalid": "Имя пользователя %s нельзя использовать",
|
||||
"validity_missing": "Пожалуйста, назначьте срок действия",
|
||||
"value_missing": "Пожалуйста заполните все поля",
|
||||
"yotp_verification_failed": "Ошибка валидации Yubico OTP: %s",
|
||||
"cors_invalid_method": "Указан недопустимый метод разрешения",
|
||||
"demo_mode_enabled": "Демонстрационный режим включен",
|
||||
"cors_invalid_origin": "Указан неверный Allow-Origin"
|
||||
"webauthn_authenticator_failed": "Выбранный аутентификатор не был найден",
|
||||
"webauthn_publickey_failed": "Для выбранного аутентификатора не был сохранен открытый ключ",
|
||||
"webauthn_username_failed": "Выбранный аутентификатор принадлежит другой учетной записи",
|
||||
"webauthn_verification_failed": "Ошибка валидации WebAuthn: %s",
|
||||
"yotp_verification_failed": "Ошибка валидации Yubico OTP: %s"
|
||||
},
|
||||
"datatables": {
|
||||
"collapse_all": "Свернуть все",
|
||||
"decimal": ",",
|
||||
"emptyTable": "В таблице отсутствуют данные",
|
||||
"expand_all": "Развернуть все",
|
||||
"info": "Показаны записи с _START_ по _END_ из _TOTAL_",
|
||||
"infoEmpty": "Показано 0 записей",
|
||||
"infoFiltered": "(отфильтровано из _MAX_ всех записей)",
|
||||
"infoPostFix": "",
|
||||
"lengthMenu": "Показать _MENU_ записей",
|
||||
"loadingRecords": "Загрузка...",
|
||||
"processing": "Пожалуйста, подождите...",
|
||||
"search": "Поиск:",
|
||||
"thousands": " ",
|
||||
"zeroRecords": "Не найдено соответствующих записей",
|
||||
"paginate": {
|
||||
"first": "Первая",
|
||||
"last": "Последняя",
|
||||
"next": "Следующая",
|
||||
"previous": "Предыдущая"
|
||||
},
|
||||
"aria": {
|
||||
"sortAscending": ": активируйте для сортировки столбца по возрастанию",
|
||||
"sortDescending": ": активируйте для сортировки столбца по убыванию"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"architecture": "Архитектура",
|
||||
"chart_this_server": "Диаграмма (текущий сервер)",
|
||||
"containers_info": "Статус контейнеров Docker",
|
||||
"container_running": "Работающий",
|
||||
"container_disabled": "Контейнер остановлен или отключен",
|
||||
"container_running": "Работающий",
|
||||
"container_stopped": "Остановлен",
|
||||
"containers_info": "Статус контейнеров Docker",
|
||||
"cores": "яд.",
|
||||
"current_time": "Системное время",
|
||||
"disk_usage": "Использование дискового пространства",
|
||||
"docs": "Проиндексировано объектов",
|
||||
"error_show_ip": "Не удалось определить публичные IP-адреса",
|
||||
"external_logs": "Внешние журналы",
|
||||
"history_all_servers": "История (все серверы)",
|
||||
"in_memory_logs": "Журналы контейнеров",
|
||||
@ -490,9 +544,12 @@
|
||||
"log_info": "<p><b>Журналы контейнеров</b> mailcow сохраняются в Redis, и раз в минуту строки журнала за пределами <code>LOG_LINES (%d)</code> удаляются, чтобы уменьшить нагрузку на сервер.\r\n <br>Сами журналы контейнеров не сохраняются после перезагрузки контейнера. Все контейнеры дополнительно пишут логи в службу Docker, и, следовательно, используют драйвер логирования по умолчанию. Журналы контейнеров предусмотрены только для отладки мелких проблем. Для других задач, пожалуйста, настройте драйвер логирования Docker самостоятельно.</p>\r\n <p><b>Внешние журналы</b> собираются через API приложений.</p>\r\n <p><b>Статические журналы</b> – это, в основном, журналы активности, которые не записываются в Dockerd, но все равно должны быть постоянными (за исключением журналов API).</p>",
|
||||
"login_time": "Время входа",
|
||||
"logs": "Журналы",
|
||||
"memory": "Память",
|
||||
"no_update_available": "Система обновлена до последней версии",
|
||||
"online_users": "Подключено пользователей",
|
||||
"restart_container": "Перезапустить",
|
||||
"service": "Сервис",
|
||||
"show_ip": "Показать публичные IP-адреса",
|
||||
"size": "Индексы занимают",
|
||||
"solr_dead": "Solr не запущен. Если вы включили Solf в файле настроек <code>mailcow.conf</code> и это сообщение отображается более получаса, скорее всего Solr сломан.",
|
||||
"solr_status": "Состояние Solr",
|
||||
@ -500,10 +557,13 @@
|
||||
"started_on": "Запущен в",
|
||||
"static_logs": "Статические журналы",
|
||||
"success": "Успех",
|
||||
"no_update_available": "Система обновлена до последней версии",
|
||||
"system_containers": "Система и контейнеры",
|
||||
"timezone": "Часовой пояс",
|
||||
"update_available": "Доступно обновление",
|
||||
"update_failed": "Не удалось проверить наличие обновлений",
|
||||
"uptime": "Время работы",
|
||||
"username": "Имя пользователя"
|
||||
"username": "Имя пользователя",
|
||||
"wip": "В настоящее время идёт разработка"
|
||||
},
|
||||
"diagnostics": {
|
||||
"cname_from_a": "Значение, полученное из записи A/AAAA. Это поддерживается до тех пор, пока запись указывает на правильный ресурс.",
|
||||
@ -514,7 +574,7 @@
|
||||
"dns_records_name": "Название",
|
||||
"dns_records_status": "Статус",
|
||||
"dns_records_type": "Тип",
|
||||
"optional": "Эта запись не обязательна."
|
||||
"optional": "Эта запись необязательна."
|
||||
},
|
||||
"edit": {
|
||||
"acl": "ACL (Список прав)",
|
||||
@ -527,6 +587,7 @@
|
||||
"allowed_protocols": "Разрешённые протоколы",
|
||||
"app_name": "Название приложения",
|
||||
"app_passwd": "Пароль приложения",
|
||||
"app_passwd_protocols": "Разрешенные протоколы для пароля приложения",
|
||||
"automap": "Автоматическое слияние папок (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
||||
"backup_mx_options": "Параметры резервного копирования MX",
|
||||
"bcc_dest_format": "Назначением для правила BCC должен быть единственный действительный адрес электронной почты.",
|
||||
@ -534,6 +595,7 @@
|
||||
"client_secret": "Секретный ключ пользователя",
|
||||
"comment_info": "Приватный комментарий не виден пользователям, а публичный - отображается рядом с псевдонимом в личном кабинете пользователя",
|
||||
"created_on": "Дата создания",
|
||||
"custom_attributes": "Пользовательские атрибуты",
|
||||
"delete1": "Удаление из источника после завершения",
|
||||
"delete2": "Удаление писем по месту назначения, которые не находятся на исходном",
|
||||
"delete2duplicates": "Удаление дубликатов по назначению",
|
||||
@ -542,6 +604,19 @@
|
||||
"disable_login": "Вход в систему запрещен",
|
||||
"domain": "Изменение домена",
|
||||
"domain_admin": "Изменение администратора домена",
|
||||
"domain_footer": "Нижний колонтитул домена",
|
||||
"domain_footer_html": "HTML нижний колонтитул",
|
||||
"domain_footer_info": "Нижние колонтитулы на уровне домена добавляются ко всем исходящим электронным письмам, связанным с адресом в этом домене. <br> Для нижнего колонтитула можно использовать следующие переменные:",
|
||||
"domain_footer_info_vars": {
|
||||
"auth_user": "{= auth_user =} - Аутентифицированное имя пользователя, указанное MTA",
|
||||
"custom": "{= foo =} - Если почтовый ящик имеет пользовательский атрибут \"foo\" со значением \"bar\", он возвращает \"bar\".",
|
||||
"from_addr": "{= from_addr =} - Из адресной части envelope",
|
||||
"from_domain": "{= from_domain =} - из доменной части envelope",
|
||||
"from_name": "{= from_name =} - Из названия envelope, например, для \"Mailcow <moo@mailcow.tld>\" возвращается \"Mailcow\"",
|
||||
"from_user": "{= from_user =} - Из пользовательской части envelope, например, для \"moo@mailcow.tld\" возвращается \"moo\""
|
||||
},
|
||||
"domain_footer_plain": "ПРОСТОЙ нижний колонтитул",
|
||||
"domain_footer_skip_replies": "Ignore footer on reply e-mails",
|
||||
"domain_quota": "Квота домена",
|
||||
"domains": "Домены",
|
||||
"dont_check_sender_acl": "Отключить проверку отправителя для домена %s и псевдонимов домена",
|
||||
@ -550,9 +625,9 @@
|
||||
"exclude": "Исключить объекты (regex)",
|
||||
"extended_sender_acl": "Внешние адреса почты",
|
||||
"extended_sender_acl_info": "Для внешних доменов должен быть импортирован или сгенерирован доменный ключ DKIM с соответствующей записью TXT в домене, если внешний домен использует DMARC.<br>\r\n Не забудьте добавить этот сервер к соответствующей записи SPF TXT внешнего домена.<br>\r\n Добавление домена из списка внешних адресов в mailcow автоматически удалит соответствующие записи из внешних адресов пользователей.<br>\r\n Чтобы разрешить пользователю отправку от имени *@domain.tld, укажите @domain.tld.",
|
||||
"footer_exclude": "Исключить из нижнего колонтитула",
|
||||
"force_pw_update": "Требовать смены пароля при следующем входе в систему",
|
||||
"force_pw_update_info": "Пользователь должен будет войти в %s и сменить свой пароль. mailcow OAuth2, SOGo, EAS, IMAP/POP3 и SMTP будут не доступны до смены пароля.",
|
||||
"footer_exclude": "Исключить из нижнего колонтитула",
|
||||
"full_name": "Полное имя",
|
||||
"gal": "GAL - Глобальная адресная книга",
|
||||
"gal_info": "GAL содержит все объекты домена и не подлежит редактированию. Информация о занятости в SOGo будет отсутствовать для домена, если данная функция будет отключена! <b>Требуется перезапустить SOGo, чтобы применить изменения.</b>",
|
||||
@ -566,6 +641,11 @@
|
||||
"mailbox": "Изменение почтового аккаунта",
|
||||
"mailbox_quota_def": "Квота по умолчанию",
|
||||
"mailbox_relayhost_info": "Применяется только к почтовому ящику и личным псевдонимам, вне зависимости от настроек маршрутизации на уровне домена.",
|
||||
"mailbox_rename": "Переименовать почтовый ящик",
|
||||
"mailbox_rename_agree": "Я сделал резервную копию.",
|
||||
"mailbox_rename_alias": "Автоматически создать псевдоним",
|
||||
"mailbox_rename_title": "Новое имя локального почтового ящика",
|
||||
"mailbox_rename_warning": "ВАЖНО! Перед переименованием почтового ящика создайте резервную копию.",
|
||||
"max_aliases": "Максимум псевдонимов",
|
||||
"max_mailboxes": "Максимум почтовых ящиков",
|
||||
"max_quota": "Максимальная квота почтового аккаунта (MiB)",
|
||||
@ -574,9 +654,10 @@
|
||||
"mbox_rl_info": "Этот лимит применяется к SASL логину пользователя и соответствует любому адресу отправителя, используемому зарегистрированным пользователем. Лимит скорости почтового аккаунта перекрывает лимит скорости для всего домена.",
|
||||
"mins_interval": "Интервал (в минутах)",
|
||||
"multiple_bookings": "Несколько бронирований",
|
||||
"none_inherit": "Отсутствует / Наследуется",
|
||||
"nexthop": "Следующий хост",
|
||||
"none_inherit": "Отсутствует / Наследуется",
|
||||
"password": "Пароль",
|
||||
"password_recovery_email": "Адрес для восстановления пароля",
|
||||
"password_repeat": "Подтверждение пароля (повтор)",
|
||||
"previous": "Предыдущая страница",
|
||||
"private_comment": "Приватный комментарий",
|
||||
@ -587,6 +668,7 @@
|
||||
"pushover_only_x_prio": "Получать уведомления только об письмах с высоким приоритетом [<code>X-Priority: 1</code>]",
|
||||
"pushover_sender_array": "Получать уведомления от списка адресов электронной почты <small>(envelop-from разделенные запятыми)</small>:",
|
||||
"pushover_sender_regex": "Получать уведомления от отправителей, удовлетворяющих regex-выражению:",
|
||||
"pushover_sound": "Звук уведомления",
|
||||
"pushover_text": "Текст уведомления",
|
||||
"pushover_title": "Заголовок уведомления",
|
||||
"pushover_vars": "Когда фильтрация по отправителю не определена, уведомления будут доставлятся от всех отправителей.<br>Можно использовать обычный фильтр по отправителю и расширенный regex-фильтр, а также оба сразу.<br>Пожалуйста, ознакомьтесь с <a href=\"https://pushover.net/privacy\">Pushover Privacy Policy</a> перед использованием шаблонов для текста и заголовка",
|
||||
@ -600,7 +682,7 @@
|
||||
"relay_all_info": "↪<small>Если вы решите <b>не</b> ретранслировать всех получателей, вам нужно будет добавить (\"слепой\") почтовый аккаунт для каждого получателя, которого следует ретранслировать.</small>",
|
||||
"relay_domain": "Ретрансляция этого домена",
|
||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Инфо</div> Вы можете настроить собственный транспорт для домена. Если такой настройки нет, то доставка будет выполнена на основе MX записей.",
|
||||
"relay_unknown_only": "Ретрансляция только не существующих почтовых ящиков. Почта к существующим почтовым ящикам будут доставляться локально.",
|
||||
"relay_unknown_only": "Ретрансляция только несуществующих почтовых ящиков. Почта к существующим почтовым ящикам будут доставляться локально.",
|
||||
"relayhost": "Маршрутизация на основе отправителя",
|
||||
"remove": "Удалить",
|
||||
"resource": "Ресурс",
|
||||
@ -612,6 +694,8 @@
|
||||
"sieve_desc": "Краткое описание",
|
||||
"sieve_type": "Тип фильтра",
|
||||
"skipcrossduplicates": "Пропускать повторяющиеся сообщения в папках",
|
||||
"sogo_access": "Прямая переадресация в SOGo",
|
||||
"sogo_access_info": "После входа в систему пользователь автоматически перенаправляется в SOGo.",
|
||||
"sogo_visible": "Отображать псевдоним в SOGo",
|
||||
"sogo_visible_info": "Влияет только на объекты, которые могут отображаться в SOGo (персональные или общие псевдонимы, указывающие как минимум на один локальный почтовый аккаунт). Учтите, что если функция отключена, у пользователей не будет возможности выбрать адрес псевдонима в качестве отправителя в SOGo.",
|
||||
"spam_alias": "Создать или изменить временные (спам) псевдонимы",
|
||||
@ -627,23 +711,7 @@
|
||||
"title": "Изменение объекта",
|
||||
"unchanged_if_empty": "Если без изменений - оставьте пустым",
|
||||
"username": "Имя пользователя",
|
||||
"validate_save": "Подтвердить и сохранить",
|
||||
"sogo_access": "Прямая переадресация в SOGo",
|
||||
"sogo_access_info": "После входа в систему пользователь автоматически перенаправляется в SOGo.",
|
||||
"app_passwd_protocols": "Разрешенные протоколы для пароля приложения",
|
||||
"domain_footer_info": "Нижние колонтитулы на уровне домена добавляются ко всем исходящим электронным письмам, связанным с адресом в этом домене. <br> Для нижнего колонтитула можно использовать следующие переменные:",
|
||||
"domain_footer_info_vars": {
|
||||
"from_name": "{= from_name =} - Из названия envelope, например, для \"Mailcow <moo@mailcow.tld>\" возвращается \"Mailcow\"",
|
||||
"auth_user": "{= auth_user =} - Аутентифицированное имя пользователя, указанное MTA",
|
||||
"from_user": "{= from_user =} - Из пользовательской части envelope, например, для \"moo@mailcow.tld\" возвращается \"moo\"",
|
||||
"from_addr": "{= from_addr =} - Из адресной части envelope",
|
||||
"from_domain": "{= from_domain =} - из доменной части envelope",
|
||||
"custom": "{= foo =} - Если почтовый ящик имеет пользовательский атрибут \"foo\" со значением \"bar\", он возвращает \"bar\"."
|
||||
},
|
||||
"domain_footer": "Нижний колонтитул домена",
|
||||
"domain_footer_html": "HTML нижний колонтитул",
|
||||
"domain_footer_plain": "ПРОСТОЙ нижний колонтитул",
|
||||
"custom_attributes": "Пользовательские атрибуты"
|
||||
"validate_save": "Подтвердить и сохранить"
|
||||
},
|
||||
"fido2": {
|
||||
"confirm": "Подтвердить",
|
||||
@ -678,10 +746,10 @@
|
||||
"header": {
|
||||
"administration": "Настройка сервера",
|
||||
"apps": "Приложения",
|
||||
"debug": "Состояние сервера",
|
||||
"debug": "Информация",
|
||||
"email": "E-Mail",
|
||||
"mailcow_system": "Система",
|
||||
"mailcow_config": "Конфигурация",
|
||||
"mailcow_system": "Система",
|
||||
"quarantine": "Карантин",
|
||||
"restart_netfilter": "Перезапустить netfilter",
|
||||
"restart_sogo": "Перезапустить SOGo",
|
||||
@ -693,12 +761,19 @@
|
||||
"session_expires": "Ваш сеанс закончится примерно через 15 секунд"
|
||||
},
|
||||
"login": {
|
||||
"back_to_mailcow": "Вернуться к mailcow",
|
||||
"delayed": "Вход был отложен на %s секунд.",
|
||||
"fido2_webauthn": "FIDO2/WebAuthn Login",
|
||||
"forgot_password": "> Забыли пароль?",
|
||||
"invalid_pass_reset_token": "Токен восстановления пароля недействителен или срок его действия истек.<br>Пожалуйста, запросите новую ссылку для восстановления пароля.",
|
||||
"login": "Войти",
|
||||
"mobileconfig_info": "Пожалуйста, войдите в систему как пользователь почтового аккаунта для загрузки профиля подключения Apple.",
|
||||
"new_password": "Новый пароль",
|
||||
"new_password_confirm": "Повторите новый пароль",
|
||||
"other_logins": "Вход с помощью ключа",
|
||||
"password": "Пароль",
|
||||
"request_reset_password": "Запросить восстановление пароля",
|
||||
"reset_password": "Восстановление пароля",
|
||||
"username": "Имя пользователя"
|
||||
},
|
||||
"mailbox": {
|
||||
@ -716,6 +791,7 @@
|
||||
"add_mailbox": "Добавить почтовый аккаунт",
|
||||
"add_recipient_map_entry": "Добавить перезапись получателя",
|
||||
"add_resource": "Добавить ресурс",
|
||||
"add_template": "Добавить шаблон",
|
||||
"add_tls_policy_map": "Добавить политику TLS",
|
||||
"address_rewriting": "Перезапись адресов",
|
||||
"alias": "Псевдоним",
|
||||
@ -740,12 +816,12 @@
|
||||
"bcc_to_rcpt": "Переключиться на тип \"получатель\"",
|
||||
"bcc_to_sender": "Переключиться на тип \"отправитель\"",
|
||||
"bcc_type": "Тип BCC",
|
||||
"booking_null": "Всегда показывать как свободный",
|
||||
"booking_0_short": "Всегда свободнен",
|
||||
"booking_custom": "Лимит на количество бронирований",
|
||||
"booking_custom_short": "Жесткий лимит",
|
||||
"booking_ltnull": "Неограниченный, занят при бронировании",
|
||||
"booking_lt0_short": "Неограниченный лимит",
|
||||
"booking_ltnull": "Неограниченный, занят при бронировании",
|
||||
"booking_null": "Всегда показывать как свободный",
|
||||
"catch_all": "Catch-all",
|
||||
"created_on": "Дата создания",
|
||||
"daily": "Раз в день",
|
||||
@ -760,6 +836,7 @@
|
||||
"domain_aliases": "Псевдонимы доменов",
|
||||
"domain_quota": "Квота",
|
||||
"domain_quota_total": "Квота домена",
|
||||
"domain_templates": "Шаблоны доменов",
|
||||
"domains": "Домены",
|
||||
"edit": "Изменить",
|
||||
"empty": "Пусто",
|
||||
@ -787,6 +864,7 @@
|
||||
"mailbox_defaults_info": "Установите настройки по умолчанию для новых почтовых аккаунтов.",
|
||||
"mailbox_defquota": "Квота по умолчанию",
|
||||
"mailbox_quota": "Макс. квота почт. ящика",
|
||||
"mailbox_templates": "Шаблоны почтовых ящиков",
|
||||
"mailboxes": "Почтовые ящики",
|
||||
"max_aliases": "Максимум псевдонимов",
|
||||
"max_mailboxes": "Максимум почтовых ящиков",
|
||||
@ -814,16 +892,17 @@
|
||||
"recipient_map_new": "Перезапись на",
|
||||
"recipient_map_new_info": "Должен быть действующим почтовым ящиком.",
|
||||
"recipient_map_old": "Получатель",
|
||||
"recipient_map_old_info": "Должен быть валидный почтовым ящиком или доменом.",
|
||||
"recipient_map_old_info": "Должен быть действующим почтовым ящиком или доменом.",
|
||||
"recipient_maps": "Перезапись получателя",
|
||||
"relay_all": "Ретрансляция всех получателей",
|
||||
"relay_unknown": "Ретрансляция неизвестных получателей",
|
||||
"remove": "Удалить",
|
||||
"resources": "Ресурсы",
|
||||
"running": "В процессе",
|
||||
"sender": "Отправитель",
|
||||
"set_postfilter": "Использовать как постфильтр",
|
||||
"set_prefilter": "Использовать как предварительный фильтр",
|
||||
"sieve_info": "Вы можете сохранить несколько фильтров для каждого пользователя, но только один предварительный фильтр и один постфильтр могут быть активными одновременно.<br>\r\n Каждый фильтр будет обработан в описанном порядке. Не сломанный скрипт, не <code>keep;</code> не остановит обработку дальнейших скриптов.<br><br>Global sieve prefilter • Prefilter • User scripts • Postfilter • Global sieve postfilter",
|
||||
"sieve_info": "Вы можете сохранить несколько фильтров для каждого пользователя, но только один предварительный фильтр и один постфильтр могут быть активными одновременно.<br>\r\n Каждый фильтр будет обработан в описанном порядке. Ни сломанный скрипт, ни <code>keep;</code> не остановит обработку дальнейших скриптов.<br><br>Global sieve prefilter • Prefilter • User scripts • Postfilter • Global sieve postfilter",
|
||||
"sieve_preset_1": "Discard mail with probable dangerous file types",
|
||||
"sieve_preset_2": "Always mark the e-mail of a specific sender as seen",
|
||||
"sieve_preset_3": "Discard silently, stop all further sieve processing",
|
||||
@ -831,7 +910,7 @@
|
||||
"sieve_preset_5": "Auto responder (vacation)",
|
||||
"sieve_preset_6": "Reject mail with response",
|
||||
"sieve_preset_7": "Redirect and keep/drop",
|
||||
"sieve_preset_8": "Discard message sent to an alias address the sender is part of",
|
||||
"sieve_preset_8": "Переслать письмо от определенного отправителя, пометить его как прочитанное и поместить в подпапку",
|
||||
"sieve_preset_header": "Пожалуйста, ознакомьтесь с примерами ниже. Для более подробной информации прочитайте <a href=\"https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)\" target=\"_blank\">Sieve Wikipedia</a>.",
|
||||
"sogo_visible": "Отображать псевдоним в SOGo",
|
||||
"sogo_visible_n": "Не отображать псевдоним в SOGo",
|
||||
@ -840,25 +919,27 @@
|
||||
"stats": "Статистика",
|
||||
"status": "Статус",
|
||||
"sync_jobs": "Задания синхронизации",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE": "Ошибка авторизации",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Неправильное имя пользователя или пароль",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE": "Ошибка связи с сервером",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Не удалось подключиться к удаленному серверу",
|
||||
"syncjob_EXIT_OVERQUOTA": "Целевой почтовый ящик превысил квоту",
|
||||
"syncjob_EXIT_TLS_FAILURE": "Ошибка установки шифрованного соединения",
|
||||
"syncjob_EX_OK": "Успешно",
|
||||
"syncjob_check_log": "Проверить журнал",
|
||||
"syncjob_last_run_result": "Результат последнего запуска",
|
||||
"syncjob_EX_OK": "Успешно",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE": "Ошибка связи с сервером",
|
||||
"syncjob_EXIT_TLS_FAILURE": "Ошибка установки шифрованного соединения",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE": "Ошибка авторизации",
|
||||
"syncjob_EXIT_OVERQUOTA": "Целевой почтовый ящик превысил квоту",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Не удалось подключиться к удаленному серверу",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Неправильное имя пользователя или пароль",
|
||||
"table_size": "Размер таблицы",
|
||||
"table_size_show_n": "Отображать %s полей",
|
||||
"target_address": "Владельцы псевдонима",
|
||||
"target_domain": "Целевой домен",
|
||||
"template": "Шаблон",
|
||||
"templates": "Шаблоны",
|
||||
"tls_enforce_in": "Принудительный TLS (входящие)",
|
||||
"tls_enforce_out": "Принудительный TLS (исходящие)",
|
||||
"tls_map_dest": "Назначение",
|
||||
"tls_map_dest_info": "пример: example.org, .example.org, [mail.example.org]:25",
|
||||
"tls_map_parameters": "Параметры",
|
||||
"tls_map_parameters_info": "Оставьте поле пустым или укажите параметры, на пример: protocols=!SSLv2 ciphers=medium exclude=3DES",
|
||||
"tls_map_parameters_info": "Оставьте поле пустым или укажите параметры, например: protocols=!SSLv2 ciphers=medium exclude=3DES",
|
||||
"tls_map_policy": "Политика",
|
||||
"tls_policy_maps": "Правила TLS",
|
||||
"tls_policy_maps_enforced_tls": "Для исходящих сообщений от пользователей с включенной принудительной политикой шифрования исходящих соединений не описанные глобальной политикой,<br>\r\n будут применены значения по умолчанию, указанные в <code>smtp_tls_mandatory_protocols</code> и <code>smtp_tls_mandatory_ciphers</code>.",
|
||||
@ -933,14 +1014,27 @@
|
||||
"type": "Тип"
|
||||
},
|
||||
"queue": {
|
||||
"queue_manager": "Очередь на отправку"
|
||||
"ays": "Пожалуйста, подтвердите, что вы хотите удалить все элементы из текущей очереди.",
|
||||
"delete": "Удалить все",
|
||||
"deliver_mail": "Доставить",
|
||||
"deliver_mail_legend": "Попытаться повторно доставить выбранные письма.",
|
||||
"flush": "Обработать очередь",
|
||||
"hold_mail": "Отложить",
|
||||
"hold_mail_legend": "Удержать выбранные сообщения. (Предотвратить дальнейшие попытки доставки)",
|
||||
"info": "Очередь отправки почты содержит все письма, которые ожидают доставки. Если письмо надолго задерживается в почтовой очереди, оно автоматически удаляется системой.<br>Сообщение об ошибке в соответствующих письмах содержит информацию о том, почему письмо не удалось доставить.",
|
||||
"legend": "Описание действий с почтовой очередью:",
|
||||
"queue_manager": "Очередь на отправку",
|
||||
"show_message": "Показать сообщение",
|
||||
"unhold_mail": "Высвободить",
|
||||
"unhold_mail_legend": "Освобождает выбранные письма для доставки. (Требуется предварительное удержание)",
|
||||
"unban": "освободить очередь"
|
||||
},
|
||||
"ratelimit": {
|
||||
"day": "сообщений / день",
|
||||
"disabled": "Отключен",
|
||||
"second": "сообщений / секунду",
|
||||
"minute": "сообщений / минуту",
|
||||
"hour": "сообщений / час",
|
||||
"day": "сообщений / день"
|
||||
"minute": "сообщений / минуту",
|
||||
"second": "сообщений / секунду"
|
||||
},
|
||||
"start": {
|
||||
"help": "Справка",
|
||||
@ -966,6 +1060,7 @@
|
||||
"bcc_deleted": "Правила BCC удалены: %s",
|
||||
"bcc_edited": "Правило BCC %s отредактировано",
|
||||
"bcc_saved": "Правило BCC сохранено",
|
||||
"cors_headers_edited": "Настройки CORS сохранены",
|
||||
"db_init_complete": "Инициализация базы данных завершена",
|
||||
"delete_filter": "Фильтр ID %s удалён",
|
||||
"delete_filters": "Фильтры удалены: %s",
|
||||
@ -974,19 +1069,23 @@
|
||||
"dkim_added": "DKIM ключ сохранён",
|
||||
"dkim_duplicated": "DKIM ключи для домена %s были скопированы в %s",
|
||||
"dkim_removed": "DKIM ключ %s удалён",
|
||||
"domain_add_dkim_available": "DKIM ключ уже существует",
|
||||
"domain_added": "Добавлен домен %s",
|
||||
"domain_admin_added": "Администратор домена %s добавлен",
|
||||
"domain_admin_modified": "Сохранить изменения администратора домена %s",
|
||||
"domain_admin_removed": "Администратор домена %s удалён",
|
||||
"domain_footer_modified": "Изменения в нижнем колонтитуле домена %s сохранены",
|
||||
"domain_modified": "Сохранить изменения домена %s",
|
||||
"domain_removed": "Домен %s удалён",
|
||||
"dovecot_restart_success": "Dovecot перезапущен успешно",
|
||||
"eas_reset": "Кеш ActiveSync для пользователя %s был сброшен",
|
||||
"f2b_banlist_refreshed": "Идентификатор банлиста был успешно обновлен.",
|
||||
"f2b_modified": "Изменения параметров Fail2ban сохранены",
|
||||
"forwarding_host_added": "Перенаправление узла %s добавлено",
|
||||
"forwarding_host_removed": "Перенаправление узла %s удалено",
|
||||
"global_filter_written": "Фильтр успешно записан в файл",
|
||||
"hash_deleted": "Хеш удалён",
|
||||
"ip_check_opt_in_modified": "Параметры проверки IP успешно обновлены",
|
||||
"item_deleted": "Обьект %s удалён",
|
||||
"item_released": "Письмо %s восстановлено из карантина",
|
||||
"items_deleted": "Обьекты %s удалены",
|
||||
@ -997,14 +1096,17 @@
|
||||
"mailbox_added": "Почтовый аккаунт %s добавлен",
|
||||
"mailbox_modified": "Изменения почтового аккаунта %s сохранены",
|
||||
"mailbox_removed": "Почтовый аккаунт %s удалён",
|
||||
"mailbox_renamed": "Почтовый аккаунт %s был переименован в %s",
|
||||
"nginx_reloaded": "Обновление конфигурация Nginx закончено",
|
||||
"object_modified": "Изменения объекта %s сохранены",
|
||||
"password_changed_success": "Пароль был успешно изменен",
|
||||
"password_policy_saved": "Политика паролей сохранена",
|
||||
"pushover_settings_edited": "Настройки сохранены, пожалуйста, выполните проверку доступа",
|
||||
"qlearn_spam": "Письмо ID %s было изучено как спам и удалено",
|
||||
"queue_command_success": "Команда выполнена успешно",
|
||||
"recipient_map_entry_deleted": "Правило перезаписи получателя ID %s было удалено",
|
||||
"recipient_map_entry_saved": "Правило перезаписи получателя \"%s\" было сохранено",
|
||||
"recovery_email_sent": "Письмо для восстановления пароля отправлено на %s",
|
||||
"relayhost_added": "Промежуточный узел %s добавлен",
|
||||
"relayhost_removed": "Промежуточный узел %s удалён",
|
||||
"reset_main_logo": "Восстановить логотип по умолчанию",
|
||||
@ -1017,6 +1119,9 @@
|
||||
"settings_map_added": "Правило добавлено",
|
||||
"settings_map_removed": "Правило ID %s удалено",
|
||||
"sogo_profile_reset": "Профиль пользователя SOGo %s сброшен",
|
||||
"template_added": "Шаблон %s добавлен",
|
||||
"template_modified": "Изменения шаблона %s сохранены",
|
||||
"template_removed": "Шаблон ID %s удален",
|
||||
"tls_policy_map_entry_deleted": "Политика TLS ID %s удалено",
|
||||
"tls_policy_map_entry_saved": "Политика TLS \"%s\" сохранена",
|
||||
"ui_texts": "Изменения текстов UI сохранены",
|
||||
@ -1024,13 +1129,11 @@
|
||||
"verified_fido2_login": "Авторизация FIDO2 пройдена",
|
||||
"verified_totp_login": "Авторизация TOTP пройдена",
|
||||
"verified_webauthn_login": "Авторизация WebAuthn пройдена",
|
||||
"verified_yotp_login": "Авторизация Yubico OTP пройдена",
|
||||
"cors_headers_edited": "Настройки CORS сохранены",
|
||||
"domain_footer_modified": "Изменения в нижнем колонтитуле домена %s сохранены",
|
||||
"f2b_banlist_refreshed": "Идентификатор банлиста был успешно обновлен."
|
||||
"verified_yotp_login": "Авторизация Yubico OTP пройдена"
|
||||
},
|
||||
"tfa": {
|
||||
"api_register": "%s использует Yubico Cloud API. Пожалуйста, получите ключ API для вашего ключа <a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">здесь</a>",
|
||||
"authenticators": "Аутентификаторы",
|
||||
"confirm": "Подтвердите",
|
||||
"confirm_totp_token": "Пожалуйста, подтвердите изменения, введя сгенерированный код",
|
||||
"delete_tfa": "Отключить TFA",
|
||||
@ -1049,11 +1152,12 @@
|
||||
"tfa": "Двухфакторная проверка подлинности",
|
||||
"tfa_token_invalid": "Неправильный TFA токен",
|
||||
"totp": "OTP (Authy, Google Authenticator и др.)",
|
||||
"webauthn": "WebAuthn аутентификация",
|
||||
"u2f_deprecated": "Похоже, что ваш ключ был зарегистрирован с использованием устаревшего метода U2F. Мы деактивируем для вас двухфакторную аутентификацию и удалим ваш ключ.",
|
||||
"u2f_deprecated_important": "Пожалуйста, зарегистрируйте ваш ключ в панели администратора с помощью нового метода WebAuthn.",
|
||||
"waiting_usb_auth": "<i>Ожидание устройства USB...</i><br><br>Пожалуйста, нажмите кнопку на USB устройстве сейчас.",
|
||||
"waiting_usb_register": "<i>Ожидание устройства USB...</i><br><br>Пожалуйста, введите пароль выше и подтвердите регистрацию, нажав кнопку на USB устройстве.",
|
||||
"yubi_otp": "Yubico OTP аутентификация",
|
||||
"u2f_deprecated": "Похоже, что ваш ключ был зарегистрирован с использованием устаревшего метода U2F. Мы деактивируем для вас двухфакторную аутентификацию и удалим ваш ключ."
|
||||
"webauthn": "WebAuthn аутентификация",
|
||||
"yubi_otp": "Yubico OTP аутентификация"
|
||||
},
|
||||
"user": {
|
||||
"action": "Действия",
|
||||
@ -1070,13 +1174,17 @@
|
||||
"alias_valid_until": "Действителен до",
|
||||
"aliases_also_send_as": "Разрешено отправлять письма от имени",
|
||||
"aliases_send_as_all": "Разрешено отправлять письма от любого имени для домена и его псевдонимов",
|
||||
"allowed_protocols": "Разрешенные протоколы",
|
||||
"app_hint": "Пароли приложений - это альтернативные пароли для авторизации в IMAP, SMTP, CalDAV, CardDAV и EAS. При этом имя пользователя остается неизменным. <br>SOGo недоступен через пароли приложений.",
|
||||
"app_name": "Название приложения",
|
||||
"app_passwds": "Пароли приложений",
|
||||
"apple_connection_profile": "Профиль подключения Apple",
|
||||
"apple_connection_profile_complete": "Этот профиль включает настройки IMAP и SMTP, а также CalDAV (календарей) и CardDAV (контактов) для устройства Apple.",
|
||||
"apple_connection_profile_mailonly": "Этот профиль включает только настройки IMAP и SMTP для устройства Apple.",
|
||||
"apple_connection_profile_with_app_password": "Новый пароль приложения генерируется и добавляется в профиль, поэтому при настройке устройства не требуется вводить пароль. Не предоставляйте доступ к файлу, поскольку он предоставляет полный доступ к вашему почтовому ящику.",
|
||||
"attribute": "Атрибут",
|
||||
"change_password": "Изменить пароль",
|
||||
"change_password_hint_app_passwords": "В вашей учетной записи есть %d паролей приложений, которые не будут изменены. Чтобы управлять ими, перейдите на вкладку \"Пароли приложений\".",
|
||||
"clear_recent_successful_connections": "Очистить историю успешных подключений",
|
||||
"client_configuration": "Показать руководство по настройке почтовых клиентов и смартфонов",
|
||||
"create_app_passwd": "Создать новый пароль",
|
||||
@ -1087,6 +1195,7 @@
|
||||
"delete_ays": "Пожалуйста, подтвердите удаление",
|
||||
"direct_aliases": "Личные псевдонимы",
|
||||
"direct_aliases_desc": "На личные псевдонимы распространяются фильтры нежелательной почты и параметры политики TLS.",
|
||||
"direct_protocol_access": "Этот пользователь почтового ящика имеет <b>прямой, внешний доступ</b> к следующим протоколам и приложениям. Эта настройка контролируется вашим администратором. Для предоставления доступа к отдельным протоколам и приложениям могут быть созданы пароли приложений.<br> Кнопка \"Вход в веб-почту\" обеспечивает единый вход в SOGo и всегда доступна.",
|
||||
"eas_reset": "Сбросить кеш ActiveSync устройств",
|
||||
"eas_reset_help": "Во многих случаях сброс кеша устройств помогает восстановить повреждённый профиль ActiveSync.<br><b>Внимание:</b> все письма, календари и контакты будут загружены заново на все ваши устройства!",
|
||||
"eas_reset_now": "Сбросить кеш сейчас",
|
||||
@ -1131,15 +1240,18 @@
|
||||
"password": "Пароль",
|
||||
"password_now": "Текущий пароль (подтверждение изменения)",
|
||||
"password_repeat": "Подтверждение пароля (повтор)",
|
||||
"password_reset_info": "If no email for password recovery is provided, this function cannot be used.",
|
||||
"pushover_evaluate_x_prio": "Установить высокий приоритет уведомлений для писем с высоким приоритетом [<code>X-Priority: 1</code>]",
|
||||
"pushover_info": "Настройки Push-уведомления будут применяться ко всей почте <b>%s</b> (за исключением спама), включая псевдонимы (личные, общие и тегированные).",
|
||||
"pushover_only_x_prio": "Получать уведомления только о письмах с высоким приоритетом [<code>X-Priority: 1</code>]",
|
||||
"pushover_sender_array": "Получать уведомления от списка адресов электронной почты <small>(envelop-from, разделённые запятыми)</small>:",
|
||||
"pushover_sender_regex": "Получать уведомления от отправителей, удовлетворяющих regex-выражению:",
|
||||
"pushover_sound": "Звук уведомления",
|
||||
"pushover_text": "Текст уведомления",
|
||||
"pushover_title": "Заголовок уведомления",
|
||||
"pushover_vars": "Когда фильтрация по отправителю не определена, уведомения будут доставлятся от всех отправителей.<br>Можно использовать обычный фильтр по отправителю и расширенный regex-фильтр, а также оба сразу.<br>Пожалуйста, ознакомьтесь с <a href=\"https://pushover.net/privacy\">Pushover Privacy Policy</a> перед использованием шаблонов для текста и заголовка",
|
||||
"pushover_verify": "Проверить доступ",
|
||||
"pw_recovery_email": "Адрес для восстановления пароля",
|
||||
"q_add_header": "Нежелательная почта",
|
||||
"q_all": "Все категории",
|
||||
"q_reject": "Отклонённая почта",
|
||||
@ -1180,15 +1292,15 @@
|
||||
"spamfilter_yellow": "Жёлтый: эти письма могут быть спамом, будут доставлены в папку \"Спам\"",
|
||||
"status": "Статус",
|
||||
"sync_jobs": "Задания синхронизации",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE": "Ошибка авторизации",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Неправильное имя пользователя или пароль",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE": "Ошибка связи с сервером",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Не удалось подключиться к удаленному серверу",
|
||||
"syncjob_EXIT_OVERQUOTA": "Целевой почтовый ящик превысил квоту",
|
||||
"syncjob_EXIT_TLS_FAILURE": "Ошибка установки шифрованного соединения",
|
||||
"syncjob_EX_OK": "Успешно",
|
||||
"syncjob_check_log": "Проверить журнал",
|
||||
"syncjob_last_run_result": "Результат",
|
||||
"syncjob_EX_OK": "Успешно",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE": "Ошибка связи с сервером",
|
||||
"syncjob_EXIT_TLS_FAILURE": "Ошибка установки шифрованного соединения",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE": "Ошибка авторизации",
|
||||
"syncjob_EXIT_OVERQUOTA": "Целевой почтовый ящик превысил квоту",
|
||||
"syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Не удалось подключиться к удаленному серверу",
|
||||
"syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Неправильное имя пользователя или пароль",
|
||||
"tag_handling": "Обработка тегированной почты",
|
||||
"tag_help_example": "Пример тегированного адреса электронной почты: <code>ich<b>+Facebook</b>@example.org</code>",
|
||||
"tag_help_explain": "Переместить в подпапку: будет создана новая подпапка в INBOX с именем тега, например: \"INBOX/Facebook\".<br>\r\n Добавить к теме письма: имя тега будет добавлено к теме письма, например: \"[Facebook] My News\".",
|
||||
@ -1203,20 +1315,15 @@
|
||||
"tls_policy_warning": "<strong>Предупреждение:</strong> Если вы включите принудительное шифрованние почты, вы можете столкнуться с потерей писем.<br>Сообщения, которые не соответствуют политике, будут отбрасываться с сообщением почтовым сервером о серьёзном сбое.<br>Этот параметр применяется к вашему основному адресу электронной почты (логину), всем личным псевдонимам и псевдонимам доменов. Подразумеваются только псевдонимы <b>с одним почтовым ящиком</b>, как получатель.",
|
||||
"user_settings": "Настройки пользователя",
|
||||
"username": "Имя пользователя",
|
||||
"value": "Значение",
|
||||
"verify": "Проверить",
|
||||
"waiting": "В ожидании",
|
||||
"week": "неделю",
|
||||
"weekly": "Раз в неделю",
|
||||
"weeks": "недели",
|
||||
"year": "год",
|
||||
"years": "лет",
|
||||
"allowed_protocols": "Разрешенные протоколы",
|
||||
"apple_connection_profile_with_app_password": "Новый пароль приложения генерируется и добавляется в профиль, поэтому при настройке устройства не требуется вводить пароль. Не предоставляйте доступ к файлу, поскольку он предоставляет полный доступ к вашему почтовому ящику.",
|
||||
"direct_protocol_access": "Этот пользователь почтового ящика имеет <b>прямой, внешний доступ</b> к следующим протоколам и приложениям. Эта настройка контролируется вашим администратором. Для предоставления доступа к отдельным протоколам и приложениям могут быть созданы пароли приложений.<br> Кнопка \"веб-почту\" обеспечивает единый вход в SOGo и всегда доступна.",
|
||||
"with_app_password": "с паролем приложения",
|
||||
"change_password_hint_app_passwords": "В вашей учетной записи есть {{number_of_app_passwords}} паролей приложений, которые не будут изменены. Чтобы управлять ими, перейдите на вкладку \"Пароли приложений\".",
|
||||
"attribute": "Атрибут",
|
||||
"value": "Значение"
|
||||
"year": "год",
|
||||
"years": "лет"
|
||||
},
|
||||
"warning": {
|
||||
"cannot_delete_self": "Вы не можете удалить сами себя",
|
||||
@ -1230,10 +1337,5 @@
|
||||
"quota_exceeded_scope": "Квота домена превышена: могут быть созданы только почтовые ящики без лимита.",
|
||||
"session_token": "Неверный токен формы: несоответствие токена",
|
||||
"session_ua": "Неверный токен формы: ошибка проверки User-Agent"
|
||||
},
|
||||
"datatables": {
|
||||
"collapse_all": "Свернуть все",
|
||||
"expand_all": "Развернуть все",
|
||||
"infoPostFix": ""
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ $template_data = [
|
||||
'mailboxes' => $mailboxes,
|
||||
'lang_mailbox' => json_encode($lang['mailbox']),
|
||||
'lang_rl' => json_encode($lang['ratelimit']),
|
||||
'lang_edit' => json_encode($lang['edit']),
|
||||
'lang_datatables' => json_encode($lang['datatables']),
|
||||
];
|
||||
|
||||
|
@ -99,7 +99,7 @@
|
||||
{% endif %}
|
||||
<form class="form-inline" data-id="f2b_banlist" role="form" method="post">
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" aria-label="Banlist url" value="{{ f2b_banlist_url}}" id="banlist_url">
|
||||
<input type="text" class="form-control" aria-label="Banlist url" value="{{ f2b_banlist_url }}" id="banlist_url">
|
||||
{% if is_https %}
|
||||
<button class="btn btn-secondary" type="button" onclick="copyToClipboard('banlist_url')"><i class="bi bi-clipboard"></i></button>
|
||||
{% endif %}
|
||||
|
@ -68,6 +68,7 @@
|
||||
var acl = '{{ acl_json|raw }}';
|
||||
var lang = {{ lang_mailbox|raw }};
|
||||
var lang_rl = {{ lang_rl|raw }};
|
||||
var lang_edit = {{ lang_edit|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||
|
@ -43,8 +43,10 @@ services:
|
||||
|
||||
redis-mailcow:
|
||||
image: redis:7-alpine
|
||||
entrypoint: /redis-conf.sh
|
||||
volumes:
|
||||
- redis-vol-1:/data/
|
||||
- ./data/conf/redis/redis-conf.sh:/redis-conf.sh:z
|
||||
restart: always
|
||||
depends_on:
|
||||
- netfilter-mailcow
|
||||
@ -52,6 +54,7 @@ services:
|
||||
- "${REDIS_PORT:-127.0.0.1:7654}:6379"
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
- REDISPASS=${REDISPASS}
|
||||
sysctls:
|
||||
- net.core.somaxconn=4096
|
||||
networks:
|
||||
@ -80,7 +83,7 @@ services:
|
||||
- clamd
|
||||
|
||||
rspamd-mailcow:
|
||||
image: mailcow/rspamd:1.98
|
||||
image: mailcow/rspamd:1.99
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
- dovecot-mailcow
|
||||
@ -91,6 +94,7 @@ services:
|
||||
- IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
||||
volumes:
|
||||
- ./data/hooks/rspamd:/hooks:Z
|
||||
@ -112,7 +116,7 @@ services:
|
||||
- rspamd
|
||||
|
||||
php-fpm-mailcow:
|
||||
image: mailcow/phpfpm:1.91.1
|
||||
image: mailcow/phpfpm:1.92
|
||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||
depends_on:
|
||||
- redis-mailcow
|
||||
@ -147,6 +151,7 @@ services:
|
||||
environment:
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
- LOG_LINES=${LOG_LINES:-9999}
|
||||
- TZ=${TZ}
|
||||
- DBNAME=${DBNAME}
|
||||
@ -193,7 +198,7 @@ services:
|
||||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: mailcow/sogo:nightly-20241112
|
||||
image: mailcow/sogo:nightly-20241205
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
@ -210,6 +215,7 @@ services:
|
||||
- MASTER=${MASTER:-y}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
volumes:
|
||||
@ -240,7 +246,7 @@ services:
|
||||
- sogo
|
||||
|
||||
dovecot-mailcow:
|
||||
image: mailcow/dovecot:nightly-20241112
|
||||
image: mailcow/dovecot:nightly-20241205
|
||||
depends_on:
|
||||
- mysql-mailcow
|
||||
- netfilter-mailcow
|
||||
@ -282,6 +288,7 @@ services:
|
||||
- MASTER=${MASTER:-y}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
|
||||
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-n}
|
||||
ports:
|
||||
@ -324,7 +331,7 @@ services:
|
||||
- dovecot
|
||||
|
||||
postfix-mailcow:
|
||||
image: mailcow/postfix:1.77
|
||||
image: mailcow/postfix:1.78
|
||||
depends_on:
|
||||
mysql-mailcow:
|
||||
condition: service_started
|
||||
@ -346,6 +353,7 @@ services:
|
||||
- DBPASS=${DBPASS}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
||||
cap_add:
|
||||
@ -375,33 +383,26 @@ services:
|
||||
|
||||
nginx-mailcow:
|
||||
depends_on:
|
||||
- sogo-mailcow
|
||||
- php-fpm-mailcow
|
||||
- redis-mailcow
|
||||
image: nginx:mainline-alpine
|
||||
- php-fpm-mailcow
|
||||
- sogo-mailcow
|
||||
- rspamd-mailcow
|
||||
image: mailcow/nginx:1.00
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
command: /bin/sh -c "envsubst < /etc/nginx/conf.d/templates/listen_plain.template > /etc/nginx/conf.d/listen_plain.active &&
|
||||
envsubst < /etc/nginx/conf.d/templates/listen_ssl.template > /etc/nginx/conf.d/listen_ssl.active &&
|
||||
envsubst < /etc/nginx/conf.d/templates/sogo.template > /etc/nginx/conf.d/sogo.active &&
|
||||
. /etc/nginx/conf.d/templates/server_name.template.sh > /etc/nginx/conf.d/server_name.active &&
|
||||
. /etc/nginx/conf.d/templates/sites.template.sh > /etc/nginx/conf.d/sites.active &&
|
||||
. /etc/nginx/conf.d/templates/sogo_eas.template.sh > /etc/nginx/conf.d/sogo_eas.active &&
|
||||
nginx -qt &&
|
||||
until ping phpfpm -c1 > /dev/null; do sleep 1; done &&
|
||||
until ping sogo -c1 > /dev/null; do sleep 1; done &&
|
||||
until ping redis -c1 > /dev/null; do sleep 1; done &&
|
||||
until ping rspamd -c1 > /dev/null; do sleep 1; done &&
|
||||
exec nginx -g 'daemon off;'"
|
||||
environment:
|
||||
- HTTPS_PORT=${HTTPS_PORT:-443}
|
||||
- HTTP_PORT=${HTTP_PORT:-80}
|
||||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||
- IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
|
||||
- ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
|
||||
- TZ=${TZ}
|
||||
- SKIP_SOGO=${SKIP_SOGO:-n}
|
||||
- ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
|
||||
- ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
|
||||
- SKIP_RSPAMD=${SKIP_RSPAMD:-n}
|
||||
- PHPFPMHOST=${PHPFPMHOST:-php-fpm-mailcow}
|
||||
- SOGOHOST=${SOGOHOST:-sogo-mailcow}
|
||||
- RSPAMDHOST=${RSPAMDHOST:-rspamd-mailcow}
|
||||
- REDISHOST=${REDISHOST:-redis-mailcow}
|
||||
- IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
|
||||
volumes:
|
||||
- ./data/web:/web:ro,z
|
||||
- ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
|
||||
@ -428,7 +429,7 @@ services:
|
||||
condition: service_started
|
||||
unbound-mailcow:
|
||||
condition: service_healthy
|
||||
image: mailcow/acme:1.90
|
||||
image: mailcow/acme:1.91
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
environment:
|
||||
@ -451,6 +452,7 @@ services:
|
||||
- TZ=${TZ}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
- SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n}
|
||||
- SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
|
||||
volumes:
|
||||
@ -465,7 +467,7 @@ services:
|
||||
- acme
|
||||
|
||||
netfilter-mailcow:
|
||||
image: mailcow/netfilter:1.59
|
||||
image: mailcow/netfilter:1.60
|
||||
stop_grace_period: 30s
|
||||
restart: always
|
||||
privileged: true
|
||||
@ -477,6 +479,7 @@ services:
|
||||
- SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
- MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
|
||||
- DISABLE_NETFILTER_ISOLATION_RULE=${DISABLE_NETFILTER_ISOLATION_RULE:-n}
|
||||
network_mode: "host"
|
||||
@ -484,7 +487,7 @@ services:
|
||||
- /lib/modules:/lib/modules:ro
|
||||
|
||||
watchdog-mailcow:
|
||||
image: mailcow/watchdog:2.05
|
||||
image: mailcow/watchdog:2.06
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
tmpfs:
|
||||
@ -530,6 +533,7 @@ services:
|
||||
- HTTPS_PORT=${HTTPS_PORT:-443}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
- EXTERNAL_CHECKS_THRESHOLD=${EXTERNAL_CHECKS_THRESHOLD:-1}
|
||||
- NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
|
||||
- UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
|
||||
@ -555,7 +559,7 @@ services:
|
||||
- watchdog
|
||||
|
||||
dockerapi-mailcow:
|
||||
image: mailcow/dockerapi:2.09
|
||||
image: mailcow/dockerapi:2.10
|
||||
security_opt:
|
||||
- label=disable
|
||||
restart: always
|
||||
@ -566,6 +570,7 @@ services:
|
||||
- TZ=${TZ}
|
||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||
- REDISPASS=${REDISPASS}
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
networks:
|
||||
|
@ -26,7 +26,7 @@ for bin in openssl curl docker git awk sha1sum grep cut; do
|
||||
done
|
||||
|
||||
# Check Docker Version (need at least 24.X)
|
||||
docker_version=$(docker -v | grep -oP '\d+\.\d+\.\d+' | cut -d '.' -f 1)
|
||||
docker_version=$(docker -v | grep -oP '\d+\.\d+\.\d+' | head -n 1 | cut -d '.' -f 1)
|
||||
|
||||
if [[ $docker_version -lt 24 ]]; then
|
||||
echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m"
|
||||
@ -43,7 +43,7 @@ if docker compose > /dev/null 2>&1; then
|
||||
sleep 2
|
||||
echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m"
|
||||
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"
|
||||
exit 1
|
||||
fi
|
||||
@ -56,14 +56,14 @@ elif docker-compose > /dev/null 2>&1; then
|
||||
sleep 2
|
||||
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
|
||||
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 manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
else
|
||||
echo -e "\e[31mCannot find Docker Compose.\e[0m"
|
||||
echo -e "\e[31mCannot find Docker Compose.\e[0m"
|
||||
echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
@ -229,7 +229,7 @@ else
|
||||
echo -e "\033[31mCould not determine branch input..."
|
||||
echo -e "\033[31mExiting."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -z "${MAILCOW_BRANCH}" ]; then
|
||||
git_branch=${MAILCOW_BRANCH}
|
||||
@ -264,6 +264,12 @@ DBUSER=mailcow
|
||||
DBPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||
DBROOT=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||
|
||||
# ------------------------------
|
||||
# REDIS configuration
|
||||
# ------------------------------
|
||||
|
||||
REDISPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||
|
||||
# ------------------------------
|
||||
# HTTP/S Bindings
|
||||
# ------------------------------
|
||||
@ -510,7 +516,7 @@ WEBAUTHN_ONLY_TRUSTED_VENDORS=n
|
||||
|
||||
# Spamhaus Data Query Service Key
|
||||
# Optional: Leave empty for none
|
||||
# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.
|
||||
# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.
|
||||
# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS.
|
||||
# Otherwise it will work normally.
|
||||
SPAMHAUS_DQS_KEY=
|
||||
|
@ -150,7 +150,7 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REMOTE_ARCH=$(ssh -o StrictHostKeyChecking=no -i "${REMOTE_SSH_KEY}" ${REMOTE_SSH_HOST} -p ${REMOTE_SSH_PORT} "uname -m")
|
||||
REMOTE_ARCH=$(ssh -o StrictHostKeyChecking=no -i "${REMOTE_SSH_KEY}" ${REMOTE_SSH_HOST} -p ${REMOTE_SSH_PORT} "uname -m")
|
||||
|
||||
}
|
||||
|
||||
@ -204,7 +204,7 @@ fi
|
||||
|
||||
# Trigger a Redis save for a consistent Redis copy
|
||||
echo -ne "\033[1mRunning redis-cli save... \033[0m"
|
||||
docker exec $(docker ps -qf name=redis-mailcow) redis-cli save
|
||||
docker exec $(docker ps -qf name=redis-mailcow) redis-cli -a ${REDISPASS} --no-auth-warning save
|
||||
|
||||
# Syncing volumes related to compose project
|
||||
# Same here: make sure destination exists
|
||||
|
@ -119,7 +119,7 @@ function backup() {
|
||||
${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_crypt.tar.gz /crypt
|
||||
;;&
|
||||
redis|all)
|
||||
docker exec $(docker ps -qf name=redis-mailcow) redis-cli save
|
||||
docker exec $(docker ps -qf name=redis-mailcow) redis-cli -a ${REDISPASS} --no-auth-warning save
|
||||
docker run --name mailcow-backup --rm \
|
||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:ro,z \
|
||||
|
@ -101,11 +101,11 @@ if [[ ${NC_PURGE} == "y" ]]; then
|
||||
echo -e "\033[33mNot purging anything...\033[0m"
|
||||
exit 1
|
||||
fi
|
||||
docker exec -it $(docker ps -f name=redis-mailcow -q) /bin/sh -c ' cat <<EOF | redis-cli
|
||||
docker exec -it $(docker ps -f name=redis-mailcow -q) /bin/sh -c "cat <<EOF | redis-cli -a ${REDISPASS} --no-auth-warning
|
||||
SELECT 10
|
||||
FLUSHDB
|
||||
EOF
|
||||
'
|
||||
"
|
||||
if [ -d ./data/web/nextcloud/config ]; then
|
||||
mv ./data/web/nextcloud/config/ ./data/conf/nextcloud-config-folder-$(date +%s).bak
|
||||
fi
|
||||
|
@ -15,15 +15,15 @@ if [[ "$response" =~ ^(yes|y)$ ]]; then
|
||||
docker stop ${RSPAMD_ID}
|
||||
echo "LUA will return nil when it succeeds or print a warning/error when it fails."
|
||||
echo "Deleting all RS* keys - if any"
|
||||
docker exec -it ${REDIS_ID} redis-cli EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'RS*'
|
||||
docker exec -it ${REDIS_ID} redis-cli -a ${REDISPASS} --no-auth-warning EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'RS*'
|
||||
echo "Deleting all BAYES* keys - if any"
|
||||
docker exec -it ${REDIS_ID} redis-cli EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'BAYES*'
|
||||
docker exec -it ${REDIS_ID} redis-cli -a ${REDISPASS} --no-auth-warning EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'BAYES*'
|
||||
echo "Deleting all learned* keys - if any"
|
||||
docker exec -it ${REDIS_ID} redis-cli EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'learned*'
|
||||
docker exec -it ${REDIS_ID} redis-cli -a ${REDISPASS} --no-auth-warning EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'learned*'
|
||||
echo "Deleting all fuzzy* keys - if any"
|
||||
docker exec -it ${REDIS_ID} redis-cli EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'fuzzy*'
|
||||
docker exec -it ${REDIS_ID} redis-cli -a ${REDISPASS} --no-auth-warning EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'fuzzy*'
|
||||
echo "Deleting all tRFANN* keys - if any"
|
||||
docker exec -it ${REDIS_ID} redis-cli EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'tRFANN*'
|
||||
docker exec -it ${REDIS_ID} redis-cli -a ${REDISPASS} --no-auth-warning EVAL "for _,k in ipairs(redis.call('keys', ARGV[1])) do redis.call('del', k) end" 0 'tRFANN*'
|
||||
echo "Starting Rspamd container"
|
||||
docker start ${RSPAMD_ID}
|
||||
fi
|
||||
|
15
update.sh
15
update.sh
@ -288,9 +288,9 @@ fix_broken_dnslist_conf() {
|
||||
# Check if the file contains the autogenerated comment
|
||||
if grep -q "# Autogenerated by mailcow" "$file"; then
|
||||
# Ask the user if custom changes were made
|
||||
echo -e "\e[91mWARNING!!! \e[31mAn old version of dns_blocklists.cnf has been detected which may cause a broken postfix upon startup (see: https://github.com/mailcow/mailcow-dockerized/issues/6143)...\e[0m"
|
||||
echo -e "\e[91mWARNING!!! \e[31mAn old version of dns_blocklists.cf has been detected which may cause a broken postfix upon startup (see: https://github.com/mailcow/mailcow-dockerized/issues/6143)...\e[0m"
|
||||
echo -e "\e[31mIf you have any custom settings in there you might copy it away and adapt the changes after the file is regenerated...\e[0m"
|
||||
read -p "Do you want to delete the file now and let mailcow regenerate it properly? " response
|
||||
read -p "Do you want to delete the file now and let mailcow regenerate it properly? [y/n]" response
|
||||
if [[ "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||
rm "$file"
|
||||
echo -e "\e[32mdns_blocklists.cf has been deleted and will be properly regenerated"
|
||||
@ -299,7 +299,7 @@ fix_broken_dnslist_conf() {
|
||||
echo -e "\e[35mOk, not deleting it! Please make sure you take a look at postfix upon start then..."
|
||||
return 2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
@ -540,6 +540,7 @@ CONFIG_ARRAY=(
|
||||
"SPAMHAUS_DQS_KEY"
|
||||
"SKIP_UNBOUND_HEALTHCHECK"
|
||||
"DISABLE_NETFILTER_ISOLATION_RULE"
|
||||
"REDISPASS"
|
||||
)
|
||||
|
||||
detect_bad_asn
|
||||
@ -832,6 +833,14 @@ for option in "${CONFIG_ARRAY[@]}"; do
|
||||
echo '# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost' >> mailcow.conf
|
||||
echo 'DISABLE_NETFILTER_ISOLATION_RULE=n' >> mailcow.conf
|
||||
fi
|
||||
elif [[ "${option}" == "REDISPASS" ]]; then
|
||||
if ! grep -q "${option}" mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo -e '\n# ------------------------------' >> mailcow.conf
|
||||
echo '# REDIS configuration' >> mailcow.conf
|
||||
echo -e '# ------------------------------\n' >> mailcow.conf
|
||||
echo "REDISPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)" >> mailcow.conf
|
||||
fi
|
||||
elif ! grep -q "${option}" mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo "${option}=n" >> mailcow.conf
|
||||
|
Loading…
Reference in New Issue
Block a user