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:
- Go to Management → Connectivity
- Click Create Tunnel
- Enter a label (e.g., your company name)
- Copy the generated token (
ztun_...)
| Item | Example |
|---|---|
| Agent token | ztun_a1b2c3d4e5f6... |
| Tunnel URL | wss://tunnel.zihin.ai (default) |
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
| Field | Required | Description |
|---|---|---|
token_env | Yes | Name of the environment variable containing the token (ZIHIN_TOKEN) |
tunnel_url | No | WebSocket URL of the cloud server (default: wss://tunnel.zihin.ai) |
log_level | No | Log level: debug, info, warn, error (default: info) |
services[].name | Yes | Service identifier — must match the name configured in Zihin Cloud |
services[].url | Yes | Internal service URL (host and port only, no path) |
services[].inject_headers | No | Headers added to every request. Supports ${VAR} for environment variables |
services[].ssl_verify | No | Set to false for self-signed certificates (default: true) |
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.
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
Option A: Docker (recommended)
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)
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 (
index0 through 3) - No authentication errors in logs (
code: 4001or4003) - Container/process is running (
docker psorsystemctl 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:
- A new token is generated and displayed once — copy it immediately
- The previous token continues working for 24 hours (grace period) — both tokens are accepted during this window
- Update the
ZIHIN_TOKENvariable 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
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.