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.
Long-form template copy for Railway (description / Deploy and Host sections): RAILWAY.md.
- Grafana with automated setup
- Grafana UI
- Password Authentication (Set username & password in environment variables)
- Railway config as code via
railway.toml
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")]
- 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_INSTALL_PLUGINSto required plugins only
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 to set RAILWAY_RUN_UID=0. That variable is the common
workaround for this class of error, but it leaves Grafana running as root for the
entire lifetime of the container.
The recursive chown only runs when the mount root is still misowned, so it
costs one pass on the first boot after attaching a volume and nothing on
subsequent restarts.
Adding grafana-image-renderer to GF_INSTALL_PLUGINS 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=latest-ubuntu (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>:8081/render and GF_RENDERING_CALLBACK_URL=http://<grafana-service>: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.
- 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_INSTALL_PLUGINS=grafana-piechart-panel,grafana-worldmap-panel,grafana-clock-panel,grafana-simple-json-datasource
GF_LOG_MODE=console
GF_VERSION=latest
PORT=3000- Wait for Build & Deployment to Finish
- Open the custom URL an enter your credentials
- When you configure your Grafana connection, use your custom URL as the host.
- Use the token in the environment variables to authenticate
- Setup bucket name and organization name in the environment variables
- Use grafana version 2.0 or above
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.
docker compose build
docker compose up -dConnect to http://localhost:3000 use setup username & password from docker-compose file to login to grafana.