Running musefs as a systemd user service
These units run musefs on the host (the recommended deployment) under your own
user account — no root, no CAP_SYS_ADMIN.
Files
musefs.service— the mount daemon (musefs mount); blocks until stopped.musefs-scan.service+musefs-scan.timer— optional periodicmusefs scan --revalidate.musefs.conf.example— everyMUSEFS_*setting, commented with defaults.
Install
mkdir -p ~/.config/systemd/user ~/.config/musefs
cp musefs.service musefs-scan.service musefs-scan.timer ~/.config/systemd/user/
cp musefs.conf.example ~/.config/musefs/musefs.conf
$EDITOR ~/.config/musefs/musefs.conf # set MUSEFS_MOUNTPOINT and MUSEFS_DB
systemctl --user daemon-reload
systemctl --user enable --now musefs.service
Enable the periodic re-scan too (edit the library path in
musefs-scan.service first):
systemctl --user enable --now musefs-scan.timer
Hardening
These units run under the --user manager, which constrains what systemd
sandboxing is possible. The two units differ sharply:
-
musefs-scan.serviceis fully sandboxed. The scanner creates no FUSE mount, so it takes a strong sandbox (ProtectSystem=true,SystemCallFilter=, plus namespace and seccomp restrictions).ProtectSystem=true(notstrict) keeps system directories read-only while leaving your library andMUSEFS_DBwritable, so a custom DB location needs noReadWritePaths=edit. A few directives that require capability-bounding-set drops (CapabilityBoundingSet=,PrivateDevices,ProtectKernelModules,ProtectKernelLogs,ProtectClock) are omitted: the unprivileged user manager cannot apply them, and the process is already capability-less, so nothing is lost. Inspect withsystemd-analyze --user security musefs-scan.service. -
musefs.serviceis intentionally not sandboxed, and cannot be. musefs mounts via the setuidfusermount3helper.NoNewPrivileges=true— and nearly every other systemd hardening directive, since installing a seccomp filter for an unprivileged process forces the kernelno_new_privsflag — disables the setuid escalation, and the mount then fails withfusermount3: mount failed: Operation not permitted. The unit comment explains this in full.
Notes
-
The store must exist before the mount starts.
musefs mountnever creates the DB — it requires a populated store and exits non-zero otherwise, so a mount unit that starts before anything has scanned hard-fails and (withRestart=on-failure) crash-loops. Seed the store with an initialmusefs scanbeforeenable --now musefs.service. If you generate the store from another unit, order this one after it with a drop-in (systemctl --user edit musefs):[Unit] After=musefs-initial-scan.service Requires=musefs-initial-scan.service(The
musefs-scan.timeris a periodic re-scan, not the initial seed.) -
Binary location. The
--usermanager does not inherit your shell'sPATH. The units setPATHfor acargo installbinary in~/.cargo/bin; if musefs is elsewhere, edit theEnvironment=PATH=line (or makeExecStartan absolute path). -
%hvs~. Unit files expand%hto your home directory; themusefs.confEnvironmentFile does not expand%hor~— use absolute paths there, and never paste~/...into a unit directive (it is taken literally). -
Settings.
musefs.conf.exampleis a commented example of the commonMUSEFS_*mount/scan variables (every scalarmount/scanflag has aMUSEFS_*form — uppercase the long flag, dashes to underscores). Explicit flags override env vars;--fallbackand scan targets are command-line only (set them inExecStart). -
Inline overrides. Prefer
systemctl --user edit musefsto addEnvironment=lines in a drop-in; it survives reinstalls. -
Headless servers. A
--usertimer only fires while your user manager runs. For a daily scan when you are not logged in:loginctl enable-linger <user>. -
Logs.
journalctl --user -u musefs -f.