Proposal: VFS cache encryption for crypt remotes
Summary
I would like to propose encrypting the VFS cache automatically when rclone mount is used with a crypt remote.
The aim is for rclone-managed cache storage to follow the crypt remote's existing configuration:
- Cache contents would be encrypted.
- Cache filenames would follow the configured filename-encryption mode.
- Cache metadata would be encrypted.
- Keys would be derived from the crypt configuration already loaded by rclone.
- No additional cache password or encryption option would be required.
For remotes that do not use crypt, existing cache behavior would remain unchanged.
Motivation
Some filesystem implementations require random or out-of-order writes. These operations require --vfs-cache-mode writes or --vfs-cache-mode full, because cache mode off only supports sequential writes.
I encountered this on macOS 26 with fuse-t's FSKit backend. Without VFS caching, writes fail with errors such as:
WriteFileHandle.Write: can't seek in file without --vfs-cache-mode >= writes
Illegal seek
Operation not permitted
Using --vfs-cache-mode writes resolves the filesystem issue, but files from a crypt remote are then represented as plaintext in the local VFS cache.
Encrypted cache storage would allow the required VFS semantics while retaining the at-rest protection configured for the remote.
Related discussions include:
- VFS Cache Dir Encryption #2896
- Rclone leaves decrypted documents in VFS cache #6746
- VFS encrypted cache
- Unencrypted cache
- Does VFSMeta leak filenames when using encrypt
Proposed Behavior
When VFS caching is enabled:
- A non-crypt remote continues using the existing cache format.
- A crypt remote automatically uses an encrypted cache format.
- No separate cache-encryption flag is needed.
- No separate cache password is needed.
- Cache encryption follows the active crypt configuration.
- If the encrypted cache cannot be opened, rclone reports an error rather than creating a new plaintext cache.
This makes the cache behavior dependent on the remote type: encrypted remotes use encrypted caches, while unencrypted remotes continue using ordinary caches.
Cache Key Derivation
Cache encryption would not introduce another password. Rclone would deterministically derive cache-specific keys from the secret key material already loaded for the crypt remote.
Conceptually:
cacheDataKey = KDF(cryptKeyMaterial, "rclone vfs cache/data/v1")
cacheMetadataKey = KDF(cryptKeyMaterial, "rclone vfs cache/metadata/v1")
The quoted strings are public purpose labels, not passwords or stored encryption keys. Given the same crypt configuration, rclone would derive the same cache keys after restarting.
Separate derived keys are useful because the remote and cache have different encryption formats:
- Remote objects are effectively immutable encrypted streams.
- Cache files support mutable blocks, random writes, truncation, and recovery.
- Cache metadata has a different structure and nonce lifecycle from file data.
Using dedicated keys keeps these encryption contexts independent. In particular, it avoids having to coordinate nonce usage between the remote-object format and the mutable cache format. It also prevents cache metadata ciphertext from being interpreted in the file-data context, or vice versa.
The version suffix is part of the domain separation. If a future cache format requires different cryptographic behavior, it could derive new keys under labels such as:
rclone vfs cache/data/v2
rclone vfs cache/metadata/v2
This would prevent ciphertext from different cache-format generations from sharing the same key domain.
Key derivation does not make the cache stronger than the original crypt credentials. Anyone who obtains the crypt secret could also derive the cache keys. Its purpose is to safely reuse the existing credential while keeping the remote, cache data, and cache metadata cryptographic protocols separate.
Filename Encryption
Cache paths could use the crypt remote's configured filename-encryption mode.
The crypt backend already provides reversible filename encryption through EncryptFileName and DecryptFileName. Reusing that behavior would allow the cache to reconstruct logical paths during startup without storing a separate plaintext filename index.
If filename encryption is disabled or configured as obfuscation, the cache would follow that choice. No additional filename key would be needed unless maintainers prefer cache filenames to use a separate cryptographic domain as well.
Metadata Encryption
The vfsMeta hierarchy contains information such as:
- Cached ranges
- Dirty state
- Remote fingerprints
- File sizes
- Modification and access times
For crypt remotes, this metadata could be authenticated and encrypted with the dedicated cache metadata key. Associated data could bind each metadata record to its encrypted path or file identifier.
Random-Access Requirements
The existing remote crypt format may not be suitable unchanged because VFS cache files are mutable and support:
- Concurrent
ReadAtandWriteAt - Random and overlapping writes
- Partial cached ranges
- Sparse files
- Truncation and extension
- Restart recovery
- Dirty-file writeback
A cache-specific format could use fixed-size, independently authenticated blocks.
Each block could contain:
- A fresh nonce
- AEAD ciphertext
- An authentication tag
Associated data could include:
- Cache format version
- File identifier
- Logical block index
A fixed record size would allow rclone to calculate the physical location of each logical block and preserve efficient random access. Partial writes would decrypt, update, and re-encrypt the affected block with a fresh nonce.
Crash consistency would need careful consideration so that an interrupted block update does not lose the only copy of dirty data.
Integration With Crypt
It may be preferable for VFS to consume a generic cache-encryption capability rather than depend directly on the crypt backend.
The crypt backend could expose an optional interface or fs.Features capability providing:
- Cache-specific key derivation
- Filename encryption and decryption
- Metadata encryption
- Encrypted random-access cache files
VFS would use that capability when the mounted filesystem resolves to a crypt remote.
An initial implementation could support:
- Direct crypt remotes
- Wrapper chains that resolve to one crypt configuration
Configurations containing multiple crypt remotes with different keys, such as some union or combine setups, may require per-entry cache identities and could be considered separately.
Cache Accounting
Encrypted blocks introduce nonce, authentication-tag, alignment, and possibly journaling overhead.
Cache limits and statistics should account for physical encrypted storage. It may be useful for RC statistics to expose both logical cached bytes and physical disk usage.
Compatibility And Migration
The encrypted cache should use an explicitly versioned format.
Suggested migration behavior:
- Existing plaintext and encrypted caches are never confused.
- Existing dirty cache entries are not discarded automatically.
- Rclone provides a clear error or migration instruction when an incompatible cache is found.
- Clean cache entries can be safely discarded and downloaded again.
- Migration of dirty plaintext entries requires an explicit user action.
- An encrypted cache is never silently replaced with a plaintext cache.
A separate versioned cache root may be the simplest initial migration strategy.
Security Scope
The proposed cache encryption would protect cached contents and metadata against offline access when rclone is not running.
It would not protect against:
- Processes with access to the active mount
- Compromise of the running rclone process
- Compromise of the crypt credentials
- Plaintext temporary files created by applications
- Operating-system swap or crash dumps
- Observation of cache size and access patterns
Questions
- Would automatically encrypting the VFS cache for crypt remotes fit the intended relationship between VFS and crypt?
- Would an optional filesystem capability be an appropriate boundary between the crypt backend and VFS?
- Is deriving domain-separated cache keys from the active crypt configuration acceptable?
- Should the first implementation target direct crypt remotes and wrapper chains containing one crypt configuration?
- How should existing plaintext caches with dirty entries be handled?
- Are there planned VFS-cache changes that this design should account for?
If the general direction seems suitable, I would be interested in developing a more detailed design for the cache file format, crash consistency, migration behavior, and the interface between crypt and vfs/vfscache.