Expose a service#

Every instance publishes exactly one inbound port: SSH on 22. Anything else you start — a dashboard on 8080, vLLM on 8000, JupyterLab on 8888, a Gradio demo on 7860 — answers curl inside the instance and is a dead end from your laptop. Each method below fixes that the same way: a program inside the instance dials outward to Cloudflare or Tailscale, and they hand you a web address that forwards to your service. No inbound port is ever opened.

Outbound access is open, so all of this works without any change on our side. The examples use port 8080; substitute yours. Check the service answers inside the instance first:

curl -s http://localhost:8080 | head

If that prints nothing, fix the service before tunnelling — a tunnel forwards it exactly as it behaves inside the instance.

For copy-and-paste steps with a check after each one, follow the guide Expose a port over HTTP.

Warning

There is no port to open

Enverge does not open inbound ports on request, and there is no dashboard setting for it. An open port puts the service on the public internet, where anyone can find and probe it — including people who never got the address from you. The tunnels below stay scoped to the one service and audience you choose, and you can revoke them yourself at any time.

Just you: SSH port forwarding#

You already have what you need. Run this on your own machine, not in the instance, and leave the window open:

ssh -L 8080:localhost:8080 <user>@<instance-hostname>

Visit http://localhost:8080 in your browser. Closing the SSH window ends the access — no account, no public address, nothing installed to remove later. If you only check on a training run a few times a day, stop here.

Share it today: Cloudflare Quick Tunnel#

A throwaway public address with no Cloudflare account and no domain. Install cloudflared in the instance (downloads page), then run it against your service:

sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg \
  | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' \
  | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt-get update && sudo apt-get install cloudflared

cloudflared tunnel --url http://localhost:8080

It prints an address ending in trycloudflare.com. Check it from your phone with Wi-Fi off, or ask the person you are sharing with — one look from outside beats testing on the same network. Then three things to know before you send it on:

  • The link is the key. Anyone who receives it gets in. To name your visitors instead, add --allowed-mail alice@example.com, which emails each listed person a one-time PIN. It works for people in a browser; scripts cannot type a PIN.

  • No streaming. Quick Tunnels do not carry Server-Sent Events, which most chat and generation interfaces use to show output as it arrives (Cloudflare’s limits). The page can load while the reply stalls forever. Test a real reply early.

  • It will not last. No uptime promise, 200 requests in flight at once, and a new address on every run.

Off-switch: Ctrl+C. Closing the terminal also ends the link, so keep the window open for the length of the demo.

A named group, all week: Cloudflare Tunnel with Access#

A stable address on your own domain, with a real check on who is let in. Needs a free Cloudflare account and a domain whose DNS Cloudflare manages. Do these in order (Cloudflare’s walkthrough):

  • Create the connection. In the Cloudflare dashboard, Networking → Tunnels → Create a tunnel. Paste the install command it gives you into the instance. That runs cloudflared as a background service dialling outward; nothing opens inward. Restrictive networks must allow outbound traffic on port 7844.

  • Decide who may enter, before the address works. Under Zero Trust → Access controls → Applications, add a self-hosted application for the address you plan to use, such as app.example.com, with an Allow policy naming your visitors’ emails or sign-in provider. This step comes first on purpose: a published address without it is open to anyone.

  • Publish the service. Back in the tunnel, Add route → Published application — subdomain app, your domain, service address http://localhost:8080.

Verify from a private browser window: you should be asked to prove you are on the list before the service appears. Then try an account that is not on the list and confirm it is turned away. Widening or revoking access afterwards happens in the Access policy, without touching the instance. Off-switch: delete the published route, then reload the address and watch it fail — a route left in place keeps the address live.

Note

A new instance needs the tunnel installed again

The address and its Access policy live in your Cloudflare account, so they outlast any one instance. The cloudflared service does not: it is installed inside the instance, so launching a fresh one means running the install command again and pointing the route at it.

No domain? Tailscale Funnel#

Tailscale is a private network of your own devices; Funnel lets the whole internet reach one service on one device, at an address on Tailscale’s domain. In the instance:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale funnel --bg 8080

The last command prints an address like https://<machine>.<tailnet>.ts.net. The --bg flag keeps Funnel running after you log out. Check it from a phone with Wi-Fi off, or any device outside your tailnet.

Note

Three things must be switched on first

Funnel needs MagicDNS and HTTPS certificates enabled for your tailnet, and this device given permission to use Funnel. The first run walks you through all three — those prompts are the setup, not an error.

Warning

Funnel has no sign-in of its own

Anyone with the address reaches your service directly, and the visitor’s identity is never passed to it. A Gradio demo with no password set becomes someone else’s free GPU. Give the service its own password, or use Cloudflare Access above, which checks names before requests reach the instance.

Funnel is still labelled beta, and its bandwidth limits are set by Tailscale and cannot be changed — a web interface fits inside them, serving large files to a crowd does not. The address must live under ts.net. Your instance is a container, and Tailscale normally wants a networking device that containers often lack: check with ls -l /dev/net/tun, and if it is missing, fall back to userspace networking (--tun=userspace-networking). For your own devices only, the private sibling tailscale serve --bg 8080 passes the visitor’s identity through to the service. Off-switch: tailscale funnel reset, then reload the address and watch it fail.

Before you share the address#

A tunnel widens the audience for your service; it does not add permissions to it. Whatever the service already lets a visitor do, it will let a stranger do.

  • Set the service’s own password anyway. Links get forwarded, and its own sign-in is the layer that still works then.

  • Leave the service bound to localhost so the tunnel is the only way in.

  • Treat an ungated address as a password: keep it out of public posts and documents.

  • A tunnel hides where the instance is, not what the service does. Visitors connect to Cloudflare’s or Tailscale’s address, but the service itself is fully visible to anyone who reaches it.

  • Mind what a public service spends. A stranger with the address can put your GPU to work on your bill, and capacity is finite — see our serving benchmark on one RTX Pro 6000.

  • Use the off-switch the same day, then reload the address and watch it fail.

Choosing#

Your situation

Use

What you give up

Only me, now and then

SSH forwarding (ssh -L)

Ends when the SSH window closes

Only my devices, always available

Tailscale Serve

Visitors must be on your tailnet

Someone else, this afternoon

Cloudflare Quick Tunnel

Throwaway address, no streaming, and the link itself is the key unless you name emails

A named group, all week

Cloudflare Tunnel + Access

Needs your domain on Cloudflare

The public, no domain to offer

Tailscale Funnel

Beta, bandwidth limits, and your service must check who is calling

Most people land on the first row. When the audience grows, move to the matching row rather than forwarding a temporary link again.

Note

Tunnel to localhost, in the same instance

An instance reaches the internet but not its neighbours: other instances, the host, and the host’s local network are blocked by design. Point the tunnel at a port on localhost inside the same instance.

For the longer walkthrough, with the reasoning behind each choice, see Expose a web app on an SSH-only instance.