feat: Run Docker container as non-root user#722
Conversation
WalkthroughAdds a non-root runtime flow: Dockerfile installs su-exec and uses an entrypoint script; new Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Docker as Docker container start
participant Entrypoint as entrypoint.sh
participant Sys as System (user/group)
participant FS as Filesystem
participant App as Application process
Docker->>Entrypoint: start (env: PUID/PGID)
Entrypoint->>Sys: ensure group (create if missing)
Sys-->>Entrypoint: group ready
Entrypoint->>Sys: ensure user (create if missing)
Sys-->>Entrypoint: user ready
Entrypoint->>FS: mkdir /app/prompts,/app/config,/app/db,/home/paperless-gpt
FS-->>Entrypoint: dirs created
Entrypoint->>FS: chown -R to paperless-gpt:paperless-gpt
FS-->>Entrypoint: ownership set
Entrypoint->>Entrypoint: export HOME=/home/paperless-gpt
Entrypoint->>App: su-exec paperless-gpt -- run binary
App-->>Docker: running as non-root user
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@icereed Alternatively, and possibly even better, we could also set the docker container directly to UID 1000 or 33 (www). However, this is currently not backward compatible. |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
Dockerfile(1 hunks)README.md(2 hunks)docker-compose.yml(1 hunks)entrypoint.sh(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (5)
entrypoint.sh (1)
1-28: Excellent Alpine compatibility and idempotent user/group setup.The script correctly uses Alpine-compatible commands (
addgroup,adduser,su-exec) and implements proper idempotency checks withgetentbefore creating users and groups. The use of-D -Sflags for system users, proper HOME setup, and structured entrypoint flow are all correct.Dockerfile (1)
91-92: Dockerfile changes are correct and well-integrated.
su-execis properly added as a runtime dependency (line 91-92) for privilege dropping in the entrypoint.- The entrypoint script is copied, made executable (line 100-102), and correctly positioned before app execution.
- Switching to
ENTRYPOINT(line 111) is the right pattern for wrapper scripts that manage setup before launching the main application.- All paths align correctly with the working directory and binary location.
Also applies to: 100-102, 111-111
docker-compose.yml (1)
8-13: Docker Compose configuration is clear and well-documented.The PUID/PGID environment variables are correctly positioned before
env_file, with helpful comments guiding users on how to find their IDs. The defaults (1000) match the entrypoint script and are standard for non-root user scenarios. Users can easily customize these values as needed.README.md (2)
534-535: Environment variables table entries are clear and well-referenced.The new PUID and PGID entries are properly documented with defaults (1000) and include cross-references to the detailed "Running as a Non-Root User" section. This guides users to both the quick reference and in-depth explanation.
940-956: New "Running as a Non-Root User" section provides practical guidance.The documentation clearly explains the feature, provides actionable commands to find user/group IDs, and includes a concrete example showing customization. The placement is logical and the language is accessible. The example with PUID=1001, PGID=1001 effectively demonstrates that users can override defaults.
|
Hello @hensing , |
|
@matgoebl thank you for the comment -> done :) |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
entrypoint.sh (1)
8-12: Validation addresses the prior critical issue, but error message needs refinement.The validation successfully prevents
PUID=0orPGID=0and rejects negative values, resolving the previous concern. However, the error message on line 10 is grammatically awkward: "must non-root (0)" should be clarified—perhaps "must be positive integers and not equal to 0" or "must be greater than 0" for clarity.Consider updating line 10 to:
echo "ERROR: PUID and PGID must be positive integers greater than 0 (got PUID=${PUID}, PGID=${PGID})"This ensures users receive a clear, actionable error message if they accidentally set invalid values.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
README.md(2 hunks)docker-compose.yml(1 hunks)entrypoint.sh(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- docker-compose.yml
- README.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: test
🔇 Additional comments (5)
entrypoint.sh (5)
1-6: Good foundation: portable shell and safe defaults.The use of POSIX
/bin/shwithset -eensures portability and fail-fast behavior. The parameter expansion syntax is correct and the default UID/GID of 10001 aligns with security best practices mentioned in the PR comments.
14-21: Idempotent user/group creation with sound security practices.The use of
getentchecks ensures the script is idempotent and safe to run multiple times. Theadduserflags (-D -S -h -s /sbin/nologin) correctly create a system user with a disabled login shell, which follows Docker best practices.
23-27: Directory setup and permission handling is robust.The use of
mkdir -pensures idempotency, and the recursivechownon both/appand/home/paperless-gptdirectly addresses the permission issues (such as "mkdir /.config: permission denied") mentioned in the PR objectives. This ensures all files are writable by the non-root user.
29-30: HOME variable correctly targets user directory.Setting and exporting
HOME=/home/paperless-gptensures that any libraries or subprocesses writing configuration files will place them in the correct directory with proper permissions, avoiding permission denied errors.
32-34: Signal handling and privilege dropping are correctly implemented.Using
exec su-execensures the application process replaces the shell, allowing signals (SIGTERM, etc.) to be delivered directly to the application for graceful shutdown. The informational message aids visibility during container startup.
Summary
Your implementation successfully addresses the prior critical concern about PUID/PGID validation and follows Docker best practices for running as a non-root user. The script is idempotent, portable, and handles permission issues well.
One minor improvement recommended: Update the error message on line 10 to be grammatically clear and more actionable for users. The current wording "must non-root (0)" is awkward and could be misinterpreted.
Overall, the entrypoint script is solid and ready for deployment.
|
@icereed any chanced to get this into a release in the near future? can I help with something? |
|
Has this gone stale? Would love to move away from it running as root |
|
Going to guess we might not get to see this? |
This PR introduces a rootless setup for the Docker container, enhancing security and resolving file permission issues. The application now runs as a non-root user with a configurable UID and GID.
Changes:
entrypoint.sh: A new entrypoint script handles the creation of a dedicated user (paperless-gpt) at runtime. It usesPUIDandPGIDenvironment variables (defaulting to1000) to set the user and group IDs./appand/home/paperless-gptdirectories, which resolves themkdir /.config: permission deniederror caused by libraries likepdfcpu.su-execto drop privileges and executes the application via the new entrypoint script.docker-compose.ymlhas been updated to includePUIDandPGIDenvironment variables, making it easy for users to configure permissions.README.mdhas been updated to explain the newPUID/PGIDvariables and how to use them.This implementation follows Docker best practices for running services as a non-root user, improving security and preventing common permission problems with mounted volumes.
Summary by CodeRabbit
New Features
Documentation