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.
| Question | Start 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 |
Yeet uses two host names during setup:
<machine-host>is the SSH target foryeet init, such asroot@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.
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
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 & Writeif 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, selecttag:catchdirectly. If you plan to use service--net=tslater, use an owner tag such astag:yeetthat ownstag:catchand service tags such astag: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.
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:
| Case | What yeet init does |
|---|---|
| First catch enrollment | Prompts for the Tailscale OAuth client secret. |
| Fresh storage setup | Prompts for the catch data directory. The default is $HOME/yeet-data on the catch host, with services under $HOME/yeet-data/services. |
| Existing catch install | Keeps the current storage layout and upgrades catch. |
| Missing Debian/Ubuntu packages | Asks before installing supported dependencies such as Docker or VM tools. |
| Non-root SSH user | Runs the remote install with sudo. |
| VM LAN bridge setup | Can 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.
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.
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
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 inithandles 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, andip.
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.
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.