Wait for the tunnel interface, and prove the gateway answers
Two things reported success while the tunnel console was unreachable. The services were restarted the moment the hub container counted as started, but the hub brings wg0 up as part of its start command — so they were binding an address that did not exist yet. They now wait for the interface. And readiness was a container-state check. A container can be up and running while the process inside it listens in a network namespace that was torn down underneath it: nothing errors, the address simply refuses connections, and "running" reports everything fine. It asks the gateway now, and only a real answer counts — because the consequence of getting this wrong is a client config naming a resolver that is not there, which takes the device's whole name resolution with it for as long as the tunnel is up. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>feat/portal-design tested-20260727-0946-c464957
parent
d2d79b4f5f
commit
c4649571df
|
|
@ -113,15 +113,25 @@ deployed="$(cat "$STATE_FILE" 2>/dev/null || echo '')"
|
||||||
reconcile_vpn_readiness() {
|
reconcile_vpn_readiness() {
|
||||||
grep -qE '^COMPOSE_PROFILES=.*vpn' .env 2>/dev/null || return 0
|
grep -qE '^COMPOSE_PROFILES=.*vpn' .env 2>/dev/null || return 0
|
||||||
|
|
||||||
sleep 3
|
local host vpn_ready=false
|
||||||
local running vpn_ready
|
host="$(sed -n 's/^VPN_INTERNAL_HOST=//p' .env | tail -1)"
|
||||||
running="$(docker compose --profile vpn ps --status running --services 2>/dev/null || true)"
|
|
||||||
|
|
||||||
if grep -q '^vpn-gateway$' <<<"$running" && grep -q '^vpn-dns$' <<<"$running"; then
|
# ASKED, not assumed. A container can be up and running while the process
|
||||||
vpn_ready=true
|
# inside it listens in a network namespace that was torn down underneath it
|
||||||
else
|
# — nothing errors, the address simply refuses connections, and a
|
||||||
vpn_ready=false
|
# container-state check reports everything fine.
|
||||||
printf '\033[1;33m !\033[0m %s\n' "The tunnel gateway is not running — clients will not be given its resolver."
|
for _ in $(seq 1 10); do
|
||||||
|
if docker compose exec -T vpn-gateway sh -c \
|
||||||
|
"wget -q --spider --no-check-certificate https://127.0.0.1/ 2>/dev/null \
|
||||||
|
|| wget -q -O /dev/null --no-check-certificate https://127.0.0.1/ 2>/dev/null" >/dev/null 2>&1; then
|
||||||
|
vpn_ready=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "$vpn_ready" != "true" ]]; then
|
||||||
|
printf '\033[1;33m !\033[0m %s\n' "The tunnel gateway is not answering on ${host} — clients will not be given its resolver."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$(sed -n 's/^VPN_READY=//p' .env | tail -1)" != "$vpn_ready" ]]; then
|
if [[ "$(sed -n 's/^VPN_READY=//p' .env | tail -1)" != "$vpn_ready" ]]; then
|
||||||
|
|
@ -322,6 +332,13 @@ docker compose restart queue queue-provisioning scheduler reverb
|
||||||
# Nothing errors; connections to the tunnel address are simply refused, which
|
# Nothing errors; connections to the tunnel address are simply refused, which
|
||||||
# looks exactly like the gateway never having worked.
|
# looks exactly like the gateway never having worked.
|
||||||
if grep -qE '^COMPOSE_PROFILES=.*vpn' .env 2>/dev/null; then
|
if grep -qE '^COMPOSE_PROFILES=.*vpn' .env 2>/dev/null; then
|
||||||
|
# And only once wg0 is back. The hub brings the interface up as part of its
|
||||||
|
# start command, so restarting these the instant the container is "started"
|
||||||
|
# has them binding an address that does not exist yet.
|
||||||
|
for _ in $(seq 1 30); do
|
||||||
|
docker compose exec -T queue-provisioning ip -4 addr show wg0 2>/dev/null | grep -q 'inet ' && break
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
docker compose --profile vpn restart vpn-dns vpn-gateway >/dev/null 2>&1 || true
|
docker compose --profile vpn restart vpn-dns vpn-gateway >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue