Grafana Alloy
Overview
Grafana Alloy is a vendor-neutral distribution of the OpenTelemetry Collector. It collects, processes and forwards telemetry (metrics, logs, traces and profiles) using a single declarative configuration built from composable components. It can ship that data to Prometheus, Grafana Cloud, Mimir, Loki, Tempo, Pyroscope and any OpenTelemetry-compatible backend.
A built-in web UI renders the live component graph and the health of every component, so you can see exactly how telemetry flows through your pipeline. Alloy is a single Go binary managed by systemd, so it stays lightweight and starts instantly.
This SecureAnyCloud image installs Grafana Alloy 1.17.1 from Grafana's official package repository and puts the web UI behind an nginx reverse proxy. The Alloy UI has no built-in authentication, so the appliance is secure by default. A fully self-contained demo pipeline keeps every component healthy on first boot, and you replace it with your own pipeline whenever you are ready.
What you get:
- Grafana Alloy 1.17.1 as a single Go binary (
/usr/bin/alloy), installed from Grafana's official apt repository and version-pinned alloy.servicerunning as thealloyuser, with the web UI bound to loopback127.0.0.1:12345onlynginx.serviceas a reverse proxy on TCP 80 with a per-VM HTTP Basic Auth gate (useradmin), TLS-ready. The gate password is generated uniquely and at random on the first boot of every VM, so no shared or default credential is baked into the imagegrafana-alloy-firstboot.service, which generates the per-VM password and writes this VM's URL into the MOTD and a root-only info note on first boot- An unauthenticated static
/healthzendpoint for load balancer and probe checks - A fully self-contained demo pipeline in
/etc/alloy/config.alloythat scrapes Alloy's own metrics, tags and batches them, and logs a summary locally. Every component is healthy and the component graph is populated on first boot, with nothing leaving the VM - Ubuntu 24.04 LTS base, latest patches, unattended security upgrades enabled
Prerequisites
You need an active Azure subscription, an SSH key, and a VNet with a subnet.
The recommended VM size is Standard_B2s. Alloy is light for a demo pipeline, so scale up only for heavier collection workloads.
Deploy from the Azure Portal
Search the Azure Marketplace for Grafana Alloy, choose the plan, and create the VM.
In the networking step, attach a network security group (NSG) that allows inbound TCP 22 (SSH) and TCP 80 (the UI, behind HTTP Basic Auth) from your client networks only. For production, put a TLS reverse proxy or certificate in front of port 80.
Deploy from the Azure CLI
RG="grafana-alloy-prod"; LOCATION="eastus"; VM_NAME="alloy-01" IMAGE_URN="sac1647283583153:grafana-alloy-ubuntu-24-04:default:latest" SSH_KEY="$(cat ~/.ssh/id_rsa.pub)" az group create --name "$RG" --location "$LOCATION" az network vnet create -g "$RG" --name al-vnet --address-prefix 10.108.0.0/16 --subnet-name al-subnet --subnet-prefix 10.108.1.0/24 az network nsg create -g "$RG" --name al-nsg az network nsg rule create -g "$RG" --nsg-name al-nsg --name allow-ssh --priority 100 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp az network nsg rule create -g "$RG" --nsg-name al-nsg --name allow-web --priority 110 \
--source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 --access Allow --protocol Tcp
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:grafana-alloy-ubuntu-24-04:default:latest
az vm create -g "$RG" --name "$VM_NAME" --image "$IMAGE_URN" \
--size Standard_B2s --storage-sku StandardSSD_LRS \
--admin-username azureuser --ssh-key-values "$SSH_KEY" \
--vnet-name al-vnet --subnet al-subnet --nsg al-nsg --public-ip-sku StandardConnect via SSH
Connect as the azureuser login user:
ssh azureuser@<vm-ip>alloy.service, nginx.service and grafana-alloy-firstboot.service all start automatically on first boot.
Retrieve the per-VM password
On first boot, the appliance generates a random HTTP Basic Auth password for user admin. The password is unique to this VM and is written to a root-only file. There is no shared or default credential in the image. Read the file over SSH:
sudo cat /root/grafana-alloy-credentials.txtThe file holds this VM's URL, username and password:
ALLOY_URL=http://<vm-ip>/ ALLOY_USERNAME=admin ALLOY_PASSWORD=<unique-per-vm-password>Keep this password safe. It is the only credential for the web UI, and every VM gets a different one.
Verify the services
Check the three services, the first-boot marker and the listening ports:
sudo systemctl is-active alloy nginx grafana-alloy-firstboot
sudo test -f /var/lib/sac/data/grafana-alloy-firstboot.done && echo FIRSTBOOT_DONE
sudo ss -tlnp | grep -E ':80 |:12345 'All three services are active. nginx is bound to the public port 80, and the Alloy UI is bound to loopback 127.0.0.1:12345 only:
active active active FIRSTBOOT_DONE LISTEN 0 4096 127.0.0.1:12345 0.0.0.0:* users:(("alloy",...)) LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",...))Test the authentication gate
The Alloy UI has no built-in login, so nginx fronts it with an HTTP Basic Auth gate. An unauthenticated /healthz is available for load balancer probes, but the UI itself is gated. Requests with no password or a wrong password are rejected with 401, and only the per-VM password is accepted.
Read your password from the file and test the gate:
PW=$(sudo grep '^ALLOY_PASSWORD=' /root/grafana-alloy-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'GET /healthz (unauth) -> HTTP %{http_code}\n' http://127.0.0.1/healthz
curl -s -o /dev/null -w 'GET / (no credential) -> HTTP %{http_code}\n' http://127.0.0.1/
curl -s -o /dev/null -w 'GET / (wrong password) -> HTTP %{http_code}\n' -u admin:wrong http://127.0.0.1/
curl -s -o /dev/null -w 'GET / (per-VM password) -> HTTP %{http_code}\n' -u "admin:$PW" http://127.0.0.1/The health probe is open, the UI is gated, a wrong password is rejected, and the per-VM password authenticates:
GET /healthz (unauth) -> HTTP 200 GET / (no credential) -> HTTP 401 GET / (wrong password) -> HTTP 401 GET / (per-VM password) -> HTTP 200Open the component graph
Open http://<vm-ip>/ in a browser and sign in as admin with the password from Step 4.
The Graph view visualizes the live pipeline. Telemetry flows left to right through each component, from collection through processing to the sink.
Inspect the collection stage
Click any node to open its detail page. Each component shows a Healthy badge, its latest health message, its arguments and its exports.
The prometheus.scrape component is the collection stage. Here it scrapes Alloy's own metrics endpoint every 15 seconds and forwards the results to the next component.
Inspect the processing stage
The otelcol.processor.batch component is a processing stage. It batches telemetry before the telemetry is exported.
Its detail page shows a Healthy badge, its output wiring and its dependants, so you can trace exactly how one component feeds the next.
Inspect the sink stage
The otelcol.exporter.debug component is the pipeline sink. In this self-contained demo, it logs a summary of the telemetry to Alloy's own log instead of shipping it off the VM. Nothing leaves the instance, so the whole pipeline is healthy on first boot.
Its detail page lists the components that depend on it.
Check component health through the API
Everything the UI shows is also available as JSON at /api/v0/web/components, so you can wire Alloy's health into your own tooling.
Read your password from the file and query the endpoint:
PW=$(sudo grep '^ALLOY_PASSWORD=' /root/grafana-alloy-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" http://127.0.0.1/api/v0/web/components \
| jq '[.[] | {component: .localID, health: .health.state}]'Every component in the demo pipeline reports healthy:
[ { "component": "otelcol.exporter.debug.sink", "health": "healthy" }, { "component": "otelcol.processor.batch.default", "health": "healthy" }, { "component": "otelcol.receiver.prometheus.bridge", "health": "healthy" }, { "component": "prometheus.relabel.tag", "health": "healthy" }, { "component": "prometheus.scrape.alloy_self", "health": "healthy" } ]Review the demo pipeline config
The whole pipeline is defined in one declarative file, /etc/alloy/config.alloy. View the file and validate it:
cat /etc/alloy/config.alloy alloy fmt /etc/alloy/config.alloy >/dev/null && echo "config valid"The config wires five components into a single flow and validates cleanly:
config validCustomize the pipeline
Replace the demo pipeline with your own by editing /etc/alloy/config.alloy with sudo nano /etc/alloy/config.alloy. For example, this pattern scrapes a local application and forwards its metrics to Grafana Cloud or your own Prometheus:
prometheus.scrape "my_app" { targets = [ { "__address__" = "127.0.0.1:8080", "job" = "my-app" }, ] forward_to = [prometheus.remote_write.default.receiver] } prometheus.remote_write "default" { endpoint { url = "https://<your-prometheus>/api/v1/write" } }Validate your changes with alloy fmt /etc/alloy/config.alloy. Then apply them with sudo systemctl reload alloy, because Alloy reloads its config without a full restart. The full component reference is at grafana.com/docs/alloy.
Manage the service
Alloy is managed by systemd, so it restarts automatically on failure and on boot. Check its state:
sudo systemctl show alloy --property=ActiveState,SubState,MainPID,NRestartsActiveState=active SubState=running MainPID=... NRestarts=0After an edit, reload the config with sudo systemctl reload alloy, or restart the service fully with sudo systemctl restart alloy. Read the logs, including the demo sink's telemetry summaries, with sudo journalctl -u alloy -f.
Add TLS (optional)
For production, terminate TLS at nginx. Point a DNS record at the VM, then use the packaged nginx with a certificate from Let's Encrypt:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>certbot installs the certificate, rewrites the nginx server block to listen on 443, and sets up automatic renewal. The HTTP Basic Auth gate stays in front of the UI over TLS.
Security recommendations
- Restrict the NSG so that ports 80 and 22 reach only trusted networks
- Terminate TLS at nginx (Step 15) so that the UI and its Basic Auth credentials travel encrypted
- Rotate the Basic Auth password when needed by regenerating
/etc/nginx/.alloy.htpasswdwithsudo htpasswd -B /etc/nginx/.alloy.htpasswd adminand reloading nginx - Keep the UI private. The Alloy UI can trigger config reloads and expose pipeline internals, so treat access as privileged even behind Basic Auth
- Review your pipeline's exporters so that telemetry leaves the VM only for the backends you intend
- Patch the OS monthly with
sudo apt-get update && sudo apt-get upgrade. Unattended security upgrades are already enabled
Support and Licensing
Grafana Alloy is licensed under the Apache License 2.0, with no per-CPU or per-user fee. SecureAnyCloud provides commercial support separately.
- Email: sales@secureanycloud.com
- Website: secureanycloud.com
- Support hours: 24/7, 24-hour response SLA
Deploy on Azure
Launch Grafana Alloy on Ubuntu 24.04 with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7. sales@secureanycloud.com
Deploy on Azure
Launch Grafana Alloy on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
Grafana Alloy is a vendor-neutral distribution of the OpenTelemetry Collector. It collects, processes and forwards telemetry (metrics, logs, traces and profiles) using a single declarative configuration built from composable components. It can ship that data to Prometheus, Grafana Cloud, Mimir, Loki, Tempo, Pyroscope and any OpenTelemetry-compatible backend.
A built-in web UI renders the live component graph and the health of every component, so you can see exactly how telemetry flows through your pipeline. Alloy is a single Go binary managed by systemd, so it stays lightweight and starts instantly.
This SecureAnyCloud image installs Grafana Alloy 1.17.1 from Grafana's official package repository and puts the web UI behind an nginx reverse proxy. The Alloy UI has no built-in authentication, so the appliance is secure by default. A fully self-contained demo pipeline keeps every component healthy on first boot, and you replace it with your own pipeline whenever you are ready.
What you get:
- Grafana Alloy 1.17.1 as a single Go binary (
/usr/bin/alloy), installed from Grafana's official apt repository and version-pinned alloy.servicerunning as thealloyuser, with the web UI bound to loopback127.0.0.1:12345onlynginx.serviceas a reverse proxy on TCP 80 with a per-instance HTTP Basic Auth gate (useradmin), TLS-ready. The gate password is generated uniquely and at random on the first boot of every instance, so no shared or default credential is baked into the imagegrafana-alloy-firstboot.service, which generates the per-instance password and writes this instance's URL into the MOTD and a root-only info note on first boot- An unauthenticated static
/healthzendpoint for load balancer and probe checks - A fully self-contained demo pipeline in
/etc/alloy/config.alloythat scrapes Alloy's own metrics, tags and batches them, and logs a summary locally. Every component is healthy and the component graph is populated on first boot, with nothing leaving the instance - Ubuntu 24.04 LTS base, latest patches, unattended security upgrades enabled
Prerequisites
You need an active AWS account, an EC2 key pair, and a VPC with a subnet.
The recommended instance type is m5.large. Alloy is light for a demo pipeline, so scale up only for heavier collection workloads.
Launch from the AWS Marketplace
Find Grafana Alloy on the AWS Marketplace, subscribe, and launch an instance.
In the launch wizard, attach a security group that allows inbound TCP 22 (SSH) and TCP 80 (the UI, behind HTTP Basic Auth) from your client networks only. For production, put a TLS listener or reverse proxy in front of port 80 (Step 13).
Launch from the AWS CLI
AMI_ID="<marketplace-ami-id>"
# from the Marketplace listing, in your region KEY_NAME="my-key" SUBNET_ID="subnet-xxxxxxxx" SG_ID="sg-xxxxxxxx"
# allows 22 + 80 from your networks only aws ec2 run-instances \
--image-id "$AMI_ID" --instance-type m5.large \
--key-name "$KEY_NAME" --subnet-id "$SUBNET_ID" \
--security-group-ids "$SG_ID" \
--metadata-options 'HttpTokens=required' \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeType":"gp3","VolumeSize":30}}]' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=grafana-alloy}]'Connecting to your instance
Connect over SSH as the login user for your image's operating system. For Ubuntu 24.04 LTS, the login user is ubuntu, and the connect command is ssh -i my-key.pem ubuntu@<instance-public-ip>.
alloy.service, nginx.service and grafana-alloy-firstboot.service all start automatically on first boot.
Retrieve the per-instance password
On first boot, the appliance generates a random HTTP Basic Auth password for user admin. The password is unique to this instance and is written to a root-only file. There is no shared or default credential in the image. Read the file over SSH:
sudo cat /root/grafana-alloy-credentials.txtThe file holds this instance's URL, username and password:
ALLOY_URL=http://<instance-public-ip>/ ALLOY_USERNAME=admin ALLOY_PASSWORD=<unique-per-instance-password>Keep this password safe. It is the only credential for the web UI, and every instance gets a different one.
Verify the services
Check the three services, the first-boot marker and the listening ports:
sudo systemctl is-active alloy nginx grafana-alloy-firstboot
sudo test -f /var/lib/sac/data/grafana-alloy-firstboot.done && echo FIRSTBOOT_DONE
sudo ss -tlnp | grep -E ':80 |:12345 'All three services are active. nginx is bound to the public port 80, and the Alloy UI is bound to loopback 127.0.0.1:12345 only:
active active active FIRSTBOOT_DONE LISTEN 0 511 0.0.0.0:80 0.0.0.0:* LISTEN 0 4096 127.0.0.1:12345 0.0.0.0:* LISTEN 0 511 [::]:80 [::]:*Test the authentication gate
The Alloy UI has no built-in login, so nginx fronts it with an HTTP Basic Auth gate. An unauthenticated /healthz is available for load balancer probes, but the UI itself is gated. Requests with no password or a wrong password are rejected with 401, and only the per-instance password is accepted.
Read your password from the file and test the gate:
PW=$(sudo grep '^ALLOY_PASSWORD=' /root/grafana-alloy-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'GET /healthz (unauth) -> HTTP %{http_code}\n' http://127.0.0.1/healthz
curl -s -o /dev/null -w 'GET / (no credential) -> HTTP %{http_code}\n' http://127.0.0.1/
curl -s -o /dev/null -w 'GET / (wrong password) -> HTTP %{http_code}\n' -u admin:wrong http://127.0.0.1/
curl -s -o /dev/null -w 'GET / (per-instance pw) -> HTTP %{http_code}\n' -u "admin:$PW" http://127.0.0.1/The health probe is open, the UI is gated, a wrong password is rejected, and the per-instance password authenticates:
GET /healthz (unauth) -> HTTP 200 GET / (no credential) -> HTTP 401 GET / (wrong password) -> HTTP 401 GET / (per-instance pw) -> HTTP 200Open the component graph
Open http://<instance-public-ip>/ in a browser and sign in as admin with the password from Step 3.
The Graph view visualizes the live pipeline. Telemetry flows left to right through each component, from collection through processing to the sink.
Review component health
The Components view lists every component in your pipeline with its health.
In this self-contained demo, every component reports Healthy on first boot, because nothing depends on an external endpoint being reachable.
Inspect a component
Click View on any component to open its detail page. Each component shows a Healthy badge, its latest health message, its arguments, its exports and its dependencies.
The prometheus.scrape component is the collection stage. Here it scrapes Alloy's own metrics endpoint every 15 seconds and forwards the results to the next component.
Check component health through the API
Everything the UI shows is also available as JSON at /api/v0/web/components, so you can wire Alloy's health into your own tooling.
Read your password from the file and query the endpoint:
PW=$(sudo grep '^ALLOY_PASSWORD=' /root/grafana-alloy-credentials.txt | cut -d= -f2-)
curl -s -u "admin:$PW" http://127.0.0.1/api/v0/web/components \
| jq '[.[] | {component: .localID, health: .health.state}]'Every component in the demo pipeline reports healthy:
[ { "component": "otelcol.exporter.debug.sink", "health": "healthy" }, { "component": "otelcol.processor.batch.default", "health": "healthy" }, { "component": "otelcol.receiver.prometheus.bridge", "health": "healthy" }, { "component": "prometheus.relabel.tag", "health": "healthy" }, { "component": "prometheus.scrape.alloy_self", "health": "healthy" } ]Review the demo pipeline config
The whole pipeline is defined in one declarative file, /etc/alloy/config.alloy. Check the version, view the file and validate it:
/usr/bin/alloy --version | head -1 cat /etc/alloy/config.alloy alloy fmt /etc/alloy/config.alloy >/dev/null && echo "config valid"The pinned binary and the self-contained demo pipeline validate cleanly:
alloy, version v1.17.1 (branch: HEAD, revision: 76a2e2a) config validCustomize the pipeline
Replace the demo pipeline with your own by editing /etc/alloy/config.alloy with sudo nano /etc/alloy/config.alloy. For example, this pattern scrapes a local application and forwards its metrics to Grafana Cloud or your own Prometheus:
prometheus.scrape "my_app" { targets = [ { "__address__" = "127.0.0.1:8080", "job" = "my-app" }, ] forward_to = [prometheus.remote_write.default.receiver] } prometheus.remote_write "default" { endpoint { url = "https://<your-prometheus>/api/v1/write" } }Validate your changes with alloy fmt /etc/alloy/config.alloy. Then apply them with sudo systemctl reload alloy, because Alloy reloads its config without a full restart. The full component reference is at grafana.com/docs/alloy.
Manage the service
Alloy is managed by systemd, so it restarts automatically on failure and on boot. Check its state:
sudo systemctl show alloy --property=ActiveState,SubState,MainPID,NRestartsMainPID=2000 NRestarts=0 ActiveState=active SubState=runningAfter an edit, reload the config with sudo systemctl reload alloy, or restart the service fully with sudo systemctl restart alloy. Read the logs, including the demo sink's telemetry summaries, with sudo journalctl -u alloy -f.
Add TLS (optional)
For production, terminate TLS at nginx. Point a DNS record at the instance and allow inbound TCP 443 in the security group. Then use the packaged nginx with a certificate from Let's Encrypt:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>certbot installs the certificate, rewrites the nginx server block to listen on 443, and sets up automatic renewal. The HTTP Basic Auth gate stays in front of the UI over TLS.
Security recommendations
- Restrict the security group so that ports 80 and 22 reach only trusted networks
- Terminate TLS at nginx (Step 13) so that the UI and its Basic Auth credentials travel encrypted
- Rotate the Basic Auth password when needed by regenerating
/etc/nginx/.alloy.htpasswdwithsudo htpasswd -B /etc/nginx/.alloy.htpasswd adminand reloading nginx - Keep the UI private. The Alloy UI can trigger config reloads and expose pipeline internals, so treat access as privileged even behind Basic Auth
- Review your pipeline's exporters so that telemetry leaves the instance only for the backends you intend
- Patch the OS monthly with
sudo apt-get update && sudo apt-get upgrade. Unattended security upgrades are already enabled
Support and Licensing
Grafana Alloy is licensed under the Apache License 2.0, with no per-CPU or per-user fee. SecureAnyCloud provides commercial support separately.
- Email: sales@secureanycloud.com
- Website: secureanycloud.com
- Support hours: 24/7, 24-hour response SLA
Deploy on AWS
Launch Grafana Alloy with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7. sales@secureanycloud.com
Deploy on AWS
Launch Grafana Alloy with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com