---
title: "Deploy SSH Bastion"
description: "Key-only SSH jump host: tunnel to private Postgres, Redis and services."
category: "Other"
url: https://railway.com/deploy/ssh
---

# Deploy SSH Bastion

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

**[Deploy SSH Bastion on Railway](https://railway.com/template/ssh)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/ssh/manifest.json

- **Creator:** Two Workspaces
- **Category:** Other

## Template content

### ssh-bastion https://raw.githubusercontent.com/two-workspaces/ssh/main/images/icon.svg

- **Image:** ghcr.io/two-workspaces/ssh:afe7530

## Documentation

# Deploy and Host SSH Bastion on Railway

[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/ssh?referralCode=sLjDXb&utm_medium=integration&utm_source=button&utm_campaign=ssh)

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

- [OpenSSH](https://www.openssh.com/) on [Alpine Linux](https://alpinelinux.org/)
- [Railway private networking](https://docs.railway.com/guides/private-networking)

### 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](https://railway.com/deploy/linux?referralCode=sLjDXb) and [Linux Terminal](https://railway.com/deploy/ubuntu-terminal?referralCode=sLjDXb).

## 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.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/ssh
