| 1 | #!/bin/sh |
| 2 | # Entrypoint wrapper for the opt-in `vllm-openai-nonroot` image. |
| 3 | # |
| 4 | # The image also ships a `vllm` user (UID 2000, GID 0) with HOME /home/vllm |
| 5 | # and a group-0-writable home directory. When the container is launched with |
| 6 | # `--user 2000:0` (or any other UID in group 0) the passwd entry is enough on |
| 7 | # its own: Docker picks up HOME=/home/vllm, getpass.getuser() resolves to |
| 8 | # "vllm", and every cache dir (HF, Triton, Inductor, vLLM, Numba, Outlines) |
| 9 | # that defaults to `$HOME/.cache/...` lands in a writable location. |
| 10 | # |
| 11 | # This wrapper exists for the *arbitrary-UID* case (e.g. OpenShift's |
| 12 | # `runAsUser: 1000540000` Restricted Pod Security Standard) where the caller |
| 13 | # UID is not in /etc/passwd at all. In that case: |
| 14 | # * $HOME may be unset or resolve to "/" (unwritable). |
| 15 | # * getpass.getuser() falls back to pwd.getpwuid() -> KeyError. |
| 16 | # |
| 17 | # The wrapper re-points $HOME to /home/vllm when writable, /tmp/vllm-home.XXXXXX |
| 18 | # otherwise, and defaults $USER to "vllm" so the pwd-lookup path is never |
| 19 | # taken. Everything else is forwarded to `vllm serve`. |
| 20 | # |
| 21 | # Non-empty caller-set env vars (HOME, USER, LOGNAME) are preserved, so |
| 22 | # existing K8s manifests and `docker run -e ...` keep working unchanged. |
| 23 | # Unset or empty values fall through to the wrapper's defaults, matching |
| 24 | # what shell code typically expects from "unset". |
| 25 | |
| 26 | set -eu |
| 27 | |
| 28 | if [ -z "${HOME:-}" ] || [ ! -w "${HOME}" ]; then |
| 29 | if [ -w /home/vllm ]; then |
| 30 | export HOME=/home/vllm |
| 31 | else |
| 32 | if _h="$(mktemp -d /tmp/vllm-home.XXXXXX 2>/dev/null)"; then |
| 33 | export HOME="$_h" |
| 34 | chmod 0700 "$HOME" 2>/dev/null || true |
| 35 | else |
| 36 | export HOME=/tmp |
| 37 | fi |
| 38 | unset _h |
| 39 | fi |
| 40 | fi |
| 41 | |
| 42 | # Preserve the caller's cwd whenever it's still usable. A read-only mount |
| 43 | # (e.g. `docker run -w /models ... --model ./llama.gguf` where /models is |
| 44 | # the user's model share) is a legitimate, usable cwd — vllm only needs to |
| 45 | # *read* relative paths from there. We only fall back to $HOME when the |
| 46 | # cwd itself is truly inaccessible (no search bit, deleted inode, mount |
| 47 | # gone, etc.), which is when `cd .` actually fails. |
| 48 | # |
| 49 | # This is the accessibility check, not a writability check; the latter |
| 50 | # would silently rewrite cwd for any read-only workflow and break relative |
| 51 | # argv like `--model ./llama.gguf`, `--chat-template ./t.jinja`, relative |
| 52 | # TLS cert paths, etc. |
| 53 | if ! cd . 2>/dev/null; then |
| 54 | cd "$HOME" |
| 55 | fi |
| 56 | |
| 57 | # getpass.getuser() prefers $USER/$LOGNAME/etc. before hitting getpwuid(); |
| 58 | # setting it here makes the "UID not in passwd" path a no-op for everything |
| 59 | # in the process tree. |
| 60 | if [ -z "${USER:-}" ]; then |
| 61 | export USER=vllm |
| 62 | fi |
| 63 | if [ -z "${LOGNAME:-}" ]; then |
| 64 | export LOGNAME="$USER" |
| 65 | fi |
| 66 | |
| 67 | # Shell-level tooling (`whoami`, bash's `\u` prompt, `id -un`, `sudo`) does |
| 68 | # NOT consult $USER; it calls getpwuid(geteuid()) directly. For arbitrary |
| 69 | # runtime UIDs in OpenShift-style deploys this returns "I have no name!". |
| 70 | # If /etc/passwd is group-0 writable (set at build time) and doesn't yet |
| 71 | # have an entry for this UID, append a synthetic one so every downstream |
| 72 | # consumer sees a consistent "vllm" identity. |
| 73 | # |
| 74 | # We parse the passwd file directly instead of calling `getent` because |
| 75 | # the container's NSS is typically just files anyway, and this lets us |
| 76 | # unit-test via the VLLM_PASSWD_FILE hook (undocumented; production uses |
| 77 | # /etc/passwd). |
| 78 | _passwd_file="${VLLM_PASSWD_FILE:-/etc/passwd}" |
| 79 | _uid="$(id -u)" |
| 80 | if [ -w "$_passwd_file" ] \ |
| 81 | && ! awk -F: -v u="$_uid" '$3==u {found=1; exit} END {exit !found}' "$_passwd_file" 2>/dev/null; then |
| 82 | printf 'vllm:x:%s:%s:vllm:%s:/bin/bash\n' \ |
| 83 | "$_uid" "$(id -g)" "$HOME" >> "$_passwd_file" |
| 84 | fi |
| 85 | unset _uid _passwd_file |
| 86 | |
| 87 | exec vllm serve "$@" |