feat: add monitoring stack (Prometheus + Grafana + cAdvisor + Node Exporter)
All checks were successful
CI/CD / syntax-check (push) Successful in 3m0s
CI/CD / deploy (push) Successful in 6m51s

- Adds monitoring Docker network (internal)
- Prometheus scrapes node-exporter (host metrics) and cAdvisor (containers)
  with 30-day retention
- Grafana exposed at dashboard.csrx.ru with pre-provisioned datasource
  and two dashboards: Node Exporter Full (1860) and cAdvisor (14282)
- Vault secret: vault_grafana_admin_password

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jack 2026-03-22 03:05:34 +07:00
parent 9e4ac718d9
commit 972a76db4c
14 changed files with 16815 additions and 41 deletions

View file

@ -7,7 +7,8 @@ domain_vault: "vault.{{ domain_base }}"
domain_git: "git.{{ domain_base }}"
domain_plane: "plane.{{ domain_base }}"
domain_sync: "sync.{{ domain_base }}"
domain_traefik: "traefik.{{ domain_base }}"
domain_traefik: "traefik.{{ domain_base }}"
domain_dashboard: "dashboard.{{ domain_base }}"
# Service paths
services_root: /opt/services
@ -24,6 +25,7 @@ plane_minio_password: "{{ vault_plane_minio_password }}"
traefik_dashboard_htpasswd: "{{ vault_traefik_dashboard_htpasswd }}"
syncthing_basic_auth_htpasswd: "{{ vault_syncthing_basic_auth_htpasswd }}"
forgejo_runner_token: "{{ vault_forgejo_runner_token }}"
grafana_admin_password: "{{ vault_grafana_admin_password }}"
# CI/CD deploy key (public key — not a secret)
ci_deploy_pubkey: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHdr9mRSSUqt7Ym4wA5RpVyz76wEXSOtVfh2/yCSMIbg ci-deploy@forgejo-runner"

View file

@ -1,41 +1,44 @@
$ANSIBLE_VAULT;1.1;AES256
62336263356163373830666161666261396466333963303862653862306132656335376639326134
3362333062313364396539353366306638396565613333650a346432363163343033663132373638
61383563373832333936386133623939663464623631626162393039666333653037396230633662
3464633732613937300a313165313333663065626166333465613130313333343638343366306537
39393530373838656130303432376365306131396364396236623037316632643563663163633830
61383064343732326561656630326266393465333032616565356539383033333964663533643736
62636663353234396162663637633838373565396262363361663533346639653434636562313866
30393066363037313935353666313234326563326464323365366164623966653338636362386236
61323933663064336331633766363763346566376637313632623031313736646464313630363236
39663639383762376137646635656533313665666564636463376433633539623531633631666463
36303438633065353565313239383962626334323130663333653239373461613365353130343462
66383661663663636165613837633239653437343361663334646232643130653234363866613531
33643062623039616161623964363033313030373536633539323030623336353236653962373131
31383466363930653739356533336134666361653465313666363431616264346162623738346438
39303337396230353362663866386532396230656138323262303466393261653066303635666366
32386530623361373832626563366236313566333530336234613832313532396363633463333466
32613663653261316335393362623965656566336335663362646331316261366431626462356336
34396139623062633933336665376130376661643865633064666631346633383564383632383530
63646135623165623361306437306234353235313435313665623833316263343432653463326366
35623535613430383637323862396166386463353665383637383634346363353538393330353061
39616264663934633866343830303835653664373233653961643962346233663830303431316162
61373166623261616364303739306135303166346133643236616234656165306666373838653334
63346164353331333864643533656138323732616138376365643035303231303837396661646432
63346239643932393763626661366335623332353463396266616232333039626636343635623562
33643330376264393763353862663436613636393430386633333530613465343062343965663466
64653865306135376365383137363666353962663533393264663465383130343966383537353133
30663864326231663533313331613634363066663331333931643366656432313661376363316361
37323631613531343935326239333032316563376636353731343938613939333833373337313338
32356237313437643336303137343764386536356633323262386636643333386161336135356235
65366466383136343163353836663339313466313030383361316532653766613831303661346130
38633931363531383238343565366438303361333363353162646335363861613137376235643132
63663364363737396464373832363665636634393637373863396336393461333737656465336234
63373731623835383334663637313034393538633734386530373565373961386238653363323331
61313134386366623338353064343164313238646534303566386264376439663437303131303666
63646334613439343932663561333035313864346566326234326630363863306132353637666532
31336639343336363835306565383036333865373966333332393031646466636535666663373737
66343166333136363661383235653364646165653764613538376133366135616261363030316538
62323732336438336332643464383462336538633037333432393334336664376162653736613836
34376363646232373239376133633333393733623938386566616532336262636135353461333332
32653135613263636536
31613031396131376665643639663630323363366332396162356132316233323063356465643762
3637303062366530313132303165333161323737643030650a653032646534303463616562633234
65373032373464303839346430626665316437656363666164636532613837613637323064326630
3736343663396461350a396434613034393131623037333436306532373038623534363334313066
38333535376230653538633261366633366238636530656464343939623834646139396637343461
62396564616566373231343138653061366663366461343239636463633261643464633361373834
30386237383561613232626361323536636363373831356635653535656633323332666264383061
63633331343162396431653237333664663439383738333932373866643030303735643534386330
32366438623966303131613666613265313235323530626132316661383462313033653038363933
34646463666632396231313563363064396539663236356565306564653433353735333335656534
65396235656365376236613832626366666666653834626633373937386366656232633766636634
63346535643936646333663735333630623538393234383336613461343863623935393865343532
37306161646434656439323832383238643963316463643033306262613231646334303361653833
63646363653235326261333538666236353231376437653636316131623135323138636661386665
66316663393934663031623135633137366131633030626664306564396635663235383636343431
65343330373036316161626165343738323730646130663839616363326232653039303932363765
61633432386361353861393263306236343162313066653962363761373161656365353538656335
36643163383435326230326135616164333134363666616339653330656531326539653764633632
33396431346530633933626533313939316337363035333763613237356133396162316163646632
39633165653565333237376137303737383831373838656461346434663331313965323235626330
37303665313564346233666632656531323932316533613463633636633435646137653064653137
63356439336664383133376530393036653061613466383961613939633866306337653865366330
66366132383237336534363563643135313138376437336563643130383534373263373364653462
61396664373363373737633339333335653164323662623239313666666431353631306438303533
65636135343039323734393637396163366138636439656633616130643636363831643532623337
35303934656230623563366664396632356638636630613433626334303235343961616439636165
37313264643432363532373464633633343033303133346435663062323838383931393061396531
34373034313038663033383333333430326136346433646536626565663436323764316361356531
64343839373138346636336637343438616639353236336633666234643365303030656132346232
65346636626338363762653939333639313462393231616636663935333232636231326231373833
32366535353361303532633462303763386238663432333465653361373064656162343465396631
61363330666666653533653365653232313836373230336537363337666536313737353731363165
63333837356135646564663536666264346630356163663666323432393865393836326338306266
33383139383033643937383865393236396337666139633032323162303665633230346365663730
63643661323332616163326636646634616165633538383038653766303066366335393065373236
39613562363634316564346162333030393430303335323733306163396137373037346237656231
39346635333138656336346230313635353233363334633037633961306663356364383962643361
38366531396431653330393239663337626564616265636362313537373239663736636535303332
39626565306632336330386434386636656430363738383431306637666334653136633762323434
34356661633837626231346134303131353264643532613739333234346634346565376333343563
37343662376533383335356331616435393764663530616335386435653538646362613364303437
63356166353062626163313735646365643635393663316365626431383062663331366439613164
323565613761663833636330633533376131

View file

@ -20,3 +20,7 @@ plane_redis_image: "redis:7-alpine"
plane_minio_image: "minio/minio:RELEASE.2025-04-22T22-12-26Z" # https://hub.docker.com/r/minio/minio/tags
syncthing_image: "syncthing/syncthing:1.27" # https://hub.docker.com/r/syncthing/syncthing/tags
act_runner_image: "gitea/act_runner:0.3.0" # https://hub.docker.com/r/gitea/act_runner/tags
prometheus_image: "prom/prometheus:v3.4.0" # https://hub.docker.com/r/prom/prometheus/tags
node_exporter_image: "prom/node-exporter:v1.9.1" # https://hub.docker.com/r/prom/node-exporter/tags
cadvisor_image: "gcr.io/cadvisor/cadvisor:v0.52.1" # https://github.com/google/cadvisor/releases
grafana_image: "grafana/grafana:11.6.1" # https://hub.docker.com/r/grafana/grafana/tags

View file

@ -0,0 +1,817 @@
{
"__inputs": [
{
"name": "DS_PROMETHEUS",
"label": "Prometheus",
"description": "Prometheus as the datasource is obligatory",
"type": "datasource",
"pluginId": "prometheus",
"pluginName": "Prometheus"
}
],
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "7.4.5"
},
{
"type": "panel",
"id": "graph",
"name": "Graph",
"version": ""
},
{
"type": "datasource",
"id": "prometheus",
"name": "Prometheus",
"version": "1.0.0"
},
{
"type": "panel",
"id": "table",
"name": "Table",
"version": ""
}
],
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": 14282,
"graphTooltip": 0,
"id": null,
"iteration": 1617715580880,
"links": [],
"panels": [
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 0
},
"id": 8,
"panels": [],
"title": "CPU",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 7,
"w": 24,
"x": 0,
"y": 1
},
"hiddenSeries": false,
"id": 15,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(container_cpu_usage_seconds_total{instance=~\"$host\",name=~\"$container\",name=~\".+\"}[5m])) by (name) *100",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "CPU Usage",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:606",
"format": "percent",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:607",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 8
},
"id": 11,
"panels": [],
"title": "Memory",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 9
},
"hiddenSeries": false,
"id": 9,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"expr": "sum(container_memory_rss{instance=~\"$host\",name=~\"$container\",name=~\".+\"}) by (name)",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Memory Usage",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:606",
"format": "bytes",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:607",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 9
},
"hiddenSeries": false,
"id": 14,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null as zero",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": true,
"steppedLine": false,
"targets": [
{
"expr": "sum(container_memory_cache{instance=~\"$host\",name=~\"$container\",name=~\".+\"}) by (name)",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Memory Cached",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:606",
"format": "bytes",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:607",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 17
},
"id": 2,
"panels": [],
"title": "Network",
"type": "row"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 0,
"y": 18
},
"hiddenSeries": false,
"id": 4,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"hideEmpty": false,
"hideZero": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"sideWidth": null,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(container_network_receive_bytes_total{instance=~\"$host\",name=~\"$container\",name=~\".+\"}[5m])) by (name)",
"hide": false,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Received Network Traffic",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:674",
"format": "Bps",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:675",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {}
},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 8,
"w": 12,
"x": 12,
"y": 18
},
"hiddenSeries": false,
"id": 6,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": false,
"rightSide": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.4.5",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(container_network_transmit_bytes_total{instance=~\"$host\",name=~\"$container\",name=~\".+\"}[5m])) by (name)",
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Sent Network Traffic",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"$$hashKey": "object:832",
"format": "Bps",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"$$hashKey": "object:833",
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
},
{
"collapsed": false,
"datasource": "${DS_PROMETHEUS}",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 26
},
"id": 19,
"panels": [],
"title": "Misc",
"type": "row"
},
{
"datasource": "${DS_PROMETHEUS}",
"fieldConfig": {
"defaults": {
"custom": {
"align": null,
"filterable": false
},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 80
}
]
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "id"
},
"properties": [
{
"id": "custom.width",
"value": 260
}
]
},
{
"matcher": {
"id": "byName",
"options": "Running"
},
"properties": [
{
"id": "unit",
"value": "d"
},
{
"id": "decimals",
"value": 1
},
{
"id": "custom.displayMode",
"value": "color-text"
},
{
"id": "color",
"value": {
"fixedColor": "dark-green",
"mode": "fixed"
}
}
]
}
]
},
"gridPos": {
"h": 10,
"w": 24,
"x": 0,
"y": 27
},
"id": 17,
"options": {
"showHeader": true,
"sortBy": []
},
"pluginVersion": "7.4.5",
"targets": [
{
"expr": "(time() - container_start_time_seconds{instance=~\"$host\",name=~\"$container\",name=~\".+\"})/86400",
"format": "table",
"instant": true,
"interval": "",
"legendFormat": "{{name}}",
"refId": "A"
}
],
"timeFrom": null,
"timeShift": null,
"title": "Containers Info",
"transformations": [
{
"id": "filterFieldsByName",
"options": {
"include": {
"names": [
"container_label_com_docker_compose_project",
"container_label_com_docker_compose_project_working_dir",
"image",
"instance",
"name",
"Value",
"container_label_com_docker_compose_service"
]
}
}
},
{
"id": "organize",
"options": {
"excludeByName": {},
"indexByName": {},
"renameByName": {
"Value": "Running",
"container_label_com_docker_compose_project": "Label",
"container_label_com_docker_compose_project_working_dir": "Working dir",
"container_label_com_docker_compose_service": "Service",
"image": "Registry Image",
"instance": "Instance",
"name": "Name"
}
}
}
],
"type": "table"
}
],
"schemaVersion": 27,
"style": "dark",
"tags": [
"cadvisor",
"docker"
],
"templating": {
"list": [
{
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values({__name__=~\"container.*\"},instance)",
"description": null,
"error": null,
"hide": 0,
"includeAll": true,
"label": "Host",
"multi": false,
"name": "host",
"options": [],
"query": {
"query": "label_values({__name__=~\"container.*\"},instance)",
"refId": "Prometheus-host-Variable-Query"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 5,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
},
{
"allValue": ".*",
"current": {},
"datasource": "${DS_PROMETHEUS}",
"definition": "label_values({__name__=~\"container.*\", instance=~\"$host\"},name)",
"description": null,
"error": null,
"hide": 0,
"includeAll": true,
"label": "Container",
"multi": false,
"name": "container",
"options": [],
"query": {
"query": "label_values({__name__=~\"container.*\", instance=~\"$host\"},name)",
"refId": "Prometheus-container-Variable-Query"
},
"refresh": 1,
"regex": "",
"skipUrlSync": false,
"sort": 0,
"tagValuesQuery": "",
"tags": [],
"tagsQuery": "",
"type": "query",
"useTags": false
}
]
},
"time": {
"from": "now-6h",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Cadvisor exporter",
"uid": "pMEd7m0Mz",
"version": 1,
"description": "Simple exporter for cadvisor only"
}

File diff suppressed because it is too large Load diff

View file

@ -44,6 +44,51 @@
mode: "0644"
notify: Restart stack
- name: Deploy Prometheus config
ansible.builtin.template:
src: prometheus/prometheus.yml.j2
dest: "{{ services_root }}/prometheus/prometheus.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
notify: Restart stack
- name: Deploy Grafana datasource provisioning
ansible.builtin.template:
src: grafana/provisioning/datasources/prometheus.yml.j2
dest: "{{ services_root }}/grafana/provisioning/datasources/prometheus.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
notify: Restart stack
- name: Deploy Grafana dashboard provisioning config
ansible.builtin.template:
src: grafana/provisioning/dashboards/dashboards.yml.j2
dest: "{{ services_root }}/grafana/provisioning/dashboards/dashboards.yml"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
notify: Restart stack
- name: Deploy Node Exporter Full dashboard JSON
ansible.builtin.copy:
src: grafana/dashboards/node-exporter-full.json
dest: "{{ services_root }}/grafana/provisioning/dashboards/json/node-exporter-full.json"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
notify: Restart stack
- name: Deploy cAdvisor dashboard JSON
ansible.builtin.copy:
src: grafana/dashboards/cadvisor.json
dest: "{{ services_root }}/grafana/provisioning/dashboards/json/cadvisor.json"
owner: "{{ deploy_user }}"
group: "{{ deploy_group }}"
mode: "0644"
notify: Restart stack
- name: Create acme.json for Let's Encrypt certificates
ansible.builtin.file:
path: "{{ services_root }}/traefik/acme.json"

View file

@ -25,3 +25,7 @@
- syncthing/config
- syncthing/data
- act_runner
- prometheus
- grafana/provisioning/datasources
- grafana/provisioning/dashboards
- grafana/provisioning/dashboards/json

View file

@ -18,6 +18,10 @@
- "{{ plane_minio_image }}"
- "{{ syncthing_image }}"
- "{{ act_runner_image }}"
- "{{ prometheus_image }}"
- "{{ node_exporter_image }}"
- "{{ cadvisor_image }}"
- "{{ grafana_image }}"
register: pull_result
changed_when: "'Status: Downloaded newer image' in pull_result.stdout"
retries: 5

View file

@ -20,6 +20,9 @@ networks:
internal: true
runner-jobs:
driver: bridge
monitoring:
driver: bridge
internal: true
volumes:
vaultwarden_data:
@ -32,6 +35,8 @@ volumes:
syncthing_config:
syncthing_data:
act_runner_data:
prometheus_data:
grafana_data:
services:
@ -398,3 +403,72 @@ services:
networks:
- backend
- runner-jobs
# ── Monitoring Stack ───────────────────────────────────────────────────────
prometheus:
image: {{ prometheus_image }}
container_name: prometheus
restart: unless-stopped
networks:
- monitoring
volumes:
- prometheus_data:/prometheus
- {{ services_root }}/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
- "--storage.tsdb.retention.time=30d"
- "--web.console.libraries=/usr/share/prometheus/console_libraries"
- "--web.console.templates=/usr/share/prometheus/consoles"
node-exporter:
image: {{ node_exporter_image }}
container_name: node-exporter
restart: unless-stopped
networks:
- monitoring
pid: host
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)"
cadvisor:
image: {{ cadvisor_image }}
container_name: cadvisor
restart: unless-stopped
networks:
- monitoring
privileged: true
devices:
- /dev/kmsg
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker:/var/lib/docker:ro
- /dev/disk:/dev/disk:ro
grafana:
image: {{ grafana_image }}
container_name: grafana
restart: unless-stopped
depends_on:
- prometheus
networks:
- backend
- monitoring
volumes:
- grafana_data:/var/lib/grafana
- {{ services_root }}/grafana/provisioning:/etc/grafana/provisioning:ro
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
- GF_USERS_ALLOW_SIGN_UP=false
- GF_SERVER_DOMAIN={{ domain_dashboard }}
- GF_SERVER_ROOT_URL=https://{{ domain_dashboard }}
- GF_AUTH_ANONYMOUS_ENABLED=false

View file

@ -11,3 +11,4 @@ DOMAIN_PLANE={{ domain_plane }}
DOMAIN_SYNC={{ domain_sync }}
DOMAIN_TRAEFIK={{ domain_traefik }}
FORGEJO_RUNNER_TOKEN={{ forgejo_runner_token }}
GRAFANA_ADMIN_PASSWORD={{ grafana_admin_password }}

View file

@ -0,0 +1,13 @@
# Generated by Ansible — do not edit manually
apiVersion: 1
providers:
- name: default
orgId: 1
folder: ""
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: false
options:
path: /etc/grafana/provisioning/dashboards/json

View file

@ -0,0 +1,10 @@
# Generated by Ansible — do not edit manually
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false

View file

@ -0,0 +1,19 @@
# Generated by Ansible — do not edit manually
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
instance: "{{ domain_base }}"
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]
- job_name: node-exporter
static_configs:
- targets: ["node-exporter:9100"]
- job_name: cadvisor
static_configs:
- targets: ["cadvisor:8080"]

View file

@ -47,6 +47,13 @@ http:
service: syncthing
middlewares: [syncthing-auth]
grafana:
rule: "Host(`{{ domain_dashboard }}`)"
entrypoints: [websecure]
tls:
certresolver: letsencrypt
service: grafana
services:
vaultwarden:
loadBalancer:
@ -73,6 +80,11 @@ http:
servers:
- url: "http://syncthing:8384"
grafana:
loadBalancer:
servers:
- url: "http://grafana:3000"
middlewares:
traefik-auth:
basicAuth: