Free tool · Local forwarding · Databases
SSH tunnel command builder for Mac
Choose an example, then replace the connection details. Values stay in this page; this tool does not connect to your server or request passwords.
Run on your Mac
Use a local Terminal window, not a remote SSH terminal. Verify the SSH host key when prompted. Keep the window open; press Control-C there to stop the tunnel.
Connect your database or web client
Verify before using the connection
Check the listener on your Mac
This read-only command shows listeners visible to your account. Confirm the expected SSH process and loopback address. A listening port, or a successful TCP connection to it, does not verify the destination service. Do not kill an unfamiliar process.
Plain HTTP example: inspect the actual response
Run this in a second local Terminal only for a service that uses plain HTTP, after replacing / with a known read-only endpoint if needed. Check the expected status and content, not just curl's exit code. This example bypasses HTTP proxies and does not follow redirects. A 401/403 is an HTTP response requiring access checks; 200 from the wrong service is not success. For HTTPS, use the service's supported hostname and certificate setup; never add --insecure.
SSH login and database login are separate. Keep your database authentication and TLS requirements. This page cannot check whether the destination is reachable.
Maintaining the same server? Use Nexus Shell for its terminal, configuration files and containers. See website Pro lifetime pricing, or follow the remote file editing workflow.
Build a local SSH port-forwarding command for PostgreSQL, MySQL, Redis or a private web app. Set the SSH endpoint and the service address separately, then copy the command into your Mac's local Terminal. The generator requires no account and does not send form values to a server, store them or open a connection.
This tool is maintained by Nexus Shell, a native Mac SSH workspace. It generates commands for the system OpenSSH client. You do not need Nexus Shell to use the command.
A complete example without the builder
Suppose a PostgreSQL service listens on port 5432 on the same host that accepts your SSH login. This opens an IPv4 loopback listener on your Mac at port 15432:
ssh -N -T -o ExitOnForwardFailure=yes -o ServerAliveInterval=30 -L '127.0.0.1:15432:127.0.0.1:5432' -p 22 'developer@bastion.example'
Replace the example SSH endpoint locally and verify its host key. Keep the Terminal window open. In your database client choose host 127.0.0.1 and port 15432, and use your normal database login. Press Control-C in the tunnel's Terminal window when finished.
Which address belongs to which machine?
- Local port: a listener on your Mac. Pick an unused port; the builder uses ports above 1023 so it does not require sudo.
- SSH server: the endpoint your Mac can reach, using its SSH port and account. A configured SSH alias can supply the identity; enter the alias's SSH port explicitly in the form.
- Service host: resolved and reached from the SSH server. Here 127.0.0.1 means that server, not your Mac. For a separate database host, use an address reachable from the SSH server, such as db.internal.
- Service port: the port where the destination service listens. Changing the local port does not change the service's port.
The listener binds to 127.0.0.1 so it is not intentionally exposed on your LAN. Other local processes can still use it. SSH protects the path to the SSH server; when the service is on another host, the onward connection needs its own protection, such as database TLS. SSH authentication does not replace database authentication.
Verify the service, not just the open tunnel
The SSH process may stay quiet while forwarding. ExitOnForwardFailure catches failures to set up forwarding, but it does not prove that the SSH server can reach the destination service. Connect with the database client and perform your normal read-only connection check before relying on the tunnel.
For a web app, open its expected HTTP or HTTPS address at 127.0.0.1 and the chosen local port. Hostname routing and TLS certificates may still require the service's normal hostname configuration; do not disable certificate checks to hide a mismatch.
Tunnel active but the service is unavailable
Check three layers separately: the local listener, the SSH connection, and a response from the intended service. A successful TCP connect to the local port only proves that a process accepted it. It does not prove that forwarding reached the service. ServerAliveInterval tests SSH responsiveness, not database or HTTP health.
In a second local Mac Terminal, inspect the PostgreSQL example's listener without changing it:
lsof -nP -iTCP:15432 -sTCP:LISTEN
Confirm the expected SSH process and loopback binding. The output is limited to processes visible to your account. If a different process owns the port, choose an unused local port and update your client; do not kill an unknown process. No visible result requires checking the tunnel Terminal and the selected port, not disabling authentication or opening a public database port.
Next use SELECT 1 in your authenticated SQL client, or PING in an authenticated Redis client if permitted. Run those checks in the service client, not as shell commands. A refusal or timeout needs the service address, listening port and route checked from the SSH server. Administratively prohibited needs an administrator to verify forwarding policy. Database access denied needs the database account checked; an SSH password does not grant database privileges.
For the plain HTTP web example, first choose a known read-only endpoint on the intended service. This example uses / and local port 18080; adapt both before running it:
curl --disable --noproxy '*' --connect-timeout 3 --max-time 5 --include 'http://127.0.0.1:18080/'
Read the expected status and content. Without --fail, curl can exit successfully for HTTP 401, 403 or 500; an HTTP response does not mean authenticated access or a healthy application. HTTP 200 from the wrong service is also not success. This command bypasses HTTP proxies, ignores curl's default config, bounds the wait and does not follow redirects. It is a plain HTTP example, not a workaround for HTTPS. For HTTPS, preserve the service's supported hostname and certificate verification. Do not add --insecure or follow an unexpected redirect just to obtain a green result.
The builder's error selector and copyable checklist adapt to your chosen local port. They do not execute any probes or report your service as healthy. A reproducible loopback-only transport experiment demonstrates a listening TCP relay with an unavailable backend, an HTTP 403 response and a wrong-service HTTP 200. It is a Node TCP/HTTP fixture, not an SSH handshake, customer-server test or Nexus Shell GUI test.
Connect Sequel Ace or DBeaver through the external tunnel
The SSH command and the database client run on your Mac. Once you start this external tunnel, use a normal TCP connection in the database client. Leave its built-in SSH tunnel off for this connection. Running a second tunnel there changes which machine its host and port refer to.
For MySQL or MariaDB, select the MySQL example above. With its default local port, choose Standard in Sequel Ace, host 127.0.0.1 and port 13306. Do not select Socket or reuse port 3306 just because it is the remote database port. Enter your normal database username, password and database name only in your database client. If you change the builder's local port, update the client too.
For DBeaver, use a new connection or duplicate an existing profile for the test. Select the matching database driver, turn off its SSH tunnel, and set the Main host to 127.0.0.1 with the builder's local port: 15432 for the PostgreSQL example or 13306 for MySQL. Keep the original working profile until the new connection is verified. Keep the database's required TLS and certificate settings; an external tunnel does not remove them.
In either SQL client, connect and run this read-only query:
SELECT 1;
A result of 1 verifies that this connection can execute that query. It is not a test of application data, backups or broader permissions. A port-listening check alone cannot prove that the database behind the tunnel is reachable.
The service host may differ from the SSH host
Do not copy a hosting provider's SSH hostname into every field. A provider may require a private database hostname such as mysql, reached from the SSH server. Put that in the builder's service-host field. Your Mac client still uses 127.0.0.1 and the local port. Use the provider's documented destination and permitted forwarding policy, not a guessed public database port.
This builder handles TCP destinations. A provider that offers only a remote Unix socket needs a different forwarding setup; entering the socket path in this form is not supported. Neither configuration requires opening the database port to the public internet.
Common failures
Address already in use
The local port is occupied. Choose another local port in the builder and update your client to match. Do not terminate an unknown process just to free the port.
Administratively prohibited
The SSH account or server policy does not allow this forwarding destination. Ask the server administrator to check the permitted access; changing the local command cannot grant that permission.
Connection refused after the client connects
Check the service host and port from the SSH server's perspective. A working SSH login alone does not establish that the database is listening or reachable.
MySQL tries a local socket
Use a TCP connection to 127.0.0.1 and the forwarded port. Some MySQL clients treat localhost as a Unix socket connection, which bypasses the TCP tunnel.
Terminal SSH works but the database client's SSH connection fails
Compare the client's SSH configuration and file or agent access with Terminal. Sequel Ace documents sandbox-related limits for SSH agent sockets, key files and helper programs, and supports an external tunnel as a troubleshooting option. Use the external-tunnel setup above to separate the client's built-in SSH setup from database login. This is not a guarantee that every client or macOS update issue has the same cause.
Access denied or certificate mismatch after the tunnel opens
A database authentication error can mean the service was reached but rejected the database account. Check that account, selected database and allowed source with the administrator; do not substitute the SSH password. A TLS hostname mismatch needs the service's supported certificate and hostname configuration. Keep verification enabled. A successful SSH connection does not grant database permissions.
Keep server maintenance beside your database client
Use your database client for queries and this OpenSSH command for forwarding. Nexus Shell can complement that workflow with saved SSH connections, terminal sessions, SFTP and Docker inspection. Run the generated tunnel in a local Terminal, not inside a remote Nexus Shell session; this page does not configure a tunnel manager in the app.
For a configuration change, follow the remote file editing guide. For a container issue, use the remote Docker inspection workflow. Nexus Shell requires Apple Silicon and macOS 14.2 or later. Free use is personal and non-commercial; SFTP and other Pro features retain their licensing requirements.
References and verification
The builder validates syntax and generates a command; it cannot verify your host key, access policy, credentials or network. No connection to a customer server is made by this page.
- OpenSSH command reference: local forwarding, no-command mode and address binding.
- OpenSSH ExitOnForwardFailure: forwarding setup does not establish destination availability.
- curl command reference: status codes, proxy bypass, time limits and default configuration.
- PostgreSQL SSH tunnels: database connectivity and the boundary of tunnel encryption.
- MySQL connection methods: TCP and Unix socket selection.
- Sequel Ace remote connections: external Terminal tunnels and SSH agent or sandbox limitations.
- DBeaver SSH configuration: built-in tunnels, remote destinations and local ports.
- fortrabbit's Sequel Ace setup: an example where the database hostname differs from the SSH endpoint. Provider settings are not universal defaults.