Migrating from Promtail to Alloy for Log Collection
July 21, 2026 · By Justyn Larry
TL;DR: Promtail reached end of life in March 2026, making Alloy the supported replacement for shipping logs to Loki. The migration is mostly a matter of replacing Promtail’s scrape configuration with Alloy’s loki.source.*, loki.process, and loki.write components. The biggest pitfall isn’t the configuration itself. It’s assuming how a host writes logs. Detect whether a machine uses the systemd journal or log files before configuring Alloy, or you may end up silently collecting nothing.
In this article I discussed moving host metrics from a scraped node_exporter to a push-based Alloy agent, and followed it up with a piece comparing Alloy against Prometheus Agent mode. Both of those articles discussed metrics and how they move between the host and client nodes. This post covers the log-shipping portion of the same story, and it has a deadline attached that the metrics migration didn’t.
Promtail reached end of life on March 2, 2026. It continues to function, but it no longer receives bug fixes or security updates. If you are shipping logs to Loki with Promtail today, you are running an unmaintained agent, and the replacement Grafana points you at is the same Alloy you may already be running for metrics. If you’re already running Alloy for metrics, the log migration is mostly adding components to a config that already exists. If you’re not, this article will strengthen the case for consolidating onto Alloy rather than running a separate, now-unmaintained log agent.
PROMTAIL
Journal/File Logs
|
v
Promtail
|
v
Loki
ALLOY
Journal/File Logs
|
v
loki.source.*
|
v
loki.process
|
v
loki.write
|
v
Loki
// WHAT ACTUALLY CHANGES
Promtail is a standalone binary with its own YAML config: scrape_configs, clients, a positions file, built for one job. Alloy replaces that YAML configuration with a component-based pipeline. The host produces log entries, Alloy processes them if required, and forwards them to Loki. There are three component types, all wired together with forward_to references.
The three core components map almost directly onto what Promtail did:
loki.source.journal reads the systemd journal, replacing Promtail’s journal scrape config.
loki.source.file tails log files on disk, replacing Promtail’s file-based scrape_configs.
loki.write pushes to Loki, replacing Promtail’s clients block.
Between the source and destination, loki.process handles parsing, filtering, label manipulation, and other pipeline stages that previously lived inside Promtail.
// THE JOURNAL CASE
Most modern Linux hosts log to the systemd journal, so this is the common path. Alloy uses two components: a source that reads the journal and forwards to a processing stage, and that stage attaching labels before the write.
loki.source.journal "systemd_journal" {
forward_to = [loki.process.add_labels.receiver]
}
The source reads the journal and hands each line to a loki.process component named add_labels, which is where I attach the same tenant, cluster, environment, and role labels that ride along with the metrics from that host, to help maintain separation between clients. You can read more about my tenant isolation model here. Labeling logs and metrics identically at the edge is what lets me line them up later in Grafana, and it is worth getting consistent from the first host rather than fixing it in queries forever after.
// THE FILE-BASED CASE
Some hosts, older ones especially, still write to plain log files instead of the journal. For those, the source is a file matcher plus a file reader:
local.file_match "logs" {
path_targets = [
{"__path__" = "/var/log/syslog"},
{"__path__" = "/var/log/auth.log"},
{"__path__" = "/var/log/messages"},
{"__path__" = "/var/log/secure"},
]
}
loki.source.file "log_scrape" {
targets = local.file_match.logs.targets
forward_to = [loki.process.add_labels.receiver]
}
local.file_match resolves glob patterns into concrete targets, and loki.source.file tails whatever it finds. I list both Debian-family paths (syslog, auth.log) and RHEL-family ones (messages, secure) because which files exist depends on the distro, and a path that does not exist is simply skipped rather than throwing an error. In practice I detect which log method a host actually uses at install time and inject only the matching block, rather than shipping both to every machine.
// THE TRAP: DON’T GUESS THE LOG METHOD BY DISTRO
I learned this lesson the hard way. I assumed Debian meant /var/log/syslog and RHEL meant journald.
I thought that the obvious way to decide between journal and file collection was to base it on distro family. Debian and Ubuntu write to /var/log/syslog, so I could use file collection; RHEL and its relatives lean on the journal, so for those I could use journal collection. That doesn’t really cover edge cases, and led to problems. It’s bad practice to assume you know what someone else’s system is doing. Plenty of Debian systems have rsyslog disabled or absent and log only to the journal, while some hosts have been configured against type by whoever set them up. Setting your system up based on assumptions dictated simply by distro is the wrong approach. Alloy starts up cleanly, reports itself healthy, and quietly ships no logs, because it is watching a file that is never written or a journal that holds nothing useful, or nothing at all. The first indication anything is wrong is often during an incident, when the logs you expected simply aren’t there.
What actually works is an empirical check. Set the system up to look at whether the syslog files exist and are being written on that specific host, and then pick the method from that. I learned this the way most of these lessons get learned, by trusting the tidy assumption and then finding a gap in Loki that lined up exactly with the hosts where the assumption was false.
// MIGRATING WITHOUT A GAP
The safe sequence is the same shape as the metrics migration. Stand Alloy’s log collection up alongside Promtail rather than cutting over in place. Both can ship to the same Loki, and the extra resource overhead is negligible. You will get some duplicate lines during the overlap, which is a much better failure mode than a hole in your logs. Confirm in Grafana that the Alloy-sourced logs are arriving and carrying the right labels, then stop and remove Promtail. Verify the logs against the running system, not against the migration guide, and definitely not against your assumption about what the host is doing.
Loki deduplicates identical log entries that share the same labels. If Alloy adds even one different label, the same log line becomes part of a different stream and both copies remain visible. Get the label set matched before you tear the old agent down.
// WHERE THIS LEAVES YOU
If you already migrated metrics to Alloy, adding log collection is a handful of components in a config you are already maintaining. You can consolidate and have one agent doing both jobs, which was the whole argument for Alloy in the first place. If you are still on Promtail and have not started, the March 2026 end-of-life date makes this a little more urgent. The migration itself is not hard. The only genuinely dangerous part is the silent-failure trap, and that’s avoidable if you check what each host is actually doing instead of what its distro implies it should be doing.
If you have made this move already, I am curious whether you hit the journal-versus-file mismatch too, or whether your fleet was uniform enough that the distro heuristic held.