mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
Install shared shims, managed configuration, and login-shell PATH integration so golden images and multi-user hosts can protect package installs for every user. Co-authored-by: Cursor <cursoragent@cursor.com>
7.6 KiB
7.6 KiB
name, overview, todos, isProject
| name | overview | todos | isProject | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| System install design | Design for `pmg setup install --system` (Linux): general system-wide shims + config + `/etc/profile.d`, motivated by Docker golden images but not Docker-specific. Venv-after-activate remains a documented limitation. |
|
false |
PMG System Install (--system) — Design
Re-evaluation of issue #317 against current codebase. Prerequisite PR #323 (PMG_SHIM_PATH) is already merged.
Goal
Root can install PMG once for all users on a Linux host (golden Docker image, shared VM). Later USER appuser / non-root logins get interception without per-user pmg setup install.
Primary motivator: package installs inside docker build (host GHA PMG cannot see them). Feature itself is a general Linux system install, not a Docker mode.
Non-goals (v1)
- macOS / Windows
--system - Persistent proxy baked into images
- In-place wrap of
/usr/local/binbinaries - Shell function wrappers (venv interactive fix)
- Making host PMG intercept
docker buildfrom outside the image - Closing the venv-after-
activatePATH race via shims
Locked decisions
| Topic | Choice |
|---|---|
| Scope | Linux only |
| Shim location | /usr/local/lib/pmg/bin (not /usr/local/bin) |
| Config | Write /etc/safedep/pmg/config.yml (read path already exists) |
| PATH on VMs / login shells | /etc/profile.d/pmg.sh prepends shim dir |
| PATH in Docker builds | Image author sets ENV PATH="/usr/local/lib/pmg/bin:$PATH" (documented; required for RUN) |
Venv after activate |
Documented limitation → use pmg pip … |
| Proxy-in-image | Rejected for this use case |
| Layers | System and per-user installs independent |
User flows
Golden Docker base
RUN curl -fsSL … | sh && pmg setup install --system
ENV PATH="/usr/local/lib/pmg/bin:$PATH"
Child images:
FROM company/golden:latest
USER appuser
RUN npm ci # intercepted
RUN pip install pkg # intercepted (system pip)
# RUN .venv/bin/activate && pip install x # NOT intercepted — use pmg pip
Multi-user Linux VM
sudo pmg setup install --system
# new login shells get PATH via /etc/profile.d/pmg.sh
CLI UX
sudo pmg setup install --system # root-only; fail fast otherwise
sudo pmg setup remove --system
pmg setup info # reports system / user / both
pmg setup doctor # checks system shim dir + on PATH
- Root without
--system→ warn (other users not covered; point to--system), then proceed with per-user install into root’s HOME. - Non-root
--system→usefulerror+ sudo guidance.
Architecture
flowchart TB
subgraph install [pmg setup install --system]
Cfg["/etc/safedep/pmg/config.yml"]
Shims["/usr/local/lib/pmg/bin/*"]
Profile["/etc/profile.d/pmg.sh"]
end
subgraph path [How PATH gets shims]
Env["Docker ENV PATH"]
Prof["profile.d on login shells"]
end
Shims --> Env
Shims --> Prof
Env --> Run["Dockerfile RUN / any process with ENV"]
Prof --> Login["VM interactive/login shells"]
Components to add/change
[cmd/setup/setup.go](cmd/setup/setup.go)—--systemflag, uid-0 preflight, branch install/remove; root warning without flag[config/config.go](config/config.go)—WriteSystemTemplateConfig()→globalConfigDir(); remove only with--system[internal/shim/shim.go](internal/shim/shim.go)—NewSystemShimManager()withBinDir=/usr/local/lib/pmg/bin, no per-user rc edits- New system profile writer —
/etc/profile.d/pmg.sh(marker-gated, PATH prepend only) [cmd/setup/info.go](cmd/setup/info.go)/[cmd/setup/doctor.go](cmd/setup/doctor.go)— system scope reporting + PATH check[main.go](main.go)/ eventlog — soft-fail when log init fails (unusable HOME); do notFatalf
Reuse existing PMG_SHIM_PATH filtering in [internal/shim/path.go](internal/shim/path.go); no recursion work needed for the new shim dir.
Corner cases (handled or documented)
| Case | Handling |
|---|---|
Docker RUN does not source profile.d |
Document ENV PATH=… in golden image |
Login shell resets PATH via /etc/profile |
profile.d restores shim dir |
Child Dockerfile overwrites PATH without shim dir |
Document; doctor can detect when run |
Venv activate then pip |
Documented limitation → pmg pip |
| System + per-user both present | Independent; remove is scoped |
PMG_SHIM_PATH unset + direct pmg npm |
Legacy /.pmg/bin only; system dir not stripped — prefer shim invocation or ensure env from shim |
| Unwritable HOME | Eventlog soft-fail |
| Windows | --system → not supported |
Testing
- Unit tests with path overrides (same pattern as
globalConfigDirOverride) - Install/remove idempotence for system shims + profile.d
- Doctor/info system detection
- Document a minimal Dockerfile golden-image smoke example in docs (not necessarily CI matrix in v1)
Docs
- Setup / config docs:
--system, golden-image snippet, VM vs Docker PATH, venv limitation - Clarify host GHA PMG does not protect in-image
docker buildinstalls — bake PMG into the image
Implementation order (after spec approval)
- Soft-fail eventlog + root warn (small, unblocks containers)
- System shim manager + profile.d writer + config write
- Wire
--systemon install/remove - info/doctor
- Docs + tests