Skip to content

Commit f180997

Browse files
chapterjasonclaude
andcommitted
web-shell: run service as _REMOTE_USER, repair root-owned ~/.cache (1.2.0)
Systemd unit had no User=, so ExecStart ran as root and web-shell created $HOME/.cache on the remote user's home owned by root. Resolve the user via _REMOTE_USER (matching the nvm and claude-code features), set User/Group/ WorkingDirectory/HOME on the unit, and chown any pre-existing ~/.cache left behind by <1.2.0 installs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 4ccf9f6 commit f180997

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

src/web-shell/devcontainer-feature.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "web-shell",
3-
"version": "1.1.0",
3+
"version": "1.2.0",
44
"name": "web-shell",
55
"description": "Installs web-shell (persistent browser terminal backed by dtach) from the GitHub release tarball into the global Node install, and registers a systemd unit so the service starts automatically on container boot. Also publishes the service as a Coder workspace app.",
66
"documentationURL": "https://github.com/SoureCode/devcontainer-features/tree/master/src/web-shell",

src/web-shell/install.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@ WS_PORT="${PORT:-4000}"
1919
WS_HOST="${HOST:-127.0.0.1}"
2020
WS_AUTH_TOKEN="${AUTHTOKEN:-}"
2121

22+
# Resolve the container's remote user. The devcontainer spec injects
23+
# _REMOTE_USER at feature-install time; USERNAME is the older fallback some
24+
# bases still set. Default to root only when neither is present. Without this,
25+
# the systemd unit would run ExecStart as root and web-shell would create
26+
# $HOME/.cache owned by root on the remote user's home.
27+
USER_NAME="${_REMOTE_USER:-${USERNAME:-root}}"
28+
if [ "$USER_NAME" = "root" ]; then
29+
USER_GROUP="root"
30+
USER_HOME="/root"
31+
else
32+
USER_GROUP="$(id -gn "$USER_NAME")"
33+
USER_HOME="$(getent passwd "$USER_NAME" | cut -d: -f6)"
34+
fi
35+
2236
# 1. OS deps: dtach as the detachable session backend, build-essential + python3
2337
# because node-pty compiles native bindings, plus curl/jq for release lookup.
2438
APT_PKGS=""
@@ -91,6 +105,10 @@ After=network.target
91105
92106
[Service]
93107
Type=simple
108+
User=${USER_NAME}
109+
Group=${USER_GROUP}
110+
WorkingDirectory=${USER_HOME}
111+
Environment=HOME=${USER_HOME}
94112
Environment=HOST=${WS_HOST}
95113
Environment=PORT=${WS_PORT}
96114
Environment=AUTH_TOKEN=${WS_AUTH_TOKEN}
@@ -103,6 +121,12 @@ WantedBy=multi-user.target
103121
EOF
104122
chmod 0644 /etc/systemd/system/web-shell.service
105123

124+
# Repair state from earlier feature versions (<1.2.0) that ran the service as
125+
# root and left $HOME/.cache root-owned. Idempotent; cheap on clean installs.
126+
if [ "$USER_NAME" != "root" ] && [ -d "$USER_HOME/.cache" ]; then
127+
chown -R "$USER_NAME:$USER_GROUP" "$USER_HOME/.cache" || true
128+
fi
129+
106130
INIT_COMM="$(ps -p 1 -o comm= 2>/dev/null | tr -d '[:space:]' || true)"
107131
if [ "$INIT_COMM" = "systemd" ]; then
108132
systemctl daemon-reload

0 commit comments

Comments
 (0)