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.

Prefer not to run a bastion? See Direct connection — IP allowlist (sign-in required) for the simpler path.

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 in sshd_config), sshd reads C:\Users\<name>\.ssh\authorized_keys. That file has a strict ACL: only the user themself and SYSTEM can 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.