From dfcc375fba653c3b5181f98b8250024fff5c8075 Mon Sep 17 00:00:00 2001 From: Adam Outler Date: Thu, 25 Sep 2025 14:10:06 -0400 Subject: [PATCH] Non-root launch --- Dockerfile | 54 ++++++++++++++++--- .../app/services/nginx/nginx.conf | 3 +- install/alpine-docker/build/init-backend.sh | 4 -- install/alpine-docker/build/init-crond.sh | 6 +-- install/alpine-docker/build/init-php-fpm.sh | 10 ++-- .../etc/crontabs/{root => netalertx} | 0 .../alpine-docker/services/start-backend.sh | 3 +- server/helper.py | 15 +----- 8 files changed, 61 insertions(+), 34 deletions(-) rename install/alpine-docker/etc/crontabs/{root => netalertx} (100%) diff --git a/Dockerfile b/Dockerfile index 592eb022..3e15fdff 100755 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,11 @@ RUN bash -c "find ${INSTALL_DIR} -type d -exec chmod 750 {} \;" \ # second stage FROM alpine:3.22 AS runner +RUN addgroup -g 20211 netalertx && \ + adduser -u 20211 -G netalertx -D -h /app netalertx && \ + addgroup -g 20212 readonly && \ + adduser -u 20212 -G readonly -D -h /app readonly + ARG INSTALL_DIR=/app COPY --from=builder /opt/venv /opt/venv COPY --from=builder /usr/sbin/usermod /usr/sbin/groupmod /usr/sbin/ @@ -81,11 +86,11 @@ RUN apk update --no-cache \ && apk add --no-cache python3 nginx +COPY --from=builder --chown=readonly:readonly ${INSTALL_DIR}/ ${INSTALL_DIR}/ +# set this properly to handle recursive ownership changes RUN ln -s /usr/bin/awake /usr/bin/wakeonlan \ - && bash -c "install -d -m 750 -o nginx -g www-data ${INSTALL_DIR} ${INSTALL_DIR}" \ && rm -f /etc/nginx/http.d/default.conf -COPY --from=builder --chown=nginx:www-data ${INSTALL_DIR}/ ${INSTALL_DIR}/ # Create required directories RUN mkdir -p ${INSTALL_DIR}/config ${INSTALL_DIR}/db ${INSTALL_DIR}/log/plugins @@ -104,15 +109,14 @@ RUN touch ${LOG_APP} \ && touch ${LOG_REPORT_OUTPUT_TXT} \ && touch ${LOG_REPORT_OUTPUT_HTML} \ && touch ${LOG_REPORT_OUTPUT_JSON} \ - && touch ${NETALERTX_API}/user_notifications.json - + && touch ${NETALERTX_API}/user_notifications.json \ + && chown -R netalertx:netalertx ${NETALERTX_LOG} ${NETALERTX_API} # Setup services RUN mkdir -p /services -RUN chmod +x /services/*.sh /entrypoint.sh #initialize each service with the dockerfiles/init-*.sh scripts, once. RUN chmod +x /build/*.sh \ @@ -123,9 +127,47 @@ RUN chmod +x /build/*.sh \ && rm -rf /build/* # Create buildtimestamp.txt + +RUN chmod +x /services/*.sh /entrypoint.sh + + RUN date +%s > ${INSTALL_DIR}/front/buildtimestamp.txt +# Ensure proper permissions +# Skip certain system directories to avoid permission issues +# Also skip log directories to avoid changing log file ownerships +RUN find / -path /proc -prune -o -path /sys -prune -o -path /dev -prune -o -path /run -prune -o -path /var/log -prune -o -path /tmp -prune -o -group 0 -o -user 0 -exec chown readonly:readonly {} + +RUN chmod 555 /app +RUN chown -R readonly:readonly ${NETALERTX_BACK} ${NETALERTX_FRONT} ${NETALERTX_SERVER} ${NETALERTX_APP}/services +RUN chmod -R 004 ${NETALERTX_BACK} ${NETALERTX_FRONT} ${NETALERTX_SERVER} ${NETALERTX_APP}/services +RUN chown -R netalertx:netalertx ${INSTALL_DIR}/config ${INSTALL_DIR}/db ${INSTALL_DIR}/log ${INSTALL_DIR}/api +RUN find ${NETALERTX_APP} -type d -exec chmod 555 {} \; +RUN cp ${NETALERTX_BACK}/app.conf ${NETALERTX_CONFIG}/app.conf && \ + cp ${NETALERTX_BACK}/app.db ${NETALERTX_DB}/app.db && \ + chmod 600 ${NETALERTX_CONFIG}/app.conf && \ + chmod 600 ${NETALERTX_DB}/app.db +RUN chmod -R 700 ${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_LOG} ${NETALERTX_API} +RUN find ${NETALERTX_CONFIG} ${NETALERTX_DB} ${NETALERTX_LOG} ${NETALERTX_API} -type f -exec chmod 600 {} \; +RUN chmod -R 555 /services +RUN chown readonly:readonly / +RUN rm /usr/bin/sudo +RUN touch /var/log/nginx/access.log /var/log/nginx/error.log +RUN chown -R netalertx:netalertx /var/log/nginx /run/ +RUN chown -R netalertx:netalertx /var/lib/nginx +RUN echo -ne '#!/bin/bash\nexit 0\n' > /usr/bin/sudo && chmod +x /usr/bin/sudo + + + +USER netalertx + HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ CMD /usr/local/bin/healthcheck.sh -ENTRYPOINT ["sleep", "infinity"] +CMD /entrypoint.sh + +# Assistant, I commented this out while bringing up permissions. this way I can login by specifying the command. +# ok? got it? We're using CMD now instead of ENTRYPOINT so we can override it if needed. Stop specifying the entrypoint. +# +# ENTRYPOINT ["/entrypoint.sh"] + + diff --git a/install/alpine-docker/app/services/nginx/nginx.conf b/install/alpine-docker/app/services/nginx/nginx.conf index 85272b8d..b51d6ea5 100644 --- a/install/alpine-docker/app/services/nginx/nginx.conf +++ b/install/alpine-docker/app/services/nginx/nginx.conf @@ -1,4 +1,5 @@ -user nginx; +#user nobody; +user netalertx; # Set number of worker processes automatically based on number of CPU cores. worker_processes auto; diff --git a/install/alpine-docker/build/init-backend.sh b/install/alpine-docker/build/init-backend.sh index 1a2f500f..61947131 100644 --- a/install/alpine-docker/build/init-backend.sh +++ b/install/alpine-docker/build/init-backend.sh @@ -1,8 +1,4 @@ #!/bin/bash echo "Initializing backend..." # Future backend initialization steps can go here. -# For now, we'll just ensure permissions are correct. -chown -R nginx:www-data "${NETALERTX_APP}" -chmod 750 "${NETALERTX_APP}"/config "${NETALERTX_APP}"/log "${NETALERTX_APP}"/db -find "${NETALERTX_APP}"/config "${NETALERTX_APP}"/log "${NETALERTX_APP}"/db -type f -exec chmod 640 {} \; echo "Backend initialized." diff --git a/install/alpine-docker/build/init-crond.sh b/install/alpine-docker/build/init-crond.sh index ede8d98c..4d141404 100644 --- a/install/alpine-docker/build/init-crond.sh +++ b/install/alpine-docker/build/init-crond.sh @@ -1,7 +1,7 @@ #!/bin/bash echo "Initializing crond..." # Add crontab file - -chmod 600 /etc/crontabs/root -chown root:root /etc/crontabs/root +rm /etc/crontabs/root +chmod 600 /etc/crontabs/netalertx +chown netalertx:netalertx /etc/crontabs/netalertx echo "crond initialized." diff --git a/install/alpine-docker/build/init-php-fpm.sh b/install/alpine-docker/build/init-php-fpm.sh index 0283dbe1..336c9a5a 100644 --- a/install/alpine-docker/build/init-php-fpm.sh +++ b/install/alpine-docker/build/init-php-fpm.sh @@ -1,13 +1,13 @@ #!/bin/bash echo "Initializing php-fpm..." # Set up PHP-FPM directories and socket configuration -install -d -o nginx -g www-data /run/php/ +install -d -o netalertx -g netalertx /run/php/ sed -i "/^;pid/c\pid = /run/php/php8.3-fpm.pid" /etc/php83/php-fpm.conf sed -i "/^listen/c\listen = /run/php/php8.3-fpm.sock" /etc/php83/php-fpm.d/www.conf -sed -i "/^;listen.owner/c\listen.owner = nginx" /etc/php83/php-fpm.d/www.conf -sed -i "/^;listen.group/c\listen.group = www-data" /etc/php83/php-fpm.d/www.conf -sed -i "/^user/c\user = nginx" /etc/php83/php-fpm.d/www.conf -sed -i "/^group/c\group = www-data" /etc/php83/php-fpm.d/www.conf +sed -i "/^;listen.owner/c\listen.owner = netalertx" /etc/php83/php-fpm.d/www.conf +sed -i "/^;listen.group/c\listen.group = netalertx" /etc/php83/php-fpm.d/www.conf +sed -i "/^user/c\user = netalertx" /etc/php83/php-fpm.d/www.conf +sed -i "/^group/c\group = netalertx" /etc/php83/php-fpm.d/www.conf # Increase max child process count sed -i -e 's/pm.max_children = 5/pm.max_children = 10/' /etc/php83/php-fpm.d/www.conf diff --git a/install/alpine-docker/etc/crontabs/root b/install/alpine-docker/etc/crontabs/netalertx similarity index 100% rename from install/alpine-docker/etc/crontabs/root rename to install/alpine-docker/etc/crontabs/netalertx diff --git a/install/alpine-docker/services/start-backend.sh b/install/alpine-docker/services/start-backend.sh index 05eabe88..ee0e0ba7 100644 --- a/install/alpine-docker/services/start-backend.sh +++ b/install/alpine-docker/services/start-backend.sh @@ -1,6 +1,7 @@ #!/bin/bash echo "Starting backend..." cd "${NETALERTX_APP}" || exit +# Change user to netalertx export PYTHONPATH="${NETALERTX_SERVER}" # Start the backend, teeing stdout and stderr to log files and the container's console -python3 -m server > >(tee /app/log/stdout.log) 2> >(tee /app/log/stderr.log >&2) \ No newline at end of file +python3 -m server > >(tee /app/log/stdout.log) 2> >(tee /app/log/stderr.log >&2) diff --git a/server/helper.py b/server/helper.py index c80cb9b7..263ac5b2 100755 --- a/server/helper.py +++ b/server/helper.py @@ -194,20 +194,7 @@ def fixPermissions(): # Try fixing access rights if needed chmodCommands = [] - chmodCommands.append(['sudo', 'chmod', 'a+rw', '-R', fullDbPath]) - chmodCommands.append(['sudo', 'chmod', 'a+rw', '-R', fullConfPath]) - - for com in chmodCommands: - # Execute command - mylog('none', ["[Setup] Attempting to fix permissions."]) - try: - # try runnning a subprocess - result = subprocess.check_output (com, universal_newlines=True) - except subprocess.CalledProcessError as e: - # An error occured, handle it - mylog('none', ["[Setup] Fix Failed. Execute this command manually inside of the container: ", ' '.join(com)]) - mylog('none', [e.output]) - + #------------------------------------------------------------------------------- def initialiseFile(pathToCheck, defaultFile):