From 2fbb0b4291cc5684b69c5b3d095cb83062e40011 Mon Sep 17 00:00:00 2001
From: Olivier LEVILLAIN <olivier.levillain@free.fr>
Date: Fri, 20 Dec 2024 20:17:22 +0100
Subject: [PATCH 1/2] upgrade package versions

---
 requirements.txt | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/requirements.txt b/requirements.txt
index f94bf2f..64ab143 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,15 +1,15 @@
-django>=5.1.4
-pillow>=10.4.0
-django-crispy-forms>=2.3
-crispy-bulma>=0.11.0
-django-environ>=0.11.2
-django-email-validation>=2.0.5
-django-simple-captcha>=0.6.0
-daphne>=4.1.2
-supervisor>=4.2.5
-reportlab>=4.2.2
-channels>=4.1.0 
-channels_redis>=4.2.0
-Babel>=2.15
-django-cors-headers>=4.4.0
-packaging>=24.0
+django~=5.1.4
+pillow~=11.0.0
+django-crispy-forms~=2.3
+crispy-bulma~=0.11.0
+django-environ~=0.11.2
+django-email-validation~=2.0.5
+django-simple-captcha~=0.6.0
+daphne~=4.1.2
+supervisor~=4.2.5
+reportlab~=4.2.5
+channels~=4.2.0 
+channels_redis~=4.2.0
+babel~=2.16.0
+django-cors-headers~=4.6.0
+packaging~=24.2

From a9d09134bea31f53dca7eaf798cb788c16e64213 Mon Sep 17 00:00:00 2001
From: Olivier LEVILLAIN <olivier.levillain@free.fr>
Date: Fri, 20 Dec 2024 20:37:34 +0100
Subject: [PATCH 2/2] Don't run docker container as root #147

---
 Dockerfile                | 41 +++++++++++++++++++++++----------------
 scripts/entrypoint.sh     |  3 ---
 scripts/prepare-envt.sh   | 16 +++++++--------
 template.lighttpd.conf    |  5 +++--
 template.supervisord.conf |  8 ++++----
 5 files changed, 38 insertions(+), 35 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index c57e95d..7ef95ef 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,12 +1,15 @@
 FROM python:3.12-slim
 
+ARG USER=cm_user
+ARG UID=5678
+ARG APP_DIR=/app
+
 LABEL org.opencontainers.image.source=https://github.com/leolivier/cousins-matter
 LABEL org.opencontainers.image.description='Docker image for the Cousins Matter application (https://github.com/leolivier/cousins-matter)'
 LABEL org.opencontainers.image.url=https://github.com/leolivier/cousins-matter
 LABEL org.opencontainers.image.branch=main
 LABEL org.opencontainers.image.licenses=MIT
 
-
 EXPOSE 8000
 
 # Keeps Python from generating .pyc files in the container
@@ -15,16 +18,17 @@ ENV PYTHONDONTWRITEBYTECODE=1
 # Turns off buffering for easier container logging
 ENV PYTHONUNBUFFERED=1
 
-WORKDIR /app
+WORKDIR ${APP_DIR}
 
-# install lighttpd for serving static and media files, redis for chat, sqlite3 and acl for init
+# install lighttpd for serving static and media files, redis for chat, sqlite3 for installing database
 # We must update twice as we need first to install gpg before installing redis
 RUN apt-get update &&\
-		apt-get install -y lighttpd lsb-release curl gpg sqlite3 acl &&\
+		apt-get install -y lighttpd lsb-release curl gpg sqlite3 sudo supervisor && \
 		curl -fsSL https://packages.redis.io/gpg | gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg &&\
 		echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" > /etc/apt/sources.list.d/redis.list &&\
 		apt-get update &&\
 		apt-get install -y redis	&&\
+		mkdir -p "/var/log/supervisord" "/var/run/supervisord" &&\
 		rm -rf /var/lib/apt/lists/*
 
 # Allows docker to cache installed dependencies between builds
@@ -32,16 +36,19 @@ COPY requirements.txt .
 RUN pip install --no-cache-dir -r requirements.txt
 
 # Creates a non-root user with an explicit UID and adds permission to access the /app folder
-# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
-# RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
-# USER appuser
-
-COPY . .
-
-# runs the production server
-ENTRYPOINT ["/app/scripts/entrypoint.sh"]
-# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
-CMD ["supervisord", "-c", "/app/supervisord.conf"]
-
-VOLUME [ "/app/data" ]
-VOLUME [ "/app/media" ]
+# This is the user that will run the application but through supervisord so 
+# we keep running as root for supervisord which will run things as $USER
+RUN adduser --uid ${UID} --disabled-password --gecos "" ${USER} && \
+		chown -R ${USER}:${USER} ${APP_DIR}
+
+# now copy all (but .dockerignore rules) with $USER as proprietary
+COPY --chown=${USER}:${USER} . .
+
+ENV USER=${USER}
+ENV APP_DIR=${APP_DIR}
+# runs the production server (as root)
+ENTRYPOINT ["./scripts/entrypoint.sh"]
+# supervisord must run as root
+CMD ["supervisord", "-c", "./supervisord.conf"]
+
+VOLUME ./data ./media
diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh
index 8bb110a..592651d 100755
--- a/scripts/entrypoint.sh
+++ b/scripts/entrypoint.sh
@@ -1,7 +1,4 @@
 #!/bin/bash
-export APP_DIR=/app
 . ./scripts/prepare-envt.sh || exit 1
-# add full access to /app to www-data for redis and ligthttpd
-setfacl -m u:www-data:rwx /app
 echo "starting $@"   # as provided in the Dockerfile
 exec "$@"	
diff --git a/scripts/prepare-envt.sh b/scripts/prepare-envt.sh
index 8fb9635..c036d8e 100644
--- a/scripts/prepare-envt.sh
+++ b/scripts/prepare-envt.sh
@@ -7,19 +7,17 @@ then echo "Must be run from the cousins-matter directory!"
 fi
 
 for file in lighttpd.conf supervisord.conf
-do cat template.$file | sed -e "s,{%APP_DIR%},$APP_DIR,g" > $file
+do cat template.$file | sed -e "s,{%APP_DIR%},$APP_DIR,g;s,{%USER%},$USER,g" > $file
 done
 
 echo "collecting statics..."
-python manage.py collectstatic --no-input
+sudo -u $USER python manage.py collectstatic --no-input
 echo "migrating the database..."
-python manage.py migrate
-python manage.py check
+sudo -u $USER python manage.py migrate
+sudo -u $USER python manage.py check
 
+echo "importing predefined pages"
 ./scripts/import-flatpages.sh
+echo "import done..."
 
-sudo=''
-if [[ -n "$EUID" && $EUID -ne 0 ]];
-then sudo='sudo'
-fi
-$sudo mkdir -p "/var/log/supervisord" "/var/run/supervisord"
+echo "environment is ready..."
diff --git a/template.lighttpd.conf b/template.lighttpd.conf
index 46f786d..2088625 100644
--- a/template.lighttpd.conf
+++ b/template.lighttpd.conf
@@ -41,14 +41,15 @@ $HTTP["url"] =~ "^/static/" {
 } else $HTTP["url"] =~ "^/chat" {  # websocket for the chat, add upgrade header
     proxy.server = ("/" =>
       ( "cousinsmatter socket" => (
-          "socket" => "/var/run/cousinsmatter.socket"
+# sockets are created in APP_DIR for running as non root
+          "socket" => "{%APP_DIR%}/cousinsmatter.socket"
       ))
     )
     proxy.header = ( "upgrade" => "enable" )
 } else $HTTP["url"] =~ "" {
     proxy.server = ("/" =>
       ( "cousinsmatter socket" => (
-          "socket" => "/var/run/cousinsmatter.socket"
+          "socket" => "{%APP_DIR%}/cousinsmatter.socket"
       ))
     )
 }
diff --git a/template.supervisord.conf b/template.supervisord.conf
index 6e9ed51..420e6e5 100644
--- a/template.supervisord.conf
+++ b/template.supervisord.conf
@@ -16,8 +16,8 @@ stderr_logfile_maxbytes=0
 directory={%APP_DIR%}
 autostart=true
 autorestart=true
-command=daphne -u /var/run/cousinsmatter.socket  --proxy-headers cousinsmatter.asgi:application
-user=root
+command=daphne -u {%APP_DIR%}/cousinsmatter.socket  --proxy-headers cousinsmatter.asgi:application
+user={%USER%}
 
 [program:lighttpd]
 stdout_logfile=/dev/stdout
@@ -28,7 +28,7 @@ directory={%APP_DIR%}
 autostart=true
 autorestart=true
 command=lighttpd -D -f {%APP_DIR%}/lighttpd.conf
-user=www-data
+user={%USER%}
 
 [program:redis]
 stdout_logfile=/dev/stdout
@@ -39,4 +39,4 @@ directory={%APP_DIR%}
 autostart=true
 autorestart=true
 command=redis-server
-user=www-data
+user={%USER%}