// Prometheus metrics collection prometheus.exporter.unix "node" { rootfs_path = "/host/root" sysfs_path = "/host/sys" procfs_path = "/host/proc" textfile { directory = "/host/root/var/lib/node_exporter/textfile_collector" } set_collectors = ["cpu", "loadavg", "meminfo", "diskstats", "filesystem", "netdev", "textfile"] } prometheus.scrape "node_exporter" { targets = prometheus.exporter.unix.node.targets forward_to = [prometheus.remote_write.metrics.receiver] } prometheus.scrape "alloy" { targets = [{ __address__ = "localhost:{{ alloy_port }}", }] forward_to = [prometheus.remote_write.metrics.receiver] } prometheus.exporter.cadvisor "docker" { docker_host = "unix:///var/run/docker.sock" docker_only = true } prometheus.scrape "cadvisor" { targets = prometheus.exporter.cadvisor.docker.targets forward_to = [prometheus.remote_write.metrics.receiver] } prometheus.remote_write "metrics" { endpoint { url = "http://prometheus:{{ prometheus_port }}/api/v1/write" } } // Journal log collection (includes both system logs and Docker containers) loki.source.journal "journal" { forward_to = [loki.process.journal.receiver] relabel_rules = loki.relabel.journal.rules labels = { job = "journal", } } loki.relabel "journal" { forward_to = [] // Systemd unit (e.g., ssh.service, docker.service) rule { source_labels = ["__journal__systemd_unit"] target_label = "unit" } // Container name for Docker containers rule { source_labels = ["__journal_container_name"] target_label = "container" } // Syslog priority (0=emerg, 1=alert, 2=crit, 3=err, 4=warn, 5=notice, 6=info, 7=debug) rule { source_labels = ["__journal_priority"] target_label = "priority" } // Syslog identifier (program name) rule { source_labels = ["__journal_syslog_identifier"] target_label = "syslog_identifier" } // Tag tuwunel container with its own job label rule { source_labels = ["__journal_container_name"] regex = "tuwunel" target_label = "job" replacement = "tuwunel" } } loki.process "journal" { forward_to = [loki.write.logs.receiver] // Extract log level from common formats: level=info, "level":"info", [INFO], etc. stage.regex { expression = "(?i)(level=|\"level\":\\s*\"|\\[)(?Pdebug|info|warn|warning|error|err|fatal|panic|critical|crit|notice)(\\]|\"|\\s|$)" } // Map extracted level to numeric priority for consistent filtering stage.template { source = "level" template = "{% raw %}{{ if .extracted_level }}{{ .extracted_level }}{{ else }}{{ .priority }}{{ end }}{% endraw %}" } stage.labels { values = { level = "", } } } loki.write "logs" { endpoint { url = "http://loki:{{ loki_port }}/loki/api/v1/push" } } // Fail2ban log file collection (ban/unban details go to file, not journald) local.file_match "fail2ban" { path_targets = [{"__path__" = "/host/root/var/log/fail2ban.log"}] } loki.source.file "fail2ban" { targets = local.file_match.fail2ban.targets forward_to = [loki.process.fail2ban.receiver] } loki.process "fail2ban" { forward_to = [loki.write.logs.receiver] stage.static_labels { values = { job = "fail2ban", unit = "fail2ban.service", } } stage.regex { expression = "(?i)\\s(?Pnotice|warning|error|info)\\s" } stage.labels { values = { level = "extracted_level", } } } // Rspamd log file collection (logs to file inside mailserver, not stdout) local.file_match "rspamd" { path_targets = [{"__path__" = "/host/root/srv/mail/maillogs/rspamd.log"}] } loki.source.file "rspamd" { targets = local.file_match.rspamd.targets forward_to = [loki.process.rspamd.receiver] } loki.process "rspamd" { forward_to = [loki.write.logs.receiver] stage.static_labels { values = { container = "mailserver", job = "rspamd", } } }