Summary
`reach create --persist-profile ` mounts `~/.local/share/reach/profiles/` from the host into the container at `/home/sandbox/.config/google-chrome-profiles/`. The host directory is created (if missing) by reach as the host user (uid 1000 in my case, ctodie). Inside the container, the `sandbox` user is uid 1001 because the Ubuntu 24.04 base image already has `ubuntu` at uid 1000.
Result: when Chrome inside the container tries to write `SingletonLock`, it fails with `Permission denied`:
```
[65:65:0407/102612.373095:ERROR:chrome/browser/process_singleton_posix.cc:345]
Failed to create /home/sandbox/.config/google-chrome-profiles/todie/SingletonLock: Permission denied (13)
```
Inside the container the directory shows up as owned by `ubuntu` (uid 1000), which neither `sandbox` (uid 1001) nor `root` cleanly handles without an extra step.
Workaround in use
After `reach create`, the caller runs:
```bash
docker exec -u root chown -R 1001:1001 /home/sandbox/.config/google-chrome-profiles/
```
Then Chrome can launch. This is what `todie/revenant`'s start-daemon.sh does today as a workaround.
Suggested fixes (any one is fine)
- Delete the `ubuntu` user in the Dockerfile before `useradd sandbox` so `sandbox` lands at uid 1000 and matches typical host uids:
```Dockerfile
RUN userdel -r ubuntu 2>/dev/null || true \
&& useradd -m -s /bin/bash -u 1000 sandbox
```
- Have reach chown the profile dir to the sandbox uid after container start, before health check completes.
- Document the workaround prominently in `docs/persistent-profiles.md` and add it to the `reach create --persist-profile` success summary.
(1) is the cleanest because it removes the friction at its root. (2) keeps the Dockerfile honest about its uid choice. (3) is the cheapest but pushes the problem onto every caller.
Discovered while
Wiring Chrome's CDP through to a host process (todie/revenant) for browser-based posting. Same use case as PR #4 (auth_handoff + persist-profile).
Repro
```bash
reach create --name foo --persist-profile bar
docker exec -u sandbox foo google-chrome --user-data-dir=/home/sandbox/.config/google-chrome-profiles/bar about:blank
Permission denied creating SingletonLock
```
Summary
`reach create --persist-profile ` mounts `~/.local/share/reach/profiles/` from the host into the container at `/home/sandbox/.config/google-chrome-profiles/`. The host directory is created (if missing) by reach as the host user (uid 1000 in my case, ctodie). Inside the container, the `sandbox` user is uid 1001 because the Ubuntu 24.04 base image already has `ubuntu` at uid 1000.
Result: when Chrome inside the container tries to write `SingletonLock`, it fails with `Permission denied`:
```
[65:65:0407/102612.373095:ERROR:chrome/browser/process_singleton_posix.cc:345]
Failed to create /home/sandbox/.config/google-chrome-profiles/todie/SingletonLock: Permission denied (13)
```
Inside the container the directory shows up as owned by `ubuntu` (uid 1000), which neither `sandbox` (uid 1001) nor `root` cleanly handles without an extra step.
Workaround in use
After `reach create`, the caller runs:
```bash
docker exec -u root chown -R 1001:1001 /home/sandbox/.config/google-chrome-profiles/
```
Then Chrome can launch. This is what `todie/revenant`'s start-daemon.sh does today as a workaround.
Suggested fixes (any one is fine)
```Dockerfile
RUN userdel -r ubuntu 2>/dev/null || true \
&& useradd -m -s /bin/bash -u 1000 sandbox
```
(1) is the cleanest because it removes the friction at its root. (2) keeps the Dockerfile honest about its uid choice. (3) is the cheapest but pushes the problem onto every caller.
Discovered while
Wiring Chrome's CDP through to a host process (todie/revenant) for browser-based posting. Same use case as PR #4 (auth_handoff + persist-profile).
Repro
```bash
reach create --name foo --persist-profile bar
docker exec -u sandbox foo google-chrome --user-data-dir=/home/sandbox/.config/google-chrome-profiles/bar about:blank
Permission denied creating SingletonLock
```