Deploy SSH Bastion

Key-only SSH jump host: tunnel to private Postgres, Redis and services.

Deploy SSH Bastion

Just deployed

/data

Deploy and Host SSH Bastion on Railway

Deploy on Railway

SSH Bastion is a small, key-only OpenSSH jump host that runs inside your Railway project. It lets you reach the project's private services from your own machine: open a tunnel to postgres.railway.internal:5432, then point psql, TablePlus or your local app at localhost. Your database never needs a public TCP proxy.

About Hosting SSH Bastion

Railway services talk to each other over a private network (‹service›.railway.internal) that the internet can't reach. That's what you want for databases, but it also locks you out when you need to inspect data, run a migration from your laptop or debug an internal API. The usual workaround, a public TCP proxy on the database, exposes it to anyone who finds the port and guesses or leaks the password.

This template adds one tiny service with a TCP proxy on port 22. It's Alpine with OpenSSH, it uses about 3 MB of memory, and it has no web interface. Login is by public key only, as a regular user. Its host keys live on a volume, so the fingerprint stays the same across redeploys.

Common Use Cases

  • Connect a local database client to a private Postgres, MySQL, Redis or MongoDB with ssh -L
  • Run migrations or one-off scripts from your laptop against private services
  • Browse internal dashboards and APIs through a SOCKS proxy (ssh -D)
  • Jump to other services in the project that run sshd (ssh -J)
  • Give a teammate temporary access with their GitHub keys, then remove it

Dependencies for SSH Bastion Hosting

  • None. It's a single service, and it should go in the same project and environment as the services you want to reach.

Deployment Dependencies

Implementation Details

Add it to the right project. A private network only spans one project environment. Inside the project that holds your database, click Create → Template and pick SSH Bastion. A new project from the Deploy button can only reach its own services.

Set AUTHORIZED_KEYS. Use your public key (the output of cat ~/.ssh/id_ed25519.pub), one key per line. You can also write github:‹username› to use the keys on that GitHub account; they're re-read on every deploy. Lines that aren't keys are skipped, and the deploy log says so.

Connect. The deploy log prints the exact command, and the address is also under Settings → Networking → TCP Proxy:

ssh -p ‹port› railway@‹domain›.proxy.rlwy.net

The log also lists the host key fingerprints, so you can check them on your first connection.

Tunnel to a private Postgres, then connect to it locally. The user and password come from the database's Variables tab:

ssh -N -L 5432:postgres.railway.internal:5432 -p ‹port› railway@‹domain›.proxy.rlwy.net
psql "postgresql://postgres:‹password›@localhost:5432/railway"

Other examples:

# Redis on local port 6380
ssh -N -L 6380:redis.railway.internal:6379 -p ‹port› railway@‹domain›.proxy.rlwy.net

# SOCKS proxy (with remote DNS, e.g. curl --socks5-hostname): reach http://api.railway.internal:8080
ssh -N -D 1080 -p ‹port› railway@‹domain›.proxy.rlwy.net

# Jump to another service in the project that runs sshd
ssh -J railway@‹domain›.proxy.rlwy.net:‹port› root@box.railway.internal

Save it in ~/.ssh/config so a plain ssh railway-db opens the tunnel:

Host railway-db
  HostName ‹domain›.proxy.rlwy.net
  Port ‹port›
  User railway
  LocalForward 5432 postgres.railway.internal:5432
  ServerAliveInterval 30

The shell has dig, nc and curl for checking a target from inside the network, for example nc -zv postgres.railway.internal 5432. Your home directory is on the volume, so scp and sftp work for moving files in and out.

Security:

  • Keys only: password and keyboard-interactive logins are off, and root can't log in.
  • The key list is root-owned, so a session can't add keys.
  • Remote forwards (-R), agent forwarding and X11 are off.
  • Each login is logged with the fingerprint of the key used.
  • To lock everyone out, empty AUTHORIZED_KEYS and redeploy, or remove the TCP proxy.

Limits:

  • TCP only. Railway's TCP proxy carries no UDP.
  • Tunnel traffic counts as egress on the bastion service, the same as a public database proxy would.

Other templates by the same author: for a full Linux machine rather than a bastion, see Linux and Linux Terminal.

Why Deploy SSH Bastion on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying SSH Bastion on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.


Template Content

More templates in this category

View Template
Rocky Linux
Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀

codestorm
51
View Template
Foundry Virtual Tabletop
A Self-Hosted & Modern Roleplaying Platform

Lucas
71
View Template
Letta Code Remote
Run a Letta Code agent 24/7. No inbound ports, just deploy.

Letta
51