nautical-backup icon indicating copy to clipboard operation
nautical-backup copied to clipboard

Run container as non-root user

Open robflate opened this issue 1 year ago • 10 comments

Is it possible to run the container as a non-root user, specifically I want to run it as my host user either by passing PUID and PGID env vars or with user: 1000:1000.

robflate avatar Sep 12 '24 13:09 robflate

Yes it is. I tested it on my end and it should work. You just need to ensure the user you use has access to both the source, config and destination folder.

You should be able to use it like this:

services:
  nautical-backup:
    image: minituff/nautical-backup:2 
    container_name: nautical-backup
    user: 1000:1000  # <--- override default `root` user
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /config:/config
      - /source:/app/source
      - /destination:/app/destination
    environment: # Optional variables
      - TZ=America/Los_Angeles
      - CRON_SCHEDULE=0 4 * * *
      - SKIP_CONTAINERS=example1,example2,example3

Let me know if this works for you. I can also update the docs so everyone else knows that it's supported.

Minituff avatar Sep 13 '24 22:09 Minituff

Thanks. I just tried it and it doesn't seem to work. I'm getting some permission denied errors. Perhaps what I'm wanting is not supported by this simple change.

I want /config to be owned by the user passed with user: PUID:PGID but I also want Nautical to be able to read /source files owned by any USER:GROUP and with any permissions and then write these files to /destination while maintaining the USER:GROUP and permissions of the original files.

A few of the containers I run create appdata owned by other users (including root), sometimes with restrictive permissions (600).

DEBUG: REPORT_FILE: true
/app/logger.sh: line 33: /Backup Report - 2024-09-14.txt: Permission denied
INFO: Nautical Backup Version: 2.6.0
DEBUG: Built for the platform: linux/amd64
DEBUG: Perparing enviornment variables...
DEBUG: Found defaults.env
DEBUG: CRON_SCHEDULE: 0 4 * * *
DEBUG: USE_DEST_DATE_FOLDER: false
DEBUG: DEST_DATE_PATH_FORMAT: date/container
DEBUG: DEST_DATE_FORMAT: %Y-%m-%d
DEBUG: USE_DEFAULT_RSYNC_ARGS: true
DEBUG: REPORT_FILE_ON_BACKUP_ONLY: true
DEBUG: KEEP_SRC_DIR_NAME: true
DEBUG: EXIT_AFTER_INIT: false
DEBUG: LOG_RSYNC_COMMANDS: false
DEBUG: SOURCE_LOCATION: /app/source
DEBUG: DEST_LOCATION: /app/destination
DEBUG: TEST_MODE: -1
DEBUG: HTTP_REST_API_ENABLED: true
DEBUG: ADDITIONAL_FOLDERS_WHEN: before
DEBUG: NAUTICAL_DB_PATH: /config
DEBUG: NAUTICAL_DB_NAME: nautical-db.json
TRACE: PRE_BACKUP_CURL: 
TRACE: POST_BACKUP_CURL: 
TRACE: RSYNC_CUSTOM_ARGS: 
TRACE: OVERRIDE_SOURCE_DIR: 
TRACE: OVERRIDE_DEST_DIR: 
TRACE: SELF_CONTAINER_ID: 
TRACE: SKIP_CONTAINERS: 
TRACE: SKIP_STOPPING: 
TRACE: ADDITIONAL_FOLDERS: 
DEBUG: SELF_CONTAINER_ID: 3ffc9fbf2a06
INFO: Skipping CRON installation since CRON_SCHEDULE_ENABLED=false
DEBUG: Verifying source directory '/app/source'...
DEBUG: Verifying destination directory '/app/destination'...
INFO: Connected to database at '/config/nautical-db.json'
DEBUG: Installing nautical backup script...
ln: /usr/local/bin/nautical: Permission denied
chmod: /usr/local/bin/nautical: No such file or directory
TRACE: ln -s /app/backup.sh /usr/local/bin/nautical
TRACE: TEST_MODE: -1
INFO: Starting backup since BACKUP_ON_START is true
INFO: Note - BACKUP_ON_START logs are not available until all containers are processed, however the report file updates in real-time.
/etc/s6-overlay/s6-rc.d/init-backup-on-start/run.sh: line 11: nautical: command not found
s6-rc: warning: unable to start service init-backup-on-start: command exited 127
INFO: API listening on port 8069...
INFO: Initialization complete. Awaiting CRON schedule: 0 4 * * *
TRACE: Running: exec with-contenv python3 -m uvicorn app.api.main:app --host 0.0.0.0 --port 8069 --lifespan on --use-colors --log-level 'warning'

robflate avatar Sep 14 '24 06:09 robflate

Hmm, yeah I checked again and I am also seeing those permissions errors.

I can fix this error ln: /usr/local/bin/nautical: Permission denied by moving the installation of the Nautical script into the Dockerfile (which is run as root) instead of the container init (which would be run as the --user specified).

This error /app/logger.sh: line 33: /Backup Report - 2024-09-14.txt: Permission denied is caused because this file was created by Nautical (which was previously run as root), so now the user you set no longer has access to it.


I was able to fix those issues but I uncovered another one. The Docker socket /var/run/docker.sock cannot be accessed unless the container is root. This means the Python library I am using to access to the Docker socker is not working unless I am root. So I am going to test if I can change that.

Also, the PUID:PGID are LinuxServer.io terms. From what I understand, they created these as a way to allow non-root containers before the Docker engine have introduced the --user flag. I don't think I would be able to incorporate both.

Minituff avatar Sep 14 '24 22:09 Minituff

Yeah, my knowledge is limited but I think the benefit of passing PUID and PGID is it allows the container to run services as that user but also run services as root when elevated permissions are required. It should also allow access to the docker socket without root by mapping PUID:PGID to an existing user in the container (e.g. abc:abc) and adding that user to the Docker group inside the container.

On the other hand, user: 1000:1000 would remove the ability to run services as root without also providing the container with elevated privileges (--privileged, --cap-add, etc).

Ultimately, most containers don't need to run as root but something like a backup tool is different. There will very often be situations where you're backing up files not owned by a specific user or with restrictive permissions. However, maybe there are lots of things the container can just run as non-root? It feels safe to assume that /config should be owned by PUID:PGID and not root. Also, any services that don't need to run as root, shouldn't. Access to /source would require root access or privileged access unless you could guarantee all files are owned by a specific user (often not the case).

I'd love to hear thoughts in general about best practices for running containers that often required elevated privileges whilst also maintaining security.

robflate avatar Sep 15 '24 10:09 robflate

There are two places where Nautical writes files, in the /config and at the backup destination. This thread has mostly been discussing the /config but I think an easy win here would be to allow customization of the UID/GID of the backup destination.

Ultimately, most containers don't need to run as root but something like a backup tool is different.

I completely agree. Getting a container to run using /var/run/docker.sock as a non-root user is a nightmare and I would say a lost cause. Don't bother going down that road. Instead, focus on the UID/GID when writing the backup. Don't get me wrong, it would also be nice if /config UID/GID could be customized, but for me personally, that is a distant second desire compared to allowing the backup destination UID/GID to be customized.

I would venture to say that there are far more users like me who would like to customize UID/GID of the files written to the backup destination than the /config. I might go so far as to say that allowing that would increase security. Allowing Nautical to write backup files to a specific share with specific permissions would be chef's kiss.

jacobslusser avatar Apr 14 '25 02:04 jacobslusser

@Minituff

I was able to fix those issues but I uncovered another one. The Docker socket /var/run/docker.sock cannot be accessed unless the container is root. This means the Python library I am using to access to the Docker socker is not working unless I am root. So I am going to test if I can change that.

But it should work in combination with a Docker socket proxy, or am I wrong in this point?

I run both Portainer and Diun under user: “1000:1000”. Both are connected via the Docker Socket Proxy (which itself is running as root). This works perfectly without ever having any authorization problems.

However, when I try the same with Nautical Backup, I still get the following error message:

/etc/s6-overlay/s6-rc.d/init-backup-on-start/run.sh: line 11: nautical: command not found
s6-rc: warning: unable to start service init-backup-on-start: command exited 127

Can this be fixed?

Saber-1980 avatar Jul 02 '25 15:07 Saber-1980

My understanding is that S6 overlay must run as root. Thats what I'm seeing in the docs. We can drop the permissions of the nautical scripts at runtime but the container itself needs to be root.

If you want to skim through the S6 docs and see if there's a way to do it -- I'm up for making changes if it is possible.

Minituff avatar Jul 02 '25 16:07 Minituff

Ok, thanks. I've seen that the non-root user support of S6 overlay is only available to a limited amount since v3.2.1.0 and not all services are compatible with it.

Saber-1980 avatar Jul 03 '25 10:07 Saber-1980

Hmm yeah I do see a mention of that in this release, but they did not talk about how to implement it. I can play around with it and test it out, but if it does not work, this will likely have to be "unplanned" because I do not plan to migrate away from S6.

Minituff avatar Aug 05 '25 02:08 Minituff

@Minituff

From my side, this is no longer a problem, as I have switched the entire server to Rootless Docker over the last few days. All user instructions have been removed, and there are now no more problems with S6.

Thank you for your support - it's a great project! Keep up the good work. :)

Saber-1980 avatar Aug 11 '25 21:08 Saber-1980