Skip to content
COMA

Bootstrap a bare VM

Install Docker or rootless Podman on a fresh Debian or Ubuntu machine with coma machine bootstrap, after reviewing the plan.

A fresh VM usually has no container engine. coma machine bootstrap prepares it: it creates COMA's directories on the machine and, with --engine, installs Docker or Podman and sets it up for your SSH user.

Add the machine first (Add a machine). When COMA finds no engine, coma machine add ends with the bootstrap command as its Next: line.

Run it

coma machine bootstrap <name> --engine docker|podman
coma machine bootstrap dev --engine docker

For rootless Podman instead:

coma machine bootstrap dev --engine podman

On a machine without an engine, --engine is required; without it, bootstrap fails with engine_selection_required.

The plan

Bootstrap first inspects the machine without changing it. It shows the plan, with every command it would run, and asks before it applies anything:

Bootstrap plan for dev (as you): 4 of 4 step(s) to apply
  pending   create-coma-dir
            Create COMA's directories under ~/.coma (owner-only)
            $ mkdir -p "$HOME/.coma" && chmod 700 "$HOME/.coma" && mkdir -p "$HOME/.coma/bin" "$HOME/.coma/run" "$HOME/.coma/cache" "$HOME/.coma/state"
  pending   install-docker [sudo]
            Install Docker from the distribution's packages (docker.io)
            $ sudo -n env DEBIAN_FRONTEND=noninteractive apt-get -q -o DPkg::Lock::Timeout=300 update
            $ pkgs=""; for p in docker-buildx docker-compose-v2; do if apt-cache show "$p" >/dev/null 2>&1; then pkgs="$pkgs $p"; fi; done
            $ sudo -n env DEBIAN_FRONTEND=noninteractive apt-get -q -o DPkg::Lock::Timeout=300 install -y docker.io $pkgs
  pending   start-docker [sudo]
            Start the Docker service now and at boot
            $ sudo -n systemctl enable --now docker
  pending   docker-group [sudo]
            Add you to the docker group so COMA reaches the engine without sudo (this is root-equivalent access on the machine)
            $ sudo -n usermod -aG docker "$(id -un)"

Each step is satisfied (nothing to do) or pending (apply would run its commands). Commands are listed only for pending steps.

To see the plan and change nothing, add --plan:

coma machine bootstrap dev --engine docker --plan

Confirmation

In a terminal, COMA asks Apply 4 step(s) to dev? before it changes anything. For scripts and coding agents, pass --yes. Without a terminal and without --yes, bootstrap fails with confirmation_required and changes nothing.

Steps marked sudo

Steps marked [sudo] need passwordless sudo on the machine (they run sudo -n, which never prompts). If your SSH user does not have it, the plan says which step is blocked, and applying fails with bootstrap_privilege_required before anything changes. Run the plan's sudo commands yourself, or grant passwordless sudo, then run bootstrap again. As root, no step needs sudo.

What it installs

Packages come from the distribution's own signed repositories, through apt. There is no third-party repository and no curl | sh.

Docker (--engine docker):

StepWhat it does
create-coma-dirCreates ~/.coma (mode 0700) and its bin, run, cache and state directories
install-dockerInstalls docker.io, plus docker-buildx and docker-compose-v2 where the distribution has them
start-dockerStarts Docker now and at boot
docker-groupAdds your user to the docker group; this is root-equivalent access on the machine

Podman (--engine podman):

StepWhat it does
create-coma-dirCreates ~/.coma and its directories
install-podmanInstalls podman, uidmap and dbus-user-session
enable-lingerKeeps your user services running without a login session, so rootless containers and the API socket survive disconnects
podman-socketStarts the rootless Podman API socket now and at boot

As root, Podman runs rootful: bootstrap starts the system Podman socket and skips the linger step.

apt waits up to five minutes for a package lock held by unattended upgrades, which is common on a freshly booted cloud VM.

Loopback publishing for containers started outside COMA

Containers started through COMA publish their ports on 127.0.0.1 on the machine. Containers started some other way, for example over a separate SSH session, follow Docker's default, which publishes on every interface. --harden-publish adds one more Docker step, engine-default-loopback-publish:

coma machine bootstrap dev --engine docker --harden-publish

It merges "ip": "127.0.0.1" into /etc/docker/daemon.json, keeps the old file as daemon.json.coma-bak, and restarts Docker. It refuses to rewrite a daemon.json that is not a JSON object. The plan marks the step restarts the engine. See Ports.

Verify and resume

Every step is a read-only check plus the commands that satisfy it.

  • Verify after apply. After running a step, COMA runs its check again and moves on only if it passes. When all steps are done, COMA refreshes the machine's inventory over a new SSH connection and fails unless the engine you asked for is healthy.
  • Resume. A failed step stops the run with bootstrap_failed and the step's ID. Fix the cause and run the same command again: satisfied steps are skipped, and bootstrap continues from the step that failed.
  • Idempotent. On a machine that is already ready, bootstrap changes nothing:
dev is already bootstrapped; nothing to change

After a successful run:

Bootstrapped dev
  Ubuntu 24.04.3 LTS · linux/amd64 · 8 CPUs · 31.3 GiB memory · 142.6 GiB free on /
  engines: docker 28.2.2
  health:  healthy (observed 2026-10-04 14:05)
Next: coma connect dev

Supported distributions

Bootstrap installs engines on Debian and Ubuntu, with apt.

Not supported yet:

  • Fedora, RHEL and other distributions without apt. The plan fails with bootstrap_plan_failed. Install Docker or Podman yourself, then run coma machine discover <name> so COMA records it.
  • Docker's own apt repository. Bootstrap uses the distribution's docker.io package.
  • Rolling a bootstrap back.

A machine that already has the engine you ask for needs no package manager: bootstrap only checks it and creates COMA's directories.

Next

coma connect dev

Then continue with the Quickstart, or set up your first workspace.

On this page