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
.envvariables at your legacy rippled paths instead, for exampleXRPLD_CONFIG_FILE=/etc/opt/ripple/rippled.cfgandXRPLD_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.logandperf.logare 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.logandperf.logfiles. xrpldStatsD configured to send to a host loopback UDP port that Docker publishes to Alloy. The default is127.0.0.1:9125.- Optionally, the validator’s public 52-character
nHmaster 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:localUse 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.1binds the port only on host localhost, so it is not opened to the network.<host-port>is the UDP port fromxrpld.cfg, for example9125or19125.9125/udpis the container port and protocol. Keep this as9125/udpbecause the image listens on0.0.0.0:9125inside 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:localThat 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.alloyFor 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
nHstructure, before checking files or other configuration. - Required environment variables are present and not placeholders.
xrpld.cfgis mounted and readable.debug.logandperf.logare mounted and readable.[insight] serverisstatsd.[insight] addressmatches the configured host loopback StatsD address.[insight] prefixexists.- The generated StatsD mapping can be read.
alloy validate /etc/alloy/config.alloypasses.
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-alloyCheck startup errors:
docker logs xrpl-monitoring-alloyCommon 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 valuemeans a placeholder was not replaced.xrpld config was not mounted as a filemeans the hostxrpld.cfgpath is wrong.xrpld debug log is not readableorxrpld perf log is not readablemeans the log directory or file permissions are wrong.[insight] address must be ...meansxrpld.cfgdoes not match the host loopback StatsD address passed to the container.alloy validateerrors mean the Alloy config did not pass validation.
Common post-start symptoms:
401push errors usually mean the username or password is wrong.403push 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 whatxrpldemits, orxrpldhas not emitted the metric yet. - Missing logs usually means the mounted log directory does not contain the configured
debug.logorperf.log.
Stop Or Remove
Stop monitoring:
docker stop xrpl-monitoring-alloyStart it again:
docker start xrpl-monitoring-alloyRemove the container:
docker rm xrpl-monitoring-alloyRecreate 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-dataIf 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.