Prometheus Metrics

Expose opt-in Prometheus metrics from self-hosted Password Pusher on a private exporter port.

This article applies to: OSS Self-Hosted

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 metrics process alongside web and worker.
  • 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 metrics container 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_total and http_request_duration_seconds
  • active_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