How to connect your private server to ChatGPT and AgentKit without data leaks: OpenAI's new tunnel-client
I’m Denis Shokhirev, Agentic AI Systems Architect based in Freiburg, Germany. At DennisCraft AI Studio, my stack runs in production: Claude, Supabase, n8n, Doppler, self-hosted Postgres. The real pain: letting ChatGPT/AgentKit access private APIs or databases—without ever exposing internal services or risking token leakage. One config slip, and a client’s entire prod database could show up on Shodan. Introducing OpenAI’s tunnel-client: what it is and why it matters In June 2024, OpenAI releas
I’m Denis Shokhirev, Agentic AI Systems Architect based in Freiburg, Germany. At DennisCraft AI Studio, my stack runs in production: Claude, Supabase, n8n, Doppler, self-hosted Postgres. The real pain: letting ChatGPT/AgentKit access private APIs or databases—without ever exposing internal services or risking token leakage. One config slip, and a client’s entire prod database could show up on Shodan.
Introducing OpenAI’s tunnel-client: what it is and why it matters
In June 2024, OpenAI released tunnel-client, a CLI tool to create a secure reverse tunnel between your private server and OpenAI’s AgentKit/ChatGPT infrastructure. Think of it as an SSH tunnel purpose-built for LLM agent integrations—no need to open inbound firewall ports or run your own proxies. Example usage:
tunnel-client \
--url http://localhost:8080 \
--token $OPENAI_TUNNEL_TOKEN \
--server https://tunnel.openai.com
The tunnel is authenticated with a short-lived token provisioned from the OpenAI console. All traffic is outbound-only over TLS, and your server never gets an externally routable endpoint. This instantly removes entire classes of exposure.
How data actually leaks in real-world LLM pipelines
Where the risks start: LLM misbehavior meets infra misconfig
Across three recent multi-agent deployments, I found the same pattern: LLM-generated code or logs sometimes output .env secrets or API keys, especially when running in debug mode. Even with a sandboxed LLM runtime, if your webhook or API is exposed to the public net, a single misconfigured endpoint can lead to credential leaks. The 2024 Stanford CodeML study found that 38% of LLM-generated Python code samples contained CWE-89 (SQL injection) vulnerabilities.
What tunnel-client changes: reducing your attack surface
| Approach | Exposed Ports | Integration with OpenAI | Leak Vector |
|---|---|---|---|
| Direct webhook | 80/443 open | Direct | Scanning, brute-force, exploits |
| VPN + self-hosted proxy | Limited | Manual | Config leaks, env keys |
| tunnel-client | Outbound only | Official | Only if token is compromised |
With tunnel-client, the only attack vector is theft of the OpenAI-issued token. No inbound port—no chance of external scans or zero-day attacks on your API. Revoke the token, and the connection instantly breaks. No “zombie” sessions.
How to deploy tunnel-client in a production stack
Minimal integration: Supabase, n8n, Claude
My production stack: Supabase (Postgres + storage), n8n for workflow orchestration, and Claude Code for LLM logic. Typical scenario: ChatGPT agents (via AgentKit) need access to an internal API or service.
# Get your tunnel token in the OpenAI console (chat.openai.com)
export OPENAI_TUNNEL_TOKEN=sk-...
# Run tunnel-client as a systemd service:
[Unit]
Description=OpenAI Tunnel Client
After=network.target
[Service]
ExecStart=/usr/local/bin/tunnel-client \
--url http://localhost:8000 \
--token ${OPENAI_TUNNEL_TOKEN} \
--server https://tunnel.openai.com
Restart=always
[Install]
WantedBy=multi-user.target
This ensures your internal service is never directly exposed, but ChatGPT/AgentKit can reach it securely via the tunnel.
Securing the stack: gitleaks, Doppler, OWASP
Before launch, I enforce static config only (no hardcoded secrets). I scan all repos with gitleaks and manage runtime secrets in Doppler. For runtime exposure, I run OWASP ZAP scans on staging to ensure the tunnel isn’t used as a backdoor to legacy endpoints.
Advanced best practices: isolation and traffic controls
Rate limiting and audit logging
tunnel-client alone doesn’t stop abuse. If AgentKit or a misbehaving LLM agent sends too many requests, you risk a mini-DDoS on your infra or DB. In production, I add NGINX rate limiting in front of all tunnel-client endpoints:
limit_req_zone $binary_remote_addr zone=llm:10m rate=10r/s;
server {
listen 8000;
location / {
limit_req zone=llm burst=20;
proxy_pass http://localhost:9000;
}
}
I also log every inbound request for anomaly detection and forensic audit.
Principle of least privilege and zero trust
Never run tunnel-client as root. Create a dedicated system user with minimal privileges and no write access to local files. In Supabase, issue a dedicated service account with the narrowest possible permissions for tunnel-connected use cases.
FAQ
Can I map multiple services through a single tunnel-client?
No, each tunnel-client maps one local endpoint to one tunnel. For multiple internal services, run multiple tunnel-client instances on different ports.
What happens if my tunnel-client token leaks to the public?
Anyone with the token can open a tunnel to your server. Always store tokens in Doppler or HashiCorp Vault, keep them out of code (scan with gitleaks), and rotate regularly.
Does tunnel-client handle authentication?
No, it’s just a transport layer. You must implement authentication at your API or via middleware (e.g., JWT).
Is WebSocket/streaming supported?
Yes, tunnel-client can proxy WebSocket streams, but you may hit latency or message size limits depending on your infra.
Do I need to change my firewall rules?
No inbound rules are required; tunnel-client initiates outbound connections only. Just allow egress to tunnel.openai.com.
Which stage in your LLM pipeline catches the most issues in prod—static analysis, runtime sandbox, or human review? I’d genuinely like to know. I run a free 30-min stack audit for DACH founders building AI in regulated markets. DM me on LinkedIn or write to @ger_dennis_ai.
Turn your process into an AI system
Production quality. DACH B2B focus.