Remote Recipes
Provisioning snippets that get a Linux host into a state where dot-agent-deck remote add will succeed. The deck itself doesn't ship a provisioner — these recipes are starting points you adapt to your environment.
For prerequisites the host must satisfy see Remote Environment Requirements. For lifecycle and connection semantics see Remote Environments. The Kubernetes-as-host recipe lives in PRD #81 and is not yet shipped.
Status. Validated on a fresh Ubuntu 24.04 LTS UpCloud VM (the M0.2 reference host). Other providers should work given the same OS and SSH posture, but have not been independently re-tested. If a provider's image needs different bootstrap steps, the differences are typically in the cloud-init / first-login section — the deck-side flow (
remote add) is identical once SSH and a non-root user with the agent toolchain are in place.
Common shape
Every recipe converges on the same end state:
-
A Linux VM running Ubuntu 24.04 LTS (or equivalent), reachable over ssh.
-
A non-root user with
~/.local/binonPATHand the agent CLI installed. -
Outbound HTTPS to the LLM provider, package registries, and your git remote.
-
From your laptop:
dot-agent-deck remote add <name> <user>@<host>
The recipes below differ only in steps 1–3.
Multipass (local VM, macOS or Linux)
For a fully local dev setup with no cloud account.
# Launch an Ubuntu 24.04 LTS VM with sensible defaults.
multipass launch 24.04 --name dad-dev --cpus 2 --memory 2G --disk 20G
# Get into the VM as the default `ubuntu` user.
multipass shell dad-dev
Inside the VM:
# Make sure ~/.local/bin is on PATH for future shells.
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
mkdir -p ~/.local/bin
# Install Node.js (for npm-distributed agents like Claude Code).
sudo apt-get update
sudo apt-get install -y nodejs npm
# Install your agent. Example: Claude Code.
npm install -g @anthropic-ai/claude-code
# Set the agent's API key in your shell rc.
echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ~/.bashrc
# Enable systemd lingering so user services survive your shell exit.
sudo loginctl enable-linger $USER
exit
Back on the laptop:
# Multipass exposes the VM's IP via `multipass info`.
IP=$(multipass info dad-dev | awk '/IPv4/ {print $2; exit}')
# Multipass installs your laptop's authorized key by default; if not, use
# `multipass exec dad-dev -- bash -c 'echo <pubkey> >> ~/.ssh/authorized_keys'`.
dot-agent-deck remote add dad-dev ubuntu@$IP
dot-agent-deck connect dad-dev
Hetzner Cloud
Cheap, reliable, simple API. Replace <your-ssh-key-name> with the key registered in Hetzner Cloud Console.
# Create the server. CX22 is the smallest tier that comfortably runs an
# agent + the workspace; bump to CX32 for parallel agents or heavier tools.
hcloud server create \
--name dad-dev \
--type cx22 \
--image ubuntu-24.04 \
--ssh-key <your-ssh-key-name>
# Wait for it, then read the public IP.
IP=$(hcloud server ip dad-dev)
First login as root (Hetzner's default for cloud images) — create a non-root user, install the toolchain, then never log in as root again:
ssh root@$IP
adduser --disabled-password --gecos "" deck
usermod -aG sudo deck
mkdir -p /home/deck/.ssh
cp ~/.ssh/authorized_keys /home/deck/.ssh/
chown -R deck:deck /home/deck/.ssh
chmod 700 /home/deck/.ssh
chmod 600 /home/deck/.ssh/authorized_keys
# Disable password auth and root login (sshd hardening).
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl restart ssh
exit
Then as deck:
ssh deck@$IP
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
mkdir -p ~/.local/bin
sudo apt-get update
sudo apt-get install -y nodejs npm git
npm install -g @anthropic-ai/claude-code
echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ~/.bashrc
sudo loginctl enable-linger deck
exit
Back on the laptop:
dot-agent-deck remote add hetzner-1 deck@$IP
dot-agent-deck connect hetzner-1
If your ssh identity isn't at one of ssh's default search paths, pass it explicitly:
dot-agent-deck remote add hetzner-1 deck@$IP \
--key ~/.ssh/dot-agent-deck
UpCloud
UpCloud is the M0.2 reference host. The flow is identical to Hetzner once the VM exists; the differences are at the IaaS layer.
# Create the VM via the upctl CLI (or the web console). Pick whichever
# template / plan fits — anything ≥ 2 vCPU / 2 GiB RAM running Ubuntu
# 24.04 LTS is sufficient.
upctl server create \
--hostname dad-dev \
--plan 2xCPU-2GB \
--os "Ubuntu Server 24.04 LTS" \
--ssh-keys "$(cat ~/.ssh/id_ed25519.pub)" \
--zone <your-zone>
Then bootstrap the VM the same way as the Hetzner recipe (non-root user, ~/.local/bin on PATH, Node.js + agent install, enable-linger). The only UpCloud-specific note: cloud-init sets root as the default user; create a non-root user before running remote add so the daemon doesn't run as root.
Bare metal / desk-side box
Any always-on Linux box on your network works — a homelab server, a Raspberry Pi 5, an old laptop. The flow is just the bootstrap section of the cloud recipes minus the IaaS step:
- Install Ubuntu 24.04 LTS (or your distribution of choice — see Remote Environment Requirements for what's required).
- Create a non-root user, add your laptop's ssh key to its
~/.ssh/authorized_keys. - Install Node.js + the agent CLI; set the agent's API key in the user's environment.
sudo loginctl enable-linger $USER.- From the laptop:
dot-agent-deck remote add desk-pi user@hostname.local.
mDNS (hostname.local) is convenient on a home LAN. For routed access from outside the LAN, set up a tunnel (Tailscale, ZeroTier, or a port-forwarded ssh) before running remote add.
What to watch for
If remote add fails, the deck distinguishes three failure classes; see Remote Environments → Failure modes for what each one means and how to recover.
The most common first-time failures are:
- Wrong user. If the cloud image's default user isn't
root, the install steps above need to run under the right account. Check the provider's image documentation. ~/.local/binnot onPATH. The remote-side install lands the binary there, but a fresh non-interactive ssh session may not source~/.bashrc. The deck handles this —remote addinvokes the binary by absolute path during install — but later commands assume a login shell withPATHset.- Node.js too old. Ubuntu's
aptNode.js is sometimes lagging; if your agent's CLI requires a newer version, install via NodeSource ornvminstead ofapt.
See also
- Remote Environment Requirements — what a host must provide.
- Remote Environments — lifecycle, failure modes, hooks behavior.