Fix the “Error: EACCES: permission denied, mkdir ‘/home/node/.n8n’” when running n8n in Docker inside an LXC on Proxmox VE
Learn how to fix the n8n EACCES permission denied error when running Docker inside an LXC on Proxmox with a simple chown fix.
Before you start: versions, package names and storage identifiers change over time. Check the commands against the official documentation for your setup before running them, especially anything that creates, deletes or overwrites data.
n8n exits immediately after docker compose up and the log ends with:
Error: EACCES: permission denied, mkdir '/home/node/.n8n'
Nothing is corrupted and Docker is working. The container cannot write to the directory you mounted, because of a user ID mismatch between the image and the host.
Why it happens
The n8n image does not run as root. It runs as a user called node, with UID and GID 1000:
$ docker exec n8n id
uid=1000(node) gid=1000(node) groups=1000(node)
When you bind-mount a host directory like ./n8n_data, Docker passes it through with its host ownership intact. If you created that directory as root — which is what happens when you run mkdir in a root shell, as most people do inside an LXC — it arrives owned by 0:0. UID 1000 then has no write permission, mkdir fails, and n8n exits before it can start.
The directory matters because it holds n8n’s SQLite database and, more importantly, the encryption key for your stored credentials.
Why an LXC makes this more likely
In an unprivileged Proxmox container, root inside the container is already mapped to a high-numbered unprivileged UID on the Proxmox host. That mapping is invisible from inside, so ownership can look correct at one layer and still be wrong at another. Judge it from inside the container — that is the view Docker acts on.
Fix 1: correct the ownership (keeping the bind mount)
Stop the stack, fix ownership, start it again:
docker compose down
sudo chown -R 1000:1000 ./n8n_data
ls -ldn ./n8n_data
docker compose up -d
Use ls -ldn rather than ls -ld: the -n flag prints numeric IDs. You want to see 1000 1000:
drwxr-xr-x 4 1000 1000 4096 Sep 20 05:40 ./n8n_data
With plain ls -ld you may see a host username that happens to own UID 1000, which tells you nothing useful about what the container sees.
Fix 2: use a named volume instead (recommended)
The mismatch only exists because you chose a host path. A named volume has no pre-existing host ownership, so Docker initialises it with the image’s own user and the problem cannot occur:
services:
n8n:
image: docker.n8n.io/n8nio/n8n:latest
restart: unless-stopped
ports:
- "5678:5678"
environment:
- GENERIC_TIMEZONE=Europe/Rome
- TZ=Europe/Rome
- N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
volumes:
- n8n_data:/home/node/.n8n
volumes:
n8n_data:
This is what the official n8n Docker instructions use (docker volume create n8n_data, then -v n8n_data:/home/node/.n8n).
The trade-off is real, so choose deliberately rather than by default:
Bind mount (./n8n_data) |
Named volume | |
|---|---|---|
| Permission mismatch | Likely; needs chown |
Cannot happen |
| Finding the files | Right there in your project directory | Under /var/lib/docker/volumes/ |
| Backing up | Copy the directory | Needs a helper container or docker run --volumes-from |
If you already have data in a bind mount, do not just switch the Compose file to a named volume — you will get an empty n8n and your credentials will be unreadable. Copy the contents across first.
Do not “fix” it by running as root
Adding user: root to the service makes the error disappear, which is why it gets suggested. It also discards the image’s privilege separation, and it rewrites the directory’s ownership to 0:0, so if you later revert to the default user you land back on the same error with a directory that is now harder to reason about. Set N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true and fix the ownership instead.
Verify
docker compose ps
docker compose logs -f n8n
A healthy start ends with a line reporting n8n listening on port 5678. Then load http://<container-ip>:5678. On a fresh instance it asks you to create an owner account — that is expected, and there is no supported way to disable it since n8n 1.0.
If the container now starts but the port does not answer, that is a different problem: see fixing “address already in use” on port 5678.
Sources
- n8n docs — Install with Docker (named volume,
/home/node/.n8n,N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS) - Docker docs — Volumes (named volumes vs bind mounts and ownership behavior)
- Proxmox VE docs — Linux Container (unprivileged UID mapping)
Related reading
Some links on this page may be affiliate links. If you buy through them we may earn a commission at no extra cost to you. See our affiliate disclosure.