Nexus Shell

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.

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 '[email protected]'

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?

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.

Localhost reaches the wrong service or misses the tunnel

This builder binds the Mac listener to IPv4 127.0.0.1. A client using localhost might select IPv6 ::1, or a database client might select a Unix socket instead of TCP. Those are different endpoints. The same port number on ::1 can even reach a different local service. A refusal or unexpected database is not by itself evidence that the remote server is broken.

First compare the client's actual host and port with the loopback address shown by the listener check. Use 127.0.0.1 and the builder's local port for this IPv4 tunnel. Do not disable IPv6, change /etc/hosts or bind to 0.0.0.0 to compensate. Keep the service's required TLS and hostname verification; an explicit IP address is not a certificate workaround.

MySQL localhost ignores the forwarded port

On Unix, the MySQL command-line client normally uses a Unix socket for localhost; specifying a TCP port alone does not select TCP. With the default MySQL example, use this in a second local Terminal if the MySQL client is installed:


mysql --protocol=TCP --host=127.0.0.1 --port=13306 --user=YOUR_DB_USER --password

Replace YOUR_DB_USER with the database account, then enter its password at the prompt. If the builder's local port changes, update this port too. Retain the service's TLS requirements. The interactive example above follows the selected local port; the page does not run it. In a graphical client choose its normal TCP connection mode, not Socket or a second SSH tunnel.

Psql tries a local socket instead of the tunnel

On Unix, libpq can use a Unix socket when the host is omitted. With the PostgreSQL example, explicitly select the TCP host and local port in your installed psql client:


psql --host=127.0.0.1 --port=15432 --username=YOUR_DB_USER --dbname=YOUR_DB_NAME --password

Replace both database placeholders and retain the required TLS settings. Once authenticated, SELECT 1 checks that connection's ability to execute a query; it does not establish that you reached the intended database. Also verify its identity with the service's normal read-only checks before doing work.

A reproducible loopback transport experiment distinguishes IPv4, IPv6 at the same port and a Unix socket using different response markers. It needs no server account and changes no network settings. It tests Node transports, not an SSH handshake, MySQL, PostgreSQL or a GUI client; database transport rules come from the manuals below.

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.

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.