You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature] Run the PD, Store and Server images as a non-root user #3211
The published hugegraph/pd, hugegraph/store and hugegraph/server images all run their Java process as root: none of the three declares a USER, checked against the current latest image configs on Docker Hub (registry config blob, .config.User empty on all three, 2026-09-17).
Why it matters on Kubernetes:
A namespace under the restricted Pod Security Standard rejects these pods outright (runAsNonRoot != true).
The Helm chart in feat(helm): add HStore deployment chart #3132 cannot set runAsNonRoot: true or readOnlyRootFilesystem: true as defaults; it documents this in its Limitations and ships the remaining hardening it can (allowPrivilegeEscalation: false, capabilities.drop: [ALL], seccompProfile: RuntimeDefault).
Security scanners (kube-score, polaris, kubescape) flag every workload for it, which any adopter evaluating the chart sees on day one; the 2026-09-10 chart test campaign recorded it as a failing kubescape NSA control on both branches.
Proposal:
Create a fixed-UID user in each Dockerfile (the toolchain's Hubble image can follow the same pattern later) and chown the data and log directories to it.
Declare USER in the image and keep the entrypoints from writing outside the data, log and temp directories, so readOnlyRootFilesystem becomes possible as a follow-up.
Ship it in a minor release with an upgrade note: existing PVC data written as root needs a one-time chown, or an initContainer / fsGroup note in the chart.
The chart side is ready to adopt this the release it lands: podSecurityContext and securityContext are fully configurable per component today, so only the defaults would change.
I'd like to take this, but before writing code I want to agree on the shape, since it touches all three images at once and existing data on PVCs. What I checked in the repo and in the :latest images of 2026-09-18:
None of the three Dockerfiles declares USER; each has a VOLUME on the whole install directory (/hugegraph-server, /hugegraph-pd, /hugegraph-store), so data, logs, conf and bin/pid are one root-owned tree; the entrypoint is dumb-init + docker-entrypoint.sh, HEALTHCHECK through curl. Hubble starts as root too.
What writes at runtime: all three start scripts write bin/pid and logs/* (including heap dumps via -XX:HeapDumpPath=logs, and logs/gc.log on the Store); Jetty unpacks into /tmp; the Server entrypoint appends to conf/graphs/hugegraph.properties and conf/rest-server.properties and creates an init marker; the PD and Store entrypoints write nothing (their config goes through SPRING_APPLICATION_JSON). Data: pd_data, storage, rocksdb-data under the install directory.
Step 1, this PR: non-root. A fixed UID/GID and user (hugegraph) in each Dockerfile, chown of the install directory, USER before ENTRYPOINT; dumb-init and HEALTHCHECK unchanged. Start scripts unchanged except one thing: the pid file out of bin/ (question 2). CI: extend the existing image tests (docker/test-compose.sh smoke, test-wait-storage.sh) with an id -u check inside the container and a start under --user/runAsNonRoot. Upgrade note: data on existing volumes was written as root, one-time chown, and in the chart fsGroup plus an optional initContainer that does it for the operator.
Step 2, follow-up: readOnlyRootFilesystem. Requires everything written to live on mounted volumes: logs and /tmp on emptyDir, the pid next to the logs, and the Server entrypoint rendering its config into a writable directory instead of editing conf/ in place. A separate PR, since it changes the Server entrypoint and the chart templates.
Validation I can do
On a three-node k3s with the #221 chart: a namespace with pod-security.kubernetes.io/enforce: restricted, kubescape before and after, the full fault battery of 2026-09-16 and the readiness scenarios on the new images, plus an upgrade of an existing cluster whose data was written as root, through the initContainer. I'd build the images with docker/bake.hcl and overlay them on the cluster the way I tested #3221.
Four questions
UID. I'd propose a fixed 1000:1000: least friction with fsGroup and with provisioners like local-path, and the default user of many base images. The alternative is a dedicated high UID (e.g. 10001) that collides with nothing on the host. Do you have a preference or a requirement from the chart / scanner side?
Pid file. The scripts write bin/pid; in step 2 bin/ becomes read-only. Move the pid to logs/ now (one change in the three start/stop scripts, consistent with the tarball), or leave it in bin/ for step 1 and move it together with read-only?
Server config. The entrypoint edits conf/ in place. For step 1 it is enough that conf/ belongs to the image user. For step 2 I'd render into /hugegraph-server/run/conf (emptyDir) and start the server from there. Any reason to do that right away?
Existing data. The upgrade note plus fsGroup in the chart cover volumes where fsGroup works; hostPath/local-path it does not. Do you want an optional initContainer (chown -R on dataPath, off by default) in the chart as part of this step, or the note only?
After the answers I'll do the PR for the images and tests, and the chart diff under #221.
Still open on my side: the four questions in the design comment above are what I need before writing code. A yes or no on the direction is enough for me to start with one image as a first PR.
Activity
SebastianGruza commentedon Sep 20, 2026
I'd like to take this, but before writing code I want to agree on the shape, since it touches all three images at once and existing data on PVCs. What I checked in the repo and in the
:latestimages of 2026-09-18:USER; each has aVOLUMEon the whole install directory (/hugegraph-server,/hugegraph-pd,/hugegraph-store), so data, logs,confandbin/pidare one root-owned tree; the entrypoint isdumb-init+docker-entrypoint.sh,HEALTHCHECKthrough curl. Hubble starts as root too.bin/pidandlogs/*(including heap dumps via-XX:HeapDumpPath=logs, andlogs/gc.logon the Store); Jetty unpacks into/tmp; the Server entrypoint appends toconf/graphs/hugegraph.propertiesandconf/rest-server.propertiesand creates an init marker; the PD and Store entrypoints write nothing (their config goes throughSPRING_APPLICATION_JSON). Data:pd_data,storage,rocksdb-dataunder the install directory.podSecurityContext/securityContextper component and mounts the PVC only atdataPath, so logs,confandbinlive in the image layer today.Proposal: two steps
Step 1, this PR: non-root. A fixed UID/GID and user (
hugegraph) in each Dockerfile,chownof the install directory,USERbeforeENTRYPOINT;dumb-initandHEALTHCHECKunchanged. Start scripts unchanged except one thing: the pid file out ofbin/(question 2). CI: extend the existing image tests (docker/test-compose.sh smoke,test-wait-storage.sh) with anid -ucheck inside the container and a start under--user/runAsNonRoot. Upgrade note: data on existing volumes was written as root, one-timechown, and in the chartfsGroupplus an optional initContainer that does it for the operator.Step 2, follow-up:
readOnlyRootFilesystem. Requires everything written to live on mounted volumes:logsand/tmponemptyDir, the pid next to the logs, and the Server entrypoint rendering its config into a writable directory instead of editingconf/in place. A separate PR, since it changes the Server entrypoint and the chart templates.Validation I can do
On a three-node k3s with the #221 chart: a namespace with
pod-security.kubernetes.io/enforce: restricted, kubescape before and after, the full fault battery of 2026-09-16 and the readiness scenarios on the new images, plus an upgrade of an existing cluster whose data was written as root, through the initContainer. I'd build the images withdocker/bake.hcland overlay them on the cluster the way I tested #3221.Four questions
1000:1000: least friction withfsGroupand with provisioners like local-path, and the default user of many base images. The alternative is a dedicated high UID (e.g. 10001) that collides with nothing on the host. Do you have a preference or a requirement from the chart / scanner side?bin/pid; in step 2bin/becomes read-only. Move the pid tologs/now (one change in the three start/stop scripts, consistent with the tarball), or leave it inbin/for step 1 and move it together with read-only?conf/in place. For step 1 it is enough thatconf/belongs to the image user. For step 2 I'd render into/hugegraph-server/run/conf(emptyDir) and start the server from there. Any reason to do that right away?fsGroupin the chart cover volumes wherefsGroupworks; hostPath/local-path it does not. Do you want an optional initContainer (chown -RondataPath, off by default) in the chart as part of this step, or the note only?After the answers I'll do the PR for the images and tests, and the chart diff under #221.
github-actions commentedon Oct 5, 2026
Due to the lack of activity, the current issue is marked as stale and will be closed after 20 days, any update will remove the stale label
SebastianGruza commentedon Oct 10, 2026
Still open on my side: the four questions in the design comment above are what I need before writing code. A yes or no on the direction is enough for me to start with one image as a first PR.