XRPL Validator Docker Monitoring Guide

Revision: July 2026

Need monitoring credentials? If you do not have a Basic Auth username and password, request monitoring access before you start this guide.

Introduction

This guide explains how to connect an xrpld validator host to the XRPL monitoring platform with Grafana Alloy running in Docker.

Still running rippled (pre-3.2.0)? rippled was renamed to xrpld in version 3.2.0. Point the .env variables at your legacy rippled paths instead, for example XRPLD_CONFIG_FILE=/etc/opt/ripple/rippled.cfg and XRPLD_LOG_DIR=/var/log/rippled. Everything else in this guide applies unchanged.

Opting in gives the validator operator access to validator health in Grafana. Metrics and logs make it easier to catch problems early, confirm that telemetry is flowing, and troubleshoot incidents without manually collecting log files after the fact.

The setup is designed to stay under the operator’s control. Alloy reads local telemetry and pushes it with credentials provided by the XRPL Foundation, but the Docker path does not edit xrpld.cfg and does not restart xrpld.

The mental model is simple:

xrpld -> Docker -> Alloy container -> XRPL monitoring proxy -> Grafana

Grafana Alloy runs in a container on the validator host. It reads local xrpld telemetry and pushes it to the monitoring platform:

  • StatsD metrics are collected.
  • debug.log and perf.log are collected.
  • Grafana shows the validator dashboards.

The trusted validator identity is the Basic Auth username provided by the XRPL Foundation. The local node label is only a dashboard filter. Operators may optionally supply the validator’s public master key for correlation with public XRPL network statistics.

Use the Docker path when the host already runs Docker and you want Alloy kept in a container. Use the native guide when you prefer the hosted installer, systemd, and OS packages.

What You Need

The XRPL Foundation provides:

  • Monitoring push host, for example push.monitoring.xrplf.org.
  • Basic Auth username.
  • Basic Auth password.
  • Grafana URL and account access.

The validator host needs:

  • Docker.
  • The Alloy Docker image.
  • A readable xrpld.cfg.
  • Readable debug.log and perf.log files.
  • xrpld StatsD configured to send to a host loopback UDP port that Docker publishes to Alloy. The default is 127.0.0.1:9125.
  • Optionally, the validator’s public 52-character nH master key. This is not an account address, signing key, private key, or seed.

Configure xrpld

StatsD must point to Alloy on a host localhost UDP port. Use 9125 unless that port is already used on the host:

[insight]
server=statsd
address=127.0.0.1:9125
prefix=xrpld

Keep your existing prefix if you already use one. The container reads the prefix from xrpld.cfg and builds the StatsD mapping at startup.

If host port 9125 is already used, choose another host port, for example:

[insight]
server=statsd
address=127.0.0.1:19125
prefix=xrpld

The address should stay on 127.0.0.1 because xrpld runs on the host and the Docker published port is also on the host. The host port can change, but the Docker publish rule must change with it.

Debug log must be configured. The host path can be any path:

[debug_logfile]
/var/log/xrpld/debug.log

Perf log must be configured. The host path can be any path:

[perf]
perf_log=/var/log/xrpld/perf.log
log_interval=2

Back up xrpld.cfg before changing it. Restart xrpld using your normal process after changing that file.

Run With Docker

Adjust the values and host paths, then run:

docker run -d \
  --name xrpl-monitoring-alloy \
  --restart unless-stopped \
  -p 127.0.0.1:9125:9125/udp \
  -p 127.0.0.1:12345:12345 \
  -e ALLOY_NODE=<node-label> \
  -e ALLOY_PUSH_HOST=push.monitoring.xrplf.org \
  -e ALLOY_USERNAME=<basic-auth-user> \
  -e ALLOY_PASSWORD=<basic-auth-password> \
  -e ALLOY_VALIDATOR_MASTER_KEY=<public-validator-master-key> \
  -v /etc/xrpld/xrpld.cfg:/xrpld-config/xrpld.cfg:ro \
  -v /var/log/xrpld/debug.log:/xrpld-logs/debug.log:ro \
  -v /var/log/xrpld/perf.log:/xrpld-logs/perf.log:ro \
  -v alloy-data:/var/lib/alloy/data \
  xrpl-monitoring-alloy:local

Use the actual xrpld.cfg path if it is not /etc/xrpld/xrpld.cfg. Use the actual log file paths if they are not /var/log/xrpld/debug.log and /var/log/xrpld/perf.log.

If you use a different host StatsD port, change the left side of the Docker publish rule and tell the entrypoint which host address it should expect in xrpld.cfg. For example, host port 19125 means:

-p 127.0.0.1:19125:9125/udp \
-e ALLOY_XRPLD_STATSD_ADDRESS=127.0.0.1:19125 \

The container always listens on container port 9125; only the host port needs to change. ALLOY_XRPLD_STATSD_ADDRESS is only a startup validation value. It does not publish a port and it does not change Alloy’s listener.

Why These Options Matter

Optional Validator Correlation

-e ALLOY_VALIDATOR_MASTER_KEY=<public-validator-master-key>

This opt-in value must be the public 52-character validator master key that starts with nH. The startup check validates only its structure; it does not validate the key’s checksum or ownership. Leave the variable unset or exactly empty to opt out. Never use an account address, signing key, private key, or seed.

The public master key is attached only to the Prometheus up metric. It is not attached to other metrics or any Loki log stream, and it does not replace the Basic Auth tenant as the trusted identity. Docker environment values can be viewed by users with container-inspection access, so keep all private key or seed material out of the environment.

Changing the public key or opting out requires recreating the container with the new environment. Existing labeled series remain in the backend until normal retention removes them.

StatsD Port

-p 127.0.0.1:<host-port>:9125/udp

This is the Docker port publish rule for StatsD. It has three important parts:

  • 127.0.0.1 binds the port only on host localhost, so it is not opened to the network.
  • <host-port> is the UDP port from xrpld.cfg, for example 9125 or 19125.
  • 9125/udp is the container port and protocol. Keep this as 9125/udp because the image listens on 0.0.0.0:9125 inside the container in bridge mode.

xrpld sends UDP StatsD packets to host 127.0.0.1:<host-port>, Docker forwards them into the container, and Alloy receives them on container port 9125.

The 0.0.0.0 listener is container-internal in bridge mode. It is not opened to the host network because the Docker publish rule binds the host side to 127.0.0.1.

Without this port publish, xrpld would send packets to the host localhost, but Alloy would only be listening inside the container.

Alloy UI Port

-p 127.0.0.1:12345:12345

This exposes the Alloy UI and API on host localhost only. Open http://127.0.0.1:12345 on the validator host if you need to inspect Alloy after it starts.

xrpld.cfg Mount

-v /etc/xrpld/xrpld.cfg:/xrpld-config/xrpld.cfg:ro

The entrypoint checks the telemetry settings in xrpld.cfg and reads the StatsD prefix from it. The :ro flag makes it read-only, so the container cannot modify this operator-owned file.

Log File Mounts

-v /path/to/debug.log:/xrpld-logs/debug.log:ro
-v /path/to/perf.log:/xrpld-logs/perf.log:ro

xrpld.cfg can use any host paths for debug.log and perf.log, but those same files must be mounted into the container at the fixed paths Alloy tails: /xrpld-logs/debug.log and /xrpld-logs/perf.log. The :ro flag keeps the logs read-only from the container.

Alloy Data Volume

-v alloy-data:/var/lib/alloy/data

Alloy uses its storage path for runtime state such as queues and file read positions. Keeping it in a Docker volume lets Alloy survive container restarts without starting from an empty state.

Existing StatsD Collector

If xrpld already sends StatsD to another collector, put Alloy in front of that collector:

ALLOY_STATSD_RELAY_ADDR=<collector-host>:<collector-port>

This must be the existing collector’s StatsD UDP listener, for example a statsd_exporter UDP port. It is not the Prometheus HTTP scrape port.

Keep xrpld pointed at the host StatsD port published to Alloy. Alloy forwards the original StatsD packets to ALLOY_STATSD_RELAY_ADDR unchanged, while also sending mapped metrics to the XRPL monitoring platform.

The relay address is resolved from inside the container. Do not use 127.0.0.1:8125 for a collector running on the host, because that would point back to the Alloy container itself. If there is no existing collector, leave ALLOY_STATSD_RELAY_ADDR empty.

For a host collector that is reachable from Docker, add a host gateway name and use it as the relay target:

docker run -d \
  --name xrpl-monitoring-alloy \
  --restart unless-stopped \
  --add-host=host.docker.internal:host-gateway \
  -p 127.0.0.1:9125:9125/udp \
  -p 127.0.0.1:12345:12345 \
  -e ALLOY_NODE=<node-label> \
  -e ALLOY_PUSH_HOST=push.monitoring.xrplf.org \
  -e ALLOY_USERNAME=<basic-auth-user> \
  -e ALLOY_PASSWORD=<basic-auth-password> \
  -e ALLOY_VALIDATOR_MASTER_KEY=<public-validator-master-key> \
  -e ALLOY_STATSD_RELAY_ADDR=host.docker.internal:8125 \
  -v /etc/xrpld/xrpld.cfg:/xrpld-config/xrpld.cfg:ro \
  -v /var/log/xrpld/debug.log:/xrpld-logs/debug.log:ro \
  -v /var/log/xrpld/perf.log:/xrpld-logs/perf.log:ro \
  -v alloy-data:/var/lib/alloy/data \
  xrpl-monitoring-alloy:local

That only works if the existing collector listens on an address reachable from the Docker bridge. If it only listens on host 127.0.0.1, Docker bridge containers cannot reach it through host.docker.internal.

Host Network Relay

If the existing collector only listens on host localhost, use Docker host networking instead of bridge mode. In host networking, the container shares the host network namespace:

container 127.0.0.1 == host 127.0.0.1

That means ALLOY_STATSD_RELAY_ADDR=127.0.0.1:8125 can reach a collector bound to host localhost. It also means Docker port publishing is not used.

Example:

docker run -d \
  --name xrpl-monitoring-alloy \
  --restart unless-stopped \
  --network host \
  -e ALLOY_NODE=<node-label> \
  -e ALLOY_PUSH_HOST=push.monitoring.xrplf.org \
  -e ALLOY_USERNAME=<basic-auth-user> \
  -e ALLOY_PASSWORD=<basic-auth-password> \
  -e ALLOY_VALIDATOR_MASTER_KEY=<public-validator-master-key> \
  -e ALLOY_STATSD_LISTEN=127.0.0.1:9125 \
  -e ALLOY_STATSD_RELAY_ADDR=127.0.0.1:8125 \
  -v /etc/xrpld/xrpld.cfg:/xrpld-config/xrpld.cfg:ro \
  -v /var/log/xrpld/debug.log:/xrpld-logs/debug.log:ro \
  -v /var/log/xrpld/perf.log:/xrpld-logs/perf.log:ro \
  -v alloy-data:/var/lib/alloy/data \
  xrpl-monitoring-alloy:local \
  run --server.http.listen-addr=127.0.0.1:12345 \
    --storage.path=/var/lib/alloy/data \
    /etc/alloy/config.alloy

For this mode, keep xrpld.cfg pointed at:

address=127.0.0.1:9125

There is no -p option because Docker is not translating ports. Alloy binds directly on the host network. Keep ALLOY_STATSD_LISTEN and --server.http.listen-addr on 127.0.0.1 unless you intentionally want those listeners reachable from outside the host.

Startup Checks

The container entrypoint checks:

  • The optional validator master key is exactly empty or has the public 52-character nH structure, before checking files or other configuration.
  • Required environment variables are present and not placeholders.
  • xrpld.cfg is mounted and readable.
  • debug.log and perf.log are mounted and readable.
  • [insight] server is statsd.
  • [insight] address matches the configured host loopback StatsD address.
  • [insight] prefix exists.
  • The generated StatsD mapping can be read.
  • alloy validate /etc/alloy/config.alloy passes.

These checks prove the container can start with the expected configuration. They do not prove live StatsD traffic is arriving.

StatsD is UDP. There is no connection handshake to check, and the entrypoint runs before Alloy starts receiving packets. xrpld also emits StatsD over time, not on demand. For that reason, the entrypoint cannot prove StatsD is working end to end.

Finding Errors

Check whether the container is running:

docker ps -a --filter name=xrpl-monitoring-alloy

Check startup errors:

docker logs xrpl-monitoring-alloy

Common entrypoint errors:

  • ALLOY_VALIDATOR_MASTER_KEY must be blank or ... means the optional value is not a structurally valid public validator master key. The rejected value is not printed.
  • ALLOY_NODE is required. means an environment variable is missing.
  • still contains a placeholder value means a placeholder was not replaced.
  • xrpld config was not mounted as a file means the host xrpld.cfg path is wrong.
  • xrpld debug log is not readable or xrpld perf log is not readable means the log directory or file permissions are wrong.
  • [insight] address must be ... means xrpld.cfg does not match the host loopback StatsD address passed to the container.
  • alloy validate errors mean the Alloy config did not pass validation.

Common post-start symptoms:

  • 401 push errors usually mean the username or password is wrong.
  • 403 push errors usually mean the username is not mapped to a monitoring tenant.
  • No xrpld_* metrics usually means live StatsD packets are not arriving, the prefix does not match what xrpld emits, or xrpld has not emitted the metric yet.
  • Missing logs usually means the mounted log directory does not contain the configured debug.log or perf.log.

Stop Or Remove

Stop monitoring:

docker stop xrpl-monitoring-alloy

Start it again:

docker start xrpl-monitoring-alloy

Remove the container:

docker rm xrpl-monitoring-alloy

Recreate the container after changing ALLOY_VALIDATOR_MASTER_KEY, including when opting out by removing or blanking it. Historical labeled series are not rewritten and remain until backend retention expires them.

Remove the Alloy data volume only if you want to discard Alloy runtime state:

docker volume rm alloy-data

If you changed xrpld.cfg and want to go back to a previous StatsD collector, restore the previous [insight] address yourself and restart xrpld using your normal process.

Back to top