Use cases
This page collects practical configuration patterns. Each snippet is intentionally partial — merge it into your mount config and adjust paths/IDs.
1) Mergerfs alternative (single mount over many disks)
Goal: Present multiple disks as a single mountpoint, while distributing writes.
Suggested config:
mounts:
media:
storage_paths:
- { id: d1, path: /mnt/disk1/media, indexed: false }
- { id: d2, path: /mnt/disk2/media, indexed: false }
- { id: d3, path: /mnt/disk3/media, indexed: false }
storage_groups:
disks: [d1, d2, d3]
routing_rules:
- match: '**'
read_targets: [disks]
write_targets: [disks]
write_policy: most_free
path_preserving: true
- Pros
- Simple mental model (one mount).
- Easy to expand capacity by adding another
storage_path. - Cons
- Writes are still “one target per file” (not striping).
Recommendation: Use write_policy: most_free + path_preserving: true for the usual “fill the emptiest disk but keep directories together” behavior.
2) Media library (SSD for hot writes, HDD for capacity)
Goal: Put new writes on SSD, keep reads/listings unified, then move older files to HDD.
Recommended folder layout
Keep the same relative layout on every disk:
/mnt/ssd1/media/library/{movies,tv,music}/...
/mnt/ssd2/media/library/{movies,tv,music}/...
/mnt/hdd1/media/library/{movies,tv,music}/...
/mnt/hdd2/media/library/{movies,tv,music}/...
/mnt/hdd3/media/library/{movies,tv,music}/...
This pairs well with path_preserving: true.
Suggested config:
mounts:
media:
storage_paths:
- { id: ssd1, path: /mnt/ssd1/media, indexed: false }
- { id: ssd2, path: /mnt/ssd2/media, indexed: false }
- { id: hdd1, path: /mnt/hdd1/media, indexed: true }
- { id: hdd2, path: /mnt/hdd2/media, indexed: true }
- { id: hdd3, path: /mnt/hdd3/media, indexed: true }
storage_groups:
ssds: [ssd1, ssd2]
hdds: [hdd1, hdd2, hdd3]
routing_rules:
- match: 'library/**'
read_targets: [ssds, hdds]
write_targets: [ssds]
write_policy: most_free
path_preserving: true
- match: '**'
targets: [ssds, hdds]
write_policy: most_free
path_preserving: true
mover:
enabled: true
jobs:
- name: ssd-to-hdd
trigger:
type: usage
threshold_start: 80
threshold_stop: 70
source:
groups: [ssds]
patterns: ['library/{movies,tv,music}/**']
destination:
groups: [hdds]
policy: most_free
path_preserving: true
conditions:
min_age: 24h
- Pros
- SSD absorbs “churn” (new files, renames, lots of small metadata operations).
- HDD can stay idle longer because listings come from the index.
- Cons
- PolicyFS does not spin down disks by itself; you still need OS-level HDD power management.
Recommendation: Mark HDDs as indexed: true to reduce metadata disk touches. Use mover thresholds so the SSDs do not fill up.
3) NVR / CCTV storage (tiered retention)
Goal: Write new footage to SSD (IOPS), then archive to HDD after a minimum age.
Suggested config:
mounts:
nvr:
storage_paths:
- { id: ssd1, path: /mnt/ssd1/nvr, indexed: false }
- { id: ssd2, path: /mnt/ssd2/nvr, indexed: false }
- { id: hdd1, path: /mnt/hdd1/nvr, indexed: false }
- { id: hdd2, path: /mnt/hdd2/nvr, indexed: false }
storage_groups:
hot: [ssd1, ssd2]
archive: [hdd1, hdd2]
routing_rules:
- match: '**'
read_targets: [hot, archive]
write_targets: [hot]
write_policy: most_free
path_preserving: true
mover:
enabled: true
jobs:
- name: archive-footage
trigger:
type: manual
source:
groups: [hot]
patterns: ['**']
destination:
groups: [archive]
policy: most_free
path_preserving: true
conditions:
min_age: 24h
- Pros
- Keeps HDD from being hammered by small, frequent writes.
- Retention policy is explicit (age threshold in config).
- Cons
- The “when to run” is your responsibility (timer/scheduler).
Recommendation: Start with trigger.type: manual and run pfs move <mount> --job archive-footage from a timer you control.
4) Photo management & preview (fast browsing)
Goal: Make directory listings and metadata browsing fast without touching archival disks for metadata.
Suggested config:
mounts:
photos:
storage_paths:
- { id: hdd1, path: /mnt/hdd1/photos, indexed: true }
- { id: hdd2, path: /mnt/hdd2/photos, indexed: true }
- { id: hdd3, path: /mnt/hdd3/photos, indexed: true }
storage_groups:
archive: [hdd1, hdd2, hdd3]
routing_rules:
- match: '**'
targets: [archive]
write_policy: most_free
path_preserving: true
- Pros
readdir/getattrcomes from SQLite (fast, no metadata spin-ups).- Works well for “browse first, open occasionally”.
- Cons
- Opening the actual photo file still requires disk access.
Recommendation: Keep archival storages indexed: true and run pfs index (or pfs maint) on a schedule.
5) Seedbox hybrid (download + archive)
Goal: Download and seed from SSD, then archive to HDD later without breaking paths.
Suggested config:
mounts:
seedbox:
storage_paths:
- { id: ssd1, path: /mnt/ssd1/seedbox, indexed: false }
- { id: ssd2, path: /mnt/ssd2/seedbox, indexed: false }
- { id: hdd1, path: /mnt/hdd1/seedbox, indexed: true }
- { id: hdd2, path: /mnt/hdd2/seedbox, indexed: true }
- { id: hdd3, path: /mnt/hdd3/seedbox, indexed: true }
storage_groups:
hot: [ssd1, ssd2]
archive: [hdd1, hdd2, hdd3]
routing_rules:
- match: 'downloads/**'
read_targets: [hot, archive]
write_targets: [hot]
write_policy: most_free
path_preserving: true
- match: '**'
targets: [hot, archive]
write_policy: most_free
path_preserving: true
mover:
enabled: true
jobs:
- name: archive-downloads
trigger:
type: manual
source:
groups: [hot]
patterns: ['downloads/**']
destination:
groups: [archive]
policy: most_free
path_preserving: true
conditions:
min_age: 7d
- Pros
- High write and read performance for active torrents.
- Stable paths for apps (no bind-mount gymnastics).
- Cons
- Ratio-based policies are app-specific; PolicyFS only sees filesystem state.
Recommendation: Trigger the move job from your seedbox tooling (when it decides a torrent is “cold”). Keep trigger.type: manual and call pfs move seedbox --job archive-downloads.