[Feat]: Built-in SSH tunnel profiles (jumphost, -L/-D forwards, SOCKS)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 20/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- database, desktop, infrastructure
Research direction
Start by reviewing #406 and the existing SSH tunnel lifecycle it describes, then map how database drivers establish connections. The proposal spans tunnel profiles, credential storage, UI, driver routing, and reconnect behavior, so agree on a smaller phase and its boundaries before implementation. For the proposed v1, done means profiles support Keychain auth and multiple local forwards, status is visible, and the listed MySQL, Postgres, and Elasticsearch local-forward connections work.
Written by the indexing model from the issue text.
Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the feature has not already been requested
🚀 Feature Proposal
Built-in SSH tunnel profiles with jumphost, local forwards (-L), dynamic SOCKS (-D), and per-connection routing — so enterprise users don't need external scripts, LaunchAgents, or local HTTP/TCP proxies to reach databases behind a corporate jumphost.
Tabularis already supports basic SSH tunneling for some drivers (see #406), but real-world corporate setups need more: a shared jumphost profile, multiple forwards on one SSH session, SOCKS routing for private IPs, Keychain-backed credentials, auto-reconnect, and native support in HTTP-based drivers (Elasticsearch, Redis, etc.).
Problem
Many developers connect to databases and search engines only reachable through a corporate jumphost and internal hostnames that don't resolve on the public internet. Today this requires fragile, per-machine setup outside Tabularis:
| Workaround today | Pain |
|---|---|
Manual ssh -D 1080 -L 19200:internal-host:9200 jumphost in a terminal |
Dies on reboot; extra tab to babysit |
| macOS LaunchAgents | Auth/Keychain issues; hard to debug |
| Local Python proxies (e.g. ES 7.x compatibility shim) | Another process to maintain |
expect + Keychain for password auth |
Security tradeoffs; brittle |
SOCKS on localhost:1080 |
Tabularis ES/HTTP plugins often cannot use SOCKS |
Example real-world setup (enterprise):
Jumphost: [email protected]
SOCKS: localhost:1080
ES tunnel: localhost:19200 → internal-es-host:9200
ES proxy: localhost:19201 → patches ES 7.x _cat/indices for Tabularis
Redis: localhost:16379 → 10.x.x.x:6379 via SOCKS
A developer should not need 4 scripts, 4 LaunchAgents, and 2 proxy processes to browse data in Tabularis.
Proposed Solution
1. Tunnel Profiles (reusable)
Introduce Tunnel Profiles separate from database connections:
Name: Corporate Jumphost
SSH Host: jumphost.example.com
SSH User: developer
Auth: Keychain (ed25519 key) | Password (Keychain) | SSH Agent
Keep-alive: 30s
Auto-start: When Tabularis launches | When any linked connection opens
Forwards:
- Type: SOCKS5
Local: 127.0.0.1:1080
- Type: Local (-L)
Local: 127.0.0.1:19200
Remote: internal-es-host:9200
Connections reference a tunnel profile instead of duplicating SSH settings.
2. Connection-level tunnel modes
| Mode | Description |
|---|---|
| None | Direct connect (public/VPN reachable) |
| Use tunnel profile | Link to shared profile |
| Inline tunnel | SSH settings only for this connection |
| Local port only | User runs SSH externally; Tabularis uses localhost:PORT (with status check) |
Routing options per connection:
Direct— connect to configured host:portVia local forward—localhost:{local_port}→ tunnel forwards to{remote_host}:{remote_port}Via SOCKS— connect through profile's SOCKS proxy (for raw private IPs)
3. UI (Connection modal)
New section: Networking → SSH Tunnel
[ ] Enable SSH tunnel for this connection
Tunnel profile: [ Corporate Jumphost ▼ ] [Manage profiles…]
Routing:
(•) Local port forward
Local: [ 19200 ] → Remote: [ internal-es-host ] : [ 9200 ]
( ) SOCKS proxy
SOCKS: 127.0.0.1:1080 → Target: [ 10.x.x.x ] : [ 6379 ]
Status: ● Connected (up 2h 14m) [Reconnect] [View log]
☑ Start tunnel when opening this connection
☑ Reconnect automatically if dropped
Global: Settings → Tunnels → list all profiles, ports in use, "Test SSH".
4. Driver integration
For elasticsearch, clickhouse (HTTP), Redis, and similar:
- Local forward mode: connection URL uses
http://user:[email protected]:{local_port}automatically. - SOCKS mode: driver uses SOCKS5 for outbound TCP (no external TCP/HTTP proxy).
- Optional: built-in ES 7.x compatibility shim for
_cat/indices(dataset.sizefield added in ES 8.x).
5. Credential storage
- SSH private keys and passwords in OS Keychain (macOS Keychain, Windows Credential Manager, libsecret on Linux).
- Never store passwords in plain-text
connections.json. - Support SSH agent (
$SSH_AUTH_SOCK) as auth method.
6. Process model
- Tabularis runs a Tunnel Manager service:
- One SSH process per tunnel profile (multiplexed forwards via ControlMaster).
- Reconnect with exponential backoff.
- Log to app log directory per profile.
- On app quit: optionally keep tunnels running (user preference) or tear down.
User Stories
- Single jumphost, multiple services — One SSH session exposes SOCKS and forwards ES to localhost; open MySQL, ES, and Redis without multiple terminals.
- Per-connection tunnel — Attach a tunnel profile to "Prod ES" so Tabularis auto-forwards to
internal-es-host:9200. - SOCKS for internal IPs — Redis at a private IP works through SOCKS without a local TCP proxy script.
- Survive sleep/reboot — Tunnels reconnect when laptop wakes or Tabularis starts.
- Visibility — Connection card shows "Tunnel: connected" or "Tunnel: permission denied" before running a query.
Acceptance Criteria
- Create a tunnel profile with SSH host, user, and Keychain auth.
- Add SOCKS and multiple
-Lforwards to one profile. - Starting Tabularis (or opening a linked connection) brings tunnels up without external scripts.
- Elasticsearch connection through
-Lforward works without a local HTTP proxy. - Redis connection to a private IP works through SOCKS without a local TCP proxy.
- UI shows tunnel status; failed auth surfaces clear errors.
- Tunnels reconnect after sleep/network change (configurable).
- Credentials are not written to plain-text config files.
Phased Rollout
| Phase | Scope |
|---|---|
| v1 | Tunnel profiles, -L forwards, Keychain auth, status UI, MySQL/Postgres/ES via local forward |
| v1.1 | SOCKS5 routing for Redis and raw IPs |
| v1.2 | ES 7.x compatibility layer in driver |
| v2 | ProxyJump, shared team profiles |
Related
- #406 — existing SSH tunnel lifecycle bug (port left in use after server reboot); this proposal extends tunnel support and should address reconnect/port lifecycle holistically.
OS Version
macOS (also relevant for Linux enterprise users behind VPN/jumphost)
Tabularis Version
0.13.x (current)
Motivation
I manage 50+ database connections (MySQL, MongoDB, Elasticsearch, Redis, ClickHouse) behind a corporate jumphost. Without built-in tunnel profiles I maintain shell scripts, LaunchAgents, expect password helpers, and Python proxies just to make Tabularis work. First-class tunnel support would cut laptop onboarding from ~1 hour to minutes and eliminate an entire class of "connection refused on localhost" support issues.
Example
Before (6 moving parts):\n\n\nLaunchAgent: ssh-tunnels (1080, 19200)\nLaunchAgent: es-compatibility-proxy (19201)\nLaunchAgent: redis-tcp-proxy (16379)\nexpect + Keychain password script\nTabularis ES: http://user:pass@localhost:19201\nTabularis Redis: 127.0.0.1:16379\n\n\nAfter (Tabularis only):\n\n- Tunnel profile: SOCKS 1080 + -L 19200:internal-es-host:9200\n- ES connection: routes via local forward 19200\n- Redis connection: routes via SOCKS to 10.x.x.x:6379\n- No LaunchAgents, no Python proxies.
- Dominant language
- TypeScript
- Stars
- 5.1k
- Forks
- 335
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 62
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from TabularisDB/tabularis
-
feature request good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
TabularisDB/tabularis#853 ·
Maintainers usually reply within 1 day
-
Update the logo across the app: icons, dock, installers and in-app brandingPossibly taken @wajrock claimed this today. Openenhancement
TabularisDB/tabularis#873 · 1 assignee ·
Maintainers usually reply within 1 day
-
feature request help wanted
Difficulty 4/5 3-5 days Newbie friendliness 68/100
TabularisDB/tabularis#871 ·
Maintainers usually reply within 1 day
-
feature request good first issue
Difficulty 3/5 1-2 days Newbie friendliness 74/100
TabularisDB/tabularis#870 ·
Maintainers usually reply within 1 day
-
feature request help wanted
Difficulty 4/5 3-5 days Newbie friendliness 58/100
TabularisDB/tabularis#869 ·
Maintainers usually reply within 1 day
All issues in TabularisDB/tabularis
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
wardian-app/Wardian#1603 ·
Maintainers usually reply within 1 day
-
Sign the pledgeOpen
Difficulty 1/5 Under an hour Newbie friendliness 85/100
input-output-hk/devx-updates#168 ·
Maintainers usually reply within 1 day
-
triage
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
github/docs#46222 · 1 comment ·
Maintainers usually reply within 1 day
-
agent-ready area: config area: skills type: chore upstream: brain-kit
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
dev experience frontend good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
cuttle-cards/cuttle#1403 ·
Maintainers usually reply within 1 day