From 2e3feca05f2c98b5c468f7eade85569fba5d20aa Mon Sep 17 00:00:00 2001 From: Paulo Gomes Date: Thu, 18 Sep 2025 08:18:51 +0100 Subject: [PATCH] security: run Docker container as non-root user Running containers as a non-root user is a long standing security practice. The changes ensure that the sourcebot user is created and has the correct level of permissions to run all its dependencies (postgres, redis and node). Please note that as a side effect, existing mounted volumes would need to have their ownership reviewed or it may not be able to access the files. This is specially the case for previous versions that would create said files as 0:0. To fix that, users can run chown -R 1500:1500 /path/.sourcebot. The chmod may also need to be a bit more strict in such cases, so changing that is advised: chown -R 0750 /path/.sourcebot. Signed-off-by: Paulo Gomes --- Dockerfile | 14 ++++++++++++++ entrypoint.sh | 31 ++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index ae90c8c7..76eadbe0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -225,12 +225,26 @@ RUN mkdir -p /run/postgresql && \ chown -R postgres:postgres /run/postgresql && \ chmod 775 /run/postgresql +# To run as non-root, the user must be part of postgres, redis and node groups +RUN addgroup -g 1500 sourcebot && \ + adduser -D -u 1500 -h /app -S sourcebot && \ + adduser sourcebot postgres && \ + adduser sourcebot redis && \ + adduser sourcebot node && \ + chown -R sourcebot /data && \ + chown -R sourcebot /app && \ + mkdir /var/log/sourcebot && \ + chown sourcebot /var/log/sourcebot + COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf COPY prefix-output.sh ./prefix-output.sh RUN chmod +x ./prefix-output.sh COPY entrypoint.sh ./entrypoint.sh RUN chmod +x ./entrypoint.sh + +USER sourcebot + EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0" diff --git a/entrypoint.sh b/entrypoint.sh index cf90a377..14fdb908 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -77,19 +77,20 @@ fi # Check if DATA_CACHE_DIR exists, if not create it if [ ! -d "$DATA_CACHE_DIR" ]; then - mkdir -p "$DATA_CACHE_DIR" + mkdir -m 0750 -p "$DATA_CACHE_DIR" fi # Check if DATABASE_DATA_DIR exists, if not initialize it if [ "$DATABASE_EMBEDDED" = "true" ] && [ ! -d "$DATABASE_DATA_DIR" ]; then - echo -e "\e[34m[Info] Initializing database at $DATABASE_DATA_DIR...\e[0m" - mkdir -p $DATABASE_DATA_DIR && chown -R postgres:postgres "$DATABASE_DATA_DIR" - su postgres -c "initdb -D $DATABASE_DATA_DIR" + echo -e "\e[34m[Info] Initializing database at $DATABASE_D\ATA_DIR...\e[0m" + mkdir -m 0750 -p $DATABASE_DATA_DIR + + initdb -D "$DATABASE_DATA_DIR" fi # Create the redis data directory if it doesn't exist if [ "$REDIS_EMBEDDED" = "true" ] && [ ! -d "$REDIS_DATA_DIR" ]; then - mkdir -p $REDIS_DATA_DIR + mkdir -m 0750 -p $REDIS_DATA_DIR fi if [ -z "$SOURCEBOT_ENCRYPTION_KEY" ]; then @@ -180,13 +181,25 @@ echo "{\"version\": \"$NEXT_PUBLIC_SOURCEBOT_VERSION\", \"install_id\": \"$SOURC # Start the database and wait for it to be ready before starting any other service if [ "$DATABASE_EMBEDDED" = "true" ]; then - su postgres -c "postgres -D $DATABASE_DATA_DIR" & - until pg_isready -h localhost -p 5432 -U postgres; do + postgres -D "$DATABASE_DATA_DIR" & + until pg_isready -h localhost -p 5432 -d sourcebot -U postgres; do echo -e "\e[34m[Info] Waiting for the database to be ready...\e[0m" sleep 1 + + # As postgres runs in the background, we must check if it is still + # running, otherwise the "until" loop will be running indefinitely. + if ! pgrep -x "postgres" > /dev/null; then + echo "postgres failed to run" + exit 1 + break + fi done - # Check if the database already exists, and create it if it dne + # Running as non-root we need to ensure the postgres account is created. + psql -U postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='postgres'" | grep -q 1 \ + || createuser postgres -s + + # Check if the database already exists, and create it if it doesn't EXISTING_DB=$(psql -U postgres -tAc "SELECT 1 FROM pg_database WHERE datname = 'sourcebot'") if [ "$EXISTING_DB" = "1" ]; then @@ -205,4 +218,4 @@ DATABASE_URL="$DATABASE_URL" yarn workspace @sourcebot/db prisma:migrate:prod mkdir -p /var/log/sourcebot # Run supervisord -exec supervisord -c /etc/supervisor/conf.d/supervisord.conf \ No newline at end of file +exec supervisord -c /etc/supervisor/conf.d/supervisord.conf