diff --git a/containers/stalwart/tools/stalwart_set_mode.sh b/containers/stalwart/tools/stalwart_set_mode.sh index 2b59242..72421f4 100644 --- a/containers/stalwart/tools/stalwart_set_mode.sh +++ b/containers/stalwart/tools/stalwart_set_mode.sh @@ -102,20 +102,41 @@ appStalwartSetMode() { fi fi - # ---- 3. The firewall -------------------------------------------------- - if declare -F firewallRebuildFromDatabase >/dev/null 2>&1; then - firewallRebuildFromDatabase >/dev/null 2>&1 \ - && isSuccessful "Firewall rules rebuilt." + # ---- 3. Make the port change real -------------------------------------- + # No separate firewall rebuild here: the install below reallocates ports and + # rebuilds the rules from the result. Rebuilding first would only work from + # the old allocation and then be immediately redone. + # + # Port publishing lives in the compose file, which is only written from the + # app config during an install — so without this the setting would be saved, + # the WebUI would show the new mode, and the container would carry on + # publishing exactly the ports it did before. A mode switch that leaves port + # 25 open is worse than no mode switch at all. + # + # Safe to call from here: tools are dispatched inline rather than as their + # own task, so this is not a nested task and cannot deadlock on the task + # lock. It also cannot recurse — the install path calls Stalwart's install + # hooks, and none of them call back into this tool. Provisioning inside that + # install is a no-op too, since it skips once config.json exists. + # + # No --reset-network: the admin port keeps its existing random allocation, + # so the WebUI link people have bookmarked does not move underneath them. + echo "" + isNotice "Applying the port changes (reinstalling the app — mail and mailboxes are kept)…" + + if ! declare -F dockerInstallApp >/dev/null 2>&1; then + isError "Cannot reinstall automatically from here." + isNotice " Run it yourself to finish the switch: libreportal app install stalwart" + return 1 fi - # ---- 4. What is left --------------------------------------------------- - # Port publishing lives in the compose file, which is written from the app - # config at install time. Saying this plainly beats letting someone believe - # port 25 closed when it is still bound. - echo "" - isNotice "One step left: reinstall the app so the port changes reach the container." - isNotice " libreportal app install stalwart" - isNotice " Your mail, mailboxes and DKIM keys are untouched by this." + if dockerInstallApp "stalwart" "" "false"; then + isSuccessful "Stalwart is now running in '$mode' mode." + else + isError "The reinstall did not complete — the setting is saved, but the ports" + isNotice " have not changed yet. Retry with: libreportal app install stalwart" + return 1 + fi if [[ "$mode" == "public" ]]; then echo ""