easybot-tunnel-client/README.md

5.7 KiB

EasyBot Tunnel Client

Lightweight reverse-tunnel client that connects private services (databases, APIs, etc.) behind firewalls to your EasyBot runtime via a secure WebSocket connection.

The client connects outbound to your EasyBot server — no inbound ports, firewall rules, or public IPs needed on the client side.

Prerequisites

  1. An EasyBot instance with the Tunnels feature enabled
  2. A tunnel created from the EasyBot dashboard (Settings > Tunnels)
  3. The token shown once at creation time (starts with eb_tun_)

Quick Start (Docker)

docker run -d --restart always --name easybot-tunnel \
  -e TUNNEL_SERVER=wss://YOUR_RUNTIME_URL/ws/tunnel \
  -e TUNNEL_TOKEN=eb_tun_YOUR_TOKEN_HERE \
  repo.pyp.ar/public-pull/easybot-tunnel-client:1.0

Replace:

  • YOUR_RUNTIME_URL with your EasyBot runtime hostname (e.g. runtime.example.com)
  • eb_tun_YOUR_TOKEN_HERE with the token from the dashboard

Installation by OS

Linux (Docker)

# Pull and run
docker run -d --restart always --name easybot-tunnel \
  -e TUNNEL_SERVER=wss://runtime.example.com/ws/tunnel \
  -e TUNNEL_TOKEN=eb_tun_xxxxx \
  repo.pyp.ar/public-pull/easybot-tunnel-client:1.0

# Check logs
docker logs -f easybot-tunnel

Linux (systemd, without Docker)

# Install Node.js 20+
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo bash -
sudo apt-get install -y nodejs

# Download and install
git clone https://repo.pyp.ar/public-pull/easybot-tunnel-client.git
cd easybot-tunnel-client
npm install --omit=dev
npm run build

# Create systemd service
sudo tee /etc/systemd/system/easybot-tunnel.service <<EOF
[Unit]
Description=EasyBot Tunnel Client
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
Restart=always
RestartSec=5
Environment=TUNNEL_SERVER=wss://runtime.example.com/ws/tunnel
Environment=TUNNEL_TOKEN=eb_tun_xxxxx
WorkingDirectory=$(pwd)
ExecStart=/usr/bin/node dist/index.js

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now easybot-tunnel
sudo journalctl -u easybot-tunnel -f

Windows (Docker Desktop)

docker run -d --restart always --name easybot-tunnel `
  -e TUNNEL_SERVER=wss://runtime.example.com/ws/tunnel `
  -e TUNNEL_TOKEN=eb_tun_xxxxx `
  repo.pyp.ar/public-pull/easybot-tunnel-client:1.0

Windows (as a service, without Docker)

# Install Node.js 20+ from https://nodejs.org

# Download and build
git clone https://repo.pyp.ar/public-pull/easybot-tunnel-client.git
cd easybot-tunnel-client
npm install --omit=dev
npm run build

# Install as Windows service using nssm (https://nssm.cc)
nssm install EasyBotTunnel "C:\Program Files\nodejs\node.exe" "C:\easybot-tunnel-client\dist\index.js"
nssm set EasyBotTunnel AppEnvironmentExtra TUNNEL_SERVER=wss://runtime.example.com/ws/tunnel TUNNEL_TOKEN=eb_tun_xxxxx
nssm set EasyBotTunnel AppRestartDelay 5000
nssm start EasyBotTunnel

macOS (Docker)

docker run -d --restart always --name easybot-tunnel \
  -e TUNNEL_SERVER=wss://runtime.example.com/ws/tunnel \
  -e TUNNEL_TOKEN=eb_tun_xxxxx \
  repo.pyp.ar/public-pull/easybot-tunnel-client:1.0

macOS (launchd, without Docker)

# Install Node.js
brew install node@22

# Download and build
git clone https://repo.pyp.ar/public-pull/easybot-tunnel-client.git
cd easybot-tunnel-client
npm install --omit=dev
npm run build

# Create launch agent
cat > ~/Library/LaunchAgents/com.easybot.tunnel.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>com.easybot.tunnel</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/local/bin/node</string>
    <string>$(pwd)/dist/index.js</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <key>TUNNEL_SERVER</key><string>wss://runtime.example.com/ws/tunnel</string>
    <key>TUNNEL_TOKEN</key><string>eb_tun_xxxxx</string>
  </dict>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
</dict>
</plist>
EOF

launchctl load ~/Library/LaunchAgents/com.easybot.tunnel.plist

Environment Variables

Variable Required Description
TUNNEL_SERVER Yes WebSocket URL of your EasyBot runtime (e.g. wss://runtime.example.com/ws/tunnel)
TUNNEL_TOKEN Yes Authentication token from the dashboard (starts with eb_tun_)

How It Works

  1. The client connects to your EasyBot runtime via WebSocket (outbound only)
  2. The server sends a config with port mappings (e.g. "forward localhost:5432 on this tunnel")
  3. When EasyBot needs to reach your private service, it opens a TCP connection through the tunnel
  4. Traffic flows bidirectionally: EasyBot runtime <-> WebSocket <-> Tunnel Client <-> Your private service

All port mappings are configured server-side in the EasyBot dashboard. The client only needs the server URL and token.

Verifying the Connection

After starting the client, check the EasyBot dashboard (Tunnels section). Your tunnel should show:

  • Status: Connected (green)
  • Latency in ms
  • Client IP

Troubleshooting

Issue Solution
"Connection refused" Check TUNNEL_SERVER URL is correct and reachable
"Authentication failed" Verify TUNNEL_TOKEN is correct (not expired/regenerated)
Keeps reconnecting Check firewall allows outbound WSS (port 443)
Target not reachable Ensure the target service (e.g. PostgreSQL) is running and accessible from the machine running the tunnel client

Building from Source

git clone https://repo.pyp.ar/public-pull/easybot-tunnel-client.git
cd easybot-tunnel-client
npm install
npm run build
node dist/index.js