{"id":37768427,"url":"https://github.com/yeetrun/yeet","last_synced_at":"2026-07-04T22:00:30.336Z","repository":{"id":331024364,"uuid":"1124267358","full_name":"yeetrun/yeet","owner":"yeetrun","description":"Homelab Service Manager for Docker, Compose, and systemd","archived":false,"fork":false,"pushed_at":"2026-07-04T19:29:23.000Z","size":4381,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-04T20:05:59.715Z","etag":null,"topics":["cli","docker","docker-compose","homelab","remote-deployment","self-hosted","service-manager","systemd","tailscale"],"latest_commit_sha":null,"homepage":"https://yeetrun.com","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yeetrun.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-28T17:27:21.000Z","updated_at":"2026-07-04T19:27:35.000Z","dependencies_parsed_at":"2026-06-13T16:03:21.061Z","dependency_job_id":null,"html_url":"https://github.com/yeetrun/yeet","commit_stats":null,"previous_names":["shayne/yeet","yeetrun/yeet"],"tags_count":84,"template":false,"template_full_name":null,"purl":"pkg:github/yeetrun/yeet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeetrun%2Fyeet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeetrun%2Fyeet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeetrun%2Fyeet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeetrun%2Fyeet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yeetrun","download_url":"https://codeload.github.com/yeetrun/yeet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yeetrun%2Fyeet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35136712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","docker","docker-compose","homelab","remote-deployment","self-hosted","service-manager","systemd","tailscale"],"created_at":"2026-01-16T14:49:44.137Z","updated_at":"2026-07-04T22:00:30.324Z","avatar_url":"https://github.com/yeetrun.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://yeetrun.com\"\u003e\n    \u003cimg src=\"https://github.com/yeetrun.png\" alt=\"yeet logo\" width=\"140\" height=\"140\"\u003e\n  \u003c/a\u003e\n  \u003ch1\u003eyeet\u003c/h1\u003e\n  \u003cp\u003eRun services and VMs on your own Linux hosts from your workstation.\u003c/p\u003e\n  \u003cp\u003e\n    \u003ca href=\"https://yeetrun.com\"\u003e\u003cstrong\u003eyeetrun.com\u003c/strong\u003e\u003c/a\u003e\n    · \u003ca href=\"https://yeetrun.com/docs/getting-started/quick-start\"\u003eQuick Start\u003c/a\u003e\n    · \u003ca href=\"https://yeetrun.com/docs/getting-started/installation\"\u003eInstall\u003c/a\u003e\n    · \u003ca href=\"https://yeetrun.com/docs\"\u003eDocs\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\nYeet is a CLI for deploying and operating services on Linux hosts you control.\nYou run `yeet` locally. `yeet init` installs the `catch` daemon on a host over\nSSH. After setup, yeet talks to catch through Tailscale.\n\nUse yeet for:\n\n- Docker Compose stacks and container images.\n- Local Dockerfiles and locally built images.\n- Linux binaries and scripts.\n- Cron jobs.\n- Linux VMs on KVM-capable hosts.\n\nYeet fits single-operator homelabs and small private infrastructure. It expects\nLinux hosts with systemd. Services currently run as root-owned systemd units on\nthe catch host.\n\n## Quick Start\n\nThis path installs yeet locally, bootstraps one host, creates a service\nworkspace, and runs a disposable container.\n\n### 1. Install yeet locally\n\nRun this on your workstation:\n\n```bash\ncurl -fsSL https://yeetrun.com/install.sh | sh\n```\n\nTo install the nightly build instead:\n\n```bash\ncurl -fsSL https://yeetrun.com/install.sh | sh -s -- --nightly\n```\n\nConfirm the CLI is available:\n\n```bash\nyeet --help\n```\n\n### 2. Prepare Tailscale access\n\nDo this before running `yeet init`. Catch must join your tailnet as a tagged\ndevice, usually `tag:catch`. User-owned catch nodes are rejected.\n\nYour tailnet policy must also allow the setup user to reach catch on TCP port\n`41548` with the `yeetrun.com/app/yeet` app permissions `read`, `manage`, and\n`ssh`. First setup requires all three; split them into narrower roles later if\nyou need to.\n\nIn the Tailscale admin console, open `Trust credentials` -\u003e `Credential` -\u003e\n`OAuth`, then create an OAuth client secret.\n\nChoose one setup:\n\n- Simple setup: grant `All - Read \u0026 Write` if you are comfortable giving the\n  credential broad Tailscale API access.\n- Least-privilege setup: grant Auth Keys write (`auth_keys`) and select the tag\n  the credential may assign. Use `tag:catch` for catch-only installs. Use an\n  owner tag such as `tag:yeet` if you plan to create service Tailscale nodes\n  later with `--net=ts`.\n\nKeep the `tskey-client-...` secret ready. Interactive `yeet init` asks for it\nduring first setup.\n\nSee [Tailscale Setup](https://yeetrun.com/docs/concepts/tailscale#first-time-host-setup)\nfor the minimal policy snippet, and\n[Tailscale Access Grants](https://yeetrun.com/docs/security/tailscale-access-grants)\nfor the permission model.\n\n### 3. Bootstrap catch on a host\n\nRun this from your workstation:\n\n```bash\nyeet init root@\u003cmachine-host\u003e\n```\n\n`\u003cmachine-host\u003e` is the SSH target. If you use a non-root SSH user, yeet runs\nthe remote install with sudo.\n\nDuring first setup, paste the Tailscale OAuth client secret when prompted. For\nrepeatable setup, pass it explicitly:\n\n```bash\nyeet init --ts-client-secret=\u003csecret\u003e root@\u003cmachine-host\u003e\n```\n\nFresh interactive installs also ask where catch should store host data. The\ndefault is `$HOME/yeet-data` on the catch host, with services under\n`$HOME/yeet-data/services`. If the host has ZFS, init can use datasets instead:\n\n```bash\nyeet init --zfs --data-dir=flash/yeet/data --services-root=flash/yeet/services root@\u003cmachine-host\u003e\n```\n\nWith a ZFS services root, yeet treats the services root as a dataset prefix.\nServices under that root, including `catch`, live on child datasets such as\n`flash/yeet/services/\u003csvc\u003e`.\n\nRerunning `yeet init` for an existing catch install keeps the current storage\nlayout and upgrades catch without asking the storage questions again.\n\nIf Docker is missing on a Debian/Ubuntu-style host, init can install it:\n\n```bash\nyeet init --install-docker --ts-client-secret=\u003csecret\u003e root@\u003cmachine-host\u003e\n```\n\nFor VM payloads on a host that exposes KVM and TUN/TAP, install the VM tools\ntoo:\n\n```bash\nyeet init --install-docker --install-vm-tools --ts-client-secret=\u003csecret\u003e root@\u003cmachine-host\u003e\n```\n\nIf the host can run VMs and does not already have a LAN bridge, interactive\n`yeet init` can also ask to prepare `br0` for VM `--net=lan` networking. You\ncan skip that prompt and let the first `yeet run \u003cvm\u003e ... --net=lan` ask before\nit creates the VM service.\n\nSkip VM tools for the first run unless you already know the host supports VMs.\nContainers, binaries, scripts, and cron jobs work without VM support.\n\n### 4. Confirm yeet can reach catch\n\nAfter `yeet init`, normal commands target the catch hostname, not the SSH\nmachine host.\n\n```bash\nyeet version\nyeet status\n```\n\nIf yeet did not save this host as the default, pass the catch hostname:\n\n```bash\nyeet --host=\u003ccatch-host\u003e status\n```\n\n### 5. Create a service workspace\n\nDo this before your first `yeet run`. A successful deploy writes `yeet.toml` in\nthe current directory.\n\n```bash\nmkdir -p ~/yeet-services\ncd ~/yeet-services\n```\n\nUse this directory for real homelab services too. See the\n[Service Workspace](https://yeetrun.com/docs/getting-started/service-workspace)\nguide before deploying third-party Compose apps, env files, Dockerfiles,\nscripts, or binaries.\n\n### 6. Run a disposable service\n\nStart with a small container:\n\n```bash\nyeet run -p 18080:80 hello nginx:alpine\nyeet status hello\nyeet logs hello\n```\n\nCheck the published port from the catch host:\n\n```bash\nyeet ssh -- curl -fsS http://127.0.0.1:18080/ \u003e/dev/null\n```\n\nRemove the service and its data:\n\n```bash\nyeet rm --clean hello\n```\n\nRead the confirmation prompt before accepting. `--clean` deletes the service\ndata, including VM disks for VM services, and removes the disposable\n`yeet.toml` entry.\n\n## Common Commands\n\nRun deploy commands from your service workspace. Yeet writes `yeet.toml` in the\ncurrent directory after a successful deploy.\n\nUse the guided deploy form when you do not want to remember flags:\n\n```bash\nyeet run --web\nyeet run --web \u003csvc\u003e\nyeet run --web \u003csvc\u003e ./compose.yml\n```\n\nDeploy common payloads:\n\n```bash\nyeet run \u003csvc\u003e ./compose.yml\nyeet run -p 8080:80 \u003csvc\u003e nginx:alpine\nyeet run \u003csvc\u003e ./Dockerfile\nyeet docker push \u003csvc\u003e \u003clocal-image\u003e:\u003ctag\u003e --run\n```\n\nService names created by `yeet run` must use lowercase letters, numbers, and\ndashes, start with a letter, and end with a letter or number.\n\nDeploy a binary, script, or cron job:\n\n```bash\nGOOS=linux GOARCH=amd64 go build -o ./bin/\u003csvc\u003e ./cmd/\u003csvc\u003e\nyeet run \u003csvc\u003e ./bin/\u003csvc\u003e\nyeet run \u003csvc\u003e ./script.sh -- --app-flag value\nyeet cron \u003csvc\u003e ./job.sh \"0 9 * * *\"\n```\n\nCreate a VM on a KVM-capable catch host:\n\n```bash\nyeet vm images catalog\nyeet run \u003cvm\u003e vm://ubuntu/26.04\nyeet ssh \u003cvm\u003e\n```\n\nAfter the first successful deploy, yeet writes service config to `yeet.toml`.\nFrom that directory, redeploy the saved service with:\n\n```bash\nyeet run \u003csvc\u003e\n```\n\n## Operate a Service\n\nCheck status and logs:\n\n```bash\nyeet status\nyeet status \u003csvc\u003e\nyeet status \u003csvc-a\u003e \u003csvc-b\u003e\nyeet info\nyeet info \u003csvc\u003e\nyeet logs -f \u003csvc\u003e\n```\n\nOpen a shell or run a remote command:\n\n```bash\nyeet ssh\nyeet ssh \u003csvc\u003e\nyeet ssh -- uname -a\nyeet ssh \u003csvc\u003e -- ls -la\n```\n\nAfter `yeet init`, host and regular service shells use catch over Tailscale, so\nthey do not require host SSH keys or a host password. VM services still connect\nto the guest operating system with SSH.\n\nControl or remove a service:\n\n```bash\nyeet restart \u003csvc\u003e\nyeet stop \u003csvc\u003e\nyeet start \u003csvc\u003e\nyeet rm \u003csvc\u003e\n```\n\n`yeet rm \u003csvc\u003e` keeps service data by default and prompts before removing the\nlocal config entry. Add `--clean` when you want yeet to delete service data and\nremove the local `yeet.toml` entry too.\n\n## Target a Host\n\nUse `root@\u003cmachine-host\u003e` only for `yeet init`. Use the catch hostname for\nnormal commands.\n\n```bash\nCATCH_HOST=\u003ccatch-host\u003e yeet status\nyeet --host=\u003ccatch-host\u003e status\nyeet status@\u003ccatch-host\u003e\nyeet run \u003csvc\u003e@\u003ccatch-host\u003e ./compose.yml\n```\n\nSave a default catch host:\n\n```bash\nyeet prefs --host=\u003ccatch-host\u003e --save\n```\n\n## Upgrade\n\nCheck the local CLI and catch hosts:\n\n```bash\nyeet upgrade check\n```\n\nUpgrade from verified GitHub release assets:\n\n```bash\nyeet upgrade\n```\n\nWhen you run from a service workspace with `yeet.toml`, `yeet upgrade` includes\nall project catch hosts plus the default catch host. Use `--host=\u003ccatch-host\u003e`\nonly when you want to upgrade one catch host.\n\n```bash\nyeet upgrade --host=\u003ccatch-host\u003e\n```\n\nTo reinstall a release even when a component already looks current, newer, or\nlocally built:\n\n```bash\nyeet upgrade --force\n```\n\nTo install a specific public release:\n\n```bash\nyeet upgrade --version v0.6.1 --force\n```\n\n## Optional Capabilities\n\nStart with the quick path before adding optional features.\n\n- Docker is required for container payloads.\n- VMs require x86_64 Linux, KVM at `/dev/kvm`, TUN/TAP, and VM filesystem\n  tools on the catch host.\n- `--net=svc` creates a private service network, adds yeet DNS, and sends\n  ordinary outbound internet through the catch host.\n- `--net=svc,ts` keeps `svc` behavior and gives the service its own Tailscale\n  identity. Use this for most Tailscale-exposed services.\n- `--net=lan` requests a LAN or VLAN address. Outbound internet comes from the\n  DHCP gateway on that network.\n- VM `--net=lan` attaches the guest TAP to a host bridge. On supported\n  Debian/Ubuntu hosts, yeet can prepare `br0` during `yeet init` or before the\n  first VM LAN create.\n- Plain `--net=ts` is tailnet-only unless you configure a Tailscale exit node.\n- ZFS is optional. Init can place host data or the default service root on\n  datasets. A ZFS services root is a dataset prefix, so services under it use\n  child datasets for snapshots and fast VM disk clones.\n\nUse the manual before enabling optional storage or networking:\n\n- [Payloads](https://yeetrun.com/docs/payloads)\n- [Networking](https://yeetrun.com/docs/concepts/networking)\n- [VMs](https://yeetrun.com/docs/payloads/vms)\n- [ZFS](https://yeetrun.com/docs/concepts/zfs)\n\n## Documentation\n\n- [Quick Start](https://yeetrun.com/docs/getting-started/quick-start)\n- [Installation](https://yeetrun.com/docs/getting-started/installation)\n- [Workflows](https://yeetrun.com/docs/operations/workflows)\n- [Payloads](https://yeetrun.com/docs/payloads)\n- [yeet command reference](https://yeetrun.com/docs/cli/yeet-cli)\n- [catch reference](https://yeetrun.com/docs/cli/catch-cli)\n- [Troubleshooting](https://yeetrun.com/docs/operations/troubleshooting)\n- [FAQ](https://yeetrun.com/docs/faq)\n\n## Develop from Source\n\nUse mise to install the repo toolchain:\n\n```bash\nmise install\n```\n\nBuild and test:\n\n```bash\nmise exec -- go build ./cmd/yeet\nmise exec -- go build ./cmd/catch\nmise exec -- go test ./...\n```\n\nInstall local hooks before contributor work:\n\n```bash\nmise run install-githooks\n```\n\nRun the normal quality gate before publishing changes:\n\n```bash\nmise run quality\n```\n\n## Security\n\nYeet is for hosts you control. It is not a multi-tenant platform. Services\nmanaged by catch currently run as root-owned systemd units.\n\n## License\n\nBSD 3-Clause. See `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeetrun%2Fyeet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyeetrun%2Fyeet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyeetrun%2Fyeet/lists"}