From 52ff7f8f33c26afd937bec59f9d50eeaf5873671 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 7 Jan 2022 22:32:49 +0100 Subject: [PATCH] redo containers so they are fully rootless no more annoying useradd/userdel! allows read only containers! smaller images! doesn't crash on restart without recreating anymore! (oops) configurable children / spare servers! --- docker-compose.yml | 8 ++++--- nginx_web/Dockerfile | 7 +++--- nginx_web/entrypoint.sh | 45 ++++++-------------------------------- nginx_web/nginx.conf | 20 +++++++++++------ php_fpm/Dockerfile | 27 ++++++++++++----------- php_fpm/entrypoint.sh | 48 +++++++++++------------------------------ 6 files changed, 55 insertions(+), 100 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8d4fa12..63bb361 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,8 +11,9 @@ services: target: /data # environment: # Change this if you rename the php container # PHP_FPM: php:9000 + # user: 'youruser' depends_on: [php] - restart: always + # restart: always php: image: namelessmc/php:v2-pr12 @@ -20,7 +21,8 @@ services: - type: bind # same as web container source: ./web target: /data - restart: always + # user: 'youruser' + # restart: always db: image: mariadb @@ -33,4 +35,4 @@ services: MYSQL_USER: nameless MYSQL_PASSWORD: nameless MYSQL_DATABASE: nameless - restart: always + # restart: always diff --git a/nginx_web/Dockerfile b/nginx_web/Dockerfile index fdfc488..099bfef 100644 --- a/nginx_web/Dockerfile +++ b/nginx_web/Dockerfile @@ -2,14 +2,13 @@ FROM nginx:alpine ENV PHP_FPM="php:9000" -ENV WWW_DATA_UID=33 WWW_DATA_GID=33 - -RUN apk add --no-cache shadow - RUN find /etc/nginx -type f -not -name 'mime.types' -not -name 'fastcgi_params' -delete && \ rm -rf conf.d modules COPY nginx.conf /etc/nginx COPY entrypoint.sh / +# The www-data user has uid 33 on Debian/Ubuntu which is what most people are used to +USER 33 + ENTRYPOINT [ "sh", "/entrypoint.sh" ] diff --git a/nginx_web/entrypoint.sh b/nginx_web/entrypoint.sh index 0cf954e..90bb275 100644 --- a/nginx_web/entrypoint.sh +++ b/nginx_web/entrypoint.sh @@ -1,46 +1,13 @@ #!/bin/sh -if [ -n "$(getent passwd "$WWW_DATA_UID")" ] -then - USERNAME=$(getent passwd "$WWW_DATA_UID" | cut -d: -f1) - echo "Deleting user $USERNAME which already uses UID $WWW_DATA_UID" - userdel "$USERNAME" -else - echo "UID $WWW_DATA_UID not in use" +if [ -z "$(find /data -user "$(id -u)" -print -prune -o -prune)" ]; then + echo "/data is not owned by the correct user, we are uid $(id -u)" + exit 1 fi -if [ -n "$(getent group "$WWW_DATA_GID")" ] -then - GROUPNAME=$(getent passwd "$WWW_DATA_GID" | cut -d: -f1) - echo "Deleting group $GROUPNAME which already uses GID $WWW_DATA_GID" - groupdel "$GROUPNAME" -else - echo "GID $WWW_DATA_GID not in use" -fi - -if [ -n "$(getent group www-data)" ] -then - echo "Modifying existing www-data group, setting GID to $WWW_DATA_GID" - groupmod -g "$WWW_DATA_GID" www-data -else - echo "Adding www-data group with GID $WWW_DATA_GID" - groupadd -g "$WWW_DATA_GID" www-data -fi - -if [ -n "$(getent passwd www-data)" ] -then - echo "Modifying existing www-data user, setting GID to $WWW_DATA_GID" - usermod -g "$WWW_DATA_GID" www-data -else - echo "Adding www-data user with UID $WWW_DATA_UID and GID $WWW_DATA_GID" - getent passwd 1000 - useradd -u "$WWW_DATA_UID" -g "$WWW_DATA_GID" www-data -fi - -cat > /etc/nginx/php.conf << EOL -upstream php-handler { - server ${PHP_FPM}; -} +cat > /tmp/fastcgi-pass.conf << EOL +set \$upstream "${PHP_FPM}"; +fastcgi_pass \$upstream; EOL exec nginx -g "daemon off;" diff --git a/nginx_web/nginx.conf b/nginx_web/nginx.conf index 8fbb40c..fac1ad5 100644 --- a/nginx_web/nginx.conf +++ b/nginx_web/nginx.conf @@ -1,4 +1,5 @@ -user "www-data"; +# We're running rootless so we don't have permission to write to /var/run/nginx.pid +pid /tmp/nginx.pid; events { worker_connections 1024; @@ -8,10 +9,17 @@ http { access_log /dev/stdout; error_log /dev/stdout; + # Default directory is /var/cache/nginx/ but we're running rootless so that won't work + proxy_temp_path /tmp/proxy_temp; + client_body_temp_path /tmp/client_temp; + fastcgi_temp_path /tmp/fastcgi_temp; + uwsgi_temp_path /tmp/uwsgi_temp; + scgi_temp_path /tmp/scgi_temp; + include mime.types; default_type application/octet-stream; - include php.conf; + resolver 127.0.0.11 valid=10s; server { listen 80 default_server; @@ -25,7 +33,7 @@ http { # Remove X-Powered-By, which is an information leak fastcgi_hide_header X-Powered-By; - root /data; + root /data/; location / { try_files $uri $uri/ /index.php?route=$uri&$args; @@ -42,14 +50,14 @@ http { } location ~ \.php$ { - try_files $uri = 404; + try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; - fastcgi_pass php-handler; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include /tmp/fastcgi-pass.conf; include fastcgi_params; } - client_max_body_size 0; + client_max_body_size 512M; # This matches our default max body size for php-fpm } } diff --git a/php_fpm/Dockerfile b/php_fpm/Dockerfile index 0fa7528..7cda7af 100644 --- a/php_fpm/Dockerfile +++ b/php_fpm/Dockerfile @@ -5,23 +5,19 @@ ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/do RUN chmod +x /usr/local/bin/install-php-extensions && \ install-php-extensions @composer gd pdo_mysql mysqli zip exif -ENV WWW_DATA_UID=33 WWW_DATA_GID=33 - -RUN apk add --no-cache shadow - +# php-fpm loads configuration in alphabetical order so prefix with zz- RUN { \ echo "upload_max_filesize = 512M"; \ echo "post_max_size = 512M"; \ echo "max_input_time = 300"; \ echo "max_execution_time = 300"; \ - } > /usr/local/etc/php/conf.d/nameless.ini && \ - { \ - echo "[www]"; \ - echo "pm.max_children = 32"; \ - echo "pm.start_servers = 1"; \ - echo "pm.min_spare_servers = 1"; \ - echo "pm.max_spare_servers = 4" ; \ - } > /usr/local/etc/php-fpm.d/zz-nameless.conf + } > /usr/local/etc/php/conf.d/zz-nameless.ini +# We want to add some additional configuration at runtime, but the entrypoint script doesn't run as root and only has +# permission to write to /tmp. So, we create a symlink that doesn't exist yet but will before php-fpm is started. +# This shouldn't allow arbritrary config modifications even though /tmp is publicly writable: a container restart is +# required to load new configuration and restarting the container overwrites this config file. +# A bit weird, I know, but it's the best I could come up with. Suggestions welcome! +RUN ln -s /tmp/additional-php-fpm-settings.conf /usr/local/etc/php-fpm.d/zz-nameless.conf ADD entrypoint.sh / @@ -37,4 +33,11 @@ ENV NAMELESS_PATH_HIDE=true # Enable friendly URLs and hide the option by default, they work fine with the included configuration and there is no reason to turn it off. ENV NAMELESS_FRIENDLY_URLS=true NAMELESS_FRIENDLY_URLS_HIDE=true +ENV PHP_MAX_CHILDREN=32 \ + PHP_MIN_SPARE_SERVERS=2 \ + PHP_MAX_SPARE_SERVERS=4 + +# The www-data user has uid 33 on Debian/Ubuntu which is what most people are used to +USER 33 + ENTRYPOINT [ "sh", "/entrypoint.sh" ] diff --git a/php_fpm/entrypoint.sh b/php_fpm/entrypoint.sh index d38f45b..7c40c40 100644 --- a/php_fpm/entrypoint.sh +++ b/php_fpm/entrypoint.sh @@ -1,41 +1,9 @@ #!/bin/sh set -e -if [ -n "$(getent passwd "$WWW_DATA_UID")" ] -then - USERNAME=$(getent passwd "$WWW_DATA_UID" | cut -d: -f1) - echo "Deleting user $USERNAME which already uses UID $WWW_DATA_UID" - userdel "$USERNAME" -else - echo "UID $WWW_DATA_UID not in use" -fi - -if [ -n "$(getent group "$WWW_DATA_GID")" ] -then - GROUPNAME=$(getent passwd "$WWW_DATA_GID" | cut -d: -f1) - echo "Deleting group $GROUPNAME which already uses GID $WWW_DATA_GID" - groupdel "$GROUPNAME" -else - echo "GID $WWW_DATA_GID not in use" -fi - -if [ -n "$(getent group www-data)" ] -then - echo "Modifying existing www-data group, setting GID to $WWW_DATA_GID" - groupmod -g "$WWW_DATA_GID" www-data -else - echo "Adding www-data group with GID $WWW_DATA_GID" - groupadd -g "$WWW_DATA_GID" www-data -fi - -if [ -n "$(getent passwd www-data)" ] -then - echo "Modifying existing www-data user, setting GID to $WWW_DATA_GID" - usermod -g "$WWW_DATA_GID" www-data -else - echo "Adding www-data user with UID $WWW_DATA_UID and GID $WWW_DATA_GID" - getent passwd 1000 - useradd -u "$WWW_DATA_UID" -g "$WWW_DATA_GID" www-data +if [ -z "$(find /data -user "$(id -u)" -print -prune -o -prune)" ]; then + echo "/data is not owned by the correct user, we are uid $(id -u)" + exit 1 fi if [ -n "$(ls -A /data 2>/dev/null)" ] @@ -67,7 +35,7 @@ else phpstan.neon composer install # fix permissions - chown -R www-data:www-data . + # chown -R www-data:www-data . find . -type d -exec chmod 750 {} \; find . -type f -exec chmod 640 {} \; set +x @@ -87,4 +55,12 @@ then fi fi +{ \ + echo "[www]" + echo "pm.max_children = $PHP_MAX_CHILDREN" + echo "pm.start_servers = $PHP_MIN_SPARE_SERVERS" + echo "pm.min_spare_servers = $PHP_MIN_SPARE_SERVERS" + echo "pm.max_spare_servers = $PHP_MAX_SPARE_SERVERS" +} > /tmp/additional-php-fpm-settings.conf # this file is symlinked to the correct php-fpm configuration dir + exec php-fpm