Installer: reliably add peardock user to docker group
Release rolling / release (push) Successful in 9m12s

Create the docker group when missing, usermod -aG with verification,
align socket group/mode when needed, and set systemd Group and
SupplementaryGroups so the service can access the Docker socket.
This commit is contained in:
Raven Scott
2026-07-11 15:35:20 -04:00
parent 2e51c49526
commit a8ee0f19b7
+106 -10
View File
@@ -260,6 +260,101 @@ asset_url() {
echo "${GITEA_URL}/${OWNER}/${REPO}/releases/download/${TAG}/${name}"
}
# ─── docker group / socket access ───────────────────────────────────────────
# Engine socket is typically root:docker mode 660. peardock.service runs as
# User=peardock and must be a docker group member (SupplementaryGroups=docker).
ensure_peardock_docker_group() {
local sock="${DOCKER_HOST:-}"
local grp="docker"
# Normalize DOCKER_HOST=unix:///var/run/docker.sock → path
if [[ -z "$sock" || "$sock" == unix://* || "$sock" == /* ]]; then
sock="${sock#unix://}"
sock="${sock:-/var/run/docker.sock}"
else
# tcp://… — group membership not required for local socket, but still useful
sock="/var/run/docker.sock"
fi
if [[ ! -S "$sock" ]]; then
warn "Docker socket not found at ${sock}"
warn "Install/start Docker, then re-run: sudo usermod -aG docker peardock && sudo systemctl restart peardock"
return 0
fi
# Prefer the socket's group when it is not root
local sock_grp
sock_grp="$(stat -c '%G' "$sock" 2>/dev/null || stat -f '%Sg' "$sock" 2>/dev/null || echo docker)"
if [[ -n "$sock_grp" && "$sock_grp" != "root" ]]; then
grp="$sock_grp"
fi
if ! getent group "$grp" >/dev/null 2>&1; then
log "Creating group '${grp}' for Docker socket access…"
if command -v groupadd >/dev/null 2>&1; then
run_root groupadd --system "$grp" 2>/dev/null || run_root groupadd "$grp"
elif command -v addgroup >/dev/null 2>&1; then
run_root addgroup --system "$grp" 2>/dev/null || run_root addgroup "$grp"
else
die "Cannot create group '${grp}' (need groupadd/addgroup)"
fi
fi
# Ensure socket is group-accessible when possible
local mode
mode="$(stat -c '%a' "$sock" 2>/dev/null || echo "")"
if [[ -n "$mode" && "$mode" != "666" && "$mode" != "660" && "$mode" != "620" ]]; then
log "Setting ${sock} group to ${grp}, mode 660…"
run_root chgrp "$grp" "$sock" 2>/dev/null || true
run_root chmod 660 "$sock" 2>/dev/null || true
else
run_root chgrp "$grp" "$sock" 2>/dev/null || true
fi
log "Adding user peardock to group '${grp}'…"
if command -v usermod >/dev/null 2>&1; then
run_root usermod -aG "$grp" peardock
elif command -v gpasswd >/dev/null 2>&1; then
run_root gpasswd -a peardock "$grp"
elif command -v adduser >/dev/null 2>&1; then
run_root adduser peardock "$grp" 2>/dev/null || run_root adduser peardock "$grp"
else
die "Cannot add peardock to ${grp} (need usermod/gpasswd/adduser)"
fi
# Verify membership (id may need a moment; read /etc/group directly)
if getent group "$grp" | grep -qE '(^|,)peardock(,|$)'; then
ok "peardock is a member of group '${grp}'"
else
# usermod sometimes succeeds but getent lag — check id -nG as root
if run_root id -nG peardock 2>/dev/null | tr ' ' '\n' | grep -qx "$grp"; then
ok "peardock is a member of group '${grp}'"
else
die "Failed to add peardock to group '${grp}'. Run: sudo usermod -aG ${grp} peardock"
fi
fi
# Prove socket is reachable as peardock (sg runs with supplementary group)
if command -v sg >/dev/null 2>&1; then
if run_root sg "$grp" -c "runuser -u peardock -- test -r '$sock' -a -w '$sock'" 2>/dev/null \
|| run_root runuser -u peardock -- sg "$grp" -c "test -r '$sock' -a -w '$sock'" 2>/dev/null; then
ok "Docker socket ${sock} is read/write for peardock (via ${grp})"
else
# fallback: test as peardock with full group list after usermod
if run_root su -s /bin/sh peardock -c "test -r '$sock' -a -w '$sock'" 2>/dev/null; then
ok "Docker socket ${sock} is accessible to peardock"
else
warn "Could not verify socket RW as peardock yet — restart Docker after group change if needed"
warn " sudo systemctl restart docker && sudo systemctl restart peardock"
fi
fi
fi
# Export for unit file generation
PEARDOCK_DOCKER_GROUP="$grp"
export PEARDOCK_DOCKER_GROUP
}
# ─── server install ─────────────────────────────────────────────────────────
install_server() {
local host="$1" version="$2"
@@ -313,14 +408,15 @@ install_server() {
|| run_root useradd --system --home "$SERVER_DIR" --shell /bin/false peardock
elif command -v adduser >/dev/null 2>&1; then
run_root adduser --system --home "$SERVER_DIR" --shell /usr/sbin/nologin --no-create-home peardock || true
fi
fi
# docker group
if getent group docker >/dev/null 2>&1; then
run_root usermod -aG docker peardock 2>/dev/null || true
else
warn "docker group not found — ensure peardock can access the Docker socket"
die "Cannot create peardock user (need useradd or adduser)"
fi
fi
id peardock >/dev/null 2>&1 || die "peardock user was not created"
# Docker socket access: peardock must be in the docker group (mode 660 root:docker).
ensure_peardock_docker_group
run_root chown -R peardock:peardock "$SERVER_DIR" 2>/dev/null || run_root chown -R peardock "$SERVER_DIR"
# systemd unit
@@ -344,15 +440,15 @@ RestartSec=5
TimeoutStartSec=30
TimeoutStopSec=30
User=peardock
# Prefer docker group when present
Group=docker
SupplementaryGroups=docker
# Primary + supplementary docker group so /var/run/docker.sock (root:docker 660) works
Group=${PEARDOCK_DOCKER_GROUP:-docker}
SupplementaryGroups=${PEARDOCK_DOCKER_GROUP:-docker}
NoNewPrivileges=true
PrivateTmp=true
Environment=NODE_ENV=production
EnvironmentFile=-${SERVER_DIR}/.env
# Docker socket + state
ReadWritePaths=${SERVER_DIR}
ReadWritePaths=${SERVER_DIR} /var/run/docker.sock /run/docker.sock
[Install]
WantedBy=multi-user.target