ipv6_controller.sh 5.7 KB

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