🚀 Schritt-für-Schritt-Anleitung: Linux-Server & Logs in Grafana Cloud einbinden (mit Grafana Alloy)

Wer mehrere Server betreibt – sei es im Homelab oder in der Cloud wie der Oracle Cloud Infrastructure (OCI) –, verliert ohne zentrales Monitoring schnell den Überblick.

In dieser Anleitung zeigen wir dir Schritt für Schritt, wie du eine ARM64-Linux-VM (z. B. Ubuntu auf Oracle Ampere A1) mithilfe des neuen Grafana Alloy (dem offiziellen Nachfolger des Grafana Agents) an deine Grafana Cloud anbindest. Damit sendest du sowohl System-Metriken (CPU, RAM, Disk) als auch System-Logs (Journald & Syslog) an Loki und Prometheus.

📋 Voraussetzungen

  • Eine Linux-VM: Z. B. Ubuntu 22.04 LTS oder 24.04 LTS (ARM64-Architektur)
  • Ein Grafana Cloud Account: (Kostenlos registrierbar)
  • SSH-Zugriff auf deinen Server mit sudo-Rechten

🛠️ Schritt 1: Das All-in-One Installations-Skript ausführen

Grafana hat mit Alloy einen universellen Telemetrie-Collector geschaffen. Um die Installation und Konfiguration extrem einfach zu halten, nutzen wir ein vorgefertigtes Bash-Skript.

Öffne dein Terminal, verbinde dich per SSH mit deinem Linux-Server und führe das folgende Skript aus:

Bash

# 1. Alloy herunterladen und installieren
ARCH="arm64" \
GCLOUD_HOSTED_METRICS_URL="https://prometheus-prod-65-prod-eu-west-2.grafana.net/api/prom/push" \
GCLOUD_HOSTED_METRICS_ID="3549188" \
GCLOUD_SCRAPE_INTERVAL="60s" \
GCLOUD_HOSTED_LOGS_URL="https://logs-prod-012.grafana.net/loki/api/v1/push" \
GCLOUD_HOSTED_LOGS_ID="1770269" \
GCLOUD_RW_API_KEY="glc_eyJvIjoiMTg5MzYzOCIsIm4iOiJsaW51eC1vdGhlci1hcm02NC10b2tlbiIsImsiOiJWRW8yMXQ2VUtBWmhYZ0QwQzg0MjVzMzAiLCJtIjp7InIiOiJwcm9kLWV1LXdlc3QtMiJ9fQ==" \
/bin/sh -c "$(curl -fsSL https://storage.googleapis.com/cloud-onboarding/alloy/scripts/install-linux-binary.sh)"

# 2. Ordner anlegen & Konfigurationsdatei schreiben
sudo mkdir -p /etc/alloy
sudo bash -c 'cat << "EOF" > /etc/alloy/config.alloy
prometheus.exporter.self "alloy_check" { }

discovery.relabel "alloy_check" {
  targets = prometheus.exporter.self.alloy_check.targets

  rule {
    target_label = "instance"
    replacement  = constants.hostname
  }

  rule {
    target_label = "alloy_hostname"
    replacement  = constants.hostname
  }

  rule {
    target_label = "job"
    replacement  = "integrations/alloy-check"
  }
}

prometheus.scrape "alloy_check" {
  targets         = discovery.relabel.alloy_check.output
  forward_to      = [prometheus.relabel.alloy_check.receiver]
  scrape_interval = "60s"
}

prometheus.relabel "alloy_check" {
  forward_to = [prometheus.remote_write.metrics_service.receiver]

  rule {
    source_labels = ["__name__"]
    regex         = "(prometheus_target_sync_length_seconds_sum|prometheus_target_scrapes_.*|prometheus_target_interval.*|prometheus_sd_discovered_targets|alloy_build.*|prometheus_remote_write_wal_samples_appended_total|process_start_time_seconds)"
    action        = "keep"
  }
}

prometheus.remote_write "metrics_service" {
  endpoint {
    url = "https://prometheus-prod-65-prod-eu-west-2.grafana.net/api/prom/push"

    basic_auth {
      username = "3549188"
      password = "glc_eyJvIjoiMTg5MzYzOCIsIm4iOiJsaW51eC1vdGhlci1hcm02NC10b2tlbiIsImsiOiJWRW8yMXQ2VUtBWmhYZ0QwQzg0MjVzMzAiLCJtIjp7InIiOiJwcm9kLWV1LXdlc3QtMiJ9fQ=="
    }
  }
}

loki.write "grafana_cloud_loki" {
  endpoint {
    url = "https://logs-prod-012.grafana.net/loki/api/v1/push"

    basic_auth {
      username = "1770269"
      password = "glc_eyJvIjoiMTg5MzYzOCIsIm4iOiJsaW51eC1vdGhlci1hcm02NC10b2tlbiIsImsiOiJWRW8yMXQ2VUtBWmhYZ0QwQzg0MjVzMzAiLCJtIjp7InIiOiJwcm9kLWV1LXdlc3QtMiJ9fQ=="
    }
  }
}

discovery.relabel "integrations_node_exporter" {
  targets = prometheus.exporter.unix.integrations_node_exporter.targets

  rule {
    target_label = "instance"
    replacement  = constants.hostname
  }

  rule {
    target_label = "job"
    replacement  = "integrations/node_exporter"
  }
}

prometheus.exporter.unix "integrations_node_exporter" {
  disable_collectors = ["ipvs", "btrfs", "infiniband", "xfs", "zfs"]

  filesystem {
    fs_types_exclude     = "^(autofs|binfmt_misc|bpf|cgroup2?|configfs|debugfs|devpts|devtmpfs|tmpfs|fusectl|hugetlbfs|iso9660|mqueue|nsfs|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|selinuxfs|squashfs|sysfs|tracefs)$"
    mount_points_exclude = "^/(dev|proc|run/credentials/.+|sys|var/lib/docker/.+)($|/)"
    mount_timeout        = "5s"
  }

  netclass {
    ignored_devices = "^(veth.*|cali.*|[a-f0-9]{15})$"
  }

  netdev {
    device_exclude = "^(veth.*|cali.*|[a-f0-9]{15})$"
  }
}

prometheus.scrape "integrations_node_exporter" {
  targets    = discovery.relabel.integrations_node_exporter.output
  forward_to = [prometheus.relabel.integrations_node_exporter.receiver]
}

prometheus.relabel "integrations_node_exporter" {
  forward_to = [prometheus.remote_write.metrics_service.receiver]

  rule {
    source_labels = ["__name__"]
    regex         = "node_scrape_collector_.+"
    action        = "drop"
  }
}

loki.source.journal "logs_integrations_integrations_node_exporter_journal_scrape" {
  max_age       = "24h0m0s"
  relabel_rules = discovery.relabel.logs_integrations_integrations_node_exporter_journal_scrape.rules
  forward_to    = [loki.write.grafana_cloud_loki.receiver]
}

local.file_match "logs_integrations_integrations_node_exporter_direct_scrape" {
  path_targets = [{
    __address__ = "localhost",
    __path__    = "/var/log/{syslog,messages,*.log}",
    instance    = constants.hostname,
    job         = "integrations/node_exporter",
  }]
}

discovery.relabel "logs_integrations_integrations_node_exporter_journal_scrape" {
  targets = []

  rule {
    source_labels = ["__journal__systemd_unit"]
    target_label  = "unit"
  }

  rule {
    source_labels = ["__journal__boot_id"]
    target_label  = "boot_id"
  }

  rule {
    source_labels = ["__journal__transport"]
    target_label  = "transport"
  }

  rule {
    source_labels = ["__journal_priority_keyword"]
    target_label  = "level"
  }
}

loki.source.file "logs_integrations_integrations_node_exporter_direct_scrape" {
  targets    = local.file_match.logs_integrations_integrations_node_exporter_direct_scrape.targets
  forward_to = [loki.write.grafana_cloud_loki.receiver]
}
EOF'

# 3. Alloy als Systemdienst aktivieren und starten
sudo systemctl enable --now alloy

🔍 Schritt 2: Status überprüfen

Nachdem das Skript durchgelaufen ist, überprüfe mit folgendem Befehl, ob der Alloy-Dienst sauber läuft:

Bash

sudo systemctl status alloy

Erwartetes Ergebnis: In der Ausgabe sollte in grün active (running) stehen. Das bedeutet, dass der Dienst gestartet ist und bereits Daten verschlüsselt an Grafana Cloud sendet.

🖥️ Schritt 3: Logs & Metriken in Grafana Cloud ansehen

  1. Logge dich in deine Grafana Cloud Instanz ein.
  2. Gehe im linken Menü auf den Kompass Explore.
  3. Für Logs: Wähle oben im Dropdown deine Loki-Datenquelle (z. B. grafanacloud-yourname-logs) aus und filtere nach deiner Instanz mit:Code-Snippet{instance="dein-hostname"}
  4. Für Server-Metriken: Nutze das vorgefertigte Linux Node Dashboard unter Dashboards, um Auslastung, RAM und Festplattenspeicher grafisch aufbereitet zu sehen.

💡 Was passiert hier im Hintergrund? (Für Neugierige)

  • node_exporter: Ein integriertes Modul in Alloy, das System-Performance-Daten liest.
  • loki.source.journal & loki.source.file: Liest direkt aus dem journald (Systemd-Services) sowie Dateien aus /var/log/*.log und pusht sie in Echtzeit an Grafana Loki.
  • prometheus.remote_write: Sendet die Metriken sicher per HTTPS-Endpoint an Prometheus in der Cloud.

Viel Spaß beim Überwachen deiner Infrastruktur! 📊✨