# https://tunnels.io/learn/how-to-expose-localhost

[Home](https://tunnels.io/) / [Learn](https://tunnels.io/learn) / How to expose localhost to the internet

How to

# How do you expose localhost to the internet?

Run a tunnel client on the machine hosting the server. It opens an outbound connection to a public relay, which accepts internet traffic on a public HTTPS URL and forwards each request to your local port. The alternatives are SSH remote port forwarding, forwarding a port on your router, or deploying the application to a server.

## Why can nobody outside your network reach localhost?

Two separate things are in the way. `localhost`` resolves to a loopback address, `127.0.0.1`` or `::1``, and packets sent there never leave the machine, so a server bound only to loopback can be reached by processes on that host and nothing else. Even after you bind to `0.0.0.0`` and become visible on your own LAN, your router is doing NAT: your machine holds a private address that no host on the internet can route a packet to, and there is no inbound mapping pointing at it. Every option below solves one or both of those problems.

## Option 1: how does a tunnel service expose localhost?

A small client runs next to your server and dials out to a relay that already has a public address. Because your machine opened the connection, NAT and the outbound firewall allow it, and the relay can push inbound requests back down that same connection to your local port. The relay owns the hostname and the TLS certificate, so what you hand to a colleague or a webhook provider is a working HTTPS URL rather than an IP and a port number. Nothing changes on your router, there is no server to rent, and it works from a hotel network or behind carrier-grade NAT.

## Option 2: can you do it with SSH remote port forwarding?

Yes, if you already have a server with a public IP address and a shell account on it. `ssh -R 8080:localhost:3000 user@server`` makes the server listen on port 8080 and pushes every connection it accepts back to port 3000 on your laptop, using the session you dialled out. Two things catch people: sshd binds remote-forwarded ports to loopback until an administrator enables `GatewayPorts``, and what you publish is a bare HTTP port with no certificate, so a DNS record and a TLS-terminating reverse proxy are still yours to arrange. Plain `ssh`` also does not come back after a sleep or a network change, which is why people wrap it in autossh.

## Option 3: should you forward a port on your router?

Only for something permanent on a connection you actually control. You give the machine a fixed LAN address, map an external port to it in the router's admin page, and open the host firewall for that port. It fails in three ordinary ways: most residential connections get a dynamic address, so the mapping needs dynamic DNS to stay findable; many ISPs now put customers behind carrier-grade NAT, where there is no public address to forward at all; and a successful mapping publishes a port on your home connection with no TLS until you obtain and renew a certificate yourself.

## Option 4: is it simpler to just deploy it?

If the thing has to stay reachable when your laptop is closed, yes. A small VM or a platform-as-a-service gives you an address that does not depend on your machine being awake, along with certificates, logs and restarts you did not have to write. The cost is the feedback loop: every change needs a commit, a build and a deploy before anyone can see it, which is usually the exact thing you were trying to avoid. Deploy what is finished, tunnel the code you are editing right now.

## Which option should you pick?

Decide on two questions: how long does it need to live, and does the caller insist on HTTPS. Anything temporary that a browser, a phone or a webhook provider has to reach is a tunnel. Anything permanent and public should be deployed properly.

| Approach | Setup | HTTPS included | Works behind CGNAT | Best for |
| --- | --- | --- | --- | --- |
| Tunnel service | One command | Yes, terminated at the relay | Yes | Webhooks, client demos, testing a phone against local code |
| SSH remote forwarding | Minutes, if you already run a server | No, add your own reverse proxy | Yes, the client dials out | One-off access when the box and the shell account already exist |
| Router port forwarding | Router, DHCP reservation and firewall | No, obtain and renew a certificate | No | A permanent service on a connection you own |
| Deploying it | Build and pipeline | Yes, from the platform | Yes | Staging and production, anything that outlives your session |

## What are the security risks of exposing localhost?

A new public URL or a newly opened port gets scanned within minutes by bots that were never looking for you specifically. Development servers are the worst possible thing to expose, because debug consoles, stack traces that print environment variables, seeded admin accounts, permissive CORS and directory listings are all normal in local development and all dangerous in public. Publish only the one port you mean to publish, never the database or the SSH port, put authentication in front of anything that writes, and shut the tunnel down when you are finished with it. Router port forwarding carries the extra risk that the exposed host sits on your home LAN next to everything else you own.

## How do you expose localhost with tunnels.io?

Install the client, point it at the port, and share the URL it prints. `tunnels http 3000`` gives you a public HTTPS URL that forwards to port 3000 with a valid certificate, and no plan puts an interstitial or warning page in front of your app, including the free one. The free Basic plan is $0 for 4 GB a month, one tunnel and a random URL, at a sustained rate of 1,024 requests per second, and it carries HTTP and HTTPS. Pro at $4 a month, or $40 a year, adds 128 GB, five tunnels, up to three reserved subdomains that survive a restart, 8,192 requests per second, and TCP tunnels for things like a Postgres port. The engine carries HTTP, HTTPS and TCP; it does not carry UDP. If you are weighing this against other hosted tunnels, the [comparison pages](https://tunnels.io/compare) carry the sourced numbers.

[Get started free →](https://tunnels.io/get-started) [Read the docs](https://tunnels.io/docs)

## Related reading

[Database access Postgres, MySQL and Redis over a raw TCP tunnel, and the security posture that needs.](https://tunnels.io/use-cases/database) [What is a reverse tunnel? The mechanism behind option one, and why an outbound connection is enough to receive inbound traffic.](https://tunnels.io/learn/what-is-a-reverse-tunnel) [What is SSH tunneling? Local, remote and dynamic forwarding, the flags for each, and where GatewayPorts trips you up.](https://tunnels.io/learn/what-is-ssh-tunneling) [localhost vs 127.0.0.1 Why the name and the address are not interchangeable, and what your server is really bound to.](https://tunnels.io/learn/localhost-vs-127-0-0-1) [All Learn articles Every concept and how-to in the series, in one place.](https://tunnels.io/learn)

## Frequently asked questions

### Can I expose localhost without touching my router?

Yes. A tunnel client and SSH remote forwarding both work by dialling out from your machine, so the inbound traffic rides a connection your network already permitted. Nothing has to be mapped on the router, and both keep working behind carrier-grade NAT, where port forwarding is not possible at all.

### Is it safe to expose localhost to the internet?

It is safe enough for short, deliberate use and risky as a habit. Anything you publish will be scanned by automated traffic almost immediately, and a development server usually ships with debug output, seeded accounts and relaxed CORS that are fine locally and dangerous in public. Expose only the port you intend to expose, require authentication for anything that writes data, and close the tunnel when you are done.

### Can I get an HTTPS URL for a local server?

Yes, and it is the usual reason people give up on the do-it-yourself routes. A tunnel service terminates TLS on a hostname it already owns, so the certificate is valid without you generating anything. SSH remote forwarding and router port forwarding both publish a plain TCP port, so getting to HTTPS means adding DNS, a certificate and a reverse proxy yourself.

### Why does another device say connection refused?

Most often the server is bound to `127.0.0.1``, which only accepts connections from the same machine; binding to `0.0.0.0`` makes it answer on your LAN address as well. If it still refuses, check the host firewall, and confirm the two devices are on the same network. A tunnel sidesteps all of this because the client connects to your server from the same machine.

### Can I expose a database or another non-HTTP service?

Yes, over a TCP tunnel, which is a paid capability on tunnels.io rather than part of the free plan. That covers anything speaking TCP, including Postgres, MySQL, Redis and SSH itself. It does not cover UDP, so DNS, QUIC and game protocols that need datagrams are out of scope, and exposing a database to the internet deserves a strong password and a short lifetime.

## One command, one public URL.

The free plan needs no credit card and no router changes. Point the client at your port and send the link.

[Get started →](https://tunnels.io/get-started) [Back to Learn](https://tunnels.io/learn)
