Service Types

How yeet decides what kind of service a payload becomes.

Yeet detects payload type and installs the service accordingly. For step-by-step usage, start with Payloads.

You should be able to look at a payload and predict which host mechanism catch will use before the command changes anything.

Binary

  • ELF or Mach-O binary.
  • Catch installs it as a systemd service on the host.
  • New services run as the host's shared yeet-svc account by default. Use --run-as=<user>[:<group>] when the workload needs another existing account.
  • Fresh services run in the native Bubblewrap sandbox by default. Existing services retain their reported legacy, on, or off state.
  • Use yeet run <svc> ./bin/<svc>.
  • Build for the catch host architecture first.
  • Native binaries support --net=iso independently of --run-as.

Script

  • Shebang file (e.g., #!/usr/bin/env bash).
  • Catch treats it like a binary and installs it as a systemd service.
  • New services use the same yeet-svc default as native binaries.
  • The interpreter must exist on the host.
  • Scripts support the same identity-independent iso network path as binaries.
  • Scripts use the same native sandbox policy and exposure controls as binaries.

Docker Compose

  • Any YAML with a top-level services: key.
  • Catch installs it as a Docker Compose service.
  • Container users remain Compose-owned. Set user: in the Compose service instead of passing --run-as to yeet.
  • Use --pull on yeet run when you want to refresh images; otherwise run reuses existing images.
  • See Containers.

Docker image

  • If the payload looks like an OCI image ref (e.g. nginx:latest, ghcr.io/org/app:1.2.3), catch pulls the image on the host.
  • For local images, use yeet docker push <svc> <image>:<tag> --run.
  • For Dockerfiles, use yeet run <svc> ./Dockerfile (builds for the host arch and pushes).
  • See Containers.

TypeScript

  • .ts files are run via a Deno container.
  • Catch runs it as a container-backed service.
  • See Containers.

Python

  • .py files are run via a uv container image.
  • Catch runs it as a container-backed service.
  • See Containers.

VM

  • vm://ubuntu/26.04 creates a long-lived Ubuntu VM service.
  • vm://nixos/26.05 creates a long-lived NixOS VM service.
  • Imported images run as vm://<name> after yeet vm images import.
  • Requires a Linux catch host with KVM available.
  • Uses yeet-owned VM image bundles published from yeetrun/yeet-vm-images.
  • yeet init checks the host for KVM, TUN/TAP, and required VM tooling; on capable Debian/Ubuntu hosts it can prompt for missing VM tools.
  • VM processes use yeet's jailer identity, while software inside the guest uses guest users. VMs do not accept the native-service --run-as flag.
  • See VMs.

Zstd

  • Yeet detects and unpacks Zstd-compressed binaries.

Cron

  • yeet run <svc> <payload> --cron="..." installs a native binary or script as a timer-backed job on the host.
  • Jobs run as yeet-svc by default and accept --run-as=<user>[:<group>].
  • The invoked service can use iso; the timer remains the scheduling unit.
  • Fresh jobs use the native sandbox by default. Changing sandbox policy replaces and verifies the timer and service units without running the job.
  • See Cron Jobs.

Notes

  • Yeet detects file type by extension or content.
  • Architecture must match the target host; mismatches fail early.
  • Catch state defaults to /var/lib/yeet, and the default service root is /var/lib/yeet/services. Per-service custom roots are preserved when host storage moves.
  • yeet-svc reduces the privileges of native workloads, but it is shared by default and is not a security boundary between services. Operators can create separate accounts and select them with --run-as when isolation is required.
  • A custom run-as account keeps its configured supplementary groups when systemd starts the workload. Review memberships such as docker before using the account. The yeet ssh <svc> service shell clears supplementary groups, so it can be more restricted than the running unit.
  • Custom service roots must be below host-controlled directories whose parents are root-owned and not group- or world-writable. /srv/apps and ZFS mountpoints work; a workload-owned home directory does not.
  • Existing native services keep their current identity until an operator runs yeet service set <svc> --run-as=<user>[:<group>]. Catch, Tailscale, host networking, storage helpers, and other host management processes remain root-owned.
  • Change networks for existing non-VM services with yeet service set; change VM networks with yeet vm set. An existing-service yeet run cannot mutate networking.
  • Native and timer iso changes ordinary network placement without changing workload identity or promising containment against a hostile host-root process.
  • Native sandbox state is independent of workload identity and network mode. See Native Sandboxing for the default filesystem view, explicit legacy migration, and the off escape hatch.
  • ZFS is storage backing for service roots and VM disks, not a service type.
  • ZFS datasets are not copied or deleted implicitly by host storage migration.
  • If a service already exists, its type is fixed. Replace it with a new service name or remove the old one first.