# Migrating to Grafana Alloy from Promtail and Agent

> Promtail and Grafana Agent are both dead — here is how I moved a real Docker logging pipeline to Grafana Alloy, its OpenTelemetry Collector components, and the config syntax that replaces YAML.

URL: https://www.matthewswong.com/en/blog/grafana-alloy-opentelemetry-collector-migration/

- Author: Matthews Wong (https://www.matthewswong.com/en/about/)
- Published: 2026-07-10
- Updated: 2026-07-10
- Category: DevOps

> **Key takeaway:** Grafana Alloy is Grafana's OpenTelemetry Collector distribution and the only supported successor: Grafana Agent reached end-of-life on 1 November 2025 and Promtail on 2 March 2026. Migrate with the built-in alloy convert command, then rewrite pipelines as connected components using the Alloy configuration syntax.

I run a small fleet of services on a self-hosted VPS, and for years the logging story was Promtail tailing Docker files and shipping to Loki. That story is over. Grafana consolidated Promtail, Grafana Agent Static, and Grafana Agent Flow into a single collector called Alloy, and then set end-of-life dates on everything it replaced. If you are still on Promtail or Agent, you are running unsupported software on borrowed time.

The good news: Alloy is not a rewrite from scratch. It is a genuine OpenTelemetry Collector distribution that is fully OTLP-compatible, so the same binary now handles logs, metrics, traces, and profiles through one config. This post is the migration I actually did — the tooling, the components, and where the automated converter leaves you to finish the work by hand.

## Why Alloy, and why now

The deadlines are the forcing function. Grafana Agent (Static, Flow, and the Operator) hit end-of-life on 1 November 2025, meaning no more security patches or bug fixes. Promtail entered long-term support in February 2025 and reached end-of-life on 2 March 2026. All new feature development happens in Alloy only. Beyond the deadlines, the real win is consolidation: instead of Promtail for logs plus a separate Collector for OTLP traces, one Alloy process runs the whole telemetry pipeline with a single config language.

> Do not treat this as optional maintenance. Once a component is end-of-life, a single upstream CVE in a Go dependency has no patch coming. Running Promtail after March 2026 is a security decision, not a convenience one.

## The config syntax: components, not YAML blocks

Promtail was declarative YAML. Alloy uses a configuration syntax that started life under the name River — an HCL-like language built around components. A component is a named block that does one job: read files, relabel, batch, write to a backend. Each component exposes arguments you set and exported values other components consume. You wire them into a pipeline with the forward_to argument, which points one component's output at the next component's receiver. That reference graph is the pipeline; there is no separate pipelines section like the upstream Collector YAML has.

## Step 1: let alloy convert do the mechanical work

Do not hand-translate your existing config. Alloy ships a convert subcommand that reads your old Promtail, Agent Static, or Agent Flow file and emits equivalent Alloy syntax. For Promtail it targets the v2.8.x schema. The converter is best-effort: it prints diagnostics for anything it cannot map cleanly, and you resolve those manually. I always convert into a file first so I can read the diff before running anything.

## Step 2: understand the OpenTelemetry Collector side

This is where Alloy earns its description. Native Prometheus and Loki components (the loki.* and prometheus.* families) coexist with the full OTLP component set under the otelcol.* namespace. If you receive OTLP from an instrumented NestJS service, otelcol.receiver.otlp takes it, otelcol.processor.batch groups it, and otelcol.exporter.otlphttp ships it onward. Bridging is first-class: otelcol.exporter.loki converts OTLP logs into Loki entries, and otelcol.receiver.loki goes the other direction, so you can mix a legacy Loki push path with a modern OTLP path in one file.

## Component name mapping

Most of the migration is learning which Alloy component replaces each old concept. This is the cheat sheet I kept open the whole time.

| Old concept | Alloy component | Role |
| --- | --- | --- |
| Promtail scrape_configs (file) | loki.source.file | Tail log files by path |
| Promtail pipeline_stages | loki.process | Parse, relabel, extract fields |
| Promtail clients | loki.write | Push entries to Loki |
| Collector otlp receiver | otelcol.receiver.otlp | Ingest OTLP over gRPC or HTTP |
| Collector batch processor | otelcol.processor.batch | Group telemetry before export |
| Agent metrics scrape | prometheus.scrape | Pull Prometheus metrics |

## Where the converter left me hand-work

- Docker service discovery. Promtail's docker_sd relabel rules converted, but I re-checked every __meta_docker_* label because dropped or renamed labels silently break Loki queries downstream.
- Secrets. Inline tokens became plain strings. I moved them to environment variables read via the sys.env helper so nothing sensitive sits in the committed config.
- Multiline stages. Complex regex multiline joins needed manual verification against real log samples before I trusted them.
- Live debugging. Alloy's built-in UI on port 12345 shows each component's health and the live data flowing between them — it replaced most of my guesswork.

> Run the old and new collectors side by side into the same Loki, tagged with different job labels, for a few days. Compare line counts before you decommission Promtail. Converters get labels subtly wrong, and log gaps are invisible until you need the logs.

## Running it: Docker Compose

On my VPS everything is Docker Compose, so Alloy is just another service. Mount the config, expose the debug UI locally, and point it at the same log volumes Promtail used. The run flag matters: --stability.level for non-stable components, and the config path last.

That is the whole migration in shape: convert mechanically, learn the component graph, verify labels against real traffic, then cut over. The payoff is one agent instead of three, a single config language for logs and traces and metrics, and software that will still receive patches next quarter.

## Sources

- Grafana Alloy — Migrate from OpenTelemetry Collector
- Grafana Loki — Migrate to Alloy (from Promtail)
- Grafana Labs — From Agent to Alloy: why we transitioned

## Source links

- https://grafana.com/docs/alloy/latest/set-up/migrate/from-otelcol/
- https://grafana.com/docs/loki/latest/setup/migrate/migrate-to-alloy/
- https://grafana.com/blog/grafana-agent-to-grafana-alloy-opentelemetry-collector-faq/

## FAQ

### Is Promtail deprecated and when does it reach end-of-life?

Yes. Promtail entered long-term support in February 2025 and reached end-of-life on 2 March 2026. After that date it receives no bug fixes or security patches. Grafana's recommended replacement is Grafana Alloy, and it provides an automated conversion path via the alloy convert command.

### What is the difference between Grafana Alloy and Grafana Agent?

Grafana Alloy is the successor to Grafana Agent and is a full distribution of the OpenTelemetry Collector, 100% OTLP-compatible. Grafana Agent (Static, Flow, and Operator) reached end-of-life on 1 November 2025, and all new feature development now happens only in Alloy. Alloy keeps Agent Flow's component model and configuration syntax, so migration from Flow is mostly a rename.

### How do I convert a Promtail config to Grafana Alloy?

Use the built-in convert subcommand: run alloy convert with --source-format=promtail and an --output path pointing at your target config file. The converter targets the Promtail v2.8.x schema and works on a best-effort basis, printing diagnostics for anything it cannot map cleanly. Review the output and resolve those diagnostics by hand before restarting the service.

### What configuration language does Grafana Alloy use?

Alloy uses a component-based configuration syntax that originated under the name River, an HCL-like language. Instead of YAML pipeline blocks, you declare named components and wire them together with the forward_to argument, which points one component's output at another's receiver. The resulting reference graph is the pipeline itself.

### Can Grafana Alloy handle OpenTelemetry traces and metrics as well as logs?

Yes. Because Alloy is an OpenTelemetry Collector distribution, one process handles logs, metrics, traces, and profiles. The otelcol.* component namespace covers OTLP receivers, processors, and exporters, and it interoperates with native Loki and Prometheus components in the same config file, so you can consolidate several agents into one.

---

- HTML version: https://www.matthewswong.com/en/blog/grafana-alloy-opentelemetry-collector-migration/
- Bahasa Indonesia: https://www.matthewswong.com/id/blog/grafana-alloy-opentelemetry-collector-migration/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
