Grafana Error Guide: 'permission denied' on the Data Path — Fix Plugin and Storage Failures
Fix Grafana 'permission denied' on /var/lib/grafana: correct ownership and mode of the data and plugins dirs, fix volume mounts and fsGroup, stop crash-loops.
- #grafana
- #observability
- #troubleshooting
- #errors
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
Grafana raises this when its process cannot write to its data path (/var/lib/grafana by default) — the SQLite database, the plugins directory, or the PNG/CSV cache. It typically kills startup or breaks plugin installs:
Grafana-server Init Failed: Could not find config defaults, make sure homepath command line parameter is set or working directory is homepath
The more direct filesystem variants are:
failed to save to data path: mkdir /var/lib/grafana/plugins: permission denied
Failed to start grafana. error: failed to connect to database: open /var/lib/grafana/grafana.db: permission denied
All are the OS EACCES: the user Grafana runs as (grafana, UID 472 in the official image) does not own — or cannot write to — the directory backing its data path.
Symptoms
- The container or service crash-loops at startup with
permission deniedongrafana.dborplugins. grafana-cli plugins installfails to unpack into the plugins directory.- Panel image rendering or CSV export fails to write to the cache directory.
- The problem appeared right after mounting a new volume, restoring a backup, or changing the base image UID.
ls -lnon the data path shows an owner UID different from the Grafana process UID.
Common Root Causes
- Volume owned by the wrong UID/GID — a host bind mount or PVC owned by
root/another user, not UID 472. fsGroupnot set on a Kubernetes pod, so the mounted PVC isn’t group-writable by the Grafana user.- Restored backup with root ownership copied in as
root:root. - Read-only mount (
:robind, read-only root filesystem) where Grafana needs to write. - Custom
GF_PATHS_DATA/GF_PATHS_PLUGINSpointing at a directory the process can’t write. - SELinux/AppArmor denying writes to a host path even when Unix perms look correct.
Diagnostic Workflow
1. Identify the exact path and the process UID. The log names the path; find who Grafana runs as:
journalctl -u grafana-server --since '10 min ago' | grep -i 'permission denied'
# Container: which UID is the process?
docker exec grafana id
The official image runs as UID 472 (grafana).
2. Check ownership and mode of the data path. Compare owner UID to the process UID:
# Host / systemd install
ls -ln /var/lib/grafana /var/lib/grafana/plugins
# Container bind mount
ls -ln /path/on/host/grafana-data
If the owner UID isn’t 472 (or the configured user), that’s the cause.
3. Fix ownership and mode. Give the Grafana user ownership of the whole data tree:
# systemd package install (user: grafana)
sudo chown -R grafana:grafana /var/lib/grafana
sudo chmod -R u+rwX /var/lib/grafana
# Docker bind mount for the official image (UID 472)
sudo chown -R 472:472 /path/on/host/grafana-data
4. In Kubernetes, set fsGroup so the mounted PVC is group-writable:
spec:
securityContext:
runAsUser: 472
runAsGroup: 472
fsGroup: 472
5. Confirm the data path config if it was customized:
docker exec grafana env | grep GF_PATHS
grep -E 'data|plugins' /etc/grafana/grafana.ini | grep -v '^;'
Ensure [paths] data/plugins point at a writable directory.
6. Rule out a read-only mount or SELinux. Test a write as the Grafana user:
docker exec -u 472 grafana sh -c 'touch /var/lib/grafana/.wtest && rm /var/lib/grafana/.wtest && echo writable'
# SELinux relabel for a host bind mount, if enforcing
sudo chcon -Rt svirt_sandbox_file_t /path/on/host/grafana-data
Example Root Cause Analysis
A team migrated Grafana from a Docker bind mount to a Kubernetes StatefulSet with a PVC. The pod crash-looped: failed to connect to database: open /var/lib/grafana/grafana.db: permission denied. The image and config were unchanged from the working Docker setup.
kubectl exec ... id confirmed Grafana ran as UID 472, but the freshly provisioned PVC was owned by root:root — the default when no fsGroup is set. UID 472 had no write access, so it couldn’t even open the SQLite file.
Fix: added securityContext.fsGroup: 472 to the pod spec, which made the volume group-owned by GID 472 and group-writable on mount. The pod started cleanly. On Docker the bind mount had happened to be pre-chowned to 472, which is why the same image worked there — the difference was entirely volume ownership, not Grafana.
Prevention Best Practices
- Set
fsGroup(andrunAsUser) to the Grafana UID on every Kubernetes deployment so mounted volumes are writable. chownhost bind mounts to UID 472 (or your configured user) before first start, and after any restore.- Preserve ownership in backups/restores — restore as the Grafana user, not root.
- Keep the data path off read-only filesystems; if the root FS is read-only, mount a writable volume at the data path.
- Pin
GF_PATHS_DATA/GF_PATHS_PLUGINSto known-writable directories and document them. - Add a startup readiness check that writes a temp file to the data path so permission regressions fail fast and visibly.
Quick Command Reference
# Find the failing path
journalctl -u grafana-server --since '10 min ago' | grep -i 'permission denied'
# Process UID vs directory owner
docker exec grafana id
ls -ln /var/lib/grafana /var/lib/grafana/plugins
# Fix ownership (official image UID 472)
sudo chown -R 472:472 /path/on/host/grafana-data
# Kubernetes: set fsGroup: 472 in the pod securityContext
# Confirm writability as the Grafana user
docker exec -u 472 grafana sh -c 'touch /var/lib/grafana/.wtest && echo writable'
Conclusion
A permission denied on Grafana’s data path is a filesystem ownership problem, not a Grafana bug: the process (UID 472 in the official image) can’t write to /var/lib/grafana, its database, or its plugins directory. Compare the process UID to the directory owner, chown the volume (or set fsGroup in Kubernetes), and confirm the mount isn’t read-only or SELinux-blocked. Get ownership right at provisioning time and the crash-loop never starts.
More Grafana prompts & error guides
Every Grafana AI prompt and troubleshooting guide, in one place.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.