Back to Blog
Tutorial10 min read2026-06-30

How to Deploy Grafana Dashboards in the Cloud

Grafana is the de facto standard for observability dashboards. Learn how to deploy it with a PostgreSQL backend, provisioned data sources, and dashboards-as-code so nothing is lost on restart.

Ajay Kumar
Ajay Kumar
Founder & DevOps, PandaStack

Grafana is the visualization layer for modern observability — Prometheus metrics, Loki logs, ClickHouse analytics, and dozens of other sources, all rendered as dashboards. Running it yourself is straightforward, but a *durable* Grafana deployment needs an external database and a provisioning strategy so your dashboards and data sources survive container restarts. Here's how to do it right.

The persistence problem

Out of the box, Grafana stores its configuration — users, dashboards, data sources, API keys — in an embedded SQLite database. In a stateless container, that file is wiped on every redeploy. You have two complementary fixes:

  1. 1External database for Grafana's own state.
  2. 2Provisioning (config-as-code) so data sources and core dashboards are recreated declaratively on every boot.

Use both. The external DB persists user-created content; provisioning version-controls the foundational setup.

Step 1: Configure the external database

Grafana supports PostgreSQL and MySQL for its backend store. Configure via environment variables:

GF_DATABASE_TYPE=postgres
GF_DATABASE_HOST=<host>:5432
GF_DATABASE_NAME=grafana
GF_DATABASE_USER=<user>
GF_DATABASE_PASSWORD=<password>
GF_DATABASE_SSL_MODE=require

Grafana creates its schema automatically on first boot.

Step 2: Core settings

GF_SERVER_ROOT_URL=https://grafana.yourdomain.com
GF_SECURITY_ADMIN_USER=admin
GF_SECURITY_ADMIN_PASSWORD=<strong-password>
# pin this so signed content stays valid across restarts
GF_SECURITY_SECRET_KEY=<random 32+ chars>

The GF_SECURITY_SECRET_KEY encrypts data-source credentials stored in the database — keep it stable.

Step 3: Provision data sources as code

Drop a YAML file at /etc/grafana/provisioning/datasources/datasources.yaml:

apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
  - name: Loki
    type: loki
    access: proxy
    url: http://loki:3100

Because this is declarative, redeploying never loses your data sources.

Step 4: Provision dashboards as code

Reference a folder of dashboard JSON files:

# /etc/grafana/provisioning/dashboards/dashboards.yaml
apiVersion: 1
providers:
  - name: default
    folder: 'Provisioned'
    type: file
    options:
      path: /var/lib/grafana/dashboards

Export dashboards from the UI as JSON, commit them to your repo, and they're recreated on every deploy. This is the cleanest way to keep dashboards in version control.

Step 5: Deploy on PandaStack

Grafana publishes an official Docker image, so this fits the container app workflow perfectly. The provisioning files live in your repo, baked into the image via a small Dockerfile:

FROM grafana/grafana:latest
COPY provisioning/ /etc/grafana/provisioning/
COPY dashboards/ /var/lib/grafana/dashboards/

Then:

  1. 1Provision a managed PostgreSQL database for Grafana's state.
  2. 2Create a container app from your repo (PandaStack builds the Dockerfile with rootless BuildKit).
  3. 3Link the database and set the GF_DATABASE_* and security variables.
  4. 4Attach a custom domain — automatic SSL gives you HTTPS.

Step 6: Authentication and sharing

For a team deployment, don't rely on the single admin login:

  • Configure OAuth/SSO (GF_AUTH_* variables) so people sign in with your identity provider.
  • Disable anonymous access unless you specifically want public dashboards.
  • Use Grafana's folder permissions and teams for access control.
GF_AUTH_ANONYMOUS_ENABLED=false
GF_USERS_ALLOW_SIGN_UP=false

Comparison: persistence strategies

ApproachPersists user dashboardsVersion controlledSurvives redeploy
SQLite onlyNoNoNo
External DB onlyYesNoYes
Provisioning onlyNo (read-only)YesYes
External DB + provisioningYesPartlyYes

The last row is the production answer.

Honest caveats

Grafana visualizes data; it doesn't store time-series itself. You still need Prometheus, Loki, ClickHouse, or another backend behind it. Also, provisioned dashboards are read-only in the UI by default — if your team likes editing dashboards live, lean on the external database for those and reserve provisioning for the canonical set.

Wrapping up

A bulletproof Grafana deployment combines an external PostgreSQL backend with config-as-code provisioning. The database keeps live edits; provisioning keeps your foundation reproducible and in Git. Together they make redeploys boring — which is exactly what you want from your dashboards.

PandaStack's managed PostgreSQL and Dockerfile builds make this an easy stack to stand up, and the free tier covers a small team's Grafana. Get started at https://dashboard.pandastack.io.

References

  • Grafana documentation: https://grafana.com/docs/grafana/latest/
  • Grafana database configuration: https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#database
  • Grafana provisioning: https://grafana.com/docs/grafana/latest/administration/provisioning/
  • Run Grafana with Docker: https://grafana.com/docs/grafana/latest/setup-grafana/installation/docker/
  • Grafana configuration reference: https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/

Ready to deploy?

Start free on PandaStack.

Start free on PandaStack

More in Tutorial

Browse all Tutorial articles →

See also