Host Setup

Bootstrap catch, configure Tailscale access, choose storage, upgrade hosts, and check container or VM support.

Host setup starts over SSH and then moves to Tailscale. yeet init installs catch on the machine host, enrolls catch in your tailnet, prepares storage, and checks optional host features such as Docker, ZFS, and VM support.

Common lookups

QuestionStart here
Which host name goes where?Host names
What is the default catch hostname?Host names
How do I install release or nightly yeet?CLI install
What Tailscale policy and OAuth setup are required?Tailscale access
What does yeet init prompt for?Bootstrap catch
How do I upgrade yeet and catch?Upgrade yeet and catch
Can this host run containers, VMs, or ZFS roots?Host requirements

Host names

Yeet uses two host names during setup:

  • <machine-host> is the SSH target for yeet init, such as root@server.example.
  • <catch-host> is the Tailscale hostname yeet uses after catch starts.

Use the machine host for installation. Use the catch host with CATCH_HOST, --host, and <svc>@<catch-host> after installation. The machine name answers "how do I SSH there?" The catch name answers "which daemon am I operating?"

The default catch hostname is catch. That is fine for one host. For more than one catch host, choose a name before setup:

yeet --host=morpheus-catch init root@<machine-host>

That command still installs over SSH to <machine-host>. The --host value is the catch hostname yeet asks Tailscale to assign. Use that same catch host for normal commands:

yeet --host=morpheus-catch status
yeet run <svc>@morpheus-catch ./compose.yml

To make that catch host the local default:

yeet prefs --host=morpheus-catch --save

During setup, SSH gets catch onto the machine. After that, Tailscale is the control path. Mixing those names up is the fastest way to make a working host look unreachable.

CLI install

Release install:

curl -fsSL https://yeetrun.com/install.sh | sh

Nightly build:

curl -fsSL https://yeetrun.com/install.sh | sh -s -- --nightly

Confirm the CLI is available:

yeet --help

Tailscale access

Catch joins your tailnet as a tagged device, such as tag:catch. This is required before the first yeet init and keeps catch tied to server-side policy.

Your tailnet policy must also grant the setup user access to catch on TCP port 41548 with the yeetrun.com/app/yeet app permissions read, manage, and ssh. First setup requires all three. Later, you can split access into separate read, manage, and shell roles.

Before you run yeet init, create an OAuth credential in the Tailscale admin console:

Trust credentials -> Credential -> OAuth

You have two choices:

  • Simple broad setup: choose All - Read & Write if you are comfortable giving the credential broad Tailscale API access.
  • Least-privilege setup: choose custom scopes with Auth Keys write (auth_keys) and select the tag the credential may assign. For catch-only installs, select tag:catch directly. If you plan to use service --net=ts later, use an owner tag such as tag:yeet that owns tag:catch and service tags such as tag:app.

Keep the tskey-client-... OAuth client secret ready. Interactive yeet init asks for it during first setup. This secret creates the catch node credential, so do not lose track of where it came from. Follow Tailscale Setup for the minimal policy snippet, and use Tailscale Access Grants when you are ready to split roles.

Before deploying a service with --net=ts, read Networking. Most Tailscale-exposed services should use svc,ts so they keep yeet DNS and ordinary outbound internet through the catch host.

Bootstrap catch

Normal interactive setup runs from your workstation against the SSH machine host:

yeet init root@<machine-host>

With no saved or explicit catch host, this uses the Tailscale hostname catch. Use yeet --host=<catch-host> init root@<machine-host> when adding another catch host to the same tailnet.

What changes by case:

CaseWhat yeet init does
First catch enrollmentPrompts for the Tailscale OAuth client secret.
Fresh storage setupPrompts for the catch data directory. The default is $HOME/yeet-data on the catch host, with services under $HOME/yeet-data/services.
Existing catch installKeeps the current storage layout and upgrades catch.
Missing Debian/Ubuntu packagesAsks before installing supported dependencies such as Docker or VM tools.
Non-root SSH userRuns the remote install with sudo.
VM LAN bridge setupCan prepare the host bridge when you plan to use VM --net=lan.

The data directory is where live host state begins to accumulate, so treat it as infrastructure, not cache.

If the host has ZFS, setup can use datasets and create missing child datasets when the parent exists. Use this only when you want the host storage on ZFS:

yeet init --zfs --data-dir=flash/yeet/data --services-root=flash/yeet/services root@<machine-host>

If you plan to run VMs with --net=lan, answer yes when init asks to prepare the host bridge. If you skip it, the first yeet run <vm> ... --net=lan prompts before creating the VM service.

Many VPS providers do not expose nested virtualization. That is a host constraint. On hosts that are not VM capable, yeet warns and containers, binaries, scripts, and cron jobs still work.

Confirm and validate

After bootstrap, confirm yeet can reach catch:

yeet version
yeet status

If this is not your default catch host, pass it explicitly:

yeet --host=<catch-host> status

Then run the First-Run Validation playbook to test the payload types this host should support.

Upgrade yeet and catch

Check the local CLI and catch hosts:

yeet upgrade check

Upgrade from verified GitHub release assets:

yeet upgrade

When you run from a service workspace with yeet.toml, yeet upgrade includes all project catch hosts plus the default catch host. Use --host=<catch-host> only when you want to upgrade one catch host. Otherwise, the project file is the source of truth and yeet follows it.

yeet upgrade --host=<catch-host>

To reinstall the latest public release even when a component already looks current, newer, or locally built:

yeet upgrade --force

To install a specific public release, select the tag:

yeet upgrade --version v0.6.1 --force

Host requirements

Base host:

  • Linux with systemd.
  • SSH access from your workstation.
  • A catch tag allowed by your Tailscale policy.

Container payloads:

  • Docker on the host.
  • Docker configured for local image pushes. yeet init handles this during catch install.

VM payloads:

  • x86_64/amd64 Linux.
  • KVM at /dev/kvm.
  • TUN/TAP at /dev/net/tun.
  • qemu-img, zstd, e2fsck, resize2fs, mount, umount, and ip.

ZFS is optional. Use it when you want dataset-backed host storage, service roots, snapshots, or fast VM disk clones. Skip it when a normal filesystem path is enough.

See Data Layout and ZFS.

Manual catch install

Use yeet init unless you have a specific reason to install catch manually. Manual install has fewer guardrails.

If you do install catch yourself, see the catch reference for catch flags such as --data-dir and --tsnet-host.