Skip to content

Alloy Role

Overview

Grafana Alloy (formerly Grafana Agent) is a flexible telemetry collector for logs, metrics, and traces. In solti-monitoring, Alloy is primarily used for log collection and shipping to Loki. It can collect logs from multiple sources like files and journald, parse and label them with metadata, and ship them to Loki for storage and querying, supporting complex log processing pipelines.

Requirements

  • Ansible 2.9+
  • A running Loki instance to receive logs.

Installation / Quick Start

The alloy role installs and configures Alloy on target hosts.

Ansible Galaxy

- role: jackaltx.solti_monitoring.alloy
  vars:
    alloy_loki_endpoint: "http://monitor.example.com:3100"
    alloy_config_sources:
      - fail2ban
      - apache
      - syslog

Role Variables / Configuration

Loki Output

Name Description Default
alloy_loki_endpoint Loki API endpoint. http://127.0.0.1:3100
alloy_loki_auth Enable if using authentication. false

Log Sources

Name Description Default
alloy_config_sources List of log sources to configure. []

Available sources: - fail2ban - Security ban/unban events - apache - Apache access and error logs - bind9 - DNS query logs - mail - Postfix/mail system logs - wireguard - VPN connection logs - gitea - Git service logs - syslog - System logs via journald

Service Arguments

Name Description Default
alloy_args List of arguments for the Alloy service. []

Usage

Example of using the role with a custom configuration:

- role: jackaltx.solti_monitoring.alloy
  vars:
    alloy_loki_endpoint: "http://10.10.0.11:3100"
    alloy_config_sources:
      - name: fail2ban
        type: journald
        matches:
          - "_SYSTEMD_UNIT=fail2ban.service"
        labels:
          service_type: "fail2ban"

      - name: apache
        type: file
        path: "/var/log/apache2/access.log"
        labels:
          service_type: "web"
          log_type: "access"
    alloy_args:
      - "--disable-reporting"
      - "--server.http.listen-addr=127.0.0.1:12345"

Service Management

Commands for checking status, viewing logs, and restarting the service.

# Check status
systemctl status alloy

# View logs
journalctl -u alloy -f

# Restart service
systemctl restart alloy

Alloy also supports live config reload (experimental):

# Send SIGHUP to reload config
systemctl reload alloy

Troubleshooting

Check Service Status

systemctl status alloy
journalctl -u alloy -n 50

Validate Configuration

alloy fmt /etc/alloy/config.alloy
alloy validate /etc/alloy/config.alloy

Test Loki Connection

curl http://monitor.example.com:3100/ready

View Alloy Metrics

Alloy exposes metrics about itself:

curl http://127.0.0.1:12345/metrics

Common Issues

  1. Config syntax errors: Run alloy validate before deploying
  2. Connection to Loki failed: Check network and Loki status
  3. No logs appearing: Verify log sources are active and matches are correct
  4. High memory usage: Reduce log volume or processing complexity

Role-Specific Sections

Alloy Configuration Language

Alloy uses its own configuration language (River format):

// Log source from journald
loki.source.journal "fail2ban" {
  matches {
    _SYSTEMD_UNIT = "fail2ban.service"
  }

  labels = {
    service_type = "fail2ban",
    hostname     = env("HOSTNAME"),
  }

  forward_to = [loki.write.default.receiver]
}

// Loki endpoint
loki.write "default" {
  endpoint {
    url = "http://10.10.0.11:3100/loki/api/v1/push"
  }
}

Configuration Validation Workflow

IMPORTANT: Always validate configuration before deploying!

Test Workflow

# Validates config without restarting service
alloy fmt /tmp/config.alloy
alloy validate /tmp/config.alloy

Deploy Workflow Only deploy after successful validation:

# 1. Test (safe, no service restart)
ansible-playbook test-alloy-config.yml

# 2. Deploy (writes config and restarts)
ansible-playbook deploy-alloy.yml

Log Parsing and Labeling

Apply transformations and parsing:

// Parse fail2ban logs
loki.process "fail2ban" {
  forward_to = [loki.write.default.receiver]

  stage.regex {
    expression = "\[(?P<jail>[^\]]+)\]\s+(?P<action>Ban|Unban)\s+(?P<ip>\d+\.\d+\.\d+\.\d+)"
  }

  stage.labels {
    values = {
      jail = "",
      action = "",
      banned_ip = "ip",
    }
  }
}

Multi-Destination Setup

Ship logs to multiple Loki instances:

loki.write "primary" {
  endpoint {
    url = "http://primary.example.com:3100/loki/api/v1/push"
  }
}

loki.write "backup" {
  endpoint {
    url = "http://backup.example.com:3100/loki/api/v1/push"
  }
}

// Forward to both
loki.source.journal "logs" {
  // ... config ...
  forward_to = [
    loki.write.primary.receiver,
    loki.write.backup.receiver,
  ]
}

Fail2ban Journald Migration

As of 2026-01-01, fail2ban logs moved from file-based to journald.

OLD configuration (deprecated):

loki.source.file "fail2ban" {
  targets = [{
    __path__ = "/var/log/fail2ban.log",
  }]
}

NEW configuration (current):

loki.source.journal "fail2ban" {
  matches {
    _SYSTEMD_UNIT = "fail2ban.service"
  }
  labels = {
    service_type = "fail2ban",
  }
}

Reference

License

MIT

Author

Created by jackaltx and Claude.