Skip to content

Grafana Alloy - Client

Here we will show you how to set up Grafana Alloy to send logs to Grafana Loki hosted on another machine/VM.

Prerequisites

  1. Debian12
  2. Have Prometheus & Grafana & Grafana Loki installed on another machine that is accessible by yours

Important Notice

Make sure to change the <IP> values to your Grafana Loki IP.

This applies to both the script and manual steps.

_

I recommend looking out for highlighted lines, they indicate that something needs to be modified to fit your situation.

Script from start to finish

Script
alloy.sh
#!/usr/bin/env bash
# Install & configure Grafana Alloy, then report success/failure.
# Debian/Ubuntu-friendly. No manual gpg step needed.

set -Eeuo pipefail
umask 022

REPO_KEYRING="/etc/apt/keyrings/grafana.gpg"
REPO_LIST="/etc/apt/sources.list.d/grafana.list"
ALLOY_CONF="/etc/alloy/config.alloy"
LOKI_URL="http://<IP>:3100/loki/api/v1/push" // CHANGE HERE the <IP> to the Grafana Loki IP (don't include the <>)

# --- tiny logger ---
bold() { printf "\033[1m%s\033[0m\n" "$*"; }
ok()   { printf "\033[32m✔ %s\033[0m\n" "$*"; }
warn() { printf "\033[33m⚠ %s\033[0m\n" "$*"; }
err()  { printf "\033[31m✘ %s\033[0m\n" "$*" >&2; }
die()  { err "$*"; exit 1; }

require_root() {
if [[ ${EUID:-0} -ne 0 ]]; then
    bold "Elevating to root..."
    exec sudo -E bash "$0" "$@"
fi
}

ensure_base_tools() {
bold "Updating APT and installing base tools…"
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
# Install tools needed BEFORE adding the repo (so gpg exists)
apt-get install -y gnupg wget ca-certificates || die "Failed to install base tools"
ok "Base tools present (gnupg, wget, ca-certificates)"
}

add_repo() {
bold "Adding Grafana APT repository…"
mkdir -p /etc/apt/keyrings
if [[ ! -s "$REPO_KEYRING" ]]; then
    wget -q -O - https://apt.grafana.com/gpg.key \
    | gpg --dearmor > "${REPO_KEYRING}.tmp"
    mv -f "${REPO_KEYRING}.tmp" "$REPO_KEYRING"
    chmod 0644 "$REPO_KEYRING"
    ok "GPG key installed at $REPO_KEYRING"
else
    ok "GPG key already present"
fi

echo "deb [signed-by=${REPO_KEYRING}] https://apt.grafana.com stable main" > "$REPO_LIST"
chmod 0644 "$REPO_LIST"
ok "Repo list written to $REPO_LIST"

apt-get update -y
}

install_alloy() {
bold "Installing Grafana Alloy…"
apt-get install -y alloy || die "Failed to install 'alloy' package"
ok "Alloy installed"
}

write_config() {
bold "Writing Alloy config to $ALLOY_CONF…"
mkdir -p "$(dirname "$ALLOY_CONF")"
tee "$ALLOY_CONF" >/dev/null <<'HCL'
logging {
    level = "info"
}

// Push logs to Loki
loki.write "to_loki" {
    endpoint {
        url = "http://<IP>:3100/loki/api/v1/push" // CHANGE HERE the <IP> to the Grafana Loki IP (don't include the <>)
    }
    // Define sender label (keep or change)
    external_labels = { instance = constants.hostname }

    //--- You can also hardcode strings ---// 
    // external_labels = { instance = "some custom name" }
}

// Systemd journal -> Loki
loki.source.journal "default" {
    // Optional extra label
    labels     = { host = "Some host" }
    forward_to = [loki.write.to_loki.receiver]
}
HCL
chmod 0644 "$ALLOY_CONF"
ok "Config written"
}

enable_and_start() {
bold "Enabling and starting alloy.service…"
systemctl daemon-reload || true
systemctl enable --now alloy || die "Failed to enable/start alloy"
ok "Service enable/start requested"
}

wait_for_active() {
bold "Waiting for alloy to become active…"
for _ in {1..30}; do
    if systemctl is-active --quiet alloy; then
    ok "Alloy is active (running)"
    return 0
    fi
    sleep 1
done
return 1
}

print_result() {
if systemctl is-active --quiet alloy; then
    ok "SUCCESS: Alloy installed, configured, and running."
    printf "   • Service: "; systemctl --no-pager --full --lines=0 status alloy | sed -n '1p'
    printf "   • Config : %s\n" "$ALLOY_CONF"
    printf "   • Loki   : %s\n" "$LOKI_URL"
else
    err "FAILED: Alloy service is not running."
    warn "Last logs:"
    journalctl -u alloy -n 50 --no-pager || true
    exit 1
fi
}

main() {
require_root "$@"
ensure_base_tools
add_repo
install_alloy
write_config
enable_and_start
wait_for_active || true
print_result
}

main "$@"

Manual installation

1. Install Alloy

sudo apt update
sudo apt install gpg

sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list

# Update the repositories
sudo apt update

sudo apt install alloy

2. Configure Alloy

sudo vim /etc/alloy/config.alloy

/etc/alloy/config.alloy
    logging {
        level = "info"
    }

    // Push logs to Loki
    loki.write "to_loki" {
        endpoint {
            url = "http://<IP>:3100/loki/api/v1/push" // CHANGE HERE the <IP> to the Grafana Loki IP (don't include the <>)
        }
        // Define sender label (keep or change)
        external_labels = { instance = constants.hostname }

        //--- You can also hardcode strings ---// 
        // external_labels = { instance = "Change me!" } // Hardcoded values should be changed
    }

    // Systemd journal -> Loki
    loki.source.journal "default" {
        // Optional extra label
        labels     = { host = "Please change me" } // Hardcoded values should be changed
        forward_to = [loki.write.to_loki.receiver]
    }

3. Start and enable Alloy

# Enable and start alloy
sudo systemctl enable --now alloy