Grafana - Analytics and Monitoring Platform
Install and configure Grafana, the open analytics and monitoring platform for visualizing metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, and many more.
- Step 1
Overview
Grafana is the leading open source analytics and observability platform. It allows you to query, visualize, explore, and alert on your metrics, logs, and traces regardless of where they are stored.
Key capabilities:
- Unified Observability: Metrics, logs, and traces in one place
- Rich Visualizations: 100+ panel types including graphs, heatmaps, tables, and geospatial maps
- Multi-Source Support: Connect to Prometheus, Loki, Elasticsearch, InfluxDB, CloudWatch, Azure Monitor, and 50+ data sources
- Powerful Dashboards: Create interactive, shareable dashboards with variables and templating
- Alerting: Set up alerts based on metrics, logs, or traces with multi-channel notifications
- Annotations: Add context to your data with events from git, deployment tools, and more
- Plugins: Extend functionality with 1000+ community plugins
Why Grafana:
- Open Source: Free and extensible with AGPL-3.0 license
- Enterprise-Ready: Used by Fortune 500 companies and startups alike
- Active Community: 74K+ GitHub stars, 14K+ forks
- Versatile: Works with any data source that supports queries
- Cloud & Self-Hosted: Deploy anywhere - on-prem, containerized, or use Grafana Cloud
Official site: https://grafana.com GitHub: https://github.com/grafana/grafana (74K+ stars) Documentation: https://grafana.com/docs/ Grafana Labs: https://grafana.com/grafana-labs/ - Step 2
Quick Installation Options
Multiple installation methods available depending on your environment:
# Option 1: Docker (recommended for quick start) docker run -d -p 3000:3000 --name grafana grafana/grafana:latest # Option 2: Debian/Ubuntu sudo apt-get update -y sudo apt-get install -y adduser libfontconfig sudo apt-get install -y --no-install-recommends \ apt-transport-https \ software-properties-common \ wget curl -fsSL https://packages.grafana.com/gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/grafana.gpg echo "deb [signed-by=/usr/share/keyrings/grafana.gpg] https://packages.grafana.com/oss/deb stable main" | \ sudo tee -a /etc/apt/sources.list.d/grafana.list sudo apt-get update -y sudo apt-get install -y grafana sudo systemctl start grafana-server sudo systemctl enable grafana-server # Option 3: RHEL/CentOS/Fedora sudo rpm --import https://packages.grafana.com/gpg.key sudo sh -c 'echo -e "[grafana]\nnamed grafana\nbaseurl https://packages.grafana.com/oss/rpm\nenabled 1\ngpgcheck 1\ngpgkey https://packages.grafana.com/gpg.key\nrepo_gpgcheck 1" > /etc/yum.repos.d/grafana.repo' sudo yum install grafana sudo systemctl start grafana-server sudo systemctl enable grafana-server # Option 4: macOS (Homebrew) brew tap grafana/tap brew install grafana brew services start grafana # Option 5: Windows (Chocolatey) choco install grafana # Verify installation curl http://localhost:3000/api/health # Should return: {"database":"OK","version":"11.x.x","commit":"..."} - Step 3
Docker Compose Setup with Prometheus
The most common Grafana setup includes Prometheus for metrics. Here's a complete docker-compose setup with Grafana and Prometheus:
Components:
- Grafana - Visualization and alerting
- Prometheus - Metrics collection and storage
- Node Exporter - System metrics from Linux hosts
version: '3' services: prometheus: image: prom/prometheus:latest container_name: prometheus ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/etc/prometheus/console_libraries' - '--web.console.templates=/etc/prometheus/consoles' - '--web.enable-lifecycle' grafana: image: grafana/grafana:latest container_name: grafana ports: - "3000:3000" volumes: - grafana_data:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning:ro environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false depends_on: - prometheus node-exporter: image: prom/node-exporter:latest container_name: node-exporter ports: - "9100:9100" volumes: - '/proc:/host/proc:ro' - '/sys:/host/sys:ro' - '/:/host:ro,rslave' command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.rootfs=/host' volumes: prometheus_data: grafana_data: networks: default: name: monitoring - Step 4
Prometheus Configuration
Create a Prometheus configuration file to scrape targets and expose metrics to Grafana:
Key configuration options:
global.scrape_interval: How often to scrape targetsscrape_configs: List of scrape jobsstatic_configs: Targets to scrapefile_sd_configs: Dynamic service discovery
global: scrape_interval: 15s evaluation_interval: 15s alerting: alertmanagers: - static_configs: - targets: - localhost:9093 rule_files: - "alerts.yml" scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: 'node-exporter' static_configs: - targets: ['node-exporter:9100'] - job_name: 'grafana' static_configs: - targets: ['grafana:3000'] - job_name: 'cadvisor' static_configs: - targets: ['cadvisor:8080'] - job_name: 'blackbox' metrics_path: /probe params: module: [http_2xx] static_configs: - targets: - https://prometheus.io - https://grafana.com relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox:9115 - Step 5
Grafana Provisioning
Automatically configure datasources, dashboards, and plugins using Grafana's provisioning system. This is essential for reproducible deployments.
Provisioning directories:
/etc/grafana/provisioning/datasources/- Configure datasources/etc/grafana/provisioning/dashboards/- Configure dashboards/etc/grafana/provisioning/plugins/- Configure plugins
# Datasource provisioning (grafana/provisioning/datasources/datasources.yml) apiVersion: 1 datasources: - name: Prometheus type: prometheus access: proxy url: http://prometheus:9090 isDefault: true editable: false version: 1 jsonData: timeInterval: "15s" queryTimeout: "60s" - name: Loki type: loki access: proxy url: http://loki:3100 editable: false version: 1 - name: Tempo type: tempo access: proxy url: http://tempo:3200 editable: false version: 1 jsonData: tracesToLogs: datasourceUid: 'loki' - name: Elasticsearch type: elasticsearch access: proxy url: http://elasticsearch:9200 database: '[logs-]*' interval: Daily editable: false version: 1 jsonData: esVersion: "7.10.0" timeField: "@timestamp" logMessageField: "message" logLevelField: "level" # Dashboard provisioning (grafana/provisioning/dashboards/dashboards.yml) apiVersion: 1 dashboards: - name: 'Default' type: file foldersFromFilesStructure: true options: path: /etc/grafana/provisioning/dashboards - name: 'Node Exporter' org_id: 1 folder: 'Monitoring' type: file options: folder: /etc/grafana/provisioning/dashboards/node-exporter path: /etc/grafana/provisioning/dashboards/node-exporter/ folders: - "Monitoring" pattern: "*.json" data_sources: - name: 'Prometheus' type: prometheus uid: 'prometheus' access: proxy url: http://prometheus:9090 isDefault: true - Step 6
First Dashboard - System Monitoring
Create your first dashboard by importing a pre-made one. Grafana has hundreds of community dashboards available in the marketplace.
Popular dashboards:
- Node Exporter Full - Complete system monitoring
- Prometheus - Prometheus server metrics
- Docker - Container metrics
- PostgreSQL - Database monitoring
# Access Grafana UI open http://localhost:3000 # Login with admin/admin (change password!) # Import a dashboard via UI: # 1. Click "+" -> Import # 2. Enter dashboard Grafana.com ID # 3. Select datasource # 4. Click Import # Popular dashboard IDs: # Node Exporter Full: 1860 # Prometheus: 2 # Docker: 11402 # PostgreSQL: 9812 # AWS CloudWatch: 10017 # Or download JSON and import: curl -O https://raw.githubusercontent.com/grafana/dashboards/master/prometheus_2.json # Then import via UI or API: curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d @prometheus_2.json \ http://localhost:3000/api/dashboards/import - Step 7
Create Custom Dashboard via API
Grafana's REST API allows you to programmatically create dashboards. This is useful for CI/CD pipelines and reproducible setups.
Dashboard structure:
title: Dashboard namepanels: Array of visualization panelstimezone: Dashboard timezonerefresh: Auto-refresh interval
{ "dashboard": { "title": "My First Dashboard", "uid": "my-first-dashboard", "tags": ["demo"], "timezone": "browser", "refresh": "30s", "schemaVersion": 16, "version": 0, "panels": [ { "id": 1, "title": "CPU Usage", "type": "gauge", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, "fieldConfig": { "defaults": { "unit": "percent", "max": 100, "min": 0, "thresholds": { "mode": "absolute", "steps": [ {"color": "green", "value": null}, {"color": "yellow", "value": 70}, {"color": "red", "value": 90} ] } } }, "targets": [ { "expr": "100 - (avg(irate(node_cpu_seconds_total{mode=\"idle\", instance=\"localhost:9100\"}[5m])) * 100)", "legendFormat": "CPU Usage", "refId": "A" } ] }, { "id": 2, "title": "Memory Usage", "type": "bargauge", "datasource": { "type": "prometheus", "uid": "prometheus" }, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, "fieldConfig": { "defaults": { "unit": "percent", "max": 100, "min": 0 } }, "targets": [ { "expr": "(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100", "legendFormat": "Memory Usage", "refId": "A" } ] } ] }, "overwrite": true } - Step 8
Alerting Setup
Grafana Alerting allows you to set up alerts based on metrics, logs, or traces. Configure notifications via email, Slack, PagerDuty, and 30+ channels.
Alerting concepts:
- Alert rules: Define conditions that trigger alerts
- Contact points: Notification channels (email, Slack, etc.)
- Notification policies: Route alerts to contact points
- Mute timings: Suppress alerts during maintenance windows
# Alerting provisioning (grafana/provisioning/alerting/rules.yml) groups: - name: system_alerts folder: Monitoring interval: 1m rules: - uid: cpu-alert title: High CPU Usage condition: A data: - refId: A datasourceUid: prometheus model: expr: "100 - (avg(irate(node_cpu_seconds_total{mode='idle'}[5m])) * 100) > 80" intervalMs: 1000 relativeTimeRange: from: 5 to: 0 refId: A noDataState: NoData execErrState: OK for: 5m annotations: summary: "High CPU usage detected" description: "CPU usage is above 80% for more than 5 minutes" labels: severity: warning - uid: memory-alert title: High Memory Usage condition: A data: - refId: A datasourceUid: prometheus model: expr: "(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90" intervalMs: 1000 relativeTimeRange: from: 5 to: 0 refId: A noDataState: NoData execErrState: OK for: 5m annotations: summary: "High memory usage detected" description: "Memory usage is above 90% for more than 5 minutes" labels: severity: critical - uid: disk-alert title: Low Disk Space condition: A data: - refId: A datasourceUid: prometheus model: expr: "(node_filesystem_avail_bytes{mountpoint='/'} / node_filesystem_size_bytes{mountpoint='/'}) * 100 < 10" intervalMs: 1000 relativeTimeRange: from: 5 to: 0 refId: A noDataState: NoData execErrState: OK for: 10m annotations: summary: "Low disk space detected" description: "Disk space is below 10% for more than 10 minutes" labels: severity: critical # Contact points (grafana/provisioning/alerting/contactpoints.yml) contactPoints: - name: email-notifications receivers: - uid: email-1 type: email settings: addresses: "admin@example.com" - name: slack-notifications receivers: - uid: slack-1 type: slack settings: webhookUrl: "https://hooks.slack.com/services/YOUR/WEBHOOK/URL" recipient: "#alerts" - name: pagerduty-notifications receivers: - uid: pagerduty-1 type: pagerduty settings: routingKey: "your-routing-key" severity: "critical" - Step 9
Grafana Loki for Logs
Grafana Loki is a horizontally scalable, highly available, multi-tenant log aggregation system inspired by Prometheus. It's lightweight and cost-effective compared to Elasticsearch.
Loki architecture:
- Promtail: Scrapes and ships logs to Loki
- Loki: Stores and indexes logs
- Grafana: Visualizes logs
# Loki setup in docker-compose services: loki: image: grafana/loki:latest ports: - "3100:3100" volumes: - ./loki.yml:/etc/loki/local-config.yml command: -config.file=/etc/loki/local-config.yml promtail: image: grafana/promtail:latest volumes: - /var/log:/var/log:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro - ./promtail.yml:/etc/promtail/config.yml command: -config.file=/etc/promtail/config.yml # loki.yml configuration auth_enabled: false server: http_listen_port: 3100 grpc_max_msg_size: 33554432 common: path_prefix: /tmp/loki replication_factor: 1 ring: kvstore: store: inmemory query_range: results_cache: cache: embedded: enabled: true max_size_mb: 100 schema_config: configs: - from: 2020-10-24 store: tsdb object_store: filesystem schema: v13 index: prefix: index_ period: 24h # promtail.yml configuration server: http_listen_port: 9080 grpc_max_send_msg_size: 512000000 positions: filename: /tmp/positions.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name: system static_configs: - targets: - localhost labels: job: varlogs __path__: /var/log/*log - job_name: docker static_configs: - targets: - localhost labels: job: containerlogs __path__: /var/lib/docker/containers/*/*.log - job_name: journal journal: max_age: 12h relabel_configs: - source_labels: ['__journal__systemd_unit'] target_label: 'unit' - source_labels: ['__journal__hostname'] target_label: 'hostname' - Step 10
Grafana Tempo for Traces
Grafana Tempo is a high-volume, low-storage, horizontal scalable distributed trace backend. It integrates seamlessly with Grafana and Loki for unified observability.
Distributed tracing benefits:
- Track requests across microservices
- Identify performance bottlenecks
- Debug complex distributed systems
- Visualize service dependencies
# Tempo setup in docker-compose services: tempo: image: grafana/tempo:latest ports: - "14268:14268" # Jaeger ingest - "14269:14269" # Jaeger query - "3200:3200" # Tempo read - "4317:4317" # OTLP gRPC - "4318:4318" # OTLP HTTP volumes: - ./tempo.yml:/etc/tempo.yml - tempo_data:/tmp/tempo command: ["-config.file=/etc/tempo.yml"] # tempo.yml configuration server: http_listen_port: 3200 global: id: local-tempo # Tempo will use the machine IP for the internal server address external_grpc_addr: 0.0.0.0:9095 distributor: receivers: otlp: protocols: http: endpoint: 0.0.0.0:4318 grpc: endpoint: 0.0.0.0:4317 jaeger: protocols: thrift_http: endpoint: 0.0.0.0:14268 grpc: endpoint: 0.0.0.0:14250 thrift_compact: endpoint: 0.0.0.0:6831 thrift_binary: endpoint: 0.0.0.0:6832 zipkin: endpoint: 0.0.0.0:9411 traces: ingester: wal: directory: /tmp/tempo/wal lifecycler: ring: kvstore: store: memberlist compiler: inline_dependencies: true storage: trace: backend: local wal: path: /tmp/tempo/wal local: path: /tmp/tempo/blocks query_scheduler: frontend: type: noop overrides: max_traces_per_query: 1000 max_tag_value_length: 1000 max_datapoints_per_series: 100000 - Step 11
Plugin Management
Grafana has 1000+ community plugins to extend functionality. Install plugins for additional data sources, visualization panels, and apps.
Popular plugins:
- Grafana WorldMap Panel: Geospatial visualization
- Pie Chart: Pie and doughnut charts
- Pie Chart Panel: Multi-row pie charts
- MySQL: MySQL datasource
- MongoDB: MongoDB datasource
- CloudWatch: AWS CloudWatch metrics
# List installed plugins grafana-cli plugins ls # Install a plugin grafana-cli plugins install grafana-piechart-panel # Update all plugins grafana-cli plugins update --all # Remove a plugin grafana-cli plugins remove grafana-piechart-panel # Install from a git repo grafana-cli plugins install https://github.com/grafana/example-pie-chart-panel # Update plugin configuration # Edit /etc/grafana/plugins/<plugin-id>/plugin.json # Or use the UI: # 1. Click "Plugins" in left menu # 2. Browse or search for plugins # 3. Click "Install" # 4. Reload page to activate - Step 12
Authentication & Authorization
Grafana supports multiple authentication methods and role-based access control (RBAC) for securing your dashboards and data sources.
Authentication options:
- Anonymous access
- Basic auth (username/password)
- LDAP/Active Directory
- OAuth providers (GitHub, Google, GitLab, etc.)
- SAML
- API keys
RBAC roles:
- Admin: Full access
- Editor: Can create/edit dashboards
- Viewer: Read-only access
# Configuration file: /etc/grafana/grafana.ini # [security] # Disable anonymous access allow_sign_up = false allow_org_create = false # [users] # Auto-assign users to organization auto_assign_org = true auto_assign_org_role = Viewer # [auth] # Login cookie settings login_cookie_name = grafana_session # [auth.anonymous] # Enable anonymous access (not recommended for production) # enabled = true # org_name = Grafana # org_role = Viewer # [auth.ldap] # LDAP configuration # enabled = true # config_file = /etc/grafana/ldap.toml # allow_sign_up = true # [auth.github] # GitHub OAuth # enabled = true # allow_sign_up = true # client_id = your-client-id # client_secret = your-client-secret # scopes = user:email,read:org # auth_url = https://github.com/login/oauth/authorize # token_url = https://github.com/login/oauth/access_token # api_url = https://api.github.com/user # [auth.google] # Google OAuth # enabled = true # allow_sign_up = true # client_id = your-client-id # client_secret = your-client-secret # scopes = https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email # Create API key via UI or API: # UI: Configuration -> API Keys -> Add new API key # API: curl -X POST -H "Content-Type: application/json" \ -H "Authorization: Basic YWRtaW46YWRtaW4=" \ -d '{"name":"my-api-key","role":"Viewer"}' \ http://localhost:3000/api/auth/keys # Use API key in requests: curl -H "Authorization: Bearer YOUR_API_KEY" \ http://localhost:3000/api/search?type=dashboard - Step 13
High Availability Setup
For production deployments, set up Grafana for high availability and scalability:
HA components:
- Multiple Grafana instances behind load balancer
- External database (PostgreSQL, MySQL) instead of SQLite
- Shared filesystem or object storage for plugins
- Redis for session storage
- Grafana Enterprise for advanced features
# High availability docker-compose version: '3' services: grafana-1: image: grafana/grafana:latest ports: - "3000:3000" volumes: - grafana_data_1:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning:ro environment: - GF_SERVER_HTTP_PORT=3000 - GF_SERVER_ROOT_URL=http://grafana-1:3000/ - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false - GF_SESSION_SECRET=your-secret-key - GF_SESSION_STORE_TYPE=redis - GF_SESSION_STORE_PREFIX=grafana_session - GF_SESSION_STORE_ADDRESS=redis:6379 depends_on: - redis - postgres grafana-2: image: grafana/grafana:latest ports: - "3001:3000" volumes: - grafana_data_2:/var/lib/grafana - ./grafana/provisioning:/etc/grafana/provisioning:ro environment: - GF_SERVER_HTTP_PORT=3000 - GF_SERVER_ROOT_URL=http://grafana-2:3000/ - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin - GF_USERS_ALLOW_SIGN_UP=false - GF_SESSION_SECRET=your-secret-key - GF_SESSION_STORE_TYPE=redis - GF_SESSION_STORE_PREFIX=grafana_session - GF_SESSION_STORE_ADDRESS=redis:6379 depends_on: - redis - postgres redis: image: redis:alpine ports: - "6379:6379" volumes: - redis_data:/data postgres: image: postgres:14 ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_DB=grafana - POSTGRES_USER=grafana - POSTGRES_PASSWORD=grafana nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - grafana-1 - grafana-2 volumes: grafana_data_1: grafana_data_2: redis_data: postgres_data: # grafana.ini for HA # [database] type = postgres host = 127.0.0.1:5432 name = grafana user = grafana password = __REDACTED__ ssl_mode = disable # [session] type = redis cookie_lifetime = 86400 # [session REDIS] prefix = grafana_session address = localhost:6379 password = __REDACTED__ db = 0 pool_size = 10 - Step 14
Cloud & Managed Options
For production deployments without self-management overhead, consider managed Grafana services:
Managed options:
- Grafana Cloud: Free tier available, includes Loki, Tempo, Alertmanager
- AWS Managed Grafana: Fully managed on AWS
- Azure Managed Grafana: Managed Grafana on Azure
- Google Cloud Grafana: Grafana on GCP
Benefits:
- Zero infrastructure management
- Automatic updates
- Built-in monitoring
- Easy scaling
- Backup & disaster recovery
Grafana Cloud (free tier): - 100GB Loki log storage - 10GB Tempo trace storage - 10 Prometheus data sources - 2000 Alert rules - Unlimited dashboards https://grafana.com/cloud/ AWS Managed Grafana: https://aws.amazon.com/grafana/ Azure Managed Grafana: https://azure.microsoft.com/en-us/products/managed-grafana/ Google Cloud Grafana: https://cloud.google.com/grafana Self-hosted vs Managed comparison: https://grafana.com/hosted-vs-self-hosted-grafana/ - Step 15
Resources & Next Steps
Documentation:
- Grafana Documentation
- Grafana Labs - Blog and resources
- Prometheus Docs
- Loki Docs
- Tempo Docs
Community:
Learning:
- Grafana Academy - Free courses
- Prometheus Best Practices
- Logging Best Practices
- Distributed Tracing Guide
Plugins & Dashboards:
Next guides:
- Prometheus installation and configuration
- Grafana Loki setup for log aggregation
- Grafana Tempo for distributed tracing
- Grafana Alerting advanced configuration
- Mimir for large-scale metrics storage
GitHub: https://github.com/grafana/grafana Official site: https://grafana.com Documentation: https://grafana.com/docs/ Grafana Cloud: https://grafana.com/cloud/ Prometheus: https://prometheus.io Loki: https://grafana.com/docs/loki/ Tempo: https://grafana.com/docs/tempo/
Feature requests
Sign in to suggest features or vote on existing ones.
No feature requests yet.
Discussion
Sign in to join the discussion.
No comments yet.