I got tired of configuring Cloudflare Zero Trust manually, so I built a 15s CLI wrapper.
Every time I wanted to expose a new local service (like Grafana or a dev API) securely, the routine was always the same:
Open Cloudflare Dashboard.
Create a new Tunnel.
Configure Ingress rules.
Add a DNS CNAME record.
Switch to the Zero Trust panel.
Create an Access Application.
Set up an Access Policy to restrict access to my email.ef description of what you built.
How it works
Now, when I need to share or expose a local service, I just run:
zt up grafana 3000
In about 15 seconds, it automatically handles the whole chain:
Creates the Cloudflare Tunnel.
Sets up DNS and Ingress.
Locks it behind Cloudflare Access (asks for email OTP by default).
Fires up cloudflared in the background and saves the state locally.
If I need it to be completely public (like an webhook endpoint), I just pass a flag: zt up api 8080 --public. If I want to share it with specific colleagues: --allow mail@example.com
When I'm done, zt down grafana wipes everything clean and stops the process.
The Stack
It’s a single binary written in Go, using the official Cloudflare API package. Configuration and state are kept locally in ~/.zt-config.json and ~/.zt-state.json (secured with 0600 permissions).
I’ve been using it daily in my home lab and dev environment, and it has saved me hours of clicking through web UIs.
The project is completely open-source (MIT). If you're managing self-hosted apps or often need to expose local ports securely, feel free to check it out, open an issue, or drop a star!
Andrew
Please feel free to give a feedback. Leave a comments, make an issue on gh or just text me email. Cheers!