tailnet-policy
/tailnet-policy
Pisze, testuje i wdraża pliki polityk huJSON zgodne z Tailscale dla tailnetów Headscale: ACL, Grants, tagi, auto approvers i reguły Tailscale SSH.
- Autor
- magnus919 ↗
- Repozytorium
- agent-skills ↗
- Licencja
- MIT
- Ostatnia zmiana repozytorium
- 25.10.2026
Ocena i bezpieczeństwo
- Pliki w paczce
- 6
- Skrypty
- 3
- Komentarze HTML
- 0
- Adresy URL w SKILL.md
- 0
Brak sygnałów. Repozytorium zmienione 25.10.2026, bez odwołań do wycofanych modeli i API.
MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.
- 3 skrypty w paczce. Przejrzyj je przed instalacją, bo Claude może je uruchomić.
Skrypty: scripts/migrate-acls-to-grants.py, scripts/reload-headscale-policy.sh, scripts/validate-policy.py
Co robi i kiedy
Pisze, testuje i wdraża pliki polityk huJSON zgodne z Tailscale dla tailnetów Headscale: ACL, Grants, tagi, auto approvers i reguły Tailscale SSH.
Oryginalny opis (EN)
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.
Jak działa
- Security preflight
- Overview
- Policy Location
- Writing Policy
- Grants Syntax
- Auto Approvers
- Autogroups
- Tailscale SSH Configuration
- Testing Policies
- Gotchas
Podgląd SKILL.md
---
name: tailnet-policy
description: 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.
metadata:
category: devops
---
# tailnet-policy
## Security preflight
Before enabling SSH, Serve, connector access or changing access policy, read the
bundle's [security triage](../../references/security-triage.md). Also load it for
Tailworm or suspected compromise. Preserve tested recovery access before disabling
embedded SSH; check mode is not a forwarding fix. Treat reported findings as
version-specific until current advisories establish applicability.
Confirm the target, scope, and rollback path before acting. Read-only discovery may proceed without confirmation.
## Overview
Headscale uses Tailscale-compatible policy files written in **huJSON** (Human JSON — standard JSON with trailing commas and `//` comments). Policy files control:
- **ACLs** (deprecated legacy syntax) — `{action, users, ports}` rules
- **Grants** (modern syntax) — `{src, dst, ip, proto, via}` rules
- **Tags** — Node identity tags (`tag:dev`, `tag:prod`)
- **TagOwners** — Which users/groups can apply which tags
- **AutoApprovers** — Auto-approval for subnet routers and exit nodes
- **Tailscale SSH** — SSH access rules via `ssh.users` and `ssh.action`
### ACLs vs Grants
| 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.
## Policy Location
The policy file path is configured in Headscale's `config.yaml`:
```yaml
policy:
path: /etc/headscale/policy.hujson
```
After modifying the policy file, reload it on the Headscale server:
```bash
# Reload via SIGHUP
kill -HUP $(pgrep headscale)
# Or use the convenience script
./skills/tailnet-policy/reload-headscale-policy.sh
```
## Writing Policy
### Allow-All (default-open)
```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"]
}
}
```
### Deny-All (default-closed)
```hujson
{
"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"]
}
}
```
### Segmented (environments)
```hujson
{
"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"]
}
}
```
### Tag-Based Patterns
Tags are node-level identifiers set via `tailscale up --advertise-tags=tag:dev`. They decouple policy from user identity.
```hujson
{
"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 Syntax
Grants are the modern policy primitive:
```hujson
{
"grants": [
{
"src": ["tag:source", "user@example.com"],
"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 entities
- **`ip`** — Protocol and port filter (e.g. `tcp:80`, `udp:53`, `*:*`, `*`)
- **`proto`** — Protocol constraint (`tcp`, `udp`, `icmp`)
- **`via`** — Route through a specific exit node or relay
## Auto Approvers
Auto-approvers let specific users approve subnet routes and exit nodes without manual intervention:
```hujson
{
"autoApprovers": {
"routes": {
"10.0.0.0/8": ["autogroup:admin"],
"172.16.0.0/12": ["alice@example.com"]
},
"exitNode": ["autogroup:admin"]
}
}
```
- `routes`: Maps CIDR ranges to lists of users who can auto-approve those routes
- `exitNode`: Lists users who can advertise exit nodes
## Autogroups
Autogroups 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 Configuration
Tailscale SSH rules are configured via the `ssh` section:
```hujson
{
"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/groups
- `dst`: Destination tags/users
- `users`: Which OS users can be SSH'd into
## Testing Policies
Policy files include test definitions that are validated when loaded:
```hujson
{
"grants": [...],
"tests": [
{
"src": "alice@example.com",
"dst": "tag:webserver",
"ip": ["tcp:443"],
"action": "accept" // expected result
},
{
"src": "bob@example.com",
"dst": "tag:database",
"ip": ["tcp:22"],
"action": "drop" // expected result
}
]
}
```
Validate tests with:
```bash
./skills/tailnet-policy/validate-policy.py --policy policy.hujson
```
## Gotchas
- **Headscale does NOT support device posture** — rules like `devicePosture` or `device:managed` are Tailscale-only
- **Headscale does NOT support IP sets** — `ipSets` and `ipprotocol` are not supported
- **Headscale does NOT support OIDC groups in ACLs** — groups from OIDC claims cannot be used in policy; use `autogroup:admin` and `autogroup:member` instead
- **Tag names must start with `tag:`** and contain only lowercase letters, numbers, and hyphens
- **Policy reload via SIGHUP does not return errors on failure** — always validate before reloading
- **ACL `users` field and Grant `src` field are NOT interchangeable** — grants use `src`/`dst`, legacy ACLs use `users`/`ports`
- **Tests are not enforced at runtime** — they only validate during parsing; a passing test does not guarantee runtime behavior
## Trigger Conditions
This skill is automatically loaded when the user's message contains any of these keywords:
- tailnet policy
- headscale acl
- hujson policy
- tailscale grant
- tagowners
- autoapprovers
- tailscale ssh policy
- policy validation
- migrate acls
- /etc/headscale/policy
- policy.hujson
## When not to use
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.
Pliki w paczce (6)
- README.md 1 KB
- SKILL.md 8 KB
- evals/evals.json 6 KB
- scripts/migrate-acls-to-grants.py 14 KB
- scripts/reload-headscale-policy.sh 5 KB
- scripts/validate-policy.py 18 KB
Wersje
W bazie nie ma innych skilli o nazwie tailnet-policy.
Migawka bazy z 28.10.2026 · wersja paczki d7ad6d44f9aa (skrót SHA-256 całej paczki)
Pobrania w ostatnich 30 dniach: 0 · ranking
Zgłoś problem z tym skillem: szkodliwa treść, błędny opis albo prośba autora o usunięcie.
Podobne skille
- 100tailscale
Wdraża i zarządza ekosystemem Tailscale i Headscale: serwer kontrolny, klienci, polityki ACL, cykl życia węzłów, subnet routing, przekaźniki DERP, kopie zapasowe i migracja. - 100tailscale-helper
Wspiera pracę z siecią Tailscale VPN: operacje CLI, MagicDNS, ACL, SSH, funnel, serve i administracja siecią. - 100tailscale
Odpytuje i zarządza siecią Tailscale z Claude przez serwer tailscale-rmcp: urządzenia, status tailnetu, ACL, trasy podsieci i klucze API. - 100tailscale-operator
Zarządza urządzeniami w tailnecie Tailscale, łączy się z nimi i diagnozuje problemy: adresy IP, SSH, logowanie kluczem publicznym, Tailscale SSH i uprawnienia sudo na zdalnych Macach i hostach Linux. - 100tailscale-cli
Pomaga w pracy z poleceniami tailscale: diagnostyka łączności, status, tailscale serve, funnel i Services, także w mieszanej tailnecie z węzłami macOS i Linux. - 100tailscale-client
Instaluje, konfiguruje i diagnozuje oficjalnego klienta Tailscale połączonego z samodzielnie hostowanym serwerem Headscale: nowe urządzenia, status peerów i przekaźniki DERP.