
Deploy Grafana
Self-hosted Grafana dashboards & alerts for Prometheus, Loki, InfluxDB, SQL
Just deployed
Grafana for railway.app
Deploy Grafana Community Edition on railway with one click. Grafana is a multi-platform, feature rich metrics dashboard and graph editor for Graphite, InfluxDB & Prometheus. It is most commonly used for visualizing time series data.
✨ Features
- Grafana with automated setup
- Grafana UI
- Password Authentication (Set username & password in environment variables)
- Railway config as code via
railway.toml
🏗️ Architecture
flowchart LR
Client(["🌐 Client"]) -->|HTTPS| Domain["Railway Public Domain"]
Domain -->|"$PORT → GF_SERVER_HTTP_PORT"| App["Container\ngrafana/grafana-oss"]
App --> Volume[("Volume\n/var/lib/grafana")]
Production recommendations (Railway)
- Set strong
GF_SECURITY_ADMIN_PASSWORDin Railway Variables - Persist
/var/lib/grafanawith a Railway volume - Keep healthcheck path at
/api/health - Restrict plugin list in
GF_PLUGINS_PREINSTALLto required plugins only
📏 Resource requirements
Measured on a fresh deploy of Grafana 13.0.2:
- RAM: ~0.3 GB peak on first boot, ~0.27 GB idle
- Volume: ~0.25 GB right after first boot; grows with dashboards, alert state and plugin updates. Plan for ≥ 0.5 GB
- Plan: Hobby or higher recommended. Free and Trial cap RAM (0.5 GB / 1 GB) and volumes (0.5 GB); a full volume or memory spike crashes Grafana
📜 Logging
The first boot runs ~700 database migrations. The image sets GF_LOG_FILTERS=migrator:warn so they don't trip Railway's log rate limit; warnings and errors stay visible. Override it in Railway Variables, e.g. GF_LOG_FILTERS=migrator:info for full migration logs.
💾 Volume permissions
Railway mounts volumes as root:root, while the upstream Grafana image runs as
UID 472. A plain grafana/grafana-oss deployment therefore fails on first boot
with:
mkdir: can't create directory '/var/lib/grafana/plugins': Permission denied
GF_PATHS_DATA='/var/lib/grafana' is not writable.
This template handles it in docker-entrypoint.sh: the
container starts as root, takes ownership of the mount, and then execs into
UID 472. Since it is an exec rather than a fork, no root process survives into
runtime — the Grafana process itself stays unprivileged.
You do not need RAILWAY_RUN_UID=0, which would keep Grafana running as
root. The recursive chown only runs while the mount root is misowned, i.e. once
after attaching a volume.
🖼️ Image rendering (grafana-image-renderer)
Adding grafana-image-renderer to GF_PLUGINS_PREINSTALL does not work on the
default image and fails at startup with exit status 127:
Error: ✗ *rendering.RenderingService run error: Unrecognized remote plugin message
The plugin binary is linked against glibc, while grafana/grafana-oss is
Alpine-based and ships musl. Grafana closed the corresponding upstream report
(grafana-image-renderer#475)
as not planned, so there is no fix to wait for. Two options work:
| Option | How | Trade-off |
|---|---|---|
| Ubuntu image variant | Set VERSION=13.0.2-ubuntu (matching the pinned version) (build arg / Railway variable) | glibc-compatible, single service — but a noticeably larger image and rendering competes with Grafana for the same CPU/memory |
| Separate renderer service | Deploy grafana/grafana-image-renderer as its own Railway service, then point Grafana at it via GF_RENDERING_SERVER_URL=http://SERVICE_NAME:8081/render and GF_RENDERING_CALLBACK_URL=http://GRAFANA_SERVICE_NAME:3000/ | Scales independently and keeps Chromium out of the Grafana container — but a second service to run and pay for |
For anything beyond occasional PDF or panel exports, the separate service is the better fit: rendering is CPU- and memory-spiky, and isolating it keeps those spikes away from the dashboards themselves.
🐍 How to Deploy
- Click Deploy on Railway and setup your credentials in the environment variables
GF_DEFAULT_INSTANCE_NAME=my-instance
GF_SECURITY_ADMIN_USER=yourusername
GF_SECURITY_ADMIN_PASSWORD=yourpassword
GF_PLUGINS_PREINSTALL=grafana-clock-panel
GF_LOG_MODE=console
PORT=3000
- Wait for Build & Deployment to Finish
- Open the custom URL an enter your credentials
👩💻 How to Use
- Log in with
GF_SECURITY_ADMIN_USER/GF_SECURITY_ADMIN_PASSWORD - Add a data source (Prometheus, Loki, InfluxDB, PostgreSQL, …) via its Railway private domain
- Build dashboards and alerts; everything is persisted on the volume
🪲 Bug Reporting
If you find a bug in the template for railway, you can submit an issue to the GitHub Repository. Even better you can submit a Pull Request with a fix.
🐳 Local Development
docker compose build
docker compose up -d
Connect to http://localhost:3000 use setup username & password from docker-compose file to login to grafana.
💬 Support
Questions or feedback? Visit the template forum on Railway Central Station.
Template Content

