4.3. APFS Volume Installation

The root filesystem is read-only as of macOS 10.15 Catalina, all writable paths to a separate data volume. This means creating or writing to /nix is not allowed. While changing the default prefix would be possible, it's a very intrusive change that has side effects we want to avoid for now.

For common writable locations firmlinks where introduced, described by Apple as a "bi-directional wormhole" between two filesystems. Essentially a bind mount for APFS volumes. However this is (currently) not user configurable and only available for paths like /Users.

For special cases like NFS mount points or package manager roots synthetic.conf(5) provides a mechanism for some limited, user-controlled file-creation at /. This only applies on a reboot, but apfs.util can be used to trigger the creation (not deletion) of new entries.

alice$ /System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B
  • The simplest solution is creating a symlink with /etc/synthetic.conf to the data volume.

    nix    /System/Volumes/Data/nix
    alice$ ls -l /
    lrwxr-xr-x   1 root  wheel    25 Jan  1  2019 nix -> /System/Volumes/Data/nix

    Builds that detect or resolve this symlink will leak the canonical location or even fail in certain cases which would have to be fixed.

  • An empty directory can also be created using /etc/synthetic.conf, this won't be writable but can be used as a mount point. And with APFS it's relatively easy to create an separate volume for nix instead.

    alice$ sudo diskutil apfs addVolume diskX APFS 'Nix Store' -mountpoint /nix
    alice$ mount
    /dev/disk1s6 on /nix (apfs, local, journaled)

    This does make the installation more complicated, requiring both /etc/synthetic.conf as well as /etc/fstab

    # Warning - this file should only be modified with vifs(8)
    # Failure to do so is unsupported and may be destructive.
    LABEL=Nix\040Store /nix apfs rw

    On macOS volumes are also mounted quite late, launchd services or other things that start during login will start before our volume is mounted. For these cases eg. wait4path must be used for things that depend on /nix.

    This new volume also won't be encrypted by default, and enabling is only possible interactively?

    diskutil apfs enableFileVault /nix -user disk