How to expose your local LLM endpoint so you can use it anywhere
If you're running an LLM locally — with Ollama, LM Studio, llama.cpp, vLLM, or a custom gateway — it usually listens on 127.0.0.1 (localhost). That address only works on the machine running the model. The moment you want to reach it from anywhere else — another computer, your phone, a smartwatch, or a teammate across the internet — you need to give the model an address that other device can actually resolve.
There are several ways to do that, and the right one depends on where you'll call the model from and how private you need it to be. This guide covers all of them — from the simplest same-Wi-Fi setup to permanent public URLs and private VPNs.
Everything below applies to any OpenAI-compatible client. If you're doing this to use your own model with Hopper — the AI assistant for your watch and phone — the steps are exactly the same; once your endpoint is reachable, our companion guide covers plugging it into Hopper.
Which method should you use?
| Method | Reachable from | Setup effort | Persistent URL | Best for |
|---|---|---|---|---|
| LAN address | Same Wi-Fi only | Very low | Yes (local IP) | Using it at home |
| Cloudflare Quick Tunnel | Anywhere | Low | No (changes each restart) | Quick tests |
| Named Cloudflare Tunnel | Anywhere | Medium | Yes (your domain) | Permanent public setup |
| ngrok | Anywhere | Low | Paid for a fixed domain | Fast public sharing |
| Tailscale | Any of your devices | Low–medium | Yes (private) | Most private, no public exposure |
Rule of thumb: use the LAN address if you only need it at home, Tailscale if you want it everywhere with the least security risk, and a Cloudflare Tunnel if you want a plain public HTTPS URL.
First: confirm your endpoint and port
Most local runtimes already expose an OpenAI-compatible API. Note the port yours listens on — for example, Ollama defaults to 11434. You can check it from your machine:
curl http://localhost:11434/v1/models
If that returns your list of models, your endpoint works locally. Now let's make it reachable.
Throughout this guide we use port 11434 (Ollama's default) — swap in whatever port your runtime uses.
Bind your server to all interfaces first
Almost every method below (except a plain localhost tunnel) needs your server reachable beyond 127.0.0.1. By default many runtimes listen only on localhost, which blocks other devices. Bind to 0.0.0.0 instead.
For Ollama, set the host before starting it:
# macOS / Linux
OLLAMA_HOST=0.0.0.0 ollama serve
On Windows, set OLLAMA_HOST to 0.0.0.0 in your environment variables and restart Ollama. Other runtimes (LM Studio, llama.cpp, vLLM) have a similar "host" or "listen address" setting — set it to 0.0.0.0.
Method 1: Same network (LAN address)
If the device you'll call the model from is on the same Wi-Fi as the machine running it, you can skip tunnels entirely.
1. Find your machine's local IP
# macOS / Linux
ipconfig getifaddr en0 # or: hostname -I
# Windows
ipconfig # look for "IPv4 Address"
You'll get something like 192.168.1.50.
2. Allow the port through your firewall
Make sure your OS firewall permits inbound connections on your model's port (e.g. 11434).
Your endpoint is now http://192.168.1.50:11434/v1. That's your endpoint URL — enter it into whatever client you're using (Hopper included). Note that it only works while that device is on the same Wi-Fi network — leave the house and it stops resolving.
Method 2: Cloudflare Quick Tunnel (temporary public URL)
To use your model on the go — cellular, a friend's Wi-Fi, anywhere — put a tunnel in front of it. A Cloudflare Quick Tunnel is a free, fast way to get a public HTTPS URL with no account required.
1. Install Cloudflared
On macOS (using Homebrew):
brew install cloudflared
On Windows, download it from: https://github.com/cloudflare/cloudflared/releases
2. Start the tunnel
Point it at whatever port your model is served on:
cloudflared tunnel --url http://localhost:11434
3. Copy your public URL
Cloudflare will print something like:
Your quick tunnel URL is: https://xyz-abc-123.trycloudflare.com
Your endpoint is now https://xyz-abc-123.trycloudflare.com/v1 — reachable from anywhere. Note that this URL changes every time you restart the tunnel, and restarting your machine shuts it down.
Method 3: Named Cloudflare Tunnel (permanent URL on your domain)
If you own a domain and want a stable address that survives restarts, set up a named tunnel. This needs a free Cloudflare account with your domain added.
1. Authenticate and create the tunnel
cloudflared tunnel login
cloudflared tunnel create hopper-llm
2. Route a subdomain to it
cloudflared tunnel route dns hopper-llm llm.yourdomain.com
3. Point the tunnel at your local server
Create a config file (~/.cloudflared/config.yml). Use the absolute path to the credentials file that cloudflared tunnel create printed when it ran — cloudflared doesn't reliably expand ~ here, so don't use a shortcut path:
tunnel: hopper-llm
# macOS/Linux example — Windows: C:\Users\you\.cloudflared\<tunnel-id>.json
credentials-file: /Users/you/.cloudflared/<tunnel-id>.json
ingress:
- hostname: llm.yourdomain.com
service: http://localhost:11434
- service: http_status:404
4. Run it
cloudflared tunnel run hopper-llm
Your endpoint is now https://llm.yourdomain.com/v1 — permanent and reachable from anywhere. For an always-on setup, install it as a service with cloudflared service install. See Cloudflare's named tunnel docs for details.
Method 4: ngrok
ngrok is another popular tunneling tool. Every account — including the free tier — now gets one persistent domain assigned to it, so the URL stays the same between runs. A paid plan lets you pick a custom domain name of your own.
1. Install and add your token
Download from ngrok.com/download, then:
ngrok config add-authtoken <your-token>
2. Start the tunnel
ngrok http 11434
ngrok prints a forwarding URL like https://your-name.ngrok-free.app — the same one each time you run it. Your endpoint is that URL plus /v1.
To use a custom domain name of your own (paid), pass it explicitly:
ngrok http --url=your-name.ngrok.app 11434
Method 5: Tailscale (private, no public exposure)
If you'd rather not put your model on the public internet at all, Tailscale creates a private mesh network between your own devices. They reach your machine directly over an encrypted connection, with nothing exposed publicly.
1. Install Tailscale on both devices
Install it on the machine running your model and on the device you'll call it from, then sign in with the same account on both. (For Hopper on a watch, install Tailscale on your phone — the watch inherits the connection through it.)
2. Find your machine's Tailscale IP
tailscale ip -4
You'll get an address in the 100.x.y.z range.
Your endpoint is now http://100.x.y.z:11434/v1 — reachable from any of your devices, anywhere, without opening a public URL. This is the most private option; the trade-off is that every device that needs access must be on your tailnet.
Security tips
- Always add a token if you go public. Any method that produces a public URL (Cloudflare, ngrok) is reachable by anyone who has the address. If your server or a gateway in front of it supports an API key, set one — you'll enter it in your client's API key field (Hopper included).
- Prefer private methods when you can. LAN and Tailscale never expose your model to the open internet, so they carry the least risk.
- Use HTTPS end to end. Cloudflare, ngrok, and Tailscale handle encryption for you.
- Quick tunnels are temporary. A
trycloudflare.comor free ngrok URL changes on every restart — fine for testing, but use a named tunnel, reserved domain, or Tailscale for anything you'll keep.
Once your endpoint is reachable, point any OpenAI-compatible client at it and you're done. Using Hopper? Here's how to connect it on your watch.
Published in Tutorial
By Hopper Team