Skip to content

fix(ssh): derive relay host/port from RAILWAY_ENV instead of hardcoding prod#936

Closed
codyde wants to merge 1 commit into
masterfrom
fix/ssh-relay-env-switching
Closed

fix(ssh): derive relay host/port from RAILWAY_ENV instead of hardcoding prod#936
codyde wants to merge 1 commit into
masterfrom
fix/ssh-relay-env-switching

Conversation

@codyde
Copy link
Copy Markdown
Collaborator

@codyde codyde commented Jun 4, 2026

Problem

The SSH relay host was a compile-time constant (ssh.railway.com) while backboard URLs follow RAILWAY_ENV. A dev-mode CLI therefore registers SSH keys and creates sandboxes against the develop backboard but dials the production relay — which has never seen the key or the target — yielding a confusing Permission denied (publickey) for a key the CLI just said was registered.

Reported by Pierre in raildev:

$ railway sandbox ssh
Using SSH key from agent: pborckmans@gmail.com
sbx:f597…:343d…@ssh.railway.com: Permission denied (publickey).

Manual workaround that proved the diagnosis: ssh -p 2222 sbx:…@ssh.railway-develop.com connects fine.

Fix

Configs::get_ssh_relay() mirrors backboard's controllers/ssh mapping:

env relay
production ssh.railway.com (port 22)
staging ssh.railway.com — falls through like backboard's IS_DEV-only branch (ssh.railway-staging.com does not serve the SSH relay; probes accept TCP then close)
dev ssh.railway-develop.com -p 2222

Applied everywhere the constant was used: native ssh (railway ssh, railway sandbox ssh), tmux install/session, the generated ~/.ssh/config block (gains a Port line only when non-default), and volume SFTP (russh connect tuple).

Risk

Production behavior is byte-identical by construction: ("ssh.railway.com", None) produces the same target string, adds zero ssh args, the same (host, 22) sftp tuple, and the same config block — the existing config-block tests asserting the literal prod output pass unmodified. The only behavioral change is dev mode, which previously failed 100% of the time.

Testing

  • Full test suite green (214)
  • Prod smoke test on the built binary: sandbox createsandbox ssh -- echodestroy, all clean
  • Dev-mode verification: Pierre has a reliable raildev repro; plain railway sandbox ssh should now connect exactly where his manual -p 2222 command did

🤖 Generated with Claude Code

…ng prod

The SSH relay was a compile-time constant (ssh.railway.com) while
backboard URLs follow RAILWAY_ENV — so a dev-mode CLI registered keys
and created sandboxes against the develop backboard but dialed the
production relay, which rejected the (correctly registered) key with
'Permission denied (publickey)'.

Mirror backboard's controllers/ssh mapping: dev → ssh.railway-develop.com
-p 2222; staging falls through to the prod relay exactly like backboard's
IS_DEV-only branch (probes show ssh.railway-staging.com does not serve
the SSH relay). Applies to native ssh, tmux sessions, the generated
~/.ssh/config block (Port line when non-default), and volume SFTP.

Production behavior is byte-identical: (ssh.railway.com, None) produces
the same target string, zero extra args, and the same config block —
existing config-block tests pass unmodified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codyde
Copy link
Copy Markdown
Collaborator Author

codyde commented Jun 4, 2026

Folding this into #933 — the fix originated on that branch and will ship with the sandbox release.

@codyde codyde closed this Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant