I need to scrape Prometheus metrics from an endpoint that requires a custom HTTP header, x-service-token
.
Prometheus does not include an option to scrape using a custom HTTP header, only the Authorization
header.
One user shared a workaround for using nginx to create a reverse proxy
Just in case others come looking here for how to do this (there are at least 2 other issues on it), I’ve got a little nginx config that works. I’m not an nginx expert so don’t mock! 😉
I run it in docker. A forward proxy config file for nginx listening on 9191:
http { map $request $targetport { ~^GET http://.*:([^/]*)/ "$1"; } server { listen 0.0.0.0:9191; location / { proxy_redirect off; proxy_set_header NEW-HEADER-HERE "VALUE"; proxy_pass $scheme://$host:$targetport$request_uri; } } } events { }
Run the transparent forward proxy:
docker run -d --name=nginx --net=host -v /path/to/nginx.conf:/etc/nginx/nginx.conf:ro nginx
In your prometheus job (or global) add the
proxy_url
key- job_name: 'somejob' metrics_path: '/something/here' proxy_url: 'http://proxyip:9191' scheme: 'http' static_configs: - targets: - '10.1.3.31:2004' - '10.1.3.31:2005'
Originally posted by @sra in https://github.com/prometheus/prometheus/issues/1724#issuecomment-282418757
I have tried configuring this, but without ‘host’ networking and using host.docker.internal
instead of localhost, but nginx is not able to connect
nginx | 172.26.0.4 - - [31/Oct/2022:16:07:38 +0000] "GET http://host.docker.internal:8080/actuator/prometheus HTTP/1.1" 502 157 "-" "Prometheus/2.39.1"
This workaround also requires saving the API key in a file, which is not ideal, as this could accidentally be committed to a repo.
Prometheus locked the GitHub issue, so users are not able to ask for help or follow up questions.
There are two other StackOverflow questions on this topic, but the answers do not attempt to provide workarounds:
2
Answers
I've managed to get this working with an nginx proxy that runs on the same Docker network as the Prometheus instance.
Prometheus is configured to scrape the Prometheus metrics from nginx.
URLs
I have 3 environments, 'local', 'dev', and 'prod'.
The Prometheus metrics are available at the following URLs. Note that dev and prod require HTTPS and an API key, but local does not.
http://localhost:8080/metrics/prometheus
https://dev.my-app.website.com/metrics/prometheus
http://prod.my-app.website.com/metrics/prometheus
nginx config
The nginx server has been configured to forward the requests to each environment based on the port.
:9191
- local:9192
- dev:9193
- prodI have manually defined the URLs for each environment in each nginx
server { }
block (except for 'localhost'), because nginx or Prometheus doesn't seem to like resolving the correct URL otherwise. It's a mystery.Prometheus config
Prometheus is configured to use the nginx container as a proxy URL.
Because nginx and Prometheus are running in the same Docker network, I can specify nginx by the container name.
Docker Compose config
Finally, the Prometheus and nginx Docker instances are configured to read the
./config/prometheus.yml
and./config/nginx.conf
files.I brought you a complete setup with an app, a forward proxy, and prometheus in docker-compose. It’s quite long, so I’m putting it after the explanation. Please note that, just as with your solution, it does not work with
host.docker.internal
as it seems that NGINX does not use/etc/hosts
when resolving hosts: https://github.com/NginxProxyManager/nginx-proxy-manager/issues/259#issuecomment-1125197753 . All other hosts should work fine and you can use host’s IP address instead ofhost.docker.internal
if you need so.You can run this by saving the contents into
docker-compose.yml
and runningdocker-compose up
from the same directory. After 10 seconds or so you should see in logs how requests go through the proxy to the app and the app will show you the headers that it got. You can then proceed to Prometheus UI (localhost:9090
) and query for metricthe_answer_is
to further check that everything is in place.The proxy works as following:
target
param (e.g.GET /?target=example.com
) is the host or IP where the actual metrics are, this is the only mandatory parameter;scheme
param, use it as the protocol, default – "http";host
param, use it asHost
header, default – the value oftarget
param;port
param, use it as a TCP port, default is "" (determined by the scheme);secret_token
param, it gets injected intoX-Custom-Header
, default is "";I recommend testing the proxy with
curl
, like this:Now goes the
docker-compose.yml
: