Loki
Overview
Grafana Loki is the open-source log aggregation system from Grafana Labs. This image gives you Loki fully installed and configured. Loki runs in single-binary, single-tenant mode with a filesystem chunk store. An nginx reverse proxy on port 80 fronts the Loki HTTP API and protects the push and query endpoints with HTTP basic authentication. The companion logcli command-line query tool is preinstalled.
Loki chunks, rules and the write-ahead log live on a separate, independently resizable EBS volume mounted at /var/lib/loki. This keeps the log storage tier off the operating system disk, and you can grow it without disturbing the rest of the instance.
On the first boot of every deployed instance, a one-shot service generates a fresh HTTP basic authentication password, unique to that instance. It writes the bcrypt hash into the nginx htpasswd file and stores the plain-text value in a root-only file at /root/loki-credentials.txt. No shared or default credentials ship in the image.
What you get:
- Grafana Loki in single-binary, single-tenant mode with a filesystem chunk store
- An nginx reverse proxy on port 80 that protects the push and query endpoints with HTTP basic authentication
- The logcli command-line query tool, preinstalled
- A dedicated, independently resizable EBS volume at /var/lib/loki for chunks, rules and the write-ahead log
- A unique per-instance basic authentication password generated on first boot, stored in a root-only file at /root/loki-credentials.txt
- 24/7 SecureAnyCloud technical support
Prerequisites
Before you deploy this image, you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network and inbound port 80 from the clients that push or query logs
- The AWS CLI version 2 installed locally, if you plan to deploy from the command line
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for Grafana Loki. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger as a balanced default. Size the instance to the log ingest rate and retention that you intend to keep. Choose your EC2 key pair under Key pair (login).
Under Network settings, select your VPC and subnet. Create or select a security group that allows inbound port 22 from your management network and inbound port 80 from the networks that send logs to Loki. Leave the root volume at the default size. The image attaches a dedicated 30 GiB log storage volume automatically.
Select Launch instance. First-boot initialisation takes a few seconds after the instance state becomes Running and the status checks pass.
Launch the Instance from the AWS CLI
This command launches an instance from the SecureAnyCloud Grafana Loki Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing and <key-name> with your EC2 key pair name. Replace <subnet-id> with your subnet ID. Replace <security-group-id> with a security group that opens port 22 from your management network and port 80 from your log producers.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":20,"VolumeType":"gp3"}}' \
--metadata-options 'HttpTokens=required,HttpEndpoint=enabled' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=grafana-loki}]'The image attaches its dedicated 30 GiB log storage volume automatically. To start with more log storage, enlarge that volume on the Storage step in the console, or add a second block device mapping on the CLI.
Connect to the Instance over SSH
Connect to the instance over SSH as the default login user for the operating system variant you launched. For Ubuntu 24.04, the SSH login user is ubuntu.
Replace <key-file> with the path to your private key file. Replace <instance-public-ip> with the public IP address or DNS name of the instance.
ssh -i <key-file> ubuntu@<instance-public-ip>Confirm the Loki and nginx Services Are Running
Check that the Loki daemon, the nginx reverse proxy and the first-boot service are all active. The command prints active three times:
systemctl is-active loki.service nginx.service loki-firstboot.serviceCheck the installed Loki version and the bundled logcli companion tool. The version banner shows version 3.x.y, the Go toolchain and the platform:
/usr/local/bin/loki -version/usr/local/bin/logcli --versionRetrieve the Per-Instance Basic Auth Password
The first-boot service generated a fresh HTTP basic authentication password for the SecureAnyCloud user on this instance. Read it from the root-only credentials file:
sudo cat /root/loki-credentials.txtThe file looks like this. The password is unique to your instance, and the public URLs are filled in from the EC2 instance metadata service:
# Grafana Loki — Per-VM Credentials
# Generated: Sun May 24 11:11:17 UTC 2026
# Used by the nginx reverse proxy in front of the Loki HTTP API. loki.basicauth.user=sac loki.basicauth.pass=<LOKI_BASIC_AUTH_PASSWORD>
# Public endpoints (port 80, basic auth required): LOKI_PUSH_URL=http://<instance-public-ip>/loki/api/v1/push LOKI_QUERY_URL=http://<instance-public-ip>/loki/api/v1/query LOKI_READY_URL=http://<instance-public-ip>/ready LOKI_METRICS_URL=http://<instance-public-ip>/metrics
# Direct loopback (no auth, localhost only): LOKI_LOCAL_URL=http://127.0.0.1:3100/Treat the password as sensitive. Only the root user can read the file (0600 root:root).
Confirm the nginx Basic Auth Gate
A request to the public endpoint without credentials returns HTTP 401, which shows that the basic auth gate is in place. Run this from the instance or any client that can reach port 80:
curl -s -o /dev/null -w 'http_code=%{http_code}\n' http://127.0.0.1/http_code=401With the per-instance credentials, a request to Loki's /ready endpoint behind the proxy returns HTTP 200. Replace <LOKI_BASIC_AUTH_PASSWORD> with the password that you read from /root/loki-credentials.txt:
curl -s -o /dev/null -u sac:<LOKI_BASIC_AUTH_PASSWORD> -w 'http_code=%{http_code}\n' http://127.0.0.1/readyhttp_code=200Push a Log Line and Query It Back
Push a single log line through the nginx reverse proxy into Loki. The Loki push API expects a JSON document with a stream label set and a list of nanosecond-timestamped values. It returns HTTP 204 on success. This command builds a fresh nanosecond timestamp, posts the line, and prints the HTTP status:
TS=$(date +%s)000000000 curl -s -o /dev/null -u sac:<LOKI_BASIC_AUTH_PASSWORD> -w 'http_code=%{http_code}\n' \
-X POST -H 'Content-Type: application/json' \
-d "{\"streams\":[{\"stream\":{\"job\":\"docs\",\"host\":\"build\"},\"values\":[[\"$TS\",\"hello world from sac loki\"]]}]}" \
http://127.0.0.1/loki/api/v1/pushhttp_code=204Query the line back through the Loki query API. Loki returns a JSON envelope with the matched stream labels and the timestamped values:
curl -s -G -u sac:<LOKI_BASIC_AUTH_PASSWORD> \
--data-urlencode 'query={job="docs"}' \
--data-urlencode 'limit=5' \
http://127.0.0.1/loki/api/v1/query_range{"status":"success","data":{"resultType":"streams","result":[{"stream":{"detected_level":"unknown","host":"build","job":"docs","service_name":"docs"},"values":[["1779621125000000000","hello world from sac loki"]]}],"stats":{"summary":{"bytesProcessedPerSecond":3035,"linesProcessedPerSecond":79,"totalBytesProcessed":38,"totalLinesProcessed":1,"execTime":0.012517,"queueTime":0.000708,"subqueries":1Query Logs with logcli
The image ships the official Grafana logcli command-line client at /usr/local/bin/logcli. Point it at the local Loki endpoint with the basic auth credentials and run the same query:
LOKI_ADDR=http://127.0.0.1 \
LOKI_USERNAME=sac \
LOKI_PASSWORD=<LOKI_BASIC_AUTH_PASSWORD> \
/usr/local/bin/logcli query '{job="docs"}' --limit=5logcli prints one log line per row, with the stream labels and the original message. Use it for ad hoc log exploration from the instance itself.
Inspect the Loki Data Directory
The image mounts a dedicated 30 GiB EBS volume at /var/lib/loki for Loki's chunks, rules and write-ahead log. Confirm that the path is on its own filesystem:
df -h /var/lib/lokils -lh /var/lib/lokiThe Loki user owns chunks/, rules/ and wal/. When retention demands more storage, grow this volume in the EC2 console under Volumes. After the EBS modification completes, expand the filesystem online with sudo resize2fs.
Scrape Loki's Prometheus Metrics
Loki exposes Prometheus-format metrics at /metrics through the same nginx basic auth gate. The output begins with # HELP and # TYPE lines, followed by a long list of loki_* counters and gauges. Point any Prometheus or Grafana Alloy scraper at this endpoint with the basic auth credentials:
curl -s -u sac:<LOKI_BASIC_AUTH_PASSWORD> http://127.0.0.1/metrics | head -20Connect a Log Shipper
Most production deployments push logs to Loki from a shipper such as Promtail, Grafana Alloy, Vector or Fluent Bit. Configure your shipper with:
url:http://<instance-public-ip>/loki/api/v1/push- basic_auth.username: SecureAnyCloud
basic_auth.password: the password from/root/loki-credentials.txt
For Promtail, the relevant clients: section looks like this:
clients: - url: http://<instance-public-ip>/loki/api/v1/push basic_auth: username: sac password: <LOKI_BASIC_AUTH_PASSWORD>Connect Grafana
In Grafana, add a Loki data source. Go to Connections, then Data sources, then Add data source, and select Loki. Set:
- URL:
http://<instance-public-ip> - Auth: enable Basic auth and supply the username SecureAnyCloud and the per-instance password.
Save and test the data source. Grafana confirms the connection. Switch to the Explore view to run LogQL queries such as {job="docs"}.
Maintenance
Restart Loki and the reverse proxy after a configuration change:
sudo systemctl restart loki.service
sudo systemctl reload nginx.serviceTail the Loki journal to see ingestion, query and compaction activity:
sudo journalctl -u loki.service -fThe image leaves unattended-upgrades enabled, so security updates for nginx, the kernel and the rest of the base operating system install automatically. To upgrade Loki, replace the /usr/local/bin/loki binary with a newer release from the upstream grafana/loki GitHub releases page and restart the service.
Support
24/7 SecureAnyCloud technical support is included with this image. Contact SecureAnyCloud through the AWS Marketplace listing or at https://secureanycloud.com/contact/ for help with Loki deployment, label design, retention tuning, multi-tenant migration and log client integration.
Deploy on AWS
Launch Grafana Loki on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com