Zipfuse
ZipFUSE is a read-only FUSE filesystem that mirrors another FS, presenting all its ZIP archives as folders; comes with on-the-fly, in-memory extraction and a built-in responsive diagnostics dashboard.
Install / Use
/learn @desertwitch/ZipfuseREADME
<img alt="Example" src="assets/example.gif" width="650"><br>
ZipFUSE Filesystem
zipfuse is a read-only FUSE filesystem that mirrors another filesystem, but
exposing only its contained ZIP archives as files and folders. It handles
in-memory enumeration, chunked streaming and on-the-fly extraction - so that
consumers remain entirely unaware of an archive being involved. It includes a
HTTP webserver for a responsive diagnostics dashboard and runtime configurables.
The filesystem strives to remain simple and purpose-driven, while also utilizing caching both in userspace and on the kernel side for improved performance. In contrast to similar filesystems, it does not mount single ZIP archives, but handles any ZIP archives contained within a filesystem without re-mounting.
While initially developed entirely for a personal need and being used with photo albums, it is organically growing into a far more general-purpose direction, so that it can be useful for other applications also.
Building from source
To build from source, a Makefile is included with the project's source code.
Running make all will compile the application and pull in any necessary
dependencies. make check runs the test suite and static analysis tools.
The Makefile assumes a Go installation (1.25.1+) as a prerequisite.
git clone https://github.com/desertwitch/zipfuse.git
cd zipfuse
make all
./zipfuse --help
Running make all produces two binaries:
zipfuse- binary of the FUSE filesystemmount.zipfuse- binary of the FUSE mount helper
The latter is needed only for mounting with mount(8) or /etc/fstab.
The documentation can be built using make docs (requires asciidoc & w3m).
Installing the filesystem
You will need to ensure that you have FUSE (libfuse, fuse3...) installed on
the system that you are planning to use zipfuse on. The only hard dependency
of zipfuse is the fusermount3 binary, so ensure it exists in your $PATH.
The recommended location to install FUSE filesystems to can differ between Linux
distributions. Most important is that you install the binaries to a location
that is covered in your $PATH environment variable. A common and relatively
portable solution would be installing the zipfuse binary into /bin and the
mount.zipfuse binary into /sbin on your system. You have to ensure that the
files have the appropriate permissions set for users intending to execute them,
specifically the executable bit needs to be set on both binaries (chmod +x).
As can be derived from the recommended paths above, the zipfuse binary itself
does not need elevated permissions. In contrast, the mount.zipfuse is usually
executed by the system as root (when processing /etc/fstab), but will (when
configured to do so) execute the filesystem binary as a given unprivileged user.
You can install the documentation manpages by simply copying the release-bundled
manpage files from the man directory to the location observed by your man
program. If building from source, they will be present in docs, respectively.
If unsure about the target paths, executing of man --path should reveal them.
Mounting the filesystem
Mounting with command-line or systemd service (recommended):
The zipfuse filesystem binary runs as a foreground process and is ideal for
systemd wrapping, or use directly from command-line as either a foreground or
background (paired with nohup and/or &) process. For continous usage,
integration into the larger systemd framework is recommended and preferable.
For mounting using the command-line:
zipfuse <source> <mountpoint> [flags]
<source> is the root of the underlying filesystem to expose.
<mountpoint> is the mountpoint where the FUSE filesystem will appear.
For mounting using a systemd service unit:
[Unit]
Description=ZipFUSE
[Service]
Type=simple
ExecStart=/usr/local/bin/zipfuse /home/alice/zips /home/alice/zipfuse --webserver :8000
Restart=on-failure
RestartSec=5
TimeoutStartSec=30
TimeoutStopSec=30
KillSignal=SIGTERM
User=alice
Group=alice
[Install]
WantedBy=multi-user.target
It is not recommended to use a .mount unit over a .service unit.
The reason is that a .mount unit would again rely on the FUSE mount helper.
For more complex orchestration with systemd, see also inside the examples folder.
The above are the recommended and modern approaches for almost all use cases.
Mounting with mount(8) and /etc/fstab:
For users not able to use systemd, a FUSE mount helper is provided, so the
filesystem can be used with mount(8) or also /etc/fstab entry. This usually
requires putting the mount.zipfuse binary into /sbin or another location
that the mount(8) program examines for the filesystem helper binaries.
For mounting using the mount(8) program:
sudo mount -t zipfuse /home/alice/zips /home/alice/zipfuse -o setuid=alice,allow_other,webserver=:8000
For mounting using an entry in the /etc/fstab file:
# <file system> <mount point> <type> <options> <dump> <pass>
/home/alice/zips /home/alice/zipfuse zipfuse setuid=alice,allow_other,webserver=:8000 0 0
Additional mount options to control mount helper behavior itself:
setuid=USER (as username or UID; overrides executing user)
xbin=/full/path/to/zipfuse/binary (overrides filesystem binary)
xlog=/full/path/to/writeable/logfile (overrides filesystem logfile)
xtim=SECS (numeric and in seconds; overrides filesystem mount timeout)
As you can see, program options (read more below) need format conversion:
--allow-other --webserver :8000 is turning into allow_other,webserver=:8000
Note that FUSE mount helper events are printed to standard error (stderr).
Any filesystem events are printed to /var/log/zipfuse.log (if it is writeable).
Unmounting the filesystem
The filesystem will observe SIGTERM and SIGINT to initiate a graceful
unmount of the filesystem, if it is not busy. In foreground mode, this means you
can simply press CTRL+C to unmount the filesystem. In background mode, you can
send SIGTERM to the filesystem's PID using kill. Alternatively, of course,
fusermount3 -u or umount can be used directly on the mountpoint, which also
allows forcing an unmount on a stuck as busy filesystem (if so required).
Updating the filesystem version
You can update the filesystem by simply replacing any installed files in the locations you have installed them to with their new counterparts. This is best done when no instances of the filesystem are currently mounted.
Program options and configurables
zipfuse <source> <mountpoint> [flags]
| Flag | Shorthand | Default | Description |
|------|-----------|---------|-------------|
| --allow-other <bool> | -a | (true if root; false if not) | Allow other system users to access the mounted filesystem. |
| --dry-run <bool> | -d | false | Do not mount; instead print all would-be inodes and paths to standard output. |
| --fd-cache-bypass <bool> | (none) | false | Disable file descriptor caching; open/close a new file descriptor on every single request. |
| --fd-cache-size <int> | (none) | (70% of fd-limit) | Maximum open file descriptors to retain in cache (for more performant re-accessing). |
| --fd-cache-ttl <duration> | (none) | 60s | Time-to-live before evicting cached file descriptors (that are not in use). |
| --fd-limit <int> | (none) | (50% of OS soft limit) | Maximum total open file descriptors at any given time (must be > fd-cache-size). |
| --flatten-zips <bool> | -f | false | Flatten ZIP-contained subdirectories into one directory per ZIP archive. |
| --force-unicode <bool> | (none) | true | Unicode (or fallback to synthetic generated) paths for ZIPs; disabling garbles non-compliant ZIPs when trying to be interpreted as unicode. |
| --must-crc32 <bool> | (none) | false | Force i
