mergerfs/mkdocs/docs/config/branches.md
2026-09-21 11:46:15 -05:00

237 lines
8.3 KiB
Markdown

# branches
The `branches` argument is a colon (':') delimited list of paths to be
pooled together. It does not matter if the paths are on the same or
different filesystems nor does it matter [the filesystem
type](../faq/compatibility_and_integration.md/#what-filesystems-can-be-used-as-branches)
(within reason). Used and available space metrics will not be
duplicated for paths on the same filesystem and any features which
aren't supported by the underlying filesystem (such as file attributes
or extended attributes) will return the appropriate errors.
Branches currently have two options which can be set. A
[mode](#branch-mode) which impacts whether or not the branch is
included in a policy calculation and a individual
[minfreespace](#minfreespace) value. The values are set by
prepending an `=` at the end of a branch designation and using commas
as delimiters. Example: `/mnt/hdd/disk0=RW,1234`
### branch mode
- RW: (read/write) - Default behavior. Will be eligible in all policy
categories.
- RO: (read-only) - Will be excluded from `create` and `action`
policies. Same as a read-only mounted filesystem would be (though
faster to process).
- NC: (no-create) - Will be excluded from `create` policies. You can't
create on that branch but you can change or delete.
### minfreespace
Same purpose and syntax as the [global option](minfreespace.md) but
specific to the branch. Defaults to the global value.
### resolution
Each colon-delimited branch designation is resolved independently when
the `branches` option is parsed, both at startup and when it is updated
through the runtime API:
1. The path portion is expanded as a glob.
2. If the glob matches one or more directories, each match becomes a
branch.
3. If the glob has no matches, mergerfs logs a notice and keeps the
configured path unchanged as a single, literal branch.
4. mergerfs resolves each resulting path with `realpath`. If that
succeeds, the canonical path is stored. If it fails, typically
because the path does not exist yet, the unchanged path is stored.
5. A path which exists but is not a directory is logged and skipped. A
path which does not exist is logged but retained.
Consequently, a literal branch such as `/mnt/hdd/disk0/foobar` may be
configured before it exists and can become usable after
`/mnt/hdd/disk0` is mounted. Branch resolution is not repeated in the
background, however. If `/mnt/hdd/disk0/*` has no matches when it is
resolved, mergerfs stores the literal path `/mnt/hdd/disk0/*`;
directories which match it later are not discovered automatically.
Update `branches` through the runtime API or restart mergerfs to
resolve the glob again.
### globbing
To make it easier to include multiple branches mergerfs supports
[globbing](http://linux.die.net/man/7/glob). **The globbing tokens
MUST be escaped when using via the shell else the shell itself will
apply the glob itself.**
```
# mergerfs /mnt/hdd/\*:/mnt/ssd/\* /media
```
The above line will use all directories within `/mnt/hdd` and
`/mnt/ssd`.
To have the pool mounted at boot or otherwise accessible from related
tools use `/etc/fstab`.
```
# <file system> <mount point> <type> <options> <dump> <pass>
/mnt/hdd/*:/mnt/ssd/* /media mergerfs minfreespace=16G 0 0
```
**NOTE:** The globbing is done at mount or when updated using the
runtime API. If a new directory is added matching the glob after the
fact it will not be automatically included.
A convenient way to configure branches is to use
[symlinks](../quickstart.md/#etcfstab-w-config-file).
## branch setup
`mergerfs` does **not** require any special setup of branch paths in
order to be used however here are some suggestions.
### layout
When you have a large collection of storage devices, types of storage,
and types of interconnects it can be useful to have a verbose naming
convention. My preference is to create a directory within `/mnt/` for
each major type of storage device and/or interconnect. `hdd` for
traditional hard drives; `ssd` for slower SATA based SSDs; `nvme` for
M.2 or U.2 NVME SSDs; `remote` for NFS, SMB, sshfs, etc.
The mount points within those directories are named after the size of
the storage and its serial number in the case of physical storage and
the hostname and remote filesystem for remote.
```
$ ls -lh /mnt/
total 16K
drwxr-xr-x 8 root root 4.0K Aug 18 2024 hdd
drwxr-xr-x 6 root root 4.0K Oct 8 2024 nvme
drwxr-xr-x 3 root root 4.0K Aug 24 2024 remote
drwxr-xr-x 3 root root 4.0K Jul 14 2024 ssd
$ ls -lh /mnt/hdd/
total 8K
d--------- 2 root root 4.0K Apr 14 15:58 10T-01234567
d--------- 2 root root 4.0K Apr 12 20:51 20T-12345678
$ ls -lh /mnt/nvme/
total 8K
d--------- 2 root root 4.0K Apr 14 16:00 1T-ABCDEFGH
d--------- 2 root root 4.0K Apr 14 23:24 1T-BCDEFGHI
$ ls -lh /mnt/remote/
total 8K
d--------- 2 root root 4.0K Apr 12 20:23 foo-sshfs
d--------- 2 root root 4.0K Apr 12 20:24 bar-nfs
# You can find the serial number of a drive using lsblk
$ lsblk -d -o NAME,PATH,SIZE,SERIAL
NAME PATH SIZE SERIAL
sda /dev/sda 9.1T 01234567
sdb /dev/sdb 18.2T 12345678
nvme0n1 /dev/nvme0n1 953.9G ABCDEFGH
nvme1n1 /dev/nvme1n1 953.9G BCDEFGHI
```
### permissions and mode
#### mount points
To ensure the directory is **only** used as a point to mount another
filesystem it is good to lock it down as much as possible. Be sure to
do this **before** mounting a filesystem to it.
```
$ sudo chown root:root /mnt/hdd/10T-XYZ
$ sudo chmod 0000 /mnt/hdd/10T-XYZ
$ sudo setfattr -n user.mergerfs.branch_mounts_here
$ sudo chattr +i /mnt/hdd/10T-XYZ
```
The extended attribute `user.mergerfs.branch_mounts_here` is used by
the [branches-mount-timeout](branches-mount-timeout.md) option to
recognize whether or not a mergerfs branch path points to the intended
filesystem.
The `chattr` is likely to only work on EXT{2,3,4} filesystems but will
restrict even `root` from modifying the directory or its content but
is still able to be a mount point.
#### mounted filesystems
For those new to Linux, intending to be the primary individual logged
into the system, or simply want to simplify permissions it is
recommended to set the root of mounted filesystems like `/tmp/` is set
to. Owned by `root`, `ugo+rwx` and [sticky
bit](https://en.wikipedia.org/wiki/Sticky_bit) set.
This must be done **after** mounting the filesystem to the target
mount point.
```
$ sudo chown root:root /mnt/hdd/10T-SERIALNUM
$ sudo chmod 1777 /mnt/hdd/10T-SERIALNUM
$ sudo setfattr -n user.mergerfs.branch /mnt/hdd/10T-SERIALNUM
```
### formatting
While even less relevant to mergerfs than the details above the topic
does com up regularly with mergerfs users. When it comes to
partitioning and formatting it is suggested to keep things
simple. Most users of mergerfs will be using the whole drive capacity
and as such have a singular partition and filesystem on that
partition. Something many people don't realize is that the partition
is not necessary and actually can become problematic.
Rather than creating paritions just format the block device. Let's use
`/dev/sda` as an example.
```
$ lsblk -d -o NAME,PATH,SERIAL /dev/sda
NAME PATH SERIAL
sda /dev/sda 01234567
$ sudo mkfs.ext4 -m0 -L 01234567 /dev/sda
mke2fs 1.47.0 (5-Feb-2023)
Discarding device blocks: done
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: ede8bf96-9aff-464e-a4fb-a4ab8a197cd7
Superblock backups stored on blocks:
32768, 98304, 163840, 229376
Allocating group tables: done
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
```
You can then use the serial number as the identifier in `fstab`.
```
# <file system> <mount point> <type> <options> <dump> <pass>
LABEL=01234567 /mnt/hdd/10TB-01234567 auto nofail 0 2
```
Benefits of doing it this way?
* One less thing (partitions) to configure and worry about.
* Guarantees alignment of blocks
* Makes it easier to use the drive with different enclosures. Some
SATA to USB adapters use 4K blocks while the drive itself is using
512b. If you create partitions with one block size and move the
drive to a controller that uses the other the offset on the device
where the filesystem starts will be misinterpreted. It is possible
to manually fix this but it isn't well documented and avoidable.