V0 / DEPLOYMENT NOTES

A domain. A VPS.
A very small private Internet.

The VPS is deployed with Cloudflare DNS and publicly trusted certificates. An isolated Linux client passed IKEv2, private DNS, HTTPS, and revocation checks. The browser walkthrough remains a simulation; a physical iPhone test is still required.

Cloudflare is a good fit for DNS—not the VPN itself.
Use Cloudflare for authoritative DNS and Let’s Encrypt DNS-01 validation. Native IKEv2 runs on a VPS with public UDP 500 and 4500. Workers and a standard Cloudflare Tunnel do not replace that endpoint.

01 / Public DNS stays small

RecordValueCloudflare mode
join.secret.townVPS public IPv4DNS only for v0
vpn.secret.townVPS public IPv4DNS only (required)
*.coolkids.secret.townNo public A/AAAA/CNAMEPrivate DNS only

Do not create a wildcard public record that makes private names resolve accidentally. Keep existing email and other DNS records intact when moving nameservers. If Cloudflare already hosts your zone, no nameserver change is needed.

02 / One Linux VPS

Safari / Terminal / other apps → native iPhone IKEv2 → strongSwan gateway → 10.77.0.1 DNS :53 CoreDNS HTTPS :443 Caddy → home / radio / wall

The kit targets a dedicated Ubuntu 24.04 VPS. Private listeners bind only to 10.77.0.1. A separate public Caddy listener serves the join page. The firewall requires both an inbound IPsec policy and an active device IP for every private request.

Only 10.77.0.1/32 is selected into the v0 tunnel. Ordinary Internet traffic stays on the device’s normal connection. No full-tunnel NAT or IP forwarding is needed when all services run on the gateway.

03 / Publicly trusted certificates

Use Let’s Encrypt DNS validation for join.secret.town, vpn.secret.town, and *.coolkids.secret.town. The kit uses Certbot’s Cloudflare plugin and an RSA certificate for the VPN endpoint. A wildcard certificate does not require a public wildcard address.

Cloudflare Origin CA certificates are not suitable: Safari and native IKEv2 must trust the endpoint directly. Keep the zone-scoped Cloudflare API token on the VPS, never in chat or browser code. Public certificate transparency will reveal certificate names; this is private access, not an invisible domain.

04 / One credential per device

The local CLI creates a one-use invitation. The API atomically consumes it, allocates a non-recycled private IP, and encrypts a random EAP credential at rest. A short-lived, one-use download delivers the native profile to Safari.

The root-only gateway worker applies configuration changes about every two seconds. Revocation removes the device from the firewall allow-set first, clears stale credentials, and terminates its IKE session. The revoke command reports success only after the worker confirms completion.

05 / The test that matters

  1. Disconnected: query a public resolver for radio.coolkids.secret.town. Expect NXDOMAIN.
  2. Install the personalized profile on an ordinary iPhone and connect in Settings.
  3. Open the same hostname in Safari. It must load over HTTPS with no certificate warning.
  4. Visit an ordinary website and compare the public egress IP with and without the VPN. It should stay the same on the same Wi-Fi network.
  5. Disconnect. Private service access must stop, even if the browser retains an old DNS answer.
  6. Reconnect, revoke that device from the CLI, and confirm its existing session and new connections stop while another device still works.

A DNS cache is not an access-control boundary.
A reload may briefly use a cached address or cached page. Test a fresh network request and wait for the private DNS TTL to expire before asserting NXDOMAIN. Use the firewall test independently.

What’s implemented—and what isn’t

Download the v0 source & deployment kit

Start with README.md and deploy/README.md in the archive. No credentials are included.