/etc, so any user’s npm install or pip install is checked before it runs.
For a single developer machine, use the per-user setup in the Quickstart instead. Per-user and system-wide installs can coexist.
Requirements
- Linux and root. System install is Linux-only and must run as root.
- PMG in a system path. Every user’s shim runs PMG by absolute path, so the binary must live in a root-owned system path such as
/usr/local/bin, executable and reachable by all users.
What gets created
| Item | Path |
|---|---|
| Configuration | /etc/safedep/pmg/config.yml |
| Package-manager shims | /usr/local/lib/pmg/bin |
| Shell PATH snippet | /etc/profile.d/pmg.sh |
System install uses PATH shims only. It does not create the
~/.pmg.rc alias layer that per-user setup installs.Docker images
PMG must be installed inside the image: PMG on the Docker host cannot see installs that run duringdocker build.
Compared to a Linux VM, a Dockerfile needs two adjustments:
- No
sudo.RUNsteps execute as root. If your base image switches to a non-rootUSER, addUSER rootbefore the install step and switch back after. - Set
PATHwithENV.RUNsteps do not source/etc/profile.d, so add the shim directory toPATHexplicitly.
RUN npm install or RUN pip install after the ENV PATH line now goes through PMG, and the running container inherits the protection, for any USER. Derived images inherit it too.
Linux VMs
-
Place PMG in a system path.
Not installed yet? The install script places it in
/usr/local/bin, prompting for sudo for the copy:Already installed in a user location? Copy it over:PMG rejects a binary in a user location (~/.local/bin,~/go/bin), since any single user could modify it. The install script also picks~/.local/binwhen that is on yourPATH; if it did, use the copy command above. -
Install system-wide:
-
Activate the PATH. The install writes
/etc/profile.d/pmg.sh, which prepends the shim directory for login shells. New login sessions pick it up; for an already-open shell:
Verify
Works for a VM shell and inside a container (docker run --rm -it <image> sh):
Configuration
The system config file is authoritative for every user. PMG ignores a per-userconfig.yml while /etc/safedep/pmg/config.yml exists.
pmg config set and pmg config edit are disabled under a system config. Edit the file as root, or redeploy it through your image or configuration management.
Runtime data (event logs, cloud-sync state, cache) stays per user under
~/.config/safedep/pmg and ~/.cache/safedep/pmg. The invoking user must be able to write their own config directory. Relocate it with PMG_CONFIG_DIR / PMG_CACHE_DIR if needed.Cloud sync
Cloud sync reports install events to your SafeDep Cloud tenant, where they appear in Package Guard. To set it up, enable cloud sync and provide your tenant ID and API key from SafeDep Cloud through theSAFEDEP_API_KEY and SAFEDEP_TENANT_ID environment variables.
In a Docker image
Enable sync and set a stable endpoint name before your install steps:PMG_CLOUD_ENDPOINT_ID every run registers as a new endpoint. A stable name is what you will recognize in Endpoint Hub.
The credentials exist only where you run docker, as shell exports or CI secrets; they never go in the Dockerfile.
In the running container, pass them through at start:
environment: entries and Kubernetes Secret references work the same way. If the container is short-lived, a CI job for example, run pmg cloud sync before it exits so buffered events are not destroyed with it.
During docker build, sync in the same RUN step as the install, with the export covering both commands: PMG records events for the cloud only when credentials resolve. Mount the credentials as BuildKit secrets, which expose them to that step only (uid= makes them readable by the step’s non-root user):
--secret reads the variable exported where you run the build:
A blocked package fails its
RUN step: later commands never run, including any sync at the end of the Dockerfile, and Docker discards the failed step’s changes. Syncing per step uploads every event up to the block; the block itself shows in the build output.Complete Dockerfile with cloud sync
Complete Dockerfile with cloud sync
On a shared VM
Enable sync in/etc/safedep/pmg/config.yml as root:
/etc/profile.d/safedep-cloud.sh, so every login shell exports them:
Certificates
System install does not set up a MITM certificate authority. For npm and pip on Linux, PMG’s default ephemeral CA and environment-variable injection are sufficient. To install a persistent CA into the OS trust store, runpmg setup cert install --system as your normal user.
Uninstall
sudo rm /usr/local/bin/pmg, or uninstall it through your package manager if you installed it that way.
Troubleshooting
Try runningpmg setup doctor first: it detects each of these states and prints the matching fix.
npm or pip resolves outside the shim directory
npm or pip resolves outside the shim directory
Version managers like nvm, pyenv, volta, and asdf prepend their own bin directories from rc files that run after
/etc/profile.d, putting the real npm/pip ahead of the shims.- Keep
/usr/local/lib/pmg/binfirst in a durableENV PATHor login PATH - Or call
pmg npm/pmg pipdirectly
pip inside a virtualenv bypasses PMG
pip inside a virtualenv bypasses PMG
After
source .venv/bin/activate, bare pip uses the venv binary and skips the shims. Call pmg pip inside the venv.Every pmg command fails with permission denied on the event log
Every pmg command fails with permission denied on the event log
Another account created or owns your config directory. Check the path in the error message.If the path is inside your own home, a root run created it as root. This happens with If the path is inside another user’s home, your environment leaked that user’s
su without - (prefer sudo or su -) and with images that set ENV HOME before dropping root. Restore ownership:HOME or XDG_CONFIG_HOME (common with sudo -u on CI runners). Fix the environment; do not chown another user’s directory, that breaks PMG for them.System Install Reference
Full reference in the PMG repo: binary validation rules, user data directories, and limitations.
PMG
How PMG blocks malicious packages at install time.

