feat: add gateway bootstrap endpoint with token-based authentication

Add Bootstrap and AgentSyncBundle handlers to gateway package with X-Gateway-Bootstrap-Token header authentication. Implement UpsertByName repository method for idempotent gateway registration. Update gateway entrypoint script to auto-generate keys and bootstrap gateway on first run, persisting gateway ID to disk. Add GATEWAY_BOOTSTRAP_TOKEN config and update environment variables for gateway name, bootstrap URL, and sync URL.
This commit is contained in:
2026-03-17 18:53:26 +01:00
parent a197fb5bb6
commit 16fc6cb1b6
9 changed files with 138 additions and 9 deletions

View File

@@ -12,8 +12,11 @@ DEFAULT_DNS_SERVERS=10.20.0.53
DEFAULT_VPN_CIDR=100.96.0.0/24
DEFAULT_GATEWAY_ENDPOINT=vpn.example.com:51820
DEFAULT_GATEWAY_PUBLIC_KEY=replace-me
GATEWAY_BOOTSTRAP_TOKEN=nexavpn-gateway-bootstrap
NEXAVPN_GATEWAY_ID=
NEXAVPN_GATEWAY_SYNC_URL=http://backend:8080/api/v1/admin/gateways
NEXAVPN_GATEWAY_NAME=primary-gateway
NEXAVPN_GATEWAY_SYNC_URL=http://backend:8080/api/v1/gateway-agent
NEXAVPN_GATEWAY_BOOTSTRAP_URL=http://backend:8080/api/v1/gateway-agent/bootstrap
NEXAVPN_API_TOKEN=
NEXAVPN_GATEWAY_PRIVATE_KEY=
NEXAVPN_GATEWAY_INTERFACE=wg0

View File

@@ -61,8 +61,13 @@ services:
devices:
- /dev/net/tun:/dev/net/tun
environment:
GATEWAY_BOOTSTRAP_TOKEN: ${GATEWAY_BOOTSTRAP_TOKEN:-nexavpn-gateway-bootstrap}
NEXAVPN_GATEWAY_ID: ${NEXAVPN_GATEWAY_ID:-}
NEXAVPN_GATEWAY_SYNC_URL: ${NEXAVPN_GATEWAY_SYNC_URL:-http://backend:8080/api/v1/admin/gateways}
NEXAVPN_GATEWAY_NAME: ${NEXAVPN_GATEWAY_NAME:-primary-gateway}
NEXAVPN_GATEWAY_SYNC_URL: ${NEXAVPN_GATEWAY_SYNC_URL:-http://backend:8080/api/v1/gateway-agent}
NEXAVPN_GATEWAY_BOOTSTRAP_URL: ${NEXAVPN_GATEWAY_BOOTSTRAP_URL:-http://backend:8080/api/v1/gateway-agent/bootstrap}
DEFAULT_GATEWAY_ENDPOINT: ${DEFAULT_GATEWAY_ENDPOINT:-localhost:51820}
DEFAULT_VPN_CIDR: ${DEFAULT_VPN_CIDR:-100.96.0.0/24}
NEXAVPN_API_TOKEN: ${NEXAVPN_API_TOKEN:-}
NEXAVPN_GATEWAY_PRIVATE_KEY: ${NEXAVPN_GATEWAY_PRIVATE_KEY:-}
NEXAVPN_GATEWAY_INTERFACE: ${NEXAVPN_GATEWAY_INTERFACE:-wg0}

View File

@@ -7,10 +7,45 @@ mkdir -p /var/lib/nexavpn
IFACE="${NEXAVPN_GATEWAY_INTERFACE:-wg0}"
UPLINK_IFACE="${NEXAVPN_UPLINK_INTERFACE:-eth0}"
ENABLE_MASQUERADE="${NEXAVPN_ENABLE_MASQUERADE:-true}"
GATEWAY_NAME="${NEXAVPN_GATEWAY_NAME:-primary-gateway}"
BOOTSTRAP_URL="${NEXAVPN_GATEWAY_BOOTSTRAP_URL:-http://backend:8080/api/v1/gateway-agent/bootstrap}"
GATEWAY_ID_FILE="/var/lib/nexavpn/gateway-id"
if [ -z "${NEXAVPN_GATEWAY_ID:-}" ] || [ -z "${NEXAVPN_API_TOKEN:-}" ] || [ -z "${NEXAVPN_GATEWAY_PRIVATE_KEY:-}" ]; then
if [ -z "${GATEWAY_BOOTSTRAP_TOKEN:-}" ]; then
echo "GATEWAY_BOOTSTRAP_TOKEN is required."
tail -f /dev/null
exit 0
fi
if [ -z "${NEXAVPN_GATEWAY_PRIVATE_KEY:-}" ]; then
if [ -f /var/lib/nexavpn/gateway-private.key ]; then
NEXAVPN_GATEWAY_PRIVATE_KEY="$(cat /var/lib/nexavpn/gateway-private.key)"
else
wg genkey | tee /var/lib/nexavpn/gateway-private.key >/tmp/nexavpn-gateway-private.key
NEXAVPN_GATEWAY_PRIVATE_KEY="$(cat /tmp/nexavpn-gateway-private.key)"
rm -f /tmp/nexavpn-gateway-private.key
fi
fi
if [ -z "${NEXAVPN_GATEWAY_ID:-}" ] && [ -f "${GATEWAY_ID_FILE}" ]; then
NEXAVPN_GATEWAY_ID="$(cat "${GATEWAY_ID_FILE}")"
fi
if [ -z "${NEXAVPN_GATEWAY_ID:-}" ]; then
GATEWAY_PUBLIC_KEY="$(printf '%s' "${NEXAVPN_GATEWAY_PRIVATE_KEY}" | wg pubkey)"
echo "Bootstrapping gateway ${GATEWAY_NAME}"
BOOTSTRAP_RESPONSE="$(curl -fsSL \
-H "Content-Type: application/json" \
-H "X-Gateway-Bootstrap-Token: ${GATEWAY_BOOTSTRAP_TOKEN}" \
-d "{\"name\":\"${GATEWAY_NAME}\",\"endpoint\":\"${DEFAULT_GATEWAY_ENDPOINT:-localhost:51820}\",\"public_key\":\"${GATEWAY_PUBLIC_KEY}\",\"listen_port\":51820,\"vpn_cidr\":\"${DEFAULT_VPN_CIDR:-100.96.0.0/24}\",\"dns_servers\":[\"10.20.0.53\"]}" \
"${BOOTSTRAP_URL}")"
NEXAVPN_GATEWAY_ID="$(printf '%s' "${BOOTSTRAP_RESPONSE}" | jq -r '.id')"
printf '%s' "${NEXAVPN_GATEWAY_ID}" > "${GATEWAY_ID_FILE}"
fi
if [ -z "${NEXAVPN_GATEWAY_ID:-}" ] || [ -z "${NEXAVPN_GATEWAY_PRIVATE_KEY:-}" ]; then
echo "Gateway sync is not configured yet."
echo "Set NEXAVPN_GATEWAY_ID, NEXAVPN_API_TOKEN and NEXAVPN_GATEWAY_PRIVATE_KEY."
echo "Gateway bootstrap or key generation failed."
echo "Gateway apply state will be written to /var/lib/nexavpn when configured."
tail -f /dev/null
exit 0
@@ -27,7 +62,7 @@ mkdir -p /etc/wireguard
apply_bundle() {
echo "Fetching bundle from ${SYNC_URL}"
curl -fsSL \
-H "Authorization: Bearer ${NEXAVPN_API_TOKEN}" \
-H "X-Gateway-Bootstrap-Token: ${GATEWAY_BOOTSTRAP_TOKEN}" \
"${SYNC_URL}" \
-o "${STATE_JSON}"