From 3645e479bc46b2eeac0aaffb5feca826959235d8 Mon Sep 17 00:00:00 2001 From: Tanja Ulianova Date: Thu, 17 Sep 2026 18:18:19 +0200 Subject: [PATCH 1/2] docs(install): add unattended and MDM installs page for macOS Covers the plain `installer -pkg` command, what the package changes on the machine, why 1.16.0 and earlier fail under an MDM agent (the postinstall inherits the agent's TCC identity and cannot create /etc/fstab) with both workarounds, the behaviour on machines that already have Nix, and how to verify a fleet install without trusting /etc/flox-version alone. Related: DEV-8, flox/flox-installers#529. Co-Authored-By: Claude Fable 5.1 --- docs.json | 1 + install-flox/mdm.mdx | 104 +++++++++++++++++++++++++++++++++++++++++++ llms.txt | 1 + 3 files changed, 106 insertions(+) create mode 100644 install-flox/mdm.mdx diff --git a/docs.json b/docs.json index c99f178..80af8f4 100644 --- a/docs.json +++ b/docs.json @@ -47,6 +47,7 @@ "group": "Install Flox", "pages": [ "install-flox/install", + "install-flox/mdm", "install-flox/uninstall", "install-flox/troubleshooting", "install-flox/ide-extensions" diff --git a/install-flox/mdm.mdx b/install-flox/mdm.mdx new file mode 100644 index 0000000..64d6d8e --- /dev/null +++ b/install-flox/mdm.mdx @@ -0,0 +1,104 @@ +--- +title: "Unattended and MDM installs" +description: "How to install the Flox macOS package from an MDM or a script with nobody at the keyboard" +--- + +The Flox `.pkg` can be installed by a device management (MDM) agent or any +other script with the standard macOS command: + +```console +$ sudo installer -pkg flox-.aarch64-darwin.pkg -target / +``` + +Use the `x86_64-darwin` package on Intel Macs. The package refuses to install +on the wrong architecture, so a policy that ships both and lets the installer +decide is safe. Download links for the current release are on the +[Install](/install-flox/install#macos) page. + +## What the installer changes on the machine + +Everything happens in the package's `postinstall` script and runs as root: + +* Adds `nix` to `/etc/synthetic.conf` so that the read-only system volume gets + an empty `/nix` directory to mount on. +* Creates an APFS volume named `Nix Store` in the same container as the boot + disk. When FileVault is on, the volume is encrypted with a random passphrase + stored in the System keychain. +* Installs two LaunchDaemons: `org.nixos.darwin-store`, which mounts the + volume at `/nix` on every boot, and `org.nixos.nix-daemon`. +* Creates the `nixbld` group and the `_nixbld1` to `_nixbld32` build users. +* Writes `/etc/nix/nix.conf` and `/etc/nix/flox.conf`, links `flox` and `nix` + into `/usr/local/bin`, and patches two Apple bugs in `/etc/zshrc`. + +Flox 1.17.0 and later do not write `/etc/fstab`. The mount options for the +volume are set by the mount service instead. + +## Older installers and `/etc/fstab` + +Flox 1.16.0 and earlier add a line to `/etc/fstab` with `vifs`. On a Mac that +has never had Nix, that step fails when the install is driven by an MDM agent, +and the install log shows: + +```text +vifs: error creating /etc/fstab +``` + +followed by `PKInstallErrorDomain Code=112`. The same package installs fine +when you double-click it on the same machine. + +The cause is macOS Transparency, Consent and Control (TCC). PackageKit runs +package scripts with the TCC identity of the process that called +`installer`, which under an MDM policy script is the agent itself, and +`/etc/fstab` is a protected path. The agent has no grant for it, so the write +is refused. Nothing inside the package can change that. + + + The install stops after the volume has already been created. A machine that + hit this has a `Nix Store` volume, nothing mounted at `/nix`, no + LaunchDaemons and no package receipt. Delete the volume before trying again: + + ```bash + sudo diskutil apfs deleteVolume "Nix Store" + ``` + + +Two ways to install 1.16.0 or earlier unattended: + +* **Use the MDM's native package install command** rather than a policy script + that calls `installer`. That keeps the agent out of the process tree, and the + scripts run with the identity of an Apple system process that has the grant. +* **Grant the agent the permission** with a Privacy Preferences Policy Control + (PPPC) profile that allows `SystemPolicySysAdminFiles` for the agent binary. + The binary is the one named in the `Set responsibility to pid` line of + `/var/log/install.log`. A PPPC grant does not appear in System Settings, so + verify it by running the install rather than by looking. + +## Machines that already have Nix + +The package behaves differently when `/nix/var/nix/db/db.sqlite` exists and +Flox is not installed: + +* **Flox 1.16.0 and later** refuse a command-line install and print an + explanation. Replacing an existing Nix installation with Flox changes the Nix + daemon and the default profile, so it must be confirmed in the graphical + installer. Alternatively, install Flox + [with the existing Nix](/install-flox/install#nix). +* **Flox 1.15.0** installs nothing and reports success. Both installer choices + start deselected on such a machine, so an unattended run that appears to + work has not installed Flox. Check the result as described below. + +## Verifying a fleet install + +Do not rely on `/etc/flox-version` alone. It is written early in the install +and can be present after a failed run. Check all of the following: + +```bash +pkgutil --pkg-info com.floxdev.flox +diskutil info /nix | grep 'Mount Point' +launchctl print system/org.nixos.darwin-store > /dev/null && echo "mount service loaded" +flox --version +``` + +A successful install has a package receipt, `/nix` mounted from the +`Nix Store` volume, the mount service loaded, and `flox --version` printing +the installed version. diff --git a/llms.txt b/llms.txt index 2af4eba..27a25c8 100644 --- a/llms.txt +++ b/llms.txt @@ -68,6 +68,7 @@ Key terms: ## Install Flox - [Install Flox](https://flox.dev/docs/install-flox/install.md): How to install or upgrade the Flox CLI +- [Unattended and MDM installs](https://flox.dev/docs/install-flox/mdm.md): How to install the Flox macOS package from an MDM or a script with nobody at the keyboard - [Uninstall Flox](https://flox.dev/docs/install-flox/uninstall.md): How to uninstall the Flox CLI - [Troubleshooting installation](https://flox.dev/docs/install-flox/troubleshooting.md): How to diagnose and fix common Flox installation issues - [Extensions](https://flox.dev/docs/install-flox/ide-extensions.md): IDE extensions and AI agent integrations for Flox From 369fee771ad0cf34425a347ed9f18b829a47a3a3 Mon Sep 17 00:00:00 2001 From: Tanja Ulianova Date: Thu, 17 Sep 2026 18:18:36 +0200 Subject: [PATCH 2/2] docs(install): reword a possessive that Vale rejects Co-Authored-By: Claude Fable 5.1 --- install-flox/mdm.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install-flox/mdm.mdx b/install-flox/mdm.mdx index 64d6d8e..99e1d9e 100644 --- a/install-flox/mdm.mdx +++ b/install-flox/mdm.mdx @@ -64,7 +64,7 @@ is refused. Nothing inside the package can change that. Two ways to install 1.16.0 or earlier unattended: -* **Use the MDM's native package install command** rather than a policy script +* **Use the native package install command of the MDM** rather than a policy script that calls `installer`. That keeps the agent out of the process tree, and the scripts run with the identity of an Apple system process that has the grant. * **Grant the agent the permission** with a Privacy Preferences Policy Control