up
Start an HTTP, TCP, or UDP tunnel that forwards a public endpoint to a local service.
tunnelctl up starts a tunnel. You pick the protocol with a subcommand — HTTP tunnels are
addressed by a slug (<slug>.intunnel.eu), TCP/UDP tunnels by a remote port
(tcp.intunnel.eu:<port> / udp.intunnel.eu:<port>).
tunnelctl up http <slug> [target] # HTTP / HTTPS
tunnelctl up tcp <remote-port> [target] # raw TCP
tunnelctl up udp <remote-port> [target] # raw UDPBy default it runs in the foreground and streams output; Ctrl+C shuts the tunnel
down cleanly. Add -d to run it as a background daemon. It's idempotent — running up
again for the same tunnel re-applies config (and restarts the daemon only if the config
changed).
The [target] is required only on the first up; later runs reuse the saved target.
HTTP — up http <slug> [target]
tunnelctl up http myapp 8080 # https://myapp.intunnel.eu → 127.0.0.1:8080
tunnelctl up http myapp 8080 -d # background daemon
tunnelctl up http myapp # reuse the saved target
tunnelctl up http api http://localhost:3000
tunnelctl up http web 5173 --host-header-rewrite localhost| Flag | Default | Description |
|---|---|---|
-d, --detach | off | Run as a background daemon; return to the shell immediately. |
--host-header-rewrite <value> | — | Rewrite the outgoing HTTP Host header (e.g. localhost) so dev servers (Vite, Storybook, webpack-dev-server) that reject foreign Host headers work. |
--pool-count <n> | 5 | Pre-allocate N work connections (1–50) for lower first-byte latency under load. |
Check a slug first
Slugs are globally unique. Use slugs check <name> before reserving
one. Tip: tunnelctl slugs check myapp && tunnelctl up http myapp 8080.
TCP / UDP — up tcp|udp <remote-port> [target]
L4 tunnels expose a public port on the tunnel apex and forward it to your local service. You name the tunnel by the remote port you want; there's no slug.
tunnelctl up tcp 27017 5432 # tcp.intunnel.eu:27017 → 127.0.0.1:5432
tunnelctl up udp 5353 53 -d # udp.intunnel.eu:5353 → 127.0.0.1:53, detached
tunnelctl up tcp "$(tunnelctl ports pick tcp)" 5432 # let the pool pick a free port| Flag | Default | Description |
|---|---|---|
-d, --detach | off | Run as a background daemon. |
The remote port must be inside the server's allowed L4 pool and not already taken — see
ports to inspect the range, check a port, or pick a free one.
--host-header-rewrite and --pool-count are HTTP-only and don't apply to TCP/UDP. A
http(s):// URL is not a valid target for TCP/UDP — use <host>:<port>.
Target formats
| Form | Resolves to | HTTP | TCP/UDP |
|---|---|---|---|
5173 | 127.0.0.1:5173 | ✓ | ✓ |
localhost:5173, 192.168.1.5:8080, [::1]:5173 | as written | ✓ | ✓ |
http://localhost:3000, https://api.example:8443 | host:port from the URL | ✓ | ✗ |
Omit the target to reuse the one saved for that tunnel.
Single runner per tunnel
A tunnel can only be served from one place at a time. Starting it elsewhere mints a newer connection token, which the server validates by serial — the older session is dropped.