podspawnpodspawn

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

You type:

ssh alice@work.pod
ssh alice@gpu.pod

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

Setup

Install the client binary

podspawn setup

This 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 no

If the block already exists, setup skips it:

$ podspawn setup
~/.ssh/config already has Host *.pod block, skipping

setup creates ~/.ssh/ and ~/.ssh/config if they don't exist. It appends to the file -- it never overwrites existing config.

After running setup, your SSH directory looks like this:

config
id_ed25519
id_ed25519.pub

Configure server routing

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.net
config.yaml

Connect

ssh alice@work.pod

Client configuration

Mappings can also use an object format to include the server's session mode. This is purely informational on the client side (the server controls the actual behavior), but it shows up in podspawn servers output so you know which servers persist your files:

servers:
  default: devbox.company.com
  mappings:
    work.pod:
      host: devbox.company.com
      mode: persistent
    gpu.pod:
      host: gpu-server.company.com
      mode: ephemeral
    personal.pod: my-homelab.ddns.net

Both formats can be mixed in the same config. The string format (personal.pod: my-homelab.ddns.net) is shorthand for {host: my-homelab.ddns.net}.

The mode field is informational: ephemeral means the container is destroyed after disconnect, persistent means it stays alive and files survive. The server controls actual behavior.

How routing works

When you run ssh alice@work.pod:

  1. SSH matches Host *.pod and runs podspawn connect alice work.pod 22
  2. connect reads ~/.podspawn/config.yaml
  3. It checks servers.mappings for work.pod -- finds devbox.company.com
  4. Opens a TCP connection to devbox.company.com:22 and 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.com

Now 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.pod and backend.pod are 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

# List servers with connectivity and mode
podspawn servers
  (default)            devbox.company.com                         ok (12ms)
  gpu.pod              gpu-server.company.com   ephemeral     ok (45ms)
  work.pod             devbox.company.com       persistent    ok (11ms)
# Test the connection
ssh alice@work.pod

Next steps

How is this guide?

On this page