Best for
- Use when configuring access control, writing policy files, or troubleshooting connectivity issues caused by ACLs.
magnus919/agent-skills/tailscale/skills/tailnet-policy/SKILL.md
Author, test, and deploy Tailscale-compatible huJSON policy files for Headscale tailnets — ACLs, Grants, Tags, Auto Approvers, Tailscale SSH rules. Use when configuring access control, writing policy files, or troubleshooting connectivity issues caused by ACLs.
Decision brief
Author, test, and deploy Tailscale-compatible huJSON policy files for Headscale tailnets — ACLs, Grants, Tags, Auto Approvers, Tailscale SSH rules.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/magnus919/agent-skills --skill "tailscale/skills/tailnet-policy"Inspect the Agent Skill "tailnet-policy" from https://github.com/magnus919/agent-skills/blob/531ff6753784823c878c92b988c6e55266ce09a9/tailscale/skills/tailnet-policy/SKILL.md at commit 531ff6753784823c878c92b988c6e55266ce09a9. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Use Grants wherever possible. The migrate-acls-to-grants.py script can convert legacy ACL files automatically.
The policy file path is configured in Headscale's config.yaml:
kill -HUP $(pgrep headscale)
./skills/tailnet-policy/reload-headscale-policy.sh hujson { // Grants that allow all traffic "grants": [ { "src": ["autogroup:member"], "dst": ["autogroup:member"], "ip": [":"] } ], // Tag ownership "tagOwners": { "tag:dev": ["autogroup:admin"], "tag:prod": ["autogroup:admin"] }…
Tags are node-level identifiers set via tailscale up --advertise-tags=tag:dev. They decouple policy from user identity.
Permission review
No configured static risk pattern was detected
This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.
Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 61 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Headscale uses Tailscale-compatible policy files written in huJSON (Human JSON — standard JSON with trailing commas and // comments). Policy files control:
{action, users, ports} rules{src, dst, ip, proto, via} rulestag:dev, tag:prod)ssh.users and ssh.action| Feature | ACLs (legacy) | Grants (modern) |
|---|---|---|
| Format | {action: "accept", users: [...], ports: [...]} | {src: [...], dst: [...], ip: [...], proto: "tcp"} |
| Port filtering | Embedded in ports: ["*:*"] | Separate ip field for ports |
| Protocol filtering | Not supported | proto field (tcp, udp, icmp) |
| Destination routing | Not supported | via field for relay/exit nodes |
| Status | Deprecated by Tailscale | Current recommended syntax |
Use Grants wherever possible. The migrate-acls-to-grants.py script can convert legacy ACL files automatically.
The policy file path is configured in Headscale's config.yaml:
policy:
path: /etc/headscale/policy.hujson
After modifying the policy file, reload it on the Headscale server:
# Reload via SIGHUP
kill -HUP $(pgrep headscale)
# Or use the convenience script
./skills/tailnet-policy/reload-headscale-policy.sh
{
// Grants that allow all traffic
"grants": [
{
"src": ["autogroup:member"],
"dst": ["autogroup:member"],
"ip": ["*:*"]
}
],
// Tag ownership
"tagOwners": {
"tag:dev": ["autogroup:admin"],
"tag:prod": ["autogroup:admin"]
}
}
{
"grants": [
// Only allow ICMP (ping) between all members
{
"src": ["autogroup:member"],
"dst": ["autogroup:member"],
"ip": ["*"],
"proto": "icmp"
}
],
// Specific grants added per-service
"tagOwners": {
"tag:monitor": ["autogroup:admin"]
}
}
{
"grants": [
// Dev can reach dev
{
"src": ["tag:dev"],
"dst": ["tag:dev"],
"ip": ["*:*"]
},
// Prod can reach prod
{
"src": ["tag:prod"],
"dst": ["tag:prod"],
"ip": ["*:*"]
},
// Admin access to all
{
"src": ["autogroup:admin"],
"dst": ["tag:dev", "tag:prod"],
"ip": ["*:*"]
}
],
"tagOwners": {
"tag:dev": ["autogroup:admin"],
"tag:prod": ["autogroup:admin"]
}
}
Tags are node-level identifiers set via tailscale up --advertise-tags=tag:dev. They decouple policy from user identity.
{
"tagOwners": {
"tag:ci-runner": ["autogroup:admin"],
"tag:database": ["autogroup:admin"],
"tag:webserver": ["autogroup:admin"],
"tag:monitoring": ["autogroup:admin"]
},
"grants": [
{
"src": ["tag:monitoring"],
"dst": ["tag:webserver", "tag:database"],
"ip": ["*:*"]
},
{
"src": ["tag:webserver"],
"dst": ["tag:database"],
"ip": ["tcp:5432"]
}
]
}
Grants are the modern policy primitive:
{
"grants": [
{
"src": ["tag:source", "[email protected]"],
"dst": ["tag:destination", "100.64.0.1"],
"ip": ["*:*"], // proto:port — "*:*" means all
"proto": "tcp", // optional protocol filter
"via": ["tag:exit-node"] // optional via/routing
}
]
}
Fields:
src — Source entities (tags, users, autogroups, IPs)dst — Destination entitiesip — Protocol and port filter (e.g. tcp:80, udp:53, *:*, *)proto — Protocol constraint (tcp, udp, icmp)via — Route through a specific exit node or relayAuto-approvers let specific users approve subnet routes and exit nodes without manual intervention:
{
"autoApprovers": {
"routes": {
"10.0.0.0/8": ["autogroup:admin"],
"172.16.0.0/12": ["[email protected]"]
},
"exitNode": ["autogroup:admin"]
}
}
routes: Maps CIDR ranges to lists of users who can auto-approve those routesexitNode: Lists users who can advertise exit nodesAutogroups are dynamic groups resolved by Headscale/Tailscale at runtime:
| Autogroup | Description |
|---|---|
autogroup:member | All tailnet members |
autogroup:admin | Tailnet admins |
autogroup:tagged | All tagged nodes (any node with at least one tag) |
autogroup:internet | The public internet (used for exit node routing) |
Tailscale SSH rules are configured via the ssh section:
{
"ssh": [
{
"action": "accept", // "accept" or "check"
"src": ["autogroup:admin"],
"dst": ["tag:webserver"],
"users": ["root", "ubuntu"]
},
{
"action": "check", // "check" requires node-level SSH authorization
"src": ["autogroup:member"],
"dst": ["tag:dev"],
"users": ["*"]
}
]
}
action: "accept" (allow directly) or "check" (require node-level auth)src: Source users/groupsdst: Destination tags/usersusers: Which OS users can be SSH'd intoPolicy files include test definitions that are validated when loaded:
{
"grants": [...],
"tests": [
{
"src": "[email protected]",
"dst": "tag:webserver",
"ip": ["tcp:443"],
"action": "accept" // expected result
},
{
"src": "[email protected]",
"dst": "tag:database",
"ip": ["tcp:22"],
"action": "drop" // expected result
}
]
}
Validate tests with:
./skills/tailnet-policy/validate-policy.py --policy policy.hujson
devicePosture or device:managed are Tailscale-onlyipSets and ipprotocol are not supportedautogroup:admin and autogroup:member insteadtag: and contain only lowercase letters, numbers, and hyphensusers field and Grant src field are NOT interchangeable — grants use src/dst, legacy ACLs use users/portsThis skill is automatically loaded when the user's message contains any of these keywords:
Do not use this skill for deploying the Headscale server (load headscale-deploy instead) or for client connectivity issues unrelated to access control (load tailscale-client). It covers huJSON policy authoring and testing only.
Frequently asked questions
Author, test, and deploy Tailscale-compatible huJSON policy files for Headscale tailnets — ACLs, Grants, Tags, Auto Approvers, Tailscale SSH rules.
The source record exposes this install command: npx skills add https://github.com/magnus919/agent-skills --skill "tailscale/skills/tailnet-policy". Inspect the command and pinned source before running it.
Alternatives
vasilyu1983/AI-Agents-public
Guides iOS testing with XCTest, XCUITest, Swift Testing, simctl, and xcresult. Use when choosing destinations, controlling flakes, or parsing test artifacts for native apps.
steipete/agent-scripts
REQUIRED before ANY `op` command or whenever a task needs an API key, token, password, credential, or secret (OPENAI_API_KEY, ANTHROPIC_API_KEY, deploy tokens, live-test keys). Prompt-free 1Password service-account reads; wrong invocations spam macOS dialogs.
microsoft/Sico
Execute Android UI workflows on a sandbox device, review results, and produce a structured execution report.
mission69b/t2000
Publishing, upgrading, and deploying Sui Move packages. Use this skill when the user needs to publish a package, upgrade a published package, deploy to multiple networks, serialize transactions for multisig signing, run a local Sui network (localnet), prepare for Mainnet launch, monitor production deployments, or debug dry run failures. Also use when the user asks about sui client publish, sui client upgrade, UpgradeCap, upgrade policies, Published.toml, --serialize-output, localnet, mainnet lau