podspawnpodspawn

Admin Commands

CLI reference for podspawn machine management and monitoring commands

These commands manage machines and monitor system health. list, stop, and doctor work in both local and server mode. The rest (cleanup, status, etc.) are server-side administration commands.

stop, remove-user --force, and remove-project are destructive operations that immediately destroy containers. Connected sessions will be terminated and unsaved work lost.

list

Lists all machines (local mode) or active sessions (server mode) tracked in the state database.

podspawn list

Local mode output

In local mode, list shows machines with their name, status, image, and age. No internal container names are shown:

NAME       STATUS         IMAGE           AGE
mydev      running        ubuntu:24.04    2h30m
scratch    running        alpine:3.20     5m

Headers are bold and status is color-coded in the terminal: green for running, yellow for grace period.

Server mode output

In server mode, list shows per-user sessions with connection counts and lifetime tracking:

ColumnDescription
USERUsername that owns the session
PROJECTProject name, or (default) for non-project sessions
CONTAINERDocker container name
STATUSrunning or grace_period
CONNSNumber of active SSH connections to this session
AGETime since session was created (e.g., 2h30m, 45s)
LIFETIME LEFTTime until max lifetime expires, or expired
USER     PROJECT     CONTAINER                 STATUS        CONNS  AGE     LIFETIME LEFT
alice    backend     podspawn-alice-backend    running       2      1h30m   6h30m
bob      (default)   podspawn-bob              grace_period  0      45m     7h15m
carol    frontend    podspawn-carol-frontend   running       1      5m      7h55m

When no machines exist:

No machines.

stop

Stops a machine and destroys its container, companion services, and network.

podspawn stop <name>
podspawn stop <user[@project]>

Argument format

The argument is interpreted differently depending on mode:

Local mode: The argument is the machine name. The current $USER is used automatically.

FormatMeaning
mydevStop the machine named "mydev"

Server mode: The argument is user[@project].

FormatMeaning
aliceStop alice's default (non-project) session
alice@backendStop alice's session for the backend project

What it destroys

The session's Docker container
All companion service containers (postgres, redis, etc.)
The per-user Docker network
The session record in the state database

Examples

# Local mode: stop a machine by name
podspawn stop mydev

# Server mode: stop alice's default session
podspawn stop alice

# Server mode: stop alice's backend project session
podspawn stop alice@backend

Output

✓ Stopped machine mydev

If no active machine exists:

Error: no active machine "mydev"

This immediately destroys the container. Any unsaved work inside the container is lost. Connected SSH sessions will be terminated.


cleanup

Reconciles orphaned containers and enforces time-to-live limits. Runs a single pass by default, or loops continuously in daemon mode.

podspawn cleanup [flags]

Flags

FlagDefaultDescription
--daemonfalseRun as a background cleanup daemon
--interval60sCleanup interval in daemon mode (Go duration format)

What each cleanup pass does

Examples

# Single cleanup pass
podspawn cleanup

# Run as a daemon with default 60s interval
podspawn cleanup --daemon

# Custom interval
podspawn cleanup --daemon --interval 30s

Running with systemd

Podspawn ships systemd units in the deb/rpm packages. You can also use them manually:

# Shipped at /etc/systemd/system/podspawn-cleanup.service
sudo systemctl enable --now podspawn-cleanup.service

This runs podspawn cleanup --daemon --interval 60s as a long-lived process.

# Shipped at /etc/systemd/system/podspawn-cleanup.timer
sudo systemctl enable --now podspawn-cleanup.timer

This runs a single cleanup pass every 60 seconds via systemd's timer infrastructure.

The cleanup command is not in the critical path. The system works without it, just with slightly delayed cleanup. Orphaned containers from crashes will be caught on the next pass.


status

Shows system-level metrics about sessions and containers. Supports both human-readable and Prometheus exposition formats.

podspawn status [flags]

Flags

FlagDefaultDescription
--prometheusfalseOutput in Prometheus exposition format

Human-readable output

Sessions:    3 total (2 running, 1 grace)
Connections: 4 active
Containers:  3 in Docker
Oldest:      2h30m
MetricDescription
SessionsTotal tracked sessions, broken down by running and grace period
ConnectionsSum of active SSH connections across all sessions
ContainersDocker containers with the managed-by=podspawn label
OldestAge of the longest-running session

Prometheus output

podspawn status --prometheus
# HELP podspawn_sessions_total Total tracked sessions
# TYPE podspawn_sessions_total gauge
podspawn_sessions_total 3
# HELP podspawn_sessions_running Sessions in running state
# TYPE podspawn_sessions_running gauge
podspawn_sessions_running 2
# HELP podspawn_sessions_grace Sessions in grace period
# TYPE podspawn_sessions_grace gauge
podspawn_sessions_grace 1
# HELP podspawn_connections_total Total active SSH connections
# TYPE podspawn_connections_total gauge
podspawn_connections_total 4
# HELP podspawn_containers_docker Docker containers with managed-by=podspawn
# TYPE podspawn_containers_docker gauge
podspawn_containers_docker 3
# HELP podspawn_oldest_session_seconds Age of the oldest session in seconds
# TYPE podspawn_oldest_session_seconds gauge
podspawn_oldest_session_seconds 9000

Monitoring integration

Scrape the Prometheus output with a textfile collector or a cron job:

# Write metrics for node_exporter textfile collector
podspawn status --prometheus > /var/lib/prometheus/node-exporter/podspawn.prom

list-users

Lists all registered container users by scanning the key directory.

podspawn list-users

Example output

alice  (3 keys)
ci-runner  (1 key)
deploy  (2 keys)

remove-user

Removes a container user by deleting their key file and optionally destroying their active sessions.

podspawn remove-user <username> [flags]

Flags

FlagDefaultDescription
--forcefalseDestroy active sessions without confirmation
--purgefalseAlso delete the user's persistent home directory

Behavior

Checks the user exists in /etc/podspawn/keys/
If the user has active sessions and --force is not set, returns an error
With --force, destroys all active sessions (containers, services, networks)
Removes the key file
With --purge, removes the user's persistent home directory at <homes_dir>/<username>
Without --purge, prints a notice if a persistent home directory exists so you can decide whether to keep it

Examples

# Remove user with no active sessions
podspawn remove-user alice

# Force-remove user with active sessions
podspawn remove-user alice --force

# Remove user and delete their persistent home directory
podspawn remove-user alice --force --purge

Without --purge, the home directory is left in place:

removed user alice
NOTE: persistent home dir exists at /var/lib/podspawn/homes/alice; use --purge to delete it

With --force, all active sessions are immediately destroyed. Connected SSH sessions will be terminated and unsaved work lost. With --purge, the user's persistent home directory is permanently deleted.


doctor

Runs preflight checks to verify that podspawn is correctly configured. The checks adapt based on what's installed: if /etc/podspawn/config.yaml exists (i.e., server-setup has been run), doctor runs the full set of checks including sshd validation. Without the server config, it only checks Docker and local state.

podspawn doctor

Adaptive checks

Runs when /etc/podspawn/config.yaml does not exist.

Checks: Docker daemon, Docker socket, state directory, lock directory, disk space, default image.

Runs when /etc/podspawn/config.yaml exists.

All local checks plus: OpenSSH version, sshd config, AuthorizedKeysCommand, podspawn config dir, key directory.

Local mode output

After a local-only install (no server-setup):

podspawn doctor

  [pass] Docker daemon
  [pass] Docker socket
  [pass] state directory
  [pass] lock directory
  [pass] disk space
  [pass] default image

6 passed, 0 warnings, 0 failed

Server mode output

After running server-setup:

podspawn doctor

  [pass] Docker daemon
  [pass] Docker socket
  [pass] OpenSSH version
  [pass] sshd config valid
  [pass] AuthorizedKeysCommand
  [pass] podspawn config dir
  [pass] key directory
  [pass] state directory
  [pass] lock directory
  [pass] disk space
  [pass] default image

11 passed, 0 warnings, 0 failed

Checks


remove-project

Deregisters a project and removes its local clone.

podspawn remove-project <name>

Behavior

  1. Removes the project's local repository clone from /var/lib/podspawn/projects/
  2. Removes the project entry from projects.yaml
  3. Does NOT remove the Docker image (prints a hint to docker rmi)

Example

podspawn remove-project backend
# removed project backend
# note: image podspawn/backend:podfile-abc123 still exists; run 'docker rmi ...' to remove it

How is this guide?

On this page