Dosu LogoDosu Logo
Ask
Join our Discord
homepagePublic
homepage
Documentshomepage
Docker Socket Permissions on Synology
Docker Socket Permissions on Synology
Type
Topic
Status
Published
Created
Sep 13, 2026
Updated
Sep 13, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

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:

  1. Verify socket path and permissions on the host:

    ls -l /var/run/docker.sock
    

    Confirm it exists, is root:root, and hasn't been relocated (some DSM versions use /var/packages/ContainerManager/var/docker.sock) .

  2. Check the effective runtime user inside the container:

    docker exec homepage id
    

    If the output is not uid=0(root), the privilege drop is active and PUID/PGID is the cause.

  3. 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#

FileRelevance
docker-entrypoint.shPUID/PGID privilege-drop logic (lines 5–7, 72–77)
src/utils/config/docker.jsSocket/host connection resolution
DockerfileImage starts as root, su-exec installed
Docker config docsOfficial docker.yaml and socket-proxy setup
GitHub Discussion #7140Synology-specific EACCES report and investigation
Documents
Background Image Rendering
settings
CrowdSec Widget
Docker Socket Permissions on Synology
Dockerode Integration
Ghostfolio Widget Currency Handling
Jellyfin Widget API Compatibility
jellyfin
OIDC Authentication
Quick Launch Click Handling
Widget Proxy Request Handling
customapi
YAML Configuration Loading
CONTRIBUTING
README
adguard-home
apcups
api
arcane
argocd
atsumeru
audiobookshelf
authentik
autobrr
azuredevops
backrest
bazarr
beszel
booklore
bookmarks
bookorbit
caddy
calendar
calibre-web
changedetectionio
channelsdvrserver
checkmk
cloudflared
coin-market-cap
component
coverage
crowdsec
custom-css-js
customapi
datetime
deluge
develancacheui
diskstation
dispatcharr
docker
docker
dockhand
downloadstation
duplicati
emby
esphome
evcc
feed
filebrowser
fileflows
firefly
flood
freshrss
frigate
fritzbox
gamedig
gatus
getting-started
ghostfolio
gitea
gitlab
glances
glances
gluetun
gotify
grafana
greeting
hdhomerun
headscale
healthchecks
homeassistant
homebox
homebridge
homepage-move
iframe
immich
index
index
index
index
index
index
index
index
index
info-widgets
jackett
jdownloader
jellystat
k8s
karakeep
kavita
komga
komodo
kopia
kubernetes
kubernetes
lidarr
linkwarden
logo
longhorn
lubelogger
mailcow
maintainerr
mastodon
mcp
mealie
medusa
metadata
mikrotik
minecraft
miniflux
mjpeg
moonraker
mylar
myspeed
navidrome
netalertx
netdata
nextcloud
nextdns
nginx-proxy-manager
ntfy
nzbget
octoprint
omada
ombi
opendtu
openmediavault
openmeteo
openweathermap
openwrt
opnsense
pangolin
paperlessngx
peanut
pfsense
photoprism
pihole
plantit
plex
plex-tautulli
portainer
prometheus
prometheusmetric
prowlarr
proxies
proxmox
proxmox
proxmoxbackupserver
pterodactyl
pulse
pyload
qbittorrent
qnap
qui
radarr
readarr
resources
romm
rutorrent
sabnzbd
scrutiny
search
seerr
services
slskd
sonarr
source
sparkyfitness
speedtest-tracker
sponsors
spoolman
sportarr
stash
stocks
stocks
suwayomi
swagdashboard
syncthing
syncthing-relay-server
tailscale
tandoor
tdarr
technitium
tracearr
traefik
translations
translations
transmission
trilium
truenas
tubearchivist
tutorial
unifi-controller
unifi-drive
unifi_controller
unmanic
unraid
unraid
uptime-kuma
uptimerobot
urbackup
vikunja
wallos
watchtower
wgeasy
whatsupdocker
xteve
yourspotify
zabbix