SSH Tunnels
Reach a MariaDB server that is only accessible through SSH, with a mariadb+ssh:// URI or with the --ssh options.
Database servers are often not reachable from your workstation: they listen only on their loopback interface, or sit in a private network behind a bastion host. MariaDB Shell can open an SSH tunnel for such a connection itself, so you don't need to run ssh -L in another terminal.
You can describe a tunnel in two ways:
- With a
mariadb+ssh://URI, which carries the whole connection, tunnel included, in one string. This is the recommended form. - With the older
--sshcommand-line options or thesshdictionary key, which describe the tunnel separately from the database URI.
MariaDB Shell uses its built-in SSH client for the tunnel. It doesn't need the ssh command.
Tunnel URIs
Add +ssh to the scheme to tunnel a connection: mariadb+ssh://, or mysql+ssh:// for the same thing written the MySQL way. In a tunnel URI, the user, host, and port always describe the database: the account, the database server, and its port. The SSH connection is described by ssh-* options in the query string.
There are two cases, depending on where the database runs:
mariadb+ssh://dba@db1.example.com:3306
mariadb+ssh://dba@db-01.internal:3306?ssh-host=bastion.example.com
- The database runs on the SSH host. Leave out
ssh-host. MariaDB Shell opens the SSH connection to the host in the URI,db1.example.com, and forwards the database connection to127.0.0.1on that machine. This works for a server that listens only on its loopback interface, which is a common reason to use a tunnel. - The database runs behind the SSH host. Set
ssh-hostto the SSH host, such as a bastion. MariaDB Shell opens the SSH connection tobastion.example.com, and forwards the database connection from there todb-01.internal:3306. The SSH host resolves the database host name, so you can use names and addresses of the private network.
Because the host in the URI always means the database server, whether ssh-host is set or not, a tunnel URI has only one reading.
SSH Options
| Option | Default | Description |
|---|---|---|
ssh-host | The host in the URI | The SSH host. When you set it, the tunnel forwards to the host in the URI instead of to 127.0.0.1. |
ssh-user | The operating system user that runs MariaDB Shell | The user on the SSH host. A User setting for the host in the OpenSSH configuration file takes precedence over this default. |
ssh-port | 22 | The SSH port, from 1 to 65535. |
ssh-identity-file | The default keys and the SSH agent | The private key file to authenticate with. |
ssh-config-file | The ssh.configFile shell option, or ~/.ssh/config | An OpenSSH configuration file to read the settings for the SSH host from. |
The database port defaults to 3306. Encode file paths in the query string, or enclose them in parentheses. A leading ~ in a path is expanded to your home directory. The identity file must exist when the URI is parsed.
The ssh-* options are valid only with a +ssh scheme. On a mariadb:// URI, MariaDB Shell rejects them:
Invalid URI: The connection option 'ssh-user' requires an SSH tunnel. Use the '+ssh' scheme extension, as in 'mariadb+ssh://'.
Passwords Aren't Part of the URI
A URI can't contain the SSH password or the passphrase of a key. The options ssh-password and ssh-identity-file-password are rejected in a URI with The connection option '...' cannot be set in a URI. A URI names a connection, and MariaDB Shell displays it and writes it to logs, so the SSH secrets are kept out of it. MariaDB Shell prompts for the secrets it needs instead, or takes them from the credential store. See Authentication.
Examples
A server that listens only on 127.0.0.1, reached by SSH on the server itself:
mariadb+ssh://dba@db1.example.com
A server in a private network behind a bastion host, with a dedicated user and key for the tunnel:
mariadb+ssh://dba@db-01.internal:3306?ssh-host=bastion.example.com&ssh-user=tunnel&ssh-identity-file=(~/.ssh/tunnel_ed25519)
An SSH host defined in your OpenSSH configuration, which also supplies the user, port, and key:
Host bastion
HostName bastion.example.com
User tunnel
Port 2222
IdentityFile ~/.ssh/tunnel_ed25519
mariadb+ssh://dba@db-01.internal?ssh-host=bastion
Using a Tunnel URI
Pass a tunnel URI to shell.connect(), shell.open_session(), or any other Python function that takes connection data:
shell.connect("mariadb+ssh://dba@db-01.internal?ssh-host=bastion.example.com")
MariaDB Shell reports the tunnel before it prompts for the database password:
Opening SSH tunnel to bastion.example.com:22...
Please provide the password for 'dba@db-01.internal:3306':
session.uri and \status show the defaulted SSH settings that were filled in:
MariaDB db-01.internal:3306 ssl Py > session.uri
mariadb+ssh://dba@db-01.internal:3306?ssh-host=bastion.example.com&ssh-user=jdoe&ssh-port=22
A tunnel URI keeps its tunnel through shell.parse_uri() and shell.unparse_uri(). The dictionary carries mariadb+ssh as the scheme, and only the SSH settings that were set.
In MariaDB Shell 26.9.5, the mariadb-shell command line and the \connect command don't accept tunnel URIs yet: they fail with Scheme extension [ssh] is not supported. To open a tunnel from the command line, use the older SSH options. In a script run with mariadb-shell --py -f, or after starting mariadb-shell --py, call shell.connect() with the tunnel URI.
Authentication
MariaDB Shell tries the following SSH authentication methods, in this order, until one succeeds:
- Public key authentication. With
ssh-identity-file, MariaDB Shell uses that key, and prompts for its passphrase if the key is encrypted. Without it, MariaDB Shell tries the keys that the SSH agent offers and your default key files, such as~/.ssh/id_ed25519and~/.ssh/id_rsa. - Password authentication. MariaDB Shell looks for a stored password for
ssh://user@host:portin the credential store, and otherwise prompts for it. - Keyboard-interactive authentication, which shows the prompts that the SSH server sends. This method is skipped when MariaDB Shell runs with
--no-wizard.
Each method runs only if the SSH server offers it. SSH passwords and key passphrases that you type can be saved in the credential store like database passwords. If a stored SSH password is rejected, MariaDB Shell deletes it.
For scripts and other runs without a terminal, use a key that MariaDB Shell can use without a prompt: an unencrypted key file, or a key loaded into the SSH agent.
Host Keys
MariaDB Shell checks the SSH host's key against your known-hosts file, ~/.ssh/known_hosts. If the host is unknown, it shows the key fingerprint and asks whether to continue:
The authenticity of host 'bastion.example.com' can't be established.
Server key fingerprint is ...
Are you sure you want to continue connecting?
If you answer Yes, MariaDB Shell adds the key to the known-hosts file. Without a terminal to ask, it refuses the connection to an unknown host. If the host key has changed since it was recorded, MariaDB Shell warns that the public key has changed and refuses the connection. To prepare a host for scripts, add the host key beforehand, for example with ssh-keyscan bastion.example.com >> ~/.ssh/known_hosts, after you have checked the fingerprint.
Listing Open Tunnels
MariaDB Shell keeps a tunnel open while sessions use it. When you open another session with the same SSH settings and target, MariaDB Shell reuses the existing tunnel. shell.list_ssh_connections() lists the open tunnels:
MariaDB db-01.internal:3306 ssl Py > shell.list_ssh_connections()
[
{
"remote": "db-01.internal:3306",
"timeCreated": "2026-10-05T16:55:46",
"uri": "jdoe@bastion.example.com:22"
}
]
The uri entry is the SSH endpoint, and remote is the database address that the tunnel forwards to.
The Older SSH Options
Before tunnel URIs existed, a tunnel was described separately from the database URI. These forms still work, and they are the way to open a tunnel from the mariadb-shell command line.
On the command line:
| Option | Description |
|---|---|
--ssh=<[user@]host[:port]> | The SSH host to tunnel through. |
--ssh-identity-file=<file> | The private key file. |
--ssh-config-file=<file> | The OpenSSH configuration file. Sets the ssh.configFile shell option for the session. |
mariadb-shell --ssh tunnel@bastion.example.com dba@db-01.internal:3306 --sql
\connect accepts --ssh in the same way:
\connect --ssh tunnel@bastion.example.com dba@db-01.internal:3306
In a connection dictionary:
| Key | Description |
|---|---|
ssh | The SSH host, as [user@]host[:port]. |
ssh-password | The SSH password. |
ssh-identity-file | The private key file. |
ssh-identity-file-password | The passphrase of the key file. |
ssh-config-file | The OpenSSH configuration file. |
session = shell.open_session({
"uri": "dba@db-01.internal:3306",
"ssh": "tunnel@bastion.example.com:22",
"ssh-identity-file": "~/.ssh/tunnel_ed25519",
})
In these forms, the database host is always resolved by the SSH host, as with ssh-host in a tunnel URI. To reach a server that listens on the SSH host's loopback interface, use 127.0.0.1 as the database host.
Always include the user in --ssh and in the ssh key. Without it, these older forms can fall back to a different account than the one you are logged in as, such as root, in sessions that were opened by another account, for example by a CI runner. Tunnel URIs don't have this problem: they default to the user that runs MariaDB Shell.
Related Shell Options
| Option | Type | Default | Description |
|---|---|---|---|
ssh.configFile | string | empty | The default OpenSSH configuration file. If it is empty, ~/.ssh/config is used. |
ssh.bufferSize | integer | 10240 | The buffer size for tunnel data transfer, in bytes. |