
Step by Step Guide to solve n8n permission denied error
root:root, but n8n runs as UID 1000 (node user) and can’t write to it. Run this on your host machine:
sudo chown -R 1000:1000 ./n8n_data
Replace ./n8n_data with your actual volume directory. If that fixes it, you’re done. If not, continue reading — the sections below cover every other scenario.
Who this is for: Developers, DevOps engineers, and system administrators who run n8n on Linux or Docker and encounter “permission denied” errors. We cover this in detail in the n8n Installation Errors Guide.
Quick Diagnosis
- Fix the data directory ownership
sudo chown -R $(whoami):$(whoami) /path/to/.n8n sudo chmod -R u+rwX,g+rwX,o-rwx /path/to/.n8n
- Give your user access to the Docker socket
sudo usermod -aG docker $(whoami) # add to docker group newgrp docker # refresh current session
- Ensure the socket mode is correct
sudo chmod 660 /var/run/docker.sock sudo chgrp docker /var/run/docker.sock
- Restart n8n (
npm startordocker compose up -d).
If the error disappears, you’re done. Otherwise continue reading.
1. Why “permission denied” Happens in n8n?
If you encounter any missing environment variables n8n resolve them before continuing with the setup.
| Root cause | Typical symptom |
|---|---|
| Filesystem ownership | EACCES: permission denied, open ‘/home/user/.n8n’ |
| Docker socket access | docker: error during connect: permission denied |
| SELinux / AppArmor | Same error even after chmod/chown |
| Running as non‑root without rights | Service exits immediately |
The official
n8nio/n8n Docker image runs its internal process as a user named node with UID 1000 and GID 1000. When you map a volume like -v ~/.n8n:/home/node/.n8n, Docker mounts your host directory into the container – but the permissions are those of the host filesystem. If the host directory was created by Docker automatically or by root, it will be owned by UID 0 (root), and UID 1000 inside the container has no write access. That is the exact cause of EACCES: permission denied, open '/home/node/.n8n/config'.The pillar page explains what a “permission denied” error is. This guide shows how to resolve each concrete scenario for n8n.
2. Fixing Filesystem Permission Issues
If you encounter any linux systemd service error n8n resolve them before continuing with the setup.
2.1 Identify the data directory
# Default location echo $HOME/.n8n # Custom location (if set) echo $N8N_USER_FOLDER
2.2 Correct ownership & mode
# Replace with your actual folder path sudo chown -R $(whoami):$(whoami) /path/to/.n8n sudo chmod -R u+rwX,g+rwX,o-rwx /path/to/.n8n
Why it works: n8n reads and writes workflow files, execution logs, and an SQLite DB. The process must own the directory and have read/write rights on every file inside it.
2.2a Docker volume fix – use UID 1000 directly (recommended)
When using Docker named volumes or bind mounts, $(whoami) on the host does not match the node user inside the container. Use the numeric UID instead:
# For named volumes (most common Docker Compose setup) sudo chown -R 1000:1000 n8n_data # For bind-mount directories sudo chown -R 1000:1000 ~/.n8n sudo chown -R 1000:1000 /opt/n8n-data # if using custom path
Why 1000 and not $(whoami)? Inside the container, n8n runs as the node user (UID 1000). Your host user might have a different UID (e.g. 1001 on some systems). Using 1000:1000 ensures the container process always has the correct rights, regardless of the host user.
2.3 Docker‑Compose – volume permissions (part 1)
version: "3.8"
services:
n8n:
image: n8nio/n8n
environment:
- N8N_USER_FOLDER=/home/node/.n8n
2.4 Docker‑Compose – volume permissions (part 2)
volumes:
- n8n_data:/home/node/.n8n
user: "${UID}:${GID}" # inject host UID/GID
volumes:
n8n_data:
2.5 Supply UID/GID via .env
UID=$(id -u) GID=$(id -g)
Result: The container writes to the host volume with the exact same UID/GID that owns the directory, eliminating EACCES inside the container.
3. Docker Socket Permission Errors
3.1 Add your user to the docker group
sudo usermod -aG docker $(whoami) newgrp docker # refresh group membership in current shell
EEFA note: Adding a user to the docker group grants root‑equivalent access to the host. Do this only on trusted machines.
3.2 Adjust socket mode (temporary fix)
sudo chmod 660 /var/run/docker.sock sudo chgrp docker /var/run/docker.sock
3.3 Run the n8n container with explicit UID/GID (part 1)
docker run -d \ --name n8n \ -p 5678:5678 \ -v /home/user/.n8n:/home/node/.n8n \
3.4 Run the n8n container with explicit UID/GID (part 2)
-u $(id -u):$(id -g) \ n8nio/n8n
Why this matters: The Docker daemon socket (/var/run/docker.sock) is owned by root:docker with mode 660. If n8n runs as a non‑docker user, it cannot talk to the daemon, causing the error.
4. SELinux / AppArmor Interference
4.1 Quick SELinux test
getenforce # Enforcing | Permissive | Disabled sudo setenforce 0 # switch to Permissive temporarily
If n8n starts after setenforce 0, you need a proper policy module.
4.2 Create a SELinux policy for the data folder
sudo yum install -y policycoreutils-python-utils # if missing sudo semanage fcontext -a -t var_lib_t "/home/[^/]+/.n8n(/.*)?" sudo restorecon -R -v /home/youruser/.n8n
4.3 AppArmor status check
sudo aa-status | grep n8n # see if a profile is loaded
4.4 Disable AppArmor for testing (do not use in production)
sudo aa-disable /etc/apparmor.d/docker
Production tip: Instead of disabling, write a confined profile that grants r,w on the data folder and unix socket access.
4a. N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS — The New Variable You Need to Know
Starting with recent n8n versions (and required in v2.0), n8n checks that the /home/node/.n8n/config file has strict permissions (0600 — owner read/write only). If the file is too permissive (0644 is the most common case), you will see this warning:
Permissions 0644 for n8n settings file /home/node/.n8n/config are too wide. This is ignored for now, but in the future n8n will attempt to change the permissions automatically. To automatically enforce correct permissions now set N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
This is different from a full EACCES crash — but it is a warning that will become an error in n8n v2.0.
Option A: Let n8n enforce the permissions automatically (recommended)
Add this to your docker-compose.yml environment block or your .env file:
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
n8n will automatically set 0600 on the config file at startup. This is the clean, long-term fix.
Option B: Fix permissions manually
# On the host machine, inside the volume directory chmod 600 n8n_data/config # Or if using a bind mount chmod 600 ~/.n8n/config
Option C: Disable the check (not recommended for production)
If you are on Windows, a platform that does not support Unix file permissions, or a managed hosting environment where you cannot change file permissions:
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false
4b. EACCES After Updating n8n – Why the Error Returns
A very common scenario: n8n was working fine, you ran docker pull n8nio/n8n and docker compose up -d to update, and now you get the EACCES: permission denied error again. This happens because pulling a new image can change the internal UID/GID mapping of the node user, or the new version adds new files it expects to own.
Fix after update:
# Step 1 — bring containers down docker compose down # Step 2 — re-apply ownership (always use 1000:1000 for n8nio/n8n) sudo chown -R 1000:1000 ./n8n_data # or your volume path # Step 3 — bring back up with the new image docker compose up -d # Step 4 — confirm n8n started without errors docker compose logs n8n --tail=30
If you use a named Docker volume instead of a bind mount, run docker volume inspect <volume_name> to find the mount path on the host, then apply the chown there.
4c. EACCES: permission denied, open ‘/home/node/.n8n/crash.journal’
This is a distinct variant of the permission denied error that appears specifically during startup after a crash, a restore, or when n8n detects an unclean shutdown. The error message looks like:
Error: Worker exiting due to an error. Error: EACCES: permission denied, open '/home/node/.n8n/crash.journal'
Why it happens: The crash.journal file is written by a different process (sometimes root) during container crash recovery. When n8n restarts, it tries to open that file as UID 1000 and gets denied.
Fix:
# Fix ownership of the entire .n8n directory (covers config AND crash.journal) sudo chown -R 1000:1000 ./n8n_data # If the crash.journal is blocking startup, remove it (safe — it is only for recovery tracking) sudo rm ./n8n_data/crash.journal # Restart docker compose up -d
Deleting crash.journal is safe. It is not your workflow data — it is just a flag file n8n uses to detect unclean shutdowns. Your workflows and credentials live in the database, not in this file.
4d. Platform-Specific Fixes (Railway, Coolify, Kubernetes, GitHub Actions)
Railway
On Railway, the n8n container crashes on startup with EACCES: permission denied, open '/home/node/.n8n/config' because Railway’s volume mount is created as root before the node user inside the container can write to it. Any chown in your Dockerfile or entrypoint is overwritten by the volume mount.
Fix options on Railway:
- Option 1 (simplest): Set
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=falsein Railway environment variables. Not ideal for production but gets you running. - Option 2 (recommended for PostgreSQL setups): Remove the volume entirely. If you use PostgreSQL as your database, the
/home/node/.n8nfolder only stores transient cache — workflow data lives in Postgres. Without the volume, the container’s ephemeral filesystem is owned bynodeand the error disappears. - Option 3: Override the user in your Railway service config to run as
root— remove or overrideUSER nodein a custom Dockerfile.
Coolify
Coolify deployments often show the “permissions 0644 too wide” warning. The fix is straightforward:
# In Coolify's environment variables for the n8n service, add: N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
If you continue to get a full EACCES crash (not just a warning), SSH into your Coolify host and run chown -R 1000:1000 on the n8n data directory that Coolify has mapped.
Kubernetes (pod crashloop)
n8n pods in Kubernetes crashloop with EACCES when the PersistentVolumeClaim is provisioned with root ownership. Fix with an initContainer that runs as root and resets ownership before the main container starts:
initContainers:
- name: fix-permissions
image: busybox
command: ["sh", "-c", "chown -R 1000:1000 /home/node/.n8n"]
volumeMounts:
- name: n8n-storage
mountPath: /home/node/.n8n
securityContext:
runAsUser: 0 # run as root for the chown
Alternatively, use securityContext.fsGroup on the pod spec to tell Kubernetes to chown the volume to the specified GID at mount time:
spec:
securityContext:
fsGroup: 1000
containers:
- name: n8n
image: n8nio/n8n
GitHub Actions (CI/CD runners)
The EACCES error in GitHub Actions is almost always caused by rootless Docker mode. The Docker socket on the runner lives at $XDG_RUNTIME_DIR/docker.sock rather than /var/run/docker.sock. Fix:
# In your workflow step, before starting n8n:
- name: Fix n8n volume permissions
run: |
mkdir -p ${{ github.workspace }}/n8n-data
sudo chown -R 1000:1000 ${{ github.workspace }}/n8n-data
- name: Start n8n
run: |
docker run -d \
--name n8n \
-p 5678:5678 \
-v ${{ github.workspace }}/n8n-data:/home/node/.n8n \
-u 1000:1000 \
n8nio/n8n
5. Verification Checklist
| ✅ Check | Command / Action | Expected outcome |
|---|---|---|
| Data folder owned by n8n user | ls -ld /path/to/.n8n | user:user ownership |
| Docker socket group‑accessible | ls -l /var/run/docker.sock | srw-rw—- 1 root docker … |
User in docker group |
groups $(whoami) | list includes docker |
| SELinux/AppArmor not blocking | audit2allow -w -a (if logs) | no denials related to n8n |
| n8n process starts | npm start or docker compose up -d | logs show Started n8n without errors |
| Config file permissions not too wide | stat -c “%a” ~/.n8n/config | 600 (not 644) |
| Volume directory owned by UID 1000 | ls -lan ./n8n_data | head -5 | 1000 1000 in owner/group columns |
If any check fails, revisit the corresponding section above.
6. EEFA (Expert‑Level, Real‑World) Notes
| Situation | Why a naïve fix fails |
|---|---|
| Running n8n as a systemd service | Systemd defaults to User=nobody; simple chmod isn’t enough. |
| Docker on a CI/CD runner (rootless mode) | Socket lives at $XDG_RUNTIME_DIR/docker.sock and is owned by the runner’s UID. |
| Multiple n8n instances on a shared host | Sharing the same data directory creates race conditions and permission clashes. |
| Enterprise SELinux enforcing policy | setenforce 0 is prohibited. |
chown in Dockerfile gets overwritten |
Volume mounts happen after the Dockerfile runs — any ownership set in the image is replaced by host filesystem ownership at mount time. |
| Railway / Coolify managed volumes | Platform-managed volumes are created as root. Standard chown instructions assume host SSH access that managed platforms don’t give you. |
Production‑grade solutions
- systemd service: Create a dedicated
n8nsystem user,chown -R n8n:n8n /home/n8n/.n8n, and setUser=n8nin the unit file. - Rootless Docker CI: Export
DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sockand run containers with--user $(id -u):$(id -g). - Separate instances: Allocate a distinct volume per instance and map unique
UID:GID. - SELinux enforcing: Generate a custom module (
audit2allow -M n8n && semodule -i n8n.pp).
Bottom line
A “permission denied” error in n8n almost always stems from mismatched ownership or group rights on either the data directory or the Docker socket. Align UID/GID, fix socket modes, and account for SELinux/AppArmor, and n8n will start reliably on any Linux host or Docker environment.
7. Frequently Asked Questions
Why does my n8n Docker container keep restarting with permission denied?
The container is in a crashloop because the n8n process (running as UID 1000) cannot write to /home/node/.n8n/config — the directory is owned by root. The fix is sudo chown -R 1000:1000 ./n8n_data on your host machine, then docker compose up -d again. This is the most common cause of the restart loop.
What is UID 1000 in Docker and why does n8n use it?
UID 1000 is the numeric user ID of the node user inside the official n8nio/n8n Docker image. Docker containers have their own user namespace — the username inside the container is node, but on the host filesystem it appears as UID 1000. When you map a host directory as a volume, the container’s node user can only write to files and folders owned by UID 1000 on the host.
What does N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS do?
This environment variable controls whether n8n enforces strict file permissions (0600) on its config file at startup. Setting it to true makes n8n automatically fix the permissions itself. Setting it to false suppresses the warning. From n8n v2.0 onwards, strict permissions will be mandatory — so true is the correct setting for any production instance.
Is it safe to delete crash.journal in n8n?
Yes. The crash.journal file inside /home/node/.n8n/ is only a flag file that n8n uses to detect whether the previous session ended cleanly. It does not contain your workflow data, credentials, or execution history. Those are stored in your database (SQLite or PostgreSQL). Deleting crash.journal is safe and will unblock a startup that is failing due to permission denied on that specific file.
How do I fix n8n permission denied on Railway?
On Railway, the easiest fix is to set N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false in your service’s environment variables, or to remove the volume entirely and use PostgreSQL for persistence (since the .n8n directory only stores transient cache when using Postgres). Alternatively, override the container to run as root by removing the USER node directive in a custom Dockerfile.
Why does the permission denied error come back after updating n8n?
When you pull a new n8n image and restart, the container may create new files (e.g., updated config structure, new cache files) that inherit root ownership from how Docker sets up the volume. Always run sudo chown -R 1000:1000 ./n8n_data after pulling a new image and before starting the container. This re-aligns all files to the UID that n8n’s internal process uses.
How do I fix n8n EACCES permission denied in Kubernetes?
Add a securityContext.fsGroup: 1000 to your pod spec. This tells Kubernetes to recursively chown the mounted volume to GID 1000 at startup, so the n8n container’s node user has full write access. Alternatively, use an initContainer running as root to run chown -R 1000:1000 /home/node/.n8n before the main n8n container starts.



