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 useremoteAddress.network(...)).conditions— reusable named condition groups (optional).rules— the ordered list of rules to evaluate (required).
examples/policy.yaml:
Defining networks
Thenetworks 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 therules 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.
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 theUser-Agentrequest 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 totrueif 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 ifstrcontainssubstr.startsWith(str, prefix)— true ifstrstarts withprefix.matches(str, regex)— true ifstrmatches the regular expressionregex.
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 underconditions 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.