Tutorials
Expose a local web app
Publish a locally running web app or API over HTTPS with a proxy-mode Kepeink tunnel that reverse-proxies your local HTTP target.
Expose a local web app
Use a proxy tunnel to put a web app or API that is already running on your machine online. In proxy mode the agent reverse-proxies a local HTTP(S) target you name and streams responses back to visitors.
1. Have your app running locally
Start the app you want to expose and note the address it listens on. For example a dev server on port 3000:
npm run dev
# → listening on http://localhost:3000
Any local HTTP(S) address works, including a service on your LAN such as http://192.168.1.5:8080.
2. Create a proxy tunnel
In the dashboard, create a tunnel with:
- Backend mode:
proxy - Target: the address from step 1, for example
http://localhost:3000
Kepeink assigns the tunnel a public hostname and gives you an agent token.
3. Run the agent
Install the agent with the tunnel's token (see Install the Agent):
curl -fsSL https://cdn.kepeink.hu/install.sh | sudo sh -s -- --token=kpt_xxxxxxxx
Already running your app in Docker? Use the same compose project instead — see Run the agent with Docker. The target must be reachable from inside the agent container: use http://<service>:<port> on the same Docker network (e.g. http://web:3000 or http://immich-server:2283), not http://localhost:3000 (that is the agent container itself). For a host-side service add extra_hosts: ["host.docker.internal:host-gateway"] and target http://host.docker.internal:<port>.
4. Open your public URL
Visit the assigned hostname from the dashboard. Requests arrive at Kepeink, travel down the open tunnel to your machine, and the agent forwards them to http://localhost:3000 (or http://<service>:<port> when the agent runs in Docker). The response streams back to the visitor over HTTPS.
Notes
- The target only has to be reachable **from the machine (or container) running the agent** — it never needs to be reachable from the internet. Docker: join the same compose network and use the service DNS name.
- Changes you make to the app are live immediately; the tunnel just relays traffic, it does not cache your app.
- Getting a 404 through the tunnel while the same URL works locally? Your app is routing on the
Hostheader and does not recognise the tunnel's hostname. The agent forwards the originalHost, so a request tohttps://your-tunnel.rproxy.kepeink.hu/reaches your app withHost: your-tunnel.rproxy.kepeink.hu. That is deliberate — the backend is normally your own server, which either expects that name or ignoresHostentirely — but it surprises nginxserver_name, ApacheVirtualHost, shared hosting and anything behind a CDN, and nothing in the logs explains it, because the tunnel completed a perfectly normal request. Confirm it without the tunnel involved:curl -H "Host: your-tunnel.rproxy.kepeink.hu" http://localhost:3000/— if that also 404s, add a server block for the tunnel hostname. - Want a branded URL? See Add a custom domain. Want the agent to hold the HTTPS certificate itself? See Turn on end-to-end TLS.