Skip to content

Run the UI container as a non-root user - #159

Merged
omarghatasheh merged 1 commit into
mainfrom
hamza/fix/nonroot-container
Aug 10, 2026
Merged

Run the UI container as a non-root user#159
omarghatasheh merged 1 commit into
mainfrom
hamza/fix/nonroot-container

Conversation

@hamzahalq

Copy link
Copy Markdown
Contributor

Switches to nginx-unprivileged and moves the internal port to 8080, since ports below 1024 require root. The Service's external port is unchanged.

Switches to nginx-unprivileged and moves the internal port to 8080,
since ports below 1024 require root. The Service's external port is unchanged.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

What changed

  • Replaced the production base image with nginx-unprivileged.
  • Configured Nginx and the container to listen on port 8080.
  • Configured the deployment to run as UID 101.
  • Updated the Service target port to 8080.
  • Kept the external Service port configurable, with a default of 80.

Risk

risk:low

Security-sensitive areas

  • The container no longer requires root privileges.
  • Nginx now uses an unprivileged listener on port 8080.
  • Verify that file permissions and runtime paths support UID 101.

Test coverage impact

  • No test changes are reported.
  • Validate the image startup, Nginx health checks, static asset serving, and Service routing.

Operational concerns

  • Existing clients can continue using the external Service port.
  • Confirm that probes, ingress rules, network policies, monitoring, and firewall rules target the correct internal and external ports.
  • Rollback requires restoring the previous image, port 80 configuration, and root container settings.

Walkthrough

The production container now uses unprivileged Nginx with UID 101. Nginx listens on port 8080. The Kubernetes Deployment and Service route traffic to port 8080 while keeping the Service port configurable with a default of 80.

Changes

Unprivileged Nginx runtime

Layer / File(s) Summary
Unprivileged image and listener
Dockerfile, nginx/nginx.conf
The production image uses nginxinc/nginx-unprivileged:stable-alpine. Nginx listens on port 8080.
Kubernetes security and port wiring
chart/templates/deployment.yaml, chart/templates/service.yaml
The Deployment requires UID 101 and exposes container port 8080. The Service forwards traffic to port 8080 while retaining its configurable service port.
Estimated code review effort: 2 (Simple) ~10 minutes

Suggested labels: security, infra, risk:critical

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: running the UI container as a non-root user.
Description check ✅ Passed The description accurately covers the unprivileged Nginx image, port change, and unchanged external Service port.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Dockerfile`:
- Line 12: Replace the mutable stable-alpine reference in the Dockerfile’s FROM
directive with the tested Nginx unprivileged Alpine version and its verified
sha256 digest, preserving the nginxinc/nginx-unprivileged image while making the
base immutable.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: simplify9/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 61b45760-fd5e-4d20-98d7-ec8dc46de792

📥 Commits

Reviewing files that changed from the base of the PR and between cf5fa56 and 0e8de67.

📒 Files selected for processing (4)
  • Dockerfile
  • chart/templates/deployment.yaml
  • chart/templates/service.yaml
  • nginx/nginx.conf
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/Dockerfile

⚙️ CodeRabbit configuration file

**/Dockerfile: Review Dockerfiles for root user usage, unnecessary packages,
unpinned base images, secret leakage, cache poisoning,
excessive image size, and missing health checks.

Flag:

  • running as root
  • copying secrets into the image
  • package manager cache left behind
  • unpinned base images
  • curl | sh installation patterns
  • unnecessary build tools in runtime images

Files:

  • Dockerfile
🔇 Additional comments (4)
Dockerfile (1)

13-17: LGTM!

nginx/nginx.conf (1)

2-2: LGTM!

chart/templates/deployment.yaml (1)

29-34: LGTM!

chart/templates/service.yaml (1)

14-14: LGTM!

Comment thread Dockerfile

# production environment
FROM nginx:stable-alpine
FROM nginxinc/nginx-unprivileged:stable-alpine

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pin the production base image to an immutable reference.

Line 12 uses the mutable stable-alpine tag. A rebuild can silently pull different Nginx or Alpine contents. Use a tested version with a digest, such as nginxinc/nginx-unprivileged:<tested-version>-alpine@sha256:<verified-digest>.

As per path instructions, Dockerfiles must flag unpinned base images.

Suggested change and verification
-FROM nginxinc/nginx-unprivileged:stable-alpine
+FROM nginxinc/nginx-unprivileged:<tested-version>-alpine@sha256:<verified-digest>
#!/usr/bin/env bash
set -euo pipefail

tag_info="$(curl -fsSL \
  'https://hub.docker.com/v2/repositories/nginxinc/nginx-unprivileged/tags/stable-alpine')"
digest="$(jq -r '.digest // empty' <<<"$tag_info")"

test -n "$digest"
case "$digest" in
  sha256:*) ;;
  *) exit 1 ;;
esac

printf '%s\n' "$digest"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile` at line 12, Replace the mutable stable-alpine reference in the
Dockerfile’s FROM directive with the tested Nginx unprivileged Alpine version
and its verified sha256 digest, preserving the nginxinc/nginx-unprivileged image
while making the base immutable.

@omarghatasheh
omarghatasheh merged commit 1f46fe6 into main Aug 10, 2026
5 checks passed
@omarghatasheh
omarghatasheh deleted the hamza/fix/nonroot-container branch August 10, 2026 11:23
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.

2 participants