mirror of
https://github.com/karatektus/pl_mail.git
synced 2026-10-25 01:54:10 +00:00
Let the image run as a user that is not root
Nothing here needs root at run time, and a platform that chooses the uid
itself and drops every capability could not start it. Three things were
in the way, found by running it as uid 568 with nothing granted:
frankenphp carried cap_net_bind_service as a file capability, and
a process without that capability may not execute such
a binary at all. Removed: in a container the
unprivileged port range starts at 0 anyway.
var/ cache, log and share were root's. Writable by anyone
now, since the uid is not known when the image is built.
/data, /config root's as well, so the hub could not open its database
on a fresh volume. Same answer.
The entrypoint's setfacl step is skipped for a non-root user, who can
grant nothing and has no name for whoami to print.
Installs that run as root, which is every compose file here, are
unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
889aeec925
commit
1ff8c81f4b
2 files changed
+42
-5
No files matched your search
+31
-1
@@ -100,6 +100,28 @@ COPY --link frankenphp/Caddyfile /etc/frankenphp/Caddyfile
|
||||
COPY --link --from=mercure_upstream /usr/bin/caddy /usr/local/bin/mercure
|
||||
COPY --link --from=mercure_upstream /etc/caddy/Caddyfile /etc/mercure/Caddyfile
|
||||
|
||||
# Runnable as a user that is not root, and not any particular one.
|
||||
#
|
||||
# Nothing here needs root at run time, and a platform that picks the uid itself
|
||||
# (the TrueNAS catalogue runs apps as 568 by default, with every capability
|
||||
# dropped) found two things in the way before PHP ever started:
|
||||
#
|
||||
# - The FrankenPHP binary carries cap_net_bind_service as a FILE capability.
|
||||
# A process that does not hold that capability may not execute such a file
|
||||
# at all: "exec: frankenphp: Operation not permitted". It is there so a
|
||||
# non-root user can bind port 80 on a bare host; in a container the
|
||||
# unprivileged port range starts at 0, so it buys nothing and costs the
|
||||
# start. Root keeps binding 80 exactly as before.
|
||||
# - /data and /config, where the web server and the hub keep their state,
|
||||
# belong to root. A new volume mounted there copies the directory's
|
||||
# permissions, so the hub died on "open /data/caddy/mercure.db: permission
|
||||
# denied". Writable by anyone, because the uid is not known here; there is
|
||||
# one tenant in this container.
|
||||
RUN set -eux; \
|
||||
setcap -r /usr/local/bin/frankenphp; \
|
||||
mkdir -p /data/caddy /config/caddy; \
|
||||
chmod -R a+rwX /data /config
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint"]
|
||||
|
||||
# /healthz, not Caddy's metrics port. The old probe answered as soon as the web
|
||||
@@ -195,4 +217,12 @@ RUN set -eux; \
|
||||
composer run-script --no-dev post-install-cmd; \
|
||||
php bin/console tailwind:build --minify; \
|
||||
php bin/console asset-map:compile; \
|
||||
chmod +x bin/console; sync;
|
||||
chmod +x bin/console; \
|
||||
# The directories PHP writes at run time, for whichever user that turns out
|
||||
# to be — see the note on running without root in the base stage. var/ itself
|
||||
# as well, not recursively: the default secrets directory is created in it
|
||||
# on first start.
|
||||
mkdir -p var/share; \
|
||||
chmod a+rwx var; \
|
||||
chmod -R a+rwX var/cache var/log var/share; \
|
||||
sync;
|
||||
@@ -257,11 +257,18 @@ if [ "$1" = 'frankenphp' ] || [ "$1" = 'php' ] || [ "$1" = 'bin/console' ]; then
|
||||
# TrueNAS layout set off on it at once.
|
||||
mkdir -p var/cache var/log
|
||||
|
||||
if ! setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var/cache var/log 2>/dev/null; then
|
||||
echo 'Note: POSIX ACLs are not supported on this filesystem; skipping setfacl for var/cache and var/log.'
|
||||
fi
|
||||
# Root only. As any other user there is nobody to grant anything to — the
|
||||
# process can only change ACLs on what it owns, and a uid a platform picked
|
||||
# has no name for `whoami` to answer with ("cannot find name for user ID
|
||||
# 568", twice, on every start). The image makes both directories writable
|
||||
# for that case; see the Dockerfile.
|
||||
if [ "$(id -u)" = '0' ]; then
|
||||
if ! setfacl -R -m u:www-data:rwX -m u:"$(whoami)":rwX var/cache var/log 2>/dev/null; then
|
||||
echo 'Note: POSIX ACLs are not supported on this filesystem; skipping setfacl for var/cache and var/log.'
|
||||
fi
|
||||
|
||||
setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var/cache var/log 2>/dev/null || true
|
||||
setfacl -dR -m u:www-data:rwX -m u:"$(whoami)":rwX var/cache var/log 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
exec docker-php-entrypoint "$@"
|
||||
Reference in new issue
Block a user