This guide provides a complete Ansible playbook to install Prometheus from official sources with proper configuration, systemd service, and firewall setup.
Current Prometheus version: 3.10.0 (LTS 3.5.1)
Create a file named prometheus.yml:
---
- name: Install and Configure Prometheus
hosts: prometheus
become: true
vars:
prometheus_version: "3.10.0"
prometheus_user: "prometheus"
prometheus_group: "prometheus"
prometheus_config_dir: "/etc/prometheus"
prometheus_data_dir: "/var/lib/prometheus"
prometheus_binary_url: "https://github.com/prometheus/prometheus/releases/download/v{{ prometheus_version }}/prometheus-{{ prometheus_version }}.linux-amd64.tar.gz"
prometheus_port: 9090
tasks:
- name: Create Prometheus group
group:
name: "{{ prometheus_group }}"
state: present
- name: Create Prometheus user
user:
name: "{{ prometheus_user }}"
group: "{{ prometheus_group }}"
system: true
shell: /usr/sbin/nologin
create_home: false
- name: Install required packages
package:
name:
- wget
- curl
- tar
state: present
when: ansible_os_family == "RedHat"
- name: Install required packages (Debian/Ubuntu)
apt:
name:
- wget
- curl
- tar
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Create Prometheus directories
file:
path: "{{ item }}"
state: directory
owner: "{{ prometheus_user }}"
group: "{{ prometheus_group }}"
mode: '0755'
loop:
- "{{ prometheus_config_dir }}"
- "{{ prometheus_data_dir }}"
- /etc/prometheus/rules
- /etc/prometheus/file_sd
- name: Download Prometheus
get_url:
url: "{{ prometheus_binary_url }}"
dest: "/tmp/prometheus-{{ prometheus_version }}.tar.gz"
mode: '0644'
register: download_result
- name: Extract Prometheus archive
unarchive:
src: "/tmp/prometheus-{{ prometheus_version }}.tar.gz"
dest: /tmp
remote_src: true
creates: "/tmp/prometheus-{{ prometheus_version }}.linux-amd64"
- name: Move Prometheus binaries
copy:
src: "/tmp/prometheus-{{ prometheus_version }}.linux-amd64/{{ item }}"
dest: /usr/local/bin/
owner: root
group: root
mode: '0755'
remote_src: true
loop:
- prometheus
- promtool
- name: Create Prometheus configuration file
copy:
dest: "{{ prometheus_config_dir }}/prometheus.yml"
owner: "{{ prometheus_user }}"
group: "{{ prometheus_group }}"
mode: '0644'
content: |
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets: []
rule_files:
- /etc/prometheus/rules/*.yml
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:{{ prometheus_port }}']
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
- name: Create systemd service file
copy:
dest: /etc/systemd/system/prometheus.service
owner: root
group: root
mode: '0644'
content: |
[Unit]
Description=Prometheus Monitoring
Wants=network-online.target
After=network-online.target
[Service]
User={{ prometheus_user }}
Group={{ prometheus_group }}
Type=simple
ExecStart=/usr/local/bin/prometheus \
--config.file={{ prometheus_config_dir }}/prometheus.yml \
--storage.tsdb.path={{ prometheus_data_dir }} \
--storage.tsdb.retention.time=15d \
--web.listen-address=0.0.0.0:{{ prometheus_port }} \
--web.console.templates=/etc/prometheus/consoles \
--web.console.libraries=/etc/prometheus/console_libraries
Restart=on-failure
[Install]
WantedBy=multi-user.target
- name: Reload systemd daemon
systemd:
daemon_reload: true
- name: Enable and start Prometheus service
systemd:
name: prometheus
enabled: true
state: started
daemon_reload: true
- name: Configure firewall (UFW)
ufw:
rule: allow
port: "{{ prometheus_port }}"
proto: tcp
comment: "Prometheus monitoring"
when: ansible_os_family == "Debian"
failed_when: false
- name: Configure firewall (firewalld)
firewalld:
port: "{{ prometheus_port }}/tcp"
permanent: true
immediate: true
state: enabled
when: ansible_os_family == "RedHat"
failed_when: false
- name: Verify Prometheus is running
uri:
url: "http://localhost:{{ prometheus_port }}/-/healthy"
method: GET
status_code: 200
register: health_check
retries: 5
delay: 3
until: health_check.status == 200
- name: Display Prometheus status
debug:
msg: "Prometheus {{ prometheus_version }} installed successfully. Access at http://{{ ansible_default_ipv4.address }}:{{ prometheus_port }}"
Create an inventory file inventory.yml:
---
prometheus:
hosts:
prometheus-server:
ansible_host: 192.168.1.100
ansible_user: ansible
ansible_become: true
# Test connectivity first
ansible all -i inventory.yml -m ping
# Run the Prometheus playbook
ansible-playbook -i inventory.yml prometheus.yml
# Run with verbose output
ansible-playbook -i inventory.yml prometheus.yml -v
# Check service status
ssh prometheus-server "sudo systemctl status prometheus"
# Test health endpoint
curl http://prometheus-server:9090/-/healthy
# Access web UI
# http://prometheus-server:9090
To monitor system metrics, add Node Exporter:
- name: Install Node Exporter
hosts: prometheus
become: true
vars:
node_exporter_version: "1.10.2"
tasks:
- name: Create node_exporter user
user:
name: node_exporter
system: true
shell: /usr/sbin/nologin
create_home: false
- name: Download Node Exporter
get_url:
url: "https://github.com/prometheus/node_exporter/releases/download/v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.linux-amd64.tar.gz"
dest: /tmp/node_exporter.tar.gz
- name: Extract Node Exporter
unarchive:
src: /tmp/node_exporter.tar.gz
dest: /tmp
remote_src: true
- name: Move Node Exporter binary
copy:
src: "/tmp/node_exporter-{{ node_exporter_version }}.linux-amd64/node_exporter"
dest: /usr/local/bin/node_exporter
owner: node_exporter
group: node_exporter
mode: '0755'
remote_src: true
- name: Create Node Exporter systemd service
copy:
dest: /etc/systemd/system/node_exporter.service
content: |
[Unit]
Description=Node Exporter
After=network.target
[Service]
User=node_exporter
Group=node_exporter
Type=simple
ExecStart=/usr/local/bin/node_exporter
Restart=on-failure
[Install]
WantedBy=multi-user.target
- name: Enable and start Node Exporter
systemd:
name: node_exporter
enabled: true
state: started
daemon_reload: true
Create /etc/prometheus/rules/alerts.yml:
groups:
- name: example-alerts
rules:
- alert: InstanceDown
expr: up == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes."
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 10m
labels:
severity: warning
annotations:
summary: "High memory usage on {{ $labels.instance }}"
description: "Memory usage is above 90%"
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 10m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU usage is above 80%"
Update prometheus.yml to add more targets:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['localhost:9100']
- job_name: 'webservers'
static_configs:
- targets: ['web1.example.com:9100', 'web2.example.com:9100']
- job_name: 'databases'
static_configs:
- targets: ['db1.example.com:9104'] # MySQL exporter
# Check logs
sudo journalctl -u prometheus -f
# Test configuration
sudo -u prometheus promtool check config /etc/prometheus/prometheus.yml
# UFW (Debian/Ubuntu)
sudo ufw status
sudo ufw allow 9090/tcp
# firewalld (RHEL/CentOS)
sudo firewall-cmd --list-ports
sudo firewall-cmd --add-port=9090/tcp --permanent
sudo firewall-cmd --reload
# Check SELinux status
getenforce
# Allow Prometheus to bind to port
sudo semanage port -a -t http_port_t -p tcp 9090
Beyond this playbook, we offer:
Contact our automation team: office@linux-server-admin.com