From f94424c43b6e29509402cd353fc33799f07b4897 Mon Sep 17 00:00:00 2001 From: Pi Web Agent Date: Sun, 21 Jun 2026 22:51:29 +0000 Subject: [PATCH] fix: name docker runtime user --- .changeset/docker-user-name.md | 5 +++++ docker/Dockerfile | 4 +++- docker/Dockerfile.dev | 2 ++ docker/README.md | 6 +++--- docker/bin/install-opensuse-base | 36 ++++++++++++++++++++++++++------ docker/compose.dev.yml | 2 ++ docker/compose.yml | 2 ++ docker/install.sh | 2 +- 8 files changed, 48 insertions(+), 11 deletions(-) create mode 100644 .changeset/docker-user-name.md diff --git a/.changeset/docker-user-name.md b/.changeset/docker-user-name.md new file mode 100644 index 0000000..cfddfc7 --- /dev/null +++ b/.changeset/docker-user-name.md @@ -0,0 +1,5 @@ +--- +"@jmfederico/pi-web": patch +--- + +Create the Docker image `pi-web` user with the configured host UID/GID so container terminals show a normal username instead of `I have no name!`. diff --git a/docker/Dockerfile b/docker/Dockerfile index c411301..bb2b80a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,6 +10,8 @@ FROM ${OPENSUSE_IMAGE} AS base ARG NODEJS_MAJOR=22 ARG NODEJS_REPO=auto ARG PI_WEB_EXTRA_ZYPPER_PACKAGES="" +ARG PI_WEB_UID=1000 +ARG PI_WEB_GID=1000 SHELL ["/bin/bash", "-o", "pipefail", "-c"] @@ -68,7 +70,7 @@ RUN bash -euxo pipefail -c '\ ' WORKDIR /workspace -USER node +USER pi-web EXPOSE 8504 diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev index a1a9608..f5eda36 100644 --- a/docker/Dockerfile.dev +++ b/docker/Dockerfile.dev @@ -10,6 +10,8 @@ FROM ${OPENSUSE_IMAGE} AS dev ARG NODEJS_MAJOR=22 ARG NODEJS_REPO=auto ARG PI_WEB_EXTRA_ZYPPER_PACKAGES="" +ARG PI_WEB_UID=1000 +ARG PI_WEB_GID=1000 SHELL ["/bin/bash", "-o", "pipefail", "-c"] diff --git a/docker/README.md b/docker/README.md index d9bfb74..fd9cd75 100644 --- a/docker/README.md +++ b/docker/README.md @@ -91,7 +91,7 @@ Common environment variables written to `.env`: | Variable | Purpose | | --- | --- | -| `PI_WEB_UID`, `PI_WEB_GID` | user/group used by the runtime containers | +| `PI_WEB_UID`, `PI_WEB_GID` | user/group used by the runtime containers and the image's `pi-web` account | | `DOCKER_GID` | extra group used for Docker socket access | | `PI_WEB_DOCKER_DATA_DIR` | persistent data bind mount | | `PI_WEB_BIND_ADDR`, `PI_WEB_PORT` | host bind address and port | @@ -108,7 +108,7 @@ Host-derived IDs are refreshed on rerun unless you explicitly override them. Use ### Base image and tooling -The Docker runtime and development images are openSUSE Tumbleweed based by default. They install Node.js 22, npm, `npx`, and Corepack through zypper, using the openSUSE Node.js build service repository when needed for the selected architecture. The image also includes common agent/development tools such as Git/Git LFS, GitHub CLI, OpenSSH, Python with pip/virtualenv and headers, native build tooling, `jq`, `ripgrep`, `fd`, `fzf`, `bat`, ShellCheck, archive tools, network utilities, and the Docker CLI. +The Docker runtime and development images are openSUSE Tumbleweed based by default. They install Node.js 22, npm, `npx`, and Corepack through zypper, using the openSUSE Node.js build service repository when needed for the selected architecture. The image's `pi-web` account is created with `PI_WEB_UID:PI_WEB_GID`, so shells have a passwd entry instead of showing `I have no name!` when the host user is not `1000:1000`. The image also includes common agent/development tools such as Git/Git LFS, GitHub CLI, OpenSSH, Python with pip/virtualenv and headers, native build tooling, `jq`, `ripgrep`, `fd`, `fzf`, `bat`, ShellCheck, archive tools, network utilities, and the Docker CLI. Install extra distro packages without writing a hook by setting a whitespace-delimited package list: @@ -266,7 +266,7 @@ Restart `sessiond` manually after changes that affect `src/server/sessiond.ts`, The dev setup intentionally has the same Docker socket and broad host mounts as the runtime setup. The same trust warnings apply. -On startup, a short `data-init` service creates the shared `/data` subdirectories and gives them to `PI_WEB_UID:PI_WEB_GID`. This handles the common Flatcar/Docker case where a missing bind-mount directory is created as root by the Docker daemon. +On startup, a short `data-init` service creates the shared `/data` subdirectories and gives them to `PI_WEB_UID:PI_WEB_GID`. This handles the common Flatcar/Docker case where a missing bind-mount directory is created as root by the Docker daemon. Because the image also builds its `pi-web` account with those IDs, rebuild the image if you change `PI_WEB_UID` or `PI_WEB_GID`. ### Sharing runtime and development state diff --git a/docker/bin/install-opensuse-base b/docker/bin/install-opensuse-base index 7e0adfe..fdfb888 100755 --- a/docker/bin/install-opensuse-base +++ b/docker/bin/install-opensuse-base @@ -4,6 +4,8 @@ set -euo pipefail nodejs_major=${NODEJS_MAJOR:-22} nodejs_repo=${NODEJS_REPO:-auto} extra_zypper_packages=${PI_WEB_EXTRA_ZYPPER_PACKAGES:-} +runtime_uid=${PI_WEB_UID:-1000} +runtime_gid=${PI_WEB_GID:-1000} nodejs_repo_flavor() { local rpm_arch @@ -120,16 +122,38 @@ npx --version python3 --version git --version -if ! getent group node >/dev/null 2>&1; then - groupadd --gid 1000 node +case "$runtime_uid" in + ""|*[!0-9]*) + echo "PI_WEB_UID must be a numeric user ID, got: $runtime_uid" >&2 + exit 1 + ;; +esac + +case "$runtime_gid" in + ""|*[!0-9]*) + echo "PI_WEB_GID must be a numeric group ID, got: $runtime_gid" >&2 + exit 1 + ;; +esac + +runtime_user=pi-web +runtime_group=pi-web +if getent group "$runtime_gid" >/dev/null 2>&1; then + runtime_group=$(getent group "$runtime_gid" | cut -d: -f1) +elif getent group "$runtime_group" >/dev/null 2>&1; then + groupmod --gid "$runtime_gid" "$runtime_group" +else + groupadd --gid "$runtime_gid" "$runtime_group" fi -if ! id node >/dev/null 2>&1; then - useradd --uid 1000 --gid node --create-home --home-dir /home/node --shell /bin/bash node +if id "$runtime_user" >/dev/null 2>&1; then + usermod --non-unique --uid "$runtime_uid" --gid "$runtime_group" --home "/home/$runtime_user" --shell /bin/bash "$runtime_user" +else + useradd --non-unique --uid "$runtime_uid" --gid "$runtime_group" --create-home --home-dir "/home/$runtime_user" --shell /bin/bash "$runtime_user" fi -mkdir -p /data/home /data/config /data/npm-cache /data/pi-web /data/pi-agent /workspace -chown -R node:node /data /workspace /home/node +mkdir -p /data/home /data/config /data/npm-cache /data/pi-web /data/pi-agent /workspace "/home/$runtime_user" +chown -R "$runtime_uid:$runtime_gid" /data /workspace "/home/$runtime_user" zypper clean --all rm -rf /var/cache/zypp/* diff --git a/docker/compose.dev.yml b/docker/compose.dev.yml index cf582de..fec1abc 100644 --- a/docker/compose.dev.yml +++ b/docker/compose.dev.yml @@ -8,6 +8,8 @@ x-pi-web-dev-build: &pi-web-dev-build NODEJS_MAJOR: ${PI_WEB_NODEJS_MAJOR:-22} NODEJS_REPO: ${PI_WEB_NODEJS_REPO:-auto} PI_WEB_EXTRA_ZYPPER_PACKAGES: ${PI_WEB_EXTRA_ZYPPER_PACKAGES:-} + PI_WEB_UID: ${PI_WEB_UID:-1000} + PI_WEB_GID: ${PI_WEB_GID:-1000} x-pi-web-dev-environment: &pi-web-dev-environment HOME: /data/home diff --git a/docker/compose.yml b/docker/compose.yml index b35a6bd..9e37247 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -8,6 +8,8 @@ x-pi-web-build: &pi-web-build NODEJS_MAJOR: ${PI_WEB_NODEJS_MAJOR:-22} NODEJS_REPO: ${PI_WEB_NODEJS_REPO:-auto} PI_WEB_EXTRA_ZYPPER_PACKAGES: ${PI_WEB_EXTRA_ZYPPER_PACKAGES:-} + PI_WEB_UID: ${PI_WEB_UID:-1000} + PI_WEB_GID: ${PI_WEB_GID:-1000} PI_WEB_VERSION: ${PI_WEB_VERSION:-latest} PI_VERSION: ${PI_VERSION:-latest} CACHE_BUST: ${CACHE_BUST:-local} diff --git a/docker/install.sh b/docker/install.sh index 5e26fda..cfd902c 100755 --- a/docker/install.sh +++ b/docker/install.sh @@ -388,7 +388,7 @@ cat >"$temp_env" <