name: pds-monitoring # Self-contained monitoring stack for a self-hosted PDS. # Deployed by Ansible to {{ pds_data_dir }}/monitoring/compose.yaml # # All services bind to 127.0.0.1 — nothing is exposed to the internet. # Reach Grafana via SSH tunnel: # ssh -L 3001:localhost:3001 you@your-pds-host # Then open http://localhost:3001 (admin/admin, change on first login) services: node-exporter: container_name: pds-node-exporter image: prom/node-exporter:v1 network_mode: host pid: host restart: unless-stopped command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.rootfs=/rootfs' - '--collector.filesystem.mount-points-exclude=^/(dev|proc|sys|run|var/lib/docker/.+)($$|/)' - '--web.listen-address=127.0.0.1:9100' volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro prometheus: container_name: pds-prometheus image: prom/prometheus:v3 network_mode: host restart: unless-stopped command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--storage.tsdb.retention.time=15d' - '--web.listen-address=127.0.0.1:9090' # Lets the PDS push OTLP metrics directly — no collector needed - '--web.enable-otlp-receiver' volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro - prometheus-data:/prometheus grafana: container_name: pds-grafana # Grafana publishes no floating major tag — pinned to exact version image: grafana/grafana:{{ pds_grafana_image_tag }} network_mode: host depends_on: - prometheus restart: unless-stopped environment: GF_SERVER_HTTP_ADDR: 127.0.0.1 GF_SERVER_HTTP_PORT: 3001 GF_ANALYTICS_REPORTING_ENABLED: false GF_ANALYTICS_CHECK_FOR_UPDATES: false GF_USERS_ALLOW_SIGN_UP: false volumes: - ./grafana/provisioning:/etc/grafana/provisioning:ro - ./dashboards:/var/lib/grafana/dashboards:ro - grafana-data:/var/lib/grafana volumes: prometheus-data: grafana-data: