> ## Documentation Index
> Fetch the complete documentation index at: https://docs.monad.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Prometheus Metrics Migration

> Configure Monad metrics endpoint

<Note>
  Do not run this procedure. Wait for the official Monad Foundation announcement.
</Note>

Monad nodes expose a native HTTP endpoint in Prometheus format. Monitoring systems can scrape this endpoint directly.

<Note>
  Collecting node metrics through the OpenTelemetry (OTel) collector is deprecated. Use the native metrics endpoint instead.
</Note>

## Default configuration

Since v0.16.0, the native metrics endpoint is **enabled by default**:

* **Port:** `9143/TCP`.
* **Listen address:** `0.0.0.0:9143` (all IPv4 interfaces).
* **Path:** `/metrics`.
* **Local URL:** `http://127.0.0.1:9143/metrics`.
* **Remote URL:** `http://NODE_IP:9143/metrics`.

This is the implicit default configuration, in `/home/monad/monad-bft/config/node.toml`:

```toml theme={null}
[metrics]
enabled = true
listen_addr = "0.0.0.0:9143"
```

If you have not overridden these settings, no configuration change or restart is needed to enable the endpoint.

## Configure your node

### 1. Configure the endpoint

The endpoint is enabled by default, so no extra configuration is required. To confirm, edit the `node.toml` file and verify the metrics endpoint is not set as `enabled = false`.

**To set up a custom port, for example, to listen on port `9144`**:

```toml theme={null}
[metrics]
enabled = true
listen_addr = "0.0.0.0:9144"
```

**To listen on another interface, for example, if metrics are collected only by a scraper on the same host**:

```toml theme={null}
[metrics]
enabled = true
listen_addr = "127.0.0.1:9143"
```

Then restart the `monad-bft` service to reload the configuration.

```bash theme={null}
systemctl restart monad-bft
systemctl status monad-bft --no-pager -l
```

### 2. Set up the firewall

Block the metrics port from the public internet and allow only approved monitoring source IPs.

It is requested that validators allow the **Monad Foundation monitoring server's source IP (`84.32.32.227`)** to access their metrics endpoint.

<Warning>
  UFW evaluates rules in order, and the first matching rule wins. The monitoring allow rule must appear **before** the general deny.
</Warning>

```bash theme={null}
# Remove all existing rules referencing the metrics port.
for n in $(ufw status numbered | grep "9143" | grep -oP '(?<=\[)[0-9]+(?=\])' | sort -rn); do
  ufw --force delete "$n"
done

# Allow the monitoring IP source and deny by default.
ufw insert 1 allow proto tcp from 84.32.32.227 to any port 9143 comment 'Monad Foundation monitoring'
ufw deny 9143 comment 'Block public access to metrics port'

ufw status numbered
```

If the node uses a different metrics port, replace `9143` in the commands above.

Verify that the allow from `84.32.32.227` appears above the deny from `Anywhere`.

### 3. Verify the endpoint

Locally, this should work:

```bash theme={null}
curl http://127.0.0.1:9143/metrics
```

Expect Prometheus text output with metric samples and metadata such as `# TYPE` lines.

Also, from another node on the internet, test with the node's public address to confirm the firewall is blocking external traffic:

```bash theme={null}
curl http://PUBLIC_NODE_ID:9143/metrics
```

This request should fail. If it succeeds, the firewall is not blocking the metrics port as expected.

## Monad Foundation scrapping

By default, Monad Foundation will scrape all active validators on their public IP address, on the default `9143` port.

### Custom port

It is possible to expose the validator metrics using a custom port or custom IP address. You can set up your metrics endpoint on a different port (see above), or behind a NAT setup.

To declare the custom configuration, set the optional `metrics_address` or `metrics_port` on your validator-info record. Open a pull request in [monad-developers/validator-info](https://github.com/monad-developers/validator-info) with the change.

For example, merge the following fields into your validator file, keeping its other fields unchanged:

```json theme={null}
{
  "metrics_address": "192.0.2.10",
  "metrics_port": 9144
}
```

Replace the example address with the IP address or hostname reachable by the monitoring server. Use a host only, without `http://`, a port, or `/metrics`; specify the port separately as an integer. Do not use `0.0.0.0` as `metrics_address`: it is a local bind address, not a scrape destination.

The reachable address does not have to be the node's own IP. The endpoint can be exposed through NAT redirection — a firewall or load balancer that forwards a custom public IP and port to the node's `listen_addr` — in which case `metrics_address` and `metrics_port` must match that public-facing IP and port, not the node's internal bind address.

### Confirming MF connects

To confirm Monad Foundation is actively scraping your metrics endpoint, check both sides of the connection.

To see the MF monitoring server's requests coming in:

```bash theme={null}
tcpdump -nn -i any src host 84.32.32.227 and dst port 9143
```

To see your node sending metrics back:

```bash theme={null}
tcpdump -nn -i any src port 9143 and dst host 84.32.32.227
```

The second command is the stronger signal: seeing packets there means the node actually responded to the scrape, not just that a request came in.

## Related instructions

* [v0.16.0 upgrade instructions](./v0.16.0.mdx): configuration rename and metrics defaults.
* [v0.16.1 upgrade instructions](./v0.16.1.mdx): confirmation of the default endpoint for mainnet and testnet operators.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.