# The console, served on the WireGuard hub address.
#
# Runs inside the provisioning container's network namespace, so it listens on
# 10.66.0.1 — the tunnel address itself. A VPN client therefore needs no route
# beyond the management subnet it already has, and the request arrives at the
# application with its real 10.66.0.x source, which is what the console's own
# IP allowlist checks.
#
# The certificate is the one the public Caddy already obtains and renews for
# this hostname. A certificate is bound to the NAME, not to the address that
# serves it, so the same file is valid here. Shared read-only rather than
# duplicated: a second ACME client would be a second thing to renew, and a
# private address cannot satisfy an HTTP challenge in any case.
{
	admin off
	auto_https off
}

https://{$VPN_INTERNAL_HOST}:443 {
	bind {$VPN_HUB_ADDRESS}
	tls {$VPN_CERT_PATH} {$VPN_KEY_PATH}

	# To the application directly. Resolvable because this container shares the
	# provisioning container's namespace, which is on the compose network.
	reverse_proxy app:80 {
		header_up X-Forwarded-For {remote_host}
		header_up X-Forwarded-Proto https
		header_up Host {host}
	}
}

# A health port the deployment can ask, on the hub address and nowhere else.
#
# The site above matches on the console's HOSTNAME. A probe to the bare address
# sends no SNI, is offered no certificate and fails the handshake — which is
# indistinguishable from the gateway being down, and that is precisely the
# mistake that left VPN_READY false on a healthy tunnel. Plain HTTP on a
# separate port removes TLS, SNI and name resolution from the question and
# answers only what is being asked: is this gateway listening, in this network
# namespace, right now.
#
# Not a hole: 10.66.0.1 exists only inside the tunnel, and this port is never
# published. Caddy also refuses to start when the certificate above cannot be
# read, so a health port that answers proves the whole file loaded.
http://{$VPN_HUB_ADDRESS}:{$VPN_HEALTH_PORT:8081} {
	# bind, not merely a matching hostname: without it Caddy listens on every
	# interface in the namespace and only MATCHES on the address. Nothing is
	# published, so it was not reachable from outside either way — but "on the
	# hub address and nowhere else" should be what the file actually does.
	bind {$VPN_HUB_ADDRESS}
	respond /healthz 204
	respond 404
}
