golocal-server is a lightweight drop in replacement for localtunnel server written in Go that provisions per-client TCP tunnel listeners and routes HTTP traffic through subdomains.
It supports:
- Random or named tunnel creation over HTTP.
- HTTP request proxying to connected tunnel clients.
- Upgrade passthrough for websocket-style connections.
- Basic status endpoints for server and tunnel socket counts.
- Containerized deployment with a small final image.
Roadmap:
- Password protection for new clients (requires a port of localtunnel client with support for authentication)
The following variables are read at startup:
| Variable | Default | Description |
|---|---|---|
PORT |
8000 |
HTTP listen port for the server process. |
LISTEN_ON |
0.0.0.0 |
Listen address bound by the HTTP server and TCP listener. 0.0.0.0 for all interfaces. |
DOMAIN |
empty | Base domain used to resolve tunnel subdomains. If unset, the server infers the client ID from the incoming host. |
SECURE |
false |
Controls whether generated tunnel URLs use https instead of http. This does not terminate TLS by itself. |
MAX_SOCKETS |
10 |
Maximum pooled TCP sockets allowed per tunnel client. |
GRACE_PERIOD |
5s |
Grace period before removing a client that disconnected (time.Duration value) |
PORT_START |
0 |
Optional first port in a fixed tunnel-port allocation range. When unset, ports are assigned dynamically. |
PORT_END |
0 |
Optional last port in a fixed tunnel-port allocation range. Must be greater than or equal to PORT_START when a range is configured. |
LOG_LEVEL |
info |
debug/info/warn/error |
DOMAINshould be set when running behind a real DNS (eg. tunnel.mydomain.com)SECURE=trueonly changes the reported tunnel URL scheme. TLS termination still needs to happen in a reverse proxy or load balancer.- Set
PORT_STARTandPORT_ENDto limit the ports you need to expose to the public. Setting a port range implicitly limits the maximum amount of simultaneous clients
Run the container directly:
docker run --rm --net host -p 8000:8000 \
-e PORT=8000 \
-e DOMAIN=tunnels.example.com \
-e SECURE=true \
ghcr.io/monodepth/golocal-server:latestservices:
golocal-server:
container_name: golocal-server
image: ghcr.io/monodepth/golocal-server:latest
restart: unless-stopped
environment:
PORT: "8000"
LISTEN_ON: "0.0.0.0"
DOMAIN: "tunnels.example.com"
SECURE: "true"
MAX_SOCKETS: "20"
PORT_START: "30000"
PORT_END: "30100"
LOG_LEVEL: "info"
ports:
- "8000:8000"
- "30000-30100:30000-30100"- If you use
DOMAIN=tunnels.example.com, you need wildcard DNS such as*.tunnels.example.compointing at this service. - If TLS is required, place the service behind a proxy such as Caddy, Nginx, or Traefik and forward the HTTP traffic to the configured
PORT. - If you restrict tunnel ports with
PORT_STARTandPORT_END, publish that range in Docker or your firewall so clients can connect.
tunnel.yourdomain.com {
reverse_proxy 192.168.1.111:8000
}
*.tunnel.yourdomain.com {
reverse_proxy 192.168.1.111:8000
}The binary reads configuration from environment variables. A .env file is also supported automatically through godotenv autoloading.
go run .To run the test suite:
go test ./...