Request for comment: ERIS-FS - a NAR like archive

The ERIS project wants to define an file-system archival format that is optimized for ERIS content addressing.

I’m not (yet) proposing that we replace the NAR format, but we see no better use case to optimize for. Therefore we invite comments on the ERIS-FS format from the Guix and NIx communities.

Rendered: EER - ERIS-FS: A format for encoding file systems

RFC PR: #2 - ERIS-FS: A format for encoding file systems - eris/eer - Codeberg.org

(I said I wasn’t proposing to replace NAR, but I have been experimenting with replacing the worker protocol, and since the bulk of the initial worker conversation is sending NARs to the daemon, I have in my experiments serialized the NARs to ERIS, transferred the ERIS URNs to the daemon, and let the daemon get the NARs out of band, if it doesn’t have them already. The ERIS-FS format would further reduce the out-of-band traffic in this constellation by de-duplicating the archives - client.nim, daemons.nim, sockets.nim.)

2 Likes

My #1 feedback is that the URN namespace eris does not seem to be registered with the IANA. The website indicates that urn:eris:B4AA3MW3FV2TEXITL72IJTNVSGH5XQPMAI26U3QABFBVERSHCM3TOHIBO537J77XJSIUXE2KSJVZIRKIKNF6JECYQUL6QJHK3RKCJ7L7QE is a valid urn, but that is not the case if the namespace isn’t registered.

About ERIS-FS itself, the most glaring issue seems to be the large block size of 32KiB. I’m not sure if this might improve performance, but to me it just seems horribly inefficient, especially considering many paths in a nix output path are just symlinks.

The format itself seems ok, almost exactly how NAR works except for the addition of an index.

One thing I’m not sure about is what problem this solves in comparison to NAR? Your point about transferring URNs rather than full archive files seems to not really require ERIS-FS at all, you could just as well write NARs to a known location and transmit the paths.

Are you intending to build an exchange protocol, or a complete binary representation all contents inside a store path? I think these are two different things, with different requirements.


With tvix-store, we took a different approach, more tailored towards an exchange protocol: We encode the “shape” of the store path (as a merkle DAG similar to git trees), and for regular file contents, simply encode the digest of the literal contents, and rely on another service to provide these files.
Because we use blake3, seeking can be provided with verified streaming, allowing parts of the file to be fetched with confidence. Whether there’s compression over the wire when sending these blob( parts) is up to the implementation :slight_smile:

Only encoding the “shape” of the filesystem structure, but leaving the serving of file contents up to another service makes allows substition of files to happen out-of-band, and only when needed.


I didn’t fully make up my mind yet if there’s a need to define some other “pack format”, or whether there should just be more granular requests. In my case, I simply added ways to synthesize NAR on demand if e.g. the NarHash or NarSize is needed.


In any case, I would not make the compression (+level) part of the serialization format. It’s hard to change afterwards, and forcing zstd with compression level 19 for a local client talking to a daemon feels unnecessary.

1 Like

The goal is a terse but complete binary representation, not an exchange protocol. You are right that these are different things so I shouldn’t frame this as the latter. I suppose NAR does both but the emphasis for ERIS-FS would be long-term archival images that de-dup well and can be mounted into a VFS.

There is a motivation in the Nix community to optimize the store for de-duplication so its easy to contextualize things in that regard. ERIS-FS is probably more interesting as a Nix/Guix flavor of distri packages, where packages are represented as mountable images.

I imagine this a better approach than serializing everything as file archives.

Right, We need to do anything at this point but we should be experimenting. Synthesizing NARs is probably going to be the migration path in any case.

Compression does make this impractical for normal client-daemon communication. At this point zstd is more of a placeholder than a fixed detail. It’s awkard but we can’t avoid this per-file deterministic compression. If the files were uncompressed within the archive and compression was applied to the whole archive image then de-duplication would be impractical and in some cases there would be read-amplification when files cross ERIS block alignment. When the ERIS-FS representation is serialized to ERIS the ERIS blocks are encrypted, so the blocks at-rest are uncompressible.

Where is it claimed that urn:eris:… is a valid URN? The ERIS-FS document does not mention URNs anywhere and the ERIS website and spec use the term URN but do not qualify urn:eris as a “valid URN” in any specific normative bureaucratic sense. The urn:eris format is described as being a URN because meets the syntatic and semantic definition of a URN. We use the term URN in a context that is limited to these considerations, in the same way that the word “universal” in URN is limited in scope, as URNs are not in fact “universal resources”.

The spec has been updated to support aligning files to both 32KiB and 1Kib eer/eer/eris-fs/index.md at eris-fs - eris/eer - Codeberg.org.