Skip to main content

Getting Started

This guide walks you through installing and configuring the Tunnel Agent to connect your on-premise services to Zihin Cloud.

1. Create the tunnel

An admin or owner of your organization creates the tunnel from the Zihin Console:

  1. Go to Management → Connectivity
  2. Click Create Tunnel
  3. Enter a label (e.g., your company name)
  4. Copy the generated token (ztun_...)
ItemExample
Agent tokenztun_a1b2c3d4e5f6...
Tunnel URLwss://tunnel.zihin.ai (default)
caution

The token is displayed only once at creation time. Copy it immediately and store it in a secure location (vault, secret manager, or .env file with restricted permissions).

2. Create the configuration file

Create a file named zihin-agent.yml:

token_env: ZIHIN_TOKEN
tunnel_url: wss://tunnel.zihin.ai
log_level: info

services:
- name: my-service
url: http://192.168.1.100:8080
inject_headers:
Authorization: "Bearer ${SERVICE_API_KEY}"

- name: another-service
url: https://internal.example.com
ssl_verify: false
inject_headers:
X-API-Key: "${ANOTHER_KEY}"

Configuration reference

FieldRequiredDescription
token_envYesName of the environment variable containing the token (ZIHIN_TOKEN)
tunnel_urlNoWebSocket URL of the cloud server (default: wss://tunnel.zihin.ai)
log_levelNoLog level: debug, info, warn, error (default: info)
services[].nameYesService identifier — must match the name configured in Zihin Cloud
services[].urlYesInternal service URL (host and port only, no path)
services[].inject_headersNoHeaders added to every request. Supports ${VAR} for environment variables
services[].ssl_verifyNoSet to false for self-signed certificates (default: true)
Important

The services[].url field should contain only the host and port (e.g., https://192.168.1.100:8080). The request path is forwarded automatically by the tunnel — do not include it in the URL.

Security

Values in inject_headers are resolved locally and never sent to the cloud. Zihin Cloud only sends the service name — the agent resolves the URL and injects headers on your network.

3. Start the agent

Create a docker-compose.yml:

services:
zihin-tunnel:
image: ghcr.io/zihin-ai/tunnel-agent:latest
container_name: zihin-tunnel
restart: unless-stopped
environment:
- ZIHIN_TOKEN=ztun_your_token_here
- SERVICE_API_KEY=your-api-key
- ANOTHER_KEY=another-key
volumes:
- ./zihin-agent.yml:/app/zihin-agent.yml:ro
# Start
docker compose up -d

# View logs
docker compose logs -f zihin-tunnel

Option B: Docker run

docker run -d \
--name zihin-tunnel \
--restart unless-stopped \
-e ZIHIN_TOKEN="ztun_your_token_here" \
-e SERVICE_API_KEY="your-api-key" \
-v $(pwd)/zihin-agent.yml:/app/zihin-agent.yml:ro \
ghcr.io/zihin-ai/tunnel-agent:latest

Option C: Node.js (coming soon)

Coming Soon

The @zihin/tunnel-agent npm package is not yet published. Use Docker (Option A or B) for now.

4. Verify the connection

After starting the agent, the logs should show:

{"level":"info","message":"Zihin Tunnel Agent starting","services":["my-service","another-service"]}
{"level":"info","message":"WebSocket connected","index":0}
{"level":"info","message":"WebSocket connected","index":1}
{"level":"info","message":"WebSocket connected","index":2}
{"level":"info","message":"WebSocket connected","index":3}

The 4 connections indicate the pool is active and ready to handle requests.

Verification checklist

  • All 4 WebSocket connections established (index 0 through 3)
  • No authentication errors in logs (code: 4001 or 4003)
  • Container/process is running (docker ps or systemctl status)

5. Self-signed certificates

If your internal service uses HTTPS with a self-signed certificate, you have two options:

Option 1: Disable verification (simpler)

services:
- name: my-service
url: https://internal-host:8443
ssl_verify: false

Option 2: Mount the CA certificate (more secure)

# docker-compose.yml
services:
zihin-tunnel:
image: ghcr.io/zihin-ai/tunnel-agent:latest
environment:
- NODE_EXTRA_CA_CERTS=/app/certs/ca-cert.pem
volumes:
- ./zihin-agent.yml:/app/zihin-agent.yml:ro
- ./certs/ca-cert.pem:/app/certs/ca-cert.pem:ro

6. Token rotation

An admin can rotate the tunnel token from the Console at any time (Management → Connectivity → Rotate Token). When a rotation happens:

  1. A new token is generated and displayed once — copy it immediately
  2. The previous token continues working for 24 hours (grace period) — both tokens are accepted during this window
  3. Update the ZIHIN_TOKEN variable and restart the agent before the 24-hour grace period expires
# Update the token in your .env or docker-compose.yml, then:
docker compose down && docker compose up -d
warning

After the 24-hour grace period, only the new token is accepted. Make sure to update the agent configuration within this window to avoid disconnection.

7. Updating the agent

docker compose pull
docker compose up -d

The agent reconnects automatically after restart. The pool re-establishes all 4 connections in seconds.

Environment-only configuration

For environments where a YAML file is impractical (Kubernetes, ECS), configure everything via environment variables:

export ZIHIN_TOKEN="ztun_your_token_here"
export ZIHIN_TUNNEL_URL="wss://tunnel.zihin.ai"
export ZIHIN_LOG_LEVEL="info"
export ZIHIN_SERVICES='[
{"name":"my-service","url":"http://192.168.1.100:8080","headers":{"Authorization":"Bearer key"}},
{"name":"another","url":"http://192.168.1.50:3000","headers":{"X-API-Key":"token"}}
]'

The agent automatically detects this: if no zihin-agent.yml is found, it uses environment variables.