Blog / Tunneling, Development, Cloudflare
Tunneling · Development · Cloudflare

Cloudflare Tunnel als tunneling-alternatief voor lokale development zonder poortforwarding

Pim van der Molen ·

Soms werk ik aan projecten waarbij een externe partij mijn lokale omgeving moet bereiken. Denk aan een betaalprovider die een webhook naar mijn machine stuurt, of een klant die live wil meekijken terwijl ik iets instel. Expose.dev en ngrok zijn dan de voor de hand liggende keuzes, maar ik loop daar steeds tegen hetzelfde punt aan: willekeurige subdomeinen die veranderen zodra je de tunnel herstart, of een betaalmuur voor iets dat eigenlijk basisinfrastructuur zou moeten zijn. Cloudflare Tunnel biedt een andere aanpak, en na het configureren ervan ben ik er eigenlijk niet meer van losgeraakt.

Wat Cloudflare Tunnel anders doet

Cloudflare Tunnel werkt via een daemon genaamd cloudflared die een uitgaande verbinding opent naar het Cloudflare-netwerk. Er hoeft geen enkel inkomend poortnummer open te staan op jouw router of firewall, want het verkeer loopt altijd van binnenuit naar buiten. Dat is een fundamenteel ander model dan tools die een publiek IP van een externe server koppelen aan jouw lokale poort.

Omdat je een eigen domein koppelt, krijg je een vast subdomein dat niet verandert bij het herstarten van de daemon. Dit maakt het heel bruikbaar voor situaties waarbij je een webhook-URL bij een externe dienst configureert, want je hoeft die URL niet bij te werken zodra je opnieuw opstart. Voor platforms als Stripe, Mollie of GitHub Actions is dat een groot praktisch voordeel.

Het enige dat je nodig hebt is een domein dat via Cloudflare's nameservers loopt. Als je dat al doet voor productiedomeinen, kost het instellen van een tunnel vrijwel niets extra. Heb je dat nog niet, dan is het wel een extra stap. Voor mij was dat geen drempel, want het meeste DNS-beheer gaat al via Cloudflare.

Installeren en configureren op macOS

De installatie van cloudflared op macOS gaat via Homebrew.

brew install cloudflared

Daarna log je in met je Cloudflare-account, zodat de tool weet welk domein het mag aansturen.

cloudflared tunnel login

Dit opent een browser waar je een domein selecteert en autoriseert. Na het inloggen maak je een tunnel aan met een naam naar keuze.

cloudflared tunnel create mijn-dev-tunnel

Dit genereert een tunnel-ID en een credentials-bestand in ~/.cloudflared/. Noteer het tunnel-ID, want je hebt het straks nodig in de configuratie. Daarna stel je in welk subdomein naar welke lokale poort moet routeren. Dit doe je in een YAML-bestand.

tunnel: jouw-tunnel-id-hier
credentials-file: /Users/pim/.cloudflared/jouw-tunnel-id-hier.json

ingress:
  - hostname: dev.jouwdomein.nl
    service: http://localhost:8000
  - service: http_status:404

De laatste regel in het ingress-blok is verplicht: Cloudflare wil altijd een catch-all route hebben voor verkeer dat niet overeenkomt met een hostname. Sla dit op als ~/.cloudflared/config.yml. Vervolgens koppel je het subdomein aan de tunnel, zodat de DNS-record automatisch wordt aangemaakt in Cloudflare.

cloudflared tunnel route dns mijn-dev-tunnel dev.jouwdomein.nl

Nu kan je de tunnel starten met het commando hieronder, en je lokale server op poort 8000 is bereikbaar via https://dev.jouwdomein.nl.

cloudflared tunnel run mijn-dev-tunnel

De tunnel als achtergrondservice draaien

Handmatig de tunnel starten en stoppen is prima voor een incidentele sessie, maar ik wil dat hij vanzelf meestuurt zodra mijn machine opstart. Op macOS regel ik dat als een launchd-service.

sudo cloudflared service install

Dit registreert de tunnel als een systeemservice op basis van je bestaande config.yml. Na een reboot is de tunnel beschikbaar zonder dat je eraan hoeft te denken. Je kunt de status controleren via sudo launchctl list | grep cloudflared of door simpelweg je subdomein te bezoeken.

Op Linux werkt het via systemd, en het commando is identiek. De service-definitie wordt dan geplaatst in /etc/systemd/system/ en je kan hem beheren met de gebruikelijke systemctl-commando's.

sudo systemctl status cloudflared

Een voordeel dat ik hierbij merk: omdat de tunnel zonder handmatige actie actief is, kan ik een webhook in een externe dienst eenmalig instellen en hoef ik die URL maanden later niet opnieuw te configureren. Voor projecten waarbij ik een webhook van een CRM of betaalplatform debug, scheelt dit veel heen-en-weer.

Meerdere services op één tunnel routeren

Eén tunnel kan meerdere hostnames afhandelen. Dit is handig als je gelijktijdig aan een frontend en een API werkt die allebei bereikbaar moeten zijn.

tunnel: jouw-tunnel-id-hier
credentials-file: /Users/pim/.cloudflared/jouw-tunnel-id-hier.json

ingress:
  - hostname: api.jouwdomein.nl
    service: http://localhost:8000
  - hostname: app.jouwdomein.nl
    service: http://localhost:3000
  - service: http_status:404

Voor elk nieuw hostname voeg je een aparte DNS-route toe via cloudflared tunnel route dns. De tunnel zelf hoeft niet opnieuw te worden aangemaakt. Dit werkt goed als je een Laravel API lokaal op poort 8000 draait en een Node.js frontend op poort 3000, want beide zijn dan bereikbaar op hun eigen subdomein via dezelfde actieve tunnel.

Het is wel goed om te weten dat Cloudflare Tunnel HTTPS afhandelt op de edge. Het verkeer tussen de cloudflared-daemon en jouw lokale service loopt onversleuteld over localhost, maar wat de buitenwereld ziet is altijd HTTPS. Je hoeft dus geen lokaal SSL-certificaat te configureren voor de tunnel zelf. Dat is anders dan bij expose.dev of Laravel Herd, waar je lokale HTTPS apart instelt.

Wanneer ik toch voor expose.dev kies

Cloudflare Tunnel heeft één praktisch nadeel: je hebt er een eigen domein voor nodig dat via Cloudflare's nameservers loopt. Bij korte demo's voor klanten die ik snel wil opzetten zonder iets te configureren, pak ik soms nog expose.dev. Daar start ik een tunnel op met één commando en krijg ik direct een tijdelijk publiek adres.

expose share http://localhost:8000

De drempel is nul, want er is geen account of DNS-configuratie nodig voor de basisversie. Maar zodra ik langere tijd met een externe dienst werk, of een stabiele URL nodig heb die ik ook morgen nog kan bezoeken, ga ik terug naar Cloudflare Tunnel.

De keuze hangt dus samen met de levensduur van wat je bouwt. Voor een snelle test van vijf minuten is expose.dev of zelfs npx localtunnel sneller. Voor structureel lokale development waarbij externe diensten jou moeten kunnen bereiken, betaalt de eenmalige configuratie van Cloudflare Tunnel zichzelf terug binnen de eerste dag.

Wat ik zelf doe is de tunnel permanent draaien op mijn werkcomputer en alleen de ingress-regels aanpassen wanneer een project een andere poort nodig heeft. Dat kost letterlijk dertig seconden: de YAML aanpassen, cloudflared herstarten, klaar. De stabiliteit en het feit dat er niks achter een betaalmuur zit, maakt het voor mij de standaardkeuze geworden.

Veelgestelde vragen

Cloudflare Tunnel en ngrok bieden beide een manier om lokale servers publiek toegankelijk te maken zonder poortforwarding, maar Cloudflare Tunnel is gratis te gebruiken via een Cloudflare-account en integreert naadloos met je eigen domeinnaam. Ngrok is eenvoudiger op te zetten maar heeft beperkingen in de gratis versie, zoals willekeurige subdomeinen en een limiet op verbindingen.

Ja, Cloudflare Tunnel is over het algemeen veilig omdat het verkeer via het versleutelde netwerk van Cloudflare loopt en je geen inkomende poorten hoeft te openen op je router of firewall. Het is echter belangrijk om toegang te beperken tijdens development, zodat gevoelige data of testomgevingen niet onbedoeld publiek toegankelijk zijn.

Nee, Cloudflare Tunnel is beschikbaar op het gratis Cloudflare-abonnement via cloudflared, de officiële CLI-tool. Je hebt wel een gratis Cloudflare-account nodig en een domeinnaam die aan Cloudflare is gekoppeld om de tunnel volledig te configureren.

Ja, Cloudflare Tunnel is zeer geschikt voor het lokaal testen van webhooks, omdat externe diensten via een publieke URL verzoeken kunnen sturen naar je lokale ontwikkelomgeving. Dit maakt het een handig alternatief voor tools zoals ngrok of localtunnel bij het debuggen van webhook-integraties.

TAGS
Tunneling · Development · Cloudflare