Database & GUI clients
Point a database GUI (TablePlus, DBeaver, …) at a tailnet host through the profile that owns its suffix — without a system-wide Tailscale client.
View as MarkdownQuick answer#
Give the client a fixed loopback endpoint instead of the tailnet hostname:
- In the app — menu bar → Open → Tunnels → Add Tunnel, target
db.internal.example:5432, copy the assigned127.0.0.1:<port>into TablePlus. Always-on, managed for you. - From the command line —
tailmux tunnel --listen 127.0.0.1:15432 db.internal.example:5432, then connect to127.0.0.1:15432. Lives as long as the command runs.
Either way, TailMux resolves and dials the target inside the owning profile's tailnet and relays the bytes both ways — pure transport, like an SSH port-forward.
In the app#
- Click the TailMux menu bar icon → Open → Tunnels → Add Tunnel.
- Pick the profile (or leave it to the target's suffix), name the tunnel, and set the Target to the database's
host:port— for exampledb.internal.example:5432for Postgres. - Leave the Local endpoint blank: TailMux assigns a fixed free port from the tunnel base (default
43300, configurable under Settings → Profile defaults). The port is stable across restarts, so you configure the client once. - Click the copy button on the tunnel row and paste the endpoint into your client — e.g. in TablePlus set Host
127.0.0.1and Port to the copied port.
1Profile: work2Target: db.internal.example:54323Endpoint: 127.0.0.1:43301 (assigned for you — copy with one click)The tunnel starts automatically whenever its profile is running and appears in the menu bar with a start/stop switch and a live connection count. Tunnel edits apply live — no router restart needed.
bastion.example.ts.net), the SSH user, and how to authenticate — ssh-agent, a private key, or a password stored in the macOS Keychain. TailMux keeps a background ssh -L up for you. Details on the tunnels page.From the command line#
The same endpoint from a terminal — for scripts, for Linux, or for a one-session tunnel that ends when you close it:
$tailmux tunnel --listen 127.0.0.1:15432 db.internal.example:5432The profile is selected automatically from the host's suffix; pass --profile <name> to force one (required for raw-IP targets). The tunnel lives for as long as the command runs. Swap the port for your engine — 3306 MySQL, 1433 SQL Server, 27017 MongoDB, 6379 Redis.
Connect a terminal client to the listener:
$psql "postgresql://app@127.0.0.1:15432/appdb"Client settings#
With a tunnel running (app or CLI), point the client at the loopback endpoint:
1Host: 127.0.0.12Port: 43301 (the tunnel's assigned or chosen port)3Database: <your database>4User: <your user>Nothing about the database itself changes — credentials, TLS to the server, and permissions are exactly what they'd be from inside the tailnet.
Why the client fails without a tunnel#
A database client opens a raw TCP connection and first asks the operating system to resolve the hostname. TailMux stays at the proxy layer — it never installs a TUN device and never touches the system resolver — so a tailnet-internal name like db.internal.example is invisible to macOS: the lookup hits public DNS, returns NXDOMAIN, and the client fails before TailMux is ever involved. GUI clients also ignore HTTP_PROXY / ALL_PROXY, so tailmux run can't help either. The tunnel removes both problems: the client only ever dials 127.0.0.1, and TailMux does the resolving and dialing inside the right profile.
Why diagnostics still passes#
The Diagnostics check reporting the route as successful for db.internal.example means TailMux knows which profile owns that suffix and can dial it — resolution and dial happen inside TailMux's process, through the profile's own tailnet DNS. It does not mean your Mac's other apps can reach it. The diagnostic confirms ownership and reachability; the tunnel is what puts your client onto that route.
Notes#
- The owning profile must list the suffix (e.g.
.internal.example) under its suffixes, and — when the host sits behind a tailnet subnet router — have accept routes enabled. - Adding a suffix is a routing change: it applies on router restart. The app prompts you to restart after saving. Tunnel edits themselves are live.
- The profile must be logged in before the dial succeeds.
- Keep one endpoint per service (the app does this for you) so saved connections in your client keep working across restarts.
- The same pattern covers any raw-TCP service — RDP, SMB, Redis. For interactive SSH shells, use tailmux ssh instead of a tunnel.