mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2024-12-23 02:04:46 +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"]
|
custom: ["https://www.servercow.de/mailcow?lang=en#sal"]
|
||||||
|
@ -4,9 +4,9 @@ exec 5>&1
|
|||||||
|
|
||||||
# Do not attempt to write to slave
|
# Do not attempt to write to slave
|
||||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
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
|
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
|
fi
|
||||||
|
|
||||||
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
||||||
|
@ -124,7 +124,7 @@ case "$SUCCESS" in
|
|||||||
;;
|
;;
|
||||||
*) # non-zero is non-fun
|
*) # non-zero is non-fun
|
||||||
log_f "Failed to obtain certificate ${CERT} for domains '${CERT_DOMAINS[*]}'"
|
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}
|
exit 100${SUCCESS}
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -34,9 +34,9 @@ async def lifespan(app: FastAPI):
|
|||||||
|
|
||||||
# Init redis client
|
# Init redis client
|
||||||
if os.environ['REDIS_SLAVEOF_IP'] != "":
|
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:
|
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
|
# Init docker clients
|
||||||
sync_docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
|
sync_docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
source /source_env.sh
|
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
|
if [[ -z ${MAX_AGE} ]]; then
|
||||||
echo "Max age for quarantine items not defined"
|
echo "Max age for quarantine items not defined"
|
||||||
|
@ -14,9 +14,9 @@ done
|
|||||||
|
|
||||||
# Do not attempt to write to slave
|
# Do not attempt to write to slave
|
||||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
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
|
else
|
||||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
||||||
|
@ -31,7 +31,7 @@ try:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
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()
|
r.ping()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print('%s - trying again...' % (ex))
|
print('%s - trying again...' % (ex))
|
||||||
|
@ -23,7 +23,7 @@ else:
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
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()
|
r.ping()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print('%s - trying again...' % (ex))
|
print('%s - trying again...' % (ex))
|
||||||
|
@ -4,9 +4,9 @@ source /source_env.sh
|
|||||||
|
|
||||||
# Do not attempt to write to slave
|
# Do not attempt to write to slave
|
||||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
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
|
else
|
||||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Is replication active?
|
# Is replication active?
|
||||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
|||||||
host("`REDIS_SLAVEOF_IP`")
|
host("`REDIS_SLAVEOF_IP`")
|
||||||
persist-name("redis1")
|
persist-name("redis1")
|
||||||
port(`REDIS_SLAVEOF_PORT`)
|
port(`REDIS_SLAVEOF_PORT`)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
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`")
|
host("`REDIS_SLAVEOF_IP`")
|
||||||
persist-name("redis2")
|
persist-name("redis2")
|
||||||
port(`REDIS_SLAVEOF_PORT`)
|
port(`REDIS_SLAVEOF_PORT`)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
|||||||
host("redis-mailcow")
|
host("redis-mailcow")
|
||||||
persist-name("redis1")
|
persist-name("redis1")
|
||||||
port(6379)
|
port(6379)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
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")
|
host("redis-mailcow")
|
||||||
persist-name("redis2")
|
persist-name("redis2")
|
||||||
port(6379)
|
port(6379)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,9 +10,9 @@ catch_non_zero() {
|
|||||||
source /source_env.sh
|
source /source_env.sh
|
||||||
# Do not attempt to write to slave
|
# Do not attempt to write to slave
|
||||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
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
|
else
|
||||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||||
fi
|
fi
|
||||||
catch_non_zero "${REDIS_CMDLINE} LTRIM ACME_LOG 0 ${LOG_LINES}"
|
catch_non_zero "${REDIS_CMDLINE} LTRIM ACME_LOG 0 ${LOG_LINES}"
|
||||||
catch_non_zero "${REDIS_CMDLINE} LTRIM POSTFIX_MAILLOG 0 ${LOG_LINES}"
|
catch_non_zero "${REDIS_CMDLINE} LTRIM POSTFIX_MAILLOG 0 ${LOG_LINES}"
|
||||||
|
@ -434,9 +434,9 @@ if __name__ == '__main__':
|
|||||||
redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '')
|
redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '')
|
||||||
redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '')
|
redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '')
|
||||||
if "".__eq__(redis_slaveof_ip):
|
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:
|
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()
|
r.ping()
|
||||||
pubsub = r.pubsub()
|
pubsub = r.pubsub()
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
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_HOST="redis"
|
||||||
REDIS_PORT="6379"
|
REDIS_PORT="6379"
|
||||||
fi
|
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
|
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
||||||
echo "Waiting for Redis..."
|
echo "Waiting for Redis..."
|
||||||
@ -26,7 +26,7 @@ done
|
|||||||
# Set redis session store
|
# Set redis session store
|
||||||
echo -n '
|
echo -n '
|
||||||
session.save_handler = redis
|
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
|
' > /usr/local/etc/php/conf.d/session_store.ini
|
||||||
|
|
||||||
# Check mysql_upgrade (master and slave)
|
# Check mysql_upgrade (master and slave)
|
||||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
|||||||
host("`REDIS_SLAVEOF_IP`")
|
host("`REDIS_SLAVEOF_IP`")
|
||||||
persist-name("redis1")
|
persist-name("redis1")
|
||||||
port(`REDIS_SLAVEOF_PORT`)
|
port(`REDIS_SLAVEOF_PORT`)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
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`")
|
host("`REDIS_SLAVEOF_IP`")
|
||||||
persist-name("redis2")
|
persist-name("redis2")
|
||||||
port(`REDIS_SLAVEOF_PORT`)
|
port(`REDIS_SLAVEOF_PORT`)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -20,6 +20,7 @@ destination d_redis_ui_log {
|
|||||||
host("redis-mailcow")
|
host("redis-mailcow")
|
||||||
persist-name("redis1")
|
persist-name("redis1")
|
||||||
port(6379)
|
port(6379)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
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")
|
host("redis-mailcow")
|
||||||
persist-name("redis2")
|
persist-name("redis2")
|
||||||
port(6379)
|
port(6379)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -56,27 +56,29 @@ if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
|||||||
cat <<EOF > /etc/rspamd/local.d/redis.conf
|
cat <<EOF > /etc/rspamd/local.d/redis.conf
|
||||||
read_servers = "redis:6379";
|
read_servers = "redis:6379";
|
||||||
write_servers = "${REDIS_SLAVEOF_IP}:${REDIS_SLAVEOF_PORT}";
|
write_servers = "${REDIS_SLAVEOF_IP}:${REDIS_SLAVEOF_PORT}";
|
||||||
|
password = "${REDISPASS}";
|
||||||
timeout = 10;
|
timeout = 10;
|
||||||
EOF
|
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..."
|
echo "Waiting for Redis @redis-mailcow..."
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
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}..."
|
echo "Waiting for Redis @${REDIS_SLAVEOF_IP}..."
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
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
|
else
|
||||||
cat <<EOF > /etc/rspamd/local.d/redis.conf
|
cat <<EOF > /etc/rspamd/local.d/redis.conf
|
||||||
servers = "redis:6379";
|
servers = "redis:6379";
|
||||||
|
password = "${REDISPASS}";
|
||||||
timeout = 10;
|
timeout = 10;
|
||||||
EOF
|
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..."
|
echo "Waiting for Redis slave..."
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
redis-cli -h redis-mailcow SLAVEOF NO ONE
|
redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning SLAVEOF NO ONE
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Provide additional lua modules
|
# Provide additional lua modules
|
||||||
|
@ -22,6 +22,7 @@ destination d_redis_ui_log {
|
|||||||
host("`REDIS_SLAVEOF_IP`")
|
host("`REDIS_SLAVEOF_IP`")
|
||||||
persist-name("redis1")
|
persist-name("redis1")
|
||||||
port(`REDIS_SLAVEOF_PORT`)
|
port(`REDIS_SLAVEOF_PORT`)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
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`")
|
host("`REDIS_SLAVEOF_IP`")
|
||||||
persist-name("redis2")
|
persist-name("redis2")
|
||||||
port(`REDIS_SLAVEOF_PORT`)
|
port(`REDIS_SLAVEOF_PORT`)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,7 @@ destination d_redis_ui_log {
|
|||||||
host("redis-mailcow")
|
host("redis-mailcow")
|
||||||
persist-name("redis1")
|
persist-name("redis1")
|
||||||
port(6379)
|
port(6379)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
|
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")
|
host("redis-mailcow")
|
||||||
persist-name("redis2")
|
persist-name("redis2")
|
||||||
port(6379)
|
port(6379)
|
||||||
|
auth("`REDISPASS`")
|
||||||
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -40,9 +40,9 @@ done
|
|||||||
|
|
||||||
# Do not attempt to write to slave
|
# Do not attempt to write to slave
|
||||||
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
|
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
|
else
|
||||||
REDIS_CMDLINE="redis-cli -h redis -p 6379"
|
REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
|
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
|
touch /tmp/redis-mailcow; echo "$(tail -50 /tmp/redis-mailcow)" > /tmp/redis-mailcow
|
||||||
host_ip=$(get_container_ip redis-mailcow)
|
host_ip=$(get_container_ip redis-mailcow)
|
||||||
err_c_cur=${err_count}
|
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} -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} ))
|
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
|
||||||
progress "Redis" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c}
|
progress "Redis" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c}
|
||||||
@ -503,12 +503,12 @@ dovecot_repl_checks() {
|
|||||||
err_count=0
|
err_count=0
|
||||||
diff_c=0
|
diff_c=0
|
||||||
THRESHOLD=${DOVECOT_REPL_THRESHOLD}
|
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
|
# Reduce error count by 2 after restarting an unhealthy container
|
||||||
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
||||||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||||
err_c_cur=${err_count}
|
err_c_cur=${err_count}
|
||||||
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
|
if [[ "${D_REPL_STATUS}" != "1" ]]; then
|
||||||
err_count=$(( ${err_count} + 1 ))
|
err_count=$(( ${err_count} + 1 ))
|
||||||
fi
|
fi
|
||||||
@ -578,19 +578,19 @@ ratelimit_checks() {
|
|||||||
err_count=0
|
err_count=0
|
||||||
diff_c=0
|
diff_c=0
|
||||||
THRESHOLD=${RATELIMIT_THRESHOLD}
|
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
|
# Reduce error count by 2 after restarting an unhealthy container
|
||||||
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
|
||||||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||||
err_c_cur=${err_count}
|
err_c_cur=${err_count}
|
||||||
RL_LOG_STATUS_PREV=${RL_LOG_STATUS}
|
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
|
if [[ ${RL_LOG_STATUS_PREV} != ${RL_LOG_STATUS} ]]; then
|
||||||
err_count=$(( ${err_count} + 1 ))
|
err_count=$(( ${err_count} + 1 ))
|
||||||
echo 'Last 10 applied ratelimits (may overlap with previous reports).' > /tmp/ratelimit
|
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 'Full ratelimit buckets can be emptied by deleting the ratelimit hash from within mailcow UI (see /debug -> Protocols -> Ratelimit):' >> /tmp/ratelimit
|
||||||
echo >> /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
|
fi
|
||||||
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
|
[ ${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} ))
|
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
|
||||||
@ -673,7 +673,7 @@ acme_checks() {
|
|||||||
err_count=0
|
err_count=0
|
||||||
diff_c=0
|
diff_c=0
|
||||||
THRESHOLD=${ACME_THRESHOLD}
|
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
|
if [[ -z "${ACME_LOG_STATUS}" ]]; then
|
||||||
${REDIS_CMDLINE} SET ACME_FAIL_TIME 0
|
${REDIS_CMDLINE} SET ACME_FAIL_TIME 0
|
||||||
ACME_LOG_STATUS=0
|
ACME_LOG_STATUS=0
|
||||||
@ -685,7 +685,7 @@ acme_checks() {
|
|||||||
ACME_LOG_STATUS_PREV=${ACME_LOG_STATUS}
|
ACME_LOG_STATUS_PREV=${ACME_LOG_STATUS}
|
||||||
ACME_LC=0
|
ACME_LC=0
|
||||||
until [[ ! -z ${ACME_LOG_STATUS} ]] || [ ${ACME_LC} -ge 3 ]; do
|
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
|
sleep 3
|
||||||
ACME_LC=$((ACME_LC+1))
|
ACME_LC=$((ACME_LC+1))
|
||||||
done
|
done
|
||||||
|
@ -20,7 +20,7 @@ thread_cache_size = 8
|
|||||||
query_cache_type = 0
|
query_cache_type = 0
|
||||||
query_cache_size = 0
|
query_cache_size = 0
|
||||||
max_heap_table_size = 48M
|
max_heap_table_size = 48M
|
||||||
thread_stack = 128K
|
thread_stack = 192K
|
||||||
skip-host-cache
|
skip-host-cache
|
||||||
skip-name-resolve
|
skip-name-resolve
|
||||||
log-warnings = 0
|
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/
|
# https://github.com/stevejenkins/postwhite/
|
||||||
# 2013 total rules
|
# 1971 total rules
|
||||||
2a00:1450:4000::/36 permit
|
2a00:1450:4000::/36 permit
|
||||||
2a01:111:f400::/48 permit
|
2a01:111:f400::/48 permit
|
||||||
2a01:111:f403:8000::/50 permit
|
2a01:111:f403:8000::/50 permit
|
||||||
@ -19,8 +19,7 @@
|
|||||||
8.20.114.31 permit
|
8.20.114.31 permit
|
||||||
8.25.194.0/23 permit
|
8.25.194.0/23 permit
|
||||||
8.25.196.0/23 permit
|
8.25.196.0/23 permit
|
||||||
8.39.54.0/23 permit
|
10.162.0.0/16 permit
|
||||||
8.40.222.0/23 permit
|
|
||||||
12.130.86.238 permit
|
12.130.86.238 permit
|
||||||
13.110.208.0/21 permit
|
13.110.208.0/21 permit
|
||||||
13.110.209.0/24 permit
|
13.110.209.0/24 permit
|
||||||
@ -31,9 +30,11 @@
|
|||||||
15.200.21.50 permit
|
15.200.21.50 permit
|
||||||
15.200.44.248 permit
|
15.200.44.248 permit
|
||||||
15.200.201.185 permit
|
15.200.201.185 permit
|
||||||
|
17.41.0.0/16 permit
|
||||||
17.57.155.0/24 permit
|
17.57.155.0/24 permit
|
||||||
17.57.156.0/24 permit
|
17.57.156.0/24 permit
|
||||||
17.58.0.0/16 permit
|
17.58.0.0/16 permit
|
||||||
|
17.142.0.0/15 permit
|
||||||
17.143.234.140/30 permit
|
17.143.234.140/30 permit
|
||||||
18.156.89.250 permit
|
18.156.89.250 permit
|
||||||
18.157.243.190 permit
|
18.157.243.190 permit
|
||||||
@ -116,7 +117,6 @@
|
|||||||
40.233.64.216 permit
|
40.233.64.216 permit
|
||||||
40.233.83.78 permit
|
40.233.83.78 permit
|
||||||
40.233.88.28 permit
|
40.233.88.28 permit
|
||||||
43.228.184.0/22 permit
|
|
||||||
44.206.138.57 permit
|
44.206.138.57 permit
|
||||||
44.217.45.156 permit
|
44.217.45.156 permit
|
||||||
44.236.56.93 permit
|
44.236.56.93 permit
|
||||||
@ -325,7 +325,6 @@
|
|||||||
65.110.161.77 permit
|
65.110.161.77 permit
|
||||||
65.123.29.213 permit
|
65.123.29.213 permit
|
||||||
65.123.29.220 permit
|
65.123.29.220 permit
|
||||||
65.154.166.0/24 permit
|
|
||||||
65.212.180.36 permit
|
65.212.180.36 permit
|
||||||
66.102.0.0/20 permit
|
66.102.0.0/20 permit
|
||||||
66.119.150.192/26 permit
|
66.119.150.192/26 permit
|
||||||
@ -1114,10 +1113,8 @@
|
|||||||
98.139.245.212/31 permit
|
98.139.245.212/31 permit
|
||||||
99.78.197.208/28 permit
|
99.78.197.208/28 permit
|
||||||
99.83.190.102 permit
|
99.83.190.102 permit
|
||||||
103.2.140.0/22 permit
|
|
||||||
103.9.96.0/22 permit
|
103.9.96.0/22 permit
|
||||||
103.28.42.0/24 permit
|
103.28.42.0/24 permit
|
||||||
103.47.204.0/22 permit
|
|
||||||
103.151.192.0/23 permit
|
103.151.192.0/23 permit
|
||||||
103.168.172.128/27 permit
|
103.168.172.128/27 permit
|
||||||
104.43.243.237 permit
|
104.43.243.237 permit
|
||||||
@ -1285,9 +1282,6 @@
|
|||||||
117.120.16.0/21 permit
|
117.120.16.0/21 permit
|
||||||
119.42.242.52/31 permit
|
119.42.242.52/31 permit
|
||||||
119.42.242.156 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
|
123.126.78.64/29 permit
|
||||||
124.108.96.24/31 permit
|
124.108.96.24/31 permit
|
||||||
124.108.96.28/31 permit
|
124.108.96.28/31 permit
|
||||||
@ -1348,19 +1342,7 @@
|
|||||||
134.170.141.64/26 permit
|
134.170.141.64/26 permit
|
||||||
134.170.143.0/24 permit
|
134.170.143.0/24 permit
|
||||||
134.170.174.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
|
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.128.0/20 permit
|
||||||
136.147.135.0/24 permit
|
136.147.135.0/24 permit
|
||||||
136.147.176.0/20 permit
|
136.147.176.0/20 permit
|
||||||
@ -1375,7 +1357,6 @@
|
|||||||
139.138.46.219 permit
|
139.138.46.219 permit
|
||||||
139.138.57.55 permit
|
139.138.57.55 permit
|
||||||
139.138.58.119 permit
|
139.138.58.119 permit
|
||||||
139.167.79.86 permit
|
|
||||||
139.180.17.0/24 permit
|
139.180.17.0/24 permit
|
||||||
140.238.148.191 permit
|
140.238.148.191 permit
|
||||||
141.148.159.229 permit
|
141.148.159.229 permit
|
||||||
@ -1410,6 +1391,7 @@
|
|||||||
146.20.215.0/24 permit
|
146.20.215.0/24 permit
|
||||||
146.20.215.182 permit
|
146.20.215.182 permit
|
||||||
146.88.28.0/24 permit
|
146.88.28.0/24 permit
|
||||||
|
147.154.32.0/25 permit
|
||||||
147.243.1.47 permit
|
147.243.1.47 permit
|
||||||
147.243.1.48 permit
|
147.243.1.48 permit
|
||||||
147.243.1.153 permit
|
147.243.1.153 permit
|
||||||
@ -1450,7 +1432,6 @@
|
|||||||
157.151.208.65 permit
|
157.151.208.65 permit
|
||||||
157.255.1.64/29 permit
|
157.255.1.64/29 permit
|
||||||
158.101.211.207 permit
|
158.101.211.207 permit
|
||||||
158.120.80.0/21 permit
|
|
||||||
158.247.16.0/20 permit
|
158.247.16.0/20 permit
|
||||||
159.92.154.0/24 permit
|
159.92.154.0/24 permit
|
||||||
159.92.155.0/24 permit
|
159.92.155.0/24 permit
|
||||||
@ -1478,6 +1459,11 @@
|
|||||||
161.38.204.0/22 permit
|
161.38.204.0/22 permit
|
||||||
161.71.32.0/19 permit
|
161.71.32.0/19 permit
|
||||||
161.71.64.0/20 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
|
162.247.216.0/22 permit
|
||||||
163.47.180.0/22 permit
|
163.47.180.0/22 permit
|
||||||
163.114.130.16 permit
|
163.114.130.16 permit
|
||||||
@ -1486,7 +1472,6 @@
|
|||||||
163.114.135.16 permit
|
163.114.135.16 permit
|
||||||
164.152.23.32 permit
|
164.152.23.32 permit
|
||||||
164.177.132.168/30 permit
|
164.177.132.168/30 permit
|
||||||
165.173.128.0/24 permit
|
|
||||||
166.78.68.0/22 permit
|
166.78.68.0/22 permit
|
||||||
166.78.68.221 permit
|
166.78.68.221 permit
|
||||||
166.78.69.169 permit
|
166.78.69.169 permit
|
||||||
@ -1515,12 +1500,6 @@
|
|||||||
168.245.12.252 permit
|
168.245.12.252 permit
|
||||||
168.245.46.9 permit
|
168.245.46.9 permit
|
||||||
168.245.127.231 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.128.0/24 permit
|
||||||
170.10.129.0/24 permit
|
170.10.129.0/24 permit
|
||||||
170.10.132.56/29 permit
|
170.10.132.56/29 permit
|
||||||
@ -1626,6 +1605,7 @@
|
|||||||
192.18.139.154 permit
|
192.18.139.154 permit
|
||||||
192.18.145.36 permit
|
192.18.145.36 permit
|
||||||
192.18.152.58 permit
|
192.18.152.58 permit
|
||||||
|
192.29.103.128/25 permit
|
||||||
192.30.252.0/22 permit
|
192.30.252.0/22 permit
|
||||||
192.161.144.0/20 permit
|
192.161.144.0/20 permit
|
||||||
192.162.87.0/24 permit
|
192.162.87.0/24 permit
|
||||||
@ -1651,14 +1631,6 @@
|
|||||||
195.234.109.226 permit
|
195.234.109.226 permit
|
||||||
195.245.230.0/23 permit
|
195.245.230.0/23 permit
|
||||||
198.2.128.0/18 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.21.0.0/21 permit
|
||||||
198.37.144.0/20 permit
|
198.37.144.0/20 permit
|
||||||
198.37.152.186 permit
|
198.37.152.186 permit
|
||||||
@ -1678,15 +1650,7 @@
|
|||||||
199.16.156.0/22 permit
|
199.16.156.0/22 permit
|
||||||
199.33.145.1 permit
|
199.33.145.1 permit
|
||||||
199.33.145.32 permit
|
199.33.145.32 permit
|
||||||
199.34.22.36 permit
|
|
||||||
199.59.148.0/22 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.161.130 permit
|
||||||
199.101.162.0/25 permit
|
199.101.162.0/25 permit
|
||||||
199.122.120.0/21 permit
|
199.122.120.0/21 permit
|
||||||
@ -1698,7 +1662,6 @@
|
|||||||
202.165.102.47 permit
|
202.165.102.47 permit
|
||||||
202.177.148.100 permit
|
202.177.148.100 permit
|
||||||
202.177.148.110 permit
|
202.177.148.110 permit
|
||||||
203.31.36.0/22 permit
|
|
||||||
203.32.4.25 permit
|
203.32.4.25 permit
|
||||||
203.55.21.0/24 permit
|
203.55.21.0/24 permit
|
||||||
203.81.17.0/24 permit
|
203.81.17.0/24 permit
|
||||||
@ -1744,19 +1707,13 @@
|
|||||||
204.92.114.187 permit
|
204.92.114.187 permit
|
||||||
204.92.114.203 permit
|
204.92.114.203 permit
|
||||||
204.92.114.204/31 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.160.0/21 permit
|
||||||
204.220.168.0/21 permit
|
204.220.168.0/21 permit
|
||||||
204.220.176.0/20 permit
|
204.220.176.0/20 permit
|
||||||
204.232.168.0/24 permit
|
204.232.168.0/24 permit
|
||||||
205.139.110.0/24 permit
|
205.139.110.0/24 permit
|
||||||
205.201.128.0/20 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.137.229 permit
|
||||||
205.201.139.0/24 permit
|
|
||||||
205.207.104.0/22 permit
|
205.207.104.0/22 permit
|
||||||
205.220.167.17 permit
|
205.220.167.17 permit
|
||||||
205.220.167.98 permit
|
205.220.167.98 permit
|
||||||
@ -1784,7 +1741,6 @@
|
|||||||
207.46.132.128/27 permit
|
207.46.132.128/27 permit
|
||||||
207.46.198.0/25 permit
|
207.46.198.0/25 permit
|
||||||
207.46.200.0/27 permit
|
207.46.200.0/27 permit
|
||||||
207.58.147.64/28 permit
|
|
||||||
207.67.38.0/24 permit
|
207.67.38.0/24 permit
|
||||||
207.67.98.192/27 permit
|
207.67.98.192/27 permit
|
||||||
207.68.176.0/26 permit
|
207.68.176.0/26 permit
|
||||||
@ -1831,6 +1787,8 @@
|
|||||||
208.74.204.5 permit
|
208.74.204.5 permit
|
||||||
208.74.204.9 permit
|
208.74.204.9 permit
|
||||||
208.75.120.0/22 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.96/29 permit
|
||||||
208.82.237.104/31 permit
|
208.82.237.104/31 permit
|
||||||
208.82.238.96/29 permit
|
208.82.238.96/29 permit
|
||||||
@ -1930,7 +1888,6 @@
|
|||||||
213.199.177.0/26 permit
|
213.199.177.0/26 permit
|
||||||
216.17.150.242 permit
|
216.17.150.242 permit
|
||||||
216.17.150.251 permit
|
216.17.150.251 permit
|
||||||
216.22.15.224/27 permit
|
|
||||||
216.24.224.0/20 permit
|
216.24.224.0/20 permit
|
||||||
216.39.60.154/31 permit
|
216.39.60.154/31 permit
|
||||||
216.39.60.156/30 permit
|
216.39.60.156/30 permit
|
||||||
@ -1973,7 +1930,10 @@
|
|||||||
216.136.162.65 permit
|
216.136.162.65 permit
|
||||||
216.136.162.120/29 permit
|
216.136.162.120/29 permit
|
||||||
216.136.168.80/28 permit
|
216.136.168.80/28 permit
|
||||||
|
216.139.64.0/19 permit
|
||||||
216.145.221.0/24 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.198.0.0/18 permit
|
||||||
216.203.30.55 permit
|
216.203.30.55 permit
|
||||||
216.203.33.178/31 permit
|
216.203.33.178/31 permit
|
||||||
@ -1999,8 +1959,6 @@
|
|||||||
2603:1030:20e:3::23c permit
|
2603:1030:20e:3::23c permit
|
||||||
2603:1030:b:3::152 permit
|
2603:1030:b:3::152 permit
|
||||||
2603:1030:c02:8::14 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
|
2607:f8b0:4000::/36 permit
|
||||||
2620:109:c003:104::/64 permit
|
2620:109:c003:104::/64 permit
|
||||||
2620:109:c003:104::215 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
|
// Init Redis
|
||||||
$redis = new Redis();
|
$redis = new Redis();
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
|
|
||||||
function parse_email($email) {
|
function parse_email($email) {
|
||||||
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
|
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
|
||||||
|
@ -4,6 +4,7 @@ ini_set('error_reporting', 0);
|
|||||||
|
|
||||||
$redis = new Redis();
|
$redis = new Redis();
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
|
|
||||||
function in_net($addr, $net) {
|
function in_net($addr, $net) {
|
||||||
$net = explode('/', $net);
|
$net = explode('/', $net);
|
||||||
|
@ -24,6 +24,7 @@ catch (PDOException $e) {
|
|||||||
// Init Redis
|
// Init Redis
|
||||||
$redis = new Redis();
|
$redis = new Redis();
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
function parse_email($email) {
|
function parse_email($email) {
|
||||||
|
@ -14,6 +14,7 @@ try {
|
|||||||
else {
|
else {
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
}
|
}
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
exit;
|
exit;
|
||||||
|
@ -24,6 +24,7 @@ catch (PDOException $e) {
|
|||||||
// Init Redis
|
// Init Redis
|
||||||
$redis = new Redis();
|
$redis = new Redis();
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
function parse_email($email) {
|
function parse_email($email) {
|
||||||
|
@ -7,6 +7,7 @@ try {
|
|||||||
else {
|
else {
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
}
|
}
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
exit;
|
exit;
|
||||||
|
@ -106,7 +106,7 @@ $template_data = [
|
|||||||
'all_domains' => $all_domains,
|
'all_domains' => $all_domains,
|
||||||
'mailboxes' => $mailboxes,
|
'mailboxes' => $mailboxes,
|
||||||
'f2b_data' => $f2b_data,
|
'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'),
|
'q_data' => quarantine('settings'),
|
||||||
'qn_data' => quota_notification('get'),
|
'qn_data' => quota_notification('get'),
|
||||||
'pw_reset_data' => reset_password('get_notification'),
|
'pw_reset_data' => reset_password('get_notification'),
|
||||||
|
@ -19,6 +19,7 @@ try {
|
|||||||
else {
|
else {
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
}
|
}
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
exit;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (!ctype_alnum(str_replace(['-', '_'], '', $dkim_selector))) {
|
if (!ctype_alnum(str_replace(['-', '_', '.'], '', $dkim_selector))) {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
'log' => array(__FUNCTION__, $_action, $_data),
|
'log' => array(__FUNCTION__, $_action, $_data),
|
||||||
@ -188,7 +188,7 @@ function dkim($_action, $_data = null, $privkey = false) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ctype_alnum($dkim_selector)) {
|
if (!ctype_alnum(str_replace(['-', '_', '.'], '', $dkim_selector))) {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
'log' => array(__FUNCTION__, $_action, $_data),
|
'log' => array(__FUNCTION__, $_action, $_data),
|
||||||
|
@ -2917,6 +2917,8 @@ function reset_password($action, $data = null) {
|
|||||||
':username' => $username
|
':username' => $username
|
||||||
));
|
));
|
||||||
|
|
||||||
|
update_sogo_static_view($username);
|
||||||
|
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'success',
|
'type' => 'success',
|
||||||
'log' => array(__FUNCTION__, $action, $_data_log),
|
'log' => array(__FUNCTION__, $action, $_data_log),
|
||||||
|
@ -3440,7 +3440,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
'old_maildir' => $domain . '/' . $old_local_part,
|
'old_maildir' => $domain . '/' . $old_local_part,
|
||||||
'new_maildir' => $domain . '/' . $new_local_part
|
'new_maildir' => $domain . '/' . $new_local_part
|
||||||
);
|
);
|
||||||
|
if (getenv("CLUSTERMODE") == "replication") {
|
||||||
|
// broadcast to each dovecot container
|
||||||
|
docker('broadcast', 'dovecot-mailcow', 'exec', $exec_fields);
|
||||||
|
} else {
|
||||||
docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
|
docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
|
||||||
|
}
|
||||||
|
|
||||||
// rename username in sogo
|
// rename username in sogo
|
||||||
$exec_fields = array(
|
$exec_fields = array(
|
||||||
|
@ -3,7 +3,7 @@ function init_db_schema() {
|
|||||||
try {
|
try {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
$db_version = "15082024_1212";
|
$db_version = "20112024_1105";
|
||||||
|
|
||||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||||
@ -111,6 +111,10 @@ function init_db_schema() {
|
|||||||
"c_name" => "VARCHAR(255) NOT NULL",
|
"c_name" => "VARCHAR(255) NOT NULL",
|
||||||
"c_password" => "VARCHAR(255) NOT NULL DEFAULT ''",
|
"c_password" => "VARCHAR(255) NOT NULL DEFAULT ''",
|
||||||
"c_cn" => "VARCHAR(255)",
|
"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",
|
"mail" => "VARCHAR(255) NOT NULL",
|
||||||
// TODO -> use TEXT and check if SOGo login breaks on empty aliases
|
// TODO -> use TEXT and check if SOGo login breaks on empty aliases
|
||||||
"aliases" => "TEXT NOT NULL",
|
"aliases" => "TEXT NOT NULL",
|
||||||
|
@ -66,6 +66,7 @@ try {
|
|||||||
else {
|
else {
|
||||||
$redis->connect('redis-mailcow', 6379);
|
$redis->connect('redis-mailcow', 6379);
|
||||||
}
|
}
|
||||||
|
$redis->auth(getenv("REDISPASS"));
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
// Stop when redis is not available
|
// Stop when redis is not available
|
||||||
|
@ -692,8 +692,8 @@ jQuery(function($){
|
|||||||
} else if (item.attributes.rl_frame === "d"){
|
} else if (item.attributes.rl_frame === "d"){
|
||||||
item.attributes.rl_frame = lang_rl.day;
|
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"){
|
if (item.template.toLowerCase() == "default"){
|
||||||
item.action = '<div class="btn-group">' +
|
item.action = '<div class="btn-group">' +
|
||||||
@ -817,14 +817,8 @@ jQuery(function($){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'rl_frame',
|
title: lang_edit.ratelimit,
|
||||||
data: 'attributes.rl_frame',
|
data: 'attributes.ratelimit',
|
||||||
defaultContent: '',
|
|
||||||
class: 'none',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'rl_value',
|
|
||||||
data: 'attributes.rl_value',
|
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
class: 'none',
|
class: 'none',
|
||||||
},
|
},
|
||||||
@ -893,7 +887,10 @@ jQuery(function($){
|
|||||||
item.quota.value = humanFileSize(item.quota_used) + "/" + item.quota.value;
|
item.quota.value = humanFileSize(item.quota_used) + "/" + item.quota.value;
|
||||||
|
|
||||||
item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox);
|
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) {
|
if (!item.rl) {
|
||||||
item.rl = '∞';
|
item.rl = '∞';
|
||||||
@ -1009,14 +1006,7 @@ jQuery(function($){
|
|||||||
data: 'last_mail_login',
|
data: 'last_mail_login',
|
||||||
searchable: false,
|
searchable: false,
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
responsivePriority: 7,
|
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>';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: lang.last_pw_change,
|
title: lang.last_pw_change,
|
||||||
@ -1191,7 +1181,8 @@ jQuery(function($){
|
|||||||
} else if (item.attributes.rl_frame === "d"){
|
} else if (item.attributes.rl_frame === "d"){
|
||||||
item.attributes.rl_frame = lang_rl.day;
|
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);
|
item.attributes.quota = humanFileSize(item.attributes.quota);
|
||||||
|
|
||||||
@ -1336,14 +1327,8 @@ jQuery(function($){
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "rl_frame",
|
title: lang_edit.ratelimit,
|
||||||
data: 'attributes.rl_frame',
|
data: 'attributes.ratelimit',
|
||||||
defaultContent: '',
|
|
||||||
class: 'none',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'rl_value',
|
|
||||||
data: 'attributes.rl_value',
|
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
class: 'none',
|
class: 'none',
|
||||||
},
|
},
|
||||||
|
@ -510,16 +510,6 @@ if (isset($_GET['query'])) {
|
|||||||
$_SESSION['challenge'] = $WebAuthn->getChallenge();
|
$_SESSION['challenge'] = $WebAuthn->getChallenge();
|
||||||
return;
|
return;
|
||||||
break;
|
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'])) {
|
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||||
switch ($category) {
|
switch ($category) {
|
||||||
@ -1431,10 +1421,6 @@ if (isset($_GET['query'])) {
|
|||||||
break;
|
break;
|
||||||
case "fail2ban":
|
case "fail2ban":
|
||||||
switch ($object) {
|
switch ($object) {
|
||||||
case 'banlist':
|
|
||||||
header('Content-Type: text/plain');
|
|
||||||
echo fail2ban('banlist', 'get', $extra);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
$data = fail2ban('get');
|
$data = fail2ban('get');
|
||||||
process_get_return($data);
|
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",
|
"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",
|
"includes": "Inclure ces destinataires",
|
||||||
"last_applied": "Dernière application",
|
"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",
|
"link": "Lien",
|
||||||
"loading": "Veuillez patienter…",
|
"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é.",
|
"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",
|
"prohibited": "Запрещено правилами ACL",
|
||||||
"protocol_access": "Настройка разрешенных протоколов",
|
"protocol_access": "Настройка разрешенных протоколов",
|
||||||
"pushover": "Pushover API",
|
"pushover": "Pushover API",
|
||||||
|
"pw_reset": "Разрешить пользователям mailcow восстановление паролей",
|
||||||
"quarantine": "Карантин - действия",
|
"quarantine": "Карантин - действия",
|
||||||
"quarantine_attachments": "Карантин - вложения",
|
"quarantine_attachments": "Карантин - вложения",
|
||||||
"quarantine_category": "Категория уведомлений о спаме",
|
"quarantine_category": "Категория уведомлений о спаме",
|
||||||
@ -28,8 +29,7 @@
|
|||||||
"spam_score": "Политика фильтрации спама",
|
"spam_score": "Политика фильтрации спама",
|
||||||
"syncjobs": "Задания синхронизации",
|
"syncjobs": "Задания синхронизации",
|
||||||
"tls_policy": "Политика шифрования",
|
"tls_policy": "Политика шифрования",
|
||||||
"unlimited_quota": "Неограниченная квота для почтовых ящиков",
|
"unlimited_quota": "Неограниченная квота для почтовых ящиков"
|
||||||
"pw_reset": "Разрешить сброс пароля пользователей mailcow"
|
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"activate_filter_warn": "Активация этого фильтра отключит все остальные фильтры этого типа.",
|
"activate_filter_warn": "Активация этого фильтра отключит все остальные фильтры этого типа.",
|
||||||
@ -42,6 +42,7 @@
|
|||||||
"alias_domain": "Псевдоним домена",
|
"alias_domain": "Псевдоним домена",
|
||||||
"alias_domain_info": "<small>Действительные имена доменов, раздёленные запятыми.</small>",
|
"alias_domain_info": "<small>Действительные имена доменов, раздёленные запятыми.</small>",
|
||||||
"app_name": "Название приложения",
|
"app_name": "Название приложения",
|
||||||
|
"app_passwd_protocols": "Разрешенные протоколы для пароля приложения",
|
||||||
"app_password": "Добавить пароль приложения",
|
"app_password": "Добавить пароль приложения",
|
||||||
"automap": "Автоматическое слияние папок (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
"automap": "Автоматическое слияние папок (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
||||||
"backup_mx_options": "Параметры резервного MX",
|
"backup_mx_options": "Параметры резервного MX",
|
||||||
@ -58,6 +59,7 @@
|
|||||||
"domain": "Домен",
|
"domain": "Домен",
|
||||||
"domain_matches_hostname": "Домен %s соответствует имени хоста",
|
"domain_matches_hostname": "Домен %s соответствует имени хоста",
|
||||||
"domain_quota_m": "Квота домена (MiB)",
|
"domain_quota_m": "Квота домена (MiB)",
|
||||||
|
"dry": "Имитировать синхронизацию",
|
||||||
"enc_method": "Метод шифрования",
|
"enc_method": "Метод шифрования",
|
||||||
"exclude": "Исключить объекты (regex)",
|
"exclude": "Исключить объекты (regex)",
|
||||||
"full_name": "Полное имя",
|
"full_name": "Полное имя",
|
||||||
@ -89,7 +91,7 @@
|
|||||||
"relay_all_info": "↪<small>Если вы решите <b>не</b> ретранслировать всех получателей, вам нужно будет добавить (\"слепой\") почтовый адрес для каждого получателя, которого следует ретранслировать.</small>",
|
"relay_all_info": "↪<small>Если вы решите <b>не</b> ретранслировать всех получателей, вам нужно будет добавить (\"слепой\") почтовый адрес для каждого получателя, которого следует ретранслировать.</small>",
|
||||||
"relay_domain": "Ретрансляция этого домена",
|
"relay_domain": "Ретрансляция этого домена",
|
||||||
"relay_transport_info": "<div class=\"badge fs-6 bg-info\">Инфо</div> Вы можете настроить собственный транспорт для домена. Если такой настройки нет, то доставка будет выполнена на основе MX записей.",
|
"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.",
|
"relayhost_wrapped_tls_info": "Пожалуйста <b>не</b> используйте TLS порты (в основном это 465 порт).<br>\r\nИспользуйте любой <b>не</b> TLS порт который поддерживает STARTTLS. А для защиты от downgrate атак - настройке принудительную политику TLS.",
|
||||||
"select": "Пожалуйста, выберите...",
|
"select": "Пожалуйста, выберите...",
|
||||||
"select_domain": "Пожалуйста, сначала выберите домен",
|
"select_domain": "Пожалуйста, сначала выберите домен",
|
||||||
@ -99,6 +101,7 @@
|
|||||||
"subscribeall": "Подписаться на все папки и подпапки",
|
"subscribeall": "Подписаться на все папки и подпапки",
|
||||||
"syncjob": "Добавить задание синхронизации",
|
"syncjob": "Добавить задание синхронизации",
|
||||||
"syncjob_hint": "Пароли к вашему аккаунту будут сохранены на сервере в виде простого текста!",
|
"syncjob_hint": "Пароли к вашему аккаунту будут сохранены на сервере в виде простого текста!",
|
||||||
|
"tags": "Теги",
|
||||||
"target_address": "Владельцы псевдонима",
|
"target_address": "Владельцы псевдонима",
|
||||||
"target_address_info": "<small>Адреса почтовых ящиков, разделенные запятыми.</small>",
|
"target_address_info": "<small>Адреса почтовых ящиков, разделенные запятыми.</small>",
|
||||||
"target_domain": "Целевой домен",
|
"target_domain": "Целевой домен",
|
||||||
@ -106,10 +109,7 @@
|
|||||||
"timeout2": "Тайм-аут для подключения к локальному хосту",
|
"timeout2": "Тайм-аут для подключения к локальному хосту",
|
||||||
"username": "Имя пользователя",
|
"username": "Имя пользователя",
|
||||||
"validate": "Проверить",
|
"validate": "Проверить",
|
||||||
"validation_success": "Проверка прошла успешно",
|
"validation_success": "Проверка прошла успешно"
|
||||||
"tags": "Теги",
|
|
||||||
"app_passwd_protocols": "Разрешенные протоколы для пароля приложения",
|
|
||||||
"dry": "Имитировать синхронизацию"
|
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"access": "Настройки доступа",
|
"access": "Настройки доступа",
|
||||||
@ -135,6 +135,8 @@
|
|||||||
"admins": "Администраторы",
|
"admins": "Администраторы",
|
||||||
"admins_ldap": "Администраторы LDAP",
|
"admins_ldap": "Администраторы LDAP",
|
||||||
"advanced_settings": "Расширенные настройки",
|
"advanced_settings": "Расширенные настройки",
|
||||||
|
"allowed_methods": "Access-Control-Allow-Methods",
|
||||||
|
"allowed_origins": "Access-Control-Allow-Origin",
|
||||||
"api_allow_from": "Список IP-адресов для доступа к API (разделенных запятой или новой строкой)",
|
"api_allow_from": "Список IP-адресов для доступа к API (разделенных запятой или новой строкой)",
|
||||||
"api_info": "API находится в стадии разработки. Документация находится по адресу <a href=\"/api\">/api</a>",
|
"api_info": "API находится в стадии разработки. Документация находится по адресу <a href=\"/api\">/api</a>",
|
||||||
"api_key": "Ключ API",
|
"api_key": "Ключ API",
|
||||||
@ -151,6 +153,8 @@
|
|||||||
"change_logo": "Изменить логотип",
|
"change_logo": "Изменить логотип",
|
||||||
"configuration": "Глобальные настройки",
|
"configuration": "Глобальные настройки",
|
||||||
"convert_html_to_text": "Сконвертировать HTML в обычный текст",
|
"convert_html_to_text": "Сконвертировать HTML в обычный текст",
|
||||||
|
"copy_to_clipboard": "Текст скопирован в буфер обмена!",
|
||||||
|
"cors_settings": "Настройки CORS",
|
||||||
"credentials_transport_warning": "<b>Предупреждение</b>: добавление новой записи перезапишет учетные данные для всех записей с таким же <i>следующим хостом</i>.",
|
"credentials_transport_warning": "<b>Предупреждение</b>: добавление новой записи перезапишет учетные данные для всех записей с таким же <i>следующим хостом</i>.",
|
||||||
"customer_id": "ID клиента",
|
"customer_id": "ID клиента",
|
||||||
"customize": "Персонализация",
|
"customize": "Персонализация",
|
||||||
@ -179,10 +183,14 @@
|
|||||||
"empty": "Пусто",
|
"empty": "Пусто",
|
||||||
"excludes": "Исключает этих получателей",
|
"excludes": "Исключает этих получателей",
|
||||||
"f2b_ban_time": "Время бана (в секундах)",
|
"f2b_ban_time": "Время бана (в секундах)",
|
||||||
|
"f2b_ban_time_increment": "Время бана увеличивается с каждым баном",
|
||||||
"f2b_blacklist": "Черный список подсетей/хостов",
|
"f2b_blacklist": "Черный список подсетей/хостов",
|
||||||
"f2b_filter": "Правила фильтрации с помощью регулярных выражений",
|
"f2b_filter": "Правила фильтрации с помощью регулярных выражений",
|
||||||
"f2b_list_info": "Хосты или подсети, занесенные в черный список, всегда будут перевешивать объекты из белого списка. <b>Обновление списка займет несколько секунд.</b>",
|
"f2b_list_info": "Хосты или подсети, занесенные в черный список, всегда будут перевешивать объекты из белого списка. <b>Обновление списка займет несколько секунд.</b>",
|
||||||
|
"f2b_manage_external": "Внешнее управление Fail2Ban",
|
||||||
|
"f2b_manage_external_info": "Fail2ban по-прежнему будет вести банлист, но не будет активно устанавливать правила для блокировки трафика. Используйте сгенерированный ниже банлист для внешнего блокирования трафика.",
|
||||||
"f2b_max_attempts": "Максимальное количество попыток",
|
"f2b_max_attempts": "Максимальное количество попыток",
|
||||||
|
"f2b_max_ban_time": "Максимальное время блокировки",
|
||||||
"f2b_netban_ipv4": "Размер подсети IPv4 для применения бана (8-32)",
|
"f2b_netban_ipv4": "Размер подсети IPv4 для применения бана (8-32)",
|
||||||
"f2b_netban_ipv6": "Размер подсети IPv6 для применения бана (8-128)",
|
"f2b_netban_ipv6": "Размер подсети IPv6 для применения бана (8-128)",
|
||||||
"f2b_parameters": "Настройки Fail2ban",
|
"f2b_parameters": "Настройки Fail2ban",
|
||||||
@ -208,14 +216,19 @@
|
|||||||
"include_exclude": "Включить/Исключить",
|
"include_exclude": "Включить/Исключить",
|
||||||
"include_exclude_info": "По умолчанию - без выбора - <b>все почтовые ящики</b> адресованы",
|
"include_exclude_info": "По умолчанию - без выбора - <b>все почтовые ящики</b> адресованы",
|
||||||
"includes": "Включить этих получателей",
|
"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",
|
"is_mx_based": "На основе MX",
|
||||||
"last_applied": "Посл. применение",
|
"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": "Ссылка",
|
"link": "Ссылка",
|
||||||
"loading": "Пожалуйста, подождите...",
|
"loading": "Пожалуйста, подождите...",
|
||||||
"login_time": "Время входа",
|
"login_time": "Время входа",
|
||||||
|
"logo_dark_label": "Инвертированный для темного режима",
|
||||||
"logo_info": "Ваше изображение будет масштабироваться до высоты 40px для верхней панели навигации и до 250px ширины для стартовой страницы. <br>Рекомендуется использовать векторную графику, например: .svg.",
|
"logo_info": "Ваше изображение будет масштабироваться до высоты 40px для верхней панели навигации и до 250px ширины для стартовой страницы. <br>Рекомендуется использовать векторную графику, например: .svg.",
|
||||||
"lookup_mx": "Назначение на основе резовинга MX записи по регулярному выражению (<code>.*\\.example\\.com$</code> для маршрутизации всей почты через этот хост, если MX заканчивающийся на example.com)",
|
"logo_normal_label": "Обычный",
|
||||||
|
"lookup_mx": "Назначение - регулярное выражение для сопоставления с именем MX (<code>.*\\.google\\.com</code> для направления всей почты, адресованной MX, заканчивающейся на google.com, через этот хоп)",
|
||||||
"main_name": "Название для \"mailcow UI\"",
|
"main_name": "Название для \"mailcow UI\"",
|
||||||
"merged_vars_hint": "Серым цветом выделены строки полученные из <code>vars.(local.)inc.php</code>, они не могут быть изменены.",
|
"merged_vars_hint": "Серым цветом выделены строки полученные из <code>vars.(local.)inc.php</code>, они не могут быть изменены.",
|
||||||
"message": "Сообщение",
|
"message": "Сообщение",
|
||||||
@ -225,15 +238,16 @@
|
|||||||
"no_active_bans": "В данный момент нет забаненных подсетей/хостов",
|
"no_active_bans": "В данный момент нет забаненных подсетей/хостов",
|
||||||
"no_new_rows": "Нет доступных строк",
|
"no_new_rows": "Нет доступных строк",
|
||||||
"no_record": "Нет записей",
|
"no_record": "Нет записей",
|
||||||
"oauth2_client_id": "ID клиента",
|
|
||||||
"oauth2_apps": "Приложения OAuth2",
|
|
||||||
"oauth2_add_client": "Добавить клиента OAuth2",
|
"oauth2_add_client": "Добавить клиента OAuth2",
|
||||||
|
"oauth2_apps": "Приложения OAuth2",
|
||||||
|
"oauth2_client_id": "ID клиента",
|
||||||
"oauth2_client_secret": "Секретный ключ пользователя",
|
"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_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_redirect_uri": "Переадресация URI",
|
||||||
"oauth2_renew_secret": "Сгенерировать новый ключ клиента",
|
"oauth2_renew_secret": "Сгенерировать новый ключ клиента",
|
||||||
"oauth2_revoke_tokens": "Отозвать все клиентские токены",
|
"oauth2_revoke_tokens": "Отозвать все клиентские токены",
|
||||||
"optional": "опционально",
|
"optional": "опционально",
|
||||||
|
"options": "Параметры",
|
||||||
"password": "Пароль",
|
"password": "Пароль",
|
||||||
"password_length": "Минимальная длина пароля",
|
"password_length": "Минимальная длина пароля",
|
||||||
"password_policy": "Политика паролей",
|
"password_policy": "Политика паролей",
|
||||||
@ -243,6 +257,11 @@
|
|||||||
"password_policy_numbers": "Должен содержать цифру",
|
"password_policy_numbers": "Должен содержать цифру",
|
||||||
"password_policy_special_chars": "Должны содержать специальный символ",
|
"password_policy_special_chars": "Должны содержать специальный символ",
|
||||||
"password_repeat": "Подтверждение пароля (повтор)",
|
"password_repeat": "Подтверждение пароля (повтор)",
|
||||||
|
"password_reset_info": "Если получатель не указан, использование данной функции недоступно.",
|
||||||
|
"password_reset_settings": "Параметры восстановления паролей",
|
||||||
|
"password_reset_tmpl_html": "Шаблон в виде HTML",
|
||||||
|
"password_reset_tmpl_text": "Шаблон в виде обычного текста",
|
||||||
|
"password_settings": "Параметры паролей",
|
||||||
"priority": "Приоритет",
|
"priority": "Приоритет",
|
||||||
"private_key": "Закрытый ключ",
|
"private_key": "Закрытый ключ",
|
||||||
"quarantine": "Карантин",
|
"quarantine": "Карантин",
|
||||||
@ -250,7 +269,7 @@
|
|||||||
"quarantine_exclude_domains": "Исключить домены и псевдонимы доменов",
|
"quarantine_exclude_domains": "Исключить домены и псевдонимы доменов",
|
||||||
"quarantine_max_age": "Максимальный период хранения в днях<br><small>Значение должно быть равно или больше 1 дня.</small>",
|
"quarantine_max_age": "Максимальный период хранения в днях<br><small>Значение должно быть равно или больше 1 дня.</small>",
|
||||||
"quarantine_max_score": "Не уведомлять о спаме, если оценка письма выше, чем:<br><small>По умолчанию 9999.0</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_html": "Шаблон уведомления:<br><small>Оставьте пустым, чтобы восстановить шаблон по умолчанию.</small>",
|
||||||
"quarantine_notification_sender": "Email-адрес для отправки уведомления",
|
"quarantine_notification_sender": "Email-адрес для отправки уведомления",
|
||||||
"quarantine_notification_subject": "Тема письма",
|
"quarantine_notification_subject": "Тема письма",
|
||||||
@ -259,6 +278,7 @@
|
|||||||
"quarantine_release_format_att": "Как вложение",
|
"quarantine_release_format_att": "Как вложение",
|
||||||
"quarantine_release_format_raw": "Оригинальное письмо",
|
"quarantine_release_format_raw": "Оригинальное письмо",
|
||||||
"quarantine_retention_size": "Количество писем, сохраняемых в карантине на аккаунт:<br><small>0 означает, что карантин <b>отключён</b>.</small>",
|
"quarantine_retention_size": "Количество писем, сохраняемых в карантине на аккаунт:<br><small>0 означает, что карантин <b>отключён</b>.</small>",
|
||||||
|
"queue_unban": "разблокировать",
|
||||||
"quota_notification_html": "Шаблон уведомления:<br><small>Оставьте пустым, чтобы восстановить шаблон по умолчанию.</small>",
|
"quota_notification_html": "Шаблон уведомления:<br><small>Оставьте пустым, чтобы восстановить шаблон по умолчанию.</small>",
|
||||||
"quota_notification_sender": "Email-адрес для отправки уведомления",
|
"quota_notification_sender": "Email-адрес для отправки уведомления",
|
||||||
"quota_notification_subject": "Тема письма",
|
"quota_notification_subject": "Тема письма",
|
||||||
@ -267,7 +287,7 @@
|
|||||||
"quota_notifications_vars": "{{percent}} равно текущей квоте пользователя<br>{{username}} - имя почтового аккаунта",
|
"quota_notifications_vars": "{{percent}} равно текущей квоте пользователя<br>{{username}} - имя почтового аккаунта",
|
||||||
"r_active": "Включенные ограничения",
|
"r_active": "Включенные ограничения",
|
||||||
"r_inactive": "Отключенные ограничения",
|
"r_inactive": "Отключенные ограничения",
|
||||||
"r_info": "Не активные (серые) элементы списка ограничений - это не валидные ограничения, и они не могут быть перемещены. <br>Вы можете добавить новые элементы в <code>inc/vars.local.inc.php</code> чтобы иметь возможность настраивать их.",
|
"r_info": "Неактивные (серые) элементы списка ограничений - это некорректные ограничения, и они не могут быть перемещены. <br>Вы можете добавить новые элементы в <code>inc/vars.local.inc.php</code> чтобы иметь возможность настраивать их.",
|
||||||
"rate_name": "Название очереди",
|
"rate_name": "Название очереди",
|
||||||
"recipients": "Получатели",
|
"recipients": "Получатели",
|
||||||
"refresh": "Обновить",
|
"refresh": "Обновить",
|
||||||
@ -282,6 +302,8 @@
|
|||||||
"remove_row": "Удалить строку",
|
"remove_row": "Удалить строку",
|
||||||
"reset_default": "Восстановить по умолчанию",
|
"reset_default": "Восстановить по умолчанию",
|
||||||
"reset_limit": "Удалить хэш",
|
"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": "Маршрутизация",
|
"routing": "Маршрутизация",
|
||||||
"rsetting_add_rule": "Добавить правило",
|
"rsetting_add_rule": "Добавить правило",
|
||||||
"rsetting_content": "Содержание правила",
|
"rsetting_content": "Содержание правила",
|
||||||
@ -290,7 +312,7 @@
|
|||||||
"rsetting_none": "Нет доступных правил",
|
"rsetting_none": "Нет доступных правил",
|
||||||
"rsettings_insert_preset": "Вставить пример \"%s\"",
|
"rsettings_insert_preset": "Вставить пример \"%s\"",
|
||||||
"rsettings_preset_1": "Отключить все, кроме DKIM и ограничения скорости для аутентифицированных пользователей",
|
"rsettings_preset_1": "Отключить все, кроме DKIM и ограничения скорости для аутентифицированных пользователей",
|
||||||
"rsettings_preset_2": "Не проверять письма на спам Postmaster",
|
"rsettings_preset_2": "Не проверять письма Postmaster на спам",
|
||||||
"rsettings_preset_3": "Разрешить только определённых отправителей для почтового ящика (использование только в качестве внутреннего почтового ящика)",
|
"rsettings_preset_3": "Разрешить только определённых отправителей для почтового ящика (использование только в качестве внутреннего почтового ящика)",
|
||||||
"rsettings_preset_4": "Отключить Rspamd для домена",
|
"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_com_settings": "Имена правил будут сгенерированы на основе их ID.<br> Инструкция доступна на сайте <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">документация Rspamd user settings</a>, заготовленные шаблоны:",
|
||||||
@ -337,19 +359,7 @@
|
|||||||
"username": "Имя пользователя",
|
"username": "Имя пользователя",
|
||||||
"validate_license_now": "Получить лицензию на основе GUID с сервера лицензий",
|
"validate_license_now": "Получить лицензию на основе GUID с сервера лицензий",
|
||||||
"verify": "Проверить",
|
"verify": "Проверить",
|
||||||
"yes": "✓",
|
"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": "Текст скопирован в буфер обмена!"
|
|
||||||
},
|
},
|
||||||
"danger": {
|
"danger": {
|
||||||
"access_denied": "Доступ запрещён, или указаны неверные данные",
|
"access_denied": "Доступ запрещён, или указаны неверные данные",
|
||||||
@ -365,7 +375,10 @@
|
|||||||
"bcc_exists": "Для типов %s уже существует карта BCC %s",
|
"bcc_exists": "Для типов %s уже существует карта BCC %s",
|
||||||
"bcc_must_be_email": "Назначение BCC %s не является правильным адресом электронной почты",
|
"bcc_must_be_email": "Назначение BCC %s не является правильным адресом электронной почты",
|
||||||
"comment_too_long": "Комментарий слишком длинный, придел 160 символов",
|
"comment_too_long": "Комментарий слишком длинный, придел 160 символов",
|
||||||
|
"cors_invalid_method": "Указан недопустимый метод разрешения",
|
||||||
|
"cors_invalid_origin": "Указан неверный Allow-Origin",
|
||||||
"defquota_empty": "Квота по умолчанию не может быть 0.",
|
"defquota_empty": "Квота по умолчанию не может быть 0.",
|
||||||
|
"demo_mode_enabled": "Демонстрационный режим включен",
|
||||||
"description_invalid": "Недопустимое описание ресурса %s",
|
"description_invalid": "Недопустимое описание ресурса %s",
|
||||||
"dkim_domain_or_sel_exists": "Ключ DKIM для \"%s\" уже существует",
|
"dkim_domain_or_sel_exists": "Ключ DKIM для \"%s\" уже существует",
|
||||||
"dkim_domain_or_sel_invalid": "DKIM домен или селектор недопустимы для %s",
|
"dkim_domain_or_sel_invalid": "DKIM домен или селектор недопустимы для %s",
|
||||||
@ -375,20 +388,23 @@
|
|||||||
"domain_not_empty": "Нельзя удалить непустой домен %s",
|
"domain_not_empty": "Нельзя удалить непустой домен %s",
|
||||||
"domain_not_found": "Домен %s не найден",
|
"domain_not_found": "Домен %s не найден",
|
||||||
"domain_quota_m_in_use": "Квота домена должна быть больше или равна %s MiB",
|
"domain_quota_m_in_use": "Квота домена должна быть больше или равна %s MiB",
|
||||||
"extra_acl_invalid": "Адрес внешнего отправителя \"%s\" не валидный.",
|
"extended_sender_acl_denied": "отсутствует ACL для установки внешних адресов отправителей",
|
||||||
"extra_acl_invalid_domain": "Адрес внешнего отправителя \"%s\" не валидный домен",
|
"extra_acl_invalid": "Адрес внешнего отправителя \"%s\" некорректен",
|
||||||
|
"extra_acl_invalid_domain": "Адрес внешнего отправителя \"%s\" содержит некорректный домен",
|
||||||
"fido2_verification_failed": "Ошибка валидации FIDO2: %s",
|
"fido2_verification_failed": "Ошибка валидации FIDO2: %s",
|
||||||
"file_open_error": "Файл не может быть открыт на запись",
|
"file_open_error": "Файл не может быть открыт на запись",
|
||||||
"filter_type": "Неверный тип фильтра",
|
"filter_type": "Неверный тип фильтра",
|
||||||
"from_invalid": "Отправитель не может быть пустым",
|
"from_invalid": "Отправитель не может быть пустым",
|
||||||
"global_filter_write_error": "Ошибка записи фильтра в файл: %s",
|
"global_filter_write_error": "Ошибка записи фильтра в файл: %s",
|
||||||
"global_map_invalid": "Идентификатор глобального правила %s не валидный",
|
"global_map_invalid": "Недопустимый идентификатор глобального правила %s",
|
||||||
"global_map_write_error": "Не удалось создать глобальное правило ID %s: %s",
|
"global_map_write_error": "Не удалось создать глобальное правило ID %s: %s",
|
||||||
"goto_empty": "Псевдоним должен содержать по крайней мере один валидный адрес владельца",
|
"goto_empty": "Псевдоним должен содержать по крайней мере один действующий адрес владельца",
|
||||||
"goto_invalid": "Недопустимый основной адрес %s",
|
"goto_invalid": "Недопустимый основной адрес %s",
|
||||||
"ham_learn_error": "Ошибка при обучении полезной почты: %s",
|
"ham_learn_error": "Ошибка при обучении полезной почты: %s",
|
||||||
"imagick_exception": "Ошибка в Imagick при чтении изображения",
|
"imagick_exception": "Ошибка в Imagick при чтении изображения",
|
||||||
|
"img_dimensions_exceeded": "Разрешение изображения превышает допустимое значение",
|
||||||
"img_invalid": "Невозможно проверить файл изображения",
|
"img_invalid": "Невозможно проверить файл изображения",
|
||||||
|
"img_size_exceeded": "Изображение превышает допустимый размер файла",
|
||||||
"img_tmp_missing": "Невозможно проверить файл изображения: временный файл не найден",
|
"img_tmp_missing": "Невозможно проверить файл изображения: временный файл не найден",
|
||||||
"invalid_bcc_map_type": "Неверный тип правила BCC",
|
"invalid_bcc_map_type": "Неверный тип правила BCC",
|
||||||
"invalid_destination": "Назначение \"%s\" указано неверно",
|
"invalid_destination": "Назначение \"%s\" указано неверно",
|
||||||
@ -397,8 +413,9 @@
|
|||||||
"invalid_mime_type": "Неверный mime type",
|
"invalid_mime_type": "Неверный mime type",
|
||||||
"invalid_nexthop": "Формат следующего хоста неверен",
|
"invalid_nexthop": "Формат следующего хоста неверен",
|
||||||
"invalid_nexthop_authenticated": "Следующий хост существует с разными данными авторизации, пожалуйста, обновите существующие данные авторизации сначала для этого хоста.",
|
"invalid_nexthop_authenticated": "Следующий хост существует с разными данными авторизации, пожалуйста, обновите существующие данные авторизации сначала для этого хоста.",
|
||||||
"invalid_recipient_map_new": "Новый получатель: %s не валидный",
|
"invalid_recipient_map_new": "Недопустимый новый получатель: %s",
|
||||||
"invalid_recipient_map_old": "Первоначальный получатель: %s не валидный",
|
"invalid_recipient_map_old": "Недопустимый исходный получатель: %s",
|
||||||
|
"invalid_reset_token": "Неверный токен восстановления",
|
||||||
"ip_list_empty": "Список разрешенных IP адресов не может быть пустым",
|
"ip_list_empty": "Список разрешенных IP адресов не может быть пустым",
|
||||||
"is_alias": "%s уже известен как псевдоним адреса",
|
"is_alias": "%s уже известен как псевдоним адреса",
|
||||||
"is_alias_or_mailbox": "%s уже известен как псевдоним или почтовый аккаунт",
|
"is_alias_or_mailbox": "%s уже известен как псевдоним или почтовый аккаунт",
|
||||||
@ -418,7 +435,7 @@
|
|||||||
"max_quota_in_use": "Квота почтового аккаунта должна быть больше или равна %d MiB",
|
"max_quota_in_use": "Квота почтового аккаунта должна быть больше или равна %d MiB",
|
||||||
"maxquota_empty": "Максимальная квота почтового аккаунта не должна быть 0.",
|
"maxquota_empty": "Максимальная квота почтового аккаунта не должна быть 0.",
|
||||||
"mysql_error": "Ошибка в MySQL: %s",
|
"mysql_error": "Ошибка в MySQL: %s",
|
||||||
"network_host_invalid": "Сеть или хост: %s не валидный",
|
"network_host_invalid": "Недопустимые сеть или хост: %s",
|
||||||
"next_hop_interferes": "%s пересекается с %s",
|
"next_hop_interferes": "%s пересекается с %s",
|
||||||
"next_hop_interferes_any": "Существующий хост пересекается с %s",
|
"next_hop_interferes_any": "Существующий хост пересекается с %s",
|
||||||
"nginx_reload_failed": "Обновление конфигурации Nginx не удалось: %s",
|
"nginx_reload_failed": "Обновление конфигурации Nginx не удалось: %s",
|
||||||
@ -428,6 +445,8 @@
|
|||||||
"password_complexity": "Пароль не соответствует требованиям",
|
"password_complexity": "Пароль не соответствует требованиям",
|
||||||
"password_empty": "Пароль не может быть пустым",
|
"password_empty": "Пароль не может быть пустым",
|
||||||
"password_mismatch": "Введенные пароли не совпадают",
|
"password_mismatch": "Введенные пароли не совпадают",
|
||||||
|
"password_reset_invalid_user": "Почтовый ящик не найден или не задан адрес электронной почты для восстановления",
|
||||||
|
"password_reset_na": "Восстановление пароля в настоящее время недоступно. Пожалуйста, свяжитесь с вашим администратором.",
|
||||||
"policy_list_from_exists": "Запись с указанным именем уже существует",
|
"policy_list_from_exists": "Запись с указанным именем уже существует",
|
||||||
"policy_list_from_invalid": "Запись имеет недопустимый формат",
|
"policy_list_from_invalid": "Запись имеет недопустимый формат",
|
||||||
"private_key_error": "Ошибка приватного ключа: %s",
|
"private_key_error": "Ошибка приватного ключа: %s",
|
||||||
@ -436,17 +455,19 @@
|
|||||||
"pushover_token": "Токен Pushover указан в неверном формате",
|
"pushover_token": "Токен Pushover указан в неверном формате",
|
||||||
"quota_not_0_not_numeric": "Размер квоты должен быть больше или равен нулю",
|
"quota_not_0_not_numeric": "Размер квоты должен быть больше или равен нулю",
|
||||||
"recipient_map_entry_exists": "Правило перезаписи \"%s\" уже существует",
|
"recipient_map_entry_exists": "Правило перезаписи \"%s\" уже существует",
|
||||||
|
"recovery_email_failed": "Не удалось отправить письмо для восстановления. Пожалуйста, свяжитесь с вашим администратором.",
|
||||||
"redis_error": "Ошибка в Redis: %s",
|
"redis_error": "Ошибка в Redis: %s",
|
||||||
"relayhost_invalid": "Правило %s не валидное",
|
"relayhost_invalid": "Недопустимое правило %s",
|
||||||
"release_send_failed": "Сообщение не может быть восстановлено: %s",
|
"release_send_failed": "Сообщение не может быть восстановлено: %s",
|
||||||
"reset_f2b_regex": "Сброс фильтров не был выполнен за отведённый промежуток времени, пожалуйста, повторите попытку или подождите еще несколько секунд и перезагрузите веб страницу.",
|
"reset_f2b_regex": "Сброс фильтров не был выполнен за отведённый промежуток времени, пожалуйста, повторите попытку или подождите еще несколько секунд и перезагрузите веб страницу.",
|
||||||
|
"reset_token_limit_exceeded": "Превышен лимит запросов на восстановление. Пожалуйста, попробуйте ещё раз позже.",
|
||||||
"resource_invalid": "Недопустимое имя ресурса",
|
"resource_invalid": "Недопустимое имя ресурса",
|
||||||
"rl_timeframe": "Не верный временной интервал для лимита отправки",
|
"rl_timeframe": "Не верный временной интервал для лимита отправки",
|
||||||
"rspamd_ui_pw_length": "Длина пароля должна составлять не менее 6 символов для Rspamd UI",
|
"rspamd_ui_pw_length": "Длина пароля должна составлять не менее 6 символов для Rspamd UI",
|
||||||
"script_empty": "Скрипт не может быть пустым",
|
"script_empty": "Скрипт не может быть пустым",
|
||||||
"sender_acl_invalid": "Недопустимое значение ACL для: %s",
|
"sender_acl_invalid": "Недопустимое значение ACL для: %s",
|
||||||
"set_acl_failed": "Не удалось установить ACL",
|
"set_acl_failed": "Не удалось установить ACL",
|
||||||
"settings_map_invalid": "Правило ID: %s не валидное",
|
"settings_map_invalid": "Недопустимое правило ID %s",
|
||||||
"sieve_error": "Ошибка в синтаксисе Sieve: %s",
|
"sieve_error": "Ошибка в синтаксисе Sieve: %s",
|
||||||
"spam_learn_error": "Ошибка при обучении спам фильтра: %s",
|
"spam_learn_error": "Ошибка при обучении спам фильтра: %s",
|
||||||
"subject_empty": "Тема письма не может быть пустой",
|
"subject_empty": "Тема письма не может быть пустой",
|
||||||
@ -454,34 +475,67 @@
|
|||||||
"targetd_not_found": "Основной домен %s не найден",
|
"targetd_not_found": "Основной домен %s не найден",
|
||||||
"targetd_relay_domain": "Целевой домен %s уже является домен ретрансляции",
|
"targetd_relay_domain": "Целевой домен %s уже является домен ретрансляции",
|
||||||
"temp_error": "Временная ошибка",
|
"temp_error": "Временная ошибка",
|
||||||
"text_empty": "Текст не должен быть пустым",
|
"template_exists": "Шаблон %s уже существует",
|
||||||
|
"template_id_invalid": "Недопустимое значение ID шаблона: %s",
|
||||||
|
"template_name_invalid": "Недопустимое название шаблона",
|
||||||
|
"text_empty": "Текст не может быть пустым",
|
||||||
"tfa_token_invalid": "Неправильный TFA токен",
|
"tfa_token_invalid": "Неправильный TFA токен",
|
||||||
"tls_policy_map_dest_invalid": "Недопустимое значение назначения политики",
|
"tls_policy_map_dest_invalid": "Недопустимое значение назначения политики",
|
||||||
"tls_policy_map_entry_exists": "Правило политики шифрования \"%s\" уже существует",
|
"tls_policy_map_entry_exists": "Правило политики шифрования \"%s\" уже существует",
|
||||||
"tls_policy_map_parameter_invalid": "Недопустимое значение параметра политики",
|
"tls_policy_map_parameter_invalid": "Недопустимое значение параметра политики",
|
||||||
|
"to_invalid": "Получатель не может быть пустым",
|
||||||
"totp_verification_failed": "Ошибка валидации TOTP",
|
"totp_verification_failed": "Ошибка валидации TOTP",
|
||||||
"transport_dest_exists": "Назначение для отправки \"%s\" уже существует",
|
"transport_dest_exists": "Назначение для отправки \"%s\" уже существует",
|
||||||
"webauthn_verification_failed": "Ошибка валидации WebAuthn: %s",
|
|
||||||
"unknown": "Произошла неизвестная ошибка",
|
"unknown": "Произошла неизвестная ошибка",
|
||||||
"unknown_tfa_method": "Неизвестный метод TFA",
|
"unknown_tfa_method": "Неизвестный метод TFA",
|
||||||
"unlimited_quota_acl": "Неограниченная квота запрещена политикой доступа",
|
"unlimited_quota_acl": "Неограниченная квота запрещена политикой доступа",
|
||||||
"username_invalid": "Имя пользователя %s нельзя использовать",
|
"username_invalid": "Имя пользователя %s нельзя использовать",
|
||||||
"validity_missing": "Пожалуйста, назначьте срок действия",
|
"validity_missing": "Пожалуйста, назначьте срок действия",
|
||||||
"value_missing": "Пожалуйста заполните все поля",
|
"value_missing": "Пожалуйста заполните все поля",
|
||||||
"yotp_verification_failed": "Ошибка валидации Yubico OTP: %s",
|
"webauthn_authenticator_failed": "Выбранный аутентификатор не был найден",
|
||||||
"cors_invalid_method": "Указан недопустимый метод разрешения",
|
"webauthn_publickey_failed": "Для выбранного аутентификатора не был сохранен открытый ключ",
|
||||||
"demo_mode_enabled": "Демонстрационный режим включен",
|
"webauthn_username_failed": "Выбранный аутентификатор принадлежит другой учетной записи",
|
||||||
"cors_invalid_origin": "Указан неверный Allow-Origin"
|
"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": {
|
"debug": {
|
||||||
|
"architecture": "Архитектура",
|
||||||
"chart_this_server": "Диаграмма (текущий сервер)",
|
"chart_this_server": "Диаграмма (текущий сервер)",
|
||||||
"containers_info": "Статус контейнеров Docker",
|
|
||||||
"container_running": "Работающий",
|
|
||||||
"container_disabled": "Контейнер остановлен или отключен",
|
"container_disabled": "Контейнер остановлен или отключен",
|
||||||
|
"container_running": "Работающий",
|
||||||
"container_stopped": "Остановлен",
|
"container_stopped": "Остановлен",
|
||||||
|
"containers_info": "Статус контейнеров Docker",
|
||||||
|
"cores": "яд.",
|
||||||
"current_time": "Системное время",
|
"current_time": "Системное время",
|
||||||
"disk_usage": "Использование дискового пространства",
|
"disk_usage": "Использование дискового пространства",
|
||||||
"docs": "Проиндексировано объектов",
|
"docs": "Проиндексировано объектов",
|
||||||
|
"error_show_ip": "Не удалось определить публичные IP-адреса",
|
||||||
"external_logs": "Внешние журналы",
|
"external_logs": "Внешние журналы",
|
||||||
"history_all_servers": "История (все серверы)",
|
"history_all_servers": "История (все серверы)",
|
||||||
"in_memory_logs": "Журналы контейнеров",
|
"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>",
|
"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": "Время входа",
|
"login_time": "Время входа",
|
||||||
"logs": "Журналы",
|
"logs": "Журналы",
|
||||||
|
"memory": "Память",
|
||||||
|
"no_update_available": "Система обновлена до последней версии",
|
||||||
"online_users": "Подключено пользователей",
|
"online_users": "Подключено пользователей",
|
||||||
"restart_container": "Перезапустить",
|
"restart_container": "Перезапустить",
|
||||||
"service": "Сервис",
|
"service": "Сервис",
|
||||||
|
"show_ip": "Показать публичные IP-адреса",
|
||||||
"size": "Индексы занимают",
|
"size": "Индексы занимают",
|
||||||
"solr_dead": "Solr не запущен. Если вы включили Solf в файле настроек <code>mailcow.conf</code> и это сообщение отображается более получаса, скорее всего Solr сломан.",
|
"solr_dead": "Solr не запущен. Если вы включили Solf в файле настроек <code>mailcow.conf</code> и это сообщение отображается более получаса, скорее всего Solr сломан.",
|
||||||
"solr_status": "Состояние Solr",
|
"solr_status": "Состояние Solr",
|
||||||
@ -500,10 +557,13 @@
|
|||||||
"started_on": "Запущен в",
|
"started_on": "Запущен в",
|
||||||
"static_logs": "Статические журналы",
|
"static_logs": "Статические журналы",
|
||||||
"success": "Успех",
|
"success": "Успех",
|
||||||
"no_update_available": "Система обновлена до последней версии",
|
|
||||||
"system_containers": "Система и контейнеры",
|
"system_containers": "Система и контейнеры",
|
||||||
|
"timezone": "Часовой пояс",
|
||||||
|
"update_available": "Доступно обновление",
|
||||||
|
"update_failed": "Не удалось проверить наличие обновлений",
|
||||||
"uptime": "Время работы",
|
"uptime": "Время работы",
|
||||||
"username": "Имя пользователя"
|
"username": "Имя пользователя",
|
||||||
|
"wip": "В настоящее время идёт разработка"
|
||||||
},
|
},
|
||||||
"diagnostics": {
|
"diagnostics": {
|
||||||
"cname_from_a": "Значение, полученное из записи A/AAAA. Это поддерживается до тех пор, пока запись указывает на правильный ресурс.",
|
"cname_from_a": "Значение, полученное из записи A/AAAA. Это поддерживается до тех пор, пока запись указывает на правильный ресурс.",
|
||||||
@ -527,6 +587,7 @@
|
|||||||
"allowed_protocols": "Разрешённые протоколы",
|
"allowed_protocols": "Разрешённые протоколы",
|
||||||
"app_name": "Название приложения",
|
"app_name": "Название приложения",
|
||||||
"app_passwd": "Пароль приложения",
|
"app_passwd": "Пароль приложения",
|
||||||
|
"app_passwd_protocols": "Разрешенные протоколы для пароля приложения",
|
||||||
"automap": "Автоматическое слияние папок (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
"automap": "Автоматическое слияние папок (\"Sent items\", \"Sent\" => \"Sent\" etc.)",
|
||||||
"backup_mx_options": "Параметры резервного копирования MX",
|
"backup_mx_options": "Параметры резервного копирования MX",
|
||||||
"bcc_dest_format": "Назначением для правила BCC должен быть единственный действительный адрес электронной почты.",
|
"bcc_dest_format": "Назначением для правила BCC должен быть единственный действительный адрес электронной почты.",
|
||||||
@ -534,6 +595,7 @@
|
|||||||
"client_secret": "Секретный ключ пользователя",
|
"client_secret": "Секретный ключ пользователя",
|
||||||
"comment_info": "Приватный комментарий не виден пользователям, а публичный - отображается рядом с псевдонимом в личном кабинете пользователя",
|
"comment_info": "Приватный комментарий не виден пользователям, а публичный - отображается рядом с псевдонимом в личном кабинете пользователя",
|
||||||
"created_on": "Дата создания",
|
"created_on": "Дата создания",
|
||||||
|
"custom_attributes": "Пользовательские атрибуты",
|
||||||
"delete1": "Удаление из источника после завершения",
|
"delete1": "Удаление из источника после завершения",
|
||||||
"delete2": "Удаление писем по месту назначения, которые не находятся на исходном",
|
"delete2": "Удаление писем по месту назначения, которые не находятся на исходном",
|
||||||
"delete2duplicates": "Удаление дубликатов по назначению",
|
"delete2duplicates": "Удаление дубликатов по назначению",
|
||||||
@ -542,6 +604,19 @@
|
|||||||
"disable_login": "Вход в систему запрещен",
|
"disable_login": "Вход в систему запрещен",
|
||||||
"domain": "Изменение домена",
|
"domain": "Изменение домена",
|
||||||
"domain_admin": "Изменение администратора домена",
|
"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": "Квота домена",
|
"domain_quota": "Квота домена",
|
||||||
"domains": "Домены",
|
"domains": "Домены",
|
||||||
"dont_check_sender_acl": "Отключить проверку отправителя для домена %s и псевдонимов домена",
|
"dont_check_sender_acl": "Отключить проверку отправителя для домена %s и псевдонимов домена",
|
||||||
@ -550,9 +625,9 @@
|
|||||||
"exclude": "Исключить объекты (regex)",
|
"exclude": "Исключить объекты (regex)",
|
||||||
"extended_sender_acl": "Внешние адреса почты",
|
"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.",
|
"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": "Требовать смены пароля при следующем входе в систему",
|
||||||
"force_pw_update_info": "Пользователь должен будет войти в %s и сменить свой пароль. mailcow OAuth2, SOGo, EAS, IMAP/POP3 и SMTP будут не доступны до смены пароля.",
|
"force_pw_update_info": "Пользователь должен будет войти в %s и сменить свой пароль. mailcow OAuth2, SOGo, EAS, IMAP/POP3 и SMTP будут не доступны до смены пароля.",
|
||||||
"footer_exclude": "Исключить из нижнего колонтитула",
|
|
||||||
"full_name": "Полное имя",
|
"full_name": "Полное имя",
|
||||||
"gal": "GAL - Глобальная адресная книга",
|
"gal": "GAL - Глобальная адресная книга",
|
||||||
"gal_info": "GAL содержит все объекты домена и не подлежит редактированию. Информация о занятости в SOGo будет отсутствовать для домена, если данная функция будет отключена! <b>Требуется перезапустить SOGo, чтобы применить изменения.</b>",
|
"gal_info": "GAL содержит все объекты домена и не подлежит редактированию. Информация о занятости в SOGo будет отсутствовать для домена, если данная функция будет отключена! <b>Требуется перезапустить SOGo, чтобы применить изменения.</b>",
|
||||||
@ -566,6 +641,11 @@
|
|||||||
"mailbox": "Изменение почтового аккаунта",
|
"mailbox": "Изменение почтового аккаунта",
|
||||||
"mailbox_quota_def": "Квота по умолчанию",
|
"mailbox_quota_def": "Квота по умолчанию",
|
||||||
"mailbox_relayhost_info": "Применяется только к почтовому ящику и личным псевдонимам, вне зависимости от настроек маршрутизации на уровне домена.",
|
"mailbox_relayhost_info": "Применяется только к почтовому ящику и личным псевдонимам, вне зависимости от настроек маршрутизации на уровне домена.",
|
||||||
|
"mailbox_rename": "Переименовать почтовый ящик",
|
||||||
|
"mailbox_rename_agree": "Я сделал резервную копию.",
|
||||||
|
"mailbox_rename_alias": "Автоматически создать псевдоним",
|
||||||
|
"mailbox_rename_title": "Новое имя локального почтового ящика",
|
||||||
|
"mailbox_rename_warning": "ВАЖНО! Перед переименованием почтового ящика создайте резервную копию.",
|
||||||
"max_aliases": "Максимум псевдонимов",
|
"max_aliases": "Максимум псевдонимов",
|
||||||
"max_mailboxes": "Максимум почтовых ящиков",
|
"max_mailboxes": "Максимум почтовых ящиков",
|
||||||
"max_quota": "Максимальная квота почтового аккаунта (MiB)",
|
"max_quota": "Максимальная квота почтового аккаунта (MiB)",
|
||||||
@ -574,9 +654,10 @@
|
|||||||
"mbox_rl_info": "Этот лимит применяется к SASL логину пользователя и соответствует любому адресу отправителя, используемому зарегистрированным пользователем. Лимит скорости почтового аккаунта перекрывает лимит скорости для всего домена.",
|
"mbox_rl_info": "Этот лимит применяется к SASL логину пользователя и соответствует любому адресу отправителя, используемому зарегистрированным пользователем. Лимит скорости почтового аккаунта перекрывает лимит скорости для всего домена.",
|
||||||
"mins_interval": "Интервал (в минутах)",
|
"mins_interval": "Интервал (в минутах)",
|
||||||
"multiple_bookings": "Несколько бронирований",
|
"multiple_bookings": "Несколько бронирований",
|
||||||
"none_inherit": "Отсутствует / Наследуется",
|
|
||||||
"nexthop": "Следующий хост",
|
"nexthop": "Следующий хост",
|
||||||
|
"none_inherit": "Отсутствует / Наследуется",
|
||||||
"password": "Пароль",
|
"password": "Пароль",
|
||||||
|
"password_recovery_email": "Адрес для восстановления пароля",
|
||||||
"password_repeat": "Подтверждение пароля (повтор)",
|
"password_repeat": "Подтверждение пароля (повтор)",
|
||||||
"previous": "Предыдущая страница",
|
"previous": "Предыдущая страница",
|
||||||
"private_comment": "Приватный комментарий",
|
"private_comment": "Приватный комментарий",
|
||||||
@ -587,6 +668,7 @@
|
|||||||
"pushover_only_x_prio": "Получать уведомления только об письмах с высоким приоритетом [<code>X-Priority: 1</code>]",
|
"pushover_only_x_prio": "Получать уведомления только об письмах с высоким приоритетом [<code>X-Priority: 1</code>]",
|
||||||
"pushover_sender_array": "Получать уведомления от списка адресов электронной почты <small>(envelop-from разделенные запятыми)</small>:",
|
"pushover_sender_array": "Получать уведомления от списка адресов электронной почты <small>(envelop-from разделенные запятыми)</small>:",
|
||||||
"pushover_sender_regex": "Получать уведомления от отправителей, удовлетворяющих regex-выражению:",
|
"pushover_sender_regex": "Получать уведомления от отправителей, удовлетворяющих regex-выражению:",
|
||||||
|
"pushover_sound": "Звук уведомления",
|
||||||
"pushover_text": "Текст уведомления",
|
"pushover_text": "Текст уведомления",
|
||||||
"pushover_title": "Заголовок уведомления",
|
"pushover_title": "Заголовок уведомления",
|
||||||
"pushover_vars": "Когда фильтрация по отправителю не определена, уведомления будут доставлятся от всех отправителей.<br>Можно использовать обычный фильтр по отправителю и расширенный regex-фильтр, а также оба сразу.<br>Пожалуйста, ознакомьтесь с <a href=\"https://pushover.net/privacy\">Pushover Privacy Policy</a> перед использованием шаблонов для текста и заголовка",
|
"pushover_vars": "Когда фильтрация по отправителю не определена, уведомления будут доставлятся от всех отправителей.<br>Можно использовать обычный фильтр по отправителю и расширенный regex-фильтр, а также оба сразу.<br>Пожалуйста, ознакомьтесь с <a href=\"https://pushover.net/privacy\">Pushover Privacy Policy</a> перед использованием шаблонов для текста и заголовка",
|
||||||
@ -612,6 +694,8 @@
|
|||||||
"sieve_desc": "Краткое описание",
|
"sieve_desc": "Краткое описание",
|
||||||
"sieve_type": "Тип фильтра",
|
"sieve_type": "Тип фильтра",
|
||||||
"skipcrossduplicates": "Пропускать повторяющиеся сообщения в папках",
|
"skipcrossduplicates": "Пропускать повторяющиеся сообщения в папках",
|
||||||
|
"sogo_access": "Прямая переадресация в SOGo",
|
||||||
|
"sogo_access_info": "После входа в систему пользователь автоматически перенаправляется в SOGo.",
|
||||||
"sogo_visible": "Отображать псевдоним в SOGo",
|
"sogo_visible": "Отображать псевдоним в SOGo",
|
||||||
"sogo_visible_info": "Влияет только на объекты, которые могут отображаться в SOGo (персональные или общие псевдонимы, указывающие как минимум на один локальный почтовый аккаунт). Учтите, что если функция отключена, у пользователей не будет возможности выбрать адрес псевдонима в качестве отправителя в SOGo.",
|
"sogo_visible_info": "Влияет только на объекты, которые могут отображаться в SOGo (персональные или общие псевдонимы, указывающие как минимум на один локальный почтовый аккаунт). Учтите, что если функция отключена, у пользователей не будет возможности выбрать адрес псевдонима в качестве отправителя в SOGo.",
|
||||||
"spam_alias": "Создать или изменить временные (спам) псевдонимы",
|
"spam_alias": "Создать или изменить временные (спам) псевдонимы",
|
||||||
@ -627,23 +711,7 @@
|
|||||||
"title": "Изменение объекта",
|
"title": "Изменение объекта",
|
||||||
"unchanged_if_empty": "Если без изменений - оставьте пустым",
|
"unchanged_if_empty": "Если без изменений - оставьте пустым",
|
||||||
"username": "Имя пользователя",
|
"username": "Имя пользователя",
|
||||||
"validate_save": "Подтвердить и сохранить",
|
"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": "Пользовательские атрибуты"
|
|
||||||
},
|
},
|
||||||
"fido2": {
|
"fido2": {
|
||||||
"confirm": "Подтвердить",
|
"confirm": "Подтвердить",
|
||||||
@ -678,10 +746,10 @@
|
|||||||
"header": {
|
"header": {
|
||||||
"administration": "Настройка сервера",
|
"administration": "Настройка сервера",
|
||||||
"apps": "Приложения",
|
"apps": "Приложения",
|
||||||
"debug": "Состояние сервера",
|
"debug": "Информация",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"mailcow_system": "Система",
|
|
||||||
"mailcow_config": "Конфигурация",
|
"mailcow_config": "Конфигурация",
|
||||||
|
"mailcow_system": "Система",
|
||||||
"quarantine": "Карантин",
|
"quarantine": "Карантин",
|
||||||
"restart_netfilter": "Перезапустить netfilter",
|
"restart_netfilter": "Перезапустить netfilter",
|
||||||
"restart_sogo": "Перезапустить SOGo",
|
"restart_sogo": "Перезапустить SOGo",
|
||||||
@ -693,12 +761,19 @@
|
|||||||
"session_expires": "Ваш сеанс закончится примерно через 15 секунд"
|
"session_expires": "Ваш сеанс закончится примерно через 15 секунд"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
|
"back_to_mailcow": "Вернуться к mailcow",
|
||||||
"delayed": "Вход был отложен на %s секунд.",
|
"delayed": "Вход был отложен на %s секунд.",
|
||||||
"fido2_webauthn": "FIDO2/WebAuthn Login",
|
"fido2_webauthn": "FIDO2/WebAuthn Login",
|
||||||
|
"forgot_password": "> Забыли пароль?",
|
||||||
|
"invalid_pass_reset_token": "Токен восстановления пароля недействителен или срок его действия истек.<br>Пожалуйста, запросите новую ссылку для восстановления пароля.",
|
||||||
"login": "Войти",
|
"login": "Войти",
|
||||||
"mobileconfig_info": "Пожалуйста, войдите в систему как пользователь почтового аккаунта для загрузки профиля подключения Apple.",
|
"mobileconfig_info": "Пожалуйста, войдите в систему как пользователь почтового аккаунта для загрузки профиля подключения Apple.",
|
||||||
|
"new_password": "Новый пароль",
|
||||||
|
"new_password_confirm": "Повторите новый пароль",
|
||||||
"other_logins": "Вход с помощью ключа",
|
"other_logins": "Вход с помощью ключа",
|
||||||
"password": "Пароль",
|
"password": "Пароль",
|
||||||
|
"request_reset_password": "Запросить восстановление пароля",
|
||||||
|
"reset_password": "Восстановление пароля",
|
||||||
"username": "Имя пользователя"
|
"username": "Имя пользователя"
|
||||||
},
|
},
|
||||||
"mailbox": {
|
"mailbox": {
|
||||||
@ -716,6 +791,7 @@
|
|||||||
"add_mailbox": "Добавить почтовый аккаунт",
|
"add_mailbox": "Добавить почтовый аккаунт",
|
||||||
"add_recipient_map_entry": "Добавить перезапись получателя",
|
"add_recipient_map_entry": "Добавить перезапись получателя",
|
||||||
"add_resource": "Добавить ресурс",
|
"add_resource": "Добавить ресурс",
|
||||||
|
"add_template": "Добавить шаблон",
|
||||||
"add_tls_policy_map": "Добавить политику TLS",
|
"add_tls_policy_map": "Добавить политику TLS",
|
||||||
"address_rewriting": "Перезапись адресов",
|
"address_rewriting": "Перезапись адресов",
|
||||||
"alias": "Псевдоним",
|
"alias": "Псевдоним",
|
||||||
@ -740,12 +816,12 @@
|
|||||||
"bcc_to_rcpt": "Переключиться на тип \"получатель\"",
|
"bcc_to_rcpt": "Переключиться на тип \"получатель\"",
|
||||||
"bcc_to_sender": "Переключиться на тип \"отправитель\"",
|
"bcc_to_sender": "Переключиться на тип \"отправитель\"",
|
||||||
"bcc_type": "Тип BCC",
|
"bcc_type": "Тип BCC",
|
||||||
"booking_null": "Всегда показывать как свободный",
|
|
||||||
"booking_0_short": "Всегда свободнен",
|
"booking_0_short": "Всегда свободнен",
|
||||||
"booking_custom": "Лимит на количество бронирований",
|
"booking_custom": "Лимит на количество бронирований",
|
||||||
"booking_custom_short": "Жесткий лимит",
|
"booking_custom_short": "Жесткий лимит",
|
||||||
"booking_ltnull": "Неограниченный, занят при бронировании",
|
|
||||||
"booking_lt0_short": "Неограниченный лимит",
|
"booking_lt0_short": "Неограниченный лимит",
|
||||||
|
"booking_ltnull": "Неограниченный, занят при бронировании",
|
||||||
|
"booking_null": "Всегда показывать как свободный",
|
||||||
"catch_all": "Catch-all",
|
"catch_all": "Catch-all",
|
||||||
"created_on": "Дата создания",
|
"created_on": "Дата создания",
|
||||||
"daily": "Раз в день",
|
"daily": "Раз в день",
|
||||||
@ -760,6 +836,7 @@
|
|||||||
"domain_aliases": "Псевдонимы доменов",
|
"domain_aliases": "Псевдонимы доменов",
|
||||||
"domain_quota": "Квота",
|
"domain_quota": "Квота",
|
||||||
"domain_quota_total": "Квота домена",
|
"domain_quota_total": "Квота домена",
|
||||||
|
"domain_templates": "Шаблоны доменов",
|
||||||
"domains": "Домены",
|
"domains": "Домены",
|
||||||
"edit": "Изменить",
|
"edit": "Изменить",
|
||||||
"empty": "Пусто",
|
"empty": "Пусто",
|
||||||
@ -787,6 +864,7 @@
|
|||||||
"mailbox_defaults_info": "Установите настройки по умолчанию для новых почтовых аккаунтов.",
|
"mailbox_defaults_info": "Установите настройки по умолчанию для новых почтовых аккаунтов.",
|
||||||
"mailbox_defquota": "Квота по умолчанию",
|
"mailbox_defquota": "Квота по умолчанию",
|
||||||
"mailbox_quota": "Макс. квота почт. ящика",
|
"mailbox_quota": "Макс. квота почт. ящика",
|
||||||
|
"mailbox_templates": "Шаблоны почтовых ящиков",
|
||||||
"mailboxes": "Почтовые ящики",
|
"mailboxes": "Почтовые ящики",
|
||||||
"max_aliases": "Максимум псевдонимов",
|
"max_aliases": "Максимум псевдонимов",
|
||||||
"max_mailboxes": "Максимум почтовых ящиков",
|
"max_mailboxes": "Максимум почтовых ящиков",
|
||||||
@ -814,16 +892,17 @@
|
|||||||
"recipient_map_new": "Перезапись на",
|
"recipient_map_new": "Перезапись на",
|
||||||
"recipient_map_new_info": "Должен быть действующим почтовым ящиком.",
|
"recipient_map_new_info": "Должен быть действующим почтовым ящиком.",
|
||||||
"recipient_map_old": "Получатель",
|
"recipient_map_old": "Получатель",
|
||||||
"recipient_map_old_info": "Должен быть валидный почтовым ящиком или доменом.",
|
"recipient_map_old_info": "Должен быть действующим почтовым ящиком или доменом.",
|
||||||
"recipient_maps": "Перезапись получателя",
|
"recipient_maps": "Перезапись получателя",
|
||||||
"relay_all": "Ретрансляция всех получателей",
|
"relay_all": "Ретрансляция всех получателей",
|
||||||
|
"relay_unknown": "Ретрансляция неизвестных получателей",
|
||||||
"remove": "Удалить",
|
"remove": "Удалить",
|
||||||
"resources": "Ресурсы",
|
"resources": "Ресурсы",
|
||||||
"running": "В процессе",
|
"running": "В процессе",
|
||||||
"sender": "Отправитель",
|
"sender": "Отправитель",
|
||||||
"set_postfilter": "Использовать как постфильтр",
|
"set_postfilter": "Использовать как постфильтр",
|
||||||
"set_prefilter": "Использовать как предварительный фильтр",
|
"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_1": "Discard mail with probable dangerous file types",
|
||||||
"sieve_preset_2": "Always mark the e-mail of a specific sender as seen",
|
"sieve_preset_2": "Always mark the e-mail of a specific sender as seen",
|
||||||
"sieve_preset_3": "Discard silently, stop all further sieve processing",
|
"sieve_preset_3": "Discard silently, stop all further sieve processing",
|
||||||
@ -831,7 +910,7 @@
|
|||||||
"sieve_preset_5": "Auto responder (vacation)",
|
"sieve_preset_5": "Auto responder (vacation)",
|
||||||
"sieve_preset_6": "Reject mail with response",
|
"sieve_preset_6": "Reject mail with response",
|
||||||
"sieve_preset_7": "Redirect and keep/drop",
|
"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>.",
|
"sieve_preset_header": "Пожалуйста, ознакомьтесь с примерами ниже. Для более подробной информации прочитайте <a href=\"https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)\" target=\"_blank\">Sieve Wikipedia</a>.",
|
||||||
"sogo_visible": "Отображать псевдоним в SOGo",
|
"sogo_visible": "Отображать псевдоним в SOGo",
|
||||||
"sogo_visible_n": "Не отображать псевдоним в SOGo",
|
"sogo_visible_n": "Не отображать псевдоним в SOGo",
|
||||||
@ -840,19 +919,21 @@
|
|||||||
"stats": "Статистика",
|
"stats": "Статистика",
|
||||||
"status": "Статус",
|
"status": "Статус",
|
||||||
"sync_jobs": "Задания синхронизации",
|
"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_check_log": "Проверить журнал",
|
||||||
"syncjob_last_run_result": "Результат последнего запуска",
|
"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": "Размер таблицы",
|
||||||
"table_size_show_n": "Отображать %s полей",
|
"table_size_show_n": "Отображать %s полей",
|
||||||
"target_address": "Владельцы псевдонима",
|
"target_address": "Владельцы псевдонима",
|
||||||
"target_domain": "Целевой домен",
|
"target_domain": "Целевой домен",
|
||||||
|
"template": "Шаблон",
|
||||||
|
"templates": "Шаблоны",
|
||||||
"tls_enforce_in": "Принудительный TLS (входящие)",
|
"tls_enforce_in": "Принудительный TLS (входящие)",
|
||||||
"tls_enforce_out": "Принудительный TLS (исходящие)",
|
"tls_enforce_out": "Принудительный TLS (исходящие)",
|
||||||
"tls_map_dest": "Назначение",
|
"tls_map_dest": "Назначение",
|
||||||
@ -933,14 +1014,27 @@
|
|||||||
"type": "Тип"
|
"type": "Тип"
|
||||||
},
|
},
|
||||||
"queue": {
|
"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": {
|
"ratelimit": {
|
||||||
|
"day": "сообщений / день",
|
||||||
"disabled": "Отключен",
|
"disabled": "Отключен",
|
||||||
"second": "сообщений / секунду",
|
|
||||||
"minute": "сообщений / минуту",
|
|
||||||
"hour": "сообщений / час",
|
"hour": "сообщений / час",
|
||||||
"day": "сообщений / день"
|
"minute": "сообщений / минуту",
|
||||||
|
"second": "сообщений / секунду"
|
||||||
},
|
},
|
||||||
"start": {
|
"start": {
|
||||||
"help": "Справка",
|
"help": "Справка",
|
||||||
@ -966,6 +1060,7 @@
|
|||||||
"bcc_deleted": "Правила BCC удалены: %s",
|
"bcc_deleted": "Правила BCC удалены: %s",
|
||||||
"bcc_edited": "Правило BCC %s отредактировано",
|
"bcc_edited": "Правило BCC %s отредактировано",
|
||||||
"bcc_saved": "Правило BCC сохранено",
|
"bcc_saved": "Правило BCC сохранено",
|
||||||
|
"cors_headers_edited": "Настройки CORS сохранены",
|
||||||
"db_init_complete": "Инициализация базы данных завершена",
|
"db_init_complete": "Инициализация базы данных завершена",
|
||||||
"delete_filter": "Фильтр ID %s удалён",
|
"delete_filter": "Фильтр ID %s удалён",
|
||||||
"delete_filters": "Фильтры удалены: %s",
|
"delete_filters": "Фильтры удалены: %s",
|
||||||
@ -974,19 +1069,23 @@
|
|||||||
"dkim_added": "DKIM ключ сохранён",
|
"dkim_added": "DKIM ключ сохранён",
|
||||||
"dkim_duplicated": "DKIM ключи для домена %s были скопированы в %s",
|
"dkim_duplicated": "DKIM ключи для домена %s были скопированы в %s",
|
||||||
"dkim_removed": "DKIM ключ %s удалён",
|
"dkim_removed": "DKIM ключ %s удалён",
|
||||||
|
"domain_add_dkim_available": "DKIM ключ уже существует",
|
||||||
"domain_added": "Добавлен домен %s",
|
"domain_added": "Добавлен домен %s",
|
||||||
"domain_admin_added": "Администратор домена %s добавлен",
|
"domain_admin_added": "Администратор домена %s добавлен",
|
||||||
"domain_admin_modified": "Сохранить изменения администратора домена %s",
|
"domain_admin_modified": "Сохранить изменения администратора домена %s",
|
||||||
"domain_admin_removed": "Администратор домена %s удалён",
|
"domain_admin_removed": "Администратор домена %s удалён",
|
||||||
|
"domain_footer_modified": "Изменения в нижнем колонтитуле домена %s сохранены",
|
||||||
"domain_modified": "Сохранить изменения домена %s",
|
"domain_modified": "Сохранить изменения домена %s",
|
||||||
"domain_removed": "Домен %s удалён",
|
"domain_removed": "Домен %s удалён",
|
||||||
"dovecot_restart_success": "Dovecot перезапущен успешно",
|
"dovecot_restart_success": "Dovecot перезапущен успешно",
|
||||||
"eas_reset": "Кеш ActiveSync для пользователя %s был сброшен",
|
"eas_reset": "Кеш ActiveSync для пользователя %s был сброшен",
|
||||||
|
"f2b_banlist_refreshed": "Идентификатор банлиста был успешно обновлен.",
|
||||||
"f2b_modified": "Изменения параметров Fail2ban сохранены",
|
"f2b_modified": "Изменения параметров Fail2ban сохранены",
|
||||||
"forwarding_host_added": "Перенаправление узла %s добавлено",
|
"forwarding_host_added": "Перенаправление узла %s добавлено",
|
||||||
"forwarding_host_removed": "Перенаправление узла %s удалено",
|
"forwarding_host_removed": "Перенаправление узла %s удалено",
|
||||||
"global_filter_written": "Фильтр успешно записан в файл",
|
"global_filter_written": "Фильтр успешно записан в файл",
|
||||||
"hash_deleted": "Хеш удалён",
|
"hash_deleted": "Хеш удалён",
|
||||||
|
"ip_check_opt_in_modified": "Параметры проверки IP успешно обновлены",
|
||||||
"item_deleted": "Обьект %s удалён",
|
"item_deleted": "Обьект %s удалён",
|
||||||
"item_released": "Письмо %s восстановлено из карантина",
|
"item_released": "Письмо %s восстановлено из карантина",
|
||||||
"items_deleted": "Обьекты %s удалены",
|
"items_deleted": "Обьекты %s удалены",
|
||||||
@ -997,14 +1096,17 @@
|
|||||||
"mailbox_added": "Почтовый аккаунт %s добавлен",
|
"mailbox_added": "Почтовый аккаунт %s добавлен",
|
||||||
"mailbox_modified": "Изменения почтового аккаунта %s сохранены",
|
"mailbox_modified": "Изменения почтового аккаунта %s сохранены",
|
||||||
"mailbox_removed": "Почтовый аккаунт %s удалён",
|
"mailbox_removed": "Почтовый аккаунт %s удалён",
|
||||||
|
"mailbox_renamed": "Почтовый аккаунт %s был переименован в %s",
|
||||||
"nginx_reloaded": "Обновление конфигурация Nginx закончено",
|
"nginx_reloaded": "Обновление конфигурация Nginx закончено",
|
||||||
"object_modified": "Изменения объекта %s сохранены",
|
"object_modified": "Изменения объекта %s сохранены",
|
||||||
|
"password_changed_success": "Пароль был успешно изменен",
|
||||||
"password_policy_saved": "Политика паролей сохранена",
|
"password_policy_saved": "Политика паролей сохранена",
|
||||||
"pushover_settings_edited": "Настройки сохранены, пожалуйста, выполните проверку доступа",
|
"pushover_settings_edited": "Настройки сохранены, пожалуйста, выполните проверку доступа",
|
||||||
"qlearn_spam": "Письмо ID %s было изучено как спам и удалено",
|
"qlearn_spam": "Письмо ID %s было изучено как спам и удалено",
|
||||||
"queue_command_success": "Команда выполнена успешно",
|
"queue_command_success": "Команда выполнена успешно",
|
||||||
"recipient_map_entry_deleted": "Правило перезаписи получателя ID %s было удалено",
|
"recipient_map_entry_deleted": "Правило перезаписи получателя ID %s было удалено",
|
||||||
"recipient_map_entry_saved": "Правило перезаписи получателя \"%s\" было сохранено",
|
"recipient_map_entry_saved": "Правило перезаписи получателя \"%s\" было сохранено",
|
||||||
|
"recovery_email_sent": "Письмо для восстановления пароля отправлено на %s",
|
||||||
"relayhost_added": "Промежуточный узел %s добавлен",
|
"relayhost_added": "Промежуточный узел %s добавлен",
|
||||||
"relayhost_removed": "Промежуточный узел %s удалён",
|
"relayhost_removed": "Промежуточный узел %s удалён",
|
||||||
"reset_main_logo": "Восстановить логотип по умолчанию",
|
"reset_main_logo": "Восстановить логотип по умолчанию",
|
||||||
@ -1017,6 +1119,9 @@
|
|||||||
"settings_map_added": "Правило добавлено",
|
"settings_map_added": "Правило добавлено",
|
||||||
"settings_map_removed": "Правило ID %s удалено",
|
"settings_map_removed": "Правило ID %s удалено",
|
||||||
"sogo_profile_reset": "Профиль пользователя SOGo %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_deleted": "Политика TLS ID %s удалено",
|
||||||
"tls_policy_map_entry_saved": "Политика TLS \"%s\" сохранена",
|
"tls_policy_map_entry_saved": "Политика TLS \"%s\" сохранена",
|
||||||
"ui_texts": "Изменения текстов UI сохранены",
|
"ui_texts": "Изменения текстов UI сохранены",
|
||||||
@ -1024,13 +1129,11 @@
|
|||||||
"verified_fido2_login": "Авторизация FIDO2 пройдена",
|
"verified_fido2_login": "Авторизация FIDO2 пройдена",
|
||||||
"verified_totp_login": "Авторизация TOTP пройдена",
|
"verified_totp_login": "Авторизация TOTP пройдена",
|
||||||
"verified_webauthn_login": "Авторизация WebAuthn пройдена",
|
"verified_webauthn_login": "Авторизация WebAuthn пройдена",
|
||||||
"verified_yotp_login": "Авторизация Yubico OTP пройдена",
|
"verified_yotp_login": "Авторизация Yubico OTP пройдена"
|
||||||
"cors_headers_edited": "Настройки CORS сохранены",
|
|
||||||
"domain_footer_modified": "Изменения в нижнем колонтитуле домена %s сохранены",
|
|
||||||
"f2b_banlist_refreshed": "Идентификатор банлиста был успешно обновлен."
|
|
||||||
},
|
},
|
||||||
"tfa": {
|
"tfa": {
|
||||||
"api_register": "%s использует Yubico Cloud API. Пожалуйста, получите ключ API для вашего ключа <a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">здесь</a>",
|
"api_register": "%s использует Yubico Cloud API. Пожалуйста, получите ключ API для вашего ключа <a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">здесь</a>",
|
||||||
|
"authenticators": "Аутентификаторы",
|
||||||
"confirm": "Подтвердите",
|
"confirm": "Подтвердите",
|
||||||
"confirm_totp_token": "Пожалуйста, подтвердите изменения, введя сгенерированный код",
|
"confirm_totp_token": "Пожалуйста, подтвердите изменения, введя сгенерированный код",
|
||||||
"delete_tfa": "Отключить TFA",
|
"delete_tfa": "Отключить TFA",
|
||||||
@ -1049,11 +1152,12 @@
|
|||||||
"tfa": "Двухфакторная проверка подлинности",
|
"tfa": "Двухфакторная проверка подлинности",
|
||||||
"tfa_token_invalid": "Неправильный TFA токен",
|
"tfa_token_invalid": "Неправильный TFA токен",
|
||||||
"totp": "OTP (Authy, Google Authenticator и др.)",
|
"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_auth": "<i>Ожидание устройства USB...</i><br><br>Пожалуйста, нажмите кнопку на USB устройстве сейчас.",
|
||||||
"waiting_usb_register": "<i>Ожидание устройства USB...</i><br><br>Пожалуйста, введите пароль выше и подтвердите регистрацию, нажав кнопку на USB устройстве.",
|
"waiting_usb_register": "<i>Ожидание устройства USB...</i><br><br>Пожалуйста, введите пароль выше и подтвердите регистрацию, нажав кнопку на USB устройстве.",
|
||||||
"yubi_otp": "Yubico OTP аутентификация",
|
"webauthn": "WebAuthn аутентификация",
|
||||||
"u2f_deprecated": "Похоже, что ваш ключ был зарегистрирован с использованием устаревшего метода U2F. Мы деактивируем для вас двухфакторную аутентификацию и удалим ваш ключ."
|
"yubi_otp": "Yubico OTP аутентификация"
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"action": "Действия",
|
"action": "Действия",
|
||||||
@ -1070,13 +1174,17 @@
|
|||||||
"alias_valid_until": "Действителен до",
|
"alias_valid_until": "Действителен до",
|
||||||
"aliases_also_send_as": "Разрешено отправлять письма от имени",
|
"aliases_also_send_as": "Разрешено отправлять письма от имени",
|
||||||
"aliases_send_as_all": "Разрешено отправлять письма от любого имени для домена и его псевдонимов",
|
"aliases_send_as_all": "Разрешено отправлять письма от любого имени для домена и его псевдонимов",
|
||||||
|
"allowed_protocols": "Разрешенные протоколы",
|
||||||
"app_hint": "Пароли приложений - это альтернативные пароли для авторизации в IMAP, SMTP, CalDAV, CardDAV и EAS. При этом имя пользователя остается неизменным. <br>SOGo недоступен через пароли приложений.",
|
"app_hint": "Пароли приложений - это альтернативные пароли для авторизации в IMAP, SMTP, CalDAV, CardDAV и EAS. При этом имя пользователя остается неизменным. <br>SOGo недоступен через пароли приложений.",
|
||||||
"app_name": "Название приложения",
|
"app_name": "Название приложения",
|
||||||
"app_passwds": "Пароли приложений",
|
"app_passwds": "Пароли приложений",
|
||||||
"apple_connection_profile": "Профиль подключения Apple",
|
"apple_connection_profile": "Профиль подключения Apple",
|
||||||
"apple_connection_profile_complete": "Этот профиль включает настройки IMAP и SMTP, а также CalDAV (календарей) и CardDAV (контактов) для устройства Apple.",
|
"apple_connection_profile_complete": "Этот профиль включает настройки IMAP и SMTP, а также CalDAV (календарей) и CardDAV (контактов) для устройства Apple.",
|
||||||
"apple_connection_profile_mailonly": "Этот профиль включает только настройки IMAP и SMTP для устройства Apple.",
|
"apple_connection_profile_mailonly": "Этот профиль включает только настройки IMAP и SMTP для устройства Apple.",
|
||||||
|
"apple_connection_profile_with_app_password": "Новый пароль приложения генерируется и добавляется в профиль, поэтому при настройке устройства не требуется вводить пароль. Не предоставляйте доступ к файлу, поскольку он предоставляет полный доступ к вашему почтовому ящику.",
|
||||||
|
"attribute": "Атрибут",
|
||||||
"change_password": "Изменить пароль",
|
"change_password": "Изменить пароль",
|
||||||
|
"change_password_hint_app_passwords": "В вашей учетной записи есть %d паролей приложений, которые не будут изменены. Чтобы управлять ими, перейдите на вкладку \"Пароли приложений\".",
|
||||||
"clear_recent_successful_connections": "Очистить историю успешных подключений",
|
"clear_recent_successful_connections": "Очистить историю успешных подключений",
|
||||||
"client_configuration": "Показать руководство по настройке почтовых клиентов и смартфонов",
|
"client_configuration": "Показать руководство по настройке почтовых клиентов и смартфонов",
|
||||||
"create_app_passwd": "Создать новый пароль",
|
"create_app_passwd": "Создать новый пароль",
|
||||||
@ -1087,6 +1195,7 @@
|
|||||||
"delete_ays": "Пожалуйста, подтвердите удаление",
|
"delete_ays": "Пожалуйста, подтвердите удаление",
|
||||||
"direct_aliases": "Личные псевдонимы",
|
"direct_aliases": "Личные псевдонимы",
|
||||||
"direct_aliases_desc": "На личные псевдонимы распространяются фильтры нежелательной почты и параметры политики TLS.",
|
"direct_aliases_desc": "На личные псевдонимы распространяются фильтры нежелательной почты и параметры политики TLS.",
|
||||||
|
"direct_protocol_access": "Этот пользователь почтового ящика имеет <b>прямой, внешний доступ</b> к следующим протоколам и приложениям. Эта настройка контролируется вашим администратором. Для предоставления доступа к отдельным протоколам и приложениям могут быть созданы пароли приложений.<br> Кнопка \"Вход в веб-почту\" обеспечивает единый вход в SOGo и всегда доступна.",
|
||||||
"eas_reset": "Сбросить кеш ActiveSync устройств",
|
"eas_reset": "Сбросить кеш ActiveSync устройств",
|
||||||
"eas_reset_help": "Во многих случаях сброс кеша устройств помогает восстановить повреждённый профиль ActiveSync.<br><b>Внимание:</b> все письма, календари и контакты будут загружены заново на все ваши устройства!",
|
"eas_reset_help": "Во многих случаях сброс кеша устройств помогает восстановить повреждённый профиль ActiveSync.<br><b>Внимание:</b> все письма, календари и контакты будут загружены заново на все ваши устройства!",
|
||||||
"eas_reset_now": "Сбросить кеш сейчас",
|
"eas_reset_now": "Сбросить кеш сейчас",
|
||||||
@ -1131,15 +1240,18 @@
|
|||||||
"password": "Пароль",
|
"password": "Пароль",
|
||||||
"password_now": "Текущий пароль (подтверждение изменения)",
|
"password_now": "Текущий пароль (подтверждение изменения)",
|
||||||
"password_repeat": "Подтверждение пароля (повтор)",
|
"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_evaluate_x_prio": "Установить высокий приоритет уведомлений для писем с высоким приоритетом [<code>X-Priority: 1</code>]",
|
||||||
"pushover_info": "Настройки Push-уведомления будут применяться ко всей почте <b>%s</b> (за исключением спама), включая псевдонимы (личные, общие и тегированные).",
|
"pushover_info": "Настройки Push-уведомления будут применяться ко всей почте <b>%s</b> (за исключением спама), включая псевдонимы (личные, общие и тегированные).",
|
||||||
"pushover_only_x_prio": "Получать уведомления только о письмах с высоким приоритетом [<code>X-Priority: 1</code>]",
|
"pushover_only_x_prio": "Получать уведомления только о письмах с высоким приоритетом [<code>X-Priority: 1</code>]",
|
||||||
"pushover_sender_array": "Получать уведомления от списка адресов электронной почты <small>(envelop-from, разделённые запятыми)</small>:",
|
"pushover_sender_array": "Получать уведомления от списка адресов электронной почты <small>(envelop-from, разделённые запятыми)</small>:",
|
||||||
"pushover_sender_regex": "Получать уведомления от отправителей, удовлетворяющих regex-выражению:",
|
"pushover_sender_regex": "Получать уведомления от отправителей, удовлетворяющих regex-выражению:",
|
||||||
|
"pushover_sound": "Звук уведомления",
|
||||||
"pushover_text": "Текст уведомления",
|
"pushover_text": "Текст уведомления",
|
||||||
"pushover_title": "Заголовок уведомления",
|
"pushover_title": "Заголовок уведомления",
|
||||||
"pushover_vars": "Когда фильтрация по отправителю не определена, уведомения будут доставлятся от всех отправителей.<br>Можно использовать обычный фильтр по отправителю и расширенный regex-фильтр, а также оба сразу.<br>Пожалуйста, ознакомьтесь с <a href=\"https://pushover.net/privacy\">Pushover Privacy Policy</a> перед использованием шаблонов для текста и заголовка",
|
"pushover_vars": "Когда фильтрация по отправителю не определена, уведомения будут доставлятся от всех отправителей.<br>Можно использовать обычный фильтр по отправителю и расширенный regex-фильтр, а также оба сразу.<br>Пожалуйста, ознакомьтесь с <a href=\"https://pushover.net/privacy\">Pushover Privacy Policy</a> перед использованием шаблонов для текста и заголовка",
|
||||||
"pushover_verify": "Проверить доступ",
|
"pushover_verify": "Проверить доступ",
|
||||||
|
"pw_recovery_email": "Адрес для восстановления пароля",
|
||||||
"q_add_header": "Нежелательная почта",
|
"q_add_header": "Нежелательная почта",
|
||||||
"q_all": "Все категории",
|
"q_all": "Все категории",
|
||||||
"q_reject": "Отклонённая почта",
|
"q_reject": "Отклонённая почта",
|
||||||
@ -1180,15 +1292,15 @@
|
|||||||
"spamfilter_yellow": "Жёлтый: эти письма могут быть спамом, будут доставлены в папку \"Спам\"",
|
"spamfilter_yellow": "Жёлтый: эти письма могут быть спамом, будут доставлены в папку \"Спам\"",
|
||||||
"status": "Статус",
|
"status": "Статус",
|
||||||
"sync_jobs": "Задания синхронизации",
|
"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_check_log": "Проверить журнал",
|
||||||
"syncjob_last_run_result": "Результат",
|
"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_handling": "Обработка тегированной почты",
|
||||||
"tag_help_example": "Пример тегированного адреса электронной почты: <code>ich<b>+Facebook</b>@example.org</code>",
|
"tag_help_example": "Пример тегированного адреса электронной почты: <code>ich<b>+Facebook</b>@example.org</code>",
|
||||||
"tag_help_explain": "Переместить в подпапку: будет создана новая подпапка в INBOX с именем тега, например: \"INBOX/Facebook\".<br>\r\n Добавить к теме письма: имя тега будет добавлено к теме письма, например: \"[Facebook] My News\".",
|
"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>, как получатель.",
|
"tls_policy_warning": "<strong>Предупреждение:</strong> Если вы включите принудительное шифрованние почты, вы можете столкнуться с потерей писем.<br>Сообщения, которые не соответствуют политике, будут отбрасываться с сообщением почтовым сервером о серьёзном сбое.<br>Этот параметр применяется к вашему основному адресу электронной почты (логину), всем личным псевдонимам и псевдонимам доменов. Подразумеваются только псевдонимы <b>с одним почтовым ящиком</b>, как получатель.",
|
||||||
"user_settings": "Настройки пользователя",
|
"user_settings": "Настройки пользователя",
|
||||||
"username": "Имя пользователя",
|
"username": "Имя пользователя",
|
||||||
|
"value": "Значение",
|
||||||
"verify": "Проверить",
|
"verify": "Проверить",
|
||||||
"waiting": "В ожидании",
|
"waiting": "В ожидании",
|
||||||
"week": "неделю",
|
"week": "неделю",
|
||||||
"weekly": "Раз в неделю",
|
"weekly": "Раз в неделю",
|
||||||
"weeks": "недели",
|
"weeks": "недели",
|
||||||
"year": "год",
|
|
||||||
"years": "лет",
|
|
||||||
"allowed_protocols": "Разрешенные протоколы",
|
|
||||||
"apple_connection_profile_with_app_password": "Новый пароль приложения генерируется и добавляется в профиль, поэтому при настройке устройства не требуется вводить пароль. Не предоставляйте доступ к файлу, поскольку он предоставляет полный доступ к вашему почтовому ящику.",
|
|
||||||
"direct_protocol_access": "Этот пользователь почтового ящика имеет <b>прямой, внешний доступ</b> к следующим протоколам и приложениям. Эта настройка контролируется вашим администратором. Для предоставления доступа к отдельным протоколам и приложениям могут быть созданы пароли приложений.<br> Кнопка \"веб-почту\" обеспечивает единый вход в SOGo и всегда доступна.",
|
|
||||||
"with_app_password": "с паролем приложения",
|
"with_app_password": "с паролем приложения",
|
||||||
"change_password_hint_app_passwords": "В вашей учетной записи есть {{number_of_app_passwords}} паролей приложений, которые не будут изменены. Чтобы управлять ими, перейдите на вкладку \"Пароли приложений\".",
|
"year": "год",
|
||||||
"attribute": "Атрибут",
|
"years": "лет"
|
||||||
"value": "Значение"
|
|
||||||
},
|
},
|
||||||
"warning": {
|
"warning": {
|
||||||
"cannot_delete_self": "Вы не можете удалить сами себя",
|
"cannot_delete_self": "Вы не можете удалить сами себя",
|
||||||
@ -1230,10 +1337,5 @@
|
|||||||
"quota_exceeded_scope": "Квота домена превышена: могут быть созданы только почтовые ящики без лимита.",
|
"quota_exceeded_scope": "Квота домена превышена: могут быть созданы только почтовые ящики без лимита.",
|
||||||
"session_token": "Неверный токен формы: несоответствие токена",
|
"session_token": "Неверный токен формы: несоответствие токена",
|
||||||
"session_ua": "Неверный токен формы: ошибка проверки User-Agent"
|
"session_ua": "Неверный токен формы: ошибка проверки User-Agent"
|
||||||
},
|
|
||||||
"datatables": {
|
|
||||||
"collapse_all": "Свернуть все",
|
|
||||||
"expand_all": "Развернуть все",
|
|
||||||
"infoPostFix": ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ $template_data = [
|
|||||||
'mailboxes' => $mailboxes,
|
'mailboxes' => $mailboxes,
|
||||||
'lang_mailbox' => json_encode($lang['mailbox']),
|
'lang_mailbox' => json_encode($lang['mailbox']),
|
||||||
'lang_rl' => json_encode($lang['ratelimit']),
|
'lang_rl' => json_encode($lang['ratelimit']),
|
||||||
|
'lang_edit' => json_encode($lang['edit']),
|
||||||
'lang_datatables' => json_encode($lang['datatables']),
|
'lang_datatables' => json_encode($lang['datatables']),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
var acl = '{{ acl_json|raw }}';
|
var acl = '{{ acl_json|raw }}';
|
||||||
var lang = {{ lang_mailbox|raw }};
|
var lang = {{ lang_mailbox|raw }};
|
||||||
var lang_rl = {{ lang_rl|raw }};
|
var lang_rl = {{ lang_rl|raw }};
|
||||||
|
var lang_edit = {{ lang_edit|raw }};
|
||||||
var lang_datatables = {{ lang_datatables|raw }};
|
var lang_datatables = {{ lang_datatables|raw }};
|
||||||
var csrf_token = '{{ csrf_token }}';
|
var csrf_token = '{{ csrf_token }}';
|
||||||
var pagination_size = Math.trunc('{{ pagination_size }}');
|
var pagination_size = Math.trunc('{{ pagination_size }}');
|
||||||
|
@ -43,8 +43,10 @@ services:
|
|||||||
|
|
||||||
redis-mailcow:
|
redis-mailcow:
|
||||||
image: redis:7-alpine
|
image: redis:7-alpine
|
||||||
|
entrypoint: /redis-conf.sh
|
||||||
volumes:
|
volumes:
|
||||||
- redis-vol-1:/data/
|
- redis-vol-1:/data/
|
||||||
|
- ./data/conf/redis/redis-conf.sh:/redis-conf.sh:z
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- netfilter-mailcow
|
- netfilter-mailcow
|
||||||
@ -52,6 +54,7 @@ services:
|
|||||||
- "${REDIS_PORT:-127.0.0.1:7654}:6379"
|
- "${REDIS_PORT:-127.0.0.1:7654}:6379"
|
||||||
environment:
|
environment:
|
||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
sysctls:
|
sysctls:
|
||||||
- net.core.somaxconn=4096
|
- net.core.somaxconn=4096
|
||||||
networks:
|
networks:
|
||||||
@ -80,7 +83,7 @@ services:
|
|||||||
- clamd
|
- clamd
|
||||||
|
|
||||||
rspamd-mailcow:
|
rspamd-mailcow:
|
||||||
image: mailcow/rspamd:1.98
|
image: mailcow/rspamd:1.99
|
||||||
stop_grace_period: 30s
|
stop_grace_period: 30s
|
||||||
depends_on:
|
depends_on:
|
||||||
- dovecot-mailcow
|
- dovecot-mailcow
|
||||||
@ -91,6 +94,7 @@ services:
|
|||||||
- IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
|
- IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/hooks/rspamd:/hooks:Z
|
- ./data/hooks/rspamd:/hooks:Z
|
||||||
@ -112,7 +116,7 @@ services:
|
|||||||
- rspamd
|
- rspamd
|
||||||
|
|
||||||
php-fpm-mailcow:
|
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"
|
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis-mailcow
|
- redis-mailcow
|
||||||
@ -147,6 +151,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
- LOG_LINES=${LOG_LINES:-9999}
|
- LOG_LINES=${LOG_LINES:-9999}
|
||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
- DBNAME=${DBNAME}
|
- DBNAME=${DBNAME}
|
||||||
@ -193,7 +198,7 @@ services:
|
|||||||
- phpfpm
|
- phpfpm
|
||||||
|
|
||||||
sogo-mailcow:
|
sogo-mailcow:
|
||||||
image: mailcow/sogo:nightly-20241112
|
image: mailcow/sogo:nightly-20241205
|
||||||
environment:
|
environment:
|
||||||
- DBNAME=${DBNAME}
|
- DBNAME=${DBNAME}
|
||||||
- DBUSER=${DBUSER}
|
- DBUSER=${DBUSER}
|
||||||
@ -210,6 +215,7 @@ services:
|
|||||||
- MASTER=${MASTER:-y}
|
- MASTER=${MASTER:-y}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
dns:
|
dns:
|
||||||
- ${IPV4_NETWORK:-172.22.1}.254
|
- ${IPV4_NETWORK:-172.22.1}.254
|
||||||
volumes:
|
volumes:
|
||||||
@ -240,7 +246,7 @@ services:
|
|||||||
- sogo
|
- sogo
|
||||||
|
|
||||||
dovecot-mailcow:
|
dovecot-mailcow:
|
||||||
image: mailcow/dovecot:nightly-20241112
|
image: mailcow/dovecot:nightly-20241205
|
||||||
depends_on:
|
depends_on:
|
||||||
- mysql-mailcow
|
- mysql-mailcow
|
||||||
- netfilter-mailcow
|
- netfilter-mailcow
|
||||||
@ -282,6 +288,7 @@ services:
|
|||||||
- MASTER=${MASTER:-y}
|
- MASTER=${MASTER:-y}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
|
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
|
||||||
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-n}
|
- FLATCURVE_EXPERIMENTAL=${FLATCURVE_EXPERIMENTAL:-n}
|
||||||
ports:
|
ports:
|
||||||
@ -324,7 +331,7 @@ services:
|
|||||||
- dovecot
|
- dovecot
|
||||||
|
|
||||||
postfix-mailcow:
|
postfix-mailcow:
|
||||||
image: mailcow/postfix:1.77
|
image: mailcow/postfix:1.78
|
||||||
depends_on:
|
depends_on:
|
||||||
mysql-mailcow:
|
mysql-mailcow:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
@ -346,6 +353,7 @@ services:
|
|||||||
- DBPASS=${DBPASS}
|
- DBPASS=${DBPASS}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||||
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
||||||
cap_add:
|
cap_add:
|
||||||
@ -375,33 +383,26 @@ services:
|
|||||||
|
|
||||||
nginx-mailcow:
|
nginx-mailcow:
|
||||||
depends_on:
|
depends_on:
|
||||||
- sogo-mailcow
|
|
||||||
- php-fpm-mailcow
|
|
||||||
- redis-mailcow
|
- redis-mailcow
|
||||||
image: nginx:mainline-alpine
|
- php-fpm-mailcow
|
||||||
|
- sogo-mailcow
|
||||||
|
- rspamd-mailcow
|
||||||
|
image: mailcow/nginx:1.00
|
||||||
dns:
|
dns:
|
||||||
- ${IPV4_NETWORK:-172.22.1}.254
|
- ${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:
|
environment:
|
||||||
- HTTPS_PORT=${HTTPS_PORT:-443}
|
- HTTPS_PORT=${HTTPS_PORT:-443}
|
||||||
- HTTP_PORT=${HTTP_PORT:-80}
|
- HTTP_PORT=${HTTP_PORT:-80}
|
||||||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||||
- IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
|
- ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
|
||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
- SKIP_SOGO=${SKIP_SOGO:-n}
|
- SKIP_SOGO=${SKIP_SOGO:-n}
|
||||||
- ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
|
- SKIP_RSPAMD=${SKIP_RSPAMD:-n}
|
||||||
- ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
|
- 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:
|
volumes:
|
||||||
- ./data/web:/web:ro,z
|
- ./data/web:/web:ro,z
|
||||||
- ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
|
- ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
|
||||||
@ -428,7 +429,7 @@ services:
|
|||||||
condition: service_started
|
condition: service_started
|
||||||
unbound-mailcow:
|
unbound-mailcow:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
image: mailcow/acme:1.90
|
image: mailcow/acme:1.91
|
||||||
dns:
|
dns:
|
||||||
- ${IPV4_NETWORK:-172.22.1}.254
|
- ${IPV4_NETWORK:-172.22.1}.254
|
||||||
environment:
|
environment:
|
||||||
@ -451,6 +452,7 @@ services:
|
|||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
- SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n}
|
- SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n}
|
||||||
- SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
|
- SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
|
||||||
volumes:
|
volumes:
|
||||||
@ -465,7 +467,7 @@ services:
|
|||||||
- acme
|
- acme
|
||||||
|
|
||||||
netfilter-mailcow:
|
netfilter-mailcow:
|
||||||
image: mailcow/netfilter:1.59
|
image: mailcow/netfilter:1.60
|
||||||
stop_grace_period: 30s
|
stop_grace_period: 30s
|
||||||
restart: always
|
restart: always
|
||||||
privileged: true
|
privileged: true
|
||||||
@ -477,6 +479,7 @@ services:
|
|||||||
- SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
|
- SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
- MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
|
- MAILCOW_REPLICA_IP=${MAILCOW_REPLICA_IP:-}
|
||||||
- DISABLE_NETFILTER_ISOLATION_RULE=${DISABLE_NETFILTER_ISOLATION_RULE:-n}
|
- DISABLE_NETFILTER_ISOLATION_RULE=${DISABLE_NETFILTER_ISOLATION_RULE:-n}
|
||||||
network_mode: "host"
|
network_mode: "host"
|
||||||
@ -484,7 +487,7 @@ services:
|
|||||||
- /lib/modules:/lib/modules:ro
|
- /lib/modules:/lib/modules:ro
|
||||||
|
|
||||||
watchdog-mailcow:
|
watchdog-mailcow:
|
||||||
image: mailcow/watchdog:2.05
|
image: mailcow/watchdog:2.06
|
||||||
dns:
|
dns:
|
||||||
- ${IPV4_NETWORK:-172.22.1}.254
|
- ${IPV4_NETWORK:-172.22.1}.254
|
||||||
tmpfs:
|
tmpfs:
|
||||||
@ -530,6 +533,7 @@ services:
|
|||||||
- HTTPS_PORT=${HTTPS_PORT:-443}
|
- HTTPS_PORT=${HTTPS_PORT:-443}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
- EXTERNAL_CHECKS_THRESHOLD=${EXTERNAL_CHECKS_THRESHOLD:-1}
|
- EXTERNAL_CHECKS_THRESHOLD=${EXTERNAL_CHECKS_THRESHOLD:-1}
|
||||||
- NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
|
- NGINX_THRESHOLD=${NGINX_THRESHOLD:-5}
|
||||||
- UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
|
- UNBOUND_THRESHOLD=${UNBOUND_THRESHOLD:-5}
|
||||||
@ -555,7 +559,7 @@ services:
|
|||||||
- watchdog
|
- watchdog
|
||||||
|
|
||||||
dockerapi-mailcow:
|
dockerapi-mailcow:
|
||||||
image: mailcow/dockerapi:2.09
|
image: mailcow/dockerapi:2.10
|
||||||
security_opt:
|
security_opt:
|
||||||
- label=disable
|
- label=disable
|
||||||
restart: always
|
restart: always
|
||||||
@ -566,6 +570,7 @@ services:
|
|||||||
- TZ=${TZ}
|
- TZ=${TZ}
|
||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
|
- REDISPASS=${REDISPASS}
|
||||||
volumes:
|
volumes:
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
networks:
|
networks:
|
||||||
|
@ -26,7 +26,7 @@ for bin in openssl curl docker git awk sha1sum grep cut; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Check Docker Version (need at least 24.X)
|
# 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
|
if [[ $docker_version -lt 24 ]]; then
|
||||||
echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m"
|
echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m"
|
||||||
@ -264,6 +264,12 @@ DBUSER=mailcow
|
|||||||
DBPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
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)
|
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
|
# HTTP/S Bindings
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
@ -204,7 +204,7 @@ fi
|
|||||||
|
|
||||||
# Trigger a Redis save for a consistent Redis copy
|
# Trigger a Redis save for a consistent Redis copy
|
||||||
echo -ne "\033[1mRunning redis-cli save... \033[0m"
|
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
|
# Syncing volumes related to compose project
|
||||||
# Same here: make sure destination exists
|
# 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
|
${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)
|
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 \
|
docker run --name mailcow-backup --rm \
|
||||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \
|
||||||
-v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:ro,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"
|
echo -e "\033[33mNot purging anything...\033[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
SELECT 10
|
||||||
FLUSHDB
|
FLUSHDB
|
||||||
EOF
|
EOF
|
||||||
'
|
"
|
||||||
if [ -d ./data/web/nextcloud/config ]; then
|
if [ -d ./data/web/nextcloud/config ]; then
|
||||||
mv ./data/web/nextcloud/config/ ./data/conf/nextcloud-config-folder-$(date +%s).bak
|
mv ./data/web/nextcloud/config/ ./data/conf/nextcloud-config-folder-$(date +%s).bak
|
||||||
fi
|
fi
|
||||||
|
@ -15,15 +15,15 @@ if [[ "$response" =~ ^(yes|y)$ ]]; then
|
|||||||
docker stop ${RSPAMD_ID}
|
docker stop ${RSPAMD_ID}
|
||||||
echo "LUA will return nil when it succeeds or print a warning/error when it fails."
|
echo "LUA will return nil when it succeeds or print a warning/error when it fails."
|
||||||
echo "Deleting all RS* keys - if any"
|
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"
|
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"
|
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"
|
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"
|
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"
|
echo "Starting Rspamd container"
|
||||||
docker start ${RSPAMD_ID}
|
docker start ${RSPAMD_ID}
|
||||||
fi
|
fi
|
||||||
|
13
update.sh
13
update.sh
@ -288,9 +288,9 @@ fix_broken_dnslist_conf() {
|
|||||||
# Check if the file contains the autogenerated comment
|
# Check if the file contains the autogenerated comment
|
||||||
if grep -q "# Autogenerated by mailcow" "$file"; then
|
if grep -q "# Autogenerated by mailcow" "$file"; then
|
||||||
# Ask the user if custom changes were made
|
# 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"
|
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
|
if [[ "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
|
||||||
rm "$file"
|
rm "$file"
|
||||||
echo -e "\e[32mdns_blocklists.cf has been deleted and will be properly regenerated"
|
echo -e "\e[32mdns_blocklists.cf has been deleted and will be properly regenerated"
|
||||||
@ -540,6 +540,7 @@ CONFIG_ARRAY=(
|
|||||||
"SPAMHAUS_DQS_KEY"
|
"SPAMHAUS_DQS_KEY"
|
||||||
"SKIP_UNBOUND_HEALTHCHECK"
|
"SKIP_UNBOUND_HEALTHCHECK"
|
||||||
"DISABLE_NETFILTER_ISOLATION_RULE"
|
"DISABLE_NETFILTER_ISOLATION_RULE"
|
||||||
|
"REDISPASS"
|
||||||
)
|
)
|
||||||
|
|
||||||
detect_bad_asn
|
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 '# 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
|
echo 'DISABLE_NETFILTER_ISOLATION_RULE=n' >> mailcow.conf
|
||||||
fi
|
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
|
elif ! grep -q "${option}" mailcow.conf; then
|
||||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||||
echo "${option}=n" >> mailcow.conf
|
echo "${option}=n" >> mailcow.conf
|
||||||
|
Loading…
Reference in New Issue
Block a user