-
Notifications
You must be signed in to change notification settings - Fork 22
Expand file tree
/
Copy pathdocker-entrypoint.sh
More file actions
executable file
·103 lines (96 loc) · 4.35 KB
/
Copy pathdocker-entrypoint.sh
File metadata and controls
executable file
·103 lines (96 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/bin/sh
# docker-entrypoint.sh — UID/GID remapping shim for the pad container.
#
# Allows operators to run pad as their host's preferred uid/gid by setting
# PUID and PGID env vars at container start. Mainly for Unraid users
# (default 99/100 = nobody:users) but useful on Synology / TrueNAS / any
# Docker host where the appdata volume is owned by something other than
# uid 1000.
#
# Pattern adopted from LinuxServer.io. See TASK-1168 / PLAN-1166.
#
# Compatibility: /bin/sh (BusyBox-compatible). No bash-isms.
set -e
# Pass-through path: caller specified a uid via `docker run --user`. They
# know what they want; we don't try to outsmart them. No chown, no
# privilege drop — just exec the target program directly.
if [ "$(id -u)" != "0" ]; then
exec "$@"
fi
# Remap path: container started as root (the default).
#
# Use ${VAR-default} (no colon), not ${VAR:-default}. The colon form
# substitutes the default when VAR is unset OR empty, which would silently
# accept `docker run -e PUID= -e PGID=` and mask a real operator typo.
# The colon-less form only substitutes when VAR is unset, so an explicit
# empty value falls through to validation and is rejected.
PUID="${PUID-99}"
PGID="${PGID-100}"
# Validate: must be positive integers. Rejecting 0 explicitly is critical
# — PUID=0 (root) or PGID=0 (root group) would defeat the unprivileged-
# user invariant the whole shim exists to enforce. Empty / non-numeric
# also fail loudly so an operator typo doesn't silently default.
case "$PUID" in
''|*[!0-9]*)
echo "docker-entrypoint: PUID must be a positive integer, got '$PUID'" >&2
exit 1
;;
esac
case "$PGID" in
''|*[!0-9]*)
echo "docker-entrypoint: PGID must be a positive integer, got '$PGID'" >&2
exit 1
;;
esac
if [ "$PUID" = "0" ]; then
echo "docker-entrypoint: PUID=0 (root) is rejected — set a non-zero uid to keep pad unprivileged" >&2
exit 1
fi
if [ "$PGID" = "0" ]; then
echo "docker-entrypoint: PGID=0 (root group) is rejected — set a non-zero gid to keep pad unprivileged" >&2
exit 1
fi
# Remap the in-image `pad` user/group only when values differ — skips
# the noisy "id changed" log entry on every warm restart in the steady
# state.
#
# Use `id -u/-g pad` (BusyBox supports both flags) rather than
# `getent group pad`: getent lives in the optional `musl-utils` package
# on alpine, NOT in BusyBox's default applet list, so the entrypoint
# would crash before chown/exec on a fresh `apk add` install that
# didn't include it.
current_uid="$(id -u pad)"
current_gid="$(id -g pad)"
if [ "$current_gid" != "$PGID" ]; then
groupmod -o -g "$PGID" pad
fi
if [ "$current_uid" != "$PUID" ] || [ "$current_gid" != "$PGID" ]; then
# Combined -u + -g ensures the user's /etc/passwd primary-gid field
# is updated to PGID even when only the group renumber happened.
# `groupmod` alone changes the group's gid but leaves the user's
# /etc/passwd line referencing the OLD gid number — su-exec would
# then launch pad with the wrong process gid.
usermod -o -u "$PUID" -g "$PGID" pad
fi
# Always chown -R the data directory.
#
# Statting only `/data` itself is unsafe: a user who restored a backup
# tarball might have /data owned by the target uid but /data/pad.db,
# /data/encryption.key, or /data/attachments/* owned differently, and a
# shallow check would skip the recursive chown — leaving pad unable to
# read its own DB. The few seconds of chown cost on warm restart with
# large attachment stores is the correct trade for guaranteed correctness.
#
# Warn-and-continue (not fail-fast). chown -R can fail on individual
# files for non-fatal reasons (immutable bits, root-squashed NFS,
# partial permission gaps). Refusing to start pad over any single
# failed file would lock the operator out of an otherwise-fine /data.
# chown's per-file errors hit stderr already (visible in `docker logs`);
# the trailing aggregated warning surfaces a single clear "investigate
# this" line. The `||` form is set-e-safe.
chown -R "$PUID:$PGID" /data \
|| echo "docker-entrypoint: warning: chown -R /data had errors (see above). pad will start anyway; some files may not be writable." >&2
# Drop privileges and exec. su-exec replaces the shell process so signals
# (SIGTERM, SIGINT) propagate to the pad process correctly — without
# this, docker stop's SIGTERM would hit the shell instead of pad.
exec su-exec pad "$@"