> ## Documentation Index
> Fetch the complete documentation index at: https://verifyngo.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Core configuration fields for verifyngo's config.json file

> Configure listen address, upstream URL, cookie settings, trusted proxies, whitelist, default action, and path bypass rules in config.json.

verifyngo reads all of its settings from a single `config.json` file in the current directory. If you want to store the file somewhere else, pass the path with the `-config` flag when you start verifyngo (e.g. `-config /etc/verifyngo/config.json`). This page covers the core fields that control how verifyngo listens for incoming connections, where it forwards verified requests, and which requests skip the challenge entirely.

## Fields

<ParamField body="listen_addr" type="string">
  The address and port verifyngo binds to. Change this if you need verifyngo to
  listen on a different interface or port — for example, `"0.0.0.0:8080"` to
  accept connections on all interfaces. A common value is `"127.0.0.1:8080"`.
</ParamField>

<ParamField body="upstream_url" type="string" required>
  The URL of the service that verifyngo proxies verified requests to. Set this
  to the address your application is listening on, e.g. `"http://127.0.0.1:3000"`.
</ParamField>

<ParamField body="cookie_secret" type="string" required>
  A secret value used to sign the verified cookie. Anyone who knows this value
  can forge verified cookies, so keep it private. Generate a strong value with:

  ```bash theme={null}
  openssl rand -hex 32
  ```

  **Never commit this value to source control.**
</ParamField>

<ParamField body="cookie_name" type="string" default="cp_verified">
  The name of the cookie that verifyngo sets in the visitor's browser after they
  successfully complete a CAPTCHA.
</ParamField>

<ParamField body="cookie_ttl" type="string" default="168h">
  How long the verified cookie stays valid before the visitor must complete the
  challenge again. Uses Go's duration format — valid examples are `"24h"`,
  `"48h"`, `"168h"`. Note that `"7d"` is **not** valid; use `"168h"` for 7
  days instead.
</ParamField>

<ParamField body="default_action" type="string" default="challenge">
  What verifyngo does when a request doesn't match any rule. Accepted values are:

  * `"allow"` — let the request through without a challenge.
  * `"challenge"` — show the CAPTCHA challenge page.
  * `"deny"` — block the request outright.
</ParamField>

<ParamField body="whitelist" type="string[]">
  A list of IP addresses or CIDR blocks that always bypass the challenge,
  regardless of rules or the default action. Useful for your own monitoring
  systems, internal tooling, or trusted partners.

  ```json theme={null}
  "whitelist": ["203.0.113.10", "198.51.100.0/24"]
  ```
</ParamField>

<ParamField body="bypass_paths" type="string[]">
  A list of regular expressions matched against the request path. Any path that
  matches is proxied directly to the upstream without any challenge check — it
  won't count toward walk-away limits either. Set to `[]` to disable the bypass
  list entirely.

  ```json theme={null}
  "bypass_paths": ["\\.(?:css|js|png|jpg|gif|svg|webp|woff2?)$"]
  ```

  If you omit this field, verifyngo uses the built-in default list (see the note
  below).
</ParamField>

<ParamField body="always_pass_paths" type="string[]">
  A list of regular expressions matched against the request path. Any path that
  matches is always allowed through, even if a rule would otherwise deny it.
  Use this for health-check or status endpoints that must remain reachable at
  all times.

  ```json theme={null}
  "always_pass_paths": ["^/health$", "^/healthz$", "^/status$"]
  ```
</ParamField>

<ParamField body="trust_real_ip" type="boolean" default="false">
  When set to `true`, verifyngo reads the client's IP address from the
  `X-Forwarded-For` header instead of the direct connecting IP. Enable this
  when verifyngo sits behind another reverse proxy (such as nginx or Caddy)
  that sets this header.
</ParamField>

<ParamField body="trusted_proxies" type="string[]">
  A list of IP addresses or CIDR blocks that are trusted to supply an accurate
  `X-Forwarded-For` header. This field is only relevant when `trust_real_ip`
  is `true`. If your upstream proxy connects from a non-private, non-loopback
  address, you must list it here — otherwise verifyngo will warn you and
  fall back to trusting only loopback and private-range IPs.

  ```json theme={null}
  "trusted_proxies": ["10.0.0.1", "172.16.0.0/12"]
  ```
</ParamField>

<Note>
  When `bypass_paths` is omitted from your config, verifyngo uses a built-in
  default list that covers `favicon.ico`, `robots.txt`, `sitemap.xml`,
  `/.well-known/*`, common manifest files (`manifest.json`,
  `site.webmanifest`), `browserconfig.xml`, Apple touch icons, and all static
  asset extensions: `.css`, `.js`, `.mjs`, `.png`, `.jpg`/`.jpeg`, `.gif`,
  `.svg`, `.webp`, `.avif`, `.ico`, `.woff`/`.woff2`, `.ttf`, `.otf`, `.eot`,
  `.wasm`, `.mp4`, and `.webm`. Requests to these paths never count toward
  walk-away limits.
</Note>

## Minimal example

The following `config.json` shows the smallest set of fields you need to get
verifyngo running with sensible defaults:

```json config.json theme={null}
{
  "listen_addr": "127.0.0.1:8080",
  "upstream_url": "http://127.0.0.1:3000",
  "cookie_secret": "replace-with-output-of-openssl-rand-hex-32",
  "cookie_name": "cp_verified",
  "cookie_ttl": "168h",
  "default_action": "challenge",
  "whitelist": ["203.0.113.10", "198.51.100.0/24"],
  "bypass_paths": [],
  "always_pass_paths": ["^/health$"],
  "trust_real_ip": false,
  "trusted_proxies": []
}
```
