⚡ Self-hosted Tunnels
Run your own tunnel infrastructure using open-source tools. Full control, no third-party dependencies, no data passing through external servers.
Requirements: A VPS with a public IP to act as the relay server.
Overview
| Tool | Language | Best For | Complexity |
|---|---|---|---|
bore |
Rust | Simple HTTP/TCP tunnels | Low |
rathole |
Rust | High-performance, production use | Medium |
frp |
Go | Feature-rich, configurable | Medium–High |
bore
The simplest option. Expose a local port through a relay server in one command.
Install
On both server and client:
cargo install bore-cli
Or download prebuilt binaries from https://github.com/ekzhang/bore/releases:
# Linux x86_64
wget https://github.com/ekzhang/bore/releases/latest/download/bore-v0.5.0-x86_64-unknown-linux-musl.tar.gz
tar xzf bore-*.tar.gz
sudo mv bore /usr/local/bin/
Setup
On your VPS (relay server):
bore server
Listens on port 7835 by default.
On your local machine (client):
bore local 3000 --to your-vps-ip
Output:
listening at your-vps-ip:XXXXX
Traffic to your-vps-ip:XXXXX is now forwarded to localhost:3000.
With a secret (prevent unauthorized use)
# Server
bore server --secret mysecret
# Client
bore local 3000 --to your-vps-ip --secret mysecret
Systemd service (VPS)
# /etc/systemd/system/bore.service
[Unit]
Description=bore relay server
After=network.target
[Service]
ExecStart=/usr/local/bin/bore server
Restart=always
User=nobody
[Install]
WantedBy=multi-user.target
sudo systemctl enable --now bore
rathole
High-performance, production-ready reverse proxy tunnel. Better suited for persistent services.
Install
Download from https://github.com/rapiz1/rathole/releases:
wget https://github.com/rapiz1/rathole/releases/latest/download/rathole-x86_64-unknown-linux-musl.zip
unzip rathole-*.zip
sudo mv rathole /usr/local/bin/
Setup
Server config (server.toml) — on your VPS:
[server]
bind_addr = "0.0.0.0:2333"
[server.services.my-app]
token = "mysecrettoken"
bind_addr = "0.0.0.0:8080" # public port on VPS
Client config (client.toml) — on your local machine:
[client]
remote_addr = "your-vps-ip:2333"
[client.services.my-app]
token = "mysecrettoken"
local_addr = "127.0.0.1:3000" # your local service
Run
# On VPS
rathole server.toml
# On local machine
rathole client.toml
Traffic to your-vps-ip:8080 is now forwarded to localhost:3000.
Multiple services
# server.toml
[server.services.web]
token = "token-web"
bind_addr = "0.0.0.0:80"
[server.services.api]
token = "token-api"
bind_addr = "0.0.0.0:8080"
# client.toml
[client.services.web]
token = "token-web"
local_addr = "127.0.0.1:3000"
[client.services.api]
token = "token-api"
local_addr = "127.0.0.1:4000"
frp (Fast Reverse Proxy)
The most feature-rich option. Widely used, highly configurable, supports HTTP/HTTPS virtual hosts, TCP, UDP, STCP, and more.
Install
Download from https://github.com/fatedier/frp/releases:
wget https://github.com/fatedier/frp/releases/latest/download/frp_0.58.0_linux_amd64.tar.gz
tar xzf frp_*.tar.gz
cd frp_*_linux_amd64
Binaries:
frps— server (runs on VPS)frpc— client (runs locally)
Setup
Server config (frps.toml) — on your VPS:
bindPort = 7000
vhostHTTPPort = 80
vhostHTTPSPort = 443
auth.token = "mysecrettoken"
Client config (frpc.toml) — on your local machine:
serverAddr = "your-vps-ip"
serverPort = 7000
auth.token = "mysecrettoken"
[[proxies]]
name = "web"
type = "http"
localPort = 3000
customDomains = ["app.yourdomain.com"]
Run
# VPS
./frps -c frps.toml
# Local machine
./frpc -c frpc.toml
TCP tunnel (no domain needed)
[[proxies]]
name = "ssh"
type = "tcp"
localIP = "127.0.0.1"
localPort = 22
remotePort = 6000 # public port on VPS
Then: ssh -p 6000 user@your-vps-ip
HTTPS with Let’s Encrypt
frp can terminate TLS if you add certificate paths to frps.toml:
vhostHTTPSPort = 443
[[tlsConfig]]
certFile = "/etc/letsencrypt/live/yourdomain.com/fullchain.pem"
keyFile = "/etc/letsencrypt/live/yourdomain.com/privkey.pem"
Web dashboard (frps)
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"
Access at http://your-vps-ip:7500
Choosing the Right Tool
Need something simple and fast to set up?
→ bore
Need reliability and performance for a permanent service?
→ rathole
Need virtual hosts, dashboards, UDP, or advanced routing?
→ frp
Firewall Notes
Open the required ports on your VPS:
# bore
sudo ufw allow 7835
# rathole — tunnel control port + each service port
sudo ufw allow 2333
sudo ufw allow 8080
# frp — control port + vhost ports
sudo ufw allow 7000
sudo ufw allow 80
sudo ufw allow 443
Notes
- All three tools require a VPS with a public IP as the relay
- Combine with Nginx or Caddy on the VPS for TLS termination and virtual hosting
- For high-availability, run the server binary as a systemd service with
Restart=always - None of these route your traffic through third-party networks — everything goes through your VPS
See also: Cloudflare Tunnel for managed public access · Tailscale for private mesh VPN · Ngrok for quick testing