How to Expose Your Local Server to the Internet (Without Port Forwarding)
Source: Dev.to
TL;DR: Use Cloudflare Tunnel to make your home server accessible from anywhere. Free, secure, no router configuration needed.
I recently deployed a web app running on my laptop to a real domain—no cloud hosting, no VPS, no monthly bills. Just my laptop, a domain, and Cloudflare Tunnel. Here’s exactly how I did it.
Why Use a Tunnel?
- No access to the router’s admin panel
- Dynamic IP address
- Port forwarding isn’t an option
- Opening ports 80/443 directly would not work
Cloudflare Tunnel (formerly Argo Tunnel) creates an outbound connection from your server to Cloudflare’s edge, so no incoming ports are required.
Internet → Cloudflare (SSL) → Tunnel → Your laptop
- Free, handles SSL automatically
- Works with any domain registrar
- Works on Linux, macOS, or Windows
Prerequisites
| Item | Details |
|---|---|
| Domain name | Any registrar (e.g., Porkbun) |
| Cloudflare account | Free tier is sufficient |
| Machine running app | Linux/macOS/Windows |
| Time | ~10 minutes |
1. Point Your Domain to Cloudflare
- Go to dash.cloudflare.com → Add a site.
- Enter your domain (e.g.,
myapp.com). - Choose the Free plan.
- Cloudflare will show two nameservers (e.g.,
carter.ns.cloudflare.com,vita.ns.cloudflare.com). - In your registrar’s control panel, replace the existing nameservers with the ones Cloudflare provided.
- Wait 5–30 minutes for DNS propagation.
2. Create a Tunnel in Cloudflare Zero Trust
- In the Cloudflare dashboard, open Zero Trust (left sidebar).
- Navigate to Networks → Tunnels.
- Click Create a tunnel, give it a name (e.g.,
my-server). - Cloudflare will display an installation command that includes a one‑time token.
3. Install the cloudflared Daemon
Ubuntu / Debian
curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared.deb
macOS
brew install cloudflared
Windows
Download the latest release from the GitHub releases page and install it manually.
4. Register the Tunnel as a Service
Run the command you received in step 2, substituting the token:
sudo cloudflared service install <TOKEN>
This creates a system service that starts automatically on boot.
Verify it’s running:
sudo systemctl status cloudflared
5. Add a Public Hostname
- In the Cloudflare dashboard, go to Tunnels →
→ Configure . - Click Public Hostname → Add a public hostname.
- Fill in the fields:
| Field | Value |
|---|---|
| Subdomain | (leave empty or use www) |
| Domain | Select your domain (myapp.com) |
| Service Type | HTTP |
| URL | localhost:80 (or whatever port your app uses) |
- Save.
If you see “DNS record already exists”, delete the conflicting A record under DNS → Records first.
Now open https://myapp.com in a browser – you should see your local app served over HTTPS.
Test from the command line
curl https://myapp.com
6. Route Multiple Services
You can expose several local services by adding more public hostnames:
| Public Hostname | Local Service |
|---|---|
myapp.com | localhost:3000 (frontend) |
api.myapp.com | localhost:8080 (API) |
Just repeat the “Add a public hostname” steps for each entry.
7. Example Nginx‑Based Setup
textstack.app → localhost:80 → nginx → React frontend
textstack.app/api → localhost:80 → nginx → Docker API (port 8080)
textstack.dev → localhost:80 → nginx → Same app, different site
All running on a laptop in the living room.
8. Local Firewall (Optional but Recommended)
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # Tunnel (local only)
sudo ufw enable
- Do not expose admin panels to the internet; keep them bound to
localhostonly.
9. Security & Access Controls
- Cloudflare automatically provides SSL – no need for Let’s Encrypt.
- Use Access Policies (Zero Trust) to require authentication for sensitive routes.
10. Troubleshooting
| Symptom | Checks |
|---|---|
| Site not loading | sudo systemctl status cloudflared |
| App not responding | curl localhost:80 |
| DNS not resolved | dig myapp.com |
| “Address Not Found” on mobile | Toggle airplane mode, switch DNS to 1.1.1.1, wait 15–30 min |
| 502 Bad Gateway | Verify tunnel is running and the local service is listening |
11. When Not to Use Cloudflare Tunnel
- High‑traffic production apps (home internet bandwidth limits)
- Apps requiring 99.99 % uptime (your laptop may crash)
- Sensitive data without proper security hardening
For serious production workloads, consider a proper cloud provider.
12. Ideal Use Cases
- Side projects
- Development / staging environments
- Self‑hosted apps (e.g., home automation dashboards)
- Personal APIs
13. Wrap‑Up
It took me about 15 minutes to go from “app running locally” to “app accessible worldwide with HTTPS.” No cloud bills, no DevOps complexity—just your code on your hardware, reachable from anywhere.
Have questions? Drop a comment below or find me on Twitter/X.
Building something cool with this setup? I’d love to hear about it!