tunn is a developer-friendly wrapper around OpenSSH that makes it easy to manage multiple SSH tunnels defined in a simple configuration file
- π Simple Configuration: Define all your tunnels in a single YAML file
- π§ Selective Tunnels: Run all tunnels or specific ones by name
- π Multiple Ports: Support for multiple port mappings per tunnel
- π SSH Integration: Leverages your existing SSH configuration
- β‘ Parallel Execution: All tunnels run concurrently
- π§© Daemon Mode: Background service with status reporting via IPC
- π§Ό Lean Go Module: Depends only on
gopkg.in/yaml.v3, keeping builds clean and portable - π§ Native SSH Sessions: Spawns the system
sshbinary for each mapping, so keys and config behave exactly like your shell - ποΈ Per-Port Processes: Launches one PID per port to pave the way for fine-grained lifecycle controls
curl -sSL https://raw.githubusercontent.com/strandnerd/tunn/main/scripts/install.sh | shgo install github.com/strandnerd/tunn@latestgit clone https://github.com/strandnerd/tunn.git
cd tunn
go build -o tunn
sudo mv tunn /usr/local/bin/Create a ~/.tunnrc file in your home directory:
tunnels:
api:
host: myserver # SSH host from ~/.ssh/config
ports:
- 3000:3000 # local:remote port mapping
- 4000:4001
user: apiuser # optional: SSH user
identity_file: ~/.ssh/id_rsa # optional: SSH key
db:
host: database
ports:
- 3306:3306 # MySQL
- 5432:5432 # PostgreSQL
user: dbadmin # optional: overrides SSH config
cache:
host: cacheserver
ports:
- 6379:6379 # Redistunnels: Map of tunnel nameshost: SSH host alias from~/.ssh/configports: List of port mappings inlocal:remoteformatuser(optional): SSH username (overrides~/.ssh/config)identity_file(optional): Path to SSH private key
tunn# Single tunnel
tunn api
# Multiple tunnels
tunn api db
# All database-related tunnels
tunn db cachetunn --detach
# Or only specific tunnels
tunn --detach api dbThe CLI respawns itself as a daemon, stores metadata under $XDG_RUNTIME_DIR/tunn (or ~/.cache/tunn when the runtime dir is unavailable), and immediately returns control to the terminal.
tunn statusThe status command contacts the daemon's Unix socket, reporting the PID, mode, and the latest port states for each managed tunnel. If no daemon is running, a friendly message is printed instead.
tunn stopThe stop command asks the daemon to shut down cleanly, waits for it to exit, and reports success.
Tunnels Ready
[api]
3000 β 3000 [active]
4000 β 4001 [active]
[db]
3306 β 3306 [connecting]
5432 β 5432 [active]
tunn uses your system's SSH configuration. Make sure your hosts are defined in ~/.ssh/config:
Host myserver
HostName 192.168.1.100
User myuser
Port 22
Host database
HostName db.example.com
User dbuser
IdentityFile ~/.ssh/db_key
- Go 1.21 or higher (for building)
- OpenSSH client (
sshcommand) - Valid SSH configuration
- macOS and Linux are supported today; Windows support is planned but not available yet
While running in detached mode, tunn stores the following files in its runtime directory:
daemon.pidβ PID of the active daemon; used to prevent duplicate launches.daemon.sockβ Unix domain socket for control commands (e.g.,tunn status).daemon.logβ Aggregated stdout/stderr from the daemon process.
The directory is created with 0700 permissions, and files are cleaned up automatically when the daemon exits or when stale state is detected on the next launch.
