Since prometheus doesn't support direct variable replacement in the .yml configuration, I'm using a template and script to run when the docker image starts to create the prometheus.yml file dynamically.
This is useful so it uses the correct ports from the execution and beacon config files automatically.
Prometheus Entrypoint Script
vim ~/alerting/prometheus/entrypoint.sh
#!/bin/sh
# Source environment variables
source /etc/default/execution-variables.env
source /etc/default/beacon-variables.env
export $(cut -d= -f1 /etc/default/execution-variables.env)
export $(cut -d= -f1 /etc/default/beacon-variables.env)
# Output file
OUTPUT="/tmp/prometheus.yml"
# Start with an empty output file
: > "$OUTPUT"
# Process the template file with awk to replace environment variables
awk '{
while (match($0, /\$\{[^}]+\}/)) {
varname = substr($0, RSTART + 2, RLENGTH - 3);
value = ENVIRON[varname];
if (value == "") value = "UNDEFINED";
$0 = substr($0, 1, RSTART - 1) value substr($0, RSTART + RLENGTH);
}
print;
}' "/etc/prometheus/prometheus.yml.template" > "$OUTPUT"
# Continue with Prometheus startup
exec /bin/prometheus "$@"
# Make the scrip executable by everyone, not just the current user
chmod +x ~/alerting/prometheus/entrypoint.sh
Since each client has a different URL path for metrics, and I want a unified endpoint for Prometheus to use, configure an NGINX server to redirect requests to a single endpoint.
It will try each possible endpoint until it finds the actively running client, and if it doesn't find any, it will assume that it is down.
Install NGINX
sudo apt-get update
sudo apt-get install -y nginx
NGINX Config Script
Edit this script to add additional client metrics paths.
sudo vim /etc/default/nginx-config-script.sh
#!/bin/bash
source /etc/default/execution-variables.env
source /etc/default/beacon-variables.env
EXECUTION_METRICS_FULL_URL=""
BEACON_METRICS_FULL_URL=""
# ******************
# EXECUTION CLIENTS
# ******************
# Check if Geth service is running
status_code=$(curl -o /dev/null -s -w "%{http_code}" http://localhost:${EXECUTION_METRICS_PORT}/debug/metrics/prometheus)
if [ "$status_code" = "200" ]; then
EXECUTION_METRICS_FULL_URL=http://localhost:${EXECUTION_METRICS_PORT}/debug/metrics/prometheus
fi
# Check if Besu service is running
status_code=$(curl -o /dev/null -s -w "%{http_code}" http://localhost:${EXECUTION_METRICS_PORT}/metrics)
if [ "$status_code" = "200" ]; then
EXECUTION_METRICS_FULL_URL=http://localhost:${EXECUTION_METRICS_PORT}/metrics
fi
# ***************
# BEACON CLIENTS
# ***************
# Check if LH or Teku service is running (they both use /metrics)
status_code=$(curl -o /dev/null -s -w "%{http_code}" http://localhost:${BEACON_METRICS_PORT}/metrics)
if [ "$status_code" = "200" ]; then
BEACON_METRICS_FULL_URL=http://localhost:${BEACON_METRICS_PORT}/metrics
fi
export $(cut -d= -f1 /etc/default/execution-variables.env)
export $(cut -d= -f1 /etc/default/beacon-variables.env)
export EXECUTION_METRICS_FULL_URL
export BEACON_METRICS_FULL_URL
VARS='${NGINX_PROXY_EXECUTION_METRICS_PORT},\
${EXECUTION_METRICS_FULL_URL},\
${NGINX_PROXY_BEACON_METRICS_PORT},\
${BEACON_METRICS_FULL_URL}'
envsubst "$VARS" < /etc/nginx/sites-available/default.template > /etc/nginx/sites-available/default
echo "Configuration for NGINX has been updated."
sudo chmod +x /etc/default/nginx-config-script.sh
NGINX Service Config
Edit the NGINX service file to run the /etc/default/nginx-config-script.sh script before every start.
sudo vim /lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
Documentation=man:nginx(8)
After=network.target nss-lookup.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
# ***********
# CHANGE HERE
# ↓↓↓↓↓↓↓↓↓↓↓
ExecStartPre=/usr/bin/sudo /etc/default/nginx-config-script.sh
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed
[Install]
WantedBy=multi-user.target
daemon-reload
NGINX Service - Restart CRON
I couldn't get the NGINX service to reliably wait for the EL/BN to start, so as a workaround, run this script with CRON every minute, and if NGINX isn't running, manually restart the service.
sudo vim /etc/default/nginx-service-restart-cron-script.sh
#!/bin/bash
# Check if NGINX is active (running)
if ! systemctl is-active --quiet nginx; then
echo "NGINX is not running. Attempting to restart..."
# Reset the systemd state for NGINX to clear any failure states
sudo systemctl reset-failed nginx
# Attempt to restart NGINX
sudo systemctl restart nginx
echo "NGINX restart attempted."
fi