2
0

ipv6_controller.sh 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/usr/bin/env bash
  2. # _modules/scripts/ipv6_controller.sh
  3. # THIS SCRIPT IS DESIGNED TO BE RUNNING BY MAILCOW SCRIPTS ONLY!
  4. # DO NOT, AGAIN, NOT TRY TO RUN THIS SCRIPT STANDALONE!!!!!!
  5. # 1) Check if the host supports IPv6
  6. get_ipv6_support() {
  7. if grep -qs '^1' /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null \
  8. || ! ip -6 route show default &>/dev/null; then
  9. DETECTED_IPV6=false
  10. echo -e "${YELLOW}IPv6 not detected on host – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
  11. else
  12. DETECTED_IPV6=true
  13. echo -e "IPv6 detected on host – ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
  14. fi
  15. }
  16. # 2) Ensure Docker daemon.json has (or create) the required IPv6 settings
  17. docker_daemon_edit(){
  18. DOCKER_DAEMON_CONFIG="/etc/docker/daemon.json"
  19. MISSING=()
  20. _has_kv() { grep -Eq "\"$1\"\s*:\s*$2" "$DOCKER_DAEMON_CONFIG" 2>/dev/null; }
  21. if [[ -f "$DOCKER_DAEMON_CONFIG" ]]; then
  22. # reject empty or whitespace-only file immediately
  23. if [[ ! -s "$DOCKER_DAEMON_CONFIG" ]] || ! grep -Eq '[{}]' "$DOCKER_DAEMON_CONFIG"; then
  24. echo -e "${RED}ERROR: $DOCKER_DAEMON_CONFIG exists but is empty or contains no JSON braces – please initialize it with valid JSON (e.g. {}).${NC}"
  25. exit 1
  26. fi
  27. # Validate JSON if jq is present
  28. if command -v jq &>/dev/null && ! jq empty "$DOCKER_DAEMON_CONFIG" &>/dev/null; then
  29. echo -e "${RED}ERROR: Invalid JSON in $DOCKER_DAEMON_CONFIG – please correct manually.${NC}"
  30. exit 1
  31. fi
  32. # Gather missing keys
  33. ! _has_kv ipv6 true && MISSING+=("ipv6: true")
  34. ! grep -Eq '"fixed-cidr-v6"\s*:\s*".+"' "$DOCKER_DAEMON_CONFIG" \
  35. && MISSING+=('fixed-cidr-v6: "fd00:dead:beef:c0::/80"')
  36. if [[ -n "$docker_version" && "$docker_version" -ge 27 ]]; then
  37. _has_kv ipv6 true && ! _has_kv ip6tables true && MISSING+=("ip6tables: true")
  38. ! _has_kv experimental true && MISSING+=("experimental: true")
  39. fi
  40. # Fix if needed
  41. if ((${#MISSING[@]}>0)); then
  42. echo -e "${MAGENTA}Your daemon.json is missing: ${YELLOW}${MISSING[*]}${NC}"
  43. if [[ -n "$FORCE" ]]; then
  44. ans=Y
  45. else
  46. read -p "Would you like to update $DOCKER_DAEMON_CONFIG now? [Y/n] " ans
  47. ans=${ans:-Y}
  48. fi
  49. if [[ $ans =~ ^[Yy]$ ]]; then
  50. cp "$DOCKER_DAEMON_CONFIG" "${DOCKER_DAEMON_CONFIG}.bak"
  51. if command -v jq &>/dev/null; then
  52. TMP=$(mktemp)
  53. JQ_FILTER='.ipv6 = true | .["fixed-cidr-v6"] = "fd00:dead:beef:c0::/80"'
  54. [[ "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]] \
  55. && JQ_FILTER+=' | .ip6tables = true | .experimental = true'
  56. jq "$JQ_FILTER" "$DOCKER_DAEMON_CONFIG" >"$TMP" && mv "$TMP" "$DOCKER_DAEMON_CONFIG"
  57. echo -e "${LIGHT_GREEN}daemon.json updated. Restarting Docker...${NC}"
  58. (command -v systemctl &>/dev/null && systemctl restart docker) || service docker restart
  59. echo -e "${YELLOW}Docker restarted.${NC}"
  60. else
  61. echo -e "${RED}Please install jq or manually update daemon.json and restart Docker.${NC}"
  62. exit 1
  63. fi
  64. else
  65. echo -e "${YELLOW}User declined Docker update – please insert these changes manually:${NC}"
  66. echo "${MISSING[*]}"
  67. exit 1
  68. fi
  69. fi
  70. else
  71. # Create new daemon.json if missing
  72. if [[ -n "$FORCE" ]]; then
  73. ans=Y
  74. else
  75. read -p "$DOCKER_DAEMON_CONFIG not found. Create it with IPv6 settings? [Y/n] " ans
  76. ans=${ans:-Y}
  77. fi
  78. if [[ $ans =~ ^[Yy]$ ]]; then
  79. DOCKER_MAJOR=$(docker version --format '{{.Server.Version}}' 2>/dev/null | cut -d. -f1)
  80. if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
  81. cat > "$DOCKER_DAEMON_CONFIG" <<EOF
  82. {
  83. "ipv6": true,
  84. "fixed-cidr-v6": "fd00:dead:beef:c0::/80",
  85. "ip6tables": true,
  86. "experimental": true
  87. }
  88. EOF
  89. else
  90. cat > "$DOCKER_DAEMON_CONFIG" <<EOF
  91. {
  92. "ipv6": true,
  93. "fixed-cidr-v6": "fd00:dead:beef:c0::/80"
  94. }
  95. EOF
  96. fi
  97. echo "${GREEN}Created $DOCKER_DAEMON_CONFIG with IPv6 settings.${NC}"
  98. echo "Restarting Docker..."
  99. (command -v systemctl &>/dev/null && systemctl restart docker) || service docker restart
  100. echo "Docker restarted."
  101. else
  102. echo "User declined to create daemon.json – please manually merge the docker daemon with these configs:"
  103. echo "${MISSING[*]}"
  104. exit 1
  105. fi
  106. fi
  107. }
  108. # 3) Main wrapper for generate_config.sh and update.sh
  109. configure_ipv6() {
  110. # detect manual override if mailcow.conf is present
  111. if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]] && grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
  112. MANUAL_SETTING=$(grep '^ENABLE_IPV6=' "$MAILCOW_CONF" | cut -d= -f2)
  113. elif [[ -z "$MAILCOW_CONF" ]] && [[ ! -z "${ENABLE_IPV6:-}" ]]; then
  114. MANUAL_SETTING="$ENABLE_IPV6"
  115. else
  116. MANUAL_SETTING=""
  117. fi
  118. get_ipv6_support
  119. # if user manually set it, check for mismatch
  120. if [[ -n "$MANUAL_SETTING" ]]; then
  121. if [[ "$MANUAL_SETTING" == "false" && "$DETECTED_IPV6" == "true" ]]; then
  122. echo -e "${RED}ERROR: You have ENABLE_IPV6=false but your host and Docker support IPv6.${NC}"
  123. echo -e "${RED}This can create an open relay. Please set ENABLE_IPV6=true in your mailcow.conf and re-run.${NC}"
  124. exit 1
  125. elif [[ "$MANUAL_SETTING" == "true" && "$DETECTED_IPV6" == "false" ]]; then
  126. echo -e "${RED}ERROR: You have ENABLE_IPV6=true but your host does not support IPv6.${NC}"
  127. echo -e "${RED}Please disable or fix your host/Docker IPv6 support, or set ENABLE_IPV6=false.${NC}"
  128. exit 1
  129. else
  130. echo "Manual ENABLE_IPV6=$MANUAL_SETTING detected and matches system status—no changes applied."
  131. return
  132. fi
  133. fi
  134. # no manual override: proceed to set or export
  135. if [[ "$DETECTED_IPV6" == "true" ]]; then
  136. docker_daemon_edit
  137. else
  138. echo "Skipping Docker IPv6 configuration because host does not support IPv6."
  139. fi
  140. # now write into mailcow.conf or export
  141. if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then
  142. LINE="ENABLE_IPV6=$DETECTED_IPV6"
  143. if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
  144. sed -i "s/^ENABLE_IPV6=.*/$LINE/" "$MAILCOW_CONF"
  145. else
  146. echo "$LINE" >> "$MAILCOW_CONF"
  147. fi
  148. else
  149. export IPV6_BOOL="$DETECTED_IPV6"
  150. fi
  151. echo "IPv6 configuration complete: ENABLE_IPV6=$DETECTED_IPV6"
  152. }