Skip to main content
The YAML policy file gives you more advanced traffic control than inline rules or the plain-text rules file. It lets you define named network groups — built from ASNs, CIDR ranges, remote URLs, or local files — and then write rules with flexible boolean conditions that reference those groups. To enable it, set policy_file in config.json to the path of your YAML file. When policy_file is set, it takes priority over rules_file and any inline rules defined in config.json.

Structure of a policy file

A policy file has up to three top-level keys:
  • networks — named groups of IP ranges (required if your rules use remoteAddress.network(...)).
  • conditions — reusable named condition groups (optional).
  • rules — the ordered list of rules to evaluate (required).
Below is the example policy from examples/policy.yaml:

Defining networks

The networks section maps a name to one or more source entries. verifyngo resolves all entries at startup and builds a fast lookup table for checking IPs at request time. You can mix source types within the same group. For url and file sources you can add a jq-path key to extract CIDRs from a JSON response, or a regex key with a named capture group called prefix to extract CIDRs from arbitrary text.

Writing rules

Each rule in the rules list has a name, one or more conditions, and an action. Rules are evaluated top to bottom; the first matching rule wins. If no rule matches, default_action from config.json applies. Available actions are allow / pass (let the request through), challenge / check (serve a CAPTCHA), and deny / drop (block immediately). The paired words are aliases for the same behaviour.
When a rule has more than one condition, all conditions must be true for the rule to match (logical AND).

Condition variables

These variables are available in every condition expression:
  • path — the request URL path string (e.g. "/blog/post-1").
  • userAgent — the value of the User-Agent request header.
  • method — the HTTP method (GET, POST, etc.).
  • ip — the client IP address as a string.
  • headers["Header-Name"] — the value of any request header, accessed by its exact name.
  • remoteAddress.network("name") — evaluates to true if the client IP is a member of the named network group.

Condition functions

Three helper functions are available for string matching:
  • contains(str, substr) — true if str contains substr.
  • startsWith(str, prefix) — true if str starts with prefix.
  • matches(str, regex) — true if str matches the regular expression regex.
You can also call these as methods: userAgent.contains("bot"), path.startsWith("/api"), path.matches("^/post/[0-9]+").

Named condition groups

If the same set of conditions appears in multiple rules, define it once under conditions and reference it in rules using ($name). When a rule contains a ($name) reference, verifyngo expands the group inline and OR-joins the individual expressions within it before applying the rule’s AND logic.
Hot-reload applies to the policy file too. verifyngo watches the file and picks up any changes within about 10 seconds — no restart required.