Valerter

Configuration Reference

Valerter is configured via a YAML file, typically at /etc/valerter/config.yaml.

See config/config.example.yaml for a complete annotated example.

Configuration File

Location Description
/etc/valerter/config.yaml Default location (systemd)
Custom path via -c flag valerter -c /path/to/config.yaml

Security: The file should be owned by valerter:valerter with mode 600 (owner read/write only).

Multi-File Configuration

For large deployments, you can split rules, templates, and notifiers into separate files in .d/ directories alongside config.yaml:

/etc/valerter/
├── config.yaml         # Main config
├── rules.d/
│   ├── security.yaml   # Security team rules
│   └── infra.yaml      # Infrastructure rules
├── templates.d/
│   └── custom.yaml     # Custom templates
└── notifiers.d/
    └── team-channels.yaml

Format in .d/ Files

Files in .d/ directories use a HashMap format where the name is the YAML key:

# rules.d/security.yaml
auth_failure:
  query: "_msg:authentication AND status:failed"
  parser:
    json:
      fields: [user, ip]
  notify:
    template: "security_alert"
    destinations:
      - security-team

brute_force:
  query: "_msg:blocked"
  parser:
    regex: "IP (?P<ip>\\d+\\.\\d+\\.\\d+\\.\\d+)"
  notify:
    template: "security_alert"
    destinations:
      - security-team
# templates.d/custom.yaml
security_alert:
  title: "Security: "
  body: ""
  accent_color: "#ff0000"
# notifiers.d/team-channels.yaml
security-team:
  type: mattermost
  webhook_url: "https://mattermost.example.com/hooks/security"

infra-team:
  type: mattermost
  webhook_url: "https://mattermost.example.com/hooks/infra"

Rules

Collision Detection

If the same name is defined in multiple files, Valerter fails at startup with an explicit error:

Error: duplicate rule name 'my_rule': defined in 'config.yaml' and 'rules.d/extra.yaml'

Structure Overview

victorialogs:    # VictoriaLogs connection (REQUIRED)
metrics:         # Prometheus metrics (optional)
notifiers:       # Named notification channels (recommended)
defaults:        # Default throttle and notify settings (REQUIRED)
templates:       # Message templates (REQUIRED)
rules:           # Alert rules (REQUIRED, at least one)

VictoriaLogs Sources (multi-source)

victorialogs is a map of named sources. A single valerter instance can tail multiple VL backends concurrently and route alerts per source. At least one source is required.

victorialogs:
  default:                            # Source name (used as `vl_source`)
    url: "http://victorialogs:9428"   # REQUIRED

    # Optional: Basic Authentication (per-source)
    basic_auth:
      username: "${VL_USER}"
      password: "${VL_PASS}"

    # Optional: Custom headers (for tokens, API keys)
    headers:
      Authorization: "Bearer ${VL_TOKEN}"

    # Optional: TLS configuration
    tls:
      verify: true    # Set to false for self-signed certs

Multi-source example

victorialogs:
  vlprod:
    url: "https://victorialogs.prod.example.com:9428"
    basic_auth:
      username: "${VL_PROD_USER}"
      password: "${VL_PROD_PASS}"
  vldev:
    url: "http://victorialogs.dev.internal:9428"

Rules can target a subset of sources via vl_sources: [name, ...], or omit the field to fan out across every configured source. The current source name is exposed in templates as `` (layer 1 templates, throttle.key, and notifier-level layer 2 contexts).

Migration from v1.x (breaking change)

The v1.x single-URL shape (victorialogs.url: ... at the top level) is rejected at load with a clear error. Wrap your existing settings under a named key (we recommend default for single-source deployments):

# Before (v1.x):
victorialogs:
  url: "http://victorialogs:9428"
  basic_auth:
    username: "u"
    password: "p"

# After (v2.0+):
victorialogs:
  default:
    url: "http://victorialogs:9428"
    basic_auth:
      username: "u"
      password: "p"

The default throttle key also changed from {rule}:global to {rule}-{source}:global so multi-source buckets are isolated by default. To preserve v1.x cross-source dedup, set throttle.key: "" explicitly on the rules that need it.

Reverse Proxy Configuration

If VictoriaLogs is behind a reverse proxy (nginx, Traefik, etc.), you must disable buffering and caching for the /select/logsql/tail endpoint. Valerter uses HTTP streaming to receive logs in real-time, and proxy buffering will cause delays or connection issues.

Nginx example:

# Add this BEFORE your general /select location block
location = /select/logsql/tail {
    proxy_pass http://victorialogs_backend;

    # CRITICAL: Disable buffering and caching for streaming
    proxy_buffering off;
    proxy_cache off;

    # Long timeouts for persistent connections
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;

    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Key settings:

Defaults

Default values applied to all rules unless overridden.

defaults:
  throttle:
    count: 5         # Max alerts per window
    window: 60s      # Time window (e.g., 60s, 5m, 1h)
  # timestamp_timezone: "Europe/Paris"  # Optional: timezone for formatted timestamps (default: UTC)
  # max_streams: 50                     # Optional: hard cap on total VictoriaLogs streams (default: 50)

max_streams — fan-out guardrail

Multi-source deployments spawn one stream per (enabled rule, target source) pair. With unscoped fan-out rules and many sources the total scales as rules × sources, which can DoS a backend by accident. defaults.max_streams caps that total at load time:

total = sum(if rule.vl_sources is empty then sources.len() else rule.vl_sources.len()
            for rule in enabled_rules)

Disabled rules do not contribute. Breaching the cap fails valerter --validate with a message stating both the actual count and the cap so an operator knows whether to raise the cap or trim rules. Default: 50.

Timestamp Timezone

The timestamp_timezone setting controls the timezone used for `` in templates and Mattermost footers.

Value Example Output
UTC (default) 15/01/2026 10:00:00 UTC
Europe/Paris 15/01/2026 11:00:00 CET (winter) / CEST (summer)
America/New_York 15/01/2026 05:00:00 EST

Uses IANA timezone names. Invalid timezone will fail at startup.

Templates

Message templates use Jinja2 syntax (via minijinja).

templates:
  default_alert:
    title: ""           # REQUIRED
    body: ""                                 # REQUIRED
    email_body_html: "<p></p>"                     # REQUIRED for email destinations
    accent_color: "#ff0000"                            # Optional: hex color

Available Variables

Variables come from the parser output plus built-in fields:

Variable Description
rule_name Name of the rule that triggered
vl_source Name of the VictoriaLogs source the event came from
_msg Original log message (from VictoriaLogs)
_time Log timestamp (raw from VictoriaLogs)
_stream Stream labels
log_timestamp Original log timestamp in ISO 8601 format (for VictoriaLogs search)
log_timestamp_formatted Human-readable timestamp (respects timestamp_timezone setting)
Custom fields Extracted by regex/JSON parser

Note: rule_name and vl_source are available in all template contexts: the top-level template fields (title, body, email_body_html), the throttle.key, and the notifier-level templates (subject_template, body_template). If an event field happens to be named rule_name or vl_source, the synthetic value wins.

Note: log_timestamp and log_timestamp_formatted are available in:

These timestamps are computed after the top-level template renders, so they are only accessible in notifier-level templates. If you need a timestamp at the top-level, reference `` (raw VictoriaLogs field) directly.

email_body_html Requirement

Important: Templates used with email destinations MUST include email_body_html. Valerter validates this at startup and will fail if missing.

Rules

Alert rules define what logs to monitor and how to process them.

rules:
  - name: "high_cpu_alert"           # REQUIRED: unique name
    enabled: true                     # Default: true
    query: '_stream:{host="server1"} | json | cpu > 90'    # REQUIRED: LogsQL

    parser:                           # At least one recommended
      json:
        fields: ["host", "cpu", "timestamp"]
      # OR
      regex: '(?P<level>\S+) (?P<message>.*)'

    throttle:                         # Optional: overrides defaults
      key: ""               # Group throttling by field
      count: 3
      window: 5m

    vl_sources: [vlprod]              # Optional: target specific sources
                                      # Empty/omitted = fan out across all
                                      # sources defined in `victorialogs:`.
                                      # Unknown names rejected at load.

    notify:                           # REQUIRED
      template: "custom_template"     # REQUIRED: template name
      destinations:                   # REQUIRED: at least one notifier
        - mattermost-ops
        - email-ops
      mattermost_channel: "alerts"    # Optional: override Mattermost channel

Parser Types

JSON Parser: Extract specific fields from JSON logs.

parser:
  json:
    fields: ["host", "level", "message", "timestamp"]

Regex Parser: Extract fields using named capture groups.

parser:
  regex: '(?P<timestamp>\S+) (?P<level>\S+) (?P<message>.*)'

Throttling

Prevents alert spam by limiting notifications per time window.

Field Description
key Template to group alerts (e.g., ``)
count Max alerts per window
window Time window (e.g., 30s, 5m, 1h)

Example: Max 3 alerts per host per 5 minutes:

throttle:
  key: ""
  count: 3
  window: 5m

Secrets Management

Put secrets directly in the config file and secure with permissions:

notifiers:
  mattermost-ops:
    type: mattermost
    webhook_url: "https://mattermost.example.com/hooks/abc123def456"
sudo chmod 600 /etc/valerter/config.yaml
sudo chown valerter:valerter /etc/valerter/config.yaml

Alternative: Environment Variables

For Kubernetes or orchestrators, use ${VAR_NAME} syntax:

notifiers:
  mattermost-ops:
    type: mattermost
    webhook_url: "${MATTERMOST_WEBHOOK}"

Variables are resolved at startup from the process environment. You can use any environment variable - there is no predefined list. Common examples:

Runtime Environment Variables

These variables are read directly by the process (not substituted in config):

Variable Description
RUST_LOG Log level: error, warn, info (default), debug, trace
LOG_FORMAT Output format: text (default), json

CLI Options

valerter [OPTIONS]

Options:
  -c, --config <PATH>  Path to configuration file [default: /etc/valerter/config.yaml]
      --validate       Validate configuration and exit
  -h, --help           Print help
  -V, --version        Print version

Validation

Always validate before deploying:

valerter --validate

This checks:

See Also