|
| 1 | +# Monitor the Rundeck Server with Prometheus and Grafana |
| 2 | + |
| 3 | +Rundeck 6.0 exposes application metrics natively in Prometheus format at the [`/monitoring/prometheus`](/administration/monitoring/index.md) endpoint, which is enabled by default. This means you no longer need a third-party exporter to build a metrics dashboard — Prometheus can scrape Rundeck directly. |
| 4 | + |
| 5 | +This guide walks through a working Prometheus + Grafana stack pointed at a Rundeck server, with example queries for the most useful health and performance metrics. |
| 6 | + |
| 7 | +:::tip Looking for the older exporter guide? |
| 8 | +The community `rundeck_exporter` approach is now deprecated for Rundeck 6.0+. See [Monitor a Rundeck Instance Using Prometheus and Grafana (legacy exporter)](/learning/howto/rundeck-exporter.md) only if you are running an older version. |
| 9 | +::: |
| 10 | + |
| 11 | +For the underlying endpoint reference (formats, available metrics, configuration, and authentication), see [Monitoring overview](/administration/monitoring/index.md), [Monitoring configuration](/administration/monitoring/configuration.md), and [Using monitoring data](/administration/monitoring/monitoring.md). To monitor Runners as well, see the [Runner Metrics Reference](/administration/runner/runner-management/runner-metrics.md). |
| 12 | + |
| 13 | +## Architecture |
| 14 | + |
| 15 | +```text |
| 16 | + Rundeck server Prometheus Grafana |
| 17 | + :4440/monitoring/prometheus → :9090 (scrapes) → :3000 (dashboards) |
| 18 | +``` |
| 19 | + |
| 20 | +Prometheus scrapes the Rundeck endpoint on an interval and stores the time series; Grafana queries Prometheus to render dashboards. |
| 21 | + |
| 22 | +## Prerequisites |
| 23 | + |
| 24 | +- Rundeck 6.0 or later, reachable on its HTTP port (default `4440`). |
| 25 | +- Docker and Docker Compose (this guide runs Prometheus and Grafana as containers; you can also install them directly). |
| 26 | +- The modern monitoring endpoints enabled (the default). If they return HTTP 404, confirm `rundeck.metrics.enabled=true` and `rundeck.metrics.monitoring.enabled=true` — see [Monitoring configuration](/administration/monitoring/configuration.md). |
| 27 | + |
| 28 | +## Step 1: Confirm Rundeck is exposing metrics |
| 29 | + |
| 30 | +Before wiring up Prometheus, verify the endpoint returns Prometheus-format text: |
| 31 | + |
| 32 | +```bash |
| 33 | +curl http://localhost:4440/monitoring/prometheus |
| 34 | +``` |
| 35 | + |
| 36 | +You should see output beginning with metric definitions such as `# HELP jvm_memory_used_bytes ...`. If you get a 404, the endpoints are disabled — see the configuration reference linked above. |
| 37 | + |
| 38 | +:::warning Secure the endpoint |
| 39 | +The `/monitoring/*` endpoints are unauthenticated by default so that scrapers and health checks can reach them. On production deployments, restrict access to these paths (for example at your reverse proxy or network layer) so they are only reachable by your monitoring system. See [Monitoring configuration](/administration/monitoring/configuration.md#security-considerations). |
| 40 | +::: |
| 41 | + |
| 42 | +## Step 2: Configure the Prometheus scrape target |
| 43 | + |
| 44 | +Create `prometheus/prometheus.yml`: |
| 45 | + |
| 46 | +```yaml |
| 47 | +global: |
| 48 | + scrape_interval: 15s |
| 49 | + |
| 50 | +scrape_configs: |
| 51 | + - job_name: 'rundeck' |
| 52 | + metrics_path: /monitoring/prometheus |
| 53 | + static_configs: |
| 54 | + - targets: ['rundeck:4440'] |
| 55 | + labels: |
| 56 | + service: rundeck |
| 57 | +``` |
| 58 | +
|
| 59 | +Replace `rundeck:4440` with the address Prometheus should use to reach your server. When Prometheus and Rundeck run in the same Docker network, the service name (`rundeck`) resolves automatically; otherwise use the host and port (for example `rundeck.example.com:4440`). |
| 60 | + |
| 61 | +## Step 3: Provision the Grafana data source |
| 62 | + |
| 63 | +Create `grafana/provisioning/datasources/prometheus.yaml` so Grafana connects to Prometheus automatically on startup: |
| 64 | + |
| 65 | +```yaml |
| 66 | +apiVersion: 1 |
| 67 | +
|
| 68 | +datasources: |
| 69 | + - name: Prometheus |
| 70 | + uid: prometheus |
| 71 | + type: prometheus |
| 72 | + access: proxy |
| 73 | + url: http://prometheus:9090 |
| 74 | + isDefault: true |
| 75 | + editable: true |
| 76 | +``` |
| 77 | + |
| 78 | +## Step 4: Provision a dashboards folder (optional) |
| 79 | + |
| 80 | +To load dashboard JSON files from disk automatically, create `grafana/provisioning/dashboards/dashboard.yaml`: |
| 81 | + |
| 82 | +```yaml |
| 83 | +apiVersion: 1 |
| 84 | +
|
| 85 | +providers: |
| 86 | + - name: 'rundeck dashboards' |
| 87 | + orgId: 1 |
| 88 | + folder: 'Rundeck' |
| 89 | + type: file |
| 90 | + disableDeletion: false |
| 91 | + updateIntervalSeconds: 10 |
| 92 | + options: |
| 93 | + path: /var/lib/grafana/dashboards |
| 94 | +``` |
| 95 | + |
| 96 | +Place any exported dashboard JSON files in `grafana/dashboards/`. You can also skip provisioning and build panels directly in the Grafana UI (Step 6), then export them later. |
| 97 | + |
| 98 | +## Step 5: Run the stack |
| 99 | + |
| 100 | +Create `docker-compose.yml`: |
| 101 | + |
| 102 | +```yaml |
| 103 | +services: |
| 104 | + prometheus: |
| 105 | + image: prom/prometheus:latest |
| 106 | + container_name: rundeck-prometheus |
| 107 | + ports: |
| 108 | + - "9090:9090" |
| 109 | + volumes: |
| 110 | + - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml |
| 111 | + command: |
| 112 | + - "--config.file=/etc/prometheus/prometheus.yml" |
| 113 | + restart: unless-stopped |
| 114 | +
|
| 115 | + grafana: |
| 116 | + image: grafana/grafana:latest |
| 117 | + container_name: rundeck-grafana |
| 118 | + ports: |
| 119 | + - "3000:3000" |
| 120 | + environment: |
| 121 | + GF_SECURITY_ADMIN_USER: admin |
| 122 | + GF_SECURITY_ADMIN_PASSWORD: admin |
| 123 | + volumes: |
| 124 | + - ./grafana/provisioning/:/etc/grafana/provisioning/ |
| 125 | + - ./grafana/dashboards/:/var/lib/grafana/dashboards/ |
| 126 | + - grafana-data:/var/lib/grafana |
| 127 | + depends_on: |
| 128 | + - prometheus |
| 129 | + restart: unless-stopped |
| 130 | +
|
| 131 | +volumes: |
| 132 | + grafana-data: |
| 133 | +``` |
| 134 | + |
| 135 | +Start it: |
| 136 | + |
| 137 | +```bash |
| 138 | +docker compose up -d |
| 139 | +``` |
| 140 | + |
| 141 | +Then open: |
| 142 | + |
| 143 | +- Prometheus at `http://localhost:9090` — under **Status → Targets**, the `rundeck` target should be **UP**. |
| 144 | +- Grafana at `http://localhost:3000` (default login `admin` / `admin`). |
| 145 | + |
| 146 | +:::tip Networking |
| 147 | +If your Rundeck server runs outside this Compose project, make sure the Prometheus container can reach it (shared Docker network, or a routable host/IP in the scrape target). For a quick local test against a Rundeck on the Docker host, you can target `host.docker.internal:4440`. |
| 148 | +::: |
| 149 | + |
| 150 | +## Step 6: Build dashboard panels |
| 151 | + |
| 152 | +In Grafana, create a dashboard and add panels using the Prometheus data source. The following queries cover the most useful server health signals. Metric names are the native Micrometer names exposed at `/monitoring/prometheus`; use **Status → Targets** in Prometheus or the [`/monitoring/metrics`](/administration/monitoring/monitoring.md) endpoint to discover the full set. |
| 153 | + |
| 154 | +**JVM heap usage:** |
| 155 | + |
| 156 | +```promql |
| 157 | +sum(jvm_memory_used_bytes{area="heap"}) |
| 158 | +sum(jvm_memory_max_bytes{area="heap"}) |
| 159 | +``` |
| 160 | + |
| 161 | +**Live threads:** |
| 162 | + |
| 163 | +```promql |
| 164 | +jvm_threads_live_threads |
| 165 | +``` |
| 166 | + |
| 167 | +**Garbage collection pause (mean over 5m):** |
| 168 | + |
| 169 | +```promql |
| 170 | +rate(jvm_gc_pause_seconds_sum[5m]) / rate(jvm_gc_pause_seconds_count[5m]) |
| 171 | +``` |
| 172 | + |
| 173 | +**Process and system CPU:** |
| 174 | + |
| 175 | +```promql |
| 176 | +process_cpu_usage |
| 177 | +system_cpu_usage |
| 178 | +``` |
| 179 | + |
| 180 | +**HTTP request rate by status:** |
| 181 | + |
| 182 | +```promql |
| 183 | +sum(rate(http_server_requests_seconds_count[5m])) by (status) |
| 184 | +``` |
| 185 | + |
| 186 | +**HTTP error rate (4xx/5xx):** |
| 187 | + |
| 188 | +```promql |
| 189 | +sum(rate(http_server_requests_seconds_count{status=~"[45].."}[5m])) |
| 190 | +``` |
| 191 | + |
| 192 | +### Runner report-delivery metrics |
| 193 | + |
| 194 | +If you use [Runners](/administration/runner/index.md), the server also publishes report-delivery pipeline metrics (for example `runner_server_report_end_to_end_latency_max_seconds` and `runner_server_report_timeout_count`) on the same `/monitoring/prometheus` endpoint. These are bridged from Rundeck's internal metric registry, so their series names follow a specific naming pattern. See the [Runner Metrics Reference](/administration/runner/runner-management/runner-metrics.md#server-side-metric-names-in-prometheus) for the exact names, units, and suggested alerts. |
| 195 | + |
| 196 | +## Next steps |
| 197 | + |
| 198 | +- Import or build richer dashboards; many community Grafana dashboards exist for JVM/Micrometer applications and can be adapted. |
| 199 | +- Add [alerting rules](https://prometheus.io/docs/alerting/latest/overview/) in Prometheus or Grafana for the signals above. |
| 200 | +- Use [`/monitoring/health`](/administration/monitoring/monitoring.md#load-balancer-health-checks) for load-balancer health checks. |
| 201 | +- Monitor your Runners — see the [Runner Metrics Reference](/administration/runner/runner-management/runner-metrics.md) and [Status & Monitoring](/administration/runner/runner-management/monitoring-runners.md). |
0 commit comments