Client Setup
Configure the .pod namespace and multi-server routing
The podspawn client binary is optional. Without it, you SSH directly to your server's hostname and get a container. The client adds two things: the .pod namespace for friendly hostnames, and multi-server routing so work.pod and gpu.pod can point to different machines.
The .pod namespace
Instead of remembering server hostnames:
ssh alice@devbox.company.com
ssh alice@gpu-server.company.comYou type:
ssh alice@work.pod
ssh alice@gpu.podThe .pod suffix is not a real TLD -- it never hits DNS. Your SSH client's ProxyCommand intercepts it before resolution and routes to the real server.
Automatic setup
podspawn setupThis appends a block to ~/.ssh/config:
Host *.pod
ProxyCommand podspawn connect %r %h %p
SetEnv PODSPAWN_PROJECT=%n
SendEnv PODSPAWN_PROJECT
UserKnownHostsFile /dev/null
StrictHostKeyChecking noIf the block already exists, setup skips it:
$ podspawn setup
~/.ssh/config already has Host *.pod block, skippingsetup creates ~/.ssh/ and ~/.ssh/config if they don't exist. It appends to the file -- it never overwrites existing config.
Manual setup
If you don't want to install the client binary, add this to ~/.ssh/config yourself:
Host *.pod
ProxyCommand podspawn connect %r %h %p
SetEnv PODSPAWN_PROJECT=%n
SendEnv PODSPAWN_PROJECT
UserKnownHostsFile /dev/null
StrictHostKeyChecking noYou still need the podspawn binary in your PATH for the ProxyCommand to work.
Without the client binary at all
Skip the .pod namespace entirely and SSH directly:
ssh alice@devbox.company.comAll SSH features work. You lose the friendly hostnames and multi-server routing, but nothing else.
Client configuration
Create ~/.podspawn/config.yaml to tell the connect command which server backs each .pod hostname:
servers:
default: devbox.company.com
mappings:
work.pod: devbox.company.com
gpu.pod: gpu-server.company.com
personal.pod: my-homelab.ddns.netHow routing works
When you run ssh alice@work.pod:
- SSH matches
Host *.podand runspodspawn connect alice work.pod 22 connectreads~/.podspawn/config.yaml- It checks
servers.mappingsforwork.pod-- findsdevbox.company.com - Opens a TCP connection to
devbox.company.com:22and relays the SSH traffic
If a .pod hostname isn't in mappings, the default server is used. If neither matches, connect exits with an error:
no server configured for "staging.pod" (add it to servers.mappings or set servers.default)Single-server shortcut
If all your .pod hostnames point to one server, you only need default:
servers:
default: devbox.company.comNow ssh alice@anything.pod routes to devbox.company.com. The hostname before .pod is passed to the server as the project name -- so work.pod and frontend.pod still create separate containers.
The client config file must exist at ~/.podspawn/config.yaml for .pod routing to work. Without it, podspawn connect fails with "client config not found."
The project name
The part before .pod is the project name. When you SSH to backend.pod, the server receives "backend" as the project identifier. The server uses this to:
- Look up project-to-repo mappings in its config
- Create separate containers per project (alice's
work.podandbackend.podare different containers) - Resolve Podfile environments from the mapped repository
The SetEnv PODSPAWN_PROJECT=%n line in the SSH config block passes the full hostname (e.g., backend.pod) as an environment variable. The server's AcceptEnv PODSPAWN_PROJECT directive (added by server-setup) allows it through.
Verifying the setup
# Check SSH config
grep -A5 "Host \*.pod" ~/.ssh/config
# Check client config
cat ~/.podspawn/config.yaml
# Test the connection
ssh alice@work.pod