Download ZelTunnel

Get the client binaries.

Download the macOS Apple Silicon or Linux amd64 ZIP, install the single binary, then connect approved TCP and UDP services through HTTPS.

Install

Unzip, make executable, move into PATH.

The archive contains the ZelTunnel binary. After installation, use the commands from the main page to start a local or reverse tunnel.

macOS Apple Silicon
unzip zeltunnel-macos-arm64.zip
chmod +x zeltunnel
sudo mv zeltunnel /usr/local/bin/
zeltunnel --help
Linux amd64
unzip zeltunnel-linux-amd64.zip
chmod +x zeltunnel
sudo mv zeltunnel /usr/local/bin/
zeltunnel --help
Server setup

Prepare the tunnel endpoint.

Generate the certificate, create a hashed token, and start the ZelTunnel server with a policy file that defines exactly which targets are allowed.

Certificate and token
# Generate a development certificate
zeltunnel cert generate \
  --out certs \
  --server-name tunnel.rocheston.com

# Hash the user token before placing it in config
zeltunnel token hash MY_SECRET_TOKEN
Start server
zeltunnel server \
  --config examples/server.yml

# Recommended public endpoint
https://tunnel.rocheston.com
Docker deployment

Run ZelTunnel server in a container.

Use Docker when you want the tunnel endpoint deployed as a repeatable service with mounted config and certificates. Expose TCP/443 for WSS and UDP/443 when QUIC transport is enabled.

Pull and run
# Pull published image from Docker Hub
docker pull rocheston/zeltunnel:latest

# Run server with mounted config and certs
docker run --rm --name zeltunnel \
  -p 443:443/tcp \
  -p 443:443/udp \
  -v $(pwd)/examples/server.yml:/etc/zeltunnel/server.yml:ro \
  -v $(pwd)/certs:/etc/zeltunnel/certs:ro \
  rocheston/zeltunnel:latest \
  zeltunnel server --config /etc/zeltunnel/server.yml
docker-compose.yml
services:
  zeltunnel:
    image: rocheston/zeltunnel:latest
    container_name: zeltunnel
    restart: unless-stopped
    ports:
      - "443:443/tcp"
      - "443:443/udp"
    volumes:
      - ./examples/server.yml:/etc/zeltunnel/server.yml:ro
      - ./certs:/etc/zeltunnel/certs:ro
    command:
      - zeltunnel
      - server
      - --config
      - /etc/zeltunnel/server.yml
Start with Compose
docker compose up -d
docker compose logs -f zeltunnel
docker compose down
Tunnel commands

Run local and reverse tunnels.

Local forwarding lets the user connect to localhost. Reverse forwarding lets a protected machine connect outward and expose an approved remote listener.

Local RDP forward
zeltunnel connect \
  --server https://tunnel.rocheston.com \
  --token MY_SECRET_TOKEN \
  --listen 127.0.0.1:3390 \
  --target 2.3.3.3:3389 \
  --protocol any \
  --transport auto

# Open Remote Desktop to:
127.0.0.1:3390
Reverse tunnel
zeltunnel reverse \
  --server https://tunnel.rocheston.com \
  --token MY_SECRET_TOKEN \
  --remote-listen 0.0.0.0:3390 \
  --target 127.0.0.1:3389 \
  --protocol any
Run from config
zeltunnel client --config examples/client.yml
Policy config

Keep access narrow by default.

The server policy should define allowed targets per token. ZelTunnel should not become an open proxy by accident.

Server policy example
auth:
  tokens:
    - id: "support-user"
      token_sha256: "...hashed-token..."
      allowed_targets:
        - "2.3.3.3:3389"
        - "10.0.0.0/8:22"

security:
  allow_open_proxy: false
  allow_public_bind_default: false
Client config example
server: "https://tunnel.rocheston.com"
token: "MY_SECRET_TOKEN"
tunnels:
  - name: "rdp"
    listen: "127.0.0.1:3390"
    target: "2.3.3.3:3389"
    protocol: "any"
    transport: "auto"
Workflow

From download to protected service access.

This is the practical sequence for getting a user connected without exposing broad network access.

1

Download

Choose the macOS or Linux ZIP and install the binary into PATH.

2

Provision

Create a scoped token and policy entry for the exact target service.

3

Connect

Run the local or reverse tunnel command with protocol and transport settings.

4

Audit

Review auth events, byte counts, health checks, and policy decisions.

Operating notes

What administrators should remember.

ZelTunnel is built for precise service access. The safest deployment keeps targets explicit, tokens short-lived, and public binds controlled.

Firewall view

Client networks see HTTPS to tunnel.rocheston.com, not direct RDP, SSH, database, or DNS ports.

Transport auto

Use WSS as the reliable baseline and QUIC where UDP/443 is available.

Public binds

Require explicit approval before exposing listeners beyond localhost or approved interfaces.

No payload logs

Audit metadata should cover access, timing, targets, and byte counts, not user payload contents.

Revocation

Disable tokens server-side to cut off access without touching the user application.

Agentic layer

Metrics and health data can feed policy agents for provisioning, anomaly detection, and self-healing.

Troubleshooting

Common checks when a tunnel does not connect.

Most failures come from token mismatch, policy denial, blocked network path, or a target service that is not reachable from the server.

Authentication fails

  • 1Confirm the user token matches the hashed token in server config.
  • 2Check clock, expiry, and token revocation status.
  • 3Review auth failure counters in metrics.

Target does not respond

  • 1Verify the target host and port are reachable from the ZelTunnel server.
  • 2Confirm the target is listed in the token ACL.
  • 3Check whether TCP, UDP, or protocol any is required.
Next

Connect a protected service.

Use an approved token and target from your administrator. The local app connects to localhost while ZelTunnel carries traffic through the HTTPS tunnel.

🖥

RDP

Bind 127.0.0.1:3390, then open Remote Desktop to that local address.

⌨️

SSH

Bind a local port and point your SSH client at localhost.

🗄

Database

Forward only the approved database host and port instead of exposing a subnet.