# UtahFS: a FUSE drive over object storage, where the archive size is the only thing that leaks

> UtahFS mounts an encrypted synthetic drive that stores its data in S3, GCS, B2 or Wasabi, hiding file names, contents, sizes and the access pattern from the provider. The single release is from 2020, and the project names its own weak point: the local write-ahead log.

**cloudflare/utahfs** — UtahFS is an encrypted storage system that provides a user-friendly FUSE drive backed by cloud storage.

- Repository: https://github.com/cloudflare/utahfs
- Stars: 812 · Forks: 49
- Language: Go
- License: BSD-3-Clause
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/cloudflare-utahfs

## A synthetic drive that writes through to object storage

UtahFS is an encrypted storage system that provides a user-friendly FUSE drive backed by cloud storage. The README describes it as meant to be similar to Dropbox, and the mechanism is a FUSE binding that creates a synthetic drive on the user's computer that they can interact with like an external hard drive.

Files stored in the drive are uploaded to a cloud storage provider, which means the drive never runs out of space and minimizes the likelihood of any files being lost. The files are encrypted such that the cloud storage provider knows almost nothing about what is being stored.

That last sentence is the design brief, and everything else in the project exists to make it true in practice. The storage layer is object storage, chosen because the README describes it as cheap and commodified, with AWS S3, Google Cloud Storage, Backblaze B2 and Wasabi named as example providers. The implementation is Go, and the dependency list in go.mod shows the shape of the machine: the AWS and Google storage clients, a FUSE binding through github.com/jacobsa/fuse, SQLite through mattn/go-sqlite3 for local state, golang.org/x/crypto for the cryptography, the Backblaze client, Prometheus client libraries for metrics, and a vendored directory in the repository.

The file list at the root is worth a look, because it names the moving parts: archive.go, blockfs.go, filesystem.go, node_manager.go and utahfs.go, with cache/ and persistent/ directories and a cmd/ directory for the binaries.

## Encryption that hides everything except the archive size

The second feature in the README's list is described as very very strong encryption, and the specifics matter more than the adjective. The method of encryption hides the number of files, file names, file contents and individual file size, and it prevents any modifications, including rollbacks.

Preventing rollbacks is worth a second look, because that is a property most encrypted storage does not offer. If the client can be rolled back to an earlier state, an attacker with access to the storage can rewind the whole archive and erase writes that happened after the snapshot they are replaying. Blocking that means the encryption scheme has to bind the archive's history together, which is a different kind of construction from encrypting each file independently.

The one thing that is clearly leaked is the maximum archive size. Archives grow to fit new data but will not shrink if that data is deleted. Instead, that space is left allocated and will be re-used if needed in the future.

That is a deliberate trade, and it has a direct consequence for anyone sizing a bucket: deletions do not give the space back. A directory of files that is repeatedly rewritten will keep the peak size of the archive, so a storage plan based on current usage rather than peak usage will be wrong.

## Oblivious RAM hides the access pattern, not just the data

The fifth feature is Oblivious RAM, or ORAM, and it is the most interesting technical commitment in the project. ORAM can be used to hide the access pattern of data from the cloud storage provider, so the provider only sees the amount of data is accessed. The README defines the access pattern for the reader: which pieces of data are being accessed, and whether the access was a read or a write.

That definition makes the gap clear. Encryption hides what a file contains and what it is called, but a provider watching request patterns can still infer a great deal: which blocks are read together, how often a given block is touched, and the shape of the access graph over your data. For some workloads that is harmless. For a project where the metadata is the secret, the file names and sizes are hidden but the pattern of use is not, and ORAM is the mechanism that addresses it.

The cost is the usual one. Oblivious structures trade space and bandwidth for the property that access patterns leak nothing, and the README does not attempt to quantify that here. What it does say is what the provider ends up seeing, which is the amount of data accessed and nothing more about which data it was. For an evaluator, that sentence is the specification to test against: take a trace of your own access pattern and ask whether the provider could have inferred the same things from the request sizes alone.

## Archive mode and the local node change what the drive does

Two features change the behaviour of the drive rather than the confidentiality of the data, and they are the ones to look at if you are trying to decide whether it fits.

Archive Mode configures the client to guard against deleting or overwriting existing files, while still allowing new files to be created and old files to be moved around. The stated purpose is protection against accidental data loss. That is a different guarantee from the encryption features, and it is a useful one for a drive that holds an archive: the threat is not an attacker but a mistaken rm, and the mode makes the mistaken rm fail rather than succeed.

The third feature, local hardware, changes the topology. If the user has server-like hardware on their LAN, a Raspberry Pi or an Intel NUC, this can be used to coordinate multiple users operating in the same archive. It can also dramatically improve the performance of uploads, because a user can upload large amounts of already-encrypted data to the server over the fast local network, and let the server take over the much slower upload to the cloud provider.

The reason that works is the encryption boundary. Data is already encrypted when it reaches the local node, so the node forwards ciphertext, and the expensive part of the pipeline, the uplink to the provider, happens once at the node rather than once per user. The node_manager.go file and the persistent/ directory are where that coordination lives.

Setup documentation is in the docs/ folder of the repository, which is where the configuration for providers, the node and the client is described.

## The write-ahead log is the weak point, and the project names it

The README has a Future Work section with a single entry, and it is the most useful thing in it for an adopter: reliability strategies for the WAL.

Changes are buffered in a local Write-Ahead Log before being sent to the cloud storage provider, and the stated risk is that if the disk that the WAL is stored on fails, it could become very difficult to return the archive to a usable, partially-regressed state.

Read that carefully, because it describes an availability and consistency problem rather than a confidentiality one. The encryption can hide everything, and the archive mode can prevent accidental deletion, and neither of those helps if the local log that records what has been written is on a disk that fails. The archive then exists in the cloud in a state that does not correspond to any clean point in its history, and getting back to a usable state means working out which writes actually landed.

The phrase partially-regressed is doing work: the design already anticipates that the archive may be behind the client's view of the world, so the recovery target is a consistent earlier state rather than the latest one. That is the right instinct, and it is the reason the WAL problem is listed as future work rather than as a known defect. For an adopter, it converts into a concrete operational question: where does the WAL live, what backs it up, and is it on the same disk as the data you are trying to protect?

## Where UtahFS is the wrong choice

The first wrong fit is a workload that needs the space back. The archive does not shrink when data is deleted, so a drive that churns through large files will keep paying for the peak. A design where the storage provider is a dumb bucket you can reason about the contents of is a different model, and if the metadata leak of the maximum size is not acceptable to you, this project cannot give you that.

The second is a team that has no local hardware. The single-process client works, and the multi-user coordination and the upload speed-up need a node on the LAN. Without one, you have the encrypted drive and none of the operational benefits that come with the local machine, and you still have the WAL on a local disk.

The third is a project that needs to be current. There is a single tagged release, v1.0 from 2020-06-15, and the last push to the repository was on 2026-04-23 with the repository not archived. The Go module declares go 1.16 and the dependencies are pinned to versions from that era, so building it today means working with a dependency set that predates several years of Go releases. The repository is not dead, the commits continue, but the released artefact is six years old, and the vendor/ directory means the dependency tree is checked in.

The fourth is a compliance environment that needs an audited, supported product. This is a Cloudflare project with a permissive BSD 3-Clause licence and a single release, and the features list is short enough to read in full, which is a virtue in a tool you are evaluating and a limit in one you are standardising on. The honest summary is that UtahFS is a well specified research grade design with one of the more interesting privacy properties in cloud storage, and the gap between that and a product with a support commitment is exactly where the WAL question lives.

## Conclusion

UtahFS fits a team that wants a Dropbox-shaped drive whose provider learns nothing about the data, and that is prepared to run a local node to coordinate several users and speed up uploads. It does not fit a project that needs file sizes to shrink, or one without the local disk a write-ahead log needs. Before adopting it, read the WAL section and decide where the log lives, because the project itself flags that failure as the hard case.

## FAQ

### What is UtahFS?

It is an encrypted storage system written in Go that provides a FUSE drive backed by cloud storage, meant to be similar to Dropbox. Files are uploaded to a cloud provider and encrypted so that the provider knows almost nothing about what is stored.

### Which cloud storage providers does UtahFS support?

It uses object storage, which the readme describes as cheap and commodified, and names AWS S3, Google Cloud Storage, Backblaze B2 and Wasabi as example providers. The Go dependencies include the AWS and Google storage clients and a Backblaze client.

### What information does the storage provider still learn in UtahFS?

The maximum archive size, because archives grow to fit new data and do not shrink when data is deleted, so the space stays allocated for re-use. Encryption hides the number of files, file names, file contents and individual file size, and Oblivious RAM hides the access pattern.

### What does Archive Mode do in UtahFS?

It configures the client to guard against deleting or overwriting existing files while still allowing new files to be created and old files to be moved around, which the readme presents as protection against accidental data loss.

### What is the known weakness in UtahFS?

The readme lists reliability strategies for the write-ahead log as future work. Changes are buffered in a local WAL before reaching the cloud provider, and if the disk holding that log fails it could become very difficult to return the archive to a usable, partially-regressed state.

## Sources

- [cloudflare/utahfs on GitHub](https://github.com/cloudflare/utahfs)
- [Issues](https://github.com/cloudflare/utahfs/issues)
- [License: BSD-3-Clause](https://github.com/cloudflare/utahfs/blob/master/LICENSE)
- [README](https://github.com/cloudflare/utahfs/blob/master/README.md)
- [Releases](https://github.com/cloudflare/utahfs/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/cloudflare-utahfs
