Skip to content

feat(docker): support PUID/PGID/UMASK#858

Draft
s0up4200 wants to merge 5 commits intodevelopfrom
feat/docker-puid-pgid-umask
Draft

feat(docker): support PUID/PGID/UMASK#858
s0up4200 wants to merge 5 commits intodevelopfrom
feat/docker-puid-pgid-umask

Conversation

@s0up4200
Copy link
Collaborator

@s0up4200 s0up4200 commented Dec 25, 2025

Summary

  • Adds opt-in PUID/PGID/UMASK support for the Docker image via docker/entrypoint.sh
  • When PUID and PGID are set, the container creates the user/group, chown -Rs /config, then runs qui as that UID/GID (via su-exec)
  • Updates Dockerfile, ci.Dockerfile, docker-compose.yml, and README.md with examples and notes (including user:/--user bypass behavior)

Motivation: avoid root-owned /config artifacts and ensure directories/files created by hardlink-mode cross-seeding inherit expected ownership.

Test plan

  • Build and start container without PUID/PGID (runs as root, backward compatible)
  • Build and start container with PUID/PGID set
  • Verify /config/qui.db and logs are owned by the configured UID/GID
  • Verify hardlink-mode directories inherit the configured ownership

Summary by CodeRabbit

  • New Features

    • Container now supports PUID/PGID/UMASK environment variables; a new entrypoint applies these settings and preserves the default serve behavior.
  • Documentation

    • Added a "Permissions (PUID/PGID/UMASK)" section with Docker Compose and Docker Run examples and a note about when the entrypoint may be bypassed.

✏️ Tip: You can customize this high-level summary in your review settings.

Add opt-in PUID/PGID/UMASK support for the Docker image via
docker/entrypoint.sh. When PUID and PGID are set, the container
creates the user/group, chown -Rs /config, then runs qui as that
UID/GID (via su-exec).

- Add docker/entrypoint.sh with user/group creation and privilege drop
- Install su-exec in Dockerfile and ci.Dockerfile
- Update docker-compose.yml with PUID/PGID/UMASK documentation
- Add Permissions section to README.md with examples

Motivation: avoid root-owned /config artifacts and ensure directories
and files created by hardlink-mode cross-seeding inherit expected
ownership.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 25, 2025

Walkthrough

Adds an entrypoint script and installs su-exec in images; switches ENTRYPOINT to /entrypoint.sh. The entrypoint applies UMASK, optionally creates a user/group from PUID/PGID, chowns /config, and re-executes /usr/local/bin/qui. README and compose examples document PUID/PGID/UMASK usage.

Changes

Cohort / File(s) Summary
Dockerfiles
Dockerfile, ci.Dockerfile
Add su-exec; copy docker/entrypoint.sh into image and mark executable; change ENTRYPOINT to /entrypoint.sh; keep /usr/local/bin/qui and CMD serve.
Entrypoint Script
docker/entrypoint.sh
New strict shell entrypoint: apply UMASK if set; when PUID/PGID are provided create group/user, chown /config, then re-exec qui as that user via su-exec; otherwise run qui as current user.
Compose / Examples
docker-compose.yml
Add commented env hints for PUID, PGID, UMASK and note that user/--user bypasses entrypoint re-exec behavior.
Documentation
README.md
Add "Permissions (PUID/PGID/UMASK)" section and Unraid notes with Compose/Run examples and explanation of entrypoint behavior.

Sequence Diagram

sequenceDiagram
    participant Host as Host
    participant Container as Container
    participant Entrypoint as /entrypoint.sh
    participant App as /usr/local/bin/qui

    Container->>Entrypoint: start (env: PUID, PGID, UMASK)
    activate Entrypoint
    Entrypoint->>Entrypoint: apply UMASK (if provided)

    alt PUID & PGID set
        Entrypoint->>Host: create group (PGID) if missing
        Entrypoint->>Host: create user (PUID) if missing
        Entrypoint->>Host: chown /config to PUID:PGID
        note right of Entrypoint `#d4f1d4`: re-exec as designated user
        Entrypoint->>App: su-exec PUID:PGID /usr/local/bin/qui serve
    else PUID/PGID not set
        note right of Entrypoint `#f1f1d4`: run as current user (root)
        Entrypoint->>App: /usr/local/bin/qui serve
    end

    deactivate Entrypoint
    activate App
    App->>App: start server (CMD: serve)
    deactivate App
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I set the mask with gentle paws,
PUID and PGID follow laws,
su-exec hops, ownership true,
/config safe, the service grew,
carrot-powered container applause.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately summarizes the main feature: adding PUID/PGID/UMASK support to Docker image for correct file ownership.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/docker-puid-pgid-umask

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@s0up4200 s0up4200 added docker enhancement New feature or request labels Dec 25, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
docker/entrypoint.sh (1)

10-10: Consider handling partial PUID/PGID specification.

The current logic requires both PUID and PGID to be set. If only one is provided, the container silently runs as root without warning. Consider adding a check to warn users about this requirement or handle the partial case by deriving the missing value.

🔎 Suggested improvement
 # If PUID/PGID are set, run as that user
+if [ -n "$PUID" ] || [ -n "$PGID" ]; then
+    if [ -z "$PUID" ] || [ -z "$PGID" ]; then
+        echo "WARNING: Both PUID and PGID must be set together. Running as root." >&2
+    fi
+fi
+
 if [ -n "$PUID" ] && [ -n "$PGID" ]; then
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ace0101 and bd09ae0.

📒 Files selected for processing (5)
  • Dockerfile
  • README.md
  • ci.Dockerfile
  • docker-compose.yml
  • docker/entrypoint.sh
🔇 Additional comments (17)
docker/entrypoint.sh (6)

12-14: Group creation logic is correct.

The check properly verifies if a GID exists before attempting to create it, preventing errors when the container is restarted.


17-17: GROUP_NAME extraction could be more robust.

If multiple groups somehow have the same GID (unlikely but possible in corrupted systems), awk will return the first match. The current implementation is acceptable for typical scenarios.


20-22: User creation is properly configured.

The flags -D (don't assign password), -H (no home directory), and -s /sbin/nologin (no shell) appropriately restrict the created user for a container environment.


25-25: Be aware: recursive chown may be slow on large volumes.

The chown -R operation runs on every container start, which could delay startup if /config contains many files or is on slow storage. This is the expected behavior for PUID/PGID support, but users with large config directories should be aware of potential startup delays.

Consider documenting this behavior in the README if it's not already mentioned, especially for users with large backup archives or extensive cross-seed configurations.


28-28: Privilege drop with su-exec is correctly implemented.

The use of exec su-exec "$PUID:$PGID" /usr/local/bin/qui "$@" properly:

  • Drops privileges to the specified UID/GID
  • Replaces the shell process with qui (PID 1 benefits)
  • Forwards all arguments correctly

1-7: UMASK application and error handling look good.

The script correctly:

  • Uses #!/bin/sh for Alpine compatibility
  • Enables set -e to fail fast on errors
  • Applies UMASK before any file operations if specified
Dockerfile (3)

75-75: Runtime dependency addition is appropriate.

Adding su-exec to the runtime dependencies is correct for Alpine Linux. It's a minimal, lightweight alternative to gosu that serves the same purpose of dropping privileges.


82-85: Entrypoint installation is correctly implemented.

The script is properly:

  • Copied to the root directory for easy reference
  • Made executable with chmod +x
  • Positioned before the ENTRYPOINT declaration

93-93: ENTRYPOINT change preserves backward compatibility.

Switching to /entrypoint.sh while keeping CMD ["serve"] ensures:

  • Users without PUID/PGID continue running as root (backward compatible)
  • The binary remains at /usr/local/bin/qui for direct invocation if needed
  • Arguments are properly passed through to the application
docker-compose.yml (1)

13-28: Environment variable documentation is clear and helpful.

The added comments effectively:

  • Explain what happens when PUID/PGID are set (step-by-step process)
  • Provide sensible default examples (1000 for user IDs, 022 for UMASK)
  • Include an important warning about the user: field bypassing the entrypoint
  • Remain properly commented out for opt-in behavior
ci.Dockerfile (3)

67-67: Runtime dependencies match main Dockerfile.

The addition of su-exec is consistent with the main Dockerfile approach.


74-77: Entrypoint installation correctly uses build stage reference.

The COPY --from=go-builder /app/docker/entrypoint.sh correctly references the build stage where the source code is copied, ensuring the entrypoint script is available in the CI build.


85-85: ENTRYPOINT change is consistent with main Dockerfile.

The CI build maintains the same entrypoint behavior as the production Dockerfile.

README.md (4)

14-14: Table of Contents properly updated.

The new section is correctly added to the TOC with proper indentation under the Docker section.


166-209: Permissions documentation is comprehensive and well-written.

The new section effectively:

  • Explains the default root behavior and why PUID/PGID are useful
  • Provides a clear step-by-step breakdown of what the entrypoint does
  • Includes practical examples for both Docker Compose and Docker Run
  • Explains UMASK values with common use cases (022, 002, 077)
  • Prominently warns about the user:/--user bypass behavior
  • Connects the feature to the PR's motivation (cross-seed hardlink ownership)

The documentation quality is excellent and will help users understand and configure this feature correctly.


177-181: UMASK explanation is accurate and helpful.

The UMASK value explanations are correct:

  • 022 - rw-r--r-- for files, rwxr-xr-x for dirs (standard)
  • 002 - group-writable for shared environments
  • 077 - owner-only for maximum privacy

208-208: Important warning about user: bypass is well-placed.

The note clearly explains that using Docker's native user: field or --user flag bypasses the entrypoint's ownership correction logic, directing users to use PUID/PGID instead. This prevents a common misconfiguration.

@s0up4200 s0up4200 changed the title feat(docker): support PUID/PGID/UMASK for correct file ownership feat(docker): support PUID/PGID/UMASK Dec 25, 2025
@s0up4200 s0up4200 marked this pull request as draft December 25, 2025 19:44
@H2OKing89
Copy link

H2OKing89 commented Jan 14, 2026

This would be $\color{#008000}{\underline{\textbf{VERY!}}}$ helpful. This would fix the folders from being owned by root on unraid using hardlink cross-seed <3

@DaCeige

This comment was marked as spam.

@dolokolo

This comment was marked as spam.

@s0up4200 s0up4200 changed the base branch from main to develop January 15, 2026 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docker enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants