Legacy environment variables `PMG_PROXY_MODE` and `PMG_PROXY_INSTALL_ONLY` (for the old flat keys) are still supported when the `proxy:` section does not exist in the config file.
For centrally managed or fleet deployments, PMG can read an OS-level **global config file**. When this file exists, it is authoritative: PMG uses it and ignores the per-user `config.yml` (the two are never merged). An administrator ships a machine-wide baseline this way, and can lock it (see [Lockdown](#lockdown)) to forbid user overrides.
| Windows | `%PROGRAMDATA%\safedep\pmg\config.yml` |
Check whether a global config is active with `pmg setup info`:
```bash
pmg setup info
# Config Source: global <- global config, overrides allowed
# Config Source: global (locked) <- global config with lockdown enabled
# Config Source: user <- per-user config in effect
```
### Behaviour
Whenever a global config file is present:
- **It is authoritative.** PMG ignores the per-user `config.yml`. The file may be **partial**. Keys it does not set fall back to PMG's built-in defaults, not to a user's values.
- **`config set` and `config edit` fail.** They return an error stating the config is globally managed. To change it, deploy an updated file at the OS path, which is root-owned and not writable by users.
- **`pmg setup install` skips the per-user config.** It still creates shell aliases and shims per user.
By default a user can still override the global config's values at runtime through `PMG_*` environment variables and CLI flags. Enable lockdown to forbid that.
### Lockdown
Add `global_lockdown: true` to the global config to enforce it:
```yaml
# Only meaningful in the global config file.
global_lockdown:true
```
When lockdown is on:
- **CLI flags that would change a managed value fail fast.** For example, `pmg --sandbox=false ...` or `pmg --paranoid ...` errors out instead of overriding policy. Governed flags: `--transitive`, `--transitive-depth`, `--include-dev-dependencies`, `--paranoid`, `--skip-event-log`, `--proxy-mode`, `--sandbox`, `--sandbox-enforce`, `--sandbox-profile`, `--sandbox-allow`, `--skip-dependency-cooldown`. Operational flags such as `--dry-run` keep working.
- **`PMG_*` variables cannot change the config**, including `PMG_INSECURE_INSTALLATION` (which otherwise bypasses malicious-package blocking).
PMG reads `global_lockdown` straight from the global file, so a user cannot flip it through env or CLI. If the global file exists but cannot be read or parsed, PMG fails closed and treats it as locked. `PMG_CONFIG_DIR` and `PMG_CACHE_DIR` still relocate per-user state directories (logs, cache) in any mode, but leave the managed config alone.
### Precedence
| Mode | Effective order (highest to lowest) |
|---|---|
| No global config | CLI flags > `PMG_*` env > per-user `config.yml` > built-in defaults |
| Global config, no lockdown | CLI flags > `PMG_*` env > global config > built-in defaults |
| Global config, `global_lockdown: true` | global config > built-in defaults (env and managed-flag overrides refused) |
### Deploying via MDM (macOS)
Scripts to install or update PMG and deploy a global config across a macOS fleet (Jamf, Mosyle, Kandji, Intune) live in [`scripts/mdm`](../scripts/mdm). Bundle a `config.yml` next to the scripts. The installer places it at the global path, and the uninstaller removes it. See the [`scripts/mdm` README](../scripts/mdm/README.md) for details.