Public IPv6 for Raspberry Pi: a complete 2026 guide
How to give a Raspberry Pi (or any single-board Linux device) its own dedicated public IPv6 address — reachable from anywhere — in 5 minutes.
The Raspberry Pi 4/5 is the default "let me try self-hosting" hardware. The default obstacle: your ISP doesn't let inbound traffic reach it. CGNAT, no IPv6 delegation, no port forwarding. The Pi sits on your home LAN doing absolutely nothing visible to the outside world.
This guide gives the Pi a real public IPv6 — a dedicated one, not a Cloudflare proxy URL — and walks through three real applications: Pi-hole DNS, Jellyfin, Mosquitto MQTT.
Prerequisites
- Raspberry Pi running Raspberry Pi OS or any aarch64 / armv7 Linux.
- Working internet on the Pi (it just needs outbound UDP/443 to the wayangi hub).
- 5 minutes.
You don't need: a static IP, router port-forwarding, IPv6 from your ISP, a Cloudflare account, or any specific Linux distro.
Step 1: install wayangi
On the Pi:
curl -fsSL https://wayangi.dalang.io/install.sh | sudo sh -s -- --token=YOUR_TOKEN
Get the token from your dashboard after adding a device — free tier covers 3 mesh-only devices with no card if you just want to try. For a real public IPv6 it's $5/mo per device.
The install script does the linux-arm64 binary fetch (statically linked, so it works on Alpine / Raspbian / Ubuntu / Pi OS / etc.), SHA-verifies against the signed manifest, installs to /usr/local/bin, sets up a systemd unit, and brings up the tunnel. About 60 seconds end to end on a Pi 5.
Check it worked:
wayangi status
# agent: running (pid 1234)
# device: "raspberrypi" (id 01KS...)
# endpoint: 163.128.54.14:443
# addresses:
# - 10.66.0.5/32
# - 2001:df6:d2c0:1400:ffff::5/64
# - 2001:df6:d2c0:1400::42/128 ← this is your public IPv6
Step 2: verify reachability
From any other machine on the public internet (phone on mobile data is cleanest — bypasses your home LAN):
curl -s "https://wayangi.dalang.io/check?target=[2001:df6:d2c0:1400::42]:80"
# FAIL · couldn't reach [2001:df6:d2c0:1400::42]:80 in 18ms — connection refused
Connection refused is the right answer — the IPv6 is reachable, you just haven't started a service yet. Spin one up:
# On the Pi
sudo python3 -m http.server 80 --bind ::
Re-run the check. OK · reached [...] in 23ms. Done — your Pi is on the public internet.
Application 1: Jellyfin
sudo apt install jellyfin
# By default Jellyfin binds 0.0.0.0:8096 — fine, IPv6 inherits via dual-stack
# Or explicit IPv6: edit /etc/jellyfin/network.xml <BindAddress> to ::
sudo systemctl restart jellyfin
# Point a DNS record
# pi.example.com AAAA 2001:df6:d2c0:1400::42
# Browse https://pi.example.com:8096/
Add Caddy in front for proper TLS:
# /etc/caddy/Caddyfile
pi.example.com {
reverse_proxy localhost:8096
}
Caddy will auto-resolve AAAA, request a Let's Encrypt cert via IPv6, and front Jellyfin on HTTPS. Done.
Application 2: Pi-hole as a public DNS
Adventurous (and risky if misconfigured) — but legitimate for a personal network you want to use from your phone on mobile data:
# Install Pi-hole normally
# Edit /etc/pihole/setupVars.conf
# IPV6_ADDRESS=2001:df6:d2c0:1400::42
# DNSMASQ_LISTENING=all
sudo systemctl restart pihole-FTL
# On your phone: settings → Private DNS → pi.example.com
# (Android 9+ Private DNS works over IPv6 to the public address)
Caveat: a publicly-reachable DNS resolver can be abused for amplification attacks. Pi-hole rate-limits by default but you should also: enable Pi-hole's "DNSSEC validation", restrict its accept-from list, run unbound behind it. Not recommended unless you understand the threat model.
Application 3: MQTT for IoT
sudo apt install mosquitto
# /etc/mosquitto/conf.d/wayangi.conf
listener 8883
protocol mqtt
cafile /etc/ssl/certs/ca-certificates.crt
certfile /etc/letsencrypt/live/pi.example.com/fullchain.pem
keyfile /etc/letsencrypt/live/pi.example.com/privkey.pem
allow_anonymous false
password_file /etc/mosquitto/passwd
sudo systemctl restart mosquitto
Now ESP32s out in the world can connect to mqtts://pi.example.com:8883 directly, no third-party broker needed.
Multiple Pis sharing one prefix
If you have a Pi cluster (or just two Pis and a NAS), the cleanest model is one /124 tier = 16 dedicated IPv6 addresses, one main device that registers the tier, and the other devices joining as sub-devices. Each sub auto-claims an IP from the parent's prefix — no manual binding, no extra subscription. $25/mo for the /124 covers all 16.
Reboot, updates, and what happens if the tunnel dies
- The install script registers a systemd unit; the agent restarts on reboot automatically.
sudo wayangi updatepulls the latest signed binary (SHA-256 + ed25519 verified) and atomic-swaps. Run monthly.- If the agent dies, systemd restarts it within a second. Your public IPv6 stays assigned to your device for as long as your subscription is active — the address itself doesn't change.
- If WireGuard handshake fails (rare ISP routing issue), the agent automatically falls back to TCP/443 via WSS. Same WireGuard keys, just shipped over TLS.
Costs
- $5/mo for one Pi with one public IPv6 (
/128tier). - $25/mo for a
/124tier — 16 dedicated IPv6s, share across up to 16 Pis via sub-devices. - Free for 3 Pis on the mesh-only tier (they talk to each other but aren't reachable from outside).
- Annual cadence saves 15%.
Compare with the alternatives: a $5/mo VPS to reverse-tunnel into (manual setup, no HA), Cloudflare Tunnel (HTTPS-only on free, your DNS must be on CF), ngrok ($8/mo Personal + bandwidth caps), Tailscale Funnel (HTTPS-only + 1 GB/mo cap on free).
Wrap-up
A Raspberry Pi with a public IPv6 turns into a useful piece of infrastructure rather than a fancy paperweight. Jellyfin streams to your phone over mobile data, ESP32s out in the world hit your MQTT broker, friends ssh in over IPv6, you don't pay for cloud hosting for any of it.
If your ISP gave you working IPv6, you can do this for free — just open your router's IPv6 firewall and use the SLAAC address. If it didn't (the common case in CGNAT'd Indonesia, mobile-data US, fiber-CGNAT Europe), try wayangi free first and pick a paid tier when you're ready.