Skip to content

Client Configuration

Rod Christiansen edited this page Sep 5, 2026 · 1 revision

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.

Where configuration comes from

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-config

Run 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.

Config.yaml

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

Repository and identity

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.

Local paths

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.

Logging

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.

Install behaviour

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.

Preflight and postflight

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.

Authentication

Key Type Default Effect
AuthUser string none Basic authentication user.
AuthPassword string none Basic authentication password.
AuthToken string none Bearer token for the repository.

Client certificates and TLS

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.

Loop suppression

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.

Unused-software removal

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.

Package installer behaviour

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.

MDM policy

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.

Other registry locations

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.

Environment variables

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.

On-disk layout

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

Flag files

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.

Directory casing

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.

Admin-provided conditions

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.

Deploying configuration

Three approaches, in increasing order of manageability:

  1. Write Config.yaml during provisioning. Simple; drifts.
  2. Ship Config.yaml as a managed item through Cimian itself, after a minimal bootstrap config gets the client talking to the repository.
  3. 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.

Known inconsistency

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.

Related pages

Clone this wiki locally