---
title: "Deploy Ubuntu Dev Box (SSH + Claude Code)"
description: "Persistent Ubuntu 24.04 dev box: SSH + browser terminal, Claude Code"
category: "Other"
url: https://railway.com/deploy/kit-ubuntu-ssh-skeleton-0919
---

# Deploy Ubuntu Dev Box (SSH + Claude Code)

Persistent Ubuntu 24.04 dev box: SSH + browser terminal, Claude Code

**[Deploy Ubuntu Dev Box (SSH + Claude Code) on Railway](https://railway.com/template/kit-ubuntu-ssh-skeleton-0919)**

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

- **Creator:** Will
- **Category:** Other

## Template content

### Ubuntu https://devicons.railway.com/i/ubuntu.svg

- **Image:** ghcr.io/will-bogusz/railway-ubuntu-ssh:24.04-20260920b@sha256:ebaafc81557b7294a2b13d08986173efacab19d3004c2ac40074753dbcf6136c
- **Health check:** /healthz
- **Public domain:** Yes

## Documentation

# Deploy and Host an Ubuntu Dev Box (SSH + Claude Code) on Railway

A persistent Ubuntu 24.04 LTS dev box you reach over **SSH** (from Termius, Blink, VS Code Remote or any client) or a **browser terminal**, with **Claude Code** preinstalled and your home directory on a **volume** that survives every redeploy — the thing most SSH templates here lack. One click, no inputs: the password is generated for you. Node.js 24 LTS, Python 3, git, GitHub CLI, build-essential, tmux and the usual tools are included; `dev` has passwordless `sudo`.

**Plan requirements.** Idle, the box uses about **23 MB** of RAM (measured on this image: 23 MB after five idle minutes, 31 MB peak at boot) and is well under Railway's Free and Trial limits. Claude Code sessions add a few hundred MB while they run; builds and language servers add whatever they need. Hobby is the comfortable fit for daily use. The image is pinned by digest, so what you deploy today is what you get on every redeploy.

## About Hosting an Ubuntu SSH Workstation

The service runs three small processes: `sshd` on port 22 behind a Railway TCP proxy, `ttyd` (a terminal in your browser) behind `nginx` with basic auth on the public HTTPS domain, and a supervisor that exits if any of them dies so Railway's restart policy takes over. Login is user `dev` with the generated `SSH_PASSWORD` or your public key; root login is disabled, and failed logins are throttled per source address (with `fail2ban` banning a source after 5 failures when the container has the capability, sshd's own per-source limits otherwise). `/home/dev` is a Railway volume, so projects, dotfiles, Claude Code's own state (`~/.claude`), tools you install and even the SSH host keys persist across redeploys. Railway's healthcheck (`/healthz`) only passes once the terminal actually answers.

## Common Use Cases

- **Claude Code from anywhere.** SSH in from a laptop, or open the browser terminal from a phone or a locked-down machine, and keep an agent session running in tmux while you are away.
- **A persistent Linux scratch box.** Clone a repo, install what you need, leave it for a week, come back to the same shell.
- **A cheap always-on dev environment.** Point VS Code Remote-SSH or JetBrains Gateway at it; the box costs cents a day while idle.
- **Long-running jobs without a laptop.** Data pulls, builds and scripts that outlive a local terminal session.

## Dependencies for Ubuntu SSH Workstation Hosting

None. A single service with one volume. Claude Code needs an Anthropic account: an API key or a Claude subscription login, both optional at deploy time.

### Deployment Dependencies

- [Image source and runtime contract](https://github.com/will-bogusz/railway-ubuntu-ssh)
- [Claude Code documentation](https://docs.claude.com/en/docs/claude-code)
- [ttyd](https://github.com/tsl0922/ttyd) (browser terminal)
- [Railway TCP proxying](https://docs.railway.com/networking/tcp-proxy)
- [Railway volumes](https://docs.railway.com/volumes)

### Implementation Details

**Connecting over SSH.** Open the service, then **Settings → Networking → TCP Proxy**: it shows a host and port. Connect with

```bash
ssh dev@your-service.proxy.rlwy.net -p 12345
```

The password is `SSH_PASSWORD` in the service's **Variables** tab (Railway generated it at deploy). The deploy log also prints the exact `ssh` line once at boot. Host keys are stored on the volume, so a redeploy will not trigger a host-key-changed warning.

**Connecting from the browser.** Open the service's public URL. Sign in with user `dev` and the same `SSH_PASSWORD`. You land in a tmux session named `main`: close the tab and reopen it later and the session, and anything running in it, is still there. Works from a phone.

**Adding SSH keys.** Either paste public keys into the `AUTHORIZED_KEYS` variable (one per line) and redeploy, or, once you are in, append them to `~/.ssh/authorized_keys` on the volume. Password login stays enabled; to turn it off, add `PasswordAuthentication no` to `/etc/ssh/sshd_config.d/20-local.conf` — note that this file lives in the image layer and is reset on redeploy, so keep it in the volume and symlink it from `~/.bashrc` if you need it permanent, or just use a long generated password.

**Claude Code.** Run `claude`. With no key set it offers the Claude subscription login: open the link it prints on any device, paste the code back. The login is stored in `~/.claude` on the volume, so you do it once. To use an API key instead, set `ANTHROPIC_API_KEY` in the Variables tab and redeploy. The pinned copy in the image is Claude Code 2.1.278; to move to the latest, run `curl -fsSL https://claude.ai/install.sh | bash` — it installs into `~/.local/bin` on your volume, which is first on `PATH`.

**Codex, opencode and other tools.** `npm install -g @openai/codex` or `npm install -g opencode-ai` install into `~/.npm-global` on the volume without `sudo`. `pip`, `pipx`, `uv`, `cargo` and anything under `~/.local` persist the same way. For apt packages use `sudo apt-get install`; those live in the container layer and are gone after a redeploy, so put the command in a script on the volume if you rely on them.

**GitHub.** Set `GITHUB_TOKEN` and both `git` (HTTPS clone/push to github.com) and `gh` authenticate with it. Or run `gh auth login` interactively; its state persists on the volume too.

**Environment variables.** Every variable you add in the Variables tab is exported into your SSH and browser sessions after the next deploy, except `SSH_PASSWORD`. That is how `ANTHROPIC_API_KEY`, `GITHUB_TOKEN`, `TZ` and anything else of your own reach the shell.

**What persists and what does not.** Persists: everything under `/home/dev` (projects, dotfiles, `~/.claude`, `~/.local`, `~/.npm-global`, `~/.ssh`), and the SSH host keys. Does not persist: apt packages, files outside `/home/dev`, and running processes (a redeploy restarts the container, so tmux sessions end). Redeploying a service with a volume involves a few seconds of downtime; that is a Railway volume property, not a template setting.

**Rotating the password.** Change `SSH_PASSWORD` in the Variables tab; the next deploy applies it to SSH and the browser terminal together.

**Cost.** Railway bills RAM and CPU by the minute. Measured on this image: 22 MB idle, which is about $0.25/month at Railway's published rates before any work you run. Claude Code and builds add usage while active. There is nothing here that keeps the box busy on its own.

**Security notes.** The box is a real Linux machine on the public internet: SSH is exposed through Railway's TCP proxy (with a 24-character generated password, root login disabled, four tries per connection) and the browser terminal through HTTPS basic auth. Keys are better than passwords; add yours. `dev` has passwordless `sudo` inside the container, which is the point of a dev box, not a hole in one. This template is for personal development use; running it as a shared shell service or reselling access is outside Railway's Fair Use policy.

### Why Deploy an Ubuntu SSH Workstation 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 an Ubuntu SSH Workstation 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/kit-ubuntu-ssh-skeleton-0919
