Originally created by @SebLz on GitHub (Aug 13, 2025).
Check Existing Issues
I have searched the existing issues and discussions.
I am using the latest version of Open WebUI.
Installation Method
Other
Open WebUI Version
v0.6.22
Ollama Version (if applicable)
No response
Operating System
RHEL / OpenSHift
Browser (if applicable)
No response
Confirmation
I have read and followed all instructions in README.md.
I am using the latest version of both Open WebUI and Ollama.
I have included the browser console logs.
I have included the Docker container logs.
I have provided every relevant configuration, setting, and environment variable used in my setup.
I have clearly listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
I have documented step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation. My steps:
Start with the initial platform/version/OS and dependencies used,
Specify exact install/launch/configure commands,
List URLs visited, user input (incl. example values/emails/passwords if needed),
Describe all options and toggles enabled or changed,
Include any files or environmental changes,
Identify the expected and actual result at each stage,
Ensure any reasonably skilled user can follow and hit the same issue.
Expected Behavior
Summary
Running the official ghcr.io/open-webui/open-webui image on OpenShift with the restricted SCC fails when the app (or Python libs like transformers/tiktoken) try to write outside /app/backend/data (e.g., to $HOME or cache dirs). OpenShift injects a random non-root UID (e.g., 1000790000) and supplemental group 0, so any path not group-writable by GID 0 becomes read-only. The image mostly works because /app/backend/data is writable, but $HOME and other paths under /app default to root:root 755.
This is a standard “arbitrary UID” compatibility issue. A small Dockerfile hardening (least privilege) fixes it without breaking existing usage and improves security by avoiding reliance on a fixed user.
The process runs as random UID with supplemental GID 0 (root group).
/app/backend/data is correctly group-writable (works).
Many other paths (including $HOME=/root) are root:root 755 → permission denied when libraries write caches there.
ex: ERROR [root] An error occurred: [Errno 13] Permission denied: '/app/backend/open_webui/static/apple-touch-icon.png'
Expected
The container should be writable wherever the app and its dependencies expect to write (HOME and cache dirs), without requiring root and without baking in a specific UID. This is the recommended “arbitrary UID” pattern for OpenShift/K8s hardened clusters.
Actual
Writes outside /app/backend/data fail with EACCES unless users rebuild or wrap the container.
Root cause
OpenShift injects a random UID and keeps GID 0 as a supplemental group. If the image’s writable paths are group-owned by 0 and g+rwX, it “just works.” Today, the image sets many files to root:root 755, so $HOME and some caches are not writable.
Proposed fix (minimal, backwards-compatible)
Make the image arbitrary-UID friendly:
Ensure /app and /root are group 0 and group-writable.
Ensure the data dir is group-writable and has SGID so newly created files inherit group 0.
Do not set a fixed USER in the final image; let the platform (OpenShift restricted SCC) inject a safe UID at runtime.
Dockerfile patch (unified diff)
diff --git a/Dockerfile b/Dockerfile
index 0000000..1111111 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,6 @@
# ... existing stages omitted for brevity
FROM python:3.11-slim-bookworm AS base
+ARG OIDATA=/app/backend/data
# existing ARGs/ENVs...
WORKDIR /app/backend
@@ -120,6 +121,22 @@ COPY --chown=$UID:$GID --from=build /app/CHANGELOG.md /app/CHANGELOG.md
COPY --chown=$UID:$GID --from=build /app/package.json /app/package.json
# copy backend files
COPY --chown=$UID:$GID ./backend .
+# --- Make image arbitrary-UID friendly (OpenShift/K8s hardened) ---
+# Any random UID with supplemental GID 0 can write under these paths.
+RUN set -eux; \
+ mkdir -p "$OIDATA"; \
+ # 1) App & home must be group 0 and group-writable
+ chgrp -R 0 /app /root "$OIDATA"; \
+ chmod -R g+rwX /app /root "$OIDATA"; \
+ # 2) Keep group bit on directories so new files inherit group 0
+ find /app -type d -exec chmod g+s {} +; \
+ find "$OIDATA" -type d -exec chmod g+s {} +; \
+ # Helpful no-op if chroma cache path doesn't exist yet:
+ mkdir -p /root/.cache || true
+
EXPOSE 8080
@@ -140,7 +157,10 @@ HEALTHCHECK CMD curl --silent --fail http://localhost:${PORT:-8080}/health | jq
-USER $UID:$GID
+# IMPORTANT: Do not set a fixed USER.
+# OpenShift restricted SCC injects a safe random UID; setting USER here
+# can conflict with the cluster’s MustRunAsRange policy.
+# USER $UID:$GID
ARG BUILD_HASH
ENV WEBUI_BUILD_VERSION=${BUILD_HASH}
ENV DOCKER=true
Notes on compatibility/security
This does not grant extra privileges; it simply aligns ownership/perms with the supplemental GID 0 that restricted clusters already provide.
No behavioral changes for users running on plain Docker/Kubernetes.
Avoiding a fixed USER prevents conflicts with OpenShift’s MustRunAsRange and is the standard way to support arbitrary UIDs.
Using g+s keeps new files in group 0, so subsequent restarts/new random UIDs continue to have write access.
(Optional) Nice-to-have: writable HOME on PVC
If you want to be even stricter about not touching /root, you can set:
This keeps all caches under the mounted data volume. (The current image already exposes cache env vars like HF_HOME, SENTENCE_TRANSFORMERS_HOME, TIKTOKEN_CACHE_DIR, etc., so this is mostly a quality-of-life improvement.)
Ask
Merge the Dockerfile changes above (or equivalent) so the image is arbitrary-UID compatible out of the box.
Optionally document an “OpenShift / Restricted SCC” section that mentions:
No fixed USER in image
Group-0 + g+rwX on /app, /root, and /app/backend/data
Optional HOME=/app/backend/data/home
Actual Behavior
cf. above
Steps to Reproduce
cf. above
Logs & Screenshots
cf. above
Additional Information
No response
Originally created by @SebLz on GitHub (Aug 13, 2025).
### Check Existing Issues
- [x] I have searched the existing issues and discussions.
- [x] I am using the latest version of Open WebUI.
### Installation Method
Other
### Open WebUI Version
v0.6.22
### Ollama Version (if applicable)
_No response_
### Operating System
RHEL / OpenSHift
### Browser (if applicable)
_No response_
### Confirmation
- [x] I have read and followed all instructions in `README.md`.
- [x] I am using the latest version of **both** Open WebUI and Ollama.
- [x] I have included the browser console logs.
- [x] I have included the Docker container logs.
- [x] I have **provided every relevant configuration, setting, and environment variable used in my setup.**
- [x] I have clearly **listed every relevant configuration, custom setting, environment variable, and command-line option that influences my setup** (such as Docker Compose overrides, .env values, browser settings, authentication configurations, etc).
- [x] I have documented **step-by-step reproduction instructions that are precise, sequential, and leave nothing to interpretation**. My steps:
- Start with the initial platform/version/OS and dependencies used,
- Specify exact install/launch/configure commands,
- List URLs visited, user input (incl. example values/emails/passwords if needed),
- Describe all options and toggles enabled or changed,
- Include any files or environmental changes,
- Identify the expected and actual result at each stage,
- Ensure any reasonably skilled user can follow and hit the same issue.
### Expected Behavior
**Summary**
Running the official `ghcr.io/open-webui/open-webui` image on OpenShift with the **restricted** SCC fails when the app (or Python libs like transformers/tiktoken) try to write outside `/app/backend/data` (e.g., to `$HOME` or cache dirs). OpenShift injects a **random non-root UID** (e.g., `1000790000`) and **supplemental group 0**, so any path not group-writable by GID 0 becomes read-only. The image mostly works because `/app/backend/data` is writable, but `$HOME` and other paths under `/app` default to `root:root 755`.
This is a standard “arbitrary UID” compatibility issue. A small Dockerfile hardening (least privilege) fixes it without breaking existing usage and **improves security** by avoiding reliance on a fixed user.
A very similar fix was recently implemented for LiteLLM: [https://github.com/BerriAI/litellm/issues/13208](https://github.com/BerriAI/litellm/issues/13208)
---
**Environment**
* Platform: OpenShift 4.x (restricted SCC)
* Image: `ghcr.io/open-webui/open-webui` (e.g., v0.6.18)
* Storage: PVC mounted at `/app/backend/data`
**Observed inside the running pod**
```bash
$ id
uid=1000790000(1000790000) gid=0(root) groups=0(root),1000790000
$ pwd
/app/backend
$ ls -alh
total 32K
drwxr-xr-x. 1 root root 142 Jul 19 19:26 .
drwxr-xr-x. 1 root root 21 Jul 19 19:30 ..
drwxrws--x. 5 root 1000790000 4.0K Aug 13 14:30 data # writable (SGID + g+rw)
drwxr-xr-x. 13 root root 4.0K Jul 19 19:26 open_webui
-rwxr-xr-x. 1 root root 2.7K Jul 19 19:26 start.sh
...
```
* The process runs as **random UID** with **supplemental GID 0** (root group).
* `/app/backend/data` is correctly group-writable (works).
* Many other paths (including `$HOME=/root`) are `root:root 755` → **permission denied** when libraries write caches there.
ex:
`ERROR [root] An error occurred: [Errno 13] Permission denied: '/app/backend/open_webui/static/apple-touch-icon.png'`
**Expected**
* The container should be writable wherever the app and its dependencies expect to write (HOME and cache dirs), **without requiring root** and **without baking in a specific UID**. This is the recommended “arbitrary UID” pattern for OpenShift/K8s hardened clusters.
**Actual**
* Writes outside `/app/backend/data` fail with EACCES unless users rebuild or wrap the container.
---
## Root cause
OpenShift injects a random UID and keeps **GID 0** as a supplemental group. If the image’s writable paths are **group-owned by 0 and g+rwX**, it “just works.” Today, the image sets many files to `root:root 755`, so `$HOME` and some caches are not writable.
---
## Proposed fix (minimal, backwards-compatible)
Make the image **arbitrary-UID friendly**:
* Ensure `/app` and `/root` are **group 0** and **group-writable**.
* Ensure the **data dir** is group-writable and has **SGID** so newly created files inherit group 0.
* **Do not set a fixed `USER`** in the final image; let the platform (OpenShift restricted SCC) inject a safe UID at runtime.
### Dockerfile patch (unified diff)
```diff
diff --git a/Dockerfile b/Dockerfile
index 0000000..1111111 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,6 @@
# ... existing stages omitted for brevity
FROM python:3.11-slim-bookworm AS base
+ARG OIDATA=/app/backend/data
# existing ARGs/ENVs...
WORKDIR /app/backend
@@ -120,6 +121,22 @@ COPY --chown=$UID:$GID --from=build /app/CHANGELOG.md /app/CHANGELOG.md
COPY --chown=$UID:$GID --from=build /app/package.json /app/package.json
# copy backend files
COPY --chown=$UID:$GID ./backend .
+# --- Make image arbitrary-UID friendly (OpenShift/K8s hardened) ---
+# Any random UID with supplemental GID 0 can write under these paths.
+RUN set -eux; \
+ mkdir -p "$OIDATA"; \
+ # 1) App & home must be group 0 and group-writable
+ chgrp -R 0 /app /root "$OIDATA"; \
+ chmod -R g+rwX /app /root "$OIDATA"; \
+ # 2) Keep group bit on directories so new files inherit group 0
+ find /app -type d -exec chmod g+s {} +; \
+ find "$OIDATA" -type d -exec chmod g+s {} +; \
+ # Helpful no-op if chroma cache path doesn't exist yet:
+ mkdir -p /root/.cache || true
+
EXPOSE 8080
@@ -140,7 +157,10 @@ HEALTHCHECK CMD curl --silent --fail http://localhost:${PORT:-8080}/health | jq
-USER $UID:$GID
+# IMPORTANT: Do not set a fixed USER.
+# OpenShift restricted SCC injects a safe random UID; setting USER here
+# can conflict with the cluster’s MustRunAsRange policy.
+# USER $UID:$GID
ARG BUILD_HASH
ENV WEBUI_BUILD_VERSION=${BUILD_HASH}
ENV DOCKER=true
```
**Notes on compatibility/security**
* This does **not** grant extra privileges; it simply aligns ownership/perms with the **supplemental GID 0** that restricted clusters already provide.
* No behavioral changes for users running on plain Docker/Kubernetes.
* Avoiding a fixed `USER` prevents conflicts with OpenShift’s `MustRunAsRange` and is the standard way to support arbitrary UIDs.
* Using `g+s` keeps new files in group 0, so subsequent restarts/new random UIDs continue to have write access.
---
## (Optional) Nice-to-have: writable HOME on PVC
If you want to be even stricter about not touching `/root`, you can set:
```dockerfile
ENV HOME=/app/backend/data/home
RUN mkdir -p /app/backend/data/home && chgrp -R 0 /app/backend/data/home && chmod -R g+rwX /app/backend/data/home
```
This keeps all caches under the mounted data volume. (The current image already exposes cache env vars like `HF_HOME`, `SENTENCE_TRANSFORMERS_HOME`, `TIKTOKEN_CACHE_DIR`, etc., so this is mostly a quality-of-life improvement.)
---
**Ask**
1. Merge the Dockerfile changes above (or equivalent) so the image is **arbitrary-UID compatible** out of the box.
2. Optionally document an “OpenShift / Restricted SCC” section that mentions:
* No fixed `USER` in image
* Group-0 + `g+rwX` on `/app`, `/root`, and `/app/backend/data`
* Optional `HOME=/app/backend/data/home`
### Actual Behavior
cf. above
### Steps to Reproduce
cf. above
### Logs & Screenshots
cf. above
### Additional Information
_No response_
GiteaMirror
added the bug label 2025-11-11 16:44:24 -06:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @SebLz on GitHub (Aug 13, 2025).
Check Existing Issues
Installation Method
Other
Open WebUI Version
v0.6.22
Ollama Version (if applicable)
No response
Operating System
RHEL / OpenSHift
Browser (if applicable)
No response
Confirmation
README.md.Expected Behavior
Summary
Running the official
ghcr.io/open-webui/open-webuiimage on OpenShift with the restricted SCC fails when the app (or Python libs like transformers/tiktoken) try to write outside/app/backend/data(e.g., to$HOMEor cache dirs). OpenShift injects a random non-root UID (e.g.,1000790000) and supplemental group 0, so any path not group-writable by GID 0 becomes read-only. The image mostly works because/app/backend/datais writable, but$HOMEand other paths under/appdefault toroot:root 755.This is a standard “arbitrary UID” compatibility issue. A small Dockerfile hardening (least privilege) fixes it without breaking existing usage and improves security by avoiding reliance on a fixed user.
A very similar fix was recently implemented for LiteLLM: https://github.com/BerriAI/litellm/issues/13208
Environment
ghcr.io/open-webui/open-webui(e.g., v0.6.18)/app/backend/dataObserved inside the running pod
/app/backend/datais correctly group-writable (works).$HOME=/root) areroot:root 755→ permission denied when libraries write caches there.ex:
ERROR [root] An error occurred: [Errno 13] Permission denied: '/app/backend/open_webui/static/apple-touch-icon.png'Expected
Actual
/app/backend/datafail with EACCES unless users rebuild or wrap the container.Root cause
OpenShift injects a random UID and keeps GID 0 as a supplemental group. If the image’s writable paths are group-owned by 0 and g+rwX, it “just works.” Today, the image sets many files to
root:root 755, so$HOMEand some caches are not writable.Proposed fix (minimal, backwards-compatible)
Make the image arbitrary-UID friendly:
/appand/rootare group 0 and group-writable.USERin the final image; let the platform (OpenShift restricted SCC) inject a safe UID at runtime.Dockerfile patch (unified diff)
Notes on compatibility/security
USERprevents conflicts with OpenShift’sMustRunAsRangeand is the standard way to support arbitrary UIDs.g+skeeps new files in group 0, so subsequent restarts/new random UIDs continue to have write access.(Optional) Nice-to-have: writable HOME on PVC
If you want to be even stricter about not touching
/root, you can set:This keeps all caches under the mounted data volume. (The current image already exposes cache env vars like
HF_HOME,SENTENCE_TRANSFORMERS_HOME,TIKTOKEN_CACHE_DIR, etc., so this is mostly a quality-of-life improvement.)Ask
Merge the Dockerfile changes above (or equivalent) so the image is arbitrary-UID compatible out of the box.
Optionally document an “OpenShift / Restricted SCC” section that mentions:
USERin imageg+rwXon/app,/root, and/app/backend/dataHOME=/app/backend/data/homeActual Behavior
cf. above
Steps to Reproduce
cf. above
Logs & Screenshots
cf. above
Additional Information
No response
@tjbck commented on GitHub (Aug 13, 2025):
PR welcome