Getting Started
Install and configure the Tunnel Agent to connect your on-premise services to Zihin Cloud. Current agent version: 1.3.
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_...)
The token is displayed only once. Copy it immediately and store it securely (vault, secret manager, or a .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
inject_headers:
X-API-Key: "${ANOTHER_KEY}"
| Field | Required | Description |
|---|---|---|
token_env | Yes | Name of the environment variable containing the token (ZIHIN_TOKEN) |
tunnel_url | No | Cloud server URL (default: wss://tunnel.zihin.ai) |
log_level | No | debug, info, warn, error (default: info) |
pool_size | No | Connections to the cloud (1–10, default 4) |
services[].name | Yes | Service name — must match the name configured in Zihin Cloud |
services[].url | Yes | Internal service URL, host and port only (the request path is added automatically) |
services[].inject_headers | No | Headers added to every request. Supports ${VAR} for environment variables |
Values in inject_headers are resolved locally and never sent to the cloud. Use them for credentials only — do not add an Accept header for MCP services (it causes 406 Not Acceptable).
3. Start the agent
Option A: Docker Compose (recommended)
services:
zihin-tunnel:
image: ghcr.io/zihin-ai/tunnel-agent:1.3
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
docker compose up -d
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:1.3
Option C: Node.js
The @zihin/tunnel-agent npm package is not yet published. Use Docker for now.
4. Verify the connection
The logs should show one WebSocket connected line per connection (4 by default):
{"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}
In the Console, the tunnel status changes to Connected and lists the registered services.
5. Self-signed certificates
If an internal service uses HTTPS with a private CA, mount the CA certificate and set NODE_EXTRA_CA_CERTS:
services:
zihin-tunnel:
image: ghcr.io/zihin-ai/tunnel-agent:1.3
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
ssl_verify: false has no effect — TLS verification is always on.
6. Token rotation
When an admin rotates the token in the Console, the previous token keeps working for 24 hours. Update ZIHIN_TOKEN and restart the agent within that window:
docker compose down && docker compose up -d
7. Updating the agent
docker compose pull
docker compose up -d
The agent reconnects automatically. No configuration changes are needed between versions.
Environment-only configuration
For environments where a YAML file is impractical (Kubernetes, ECS):
export ZIHIN_TOKEN="ztun_your_token_here"
export ZIHIN_TUNNEL_URL="wss://tunnel.zihin.ai"
export ZIHIN_LOG_LEVEL="info"
export ZIHIN_POOL_SIZE="4"
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"}}
]'
If no zihin-agent.yml is found, the agent uses the environment variables.