Parent guide: AGENTS.md — product overview, architecture, domain model, global conventions Related: managed/AGENTS.md (configures VictoriaMetrics scrape targets)
vmproxy is a lightweight, stateless HTTP reverse proxy for VictoriaMetrics. It intercepts requests, reads label filters from a configurable HTTP header, and injects them as extra_filters[] query parameters before forwarding to VictoriaMetrics. This enables label-based access control (LBAC) — restricting which metrics a user can query based on their role.
Client (Grafana / API)
→ HTTP request with X-Proxy-Filter header
→ vmproxy (parses header, injects extra_filters[])
→ VictoriaMetrics (applies filters to all queries)
→ response proxied back to client
- Client includes an HTTP header (default:
X-Proxy-Filter) - Header value is a base64-encoded JSON array of filter strings
- Example:
WyJlbnY9UUEiLCAicmVnaW9uPUVVIl0=decodes to["env=QA", "region=EU"] - vmproxy strips any existing
extra_filters[]params and replaces them with the header values - VictoriaMetrics applies these filters as label matchers to all queries
- Multiple filters are combined with logical OR by VictoriaMetrics
- Invalid headers (bad base64 or JSON) return
412 Precondition Failed X-Forwarded-Foris stripped- Missing
User-Agentis set to empty
CLI flags (using Kong):
| Flag | Default | Purpose |
|---|---|---|
--target-url |
http://127.0.0.1:9090 |
VictoriaMetrics backend URL |
--listen-address |
127.0.0.1 |
Listen address |
--listen-port |
1280 |
Listen port |
--header-name |
X-Proxy-Filter |
HTTP header containing filters |
--debug |
false |
Enable debug logging |
The proxy is built on net/http/httputil.ReverseProxy with a custom Director function:
director()/prepareRequest()— rewritesreq.URLto target, sets Host and AuthorizationfailOnInvalidHeader()— if the filter header is present but malformed, returns 412- Filter injection — removes existing
extra_filters[], parses header, adds each filter asextra_filters[]
- Keep the proxy stateless — no caching, no session state
- Validate header format before processing (fail fast on malformed input)
- Use
net/http/httputil.ReverseProxyas the base - Test both valid and invalid filter scenarios
- Don't add business logic — the proxy should only transform headers into query parameters
- Don't cache responses — VictoriaMetrics handles caching
- Don't modify response bodies
- Unit tests:
proxy/proxy_test.go - Integration tests:
main_test.go - Run:
make test
vmproxy/main.go— entry point and configurationvmproxy/proxy/proxy.go— core proxy logic