SSH bastion setup
For tenants whose security policy doesn't allow direct IP allowlisting,
we connect through your SSH bastion. We never accept inbound traffic;
every connection is initiated outbound from us to your bastion. The
private key stays on our side; you install only the public key on
the bastion's authorized_keys file.
1. Bastion sizing
A small VM is fine — 1 vCPU, 1 GB RAM, your distro of choice. Each extract opens one SSH session and closes it on completion. We never keep persistent tunnels.
2. Allow inbound SSH from us
Allow inbound TCP 22 (or whatever non-default port you've
chosen for SSH) from
our static egress IPs (sign-in required).
That's the only inbound rule we need.
3. Create a dedicated user
Recommended: a Linux user account that exists only for our tunnels.
Pick anything you like — elglide /
letitsnow / etl-svc. The user needs login
permission but doesn't need a password (we only authenticate via key)
and doesn't need sudo.
sudo useradd -m -s /bin/bash elglide
sudo passwd -l elglide # disable password login; key auth only
sudo mkdir -p /home/elglide/.ssh
sudo chmod 700 /home/elglide/.ssh
sudo touch /home/elglide/.ssh/authorized_keys
sudo chmod 600 /home/elglide/.ssh/authorized_keys
sudo chown -R elglide:elglide /home/elglide/.ssh
4. Generate the keypair (in our portal)
From Account → SSH Tunnels (sign-in required) click + New SSH tunnel. Fill in the bastion host, port, username, and key type (Ed25519 is preferred — modern, smaller, faster; pick RSA-4096 only if your bastion is older and rejects Ed25519). We generate the keypair on save and show you the public key.
5. Install the public key on the bastion
Append the public key to ~/.ssh/authorized_keys for the
user you created. We strongly recommend the following hardening
directives to scope down what we can do — we only need port
forwarding, never a shell:
Replace <your-public-key> with the
key shown in the portal, and DB_HOST:DB_PORT with the
internal address of your source database from the bastion's
perspective:
command="echo not allowed",no-pty,no-X11-forwarding,no-agent-forwarding,no-user-rc,permitlisten="DB_HOST:DB_PORT" <your-public-key>
The command="echo not allowed" + no-pty
directives ensure the key can't be used to open an interactive shell.
permitlisten restricts us to forwarding to that single
DB host:port — we can't pivot to anything else on your network with
this key.
6. Configure the source DB connection
From Connections (sign-in required) → Edit / Create. Pick SSH Tunnel in the Connectivity section and select the tunnel you just made. Click Diagnose to run the 4-step test (network → SSH → database → permissions).
7. Replacing the public key (rotation)
We rotate keys periodically (or on demand) — Account → SSH Tunnels → the rotate icon. Choose Rotate the shared key to swap one key across every Connection that uses this tunnel, or Detach a specific source to give just one Connection its own fresh keypair while the others keep their existing one.
After clicking, we show you the new public key + the install line.
Until you replace the old line in authorized_keys on the
bastion, every sync that uses this tunnel will fail with
Permission denied (publickey).
Every key we issue ends with a comment of the form
elglide-tenant-<N>, where
<N> is your tenant id (visible in the portal).
That comment is how you identify which line to replace.
Replace <bastion-user> with the user you created
in step 3, <your-new-public-key> with the freshly
shown key, and DB_HOST:DB_PORT with your source
database's internal address:
sudo -u <bastion-user> sed -i '/elglide-tenant-<N>/d' ~<bastion-user>/.ssh/authorized_keys
echo 'command="echo not allowed",no-pty,no-X11-forwarding,no-agent-forwarding,no-user-rc,permitlisten="DB_HOST:DB_PORT" <your-new-public-key>' | sudo -u <bastion-user> tee -a ~<bastion-user>/.ssh/authorized_keys
sudo -u <bastion-user> chmod 600 ~<bastion-user>/.ssh/authorized_keys
Then re-run the Diagnose modal on the Connection — the SSH step
should turn green within seconds. No bastion restart needed; sshd
re-reads authorized_keys on every connection.
8. Windows bastion (OpenSSH Server)
If your bastion runs Windows OpenSSH Server, the file location depends on which group the bastion user belongs to:
-
If your bastion user is in the
Administrators group, sshd typically reads
C:\ProgramData\ssh\administrators_authorized_keys. This file is writable from any elevated PowerShell — no extra steps. Recommended: create a non-admin local user for the tunnel instead; it's safer and simpler. -
For a non-admin user (or any user with an explicit
Match User <name>block insshd_config), sshd readsC:\Users\<name>\.ssh\authorized_keys. That file has a strict ACL: only the user themself andSYSTEMcan read it. Admins cannot. Editing requires either logging in as that user, or temporarily taking ownership:
# In an elevated PowerShell. Replace <bastion-user> with your tunnel user.
$path = "C:\Users\<bastion-user>\.ssh\authorized_keys"
# Take ownership + grant Admin write temporarily
takeown /F $path /A
icacls $path /grant Administrators:F
# Edit: remove any old elglide-tenant-<N> line, append the new key.
notepad $path
# Restore — critical. OpenSSH StrictModes rejects auth if Admins retains access.
icacls $path /setowner <bastion-user>
icacls $path /remove Administrators
# Sanity check: should return "Access is denied" from your Admin shell.
# That confirms the strict ACL is back.
icacls $path
If icacls in the last step prints the ACL (instead of
denying), Administrators still has access and sshd will refuse the
key on next auth attempt. Re-run the remove line.
Troubleshooting
| Diagnose step shows… | Most likely cause | Fix |
|---|---|---|
| ✗ Network reachability — TCP refused | Inbound firewall blocks our IPs | Allow our static IPs on the bastion's SSH port |
| ✗ Network reachability — timeout | Wrong bastion hostname or no public DNS | Use the bastion's public IP or a resolvable DNS name |
| ✗ SSH tunnel — Permission denied (publickey) | Public key not installed, wrong username, or
authorized_keys file permissions wrong |
Verify the user exists, the public key matches, and file
perms are 600 (the dir 700) |
✗ SSH tunnel — open failed: permitlisten |
permitlisten doesn't include the DB host:port |
Update authorized_keys to add the right
DB_HOST:DB_PORT |
| ✗ Database access — login failed | DB credentials are wrong (everything before this passed, so the bastion is fine) | Update the username/password on the Connection |
| ✗ Permissions check — SELECT denied | The DB user can connect but lacks SELECT on
INFORMATION_SCHEMA / information_schema |
Grant SELECT on the metadata views (or use a role with schema-discovery privileges) |
| ✗ SSH tunnel — Permission denied (publickey) after a rotation | Old elglide-tenant-<N> line still in
authorized_keys; sshd is matching the old
key, not the new one |
Delete the old line; keep only the freshly-shown one. Section 7 above. |
| ✗ SSH tunnel — Permission denied (publickey) on a Windows bastion | Wrong authorized_keys file edited (per-user
vs admin), OR icacls never revoked
Administrators access after takeown |
Confirm which file your sshd reads (see Section 8), and verify the final ACL is "denied" to Administrators |
Still stuck? Open the failed step in the Diagnose modal and click Show details — the technical detail there includes the exact driver error, which is what to share when filing a support ticket.