Minituff / nautical-backup

A simple Docker volume backup tool.
https://minituff.github.io/nautical-backup/
GNU General Public License v3.0
216 stars 3 forks source link

Run container as non-root user #314

Open robflate opened 1 week ago

robflate commented 1 week ago

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.

Minituff commented 5 days ago

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.

robflate commented 5 days ago

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'
Minituff commented 4 days ago

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.

robflate commented 4 days ago

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.