496 lines
14 KiB
YAML
496 lines
14 KiB
YAML
---
|
|
# PPLG - Consolidated Observability & Admin Stack for Prospero
|
|
# PgAdmin, Prometheus, Loki, Grafana + HAProxy (TLS) + OAuth2-Proxy (Prometheus UI)
|
|
# Red Panda Approved
|
|
|
|
- name: Deploy PPLG Stack
|
|
hosts: ubuntu
|
|
become: true
|
|
tasks:
|
|
- name: Check if host has pplg service
|
|
ansible.builtin.set_fact:
|
|
has_pplg_service: "{{'pplg' in services}}"
|
|
|
|
- name: Skip hosts without pplg service
|
|
ansible.builtin.meta: end_host
|
|
when: not has_pplg_service
|
|
|
|
# ===========================================================================
|
|
# APT Repositories
|
|
# ===========================================================================
|
|
|
|
- name: Add Grafana APT repository (Grafana + Loki)
|
|
ansible.builtin.deb822_repository:
|
|
name: grafana
|
|
types: [deb]
|
|
uris: https://apt.grafana.com
|
|
suites: [stable]
|
|
components: [main]
|
|
signed_by: https://apt.grafana.com/gpg.key
|
|
state: present
|
|
|
|
- name: Add PgAdmin APT repository
|
|
ansible.builtin.deb822_repository:
|
|
name: pgadmin4
|
|
types: [deb]
|
|
uris: https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/{{ansible_distribution_release}}
|
|
suites: [pgadmin4]
|
|
components: [main]
|
|
signed_by: https://www.pgadmin.org/static/packages_pgadmin_org.pub
|
|
state: present
|
|
|
|
# ===========================================================================
|
|
# Package Installation
|
|
# ===========================================================================
|
|
|
|
- name: Install PPLG packages
|
|
ansible.builtin.apt:
|
|
name:
|
|
- acl
|
|
- haproxy
|
|
- prometheus
|
|
- loki
|
|
- grafana
|
|
- pgadmin4-web
|
|
state: present
|
|
update_cache: true
|
|
|
|
- name: Stop and disable Apache (pulled in by pgadmin4-web)
|
|
ansible.builtin.systemd:
|
|
name: apache2
|
|
state: stopped
|
|
enabled: false
|
|
|
|
# ===========================================================================
|
|
# Prometheus
|
|
# ===========================================================================
|
|
|
|
- name: Fix Prometheus directory permissions
|
|
ansible.builtin.file:
|
|
path: /var/lib/prometheus
|
|
owner: prometheus
|
|
group: prometheus
|
|
mode: '750'
|
|
recurse: true
|
|
|
|
- name: Create textfile collector directory
|
|
ansible.builtin.file:
|
|
path: /var/lib/prometheus/node-exporter
|
|
state: directory
|
|
owner: prometheus
|
|
group: prometheus
|
|
mode: '750'
|
|
|
|
- name: Template prometheus.yml
|
|
ansible.builtin.template:
|
|
src: prometheus.yml.j2
|
|
dest: /etc/prometheus/prometheus.yml
|
|
owner: prometheus
|
|
group: prometheus
|
|
mode: '640'
|
|
notify: restart prometheus
|
|
|
|
- name: Template alert_rules.yml
|
|
ansible.builtin.template:
|
|
src: alert_rules.yml.j2
|
|
dest: /etc/prometheus/alert_rules.yml
|
|
owner: prometheus
|
|
group: prometheus
|
|
mode: '640'
|
|
notify: restart prometheus
|
|
|
|
- name: Create Prometheus systemd override directory
|
|
ansible.builtin.file:
|
|
path: /etc/systemd/system/prometheus.service.d
|
|
state: directory
|
|
mode: '755'
|
|
|
|
- name: Enable remote write receiver
|
|
ansible.builtin.copy:
|
|
content: |
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=/usr/bin/prometheus --config.file=/etc/prometheus/prometheus.yml --storage.tsdb.path=/var/lib/prometheus/metrics2/ --web.console.templates=/etc/prometheus/consoles --web.console.libraries=/etc/prometheus/console_libraries --web.listen-address=0.0.0.0:9090 --web.external-url= --web.enable-remote-write-receiver
|
|
dest: /etc/systemd/system/prometheus.service.d/override.conf
|
|
mode: '644'
|
|
notify: restart prometheus
|
|
|
|
- name: Start and enable Prometheus service
|
|
ansible.builtin.systemd:
|
|
name: prometheus
|
|
state: started
|
|
enabled: true
|
|
daemon_reload: true
|
|
|
|
# ===========================================================================
|
|
# Prometheus Alertmanager
|
|
# ===========================================================================
|
|
|
|
- name: Install Alertmanager
|
|
ansible.builtin.apt:
|
|
name: prometheus-alertmanager
|
|
state: present
|
|
|
|
- name: Create alertmanager configuration directory
|
|
ansible.builtin.file:
|
|
path: /etc/alertmanager
|
|
state: directory
|
|
owner: prometheus
|
|
group: prometheus
|
|
mode: '750'
|
|
|
|
- name: Template alertmanager.yml
|
|
ansible.builtin.template:
|
|
src: alertmanager.yml.j2
|
|
dest: /etc/alertmanager/alertmanager.yml
|
|
owner: prometheus
|
|
group: prometheus
|
|
mode: '640'
|
|
notify: restart alertmanager
|
|
|
|
- name: Start and enable Alertmanager service
|
|
ansible.builtin.systemd:
|
|
name: prometheus-alertmanager
|
|
state: started
|
|
enabled: true
|
|
daemon_reload: true
|
|
|
|
# ===========================================================================
|
|
# Loki
|
|
# ===========================================================================
|
|
|
|
- name: Create loki group
|
|
ansible.builtin.group:
|
|
name: "{{loki_group}}"
|
|
|
|
- name: Create loki user
|
|
ansible.builtin.user:
|
|
name: "{{loki_user}}"
|
|
comment: "{{loki_user}}"
|
|
group: "{{loki_group}}"
|
|
system: true
|
|
|
|
- name: Create loki directories
|
|
ansible.builtin.file:
|
|
path: "{{item}}"
|
|
owner: "{{loki_user}}"
|
|
group: "{{loki_group}}"
|
|
state: directory
|
|
mode: '750'
|
|
loop:
|
|
- "{{loki_data_dir}}"
|
|
- "{{loki_config_dir}}"
|
|
|
|
- name: Template Loki configuration
|
|
ansible.builtin.template:
|
|
src: "{{loki_config_file}}.j2"
|
|
dest: "{{loki_config_dir}}/{{loki_config_file}}"
|
|
owner: "{{loki_user}}"
|
|
group: "{{loki_group}}"
|
|
mode: '550'
|
|
notify: restart loki
|
|
|
|
- name: Enable and start Loki service
|
|
ansible.builtin.systemd:
|
|
name: loki
|
|
enabled: true
|
|
state: started
|
|
|
|
# ===========================================================================
|
|
# Grafana
|
|
# ===========================================================================
|
|
|
|
- name: Create dashboards directory
|
|
ansible.builtin.file:
|
|
path: /var/lib/grafana/dashboards
|
|
state: directory
|
|
owner: grafana
|
|
group: grafana
|
|
mode: '750'
|
|
|
|
- name: Template Grafana main configuration
|
|
ansible.builtin.template:
|
|
src: "grafana.ini.j2"
|
|
dest: "/etc/grafana/grafana.ini"
|
|
owner: grafana
|
|
group: grafana
|
|
mode: '640'
|
|
when: grafana_oauth_enabled | default(false)
|
|
notify: restart grafana
|
|
|
|
- name: Enable and start Grafana service
|
|
ansible.builtin.systemd:
|
|
name: grafana-server
|
|
enabled: true
|
|
state: started
|
|
daemon_reload: true
|
|
|
|
# ===========================================================================
|
|
# PgAdmin (Gunicorn - no Apache)
|
|
# ===========================================================================
|
|
|
|
- name: Create pgadmin group
|
|
ansible.builtin.group:
|
|
name: "{{pgadmin_group}}"
|
|
system: true
|
|
|
|
- name: Create pgadmin user
|
|
ansible.builtin.user:
|
|
name: "{{pgadmin_user}}"
|
|
comment: "PgAdmin Service"
|
|
group: "{{pgadmin_group}}"
|
|
system: true
|
|
create_home: false
|
|
shell: /usr/sbin/nologin
|
|
|
|
- name: Create PgAdmin directories
|
|
ansible.builtin.file:
|
|
path: "{{item}}"
|
|
state: directory
|
|
owner: "{{pgadmin_user}}"
|
|
group: "{{pgadmin_group}}"
|
|
mode: '750'
|
|
loop:
|
|
- "{{pgadmin_data_dir}}"
|
|
- "{{pgadmin_data_dir}}/sessions"
|
|
- "{{pgadmin_data_dir}}/storage"
|
|
- "{{pgadmin_data_dir}}/certs"
|
|
- "{{pgadmin_log_dir}}"
|
|
|
|
- name: Install gunicorn into PgAdmin venv
|
|
ansible.builtin.command:
|
|
cmd: /usr/pgadmin4/venv/bin/pip install gunicorn
|
|
register: pip_gunicorn
|
|
changed_when: "'Successfully installed' in pip_gunicorn.stdout"
|
|
|
|
- name: Initialize PgAdmin database
|
|
ansible.builtin.command:
|
|
cmd: /usr/pgadmin4/venv/bin/python3 /usr/pgadmin4/web/setup.py setup-db
|
|
creates: "{{pgadmin_data_dir}}/pgadmin4.db"
|
|
become_user: "{{pgadmin_user}}"
|
|
|
|
- name: Template PgAdmin local config
|
|
ansible.builtin.template:
|
|
src: config_local.py.j2
|
|
dest: /usr/pgadmin4/web/config_local.py
|
|
owner: "{{pgadmin_user}}"
|
|
group: "{{pgadmin_group}}"
|
|
mode: '640'
|
|
notify: restart pgadmin
|
|
|
|
- name: Fetch Titania PostgreSQL SSL cert
|
|
ansible.builtin.fetch:
|
|
src: /etc/postgresql/17/main/ssl/server.crt
|
|
dest: /tmp/titania-postgres-ca.crt
|
|
flat: yes
|
|
delegate_to: titania.incus
|
|
when: "'titania.incus' in groups['ubuntu']"
|
|
|
|
- name: Copy Titania PostgreSQL SSL cert to PgAdmin
|
|
ansible.builtin.copy:
|
|
src: /tmp/titania-postgres-ca.crt
|
|
dest: "{{pgadmin_data_dir}}/certs/titania-postgres-ca.crt"
|
|
owner: "{{pgadmin_user}}"
|
|
group: "{{pgadmin_group}}"
|
|
mode: '0644'
|
|
when: "'titania.incus' in groups['ubuntu']"
|
|
|
|
- name: Template PgAdmin systemd service
|
|
ansible.builtin.template:
|
|
src: pgadmin.service.j2
|
|
dest: /etc/systemd/system/pgadmin.service
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
notify: restart pgadmin
|
|
|
|
- name: Enable and start PgAdmin service
|
|
ansible.builtin.systemd:
|
|
name: pgadmin
|
|
enabled: true
|
|
state: started
|
|
daemon_reload: true
|
|
|
|
# ===========================================================================
|
|
# OAuth2-Proxy Sidecar (Prometheus UI)
|
|
# ===========================================================================
|
|
|
|
- name: Create oauth2-proxy config directory
|
|
ansible.builtin.file:
|
|
path: "{{prometheus_oauth2_proxy_dir}}"
|
|
owner: root
|
|
group: root
|
|
state: directory
|
|
mode: '0755'
|
|
|
|
- name: Download oauth2-proxy binary
|
|
ansible.builtin.get_url:
|
|
url: "https://github.com/oauth2-proxy/oauth2-proxy/releases/download/v{{prometheus_oauth2_proxy_version}}/oauth2-proxy-v{{prometheus_oauth2_proxy_version}}.linux-amd64.tar.gz"
|
|
dest: "/tmp/oauth2-proxy-v{{prometheus_oauth2_proxy_version}}.tar.gz"
|
|
mode: '0644'
|
|
|
|
- name: Extract oauth2-proxy binary
|
|
ansible.builtin.unarchive:
|
|
src: "/tmp/oauth2-proxy-v{{prometheus_oauth2_proxy_version}}.tar.gz"
|
|
dest: /tmp
|
|
remote_src: true
|
|
creates: "/tmp/oauth2-proxy-v{{prometheus_oauth2_proxy_version}}.linux-amd64/oauth2-proxy"
|
|
|
|
- name: Install oauth2-proxy binary
|
|
ansible.builtin.copy:
|
|
src: "/tmp/oauth2-proxy-v{{prometheus_oauth2_proxy_version}}.linux-amd64/oauth2-proxy"
|
|
dest: /usr/local/bin/oauth2-proxy
|
|
owner: root
|
|
group: root
|
|
mode: '0755'
|
|
remote_src: true
|
|
|
|
- name: Template oauth2-proxy configuration for Prometheus
|
|
ansible.builtin.template:
|
|
src: oauth2-proxy-prometheus.cfg.j2
|
|
dest: "{{prometheus_oauth2_proxy_dir}}/oauth2-proxy.cfg"
|
|
owner: root
|
|
group: root
|
|
mode: '0600'
|
|
notify: restart oauth2-proxy-prometheus
|
|
|
|
- name: Template oauth2-proxy systemd service for Prometheus
|
|
ansible.builtin.template:
|
|
src: oauth2-proxy-prometheus.service.j2
|
|
dest: /etc/systemd/system/oauth2-proxy-prometheus.service
|
|
owner: root
|
|
group: root
|
|
mode: '0644'
|
|
notify:
|
|
- reload systemd
|
|
- restart oauth2-proxy-prometheus
|
|
|
|
- name: Enable and start OAuth2-Proxy for Prometheus
|
|
ansible.builtin.systemd:
|
|
name: oauth2-proxy-prometheus
|
|
enabled: true
|
|
state: started
|
|
daemon_reload: true
|
|
|
|
# ===========================================================================
|
|
# SSL Certificate Distribution (from Titania)
|
|
# ===========================================================================
|
|
|
|
- name: Create haproxy group
|
|
ansible.builtin.group:
|
|
name: "{{pplg_haproxy_group}}"
|
|
gid: "{{pplg_haproxy_gid}}"
|
|
system: true
|
|
|
|
- name: Create haproxy user
|
|
ansible.builtin.user:
|
|
name: "{{pplg_haproxy_user}}"
|
|
comment: "PPLG HAProxy"
|
|
group: "{{pplg_haproxy_group}}"
|
|
uid: "{{pplg_haproxy_uid}}"
|
|
system: true
|
|
|
|
- name: Create HAProxy directories
|
|
ansible.builtin.file:
|
|
path: "{{item}}"
|
|
state: directory
|
|
owner: "{{pplg_haproxy_user}}"
|
|
group: "{{pplg_haproxy_group}}"
|
|
mode: '750'
|
|
loop:
|
|
- /etc/haproxy
|
|
- /etc/haproxy/certs
|
|
|
|
- name: Fetch wildcard certificate from Titania
|
|
ansible.builtin.fetch:
|
|
src: /etc/haproxy/certs/ouranos.pem
|
|
dest: /tmp/ouranos-haproxy.pem
|
|
flat: yes
|
|
delegate_to: titania.incus
|
|
when: "'titania.incus' in groups['ubuntu']"
|
|
|
|
- name: Deploy wildcard certificate
|
|
ansible.builtin.copy:
|
|
src: /tmp/ouranos-haproxy.pem
|
|
dest: "{{pplg_haproxy_cert_path}}"
|
|
owner: "{{pplg_haproxy_user}}"
|
|
group: "{{pplg_haproxy_group}}"
|
|
mode: '0640'
|
|
when: "'titania.incus' in groups['ubuntu']"
|
|
|
|
- name: Generate self-signed wildcard certificate (fallback)
|
|
command: >
|
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048
|
|
-keyout {{pplg_haproxy_cert_path}}
|
|
-out {{pplg_haproxy_cert_path}}
|
|
-subj "/C=US/ST=State/L=City/O=Ouranos/CN=*.{{pplg_haproxy_domain}}"
|
|
-addext "subjectAltName=DNS:*.{{pplg_haproxy_domain}},DNS:{{pplg_haproxy_domain}}"
|
|
when: "'titania.incus' not in groups['ubuntu']"
|
|
args:
|
|
creates: "{{pplg_haproxy_cert_path}}"
|
|
|
|
# ===========================================================================
|
|
# HAProxy (TLS Termination)
|
|
# ===========================================================================
|
|
|
|
- name: Template HAProxy configuration
|
|
ansible.builtin.template:
|
|
src: pplg-haproxy.cfg.j2
|
|
dest: /etc/haproxy/haproxy.cfg
|
|
owner: "{{pplg_haproxy_user}}"
|
|
group: "{{pplg_haproxy_group}}"
|
|
mode: "640"
|
|
validate: haproxy -c -f %s
|
|
notify: restart haproxy
|
|
|
|
- name: Enable and start HAProxy service
|
|
ansible.builtin.systemd:
|
|
name: haproxy
|
|
enabled: true
|
|
state: started
|
|
|
|
# ===========================================================================
|
|
# Handlers
|
|
# ===========================================================================
|
|
handlers:
|
|
- name: restart prometheus
|
|
ansible.builtin.systemd:
|
|
name: prometheus
|
|
state: restarted
|
|
daemon_reload: true
|
|
|
|
- name: restart alertmanager
|
|
ansible.builtin.systemd:
|
|
name: prometheus-alertmanager
|
|
state: restarted
|
|
|
|
- name: restart loki
|
|
ansible.builtin.systemd:
|
|
name: loki
|
|
state: restarted
|
|
|
|
- name: restart grafana
|
|
ansible.builtin.systemd:
|
|
name: grafana-server
|
|
state: restarted
|
|
|
|
- name: restart pgadmin
|
|
ansible.builtin.systemd:
|
|
name: pgadmin
|
|
state: restarted
|
|
daemon_reload: true
|
|
|
|
- name: reload systemd
|
|
ansible.builtin.systemd:
|
|
daemon_reload: true
|
|
|
|
- name: restart haproxy
|
|
ansible.builtin.systemd:
|
|
name: haproxy
|
|
state: reloaded
|
|
|
|
- name: restart oauth2-proxy-prometheus
|
|
ansible.builtin.systemd:
|
|
name: oauth2-proxy-prometheus
|
|
state: restarted
|