Skip to content

Your first policy

By default, Tyr runs deny-by-default with no policies assigned — meaning unless you ship rules, every governed action is denied. This guide walks you through applying a starter policy, assigning it, and observing evaluation.

1. Look at the example policies

The repo ships two starter policies:

Start with the default:

# examples/policies/default-policy.yaml (excerpt)
apiVersion: tyr.dev/v1
kind: Policy
metadata:
name: tyr-default
spec:
rules:
- name: alert-sensitive-file-writes
action: file_write
resource_pattern: "/etc/*"
verdict: alert
severity: high
- name: alert-process-execution
action: exec
verdict: alert
severity: medium

2. Log in and apply it

  1. Log in to the server:

    Terminal window
    tyr --server https://localhost:7701 login --username admin
    # prompts for password

    This stores a JWT in ~/.config/tyr/token.

  2. Apply the policy:

    Terminal window
    tyr policy apply -f examples/policies/default-policy.yaml

    Output:

    ✓ Applied policy version 1 (tyr-default)

    The server parsed the YAML, compiled it to Cedar + BPF map entries, and stored it as immutable version 1.

  3. Assign it to your agent:

    Terminal window
    tyr agent list
    # find the agent_id of "docker-host" (or your host name)
    tyr policy assign \
    --target-type daemon \
    --target-id <agent_id> \
    --version 1

    Within a few seconds, the agent receives the updated policy over gRPC and hot-reloads it in-kernel — no restart.

3. Observe

Tail live events:

Terminal window
tyr audit tail

Then run something triggering a rule on the monitored host:

Terminal window
# on the host where tyrd is running
echo test | sudo tee -a /etc/tyr-test.txt

You should see:

2026-04-20T10:45:02Z alert file_write /etc/tyr-test.txt pid=12345 tee

The event is also visible in the web UI at http://localhost:7701.

4. Go strict

When you trust your rules, apply the strict policy:

Terminal window
tyr policy apply -f examples/policies/strict-policy.yaml
tyr policy assign --target-type daemon --target-id <agent_id> --version 2

Now a file_write to /etc/* returns EPERM — the syscall fails at kernel level. The event is still captured with verdict deny.

Verdict pipeline

flowchart TD
Sys(["AI process syscall"]) --> Hook["eBPF LSM hook<br/>/ tracepoint"]
Hook -- allow --> Proceed["syscall proceeds"]
Hook -- deny --> Eperm["syscall returns EPERM"]
Hook -- alert --> Proceed2["syscall proceeds + event emitted"]
Hook --> RB[["ring buffer"]]
RB --> US["tyrd userspace<br/>(Cedar evaluate for richer rules)"]
US -- "gRPC / mTLS" --> Srv["tyr-server<br/>persist, drift-check, SSE"]

→ Next: Writing policies · Policy YAML reference