Tailscale Access Grants
Decide who can observe, mutate, and open shells through catch.
Use Tailscale grants to decide who can connect to catch and what they can do after they reach it.
Reachability is not authorization. Your workstation must reach the catch Tailscale address, and the app grant must allow the requested yeet permission.
For first setup, keep the policy simple. Let Tailscale admins reach catch on
its RPC port and give those admins every yeet permission. Tailscale's built-in
admin autogroup is autogroup:admin.
You can split the roles later. First get the host enrolled with one admin grant.
{
"tagOwners": {
"tag:yeet": ["autogroup:admin"],
"tag:catch": ["tag:yeet"],
"tag:app": ["tag:yeet"],
},
"grants": [
{
"src": ["autogroup:admin"],
"dst": ["tag:catch"],
"ip": ["tcp:41548"],
"app": {
"yeetrun.com/app/yeet": [{ "allow": ["read", "manage", "ssh"] }],
},
},
{
"src": ["tag:catch"],
"dst": ["tag:catch"],
"ip": ["tcp:41548"],
},
],
}
Run yeet init after this policy is active. First setup requires read,
manage, and ssh so one admin grant covers enrollment, validation, and shell
checks.
Use autogroup:admin directly in the grant src. Do not create a
group:yeet-admins entry that contains autogroup:admin; Tailscale policy
groups are for actual user identities when you define them in the policy file.
The second grant lets catch nodes talk to other catch nodes on the same port. Keep it if you run more than one catch host.
| Permission | Allows | Common examples |
|---|---|---|
read | Observing catch state | yeet status, yeet info, logs, events, ISO pool and endpoint state, VM defaults, artifact hashes |
manage | Changing services or host state | Deploys, updates, removals, ISO pool and workload changes, yeet rm --clean, config changes, snapshots, VM lifecycle commands, catch upgrades, Tailscale service changes, local image pushes |
ssh | Opening catch-mediated shells | yeet ssh, yeet ssh <svc>, commands run inside a service namespace |
manage does not imply read, and ssh does not imply either one. Include
every permission a role needs.
yeet ssh <vm> is the exception to remember. Yeet needs read to find the VM
connection details, then the VM guest uses normal SSH keys for login. Catch-host
and service shells still require ssh.
The same rule applies to an ISO VM: read reveals its Catch-routed connection
metadata, and the guest SSH key authorizes login. Creating, changing, removing,
repairing, or configuring ISO state requires manage.
Catch joins your tailnet, but the local yeet CLI does not run its own
Tailscale client. Tailscale grants decide what a caller may do after it reaches
catch, but your workstation must still be able to reach the catch Tailscale
address. In the normal setup, install Tailscale on the workstation and connect
it to the same tailnet before testing grants.
After the first host is working, split access if you need tighter roles. Keep
the same app capability key and change the src groups and allow lists.
When you define policy-file groups, list the users in those groups directly.
Give each group only the permissions it needs.
{
"groups": {
"group:yeet-readers": ["reader@example.com"],
"group:yeet-deployers": ["deployer@example.com"],
"group:yeet-shell-admins": ["shell-admin@example.com"],
},
"grants": [
{
"src": ["group:yeet-readers"],
"dst": ["tag:catch"],
"ip": ["tcp:41548"],
"app": {
"yeetrun.com/app/yeet": [{ "allow": ["read"] }],
},
},
{
"src": ["group:yeet-deployers"],
"dst": ["tag:catch"],
"ip": ["tcp:41548"],
"app": {
"yeetrun.com/app/yeet": [{ "allow": ["read", "manage"] }],
},
},
{
"src": ["group:yeet-shell-admins"],
"dst": ["tag:catch"],
"ip": ["tcp:41548"],
"app": {
"yeetrun.com/app/yeet": [{ "allow": ["read", "ssh"] }],
},
},
],
}
If a user matches multiple grants, catch treats the allowed yeet permissions as one combined set.
When catch denies a command, yeet prints the missing permission and links back to this page:
missing yeet permission "manage"; update your Tailscale grant for yeetrun.com/app/yeet:
https://yeetrun.com/docs/security/tailscale-access-grants
Update the matching Tailscale grant, wait for the policy to apply, then rerun
the command from a workstation that can reach the catch hostname. If the error
says manage, adding SSH reachability will not help; update the app
permission instead.