Przejdź do treści
Biblioteka skilli
DevOps i chmura · Integracja z narzędziem

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.

Repozytorium
agent-skills ↗
Licencja
MIT
Ostatnia zmiana repozytorium
25.10.2026

Ocena i bezpieczeństwo

100/ 100Klasa: dobry
Format25 / 25
Frontmatter z nazwą i opisem, poprawna nazwa, opis do 1024 znaków, nazwa zgodna z folderem.
Odkrywalność25 / 25
Opis mówi, kiedy użyć skilla, ma sensowną długość i jest w 3. osobie.
Treść35 / 35
Co najmniej 150 słów i do 500 linii, nagłówki, listy kroków, przykłady albo kod.
Higiena15 / 15
Bez zaślepek typu TODO, bez ścieżek Windows, z licencją.
Ryzykobrak sygnałów w skanie
Pliki w paczce
6
Skrypty
3
Komentarze HTML
0
Adresy URL w SKILL.md
0
Przestarzałość

Brak sygnałów. Repozytorium zmienione 25.10.2026, bez odwołań do wycofanych modeli i API.

Licencja

MIT, otwarta: można używać i zmieniać, z zachowaniem informacji o autorze.

Co sprawdzić przed instalacją
  • 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

  1. Security preflight
  2. Overview
  3. Policy Location
  4. Writing Policy
  5. Grants Syntax
  6. Auto Approvers
  7. Autogroups
  8. Tailscale SSH Configuration
  9. Testing Policies
  10. Gotchas
Sekcje z nagłówków SKILL.md, w oryginale · 298 linii, 1 023 słów
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.

Uwagi i zgłoszenia

Wiadomość trafi do Bartosza Sokolińskiego. Adres e-mail jest potrzebny tylko do odpowiedzi. Szczegóły w polityce prywatności.