Prometheus Metrics
Expose opt-in Prometheus metrics from self-hosted Password Pusher on a private exporter port.
Password Pusher can run an optional Prometheus exporter as a separate process inside the container. It collects metrics from the web (Puma) workers and the background (Solid Queue) worker and serves them at /metrics on port 9394.
Metrics are off by default. Nothing is exported until you set PWP__PROMETHEUS__ENABLED=true.
Keep the exporter private. The /metrics endpoint has no authentication. Never publish port 9394 to the internet. Expose it only on a private network, the host loopback interface, or a cluster-internal Service.
How it works
Puma web workers ─┐
├──► metrics process (:9394/metrics) ◄── Prometheus scrape
Solid Queue worker┘
- When enabled, the Docker image starts an extra
metricsprocess alongsidewebandworker. - Application processes send metrics to the exporter asynchronously.
- Delivery is fail-open. If the exporter is down, requests, logins, and push retrieval keep working; the metric is simply dropped.
Configuration
| Environment Variable | Description | Default |
|---|---|---|
| PWP__PROMETHEUS__ENABLED | Enables instrumentation and starts the exporter process in the Docker images. | false |
| PWP__PROMETHEUS__BIND | Address the exporter listens on. Use 0.0.0.0 so Prometheus can reach it from outside the container. |
127.0.0.1 |
| PWP__PROMETHEUS__PORT | Port the exporter listens on. | 9394 |
| PWP__PROMETHEUS__CLIENT_HOST | Exporter address the application processes send metrics to. | 127.0.0.1 |
| PWP__PROMETHEUS__CLIENT_PORT | Exporter port the application processes send metrics to. | 9394 |
The CLIENT_* settings only need to change if you run the exporter somewhere else (see Using an external exporter).
These can also be set in settings.yml under the prometheus: key. See Configuration strategies.
Docker Compose
Enable metrics and map the exporter port to the host loopback only:
services:
pwpush:
image: pglombardo/pwpush:latest
environment:
PWP__PROMETHEUS__ENABLED: "true"
PWP__PROMETHEUS__BIND: "0.0.0.0"
ports:
- "443:443"
- "127.0.0.1:9394:9394" # Prometheus exporter; keep private
Verify from the host:
curl http://127.0.0.1:9394/metrics
If Prometheus runs in the same Compose project, skip the port mapping and scrape pwpush:9394 over the Docker network instead.
Separate worker container
If you run the pglombardo/pwpush-worker image, it starts its own exporter when PWP__PROMETHEUS__ENABLED=true. Scrape each worker container as its own target, using the same settings as above.
Kubernetes (Helm)
The bundled Helm chart (version 0.5.2 and later) has a metrics block:
metrics:
enabled: true # default: false
port: 9394
scrapeAnnotations: true
With metrics.enabled=true the chart:
- Sets the
PWP__PROMETHEUS__*environment variables for you. - Adds a
metricscontainer port. - Creates a dedicated ClusterIP Service named
<release>-metrics. The metrics port is never added to the public application Service. - Adds standard pod annotations (
prometheus.io/scrape,prometheus.io/path,prometheus.io/port).
Set metrics.scrapeAnnotations=false if a separately managed PodMonitor or ServiceMonitor (Prometheus Operator) handles discovery.
helm upgrade --install pwpush ./containers/helm --set metrics.enabled=true
Chart 0.5.2 also moves the liveness and readiness probes to /up. If you override livenessProbe or readinessProbe in your values, update them to match.
See Deploy OSS on Kubernetes for the full Helm setup.
Prometheus scrape config
A minimal static scrape job:
scrape_configs:
- job_name: pwpush
static_configs:
- targets: ["pwpush:9394"]
On Kubernetes, use your existing annotation-based discovery, or point a ServiceMonitor at the <release>-metrics Service on the metrics port.
Exported metrics
Standard Rails metrics
The exporter includes the standard prometheus_exporter Rails metrics, including:
http_requests_totalandhttp_request_duration_secondsactive_record_connection_pool_*puma_*- Ruby process, memory, allocation, and garbage-collection metrics
Password Pusher metrics
| Metric | Labels | Description |
|---|---|---|
pwpush_pushes_created_total |
kind, authenticated |
Pushes successfully created. |
pwpush_retrievals_total |
kind, event |
Push retrieval events. |
pwpush_authentication_events_total |
event, mfa |
Login, logout, signup, and MFA events. |
pwpush_uploaded_files_total |
— | Files attached to pushes. |
pwpush_uploaded_file_bytes_total |
— | Total bytes attached to file pushes. |
Label values:
| Label | Values |
|---|---|
kind |
text, file, url, qr |
authenticated |
true, false (whether a signed-in user created the push) |
event (retrievals) |
view, failed_view, failed_passphrase, expire, admin_view, owner_view |
event (authentication) |
login_success, login_failure, logout, signup, mfa_failure, mfa_rate_limited |
mfa |
true, false (whether the user has two-factor authentication enabled) |
Privacy
Labels are intentionally bounded. Metrics never include email addresses, user IDs, IP addresses, push tokens, filenames, expiry values, or payload data.
Example queries
# Pushes created per hour, by type
sum by (kind) (increase(pwpush_pushes_created_total[1h]))
# Failed passphrase attempts in the last 15 minutes
sum(increase(pwpush_retrievals_total{event="failed_passphrase"}[15m]))
# Failed logins per minute (brute-force signal)
sum(rate(pwpush_authentication_events_total{event="login_failure"}[5m])) * 60
# File upload volume per day
increase(pwpush_uploaded_file_bytes_total[1d])
Using an external exporter
To send metrics to an exporter you run yourself, point the application at it:
environment:
PWP__PROMETHEUS__ENABLED: "true"
PWP__PROMETHEUS__CLIENT_HOST: "prometheus-exporter.internal"
PWP__PROMETHEUS__CLIENT_PORT: "9394"
The external exporter must load Password Pusher’s type collector (config/prometheus_collectors.rb) for the pwpush_* metrics to appear. The Docker image still starts its own local exporter when metrics are enabled; leave its port unpublished.
Troubleshooting
| Symptom | Check |
|---|---|
curl to :9394 is refused from outside the container |
Set PWP__PROMETHEUS__BIND=0.0.0.0. The default 127.0.0.1 only accepts connections from inside the container. |
/metrics responds but has no pwpush_* series |
Counters appear after the first matching event (for example, the first push created). |
No metrics process in the container logs |
Confirm PWP__PROMETHEUS__ENABLED is exactly true and restart the container. |
| Worker metrics missing | With the separate pwpush-worker image, scrape that container’s own :9394 endpoint. |
Related
| Topic | Doc |
|---|---|
All PWP__ settings |
Configuration |
| Container ports | Container Ports |
| Kubernetes & Helm | Deploy OSS on Kubernetes |
| Background worker image | Background Jobs |
| Source summary | PROMETHEUS.md |