BINDFS(1)

πŸ“¦
version 1.18.4 Β· 3 versions
, in epel 10, epel 9, fedora 43, fedora 44, ubuntu resolute, ubuntu stonking

BINDFS(1) πŸ’–

okay bestie, sit down, grab a boba, because this is the manual for bindfs β€” that's the General Commands Manual entry, in case you were wondering which shelf it lives on πŸ“šβœ¨


✨ NAME ✨

bindfs β€” mount --bind in user-space πŸ¦‹

🌸 SYNOPSIS 🌸

bindfs [options] dir mountpoint

πŸ’œ DESCRIPTION πŸ’œ

It's a FUSE filesystem that mirrors the contents of one directory into another directory, but with changes to permissions and other features sprinkled on top. Think of it as a --bind mount that went to glow-up bootcamp πŸ’…


πŸ‘‘ FILE OWNERSHIP πŸ‘‘

  • -u, --force-user, -o force-user=... β€” makes every single file owned by the user you name. heads up though: it also makes chown on the mounted filesystem always fail. no takebacks πŸ™ˆ
  • -g, --force-group=group, -o force-group=... β€” same deal but for groups: every file is owned by the group you name, and chgrp on the mount always fails.
  • -p, --perms=permissions, -o perms=... β€” takes a comma- or colon-separated list of chmod-like permission specifications, applied to the permission bits in order. the details live in PERMISSION SPECIFICATION further down, iykyk.
    • this only changes how the permission bits of existing files look when you view them inside the mounted directory. if you want to control what brand-new files get in the source directory, that's --create-with-perms.
    • also, standard rules apply: the root user isn't bound by the permissions set here. if you want a truly read-only mount, use -r. periodt.
  • -m, --mirror=user1:user2:..., -o mirror=... β€” comma- or colon-separated list of users who will see themselves as the owner of all the files. users who aren't on the list can still access the mount if the permissions otherwise let them in, no gatekeeping there 🫢
    • bonus: you can pass a group name with an @ in front to mirror every member of that group. heads up though β€” this will not change which group the files are shown to have.
  • -M, --mirror-only=user1:user2:..., -o mirror-only=... β€” exactly like --mirror, except it disallows access for everybody else (except root, root is always the exception bestie).
  • --map=user1/user2:@group1/@group2:..., -o map=... β€” give it a mapping like user1/user2 and every file owned by user1 shows up as owned by user2. when user2 creates files, they get chowned to user1 in the underlying directory. when files get chowned to user2, they get chowned to user1 in the underlying directory. same energy for groups ✨
    • a single user or group may appear no more than once on the left and once on the right of a slash in your list of mappings. don't be greedy.
    • as of right now, the options --force-user, --force-group, --mirror, --create-for-*, --chown-* and --chgrp-* override the corresponding behavior of this option.
    • requires mounting as root.
  • --map-passwd=<passwdfile>, -o map-passwd=<passwdfile>
  • --map-group=<groupfile>, -o map-group=<groupfile>

like --map=..., but it reads the UID (GID) mapping from a passwd (group) file β€” think /etc/passwd and /etc/group. it maps the UID (GID) given in the <passwdfile> (<groupfile>) to its corresponding user (group) name. super helpful when you're restoring system backups where the UIDs and GIDs just don't match up anymore 😭

example usage:

bindfs --map-passwd=/mnt/orig/etc/passwd \
    --map-group=/mnt/orig/etc/group \
    /mnt/orig /mnt/mapped

requires mounting as root.

  • --map-passwd-rev=<passwdfile>, -o map-passwd-rev=<passwdfile>
  • --map-group-rev=<groupfile>, -o map-group-rev=<groupfile>

the reversed variant of --map-passwd and --map-group. like --map=..., but it reads the UID (GID) mapping from passwd (group) files (like /etc/passwd and /etc/group), mapping the user (group) name in <passwdfile> (<groupfile>) to its corresponding UID (GID). helpful for building compatible chroot environments where the UIDs and GIDs differ 🧚

example usage:

bindfs --map-passwd-rev=/mnt/mapped/etc/passwd \
    --map-group-rev=/mnt/mapped/etc/group \
    /mnt/orig /mnt/mapped

requires mounting as root.

  • --uid-offset=..., -o uid-offset=... β€” works like --map, but it just adds the given number to every file owner user ID. so for instance, --uid-offset=100000 makes a file owned by user 123 show up as owned by user 100123. simple math, slay πŸ”₯
    • for now, this option cannot be used together with --map. if you have a use case for combining them, the page says please file an issue with the desired semantics.
    • requires mounting as root.
  • --gid-offset=..., -o gid-offset=... β€” works exactly like --uid-offset, just for groups instead of users.

πŸŽ€ FILE CREATION POLICY πŸŽ€

New files and directories get created so they're owned by the mounter. bindfs can either let that happen (that's the default for normal users), or it can try to change the owner to the uid/gid of the process that's trying to create the file (that's the default for root). You can also make it try to change the owner to one particular user or group. so many options, main character energy fr fr πŸ‘‘

  • --create-as-user, -o create-as-user β€” tries to change the owner and group of new files and directories to the uid and gid of the caller. this can only work if the mounter is root. it's also the default behavior (mimicking mount --bind) when the mounter is root.
  • --create-as-mounter, -o create-as-mounter β€” all new files and directories will be owned by the mounter. this is the default for non-root mounters.
  • --create-for-user=user, -o create-for-user=... β€” tries to change the owner of new files and directories to the user specified here. this can only work if the mounter is root. this option overrides both --create-as-user and --create-as-mounter.
  • --create-for-group=group, -o create-for-group=... β€” tries to change the owning group of new files and directories to the group specified here. this can only work if the mounter is root. this option overrides both --create-as-user and --create-as-mounter.
  • --create-with-perms=permissions, -o create-with-perms=... β€” works like --perms, except it's applied to the permission bits that new files get in the source directory. normally the permissions of new files depend on the creating process's preferences and umask. this option lets you modify those permissions or override them completely. details in PERMISSION SPECIFICATION below.

πŸ’€ CHOWN/CHGRP POLICY πŸ’€

The behaviour of chown/chgrp calls can be changed. by default they're passed straight through to the source directory, even if bindfs is set to show a fake owner/group. a chown/chgrp call will only succeed if the user has enough mirrored permissions to chmod the mirrored file AND the mounter has enough permissions to chmod the real file. both conditions, no shortcuts 🫑

  • --chown-normal, -o chown-normal β€” tries to chown the underlying file. this is the default.
  • --chown-ignore, -o chown-ignore β€” lets chown succeed (if the user has enough mirrored permissions) but actually does nothing. a combined chown/chgrp request effectively becomes a chgrp-only request πŸ™ˆ
  • --chown-deny, -o chown-deny β€” makes chown always fail with a 'permission denied' error. a combined chown/chgrp request will fail as well.
  • --chgrp-normal, -o chgrp-normal β€” tries to chgrp the underlying file. this is the default.
  • --chgrp-ignore, -o chgrp-ignore β€” lets chgrp succeed (if the user has enough mirrored permissions) but actually does nothing. a combined chown/chgrp request effectively becomes a chown-only request.
  • --chgrp-deny, -o chgrp-deny β€” makes chgrp always fail with a 'permission denied' error. a combined chown/chgrp request will fail as well.

🌈 CHMOD POLICY 🌈

Chmod calls get forwarded to the source directory by default. this may cause unexpected behaviour if bindfs is altering permission bits. you've been warned bestie.

  • --chmod-normal, -o chmod-normal β€” tries to chmod the underlying file. this will succeed if the user has the appropriate mirrored permissions to chmod the mirrored file AND the mounter has enough permissions to chmod the real file. this is the default, specifically so it behaves like mount --bind out of the box.
  • --chmod-ignore, -o chmod-ignore β€” lets chmod succeed (if the user has enough mirrored permissions) but actually does nothing.
  • --chmod-deny, -o chmod-deny β€” makes chmod always fail with a 'permission denied' error.
  • --chmod-filter=permissions, -o chmod-filter=... β€” changes the permission bits of a chmod request before it gets applied to the original file. accepts the same permission syntax as --perms. see PERMISSION SPECIFICATION below.
  • --chmod-allow-x, -o chmod-allow-x β€” allows setting and clearing the executable attribute on files (but not directories). when used with --chmod-ignore, chmods will only affect execute bits on files and changes to other bits get discarded. with --chmod-deny, all chmods that would change any bits except execute bits on files will still fail with a 'permission denied'. this option does nothing when used with --chmod-normal.

⭐ XATTR POLICY ⭐

Extended attributes are mirrored by default, though ngl not every underlying file system supports xattrs, so temper your expectations.

  • --xattr-none, -o xattr-none β€” disables extended attributes altogether. every operation will return 'Operation not supported'.
  • --xattr-ro, -o xattr-ro β€” lets extended attributes be read-only.
  • --xattr-rw, -o xattr-rw β€” lets extended attributes be read-write (this is the default). the read/write permissions are checked against the (possibly modified) file permissions inside the mount.

πŸ¦‹ OTHER FILE OPERATIONS πŸ¦‹

  • --delete-deny, -o delete-deny β€” makes all file delete operations fail with a 'permission denied'. by default, files can still be modified if they have write permission, and renamed if the directory has write permission.
  • --rename-deny, -o rename-deny β€” makes all file rename/move operations within the mountpoint fail with a 'permission denied'. programs that move files out of a mountpoint do it by copying and deleting the original, jsyk πŸ‘€

πŸ“ RATE LIMITS πŸ“

Reads and writes through the mount point can be throttled. throttling works by sleeping the required amount of time on each read or write request. it imposes one global limit on all readers/writers, as opposed to a per-process or per-user limit β€” so everybody shares the vibe check, no cutting the line.

currently, the implementation is not entirely fair. see BUGS below.

  • --read-rate=N, -o read-rate=N β€” allow at most N bytes per second to be read. N may have one of the following (1024-based) suffixes: k, M, G, T.
  • --write-rate=N, -o write-rate=N β€” same as above, but for writes.

  • --hide-hard-links, -o hide-hard-links β€” bestie, this one just shows the hard link count of all the files as 1. that's it. that's the whole vibe. πŸ’…
  • --resolve-symlinks, -o resolve-symlinks β€” transparently resolves symbolic links. also disables creation of new symbolic links. so like, no new symlinks getting made on your watch. πŸš«πŸ”—

With these exceptions (yes there are exceptions, there are always exceptions), operations will operate directly on the target file instead of the symlink. Renaming/moving a resolved symlink (inside the same mount point) will move the symlink instead of the underlying file. Deleting a resolved symlink will delete the underlying symlink but not the destination file. This can be configured with --resolved-symlink-deletion.

ngl, note that when some programs, like vim, save files, they actually move the old file out of the way, create a new file in its place, and finally delete the old file. Doing these operations on a resolved symlink will replace it with a regular file. it's giving "surprise, you're a regular file now" 😭

Broken symlinks still show up as (unresolved) symlinks in this mode.

Symlinks are not resolved recursively. periodt.

Symlinks pointing outside the source directory are supported with the following exception: accessing the mountpoint recursively through a resolved symlink is not supported and will return an error. This is because a FUSE filesystem cannot reliably call itself recursively without deadlocking, especially in single-threaded mode. πŸ’€

  • --resolved-symlink-deletion=policy, -o resolved-symlink-deletion=policy β€” if --resolve-symlinks is enabled, this decides what happens when a resolved symlink is deleted. the options are:
    • deny β€” resolved symlinks cannot be deleted. nope. not today. πŸ™…
    • symlink-only β€” the underlying symlink is deleted, its target is not.
    • symlink-first β€” the symlink is deleted, and if that succeeds, the target is deleted but no error is reported if that fails.
    • target-first β€” the target is deleted first, and the symlink is deleted only if deleting the target succeeded.

The default is symlink-only.

heads up bestie: deleting files inside symlinked directories is always possible with all settings, including deny, unless something else protects those files. so don't be out here thinking deny is a full lockdown. 🫣

✨ MISCELLANEOUS OPTIONS ✨

  • -h, --help β€” displays a help message and exits. iconic behaviour honestly. πŸ‘‘
  • -V, --version β€” displays version information and exits.
  • --fuse-version β€” displays the version of the FUSE library interface that was seen at compile-time, as well as the version that bindfs currently runs with. two versions, one flag, we love a glow-up comparison. ✨
  • --no-allow-other, -o no-allow-other β€” does not add -o allow_other to FUSE options. This causes the mount to be accessible only by the current user. so like, it's a private lil party, just you. πŸŽ€

(The deprecated shorthand -n is also still accepted. yes it's old, no we don't gatekeep.)

  • --realistic-permissions, -o realistic-permissions β€” hides read/write/execute permissions for a mirrored file when the mounter doesn't have read/write/execute access to the underlying file. Useless when mounting as root, since root will always have full access. root really said "rules don't apply to me" 😀

(Prior to version 1.10 this option was the default behavior. I felt it violated the principle of least surprise badly enough to warrant a small break in backwards-compatibility. and honestly? fair.)

  • --ctime-from-mtime, -o ctime-from-mtime β€” recall that a unix file has three standard timestamps: atime (last access i.e. read time), mtime (last content modification time) ctime (last content or metadata (inode) change time). ✨

With this option, the ctime of each file and directory is read from its mtime. In other words, only content modifications (as opposed to metadata changes) will be reflected in a mirrored file's ctime. The underlying file's ctime will still be updated normally.

  • --enable-lock-forwarding, -o enable-lock-forwarding β€” forwards flock and fcntl locking requests to the source directory. This way, locking a file in the bindfs mount will also lock the file in the source directory. πŸ”’
this option must be used with --multithreaded because otherwise bindfs will deadlock as soon as there is lock contention. deadlock is not the vibe. 😭 However, see BUGS below for caveats about --multithreaded with the current implementation.
  • --disable-lock-forwarding, -o disable-lock-forwarding β€” currently does nothing, but a future release may default to enabling lock forwarding. If you depend on this behaviour, it's recommended to set this flag explicitly. it's giving "future-proofing, bestie." πŸ¦‹
  • --enable-ioctl, -o enable-ioctl β€” enables forwarding of ioctl, which is needed for some advanced features such as append-only files (chattr +a). Note that the ioctl action will be performed as the mounter, not the calling user. No efforts are made to check whether the calling user would ordinarily have the permissions to make the ioctl. This may be a security concern, especially when mounting as root. 🚨
lowkey this one is a big deal. the mounter does it, not the caller. read that again. please read that again.
  • --block-devices-as-files, -o block-devices-as-files β€” shows block devices as regular files. simple. clean. no notes. πŸ’…
  • --multithreaded, -o multithreaded β€” run bindfs in multithreaded mode. While bindfs is designed to be otherwise thread-safe, there is currently a race condition that may pose a security risk for some use cases. See BUGS below. ⚠️
  • --direct-io, -o direct-io β€” forwards each read/write operation 1:1 to the underlying FS, disabling batching and caching by the kernel. Some applications may require this, however it may be incompatible with other applications, as currently it has issues with mmap(2) calls, at least. 😬
  • --no-direct-io, -o no-direct-io β€” this option is provided in case the default changes in the future.
  • --forward-odirect=alignment, -o forward-odirect=alignment β€” enable experimental O_DIRECT forwarding, with all read/write requests rounded to the given alignment (in bytes). By default, the O_DIRECT flag is not forwarded to the underlying FS. See open(2) for details about O_DIRECT.

Only works on Linux. Ignored on other platforms. (linux girlies stay winning 🐧)


πŸ”₯ FUSE OPTIONS πŸ”₯

See fuse(8) for the full list of FUSE options. Some of the more common ones are mentioned below. we're just giving you the greatest hits. πŸ’–

  • -r, -o ro β€” make the mount strictly read-only. This even prevents root from writing to it. If this is all you need, then (since Linux 2.6.26) you can get a more efficient mount with mount --bind and then mount -o remount,ro.
  • -d, -o debug β€” enable debug output (implies -f).
  • -o fsname=name β€” sets the source directory name in /proc/mounts (returned by mount). This is automatically set as long as the source path has no special characters.
  • -f β€” foreground operation. it stays. it does not leave. main character energy fr. ✨

πŸŽ€ PERMISSION SPECIFICATION πŸŽ€

The -p option takes a comma- or colon-separated list of either octal numeric permission bits or symbolic representations of permission bit operations. The symbolic representation is based on that of the chmod(1) command. setuid, setgid and sticky bits are ignored. (ignored! we said what we said. πŸ’…)

This program extends the chmod symbolic representation with the following operands:

  • D (right hand side) β€” works like X but applies only to directories (not to executables).
  • d and f (left hand side) β€” makes this directive only apply to directories (d) or files (f). e.g. gd-w would remove the group write bit from all directories.
  • u, g, o (right hand side) β€” uses the user (u), group (g) or others (o) permission bits of the original file.
    • e.g. g=u would copy the user's permission bits to the group.
    • ug+o would add the others' permissions to the owner and group.

🌸 Examples 🌸

  • o-rwx β€” removes all permission bits from others. bye felicia πŸ‘‹
  • g=rD β€” allows group to read all files and enter all directories, but nothing else.
  • 0644,a+X β€” sets permission bits to 0644 and adds the execute bit for everyone to all directories and executables.
  • og-x:og+rD:u=rwX:g+rw β€” removes execute bit for others and group, adds read and directory execute for others and group, sets user permissions to read, write and execute directory/executable, adds read and write for group.

⭐ EXAMPLES ⭐

bindfs -u www -g nogroup -p 0000,u=rD ~/mywebsite ~/public_html/mysite

Publishes a website in public_html so that only the www user can read the site. 🫢


bindfs -M foo,bar,1007,@mygroup -p 0600,u+X dir mnt

Gives access to foo, bar, the user with the UID 1007 as well as everyone in the group mygroup. Sets the permission bits to 0600, thus giving the specified users read/write access, and adds the user execute bit for directories and executables. ✨


bindfs -ono-allow-other,perms=a-w somedir somedir

Makes a directory read-only and accessible only by the current user.


/home/bob/shared /var/www/shared/bob fuse.bindfs perms=0000:u+rD 0 0

An example /etc/fstab entry. Note that the colon must be used to separate arguments to perms, because the comma is an option separator in /etc/fstab. this is the trap, bestie. the colon. don't forget it. 😭


bindfs#/home/bob/shared /var/www/shared/bob fuse perms=0000:u+rD 0 0

Older systems may require this deprecated fstab syntax. (grandma syntax, we still love her πŸŽ€)


πŸ‘‘ NOTES πŸ‘‘

setuid and setgid bits have no effect inside the mount. This is a necessary security feature of FUSE.

Access to device files is denied by default by FUSE as a security precaution. Use -o dev to enable access (requires mounting as root). This may not be supported on all operating systems.

MacFuse caches file contents by default. This means that changes in source files are not always immediately visible under the mount point. -o nolocalcaches can be used to disable the cache. πŸ“

When using --mirror[-only] @somegroup, bindfs won't see changes to the group's member list. Sending bindfs a SIGUSR1 signal will make it reread the user database. so like, poke it and it'll re-check. πŸ‘‰πŸ“š

The following extra options may be useful under osxfuse: -o local,allow_other,extended_security,noappledouble See https://github.com/osxfuse/osxfuse/wiki/Mount-options for details.

πŸ’€ BUGS πŸ’€

okay so bestie, listen up: if bindfs is run in multithreaded mode (with the --multithreaded option) then it's possible for another process to briefly see a file with an incorrect owner, group or permissions. This may constitute a security risk if you rely on bindfs to reduce permissions on new files. For this reason, as of version 1.11 bindfs runs in single-threaded mode by default. periodt. πŸ’…


Rate limiting favors the process with the larger block size. If two processes compete for read/write access, the one whose read()/write() calls specify the larger block size gets to read/write faster. The total rate limit is maintained though, and clients with equal block sizes and a similar rate of requests are treated fairly as long as the kernel orders their requests fairly. no cap. πŸ¦‹


Some features relying on xattrs might not work properly on OS X (https://github.com/mpartel/bindfs/issues/21). For instance, Finder tags seem to work but comments might not. iykyk. 😭


Please report bugs and/or send pull requests to https://github.com/mpartel/bindfs/issues. do it for the plot. 🫢


🚫 DEPRECATIONS 🚫

The option names --user and --group were deprecated and replaced with --force-user and --force-group in version 1.12. The former names clashed with standard option names. They are still available but their use is discouraged and prints a warning. The synonym --owner is also deprecated for consistency. it's giving "we moved on, but the old ones are still lurking." πŸ™ˆ


πŸ‘‘ AUTHOR πŸ‘‘

Martin PΓ€rtel <martin dot partel at gmail dot com> β€” iconic. main character energy. 🌟


πŸ” SEE ALSO πŸ”


and that's the whole BINDFS(1) page, bestie. the footer has the source/version (BINDFS(1)) and the date, but I'm not copying the line β€” just sending you off with all the love. πŸ’–βœ¨πŸ¦‹