Skip to content

fix: customize container user permissions using PUID and PGID. #9657#9833

Open
asheshv wants to merge 2 commits intomasterfrom
custom_user_support_in_docker
Open

fix: customize container user permissions using PUID and PGID. #9657#9833
asheshv wants to merge 2 commits intomasterfrom
custom_user_support_in_docker

Conversation

@asheshv
Copy link
Copy Markdown
Contributor

@asheshv asheshv commented Apr 9, 2026

Summary

Re-implements custom container user permissions via PUID and PGID environment variables, fixing the issues that caused the original PR #9633 to be reverted (#9690).

Fixes #9657

What changed

Dockerfile

  • Added su-exec package for privilege dropping
  • Added chmod g=u /run/pgadmin — was missing, required for OpenShift random UIDs to write to this directory

entrypoint.sh

  • Added PUID/PGID environment variable support with input validation (must be numeric, PUID=0 rejected)
  • When running as root (--user root): reassigns pgadmin user to target UID/GID, fixes ownership of runtime directories before any initialization, runs all commands via su-exec
  • When not root (default or OpenShift): unchanged behavior
  • Fixed pgpass file operations: quoted paths, added chown when running as root
  • Wrapped all Python invocations in $SU_EXEC to prevent root-owned file creation

Why the original PR was reverted

The original implementation (#9633) had three critical issues:

  1. Removed USER 5050 from Dockerfile — container ran as root by default (security regression)
  2. DB initialization ran as rootrun_pgadmin.py and load-servers created root-owned files in /var/lib/pgadmin. The chown -R happened after init, so if anything failed between init and chown, the volume was left root-owned and inaccessible
  3. OpenShift incompatibility — hardcoded UID 5050, required root for usermod/chown, rejected by OpenShift's restricted-v2 SCC

How this fix addresses each issue

  1. USER 5050 is preserved — default behavior is completely unchanged
  2. Privileges are dropped before initialization, not after — all init scripts (run_pgadmin.py, load-servers, set-prefs) run as the target user via su-exec, so files are created with correct ownership from the start. No post-hoc chown fixup needed for init files.
  3. OpenShift works without any special configuration — see details below

Three supported modes

Mode How to use id -u Behavior
Default No changes needed 5050 Identical to current behavior. SU_EXEC="", all commands run directly as UID 5050.
Custom UID docker run --user root -e PUID=1000 -e PGID=1000 ... 0 Validates PUID/PGID, usermods pgadmin user, chowns runtime dirs, then drops to target user via su-exec for all init + gunicorn.
OpenShift Deploy normally (SCC assigns random UID) e.g. 1001320000 SU_EXEC="", passwd fixup adds entry for random UID, files accessible via group permissions (chmod g=u + GID 0). No chown needed.

OpenShift compatibility details

On OpenShift with restricted-v2 SCC:

  • The SCC overrides USER 5050 with a random UID from the namespace range (e.g., 1001320000-1001329999)
  • The container does not run as root — id -u returns the random UID, so the else branch is taken
  • The random UID is in GID 0 (root group). All runtime directories have chmod g=u in the Dockerfile, making them group-writable by GID 0
  • The passwd fixup adds an /etc/passwd entry for the random UID (needed for whoami, Python's os.getlogin(), etc.)
  • No chown is needed — file access works through group permissions
  • Do not set runAsUser: 5050 or fsGroup: 5050 in the pod spec — let the SCC assign the UID

The reported error .spec.securityContext.fsGroup: Invalid value: []int64{5050}: 5050 is not an allowed group occurs when the pod spec explicitly sets fsGroup: 5050, which the SCC rejects. The fix is to remove those fields from the pod spec.

Usage examples

# Default (unchanged behavior)
docker run -d -p 80:80 \
  -e PGADMIN_DEFAULT_EMAIL=admin@example.com \
  -e PGADMIN_DEFAULT_PASSWORD=secret \
  pgadmin4

# Custom UID/GID (match host user)
docker run -d -p 80:80 --user root \
  -e PUID=1000 -e PGID=1000 \
  -e PGADMIN_DEFAULT_EMAIL=admin@example.com \
  -e PGADMIN_DEFAULT_PASSWORD=secret \
  -v pgadmin-data:/var/lib/pgadmin \
  pgadmin4

# OpenShift (no special flags needed)
# Just deploy — the SCC handles UID assignment

Test plan

  • Default mode (USER 5050): container starts, pgAdmin accessible, can connect to PostgreSQL server
  • OpenShift simulation (--user 1001320000:0): container starts, pgAdmin accessible
  • Custom UID mode (--user root -e PUID=1000 -e PGID=1000): container starts, files owned by 1000:1000
  • Invalid PUID (non-numeric): container exits with clear error
  • PUID=0: container exits with clear error
  • Volume persistence: restart with same PUID/PGID, data preserved
  • Volume ownership change: restart with different PUID/PGID, chown corrects ownership

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Fixed permission and ownership handling for pgAdmin directories and configuration files in container environments.
    • Improved validation and error handling for critical startup files.
  • Chores

    • Enhanced container runtime configuration for improved security practices.
    • Added support for custom user and group ID specification in container deployments.

asheshv added 2 commits April 9, 2026 18:38
Add support for custom container user permissions via PUID and PGID
environment variables. When the container is started as root
(--user root), the pgadmin user is reassigned to the requested UID/GID
and all initialization runs under that user via su-exec, ensuring
files are created with correct ownership from the start.

Key changes:
- Dockerfile: add su-exec package, add chmod g=u for /run/pgadmin
  (fixes OpenShift random UID access)
- entrypoint.sh: add PUID/PGID validation and privilege dropping
  before initialization (not after), preserving OpenShift compatibility

Three modes supported:
- Default (USER 5050): unchanged behavior
- Custom UID (--user root -e PUID=N -e PGID=N): drops to target user
  before any init
- OpenShift (random UID, GID 0): passwd fixup + group permissions
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

Walkthrough

The pull request modifies Docker configuration and the pgAdmin entrypoint script to support non-root container execution via PUID/PGID environment variables. It adds the su-exec utility, implements UID/GID validation and reassignment logic, fixes directory ownership when running as root, and wraps initialization and service startup commands with privilege de-escalation.

Changes

Cohort / File(s) Summary
Docker Configuration
Dockerfile
Added su-exec package to Alpine runtime dependencies and extended chmod g=u permission fix to include /run/pgadmin alongside /var/lib/pgadmin.
Entrypoint Script
pkg/docker/entrypoint.sh
Implemented PUID/PGID initialization with numeric validation and rejection of root UID; added ownership fixes for /run/pgadmin, /var/lib/pgadmin, /pgadmin4/config_distro.py, /certs, .pgpass, and optional custom config paths; wrapped Python checks, JSON loading, email validation, database initialization, preferences setup, and Gunicorn launch with su-exec privilege de-escalation; tightened PGPASS_FILE validation and quoting; adjusted OpenShift passwd logic to remain in non-root code path.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding PUID/PGID support for customizable container user permissions, which is the core objective of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch custom_user_support_in_docker

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.

Copy link
Copy Markdown

@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.

🧹 Nitpick comments (2)
pkg/docker/entrypoint.sh (2)

240-240: Consider using parameter expansion instead of sed.

Per static analysis hint (SC2001), bash parameter expansion is more efficient and avoids spawning a subprocess:

♻️ Suggested refactor
-            PGADMIN_USER_CONFIG_DIR=$(echo "${PGADMIN_DEFAULT_EMAIL}" | sed 's/@/_/g')
+            PGADMIN_USER_CONFIG_DIR="${PGADMIN_DEFAULT_EMAIL//@/_}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/docker/entrypoint.sh` at line 240, The assignment to
PGADMIN_USER_CONFIG_DIR uses sed and spawns a subprocess; change it to use bash
parameter expansion to replace all '@' characters in PGADMIN_DEFAULT_EMAIL with
underscores (use the parameter expansion pattern that substitutes globally, e.g.
the ${VAR//@/_} form) so PGADMIN_USER_CONFIG_DIR is set without invoking sed.

47-52: Consider documenting potential startup delay for large data volumes.

The recursive chown -R on /var/lib/pgadmin will traverse all files in the volume. For containers with significant stored data (sessions, query history, server groups), this could noticeably delay startup when using custom PUID/PGID.

Consider adding a note to the PR documentation or a log message indicating this is expected behavior:

     # Fix ownership of runtime directories BEFORE any initialization
     for dir in /run/pgadmin /var/lib/pgadmin; do
         if [ -d "$dir" ]; then
+            echo "Fixing ownership of $dir (may take time for large volumes)..."
             chown -R "$PUID:$PGID" "$dir"
         fi
     done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/docker/entrypoint.sh` around lines 47 - 52, Add a brief startup warning
before the recursive ownership fix in entrypoint.sh: before the for-loop that
runs chown -R on /run/pgadmin and /var/lib/pgadmin, emit a log message (e.g.,
printf or echo to stderr) that indicates recursive chown may take significant
time on large volumes and includes the PUID/PGID values; optionally, in the same
change consider guarding the chown with a quick ownership check (stat/ls -n) to
skip chown if owner/group already match to avoid unnecessary delays.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/docker/entrypoint.sh`:
- Line 240: The assignment to PGADMIN_USER_CONFIG_DIR uses sed and spawns a
subprocess; change it to use bash parameter expansion to replace all '@'
characters in PGADMIN_DEFAULT_EMAIL with underscores (use the parameter
expansion pattern that substitutes globally, e.g. the ${VAR//@/_} form) so
PGADMIN_USER_CONFIG_DIR is set without invoking sed.
- Around line 47-52: Add a brief startup warning before the recursive ownership
fix in entrypoint.sh: before the for-loop that runs chown -R on /run/pgadmin and
/var/lib/pgadmin, emit a log message (e.g., printf or echo to stderr) that
indicates recursive chown may take significant time on large volumes and
includes the PUID/PGID values; optionally, in the same change consider guarding
the chown with a quick ownership check (stat/ls -n) to skip chown if owner/group
already match to avoid unnecessary delays.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1990768e-8eff-4a35-a7c5-4eeb2d7f4585

📥 Commits

Reviewing files that changed from the base of the PR and between 9a76ed8 and 606be5e.

📒 Files selected for processing (2)
  • Dockerfile
  • pkg/docker/entrypoint.sh

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Customizing container user permissions using PUID and PGID.

1 participant