This guide provides a complete Ansible playbook to install Grafana from official repositories with proper configuration, database setup, and security hardening.
Current Grafana version: 12.3.2
Create a file named grafana.yml:
---
- name: Install and Configure Grafana
hosts: grafana
become: true
vars:
grafana_version: "12.3.2"
grafana_port: 3000
grafana_admin_user: "admin"
grafana_admin_password: "changeme123" # Change this!
grafana_data_dir: "/var/lib/grafana"
grafana_log_dir: "/var/log/grafana"
grafana_config_dir: "/etc/grafana"
tasks:
- name: Install prerequisites (Debian/Ubuntu)
apt:
name:
- apt-transport-https
- software-properties-common
- wget
- gnupg
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install prerequisites (RHEL/CentOS)
yum:
name:
- wget
- gnupg2
state: present
when: ansible_os_family == "RedHat"
- name: Add Grafana APT key (Debian/Ubuntu)
apt_key:
url: https://packages.grafana.com/gpg.key
state: present
when: ansible_os_family == "Debian"
- name: Add Grafana APT repository (Debian/Ubuntu)
apt_repository:
repo: "deb https://packages.grafana.com/oss/deb stable main"
state: present
filename: grafana
when: ansible_os_family == "Debian"
- name: Add Grafana YUM repository (RHEL/CentOS)
yum_repository:
name: grafana
description: Grafana OSS Repository
baseurl: https://packages.grafana.com/oss/rpm
gpgcheck: true
gpgkey: https://packages.grafana.com/gpg.key
enabled: true
when: ansible_os_family == "RedHat"
- name: Install Grafana
package:
name: "grafana{% if grafana_version %}={{ grafana_version }}{% endif %}"
state: present
when: ansible_os_family == "RedHat"
- name: Install Grafana (Debian/Ubuntu)
apt:
name: "grafana{% if grafana_version %}={{ grafana_version }}{% endif %}"
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Create Grafana configuration directory
file:
path: "{{ grafana_config_dir }}/provisioning"
state: directory
owner: grafana
group: grafana
mode: '0755'
- name: Configure Grafana settings
lineinfile:
path: "{{ grafana_config_dir }}/grafana.ini"
regexp: "^;?{{ item.key }} ="
line: "{{ item.key }} = {{ item.value }}"
loop:
- { key: 'http_port', value: '{{ grafana_port }}' }
- { key: 'domain', value: '{{ ansible_fqdn | default(ansible_hostname) }}' }
- { key: 'root_url', value: 'http://{{ ansible_fqdn | default(ansible_hostname) }}:{{ grafana_port }}/' }
- { key: 'admin_user', value: '{{ grafana_admin_user }}' }
- { key: 'admin_password', value: '{{ grafana_admin_password }}' }
- { key: 'allow_sign_up', value: 'false' }
- name: Enable and start Grafana service
systemd:
name: grafana-server
enabled: true
state: started
daemon_reload: true
- name: Wait for Grafana to start
wait_for:
port: "{{ grafana_port }}"
delay: 5
timeout: 60
- name: Configure firewall (UFW)
ufw:
rule: allow
port: "{{ grafana_port }}"
proto: tcp
comment: "Grafana web interface"
when: ansible_os_family == "Debian"
failed_when: false
- name: Configure firewall (firewalld)
firewalld:
port: "{{ grafana_port }}/tcp"
permanent: true
immediate: true
state: enabled
when: ansible_os_family == "RedHat"
failed_when: false
- name: Display Grafana status
debug:
msg: |
Grafana {{ grafana_version }} installed successfully!
Access at: http://{{ ansible_default_ipv4.address | default(ansible_host) }}:{{ grafana_port }}
Username: {{ grafana_admin_user }}
Password: {{ grafana_admin_password }}
IMPORTANT: Change the default password after first login!
Create an inventory file inventory.yml:
---
grafana:
hosts:
grafana-server:
ansible_host: 192.168.1.101
ansible_user: ansible
ansible_become: true
# Test connectivity
ansible all -i inventory.yml -m ping
# Run the Grafana playbook
ansible-playbook -i inventory.yml grafana.yml
# Run with custom admin password
ansible-playbook -i inventory.yml grafana.yml -e "grafana_admin_password=MySecureP@ss123"
# Check service status
ssh grafana-server "sudo systemctl status grafana-server"
# Test health endpoint
curl http://grafana-server:3000/api/health
# Access web UI
# http://grafana-server:3000
Create a provisioning file for Prometheus:
- name: Configure Prometheus data source
hosts: grafana
become: true
vars:
prometheus_url: "http://prometheus-server:9090"
tasks:
- name: Create provisioning datasources directory
file:
path: /etc/grafana/provisioning/datasources
state: directory
owner: grafana
group: grafana
mode: '0755'
- name: Add Prometheus data source
copy:
dest: /etc/grafana/provisioning/datasources/prometheus.yml
owner: grafana
group: grafana
mode: '0640'
content: |
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: {{ prometheus_url }}
isDefault: true
editable: false
jsonData:
timeInterval: "15s"
httpMethod: POST
- name: Restart Grafana to apply data source
systemd:
name: grafana-server
state: restarted
Create dashboard provisioning:
- name: Configure Grafana dashboards
hosts: grafana
become: true
tasks:
- name: Create provisioning dashboards directory
file:
path: "{{ item }}"
state: directory
owner: grafana
group: grafana
mode: '0755'
loop:
- /etc/grafana/provisioning/dashboards
- /etc/grafana/dashboards
- name: Add dashboard provider
copy:
dest: /etc/grafana/provisioning/dashboards/default.yml
owner: grafana
group: grafana
mode: '0640'
content: |
apiVersion: 1
providers:
- name: 'Default'
orgId: 1
folder: ''
type: file
disableDeletion: false
updateIntervalSeconds: 30
options:
path: /etc/grafana/dashboards
- name: Download Node Exporter dashboard
get_url:
url: https://grafana.com/api/dashboards/1860/revisions/23735/download
dest: /etc/grafana/dashboards/node-exporter.json
owner: grafana
group: grafana
mode: '0640'
register: dashboard_download
failed_when: false
- name: Restart Grafana
systemd:
name: grafana-server
state: restarted
Add security configuration:
- name: Harden Grafana security
hosts: grafana
become: true
tasks:
- name: Configure security settings
lineinfile:
path: /etc/grafana/grafana.ini
regexp: "^;?{{ item.key }} ="
line: "{{ item.key }} = {{ item.value }}"
loop:
- { key: 'secret_key', value: 'CHANGE_THIS_TO_A_SECURE_RANDOM_STRING' }
- { key: 'login_remember_days', value: '7' }
- { key: 'cookie_secure', value: 'true' }
- { key: 'allow_embedding', value: 'false' }
- name: Configure LDAP (optional)
lineinfile:
path: /etc/grafana/grafana.ini
regexp: "^;?auth\.ldap ="
line: "auth.ldap = true"
- name: Create LDAP configuration file
copy:
dest: /etc/grafana/ldap.toml
owner: grafana
group: grafana
mode: '0640'
content: |
[[servers]]
host = "ldap.example.com"
port = 389
use_ssl = false
start_tls = true
ssl_skip_verify = false
bind_dn = "cn=admin,dc=example,dc=com"
bind_password = 'ldap_password'
[[servers.group_mappings]]
group_dn = "cn=grafana-users,dc=example,dc=com"
org_role = "Viewer"
- name: Restart Grafana
systemd:
name: grafana-server
state: restarted
- name: Configure Grafana alerting
hosts: grafana
become: true
tasks:
- name: Enable unified alerting
lineinfile:
path: /etc/grafana/grafana.ini
regexp: "^;?unified_alerting\.enabled ="
line: "unified_alerting.enabled = true"
- name: Configure alerting settings
lineinfile:
path: /etc/grafana/grafana.ini
regexp: "^;?{{ item.key }} ="
line: "{{ item.key }} = {{ item.value }}"
loop:
- { key: 'unified_alerting.execute_alerts', value: 'true' }
- { key: 'unified_alerting.evaluation_timeout', value: '30s' }
- name: Restart Grafana
systemd:
name: grafana-server
state: restarted
- name: Configure email for alerts
hosts: grafana
become: true
tasks:
- name: Configure SMTP settings
lineinfile:
path: /etc/grafana/grafana.ini
regexp: "^;?{{ item.key }} ="
line: "{{ item.key }} = {{ item.value }}"
loop:
- { key: 'smtp.enabled', value: 'true' }
- { key: 'smtp.host', value: 'smtp.example.com:587' }
- { key: 'smtp.user', value: 'grafana@example.com' }
- { key: 'smtp.password', value: 'smtp_password' }
- { key: 'smtp.from_address', value: 'grafana@example.com' }
- { key: 'smtp.skip_verify', value: 'false' }
- name: Restart Grafana
systemd:
name: grafana-server
state: restarted
# Check logs
sudo journalctl -u grafana-server -f
# Check configuration
sudo grafana-cli admin settings
# Verify port is not in use
sudo netstat -tlnp | grep 3000
# Reset admin password
sudo grafana-cli admin reset-admin-password newpassword
# Check database status
sudo sqlite3 /var/lib/grafana/grafana.db ".tables"
# List installed plugins
sudo grafana-cli plugins ls
# Install a plugin
sudo grafana-cli plugins install grafana-clock-panel
# Update all plugins
sudo grafana-cli plugins update-all
Beyond this playbook, we offer:
Contact our automation team: office@linux-server-admin.com