A self-hosted, local monitoring stack for a Nethermind node. A single Grafana Alloy agent collects both metrics and logs from your node and ships them to a local backend:
- Alloy scrapes the node's Prometheus metrics endpoint and reads its container logs.
- Prometheus stores the metrics.
- Loki stores the logs.
- Grafana visualizes both.
- Nethermind
v1.26.0or later. - Docker with Docker Compose plugin installed. (Installation Guide)
- Grafana
v13.0.0or later — the dashboard is stored in the v2 schema (dashboard.grafana.app/v2). The bundledgrafana/grafana:latestimage satisfies this; pinning an older image will leave the dashboard unprovisioned.
-
Clone this repository and move into the project folder.
-
(Optional) Open the Grafana config file and edit the admin username and password for additional security.
-
Configure Nethermind to expose a metrics endpoint (this replaces the old PushGateway setup). Launch it with the flags:
--Metrics.Enabled=true --Metrics.ExposePort=8008or the equivalent environment variables:
NETHERMIND_METRICSCONFIG_ENABLED=true NETHERMIND_METRICSCONFIG_EXPOSEPORT=8008 -
Create your environment file and set your node's container name:
cp env.example .envEdit
.envand setEXECUTION_CONTAINER_NAMEto the name of your Nethermind container (andNETHERMIND_METRICS_ADDRESSif your node is not reachable at the defaulthost.docker.internal:8008). See Node runtime scenarios below.If you run the node with a custom
--Metrics.NodeName, setNODE_NAMEto the same value: Nethermind stamps it on every metric as theInstancelabel, and Alloy usesNODE_NAMEto label the logs, so the dashboard's Instance filter only lines both up when they match. -
Execute
docker compose up -d. -
Open your local Grafana in your browser and log in with your configured username and password. Metrics appear on the Nethermind dashboard; logs are available under Explore → Loki.
Alloy needs two things from your node: a reachable metrics endpoint and a
source of logs. The defaults target the most common case; adjust .env (and,
for logs from a non-Docker node, alloy/config.alloy) as needed.
No changes needed beyond EXECUTION_CONTAINER_NAME:
- Metrics: Alloy scrapes
host.docker.internal:8008(the exposed metrics port on the host). - Logs: Alloy discovers the container through the mounted Docker socket and reads its stdout.
Security note: log collection mounts
/var/run/docker.sockinto the Alloy container. Access to the Docker socket is effectively root-equivalent control of the host, so only run this stack on a host you trust. If you don't need container logs, remove thedocker.sockmount from thealloyservice indocker-compose.yml(metrics collection does not require it).
- Metrics: still work via
host.docker.internal:8008— no change. - Logs: the Docker socket won't find a non-Docker process. In
alloy/config.alloy, comment out thediscovery.dockerandloki.source.dockerblocks and enable the commentedlocal.file_match/loki.source.fileblocks at the bottom of the file, then setNETHERMIND_LOG_PATHto your node's log file(s).
- Metrics: set
NETHERMIND_METRICS_ADDRESS=<node-ip>:8008in.env. Make sure that port is reachable and firewalled appropriately. - Logs: Docker-socket log collection does not work across hosts. Either run Alloy on the node itself for logs, or accept a metrics-only setup.
By default all services are exposed only on the localhost (127.0.0.1)
interface. To expose them on another interface, edit .env and set the desired
interface per service (use 0.0.0.0 for all interfaces):
NETHERMIND_PROMETHEUS_HOST— Prometheus interface.NETHERMIND_GRAFANA_HOST— Grafana interface.NETHERMIND_LOKI_HOST— Loki interface.NETHERMIND_ALLOY_HOST— Alloy UI interface.
Then run docker compose up -d again.
In case any of these interfaces are exposed to the internet (ie. using
0.0.0.0) be sure to restrict access to the services by using a firewall.