fuse-overlayfs: an overlay filesystem in userspace for rootless containers
FUSE implementation for overlayfs
At a glance
- What is it?
- A Rust implementation of the overlay plus shiftfs model on top of FUSE, so a rootless container runtime can get copy-on-write image layers without kernel privileges. It ships static binaries for six architectures and a test suite that splits into unit tests and root integration tests.
- Who is it for?
- Adopt fuse-overlayfs if you run rootless containers and need copy-on-write image layers without the kernel overlayfs module, since that is the exact gap it fills. Skip it if your kernel has overlayfs available and you are not in a user namespace, because the in-kernel implementation is the simpler path.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 42 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap this fills is rootless containers and kernel overlayfs
An implementation of overlay+shiftfs in FUSE for rootless containers. That one line contains the whole design brief.
Overlay filesystems are how container images get their layers. A container runtime presents an image as a stack of read-only layers with a writable upper layer on top, and the copy-on-write behaviour means a write goes to the upper layer and the lower layers are never modified. That is what makes image layers cheap to share and cheap to distribute.
The catch has historically been that the kernel overlayfs implementation is not usable from a user namespace, and rootless container runtimes run inside a user namespace. So a rootless runtime either could not use overlay semantics or had to fall back to a slower storage driver. This project re-implements the overlay behaviour in userspace on top of FUSE, which the readme describes as overlay plus shiftfs.
The shiftfs part is the interesting bit for Linux specifically. It is the mechanism that lets a container see the lower layers through the mount namespace in a way that preserves the layered view while making the upper layer writes land where they should.
The audience is narrow and specific: people running rootless container tooling, most obviously Podman, who want the storage characteristics of overlay images without root. The repository topics say containers, fuse, overlay and rootless-containers, and the readme mentions rootless podman as the example of user namespace use.
The command line is a single mount with options
The usage is one command, and the shape of it is the same as the in-kernel overlayfs mount options, which means the mental model transfers.
$ fuse-overlayfs -o lowerdir=lowerdir/a:lowerdir/b,upperdir=up,workdir=workdir mergedThree directories and a mount point. The lowerdir list is colon separated and ordered, the upperdir is where writes land, the workdir is the scratch space the filesystem needs internally, and merged is the resulting mounted view.
The second example adds UID and GID mapping, which is the part that matters in a user namespace:
$ fuse-overlayfs -o uidmapping=0:10:100:100:10000:2000,gidmapping=0:10:100:100:10000:2000,lowerdir=lowerdir/a:lowerdir/b,upperdir=up,workdir=workdir mergedEach mapping value is a three part triple of the form start:size:hoststart. So the first triple maps a range of 10 container IDs starting at 0 onto a range of 100 host IDs starting at 100, and the second maps 10000 container IDs onto 2000 host IDs, which is the compression a user namespace performs when the mapping does not fit one to one.
The option syntax is the Linux mount option syntax, and the mapping syntax is the same one used by the kernel's idmapped mounts. That consistency is deliberate: the tool is meant to be a drop-in for the mount options a runtime already knows how to emit.
The requirements, and the kernel version that catches people out
There are three requirements, and one of them is conditional in a way that is easy to miss.
The first is libfuse at version 3.2.1 or later. The readme names the packages per distribution, fuse3-devel on Fedora and libfuse3-dev on Ubuntu 19.04 or later. The 3.2.1 floor is a FUSE protocol version requirement, and the dev package matters because you need the headers to build against it.
The second is conditional, and the readme flags it in bold. When using fuse-overlayfs from a user namespace, for example when using rootless podman, a Linux kernel of version 4.18.0 or later is required.
That distinction matters. If you are mounting it as root, or in a context that is not a user namespace, the kernel version floor does not apply. If you are using it the way it is primarily intended, with rootless podman, then 4.18 is a hard floor. The requirement exists because the user namespace behaviour the tool relies on, including the ID mapping, depends on kernel support that landed at that version.
The third requirement is implied rather than stated, but it is there in the form of the tool being a FUSE filesystem. The FUSE device has to be available, and the usual kernel module has to be loaded or built in.
So the check list before you run anything is short: libfuse 3.2.1 or later with dev headers, a kernel of 4.18 or later if you are in a user namespace, and a FUSE device present.
Building from Rust, and the prebuilt binaries for six architectures
fuse-overlayfs is written in Rust, and the build is a cargo build with the release profile:
cargo build --releaseThe resulting binary is at target/release/fuse-overlayfs, and installation is:
make installThe Cargo manifest shows the crate is named fuse-overlayfs at version 2.0.0, with edition 2024 and a rust-version of 1.85.0, licensed GPL-2.0-or-later, and categorised under filesystem. The dependency list is short and tells you what the implementation is built on. fuser at 0.17.0 with the abi-7-40 feature is the FUSE binding, rustix provides the system call layer with the process feature, and libc, signal-hook, parking_lot, log, env_logger, thiserror and rustc-hash make up the rest.
The release profile has lto set to true and strip set to true, which is what makes the static binaries viable.
And there is a distribution shortcut that matters more for a lot of users than the build. Pre-built static binaries for multiple architectures, x86_64, aarch64, armv7l, s390x, ppc64le and riscv64, are available from the GitHub Releases page.
That list is the real argument for this project existing as a separate artefact. s390x and ppc64le are the ones to notice. They are big-endian and niche architectures, and a statically linked binary that runs on them without a FUSE library build is a meaningful distribution problem to have solved. The recent releases show the same spread, with v1.16 on 2025-11-05, v1.17 on 2026-06-09 and v1.18 on 2026-08-30, and the last push was on 2026-09-11.
The test suite splits into unit tests and root integration tests
The Makefile is where the project's testing philosophy shows, and the split is explicit.
There is a unit-test target that runs cargo test and, in the comment, requires no root. There is an integration-test target that requires root and FUSE, and it refuses to run otherwise, checking the effective user id and printing an error and exiting if it is not zero.
The integration tests are shell scripts, and the list is revealing about what the implementation has to get right:
INTEGRATION_TESTS = \
tests/test-copyup.sh \
tests/test-dir-ops.sh \
tests/test-hardlinks.sh \
tests/test-readonly.sh \
tests/test-rename.sh \
tests/test-special-files.sh \
tests/test-symlinks.sh \
tests/test-xattr.sh \
tests/test-stress.shCopy-up is the core overlay behaviour, where a read of a file that exists only in a lower layer causes a copy into the upper layer before modification. The rest cover the semantics that separate a real overlay from a copy: directory operations, hard links, read-only mounts, rename, special files, symlinks, extended attributes, and a stress test.
Each script is run with the built binary prepended to PATH, and the target counts passes and failures and exits non-zero if any failed. There is also a test-single target for running one script by name, with the usage line naming tests/test-copyup.sh as the example.
The make test target runs unit-test and then integration-test, so a full test run needs root. The repository tree also carries a Containerfile.alpine and a tests directory, so there is a path to running the integration tests in a container instead of on a host with root.
Where this is the wrong tool
There are cases where running the in-kernel filesystem is simply the better answer, and cases where the userspace implementation cannot reach.
The first is the ordinary rootful case. If you are running containers as root with a kernel that has overlayfs, the in-kernel implementation is faster, has no FUSE dependency, and is one less moving part. This project exists to fill the rootless gap, and using it elsewhere is a choice you have to justify rather than one you get for free.
The second is the performance envelope. A FUSE filesystem pays for the round trip through the FUSE daemon on every operation. The project does not claim parity with the kernel implementation, and if you have large image layers and heavy I/O, that overhead is real.
The third is the kernel version floor in a user namespace. If you are on a kernel older than 4.18 and you need rootless, this tool cannot help, and the readme says so plainly.
The fourth is feature coverage. An overlay implementation has to reproduce the semantics of the kernel one, and edge cases exist. The integration test list is a good guide to what has been thought about, but it is not the same as full parity with every overlayfs corner case, and the readme here does not claim it.
And the fifth is that the project is young in its current form. The Cargo manifest says 2.0.0 with edition 2024, while the published releases are numbered 1.16, 1.17 and 1.18, so the 2.0 line and the release line are not obviously the same numbering, and a user picking a binary from the releases page has to know which series it belongs to.
How it compares to the kernel implementation, and how to a VFS store
Two comparisons make the trade concrete.
The first is against the kernel's own overlayfs. The difference in approach is where the copy-on-write logic runs. The kernel implementation does it in the filesystem layer itself, with the kernel knowing about layers, whiteouts, opaque directories and index features, and it is fast because there is no user space round trip. fuse-overlayfs does the same work in user space through FUSE, using the shiftfs mechanism to present the layers correctly inside a user namespace, and it is the only option when the kernel implementation is unavailable to you because you are unprivileged.
So the choice is essentially: if you can have the kernel implementation, take it; if you cannot, this is how you get overlay semantics anyway. The cost of the userspace path is the FUSE overhead and the smaller set of exotic overlay features.
The second is against the VFS storage driver, which is what a rootless runtime falls back to when it does not use this. A fallback storage driver that does not share layers costs disk space instead of FUSE latency, and that is the trade this project exists to avoid. That is the trade this project exists to avoid, and it explains why rootless users accept a FUSE filesystem as a reasonable price for keeping the layered model.
The practical decision tree is short. Rootful with overlayfs available means use the kernel. Rootless means use this, provided the kernel is 4.18 or later and you can accept the FUSE overhead. Rootless on an old kernel means accept a VFS store and its disk cost, or upgrade.
Editorial conclusion
Adopt fuse-overlayfs if you run rootless containers and need copy-on-write image layers without the kernel overlayfs module, since that is the exact gap it fills. Skip it if your kernel has overlayfs available and you are not in a user namespace, because the in-kernel implementation is the simpler path. Verify first that your kernel is at least 4.18 when you use it from a user namespace, that libfuse is at least 3.2.1, and that your distribution's container runtime actually selects this storage driver rather than the native one.
Frequently asked questions
What is fuse-overlayfs and what is it for?
It is an implementation of overlay+shiftfs in FUSE for rootless containers. It re-implements the copy-on-write layer behaviour that rootless container runtimes cannot get from the kernel overlayfs module because they run inside a user namespace.
How do I mount a merged overlay view with fuse-overlayfs?
Run fuse-overlayfs -o lowerdir=lowerdir/a:lowerdir/b,upperdir=up,workdir=workdir merged. The lowerdir list is colon separated and ordered, the upperdir receives writes, the workdir is scratch space, and merged is the mount point.
What are the requirements for fuse-overlayfs?
libfuse version 3.2.1 or later, which is fuse3-devel on Fedora and libfuse3-dev on Ubuntu 19.04 or later, and, when using it from a user namespace such as with rootless podman, a Linux kernel of version 4.18.0 or later.
How do I build and install fuse-overlayfs from source?
It is written in Rust, so run cargo build --release, which produces target/release/fuse-overlayfs, then run make install. Pre-built static binaries for x86_64, aarch64, armv7l, s390x, ppc64le and riscv64 are also available from the GitHub Releases page.
How are the fuse-overlayfs tests run?
The Makefile has a unit-test target that needs no root, and an integration-test target that requires root and FUSE and refuses to run otherwise. The integration tests are shell scripts covering copyup, directory operations, hardlinks, readonly, rename, special files, symlinks, xattrs and stress, and make test runs both targets.
What licence is fuse-overlayfs released under?
GPL-2.0-or-later, as recorded in the Cargo manifest with the COPYING file at the root of the repository. The repository is not archived, the last push was on 2026-09-11, and the recent releases are v1.18 on 2026-08-30, v1.17 on 2026-06-09 and v1.16 on 2025-11-05.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/containers-fuse-overlayfs)Was this useful?