Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s6-int chown/chmod: Operation not permitted - non root user in dockerfile #821

Closed
2 of 6 tasks
aperoulakis opened this issue Apr 9, 2021 · 19 comments
Closed
2 of 6 tasks

Comments

@aperoulakis
Copy link

aperoulakis commented Apr 9, 2021

BUG
This is a: FILL ME IN

Details

I am trying to run pihole via docker using a dockerfile. Within the docker file I try to set a non-root user to run the container.
The docker image builds and test fine. However, when I "docker run up -d", the container gets built showing no stdout errors, but fails within 4-6 seconds and exits.

When I check the docker logs for that container, every single file s6-init tries to chown/chmod returns with "operation not permitted."

Related Issues

  • I have searched this repository/Pi-hole forums for existing issues and pull requests that look similar

linuxserver/docker-unifi-controller#62
just-containers/s6-overlay#272
just-containers/s6-overlay#309

How to reproduce the issue

  1. Environment data
  • Operating System: ENTER HERE
    Operating System: Debian GNU/Linux 10 (buster)
    Kernel: Linux 5.10.17-v8+
    Architecture: arm64
  • Hardware:
    Raspberry Pi 4 model B 8GB RAM version - armhfv8
  • Kernel Architecture:
    armv8 64 bit
  • Docker Install Info and version:
    • Software source:
      pihole/pihole:v5.7-armhf-buster
    • Supplimentary Software:
  • Hardware architecture:
    ARMv8, x64
  1. docker-compose.yml contents, docker run shell command, or paste a screenshot of any UI based configuration of containers here

Github thread - use official image as parent image

Based on OS Flavor:Version

#FROM debian:buster
FROM pihole/pihole:v5.7-armhf-buster

Build software workdir

#CMD mkdir /mnt/data/docker/pihole/appdata

Set Working Dir

WORKDIR /mnt/data/docker/pihole/appdata

Fetch Image from URL

IMAGE should not be 'latest', but exact version

URL is not a private registry - security flaw

LABEL image="pihole/pihole:v5.7-armhf-buster"
LABEL url="https://www.github.com/pi-hole/docker-pi-hole"
LABEL maintainer="MHN-APP"
LABEL vendor1="GitHub-diginc"
LABEL vendor2="DockerHub"
LABEL vendor3="Pi-hole"

#Look for OS/ARCH build
ENV TAG debian
ENV TAG pihole
ENV ARCH arm64/v8

ENTRYPOINT [ "/s6-init" ]

#Disable IPv6 and enable IPv4
ENV IPv6 False
ENV IPv4 True

#Add metadata to image - runtime ports listening
#Expose ports needed for containers
EXPOSE 53 53/udp
EXPOSE 67/udp
EXPOSE 80
EXPOSE 443

#S6-Init settings that may need to be set
ENV S6_LOGGING 0
ENV S6_KEEP_ENV 1
ENV S6_BEHAVIOR_IF_STAGE2_FAILS 2
ENV FTL_CMD no-daemon

#Create service running user/group
#Assign user to group
#Run as user
#RUN sudo groupadd docker
#RUN useradd -rm -d /home/docker -s /bin/bash -g docker -G sudo -p "$(openssl passwd -1 docker)" docker
#RUN chown -R docker:docker /mnt/data/docker/pihole/appdata
#RUN sudo useradd -m -s /bin/bash -g pihole -G sudo -u 1001 pihole
#RUN sudo usermod -aG docker docker
#RUN sudo useradd -m -s /bin/bash -g root -G sudo -u 1001 docker
#USER pihole

#Check to see if pihole started/running
#Run specific command inside the container
#IP is loopback IP for host
#HEALTHCHECK CMD dig @127.0.0.1 pi.hole || exit 1
HEALTHCHECK CMD curl --fail http://localhost:80/ || exit 1

#Run pihole status?
SHELL ["/bin/bash", "pihole -c"]
3. any additional info to help reproduce
I have tried every combination of the above "RUN adduser/useradd". All attempts fail to keep a container live longer than 4-6 seconds. When I leave the "User" section out, the entire thing works perfectly (except the service runs as root).

These common fixes didn't work for my issue

  • I have tried removing/destroying my container, and re-creating a new container
  • I have tried fresh volume data by backing up and moving/removing the old volume data
  • I have tried running the stock docker run example(s) in the readme (removing any customizations I added)
  • I have tried a newer or older version of Docker Pi-hole (depending what version the issue started in for me)
  • I have tried running without my volume data mounts to eliminate volumes as the cause

If the above debugging / fixes revealed any new information note it here.
Add any other debugging steps you've taken or theories on root cause that may help.
There as another github ticket/case that mentioned adding an environment variable for NON_ROOT_USER.
I could not get any of that to work. Not sure if that is relevant.

@dschaper
Copy link
Member

dschaper commented Apr 9, 2021

Are you building your own image?

@dschaper
Copy link
Member

dschaper commented Apr 9, 2021

docker run up -d

Is that the exact command you are trying? That won't really do much. Can you explain what it is you are intending to do, none of this looks like docker to me.

@aperoulakis
Copy link
Author

aperoulakis commented Apr 9, 2021

Yes. I built my own image using the dockerfile above.

Here is the docker-compose section, but I also tested it using only docker as well:

services:
#        pihole:
#                build: './pihole'
#                container_name: pihole
#                image: pihole/pihole:v5.7-armhf-buster
#                hostname: RPI8Dpihole
#                dns:
#                        - 127.0.0.1
#                cap_add:
#                        - NET_ADMIN
#                network_mode: host
#                #ports: -- Errors with DHCP broadcasting in BRIDGE mode
#                #       - "53:53/tcp"
#                #       - "53:53/udp"
#                #       - "67:67/udp"
#                #       - "80:80/tcp"
#                #       - "443:443/tcp"
#                environment:
#                       TZ: 'America/New_York'
#                       WEBPASSWORD: admin
#                       ServerIP: 10.0.1.144
#                       DNS1: 208.67.222.222
#                       DNS2: 208.67.220.220
#                       #DNSMASQ_USER: pihole --Causes DNS service error
#                #volumes store your data between container upgrades
#                #Bind mount to modify files without image rebuild
#                volumes:
#                       - './pihole/appdata/etc-pihole/:/etc/pihole/'
#                       - './pihole/appdata/etc-dnsmasq.d/:/etc/dnsmasq.d/'
#                       - './pihole/appdata/var-log/:/var/log/'
#                #Recommended but not required (DHCP needs NET_ADMIN)
#                #https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
#                restart: unless-stopped

@aperoulakis
Copy link
Author

I need the main user running in the docker container to not be root.
I had read and saw examples of setting the "USER" to a non-root user so the container service has no root privileges.

@dschaper
Copy link
Member

dschaper commented Apr 9, 2021

Yes. I built my own image using the dockerfile above.

Not to be flippant, but why?

@aperoulakis
Copy link
Author

Best Practice for security specifies running the services as a non-root user for production environments.

@dschaper
Copy link
Member

dschaper commented Apr 9, 2021

You may want to search through open and closed issues about running a DNS server in a container as a non-root user. I don't think anyone has done it successfully.

@aperoulakis
Copy link
Author

so pihole services cannot run as non-root?

@dschaper
Copy link
Member

dschaper commented Apr 9, 2021

It's a DNS server that needs to bind to port 80 53. It will drop priv's to a non-root user after the port binding is accomplished but that user still has sudo permissions.

@aperoulakis
Copy link
Author

Any way to bind the port via the Dockerfile or docker-compose file?
Or run the bind as root in the file, then switch to the non-root container user.

@shoenig
Copy link

shoenig commented Jun 12, 2021

@dschaper I think this is a legitimate issue / feature request. These errors are not related to port binding, but rather file permissions issues. It seems pihole's initialization scripts assume it will be run as root, which is an unfortunate requirement for something that is completely sealed in its container.

From an idealistic docker user's viewpoint, this should work:

$ docker run -u pihole --rm --name pihole -e DNSMASQ_USER:pihole -p 8080:80 -p 5353:53 --dns=1.1.1.1 pihole/pihole:v5.8.1
[s6-init] making user provided files available at /var/run/s6/etc...exited 0.
[s6-init] ensuring user provided files have correct perms...s6-chown: fatal: unable to chown /var/run/s6/etc/fix-attrs.d/01-resolver-resolv: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/fix-attrs.d/01-resolver-resolv: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/cont-init.d/20-start.sh: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/cont-init.d/20-start.sh: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/pihole-FTL/run: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/cron/run: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/lighttpd/run: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/pihole-FTL/run: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/cron/run: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/lighttpd/run: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/pihole-FTL/finish: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/cron/finish: Operation not permitted
s6-chown: fatal: unable to chown /var/run/s6/etc/services.d/lighttpd/finish: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/pihole-FTL/finish: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/cron/finish: Operation not permitted
s6-chmod: fatal: unable to change mode of /var/run/s6/etc/services.d/lighttpd/finish: Operation not permitted
exited 0.
[fix-attrs.d] applying ownership & permissions fixes...
[fix-attrs.d] 01-resolver-resolv: applying... 
s6-chown: fatal: unable to chown /etc/resolv.conf: Operation not permitted
s6-chmod: fatal: unable to change mode of /etc/resolv.conf: Operation not permitted
[fix-attrs.d] 01-resolver-resolv: exited 0.
[fix-attrs.d] done.
[cont-init.d] executing container initialization scripts...
[cont-init.d] 20-start.sh: executing... 
foreground: warning: unable to spawn /var/run/s6/etc/cont-init.d/20-start.sh: Permission denied
[cont-init.d] 20-start.sh: exited 127.
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.
[s6-finish] sending all processes the KILL signal and exiting.

@dschaper
Copy link
Member

dschaper commented Jun 14, 2021

It seems pihole's initialization scripts assume it will be run as root, which is an unfortunate requirement for something that is completely sealed in its container.

Yes, that's the assumption we make since Pi-hole is a DNS server and requires the ability to bind to lower numbered, privileged ports. pihole-FTL does drop priv's after it starts for security but it does need to be elevated for that process to happen.

Basically, you need to be root to run a DNS server, doesn't matter what the environment is.

I'm open to ideas if anyone has them but I don't see it as a possibility to do.

Edit:

-p 5353:53 that will never work unless you find a way to have every client use port 5353 for DNS.

@nettnikl
Copy link

nettnikl commented Jul 9, 2021

I think he meant -p 53:5353, so that inside the docker container, so that no root is needed there, and the high privileged docker daemon takes care of binding that to 53 towards clients.

@summed
Copy link

summed commented Sep 12, 2021

I don't see any reason why this needs to run as root. There are some extra permissions required for DHCP, but that is another story. Regarding the privileged ports (first 1024), this is not any requirement for the container, you just do as @nettnikl mentioned above.

So why non-root? - 1) This IS best practice, and especially when running "3rd party" containers. 2) If you are running on k8s with enforced non-root policy, this image with becomes a custom pain in the butt to run, or just not a possibility.

It just is a complete mystery to me why not all container authors setup their containers as non-root from the build.

But please enlighten me if there is something I am missing :)

@dschaper
Copy link
Member

dschaper commented Sep 12, 2021

PRs welcome.

@shoenig
Copy link

shoenig commented Oct 20, 2021

If anyone else out there like me wanted a simple DNS ad-blocker without root, I ended up creating https://github.com/shoenig/donutdns

e.g.

docker run --rm -p 53:5301 -u nobody shoenig/donutdns:v0.1.2

@XenGi
Copy link

XenGi commented Nov 1, 2021

Basically, you need to be root to run a DNS server, doesn't matter what the environment is.

This is simply not true. You need root privileges to bind to lower ports. DNS servers don't need any root privileges at all.

The init script of the Pihole container still assumes they are root and the container is failing to start.

PRs welcome.

Does that mean that if I rewrite half of your container to allow it to run without root you will potentially merge that or is this just your answer to end the discussion? Not wanna sound rude, I only want to put in the work if it is worth it. I don't want to maintain my own fork that will never get merged.

@github-actions
Copy link

github-actions bot commented Jan 8, 2022

This issue is stale because it has been open 30 days with no activity. Please comment or update this issue or it will be closed in 5 days.

@PromoFaux
Copy link
Member

pihole-FTL is now run as the user pihole by default since version 2022.01.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants