Prometheus¶
Query metrics, check scrape targets, read alert rules. Prometheus has no authentication of its own, so the network and the gateway do the work a credential normally does.
| Policy | prometheus/read-only |
| Connection kind | prometheus |
| Upstream looks like | http://prometheus.internal:9090 |
| Credential | None, usually — or a reverse-proxy basic-auth login |
| Tier | 2 — Prodpeek is the only fence, and the profile says so |
| Time to set up | about 10 minutes |
Grant exactly these¶
- Nothing. There is no Prometheus credential to create.
-
Prometheus has no user model, no tokens and no roles. Anyone who can reach the port gets everything. This is not a setting you have left off — the server has no concept of a user. That is why this profile is Tier 2 and says so, instead of claiming a credential is doing work it cannot do.
- A basic-auth login on the reverse proxy in front of it (recommended)
-
If Prodpeek reaches Prometheus across any network boundary at all, put a proxy in front and give Prodpeek a login for it. That credential is what the connection stores, and it is the only authentication in this picture.
Do not grant these¶
Each of these would undo the point of the rest
--web.enable-admin-api
This is the flag that turns on delete_series, clean_tombstones and snapshot. It is off by default. The Prodpeek adapter has no code path that could reach those endpoints, so leaving the flag off costs you nothing and removes the question entirely.
--web.enable-lifecycle
Enables POST /-/reload and POST /-/quit. Same reasoning: the adapter cannot call them, and an operator reading your Prometheus config should not have to work out whether something else can.
Exposing port 9090 to the internet
With no authentication, an exposed Prometheus is a public read of every metric you collect — request volumes, error rates, customer names in labels, internal hostnames, your whole topology. This is the single most common Prometheus misconfiguration and it is not made safe by putting Prodpeek in front of it, because Prodpeek is not the only thing that can reach the port.
There is no key to create¶
This is the short answer, and it is worth being blunt about because every other service in this catalog has one: Prometheus has no authentication. No users, no tokens, no roles, no read-only mode. A stock Prometheus answers whoever can reach its port, in full.
So "generate a read-only credential for Prometheus" is not a task you have been putting off — it is not a thing that exists. What you do instead is decide who can reach the port, and that is the rest of this page.
What that means for the Tier¶
Everywhere else in Prodpeek there are two fences: the credential refuses writes on
its own, and the gateway refuses them again. Here there is one. prometheus/read-only
is Tier 2, and the profile says so in the file rather than in a footnote.
What makes it defensible is the shape of the connection. This is a native adapter — Prodpeek's own fixed menu of twelve GET endpoints — not a proxy. An agent never supplies a URL path; it names a tool, and the adapter builds the request. The endpoints that would matter are unreachable because nothing constructs them:
| Endpoint | What it does |
|---|---|
POST /api/v1/admin/tsdb/delete_series |
deletes data irreversibly |
POST /api/v1/admin/tsdb/clean_tombstones |
as above |
POST /api/v1/admin/tsdb/snapshot |
writes a full copy to disk |
POST /-/reload |
re-reads configuration |
POST /-/quit |
stops Prometheus |
A generic "read-only HTTP proxy for Prometheus" would be one path-traversal bug away from the first of those. A fixed menu has no such bug available. That is the whole argument for building the adapter rather than pointing a plain HTTP upstream at the API.
Step 1 — check the two flags¶
Open Status → Command-Line Flags in the Prometheus UI, or:
Both should be "false":
If either is true, turn it off unless you have a specific reason. Prodpeek
cannot reach those endpoints either way — but a Prometheus that can be told to
delete its own data by anything on the network is a Prometheus with a bigger
problem than this integration.
Step 2 — decide who can reach port 9090¶
Pick whichever matches your setup.
A. Prodpeek and Prometheus on the same Docker network — the simplest, and the best. Do not publish 9090 to the host at all:
# docker-compose.yml
services:
prometheus:
image: prom/prometheus:v3.1.0
# No `ports:` section. Reachable from other containers, from nothing else.
networks: [obs]
prodpeek:
image: ghcr.io/prodpeek/prodpeek:latest
ports: ["127.0.0.1:8787:8787"]
networks: [obs]
The connection URL is then http://prometheus:9090, and there is no credential
at all. This is the recommended shape for EJD.
B. Prometheus on another host, private network. Bind it to the private interface and firewall the port to the Prodpeek host only:
# prometheus.yml is not where this lives — it is a command-line flag:
--web.listen-address=10.0.0.5:9090
# ufw, on the Prometheus host
ufw allow from 10.0.0.9 to any port 9090 proto tcp # 10.0.0.9 = Prodpeek
ufw deny 9090
C. Prometheus reachable over the public internet. Put a reverse proxy in front with basic auth, and give Prodpeek that login. Caddy makes this two lines:
prom.example.dk {
basic_auth {
prodpeek $2a$14$... # caddy hash-password
}
reverse_proxy localhost:9090
}
nginx, if you prefer:
location / {
auth_basic "prometheus";
auth_basic_user_file /etc/nginx/prom.htpasswd; # htpasswd -c ... prodpeek
proxy_pass http://127.0.0.1:9090;
}
The connection URL is https://prom.example.dk, the credential is
prodpeek:the-password, and the connection's authentication method is
Username & password.
Step 3 — add it to Prodpeek¶
In the console: Services → Add a service → pick prometheus/read-only.
Set the upstream to the base URL (http://prometheus:9090, or
https://prom.example.dk). Leave the credential empty for A and B; for C, choose
Username & password and enter user:password.
From an agent:
With no credential it returns a drop link. For A and B there is nothing to drop — just save it from the console instead, since an empty credential is legitimate here.
Then Test connection. You should see the twelve allowed tools, and nothing under "advertised but absent from the policy" — the adapter's menu and the profile are checked against each other in CI, so a mismatch would be a bug in Prodpeek rather than in your setup.
What your agent can then do¶
prometheus__targets which scrapes are up, and which are failing
prometheus__query query=up the classic "is everything alive"
prometheus__query_range query=rate(http_requests_total[5m]) window=6h
prometheus__alerts what is firing right now
prometheus__tsdb_status why Prometheus is using 40GB
prometheus__label_values label=job what this Prometheus actually scrapes
Two limits are built into the adapter and will produce a clear refusal rather than a slow Prometheus: a range query may cover at most 31 days, and its step may be no finer than 15 seconds. Both exist because PromQL has no write form — its danger is cost, not mutation — and one unbounded query is how a monitoring system becomes the outage.
What it refuses, and the one that surprises people¶
/api/v1/status/config is denied, and it is a genuine read. That is the point
of the read_leaks classification: prometheus.yml contains your scrape configs,
and scrape configs routinely carry basic_auth passwords and bearer tokens for
the things being scraped. Reading it is how an agent would collect every
credential your monitoring has.
You can still read it yourself. It is not secret from you.
If Prometheus is already behind Grafana¶
Then you may not need this integration at all. Grafana proxies its datasources, so a Grafana service account can query Prometheus through the Grafana connection you already have — one credential, one audit trail, and the Grafana service account's role does the scoping.
Use this profile when you want Prometheus directly: when there is no Grafana in front of it, when you want targets and TSDB cardinality (which Grafana does not expose), or when you want the two audited separately.
Check you got it right¶
- [ ] curl from outside your network to port 9090 times out or is refused.
- [ ] curl -X POST http://PROM/-/reload returns 404 (lifecycle API off).
- [ ] curl http://PROM/api/v1/status/config is reachable from your laptop but NOT through Prodpeek — the profile denies it, because it contains scrape credentials.
If an agent is reading this
There is no key to generate here, so do not ask the user for one. What you can usefully do is check the two flags above and tell them if either is on. If Prometheus sits behind a proxy, the proxy login goes in through the drop link, which you cannot open.
Then add it to Prodpeek¶
Console: Services → Add a service, pick prometheus/read-only, paste the credential. Or from an agent, add_service with no credential and hand over the drop link.
Then press Test connection and read all three lists.