
Deploy Grafana Pyroscope | (Just Updated) Continuous Profiling Server with Login On, Data Survives Redeploys
Grafana Pyroscope: continuous profiling server, flame graphs, login on
pyroscope
Just deployed
/data
Deploy and Host Grafana Pyroscope on Railway
Built for an LLM agent to deploy and use. There is no setup step and nothing to fill in: a 32-character password is generated at deploy time, anonymous requests are refused, and the contract below lists every address, variable name and the one script that proves it works.
Grafana Pyroscope is an open-source continuous profiling server from Grafana Labs. It stores CPU and memory profiles pushed by applications, agents and eBPF collectors, and answers queries as flame graphs through its HTTP API and web UI, so you can see which functions burn the time and memory in production.
About Hosting Grafana Pyroscope
This template runs one service, pyroscope, built from the official grafana/pyroscope 2.4.3 image, pinned by digest. Pyroscope runs in single-binary mode (every component in one process) with block storage, the metastore and the write-ahead state on the attached volume, mounted at /data, so profiles survive redeploys. A Caddy gateway in the same container listens on the public port and requires HTTP basic auth on every path except /ready. The entrypoint runs as root only long enough to fix the ownership of the root-owned volume, then starts Pyroscope and Caddy as unprivileged users. Profiles are kept for 30 days by default; set PYROSCOPE_RETENTION (for example 90d, or 0 to keep forever) and redeploy to change that.
Pyroscope has no login of its own, so the gateway is the only protection on the public address. Pyroscope also listens on port 4041 inside the container for its own components; that port is not published, but services in the same Railway project can reach it on the private network without a password, so do not run untrusted code in the same project. Filesystem storage suits one node and moderate ingest.
Agent contract
- Public URL:
PYROSCOPE_PUBLIC_URL(https://plus the service'sRAILWAY_PUBLIC_DOMAIN). - Private URL:
http://pyroscope.railway.internal:8080, exposed asPYROSCOPE_PRIVATE_URL. - Credentials: user
admin(set in the image; add aPYROSCOPE_USERNAMEvariable to the service to use another name), password in thePYROSCOPE_PASSWORDvariable. - Auth: HTTP basic auth on every path except
/ready. Anonymous requests and wrong passwords get401. Profiling agents that support it send the same basic auth credentials. - Health:
GET /readyreturns 200 once all components run (about 10 seconds after start). - API: push profiles to
/ingest(folded, pprof) or/push.v1.PusherService/Push; query flame graphs at/pyroscope/render; the web UI is served at/. Fresh data becomes queryable after about one minute.
# run with PYROSCOPE_PUBLIC_URL and PYROSCOPE_PASSWORD set (PYROSCOPE_USERNAME optional, default admin)
U="${PYROSCOPE_USERNAME:-admin}"
curl -s -o /dev/null -w "anonymous: %{http_code}\n" "$PYROSCOPE_PUBLIC_URL/pyroscope/render"
curl -s -o /dev/null -w "bad login: %{http_code}\n" -u "$U:nope" "$PYROSCOPE_PUBLIC_URL/pyroscope/render"
NOW=$(date +%s)
printf 'main;work;parse 600\nmain;work;emit 400\n' | curl -s -o /dev/null -w "push: %{http_code}\n" -u "$U:$PYROSCOPE_PASSWORD" -X POST \
--url-query "name=agentapp" --url-query "from=$((NOW-10))" --url-query "until=$NOW" --url-query "format=folded" --url-query "sampleRate=100" \
--data-binary @- "$PYROSCOPE_PUBLIC_URL/ingest"
sleep 90
curl -s -u "$U:$PYROSCOPE_PASSWORD" -G "$PYROSCOPE_PUBLIC_URL/pyroscope/render" \
--data-urlencode 'query=process_cpu:cpu:nanoseconds:cpu:nanoseconds{service_name="agentapp"}' \
--data-urlencode "from=now-10m" --data-urlencode "until=now+1m" --data-urlencode "format=json"
A fresh deploy prints anonymous: 401, bad login: 401, push: 200, then a JSON flame graph whose names list holds total, main, work, parse and emit.
Why Deploy Grafana Pyroscope on Railway?
Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.
By deploying Grafana Pyroscope on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.
- Agent-ready - generated password, contract block and one working script; no setup step.
- Closed by default - the profile API and UI are behind basic auth, so an exposed server does not accept or reveal data to strangers.
- Any profiler in - Pyroscope SDKs, Grafana Alloy, eBPF collectors and pprof endpoints push to the same address.
- State survives redeploys - profile blocks and the metastore live on the attached volume.
- Light when idle - about 35 MiB resident with no traffic.
Common Use Cases
- Find the slow function in production - push CPU profiles from a service and read the flame graph.
- Track memory growth - compare heap profiles across releases.
- Profiling backend for Grafana - add it as a Pyroscope data source with basic auth.
Dependencies for Grafana Pyroscope Hosting
- One Railway volume for profile blocks and the metastore (created by the template).
Deployment Dependencies
- Grafana Pyroscope documentation
- Official image
- grafana/pyroscope - upstream project
- Caddy - authentication gateway
Implementation Details
| Variable | Purpose |
|---|---|
PYROSCOPE_PASSWORD | Basic-auth password, generated per deploy. |
PYROSCOPE_PUBLIC_URL | HTTPS address for clients outside Railway. |
PYROSCOPE_PRIVATE_URL | Address on the private network, for services in the same project. |
The user is admin. To change it, add a PYROSCOPE_USERNAME variable to the service (letters, digits, dot, underscore, hyphen) and redeploy. Reference the password from another service with ${{pyroscope.PYROSCOPE_PASSWORD}}.
Template Content

