{"id":26123209,"url":"https://github.com/composefs/composefs","last_synced_at":"2025-05-15T14:04:34.792Z","repository":{"id":37740918,"uuid":"414642631","full_name":"composefs/composefs","owner":"composefs","description":"The reliability of disk images, the flexibility of files","archived":false,"fork":false,"pushed_at":"2025-04-28T20:06:07.000Z","size":19361,"stargazers_count":525,"open_issues_count":24,"forks_count":43,"subscribers_count":28,"default_branch":"main","last_synced_at":"2025-05-13T07:18:16.841Z","etag":null,"topics":["containers","filesystem","linux","oci","oci-image"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/composefs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-07T14:50:46.000Z","updated_at":"2025-05-06T11:52:28.000Z","dependencies_parsed_at":"2024-03-25T14:15:22.110Z","dependency_job_id":"e5362001-8b6f-4e7d-b5fa-82abbb9d44c5","html_url":"https://github.com/composefs/composefs","commit_stats":null,"previous_names":["composefs/composefs","containers/composefs"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composefs%2Fcomposefs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composefs%2Fcomposefs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composefs%2Fcomposefs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/composefs%2Fcomposefs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/composefs","download_url":"https://codeload.github.com/composefs/composefs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254355334,"owners_count":22057354,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["containers","filesystem","linux","oci","oci-image"],"created_at":"2025-03-10T15:39:23.158Z","updated_at":"2025-05-15T14:04:34.765Z","avatar_url":"https://github.com/composefs.png","language":"C","readme":"# composefs: The reliability of disk images, the flexibility of files\n\nThe composefs project combines several underlying Linux features\nto provide a very flexible mechanism to support read-only\nmountable filesystem trees, stacking on top of an underlying\n\"lower\" Linux filesystem.\n\nThe key technologies composefs uses are:\n\n- [overlayfs](https://www.kernel.org/doc/Documentation/filesystems/overlayfs.txt) as the kernel interface\n- [EROFS](https://erofs.docs.kernel.org) for a mountable metadata tree\n- [fs-verity](https://www.kernel.org/doc/html/next/filesystems/fsverity.html) (optional) from the lower filesystem\n\nThe manner in which these technologies are combined is important.\nFirst, to emphasize: composefs does not store any persistent data itself.\nThe underlying metadata and data files must be stored in a valid\n\"lower\" Linux filesystem.  Usually on most systems, this will be a\ntraditional writable persistent Linux filesystem such as `ext4`, `xfs`, `btrfs` etc.\n\nThe \"tagline\" for this project is \"The reliability of disk images, the flexibility of files\",\nand is worth explaining a bit more. Disk images have a lot of desirable\nproperties in contrast to other formats such as tar and zip: they're\nefficiently kernel mountable and are very explicit about all details\nof their layout. There are well known tools such as [dm-verity](https://docs.kernel.org/admin-guide/device-mapper/verity.html)\nwhich can apply to disk images for robust security. However, disk\nimages have well known drawbacks such as commonly duplicating storage\nspace on disk, can be difficult to incrementally update, and are\ngenerally inflexible.\n\ncomposefs aims to provide a similarly high level of reliability,\nsecurity, and Linux kernel integration; but with the *flexibility* of files\nfor content - avoiding doubling disk usage, worrying about partition\ntables, etc.\n\n## Separation between metadata and data\n\nA key aspect of the way composefs works is that it's designed to\nstore \"data\" (i.e. non-empty regular files) distinct from \"metadata\"\n(i.e. everything else).\n\ncomposefs reads and writes a filesystem image which is really\njust an [EROFS](https://erofs.docs.kernel.org)\nwhich today is loopback mounted.\n\nHowever, this EROFS filesystem tree is just metadata; the underlying\nnon-empty data files can be shared in a distinct \"backing store\"\ndirectory.  The EROFS filesystem includes `trusted.overlay.redirect`\nextended attributes which tell the `overlayfs` mount\nhow to find the real underlying files.\n\n## Mounting multiple composefs with a shared backing store\n\nThe key targeted use case for composefs is versioned, immutable executable\nfilesystem trees (i.e. container images and bootable host systems), where\nsome of these filesystems may share *parts* of their storage (i.e. some\nfiles may be different, but not all).\n\nComposefs ships with a mount helper that allows you to easily mount\nimages by passing the image filename and the base directory for\nthe content files like this:\n\n```bash\nmount -t composefs /path/to/image  -o basedir=/path/to/content /mnt\n```\n\nBy storing the files content-addressed (e.g. using the hash of the content to name\nthe file), shared files only need to be stored once, yet can appear in\nmultiple mounts.\n\n## Backing store shared on disk *and* in page cache\n\nA crucial advantage of composefs in contrast to other approaches\nis that data files are shared in the [page cache](https://static.lwn.net/kerneldoc/admin-guide/mm/concepts.html#page-cache).\n\nThis allows launching multiple container images that will\nreliably share memory.\n\n## Filesystem integrity\n\nComposefs also supports [fs-verity](https://www.kernel.org/doc/html/latest/filesystems/fsverity.html)\nvalidation of the content files.  When using this, the digest of the\ncontent files is stored in the image in the `trusted.overlay.metacopy`\nextended attributes which tell overlayfs to validate that\nthe content file it uses has a matching enabled fs-verity digest. This\nmeans that the backing content cannot be changed in any way (by\nmistake or by malice) without this being detected when the file is\nused.\n\nYou can also use fs-verity on the image file itself, and pass the\nexpected fs-verity digest as a mount option, which composefs will\nvalidate. In this case we have full trust of both data and metadata of\nthe mounted file. This solves a weakness that fs-verity has when used\non its own, in that it can only verify file data, not metadata (e.g.\ninode bits like permissions and ownership, but also directory\nstructures).\n\n## Usecase: container images\n\nThere are multiple container image systems; for those using e.g.\n[OCI](https://github.com/opencontainers/image-spec/blob/main/spec.md)\na common approach (implemented by both docker and podman for example)\nis to just untar each layer by itself, and then use `overlayfs`\nto stitch them together at runtime.  This is a partial inspiration\nfor composefs; notably this approach does ensure that *identical\nlayers* are shared.\n\nHowever if instead we store the file content in a content-addressed\nfashion, and then we can generate a composefs file for each layer,\ncontinuing to mount them with a chain of `overlayfs` *or* we\ncan generate a single composefs for the final merged filesystem tree.\n\nThis allows sharing of content files between images, even if the\nmetadata (like the timestamps or file ownership) vary between images.\n\nTogether with something like\n[zstd:chunked](https://github.com/containers/storage/pull/775) this\nwill speed up pulling container images and make them available for\nusage, without the need to even create these files if already present!\n\n## Usecase: Bootable host systems (e.g. OSTree)\n\n[OSTree](https://github.com/ostreedev/ostree) already uses a content-addressed\nobject store. However, normally this has to be checked out into a regular directory (using hardlinks\ninto the object store for regular files). This directory is then\nbind-mounted as the rootfs when the system boots.\n\nOSTree already supports enabling fs-verity on the files in the store,\nbut nothing can protect against changes to the checkout directories. A\nmalicious user can add, remove or replace files there. We want to use\ncomposefs to avoid this.\n\nInstead of checking out to a directory, we generate a composefs image\npointing into the object store and mount that as the root fs. We can\nthen enable fs-verity of the composefs image and embed the digest of\nthat in the kernel commandline which specifies the rootfs. Since\ncomposefs generation is reproducible, we can even verify that the\ncomposefs image we generated is correct by comparing its digest to one\nin the ostree metadata that was generated when the ostree image was built.\n\nFor more information on ostree and composefs, see [this tracking issue](https://github.com/ostreedev/ostree/issues/2867).\n\n## tools\n\nComposefs installs two main tools:\n\n- `mkcomposefs`: Creates a composefs image given a directory pathname. Can also compute digests and create a content store directory.\n- `mount.composefs`: A mount helper that supports mounting composefs images.\n\n## mounting a composefs image\n\nThe mount.composefs helper allows you to mount composefs images (of both types).\n\nThe basic use is:\n\n```bash\nmount -t composefs /path/to/image.cfs -o basedir=/path/to/datafiles  /mnt\n```\n\nThe default behaviour for fs-verity is that any image files that\nspecifies an expected digest needs the backing file to match that\nfs-verity digest, at least if this is supported in the kernel. This\ncan be modified with the `verity` and `noverity` options.\n\nMount options:\n\n- `basedir`: is the directory to use as a base when resolving relative content paths.\n- `verity`: All image files must specify a fs-verity image.\n- `noverity`: Don't verify fs-verity digests (useful for example if fs-verity is not supported on basedir).\n- `digest`: A fs-verity sha256 digest that the image file must match. If set, `verity_check` defaults to 2.\n- `upperdir`: Specify an upperdir for the overlayfs filesystem.\n- `workdir`: Specify a workdir for the overlayfs filesystem.\n- `idmap`: Specify a path to a user namespace that is used as an idmap.\n\n## Language bindings\n\n### Rust\n\nThere is active work on a [composefs crate](https://github.com/containers/composefs-rs)\nwhich has both wrappers for invocations of the `mkcomposefs` and `composefs-info` dump tooling,\nas well as higher level repository functionality.\n\n### Go\n\nThe containers/storage Go library has [code wrapping mkcomposefs](https://github.com/containers/storage/blob/5fe400b7aedc7385e07a938d393d50600ca06299/drivers/overlay/composefs.go#L41)\nthat could in theory be extracted to a helper package.\n\n## Community forums\n\n- Live chat: [Matrix channel](https://matrix.to/#/#composefs:matrix.org)\n- Async forums: [Github discussions](https://github.com/containers/composefs/discussions)\n\n## Contributing\n\nWe have a dedicated [CONTRIBUTING](CONTRIBUTING.md) document.\n\n","funding_links":[],"categories":["C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomposefs%2Fcomposefs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcomposefs%2Fcomposefs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcomposefs%2Fcomposefs/lists"}