EACCES: permission denied, open ‘/home/node/.n8n/config’ in n8n – Fixed

EACCES permission denied n8n fix guide

Step by Step Guide to solve n8n permission denied error


Fastest fix (90% of cases): Docker created your volume directory as 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

  1. 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
    
  2. Give your user access to the Docker socket
    sudo usermod -aG docker $(whoami)   # add to docker group
    newgrp docker                       # refresh current session
    
  3. Ensure the socket mode is correct
    sudo chmod 660 /var/run/docker.sock
    sudo chgrp docker /var/run/docker.sock
    
  4. Restart n8n (npm start or docker 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

🔍 Why UID 1000 specifically?
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
⚠️ Production warning: Disabling this check leaves your encryption key and credentials stored in a world-readable file. Only disable on isolated/internal environments, never on public-facing servers.

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=false in 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/.n8n folder only stores transient cache — workflow data lives in Postgres. Without the volume, the container’s ephemeral filesystem is owned by node and the error disappears.
  • Option 3: Override the user in your Railway service config to run as root — remove or override USER node in 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 n8n system user, chown -R n8n:n8n /home/n8n/.n8n, and set User=n8n in the unit file.
  • Rootless Docker CI: Export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock and 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.

Leave a Comment

Your email address will not be published. Required fields are marked *