Fix: closing the web admin port to the internet also blocked Caddy
Confirmed live: a bare `ufw delete allow <port>` closes it on every interface, including the caddy_net bridge — Caddy's own request to host.docker.internal:PORT is ordinary INPUT-chain traffic as far as UFW is concerned, not something that bypasses it just because the source is a local container. Closing the port outright silently took Caddy's reverse-proxy path down with it. Added ufw_allow_from_caddy_net() to scope the port to caddy_net's own subnet instead of leaving it fully closed — reachable from Caddy, still closed to the public internet. Wired into both asterisk-digital-ocean.sh and asterisk.sh in place of the plain delete. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015X1jRGHwrvovz2qkhKfDZi
This commit is contained in:
@@ -187,6 +187,24 @@ you. No-ops if UFW is already active or not installed. Always allows SSH
|
||||
first (reading the real port from `sshd_config` in case it's non-default)
|
||||
before enabling, so this can't lock out the session running the installer.
|
||||
|
||||
### Closing a port to the internet without also closing it to Caddy
|
||||
|
||||
```bash
|
||||
ufw_allow_from_caddy_net PORT [PROTO] # PROTO defaults to tcp
|
||||
```
|
||||
|
||||
When `CADDY_SERVICE_MODE` is `"local"` (see above) and you `ufw delete
|
||||
allow` a port because Caddy fronts it now, don't stop there — UFW rules
|
||||
apply to *all* interfaces unless scoped, and Caddy's own request to
|
||||
`host.docker.internal:PORT` is ordinary INPUT-chain traffic arriving over
|
||||
the `caddy_net` bridge, not the public internet. A bare `ufw delete allow`
|
||||
blocks that too and silently breaks the service (confirmed live: closing
|
||||
the web admin port outright took Caddy down with it). Call
|
||||
`ufw_allow_from_caddy_net` right after the `delete` to re-open the port
|
||||
scoped to just `caddy_net`'s subnet — reachable from Caddy, not from the
|
||||
internet. See `services/asterisk-digital-ocean.sh` and
|
||||
`services/asterisk.sh` for the pattern.
|
||||
|
||||
### README generation
|
||||
|
||||
```bash
|
||||
|
||||
@@ -268,6 +268,31 @@ ensure_ufw_enabled() {
|
||||
log_success "UFW enabled (SSH on port ${_ssh_port} allowed first, so this won't lock you out)."
|
||||
}
|
||||
|
||||
# Scopes a UFW allow rule to just the caddy_net bridge subnet instead of
|
||||
# every interface. Needed for any port that only needs to be reachable from
|
||||
# a *locally* Caddy-fronted service (via host.docker.internal) — a plain
|
||||
# `ufw delete allow <port>` closes it everywhere, but Caddy's own request to
|
||||
# host.docker.internal is still ordinary INPUT-chain traffic as far as UFW
|
||||
# is concerned, arriving over the caddy_net bridge, not the internet. UFW
|
||||
# rules apply to all interfaces unless scoped like this, so closing the
|
||||
# port outright also silently breaks Caddy.
|
||||
ufw_allow_from_caddy_net() {
|
||||
local _port="$1" _proto="${2:-tcp}"
|
||||
command -v ufw &>/dev/null || return 0
|
||||
[ "$DRY_RUN" = true ] && return 0
|
||||
|
||||
local _subnet
|
||||
_subnet="$(docker network inspect "${SITE_CADDY_NET:-caddy_net}" \
|
||||
--format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null)"
|
||||
if [ -n "$_subnet" ]; then
|
||||
ufw allow from "$_subnet" to any port "$_port" proto "$_proto" comment 'Caddy internal only' >/dev/null 2>&1
|
||||
log_info "Port ${_port}/${_proto} reachable only from Caddy's internal network (${_subnet}), not the public internet."
|
||||
else
|
||||
log_warning "Could not determine ${SITE_CADDY_NET:-caddy_net}'s subnet — port ${_port}/${_proto} stays closed."
|
||||
log_warning "If Caddy can't reach it: ufw allow from <caddy_net-subnet> to any port ${_port} proto ${_proto}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ── SSH client config (~/.ssh/config) Host aliases ────────────────────────────
|
||||
# Lets "ssh <alias>" connect directly to user@host without typing it out each
|
||||
# time — handy for VPN/NetBird peers with unmemorable IPs. Operates on the
|
||||
|
||||
@@ -699,7 +699,7 @@ CADDY_BLOCK
|
||||
ufw allow "${WEB_ADMIN_PORT_VAL}/tcp"
|
||||
else
|
||||
ufw delete allow "${WEB_ADMIN_PORT_VAL}/tcp" 2>/dev/null || true
|
||||
log_info "Web admin port ${WEB_ADMIN_PORT_VAL} kept closed to the internet — Caddy fronts it locally."
|
||||
ufw_allow_from_caddy_net "${WEB_ADMIN_PORT_VAL}"
|
||||
fi
|
||||
ufw allow 8088/tcp
|
||||
ufw allow 8089/tcp
|
||||
|
||||
@@ -528,7 +528,7 @@ ENV
|
||||
ufw allow 5061/tcp
|
||||
if [[ "$CADDY_SERVICE_CONFIGURED" == true && "$CADDY_SERVICE_MODE" == "local" ]]; then
|
||||
ufw delete allow "${WEB_ADMIN_PORT_VAL}/tcp" 2>/dev/null || true
|
||||
log_info "Web admin port ${WEB_ADMIN_PORT_VAL} kept off the LAN — Caddy fronts it locally."
|
||||
ufw_allow_from_caddy_net "${WEB_ADMIN_PORT_VAL}"
|
||||
else
|
||||
ufw allow "${WEB_ADMIN_PORT_VAL}/tcp"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user