Advanced Tunnel Configuration
- Applies to
- Gatewayruntime for API, AI, and MCP gateways
- Hosting
- Managed EdgeManaged DedicatedDiffersSelf-HostedDiffers
2 differences by hosting option
Tunnels work on Managed Dedicated, but most teams connect to private backends with their cloud provider's native networking, such as a transit gateway or VPC peering. See Networking.
Tunnels work on Self-Hosted, but your gateway already runs on your network, so most teams reach private backends directly or with native networking, such as a transit gateway or VPC peering.
Enterprise Feature
Secure tunneling is available as an add-on as part of an enterprise plan. If you would like to purchase this feature, please contact us at sales@zuplo.com or reach out to your account manager.
Most enterprise features can be used in a trial mode for a limited time. Feel free to use enterprise features for development and testing purposes.
The zuplo/tunnel image covers most
deployments without configuration beyond TUNNEL_TOKEN. This page is for teams
that need more control: pinning versions, tuning the transport, rotating tokens,
or mirroring the image into their own registry.
How the image runs
The image starts the tunnel with fixed settings:
| Setting | Why the image sets it |
|---|---|
| No automatic updates | The tunnel never replaces its own binary while running. The image tag is the only thing that determines the version, which keeps containers immutable and deployments reproducible. |
| HTTP/2 transport | The tunnel connects over HTTP/2 on TCP port 443. Many corporate networks block outbound UDP, so the image doesn't try a UDP transport first. |
| Remotely managed routing | The tunnel's routing configuration lives in Zuplo, not in a local config file. The tunnel reads its credentials from TUNNEL_TOKEN and fetches the rest of its configuration from Zuplo when it starts. |
Container characteristics
The image has properties worth knowing when you write a deployment manifest or a security policy:
- Distroless base, no shell. You can't exec into a running tunnel container to debug it. Run a separate debug container in the same network namespace instead — see Check connectivity to your backend.
- Runs as a non-root user (UID 65532). It needs no elevated privileges, no additional Linux capabilities, and no writable root filesystem.
- Needs no persistent volume. The tunnel holds no state between restarts and fetches its configuration from Zuplo on startup.
- Listens on no inbound ports unless you set
TUNNEL_METRICS.
Environment variables
The tunnel reads these environment variables:
| Variable | Default | Description |
|---|---|---|
TUNNEL_TOKEN | none | The tunnel's connection token, from zuplo tunnel describe. Required. |
TUNNEL_LOGLEVEL | info | Log verbosity. One of debug, info, warn, error, or fatal. Use debug when troubleshooting. |
TUNNEL_METRICS | none | Address to serve Prometheus metrics on, such as 0.0.0.0:2000. Useful for scraping connection health. |
TUNNEL_TRANSPORT_PROTOCOL | auto | Transport the tunnel uses to connect to Zuplo. One of auto, http2, or quic. |
NO_AUTOUPDATE | false | Disables in-place binary updates. |
TUNNEL_EDGE_IP_VERSION | 4 | IP version for connecting to Zuplo. One of 4, 6, or auto. |
Image settings override environment variables
The zuplo/tunnel image turns off automatic updates and sets the HTTP/2
transport on its command line, which takes precedence over environment
variables. Setting NO_AUTOUPDATE or TUNNEL_TRANSPORT_PROTOCOL on a
zuplo/tunnel container has no effect.
Pin and upgrade the image version
The zuplo/tunnel tags are date-based versions, such as
zuplo/tunnel:2025.10.1. The latest tag always points at the most recent
release.
For production, pin an explicit tag rather than using latest, so a redeploy
can't silently change connector versions:
Code
Then upgrade deliberately. Versions more than a year older than the latest release can stop working, and new releases can include breaking changes. Check for a newer tag on a regular cadence and treat the upgrade as routine maintenance. Test each new version in a staging environment before rolling it out to production.
Because tunnel instances that share a token act as replicas, you can upgrade without downtime: start instances on the new version, wait for them to connect, then stop the old ones.
Rotate the tunnel token
Rotate a token on a schedule, and immediately if you suspect it's been exposed. With at least two instances running, you can rotate without dropping traffic.
-
Issue a new token for the tunnel:
CodeAfter rotation, the old token can't establish new connections, but instances already connected with it keep serving traffic.
-
Update the token in your secret manager.
-
Restart half your instances so they pick up the new token, and wait for them to report as connected.
-
Restart the remaining instances.
Rotating with a single instance running causes a brief interruption while the instance restarts. Schedule it during a maintenance window.
Mirror the image into your registry
If a policy forbids pulling from public registries, copy zuplo/tunnel into
your own registry and run it from there. Keep the image unchanged and pass the
same TUNNEL_TOKEN:
Code
Mirror each new version the same way when you upgrade. Zuplo tests and supports
the zuplo/tunnel image. If you change the image or build your own, support can
help with the tunnel and its configuration in Zuplo but not with your image.
Next steps
- Troubleshoot a tunnel — diagnose a tunnel that's down or not passing traffic.
- Connect to tunnel services — the service
configuration reference and
service://usage.