humhub-docker icon indicating copy to clipboard operation
humhub-docker copied to clipboard

draft: feat: Run as non-root by default to allow easier deployment on the restricted environments like OpenShift, Kubernetes and any corporate (or just secure) environments where root privileges are not allowed

Open blackandred opened this issue 1 year ago • 17 comments

Hi,

The container does not necessarily start as root and then switches permissions to nginx user. I simplified it by starting everything as nginx from the beginning. Additionally I reduced the end image size and memory usage (~20 MB less) by migrating from supervisord to multirun which is a container-native init process, that does not depend on Python.

Benefits:

  • Increased security by decreasing the privileges
  • Less memory usage (by ~20 MB)
  • Less image size (398MB -> 348MB for all-in-one variant)
  • Better compatibility with restricted environments (OpenShift, Kubernetes)
  • Less attack surface by removing supervisord and Python

I was testing it initially with docker-compose, I will test also on Kubernetes and will then "undraft" the PR. I'm creating the PR at this moment to know what do you think about such a big change.

blackandred avatar Mar 03 '23 10:03 blackandred

This may probably resolve issues like https://github.com/mriedmann/humhub-docker/issues/194, because no any process will be running with other privileges than the application, so there will be no chance of accidentially creating a file as root.

blackandred avatar Mar 03 '23 10:03 blackandred

After some more testing I see volume mount points are having non-deterministic permissions, sometimes I get nginx:nginx and other times (more often) I get 101:nginx (why 101?).

Here is my testing script:

HUMHUB_VERSION=1.13.0

build-prod:
	docker build . --target humhub_nginx --build-arg HUMHUB_VERSION=${HUMHUB_VERSION} -t docker.io/mriedmann/humhub:stable-nginx
	docker build . --target humhub_phponly --build-arg HUMHUB_VERSION=${HUMHUB_VERSION} -t docker.io/mriedmann/humhub:stable-phponly

rm-prod:
	docker-compose -f docker-compose.prod.yml rm -s -v -f
	docker volume rm -f humhub-docker_assets humhub-docker_modules humhub-docker_mysql humhub-docker_themes humhub-docker_uploads

run-prod: build-prod rm-prod
	docker-compose -f docker-compose.prod.yml up

build-aio:
	docker build . --target humhub_allinone --build-arg HUMHUB_VERSION=${HUMHUB_VERSION} -t docker.io/mriedmann/humhub:latest
make run-prod

blackandred avatar Mar 04 '23 07:03 blackandred

After some more testing I see volume mount points are having non-deterministic permissions, sometimes I get nginx:nginx and other times (more often) I get 101:nginx (why 101?).

Here is my testing script:

HUMHUB_VERSION=1.13.0

build-prod:
	docker build . --target humhub_nginx --build-arg HUMHUB_VERSION=${HUMHUB_VERSION} -t docker.io/mriedmann/humhub:stable-nginx
	docker build . --target humhub_phponly --build-arg HUMHUB_VERSION=${HUMHUB_VERSION} -t docker.io/mriedmann/humhub:stable-phponly

rm-prod:
	docker-compose -f docker-compose.prod.yml rm -s -v -f
	docker volume rm -f humhub-docker_assets humhub-docker_modules humhub-docker_mysql humhub-docker_themes humhub-docker_uploads

run-prod: build-prod rm-prod
	docker-compose -f docker-compose.prod.yml up

build-aio:
	docker build . --target humhub_allinone --build-arg HUMHUB_VERSION=${HUMHUB_VERSION} -t docker.io/mriedmann/humhub:latest
make run-prod

Is it running on a reverse proxy?

ArchBlood avatar Mar 04 '23 07:03 ArchBlood

Yes, I'm testing the variant with separate nginx and php-fpm if you are asking abut this.

blackandred avatar Mar 04 '23 07:03 blackandred

Yes, I'm testing the variant with separate nginx and php-fpm if you are asking abut this.

Are there any noticeable differences in the logs between ngnix:nginx and 101:nginx after each run?

From my understanding of HumHub itself, it can be picky with reverse proxies. 🤔

ArchBlood avatar Mar 04 '23 07:03 ArchBlood

Yeah, with nginx:nginx it starts. With 101:nginx the installation fails for assets directory.

blackandred avatar Mar 04 '23 07:03 blackandred

On all-in-one variant it looks pretty fine I see, at least in docker-compose, I will have to check on Kubernetes on CRI-O.

$ docker volume ls
DRIVER    VOLUME NAME
$ docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Startup logs

humhub_1  | /docker-entrypoint.sh: Creating database...
humhub_1  | /docker-entrypoint.sh: Installing...
humhub_1  | total 776
humhub_1  | drwxr-xr-x    1 nginx    nginx         4096 Mar  3 05:56 .
humhub_1  | drwxr-xr-x    1 root     root          4096 Mar  3 05:56 ..
humhub_1  | -rw-rw-r--    1 nginx    nginx          413 Dec 21 16:01 .codeclimate.yml
humhub_1  | -rw-rw-r--    1 nginx    nginx         1588 Dec 21 16:01 .htaccess.dist
humhub_1  | -rw-rw-r--    1 nginx    nginx          312 Dec 21 16:01 .php_cs.dist
humhub_1  | -rw-rw-r--    1 nginx    nginx       123496 Dec 21 16:01 CHANGELOG.md
humhub_1  | -rw-rw-r--    1 nginx    nginx         1889 Dec 21 16:01 CONTRIBUTING.md
humhub_1  | -rw-rw-r--    1 nginx    nginx         5973 Dec 21 16:01 Gruntfile.js
humhub_1  | -rw-rw-r--    1 nginx    nginx          328 Dec 21 16:01 LICENSE
humhub_1  | -rw-rw-r--    1 nginx    nginx        34524 Dec 21 16:01 LICENSE.AGPL-3.0-or-later
humhub_1  | -rw-rw-r--    1 nginx    nginx          832 Dec 21 16:01 README.md
humhub_1  | -rw-rw-r--    1 nginx    nginx          240 Dec 21 16:01 SECURITY.md
humhub_1  | drwxrwxr-x    2 nginx    users         4096 Mar  4 08:02 assets
humhub_1  | -rw-rw-r--    1 nginx    nginx         5253 Mar  2 21:46 composer.json
humhub_1  | -rw-rw-r--    1 nginx    nginx       420847 Dec 21 16:01 composer.lock
humhub_1  | -rw-rw-r--    1 nginx    nginx         1331 Dec 21 16:01 index-test.php
humhub_1  | -rw-rw-r--    1 nginx    nginx          876 Dec 21 16:01 index.php
humhub_1  | -rw-rw-r--    1 nginx    nginx       102926 Mar  2 21:46 package-lock.json
humhub_1  | -rw-rw-r--    1 nginx    nginx          433 Mar  2 21:46 package.json
humhub_1  | drwxr-xr-x    1 nginx    nginx         4096 Mar  2 21:17 protected
humhub_1  | -rw-rw-r--    1 nginx    nginx           23 Dec 21 16:01 robots.txt
humhub_1  | drwxrwxr-x    9 nginx    nginx         4096 Mar  2 21:45 static
humhub_1  | drwxrwxr-x    1 nginx    nginx         4096 Mar  2 21:45 themes
humhub_1  | drwxrwxr-x    4 nginx    users         4096 Mar  4 08:02 uploads

(...)

humhub_1  | Validating: User Module - ContentContainer (1 entries)
humhub_1  | Validating: User Module - Users (1 entries)
humhub_1  | Validating: User Module - Password (1 entries)
humhub_1  | Validating: User Module - Profile (1 entries)
humhub_1  | Validating: User Module - Mentioning (0 entries)
humhub_1  | Validating: User Module - Follow (0 entries)
humhub_1  | Validating: User Module - Content container (1 entries)
humhub_1  | 
humhub_1  | *** All integrity checks done
humhub_1  | 
humhub_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/60-nginx-config.sh
humhub_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/70-nginx-allowedips.sh
humhub_1  | Setting HUMHUB_REVERSEPROXY_WHITELIST
humhub_1  | Added 127.0.0.1 to Reverseproxy Whitelist
humhub_1  | /docker-entrypoint.sh: Configuration complete; ready for start up
humhub_1  | /docker-entrypoint.sh: Entrypoint finished! Launching ...
humhub_1  | crond: crond (busybox 1.34.1) started, log level 8
humhub_1  | 2023/03/04 08:03:27 [notice] 72#72: using the "epoll" event method
humhub_1  | 2023/03/04 08:03:27 [notice] 72#72: nginx/1.20.2
humhub_1  | 2023/03/04 08:03:27 [notice] 72#72: OS: Linux [redacted]
humhub_1  | 2023/03/04 08:03:27 [notice] 72#72: getrlimit(RLIMIT_NOFILE): 1024:1024
humhub_1  | 2023/03/04 08:03:27 [notice] 72#72: start worker processes
humhub_1  | 2023/03/04 08:03:27 [notice] 72#72: start worker process 73
humhub_1  | [04-Mar-2023 08:03:28] NOTICE: [pool www] 'user' directive is ignored when FPM is not running as root
humhub_1  | [04-Mar-2023 08:03:28] NOTICE: [pool www] 'group' directive is ignored when FPM is not running as root
humhub_1  | [04-Mar-2023 08:03:28] NOTICE: fpm is running, pid 69
humhub_1  | [04-Mar-2023 08:03:28] NOTICE: ready to handle connections
humhub_1  | - -  04/Mar/2023:08:03:56 +0000 "GET /ping" 200
$ curl localhost:8080 -L -s  |grep HumHub|grep "<title>"
    <title>Login - HumHub</title>

blackandred avatar Mar 04 '23 08:03 blackandred

Hi! Thank you both so much for your work. I will try to have a look asap and comment/approve it.

mriedmann avatar Mar 07 '23 10:03 mriedmann

I marked is as draft so it is not an asap, take your time. I will play with it little bit more and will let you know as I don't want to break somebody's instance with this change 😃

blackandred avatar Mar 07 '23 17:03 blackandred

I started making a Helm Chart (https://github.com/riotkit-org/k8s-humhub) at first I will support root image, then I will experiment with non-root after I will get the root image working enough stable.

blackandred avatar Mar 14 '23 06:03 blackandred

I would really like to see this change and the helm chart come to (more) life, but I have no time to finish it. Is anyone interested in helping with this? Is there even a need for it? Please Emoji-Vote if you would be interested in using this, thx.

mriedmann avatar Nov 22 '23 13:11 mriedmann

I would really like to see this change and the helm chart come to (more) life, but I have no time to finish it. Is anyone interested in helping with this? Is there even a need for it? Please Emoji-Vote if you would be interested in using this, thx.

I'm going to be honest, I have no idea what you are doing with the code, but I use the docker container in truecharts with truenas scale, and I love it. If sorry you have no time, but if I could upvote it a million times I would. I'm having an issue with my deployment because of supervisord troubles and if this would fix those, it would light up my world.

chroniclesofdave avatar Dec 30 '23 02:12 chroniclesofdave

I had another look and I will try to get this going. I am still no big fan of multirun but reducing the size and complexity and getting a non-root container is a big improvement. I hope I can get to it over the weekend.

mriedmann avatar Jan 04 '24 17:01 mriedmann

Wow, sorry for abadoning the topic. I "slept" for almost a year. My instance still works on a feature branch, damn it 😁 Happy to see that somebody took over it.

blackandred avatar Jan 14 '24 21:01 blackandred

I must at least finish the Helm Chart :)

blackandred avatar Jan 14 '24 21:01 blackandred

Regarding the non-root container - I feel there could be some pitfalls on container startup, like chmod/chown or cache wipe, let's check it more strictly.

blackandred avatar Jan 14 '24 21:01 blackandred

Regarding the non-root container - I feel there could be some pitfalls on container startup, like chmod/chown or cache wipe, let's check it more strictly.

I've also considered this as well for my own Dockerfile, currently this is how I've implemented it; https://github.com/GreenMeteor/humhub-docker/pull/23

ArchBlood avatar Jan 15 '24 02:01 ArchBlood