# The protected view of the instance data tree (isolated-exec design ยง3.2). # # /data/.instances is the RAW directory, opened by the layout pass only; # this bind of it onto /data/instances is the view everything else uses. # nosymfollow is the isolation's belt: path resolution under this mount # returns ELOOP at any symlink, for every process on the box, in every # namespace that sees the mount, with no check-then-use race. An instance # runs as the agent's uid and can write its own directory, so any symlink # it plants would otherwise be followed by the agent (reading a sibling's # env file as this instance's), by the edge (dialling a sibling's socket # as this host) and by PID 1. Here none of them follow it. # # It is a bind of a DIFFERENT directory, not of itself, because rename(2) # refuses to cross a mount boundary (EXDEV) even on one filesystem, and # the migration moves /data/.db into this tree by rename (codex R4-2). # # DefaultDependencies=no, with the ordering written out: a mount unit's # default place is before local-fs.target, and systemd-tmpfiles-setup, # which creates the two directories, runs after it, so the defaults form a # cycle systemd breaks by dropping this mount (codex R2-2). Shutdown # ordering is written out for the same reason. [Unit] Description=carlos instance data (bind, nosymfollow) DefaultDependencies=no RequiresMountsFor=/data After=local-fs.target systemd-tmpfiles-setup.service Before=carlos-edge.service carlos-instance-control.service carlos-litestream.service Conflicts=umount.target Before=umount.target [Mount] What=/data/.instances Where=/data/instances Type=none Options=bind,nosymfollow,nosuid,nodev,noexec [Install] WantedBy=multi-user.target