1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-06-14 18:40:23 +00:00

Compare commits

...

16 Commits

Author SHA1 Message Date
DerLinkman 4db1569c93 Squashed commit of the following:
commit 94c1a6c4e1
Author: DerLinkman <niklas.meyer@servercow.de>
Date:   Wed Sep 10 16:20:58 2025 +0200

    scripts:  ipv6_controller improvement + fix modules handling (#6722)

    * Fix subscript handling for modules

    * ipv6: detect case when link local is present

    * v6-controller: removed fixed-cidr for docker 28+
2025-09-10 16:22:19 +02:00
FreddleSpl0it 7ce3b0faed Merge pull request #6719 from mailcow/staging
Update 2025-09
2025-09-10 11:18:17 +02:00
FreddleSpl0it b1c088a57f Merge pull request #6718 from mailcow/staging
Update 2025-09
2025-09-10 11:05:09 +02:00
FreddleSpl0it 527f27d249 Merge pull request #6632 from mailcow/staging
Update 2025-07
2025-07-15 07:48:37 +02:00
FreddleSpl0it 1994b9895b Merge pull request #6537 from mailcow/staging
Update 2025-05_2
2025-05-13 10:16:30 +02:00
FreddleSpl0it 798e6a4c00 Merge pull request #6535 from mailcow/staging
Update 2025-05
2025-05-13 09:58:32 +02:00
FreddleSpl0it 3f493e043d Merge pull request #6468 from mailcow/staging
Update 2025-03b
2025-04-07 09:09:39 +02:00
FreddleSpl0it 2c47145dee Merge pull request #6419 from mailcow/staging
Update 2025-03a
2025-03-27 09:19:29 +01:00
FreddleSpl0it c3c68360dc Merge pull request #6391 from mailcow/staging
Update 2025-03
2025-03-25 08:10:50 +01:00
FreddleSpl0it a632980871 Merge pull request #6336 from mailcow/staging
Update 2025-02
2025-02-27 11:48:57 +01:00
FreddleSpl0it 2d1ef41d32 Merge pull request #6335 from mailcow/staging
Update 2025-02
2025-02-27 11:05:55 +01:00
FreddleSpl0it 120366fec7 Merge pull request #6291 from mailcow/staging
Update 2025-01a
2025-02-04 13:55:30 +01:00
DerLinkman 244d4b8c4c compose: rollback clamd version until next major... accidentally pushed 2025-01-29 13:46:53 +01:00
DerLinkman f92ddd86c5 clamd: update to 1.4.2 + build from source instead using alpine packages (#6273)
* clamd: update to 1.4.2 + build from source instead using alpine packages

* clamd: remove exposed ports from buildfile

* clamd: cleanup dockerfile
2025-01-29 09:49:04 +01:00
FreddleSpl0it ba0349a911 Merge pull request #6256 from mailcow/staging
[Nginx] move conf.d include to end of nginx.conf
2025-01-23 14:55:38 +01:00
FreddleSpl0it 8caf09cd80 Merge pull request #6253 from mailcow/staging
2025-01
2025-01-23 12:01:38 +01:00
4 changed files with 145 additions and 42 deletions
+109 -39
View File
@@ -5,14 +5,65 @@
# 1) Check if the host supports IPv6 # 1) Check if the host supports IPv6
get_ipv6_support() { get_ipv6_support() {
if grep -qs '^1' /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null \ # ---- helper: probe external IPv6 connectivity without DNS ----
|| ! ip -6 route show default &>/dev/null; then _probe_ipv6_connectivity() {
# Use literal, always-on IPv6 echo responders (no DNS required)
local PROBE_IPS=("2001:4860:4860::8888" "2606:4700:4700::1111")
local ip rc=1
for ip in "${PROBE_IPS[@]}"; do
if command -v ping6 &>/dev/null; then
ping6 -c1 -W2 "$ip" &>/dev/null || ping6 -c1 -w2 "$ip" &>/dev/null
rc=$?
elif command -v ping &>/dev/null; then
ping -6 -c1 -W2 "$ip" &>/dev/null || ping -6 -c1 -w2 "$ip" &>/dev/null
rc=$?
else
rc=1
fi
[[ $rc -eq 0 ]] && return 0
done
return 1
}
if [[ ! -f /proc/net/if_inet6 ]] || grep -qs '^1' /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null; then
DETECTED_IPV6=false DETECTED_IPV6=false
echo -e "${YELLOW}IPv6 not detected on host ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}" echo -e "${YELLOW}IPv6 not detected on host ${LIGHT_RED}IPv6 is administratively disabled${YELLOW}.${NC}"
else return
DETECTED_IPV6=true
echo -e "IPv6 detected on host ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
fi fi
if ip -6 route show default 2>/dev/null | grep -qE '^default'; then
echo -e "${YELLOW}Default IPv6 route found testing external IPv6 connectivity...${NC}"
if _probe_ipv6_connectivity; then
DETECTED_IPV6=true
echo -e "IPv6 detected on host ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
else
DETECTED_IPV6=false
echo -e "${YELLOW}Default IPv6 route present but external IPv6 connectivity failed ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
fi
return
fi
if ip -6 addr show scope global 2>/dev/null | grep -q 'inet6'; then
DETECTED_IPV6=false
echo -e "${YELLOW}Global IPv6 address present but no default route ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
return
fi
if ip -6 addr show scope link 2>/dev/null | grep -q 'inet6'; then
echo -e "${YELLOW}Only link-local IPv6 addresses found testing external IPv6 connectivity...${NC}"
if _probe_ipv6_connectivity; then
DETECTED_IPV6=true
echo -e "External IPv6 connectivity available ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
else
DETECTED_IPV6=false
echo -e "${YELLOW}Only link-local IPv6 present and no external connectivity ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
fi
return
fi
DETECTED_IPV6=false
echo -e "${YELLOW}IPv6 not detected on host ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
} }
# 2) Ensure Docker daemon.json has (or create) the required IPv6 settings # 2) Ensure Docker daemon.json has (or create) the required IPv6 settings
@@ -21,7 +72,7 @@ docker_daemon_edit(){
DOCKER_MAJOR=$(docker version --format '{{.Server.Version}}' 2>/dev/null | cut -d. -f1) DOCKER_MAJOR=$(docker version --format '{{.Server.Version}}' 2>/dev/null | cut -d. -f1)
MISSING=() MISSING=()
_has_kv() { grep -Eq "\"$1\"\s*:\s*$2" "$DOCKER_DAEMON_CONFIG" 2>/dev/null; } _has_kv() { grep -Eq "\"$1\"[[:space:]]*:[[:space:]]*$2" "$DOCKER_DAEMON_CONFIG" 2>/dev/null; }
if [[ -f "$DOCKER_DAEMON_CONFIG" ]]; then if [[ -f "$DOCKER_DAEMON_CONFIG" ]]; then
@@ -38,12 +89,18 @@ docker_daemon_edit(){
fi fi
# Gather missing keys # Gather missing keys
! _has_kv ipv6 true && MISSING+=("ipv6: true") ! _has_kv ipv6 true && MISSING+=("ipv6: true")
! grep -Eq '"fixed-cidr-v6"\s*:\s*".+"' "$DOCKER_DAEMON_CONFIG" \
&& MISSING+=('fixed-cidr-v6: "fd00:dead:beef:c0::/80"') # For Docker < 28, keep requiring fixed-cidr-v6 (default bridge needs it on old engines)
if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -le 27 ]]; then if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 28 ]]; then
! grep -Eq '"fixed-cidr-v6"[[:space:]]*:[[:space:]]*".+"' "$DOCKER_DAEMON_CONFIG" \
&& MISSING+=('fixed-cidr-v6: "fd00:dead:beef:c0::/80"')
fi
# For Docker < 27, ip6tables needed and was tied to experimental in older releases
if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
_has_kv ipv6 true && ! _has_kv ip6tables true && MISSING+=("ip6tables: true") _has_kv ipv6 true && ! _has_kv ip6tables true && MISSING+=("ip6tables: true")
! _has_kv experimental true && MISSING+=("experimental: true") ! _has_kv experimental true && MISSING+=("experimental: true")
fi fi
# Fix if needed # Fix if needed
@@ -60,9 +117,19 @@ docker_daemon_edit(){
cp "$DOCKER_DAEMON_CONFIG" "${DOCKER_DAEMON_CONFIG}.bak" cp "$DOCKER_DAEMON_CONFIG" "${DOCKER_DAEMON_CONFIG}.bak"
if command -v jq &>/dev/null; then if command -v jq &>/dev/null; then
TMP=$(mktemp) TMP=$(mktemp)
JQ_FILTER='.ipv6 = true | .["fixed-cidr-v6"] = "fd00:dead:beef:c0::/80"' # Base filter: ensure ipv6 = true
[[ "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]] \ JQ_FILTER='.ipv6 = true'
&& JQ_FILTER+=' | .ip6tables = true | .experimental = true'
# Add fixed-cidr-v6 only for Docker < 28
if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 28 ]]; then
JQ_FILTER+=' | .["fixed-cidr-v6"] = (.["fixed-cidr-v6"] // "fd00:dead:beef:c0::/80")'
fi
# Add ip6tables/experimental only for Docker < 27
if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
JQ_FILTER+=' | .ip6tables = true | .experimental = true'
fi
jq "$JQ_FILTER" "$DOCKER_DAEMON_CONFIG" >"$TMP" && mv "$TMP" "$DOCKER_DAEMON_CONFIG" jq "$JQ_FILTER" "$DOCKER_DAEMON_CONFIG" >"$TMP" && mv "$TMP" "$DOCKER_DAEMON_CONFIG"
echo -e "${LIGHT_GREEN}daemon.json updated. Restarting Docker...${NC}" echo -e "${LIGHT_GREEN}daemon.json updated. Restarting Docker...${NC}"
(command -v systemctl &>/dev/null && systemctl restart docker) || service docker restart (command -v systemctl &>/dev/null && systemctl restart docker) || service docker restart
@@ -97,12 +164,19 @@ docker_daemon_edit(){
"experimental": true "experimental": true
} }
EOF EOF
else elif [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 28 ]]; then
cat > "$DOCKER_DAEMON_CONFIG" <<EOF cat > "$DOCKER_DAEMON_CONFIG" <<EOF
{ {
"ipv6": true, "ipv6": true,
"fixed-cidr-v6": "fd00:dead:beef:c0::/80" "fixed-cidr-v6": "fd00:dead:beef:c0::/80"
} }
EOF
else
# Docker 28+: ipv6 works without fixed-cidr-v6
cat > "$DOCKER_DAEMON_CONFIG" <<EOF
{
"ipv6": true
}
EOF EOF
fi fi
echo -e "${GREEN}Created $DOCKER_DAEMON_CONFIG with IPv6 settings.${NC}" echo -e "${GREEN}Created $DOCKER_DAEMON_CONFIG with IPv6 settings.${NC}"
@@ -122,7 +196,7 @@ configure_ipv6() {
# detect manual override if mailcow.conf is present # detect manual override if mailcow.conf is present
if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]] && grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]] && grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
MANUAL_SETTING=$(grep '^ENABLE_IPV6=' "$MAILCOW_CONF" | cut -d= -f2) MANUAL_SETTING=$(grep '^ENABLE_IPV6=' "$MAILCOW_CONF" | cut -d= -f2)
elif [[ -z "$MAILCOW_CONF" ]] && [[ ! -z "${ENABLE_IPV6:-}" ]]; then elif [[ -z "$MAILCOW_CONF" ]] && [[ -n "${ENABLE_IPV6:-}" ]]; then
MANUAL_SETTING="$ENABLE_IPV6" MANUAL_SETTING="$ENABLE_IPV6"
else else
MANUAL_SETTING="" MANUAL_SETTING=""
@@ -131,38 +205,34 @@ configure_ipv6() {
get_ipv6_support get_ipv6_support
# if user manually set it, check for mismatch # if user manually set it, check for mismatch
if [[ -n "$MANUAL_SETTING" ]]; then if [[ "$DETECTED_IPV6" != "true" ]]; then
if [[ "$MANUAL_SETTING" == "false" && "$DETECTED_IPV6" == "true" ]]; then if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then
echo -e "${RED}ERROR: You have ENABLE_IPV6=false but your host and Docker support IPv6.${NC}" if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
echo -e "${RED}This can create an open relay. Please set ENABLE_IPV6=true in your mailcow.conf and re-run.${NC}" sed -i 's/^ENABLE_IPV6=.*/ENABLE_IPV6=false/' "$MAILCOW_CONF"
exit 1 else
elif [[ "$MANUAL_SETTING" == "true" && "$DETECTED_IPV6" == "false" ]]; then echo "ENABLE_IPV6=false" >> "$MAILCOW_CONF"
echo -e "${RED}ERROR: You have ENABLE_IPV6=true but your host does not support IPv6.${NC}" fi
echo -e "${RED}Please disable or fix your host/Docker IPv6 support, or set ENABLE_IPV6=false.${NC}"
exit 1
else else
return export IPV6_BOOL=false
fi fi
fi
# no manual override: proceed to set or export
if [[ "$DETECTED_IPV6" == "true" ]]; then
docker_daemon_edit
else
echo "Skipping Docker IPv6 configuration because host does not support IPv6." echo "Skipping Docker IPv6 configuration because host does not support IPv6."
echo "Make sure to check if your docker daemon.json does not include \"enable_ipv6\": true if you do not want IPv6."
echo "IPv6 configuration complete: ENABLE_IPV6=false"
sleep 2
return
fi fi
# now write into mailcow.conf or export docker_daemon_edit
if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then
LINE="ENABLE_IPV6=$DETECTED_IPV6"
if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
sed -i "s/^ENABLE_IPV6=.*/$LINE/" "$MAILCOW_CONF" sed -i 's/^ENABLE_IPV6=.*/ENABLE_IPV6=true/' "$MAILCOW_CONF"
else else
echo "$LINE" >> "$MAILCOW_CONF" echo "ENABLE_IPV6=true" >> "$MAILCOW_CONF"
fi fi
else else
export IPV6_BOOL="$DETECTED_IPV6" export IPV6_BOOL=true
fi fi
echo "IPv6 configuration complete: ENABLE_IPV6=$DETECTED_IPV6" echo "IPv6 configuration complete: ENABLE_IPV6=true"
} }
+21
View File
@@ -1,5 +1,26 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Ensure the script is run from the directory that contains a link of .env
# Resolve the directory this script lives in for consistent behavior when invoked from elsewhere
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" >/dev/null 2>&1 && pwd)"
# Ensure script is executed in the mailcow installation directory by checking for a .env symlink that points to mailcow.conf
if [ ! -L "${PWD}/.env" ]; then
echo -e "\e[33mPlease run this script from the mailcow installation directory.\e[0m"
echo -e " \e[36mcd /path/to/mailcow && ./generate_config.sh\e[0m"
exit 1
fi
# Verify the .env symlink points to a mailcow.conf file
env_target="$(readlink -f "${PWD}/.env" 2>/dev/null || true)"
if [ -z "$env_target" ] || [ "$(basename "$env_target")" != "mailcow.conf" ]; then
echo -e "\e[31mThe found .env symlink does not point to a mailcow.conf file.\e[0m"
echo -e "\e[33mPlease create a symbolic link .env -> mailcow.conf inside the mailcow directory and run this script there.\e[0m"
echo -e "\e[33mNote: 'ln -s mailcow.conf .env' will create the symlink even if mailcow.conf does not yet exist.\e[0m"
echo -e " \e[36mcd /path/to/mailcow && ln -s mailcow.conf .env && ./generate_config.sh\e[0m"
exit 1
fi
# Load mailcow Generic Scripts # Load mailcow Generic Scripts
source _modules/scripts/core.sh source _modules/scripts/core.sh
source _modules/scripts/ipv6_controller.sh source _modules/scripts/ipv6_controller.sh
+1 -1
View File
@@ -293,7 +293,7 @@ if ! ssh -o StrictHostKeyChecking=no \
-i "${REMOTE_SSH_KEY}" \ -i "${REMOTE_SSH_KEY}" \
${REMOTE_SSH_HOST} \ ${REMOTE_SSH_HOST} \
-p ${REMOTE_SSH_PORT} \ -p ${REMOTE_SSH_PORT} \
${SCRIPT_DIR}/../update.sh -f --gc ; then "cd \"${SCRIPT_DIR}/../\" && ./update.sh -f --gc" ; then
>&2 echo -e "\e[31m[ERR]\e[0m - Could not cleanup old images on remote" >&2 echo -e "\e[31m[ERR]\e[0m - Could not cleanup old images on remote"
fi fi
+14 -2
View File
@@ -3,6 +3,20 @@
############## Begin Function Section ############## ############## Begin Function Section ##############
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
MAILCOW_CONF="${SCRIPT_DIR}/mailcow.conf"
# Ensure the script is run from the directory that contains mailcow.conf
if [ ! -f "${PWD}/mailcow.conf" ]; then
if [ -f "${SCRIPT_DIR}/mailcow.conf" ]; then
echo -e "\e[33mPlease run this script directly from the mailcow installation directory:\e[0m"
echo -e " \e[36mcd ${SCRIPT_DIR} && ./update.sh\e[0m"
exit 1
else
echo -e "\e[31mmailcow.conf not found in current directory or script directory (\e[36m${SCRIPT_DIR}\e[31m).\e[0m"
echo -e "\e[33mRun this script directly from your mailcow installation directory.\e[0m"
exit 1
fi
fi
BRANCH="$(cd "${SCRIPT_DIR}" && git rev-parse --abbrev-ref HEAD)" BRANCH="$(cd "${SCRIPT_DIR}" && git rev-parse --abbrev-ref HEAD)"
MODULE_DIR="${SCRIPT_DIR}/_modules" MODULE_DIR="${SCRIPT_DIR}/_modules"
@@ -27,8 +41,6 @@ if [ "$(id -u)" -ne "0" ]; then
exit 1 exit 1
fi fi
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Run pre-update-hook # Run pre-update-hook
if [ -f "${SCRIPT_DIR}/pre_update_hook.sh" ]; then if [ -f "${SCRIPT_DIR}/pre_update_hook.sh" ]; then
bash "${SCRIPT_DIR}/pre_update_hook.sh" bash "${SCRIPT_DIR}/pre_update_hook.sh"