Loki is a horizontally scalable, highly available log aggregation system designed by Grafana Labs to index only metadata rather than full log content, making it extremely cost-efficient compared to Elasticsearch-based stacks. Promtail is the companion agent that tails local log files, attaches labels, and ships entries to Loki over HTTP. In this tutorial you will install both components on RHEL 8, configure Promtail to collect nginx access logs and syslog entries, and then query the results in Grafana using LogQL. By the end you will have a lightweight logging pipeline ready for production use.

Prerequisites

  • A RHEL 8 server with at least 2 GB RAM
  • A non-root user with sudo privileges
  • Grafana installed and running on port 3000 (see the Grafana installation tutorial)
  • nginx installed and serving traffic (logs at /var/log/nginx/access.log)
  • Port 3100 accessible locally (Loki listens only on localhost by default)
  • curl and unzip installed: dnf install -y curl unzip

Step 1 — Download and Install the Loki Binary

Grafana Labs distributes Loki as a single statically linked binary. Download the latest release, make it executable, and place it in /usr/local/bin.

LOKI_VERSION="3.0.0"
cd /tmp

curl -LO "https://github.com/grafana/loki/releases/download/v${LOKI_VERSION}/loki-linux-amd64.zip"
unzip loki-linux-amd64.zip
sudo mv loki-linux-amd64 /usr/local/bin/loki
sudo chmod +x /usr/local/bin/loki

# Verify
loki --version

Step 2 — Create the Loki Configuration File

Create the Loki configuration directory and write a minimal loki-config.yaml that stores chunks and the index on the local filesystem and applies a 30-day retention policy.

sudo mkdir -p /etc/loki /var/loki

sudo tee /etc/loki/loki-config.yaml <<'EOF'
auth_enabled: false

server:
  http_listen_port: 3100

ingester:
  lifecycler:
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
  chunk_idle_period: 5m
  chunk_retain_period: 30s

schema_config:
  configs:
    - from: 2024-01-01
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /var/loki/index
    cache_location: /var/loki/cache
    shared_store: filesystem
  filesystem:
    directory: /var/loki/chunks

limits_config:
  retention_period: 720h    # 30 days

chunk_store_config:
  max_look_back_period: 720h

table_manager:
  retention_deletes_enabled: true
  retention_period: 720h
EOF

Step 3 — Create a systemd Service for Loki

Create a dedicated system user for Loki and write a systemd unit file so the service starts automatically at boot.

sudo useradd --system --no-create-home --shell /bin/false loki
sudo chown -R loki:loki /var/loki

sudo tee /etc/systemd/system/loki.service <<'EOF'
[Unit]
Description=Loki Log Aggregation
After=network.target

[Service]
User=loki
Group=loki
ExecStart=/usr/local/bin/loki -config.file=/etc/loki/loki-config.yaml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now loki
sudo systemctl status loki

Step 4 — Download and Configure Promtail

Download the Promtail binary and create its configuration file. The configuration below scrapes both the nginx access log and the system journal, attaching descriptive labels that you can filter on later in Grafana.

LOKI_VERSION="3.0.0"
cd /tmp

curl -LO "https://github.com/grafana/loki/releases/download/v${LOKI_VERSION}/promtail-linux-amd64.zip"
unzip promtail-linux-amd64.zip
sudo mv promtail-linux-amd64 /usr/local/bin/promtail
sudo chmod +x /usr/local/bin/promtail

sudo mkdir -p /etc/promtail

sudo tee /etc/promtail/promtail-config.yaml <<'EOF'
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://localhost:3100/loki/api/v1/push

scrape_configs:
  - job_name: nginx
    static_configs:
      - targets:
          - localhost
        labels:
          job: nginx
          host: rhel8-server
          __path__: /var/log/nginx/access.log

  - job_name: syslog
    static_configs:
      - targets:
          - localhost
        labels:
          job: syslog
          host: rhel8-server
          __path__: /var/log/messages
EOF

Step 5 — Create a systemd Service for Promtail and Start It

Create a system user for Promtail, grant it read access to the log files, and write a systemd unit so the agent starts on boot.

sudo useradd --system --no-create-home --shell /bin/false promtail
sudo usermod -aG adm promtail          # read access to /var/log

sudo tee /etc/systemd/system/promtail.service <<'EOF'
[Unit]
Description=Promtail Log Shipping Agent
After=network.target

[Service]
User=promtail
Group=promtail
ExecStart=/usr/local/bin/promtail -config.file=/etc/promtail/promtail-config.yaml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now promtail
sudo systemctl status promtail

# Confirm Loki is receiving data
curl -s http://localhost:3100/loki/api/v1/labels | python3 -m json.tool

Step 6 — Query Logs in Grafana with LogQL

In the Grafana web interface navigate to Connections → Data sources → Add data source, choose Loki, and set the URL to http://localhost:3100. Save and test the connection. Then open Explore, select the Loki data source, and enter LogQL queries to inspect your logs.

# Show all nginx log lines
{job="nginx"}

# Filter nginx logs for HTTP 500 errors
{job="nginx"} |= "" 500 "

# Filter syslog for ERROR severity
{job="syslog"} |= "ERROR"

# Count nginx request rate per minute (metric query)
rate({job="nginx"}[1m])

# Search for a specific string across all jobs
{host="rhel8-server"} |= "connection refused"

Conclusion

You now have a lightweight Loki and Promtail log aggregation stack running on RHEL 8, collecting nginx access logs and syslog entries and storing them efficiently with label-based indexing. The Grafana Explore interface lets you query those logs in real time using LogQL, dramatically reducing the time it takes to diagnose issues across your infrastructure. Because Loki stores only metadata rather than full text, this stack consumes a fraction of the disk space required by a comparable Elasticsearch deployment.

Next steps: How to Configure Prometheus Node Exporter on RHEL 8, How to Set Up Grafana Alerting and Notification Channels on RHEL 8, and How to Install InfluxDB and Telegraf on RHEL 8.