feat: add backend DNS resolution check and improve gateway sync reliability

Add wait_for_backend_dns function to verify backend hostname resolution before attempting bootstrap/sync operations. Configure NEXAVPN_BACKEND_HOST environment variable and net.ipv4.ip_forward sysctl in docker-compose. Use atomic write pattern for state.json via temporary file to prevent corruption on failed downloads. Make sysctl ip_forward call conditional on write permissions and non-fatal.
This commit is contained in:
2026-03-17 19:21:39 +01:00
parent ebc449079b
commit 6349147d8d
2 changed files with 24 additions and 3 deletions

View File

@@ -57,6 +57,8 @@ services:
dockerfile: gateway/Dockerfile dockerfile: gateway/Dockerfile
depends_on: depends_on:
- backend - backend
sysctls:
net.ipv4.ip_forward: "1"
cap_add: cap_add:
- NET_ADMIN - NET_ADMIN
- SYS_MODULE - SYS_MODULE
@@ -75,6 +77,7 @@ services:
NEXAVPN_GATEWAY_INTERFACE: ${NEXAVPN_GATEWAY_INTERFACE:-wg0} NEXAVPN_GATEWAY_INTERFACE: ${NEXAVPN_GATEWAY_INTERFACE:-wg0}
NEXAVPN_UPLINK_INTERFACE: ${NEXAVPN_UPLINK_INTERFACE:-eth0} NEXAVPN_UPLINK_INTERFACE: ${NEXAVPN_UPLINK_INTERFACE:-eth0}
NEXAVPN_ENABLE_MASQUERADE: ${NEXAVPN_ENABLE_MASQUERADE:-true} NEXAVPN_ENABLE_MASQUERADE: ${NEXAVPN_ENABLE_MASQUERADE:-true}
NEXAVPN_BACKEND_HOST: ${NEXAVPN_BACKEND_HOST:-backend}
volumes: volumes:
- ./scripts/gateway-entrypoint.sh:/scripts/gateway-entrypoint.sh:ro - ./scripts/gateway-entrypoint.sh:/scripts/gateway-entrypoint.sh:ro
- gateway-state:/var/lib/nexavpn - gateway-state:/var/lib/nexavpn

View File

@@ -9,7 +9,9 @@ UPLINK_IFACE="${NEXAVPN_UPLINK_INTERFACE:-eth0}"
ENABLE_MASQUERADE="${NEXAVPN_ENABLE_MASQUERADE:-true}" ENABLE_MASQUERADE="${NEXAVPN_ENABLE_MASQUERADE:-true}"
GATEWAY_NAME="${NEXAVPN_GATEWAY_NAME:-primary-gateway}" GATEWAY_NAME="${NEXAVPN_GATEWAY_NAME:-primary-gateway}"
BOOTSTRAP_URL="${NEXAVPN_GATEWAY_BOOTSTRAP_URL:-http://backend:8080/api/v1/gateway-agent/bootstrap}" BOOTSTRAP_URL="${NEXAVPN_GATEWAY_BOOTSTRAP_URL:-http://backend:8080/api/v1/gateway-agent/bootstrap}"
SYNC_BASE_URL="${NEXAVPN_GATEWAY_SYNC_URL:-http://backend:8080/api/v1/gateway-agent}"
GATEWAY_ID_FILE="/var/lib/nexavpn/gateway-id" GATEWAY_ID_FILE="/var/lib/nexavpn/gateway-id"
BACKEND_HOST="${NEXAVPN_BACKEND_HOST:-backend}"
if [ -z "${GATEWAY_BOOTSTRAP_TOKEN:-}" ]; then if [ -z "${GATEWAY_BOOTSTRAP_TOKEN:-}" ]; then
echo "GATEWAY_BOOTSTRAP_TOKEN is required." echo "GATEWAY_BOOTSTRAP_TOKEN is required."
@@ -54,7 +56,18 @@ NFT_CONF="/var/lib/nexavpn/nftables.generated.conf"
mkdir -p /etc/wireguard mkdir -p /etc/wireguard
wait_for_backend_dns() {
if getent hosts "${BACKEND_HOST}" >/dev/null 2>&1; then
return 0
fi
echo "Backend host ${BACKEND_HOST} is not resolvable yet."
return 1
}
apply_bundle() { apply_bundle() {
wait_for_backend_dns || return 1
if [ -z "${NEXAVPN_GATEWAY_ID:-}" ]; then if [ -z "${NEXAVPN_GATEWAY_ID:-}" ]; then
bootstrap_gateway || return 1 bootstrap_gateway || return 1
fi fi
@@ -64,12 +77,15 @@ apply_bundle() {
return 1 return 1
fi fi
SYNC_URL="${NEXAVPN_GATEWAY_SYNC_URL}/${NEXAVPN_GATEWAY_ID}/sync" SYNC_URL="${SYNC_BASE_URL}/${NEXAVPN_GATEWAY_ID}/sync"
echo "Fetching bundle from ${SYNC_URL}" echo "Fetching bundle from ${SYNC_URL}"
TMP_STATE_JSON="${STATE_JSON}.tmp"
rm -f "${TMP_STATE_JSON}"
curl -fsSL \ curl -fsSL \
-H "X-Gateway-Bootstrap-Token: ${GATEWAY_BOOTSTRAP_TOKEN}" \ -H "X-Gateway-Bootstrap-Token: ${GATEWAY_BOOTSTRAP_TOKEN}" \
"${SYNC_URL}" \ "${SYNC_URL}" \
-o "${STATE_JSON}" -o "${TMP_STATE_JSON}" || return 1
mv "${TMP_STATE_JSON}" "${STATE_JSON}"
INTERFACE_ADDRESS=$(jq -r '.interface.address' "${STATE_JSON}") INTERFACE_ADDRESS=$(jq -r '.interface.address' "${STATE_JSON}")
NETWORK_CIDR=$(jq -r '.interface.network_cidr' "${STATE_JSON}") NETWORK_CIDR=$(jq -r '.interface.network_cidr' "${STATE_JSON}")
@@ -123,7 +139,9 @@ EOF
echo "}" echo "}"
} > "${NFT_CONF}" } > "${NFT_CONF}"
sysctl -w net.ipv4.ip_forward=1 >/dev/null if [ -w /proc/sys/net/ipv4/ip_forward ]; then
sysctl -w net.ipv4.ip_forward=1 >/dev/null || true
fi
nft -f "${NFT_CONF}" nft -f "${NFT_CONF}"