Docker Socket Permissions on Synology#
When Homepage (or any container) attempts to connect to /var/run/docker.sock on Synology Container Manager, it may hit an EACCES error even when the socket is mounted correctly and other containers (e.g., Uptime Kuma) access it without issue. This article explains why, and what to do about it.
How Homepage Connects to the Docker Socket#
Homepage uses dockerode v5 to communicate with Docker. By default on Linux, it connects to /var/run/docker.sock via a Unix socket . When a named server is configured in docker.yaml, it reads that entry and passes it to dockerode on every request . The docker.yaml configuration is read on each dashboard load, which means a permission problem hits every page view.
The official docs state explicitly: "In order to use the socket directly, homepage must be running as root."
The Homepage image starts as root, but the docker-entrypoint.sh will drop privileges to the user specified by PUID/PGID using su-exec before the app process starts. If PUID is non-zero, the Node.js process runs as that UID.
Why Synology Differs from Standard Linux#
On a typical Linux Docker installation, the docker socket is owned by a docker group (commonly GID 999), and users can access it by joining that group. On Synology, the socket is owned by root:root with mode 0660 :
srw-rw---- 1 root root 0 Aug 30 20:59 /var/run/docker.sock
This means access requires either UID 0 (root) or membership in GID 0 (root group). A container running as a non-root user with a non-zero PGID — even one with full volume mounts — will be denied.
Why other containers work: Tools like Uptime Kuma typically run as root by default or bundle their own socket client differently. The issue is container-specific, not host-wide .
Common Trigger: PUID/PGID with Root Socket#
The most frequent cause of EACCES on Synology is setting PUID and PGID in the compose file while relying on the direct socket mount. For example :
environment:
- PUID=1028
- PGID=100
volumes:
- /var/run/docker.sock:/var/run/docker.sock
With this configuration, docker-entrypoint.sh drops to UID 1028, GID 100 . Neither of those can connect to a root:root socket — producing EACCES. Setting PUID=0 (the default when PUID is unset) skips the privilege drop and allows socket access.
Secondary Cause: dockerode v4 → v5 Compatibility#
Homepage uses dockerode v5 , bumped from v4, which updated the underlying docker-modem internals. In some reported cases, the EACCES error persists even when the container is confirmed running as root (verified via docker exec homepage id). This may indicate that how v5 opens Unix socket connections behaves differently under Synology Container Manager, independently of file permissions . This remains under investigation; if basic permission fixes don't resolve the issue, the socket proxy (Option 2 below) is a reliable workaround.
Diagnostics#
Before changing configuration, run these checks on the Synology host or in the container:
-
Verify socket path and permissions on the host:
ls -l /var/run/docker.sockConfirm it exists, is
root:root, and hasn't been relocated (some DSM versions use/var/packages/ContainerManager/var/docker.sock) . -
Check the effective runtime user inside the container:
docker exec homepage idIf the output is not
uid=0(root), the privilege drop is active and PUID/PGID is the cause. -
Test with a bare container (rules out host-wide confinement):
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock alpine sh -c "apk add --no-cache docker-cli && docker ps"
Resolutions#
Option 1: Run Homepage as Root (Direct Socket, Simplest)#
Remove PUID/PGID from the environment (they default to 0) or explicitly set PUID=0. Do not set user: in the compose file. See the official docs for the full compose example.
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
volumes:
- /path/to/config:/app/config
- /var/run/docker.sock:/var/run/docker.sock
Then in docker.yaml:
my-docker:
socket: /var/run/docker.sock
Option 2: Use a Docker Socket Proxy (Recommended for Non-Root)#
The socket proxy approach lets Homepage connect over TCP without needing root, and limits API surface to read-only container queries. Deploy ghcr.io/tecnativa/docker-socket-proxy on the same host with the socket mounted, then point Homepage at it over HTTP:
my-docker:
host: dockerproxy
port: 2375
This is the recommended method when you want to avoid running Homepage as root .
Option 3: Remove :ro from the Socket Mount#
Read-only bind mounts of Unix sockets have caused connection failures in some Synology setups even for root containers. If the socket is mounted with :ro, try removing that flag .
Key Source Files#
| File | Relevance |
|---|---|
| docker-entrypoint.sh | PUID/PGID privilege-drop logic (lines 5–7, 72–77) |
| src/utils/config/docker.js | Socket/host connection resolution |
| Dockerfile | Image starts as root, su-exec installed |
| Docker config docs | Official docker.yaml and socket-proxy setup |
| GitHub Discussion #7140 | Synology-specific EACCES report and investigation |