-
Notifications
You must be signed in to change notification settings - Fork 4
Client Configuration
Everything the Cimian client reads before it does anything: the configuration file, MDM-delivered policy, and the on-disk state layout.
The equivalent of Munki's /Library/Preferences/ManagedInstalls.plist, with one
important addition — a fleet can be configured entirely from MDM policy without
writing a file to any device.
| Source | Location | Precedence |
|---|---|---|
| MDM policy | HKLM\SOFTWARE\Policies\Cimian |
Highest — overrides the file |
| Configuration file | C:\ProgramData\ManagedInstalls\Config.yaml |
Normal |
| Built-in defaults | compiled in | Used when neither of the above supplies a value |
Policy is applied after the file is loaded, so a policy value always wins. If the file is missing or fails to parse, the client falls back to defaults and then still applies policy — a machine with only an MDM profile and no config file is a supported configuration.
Confirm what a client actually resolved:
managedsoftwareupdate --show-configRun this before debugging anything else. It is the fastest way to catch a config file that was never delivered, or a policy that is overriding a value you thought you set.
Keys are PascalCase, matching the property names, not snake_case. Unmatched keys are ignored silently, so a misspelled or wrongly-cased key does nothing and reports no error.
SoftwareRepoURL: https://cimian.example.com/repo
ClientIdentifier: WKSTN-0001
Catalogs:
- Production
LogLevel: INFO
InstallerTimeout: 900
CacheRetentionDays: 30| Key | Type | Default | Effect |
|---|---|---|---|
SoftwareRepoURL |
string | https://your-repo.example.com |
Base URL of the repository. Must be an absolute http or https URL; validation fails otherwise. Everything else is requested relative to it. |
ClientIdentifier |
string | the machine name | The first manifest name the client asks for. See Manifests. |
Catalogs |
list of string | [Production] |
Catalogs to resolve against when no manifest in the tree contributes any. |
| Key | Type | Default | Effect |
|---|---|---|---|
CachePath |
string | C:\ProgramData\ManagedInstalls\Cache |
Where downloaded payloads are staged. |
CatalogsPath |
string | C:\ProgramData\ManagedInstalls\catalogs |
Local catalog cache. |
ManifestsPath |
string | C:\ProgramData\ManagedInstalls\manifests |
Local manifest cache. |
A blank value for any of these means "use the default", not "use the current
directory". Older bootstrap configurations wrote CachePath: "", which
previously resolved relative to the process working directory — under the
watcher service that is the Cimian program directory, so downloads landed
outside the retention sweep and filled system drives. Blank values are now
normalised back to the defaults, but it is still better not to write them.
| Key | Type | Default | Effect |
|---|---|---|---|
LogLevel |
string | INFO |
One of DEBUG, INFO, WARNING, ERROR. |
Verbose |
bool | false |
Equivalent to a single -v. |
Debug |
bool | false |
Equivalent to -vvv. |
Command-line verbosity overrides these for a single run. See Logging.
| Key | Type | Default | Effect |
|---|---|---|---|
InstallerTimeout |
int (seconds) | 900 |
How long a single installer may run. Must be at least 60; a per-package installer_timeout overrides it. |
UseCache |
bool | true |
Reuse already-downloaded payloads. |
CacheRetentionDays |
int (days) | 30 |
How long superseded payloads are kept before the cleanup pass removes them. |
AutoRemove |
bool | false |
Uninstall packages that are recorded as installed but no longer appear in any manifest. The equivalent of Munki's AutoRemove — off by default, and worth understanding before enabling. |
CheckOnly |
bool | false |
Never install; only report. |
SkipSelfService |
bool | false |
Ignore the local self-service manifest. |
LocalOnlyManifest |
string | none | Use a local manifest file instead of a server manifest. |
CacheRetentionDays is the only lever against superseded multi-gigabyte payloads
filling a small system drive, which is why it is also settable by policy.
| Key | Type | Default | Effect |
|---|---|---|---|
NoPreflight |
bool | false |
Skip the preflight script. |
NoPostflight |
bool | false |
Skip the postflight script. |
PreflightFailureAction |
string | continue |
What to do when preflight fails. |
PostflightFailureAction |
string | continue |
What to do when postflight fails. |
The scripts themselves live at
C:\ProgramData\ManagedInstalls\sbin\preflight.ps1 and postflight.ps1, with
installed copies under the Cimian program directory. This is the same hook Munki
provides at the same points in the cycle.
| Key | Type | Default | Effect |
|---|---|---|---|
AuthUser |
string | none | Basic authentication user. |
AuthPassword |
string | none | Basic authentication password. |
AuthToken |
string | none | Bearer token for the repository. |
| Key | Type | Default | Effect |
|---|---|---|---|
UseClientCertificate |
bool | false |
Present a client certificate on repository requests (mTLS). |
ClientCertificatePath |
string | none | Path to a PFX file. |
ClientCertificatePassword |
string | none | Password for that PFX. |
ClientCertificateThumbprint |
string | none | Thumbprint of a certificate in the Windows certificate store, as an alternative to a PFX on disk. |
ClientKeyPath |
string | none | Path to a separate key file. |
SoftwareRepoCACertificate |
string | none | Custom CA certificate used to validate the repository's chain. |
UseClientCertificateCNAsClientIdentifier |
bool | false |
Use the certificate's common name as the first manifest candidate. Requires UseClientCertificate. |
Using the certificate CN as the identifier is the strongest binding available: the device cannot claim a manifest it does not hold a certificate for.
| Key | Type | Default | Effect |
|---|---|---|---|
LoopGuardEnabled |
bool | true |
Master switch. When false, packages are never suppressed and no backoff state is consulted. Passive loop detection for reporting continues either way. |
LoopMaxTime |
int (days) | 7 |
The backoff cap: the longest a package can stay suppressed before it is retried automatically. A non-positive value falls back to the default. |
LoopReprobeHours |
int (hours) | 24 |
How often a package flagged as non-converged is re-probed with a fresh install attempt. Capped at LoopMaxTime. Any pkgsinfo change clears the flag immediately. |
There is no permanent blacklist tier: a package stranded by a transient failure such as a download outage self-heals rather than staying blocked forever. See Install Loop Prevention.
| Key | Type | Default | Effect |
|---|---|---|---|
UsageStaleUninstallEnabled |
bool | true |
Master switch for unused_software_removal_info. Safe to leave on fleet-wide: every package must still opt in through its pkgsinfo, and the pass only ever touches self-service, optional and orphaned items — never admin-manifested ones. |
UsageStaleUninstallMinimumHistoryDays |
int (days) | 14 |
Global fallback for a package's minimum_history_days. Refuses removal on devices with less usage history than this. |
UsageStaleUninstallMaxSourceStalenessDays |
int (days) | 7 |
Skip the whole pass when the usage source has recorded nothing within this many days. Idle telemetry must not drive removals. |
| Key | Type | Default | Effect |
|---|---|---|---|
PreferSbinInstaller |
bool | true |
Prefer the sbin installer for package formats that support it. |
SbinInstallerPath |
string | none | Override the sbin installer location. |
SbinInstallerTargetRoot |
string | / |
Target root passed to the sbin installer. |
ForceChocolatey |
bool | false |
Force the Chocolatey path for NuPkg payloads. |
PkgRequireSignature |
bool | false |
Reject unsigned pkg payloads. |
Policy values are read from HKLM\SOFTWARE\Policies\Cimian. The intended
delivery mechanism is an ADMX-ingested Intune configuration profile, so
fleet-wide settings ship as a policy rather than as per-device file edits. See
CSP OMA-URI Configuration.
Only these four values are policy-overridable today:
| Value name | Type | Constraint | Effect |
|---|---|---|---|
SoftwareRepoURL |
REG_SZ |
non-blank | Overrides the repository URL. Trimmed. |
ClientIdentifier |
REG_SZ |
non-blank | Overrides the client identifier. Trimmed. |
InstallerTimeout |
REG_DWORD or REG_SZ
|
must be at least 60 | Overrides the fleet installer timeout. |
CacheRetentionDays |
REG_DWORD or REG_SZ
|
must be 0 or more | Overrides cache retention. |
Numeric values are accepted as either a DWORD or a string. ADMX decimal elements
normally arrive as REG_DWORD, but the Policy CSP has been observed delivering
them as strings, so both are handled.
A value that fails its constraint is ignored and the file or default value stands. A read failure of the whole policy key is non-fatal: the client logs it at debug level and carries on with the file's values.
Setting a policy value by hand, for testing:
New-Item -Path 'HKLM:\SOFTWARE\Policies\Cimian' -Force | Out-Null
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Cimian' -Name 'SoftwareRepoURL' -Value 'https://cimian.example.com/repo'Note that a policy override is invisible in Config.yaml. If --show-config
disagrees with the file, look here first.
These are state, not configuration. Cimian writes them; you do not set them.
| Key | Purpose |
|---|---|
HKLM\SOFTWARE\ManagedInstalls |
Recorded installed versions, used as the last resort in the detection chain. |
HKLM\SOFTWARE\Cimian |
Agent state. |
HKLM\SOFTWARE\Cimian\InstalledPackages\ |
Per-package install records. |
Cimian also reads standard Windows locations to determine installed state and
machine condition: the Add/Remove Programs keys under
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall and its WOW6432Node
counterpart, the Windows Installer UpgradeCodes mapping, the Component Based
Servicing and Windows Update reboot-pending flags, and the MDM enrolment keys.
Cimian reads no environment variables for its own configuration. It reads the
standard Windows ones (PATH, PROCESSOR_ARCHITECTURE, USERNAME,
USERPROFILE, SESSIONNAME and similar) as inputs to system facts and to
session detection.
One diagnostic variable exists, CIMIAN_REMOTE_PATTERN, used in remote-session
detection.
The CIMIAN_CERT_* variables documented in the repository's .env.example are
build-time settings for code signing, not client configuration. See
Development.
Everything the client keeps lives under C:\ProgramData\ManagedInstalls. The
root itself is computed from %ProgramData%, so a relocated ProgramData is
handled.
| Path | Contents |
|---|---|
Config.yaml |
The configuration file |
SelfServeManifest.yaml |
The user's self-service choices |
InstallInfo.yaml |
The resolved plan for the current run |
Cache\ |
Downloaded payloads |
catalogs\ |
Cached catalogs |
manifests\ |
Cached manifests |
icons\ |
Cached icons |
logs\ |
Session logs, dated logs\YYYY-MM-DD\HHMM\
|
logs\installs\ |
Verbose installer logs, kept across sessions |
logs\selfupdate\ |
Verbose logs from agent self-updates |
logs\packages\ |
Per-package script output, one directory per package |
logs\cimiwatcher.log |
The watcher service's rolling log |
reports\ |
Session reports |
conditions\ |
Admin-provided condition scripts |
facts\ |
Cached hardware facts |
Receipts\ |
Install receipts |
sbin\ |
preflight.ps1, postflight.ps1
|
SelfUpdateBackup\ |
The backup taken before a self-update |
| File | Meaning |
|---|---|
.cimian.bootstrap |
Run with the status window. See Bootstrap Mode. |
.cimian.headless |
Run silently. |
.cimian.selfupdate |
A self-update is queued. See Self-Update. |
Seven directories — logs, reports, catalogs, icons, manifests,
conditions, facts — are lowercase by convention, and the client renames them
at the start of every session if it finds them spelled otherwise. NTFS is
case-insensitive, so nothing is broken on a machine that has Logs from an older
install, but the reported path is wrong and a case-sensitive consumer such as a
log shipper sees two names for one directory. The rename is best-effort and never
blocks a run.
Scripts placed in C:\ProgramData\ManagedInstalls\conditions\ are executed and
their standard output parsed as key=value pairs, which are merged into the fact
set available to manifest conditions. This is Cimian's equivalent of Munki's
admin-provided conditions. See Conditional Items.
Three approaches, in increasing order of manageability:
-
Write
Config.yamlduring provisioning. Simple; drifts. -
Ship
Config.yamlas a managed item through Cimian itself, after a minimal bootstrap config gets the client talking to the repository. - Set policy from MDM and leave the file alone. Only four settings are policy-overridable, but they are the four that differ between fleets and change over time.
For most estates the right combination is a minimal file written at provisioning time and policy for anything that might need to change later.
The configuration template shipped alongside the installer uses snake_case keys
(software_repo_url, client_identifier) while the client reads PascalCase
(SoftwareRepoURL, ClientIdentifier). Because unmatched keys are ignored
silently, a config written from that template parses without error and supplies
no values at all — the client falls back to defaults and points at the
placeholder repository URL.
Write PascalCase keys, and verify with --show-config rather than assuming the
file was read.
- Installation
-
Manifests — how
ClientIdentifieris used - CSP OMA-URI Configuration — delivering policy from Intune
- Logging
- CLI Reference
Cimian — managed software deployment for Windows, modelled on Munki. Apache License 2.0. Source and issues at windowsadmins/cimian.
Start here
Repository
Authoring packages
- Installation Checks
- Uninstall Methods
- Uninstallable Key
- Conditional Items
- Importing EXE Bundle Installers
- PowerShell Execution Policy
- Chocolatey Shim Prevention
- Managed Profiles and Apps
Client runtime
Diagnostics
- Troubleshooting
- Logging
- Error Reporting
- Item Source Traceability
- CimiTrigger Troubleshooting
- Privilege Elevation
Integrations
Contributing