{"id":51338651,"url":"https://github.com/rosvik/container-cubby","last_synced_at":"2026-07-02T05:04:12.183Z","repository":{"id":361257138,"uuid":"749223791","full_name":"rosvik/container-cubby","owner":"rosvik","description":"A cozy space for all your containers ✨","archived":false,"fork":false,"pushed_at":"2026-05-29T20:24:43.000Z","size":509,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-05-29T21:16:52.660Z","etag":null,"topics":["containers","docker","opencontainers","registry"],"latest_commit_sha":null,"homepage":"https://cubby.no","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rosvik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-01-27T23:27:48.000Z","updated_at":"2026-05-29T20:24:48.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/rosvik/container-cubby","commit_stats":null,"previous_names":["rosvik/container-cubby"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/rosvik/container-cubby","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosvik%2Fcontainer-cubby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosvik%2Fcontainer-cubby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosvik%2Fcontainer-cubby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosvik%2Fcontainer-cubby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rosvik","download_url":"https://codeload.github.com/rosvik/container-cubby/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rosvik%2Fcontainer-cubby/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35033514,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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","docker","opencontainers","registry"],"created_at":"2026-07-02T05:04:11.584Z","updated_at":"2026-07-02T05:04:12.169Z","avatar_url":"https://github.com/rosvik.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Container Cubby\n\n\u003e [!WARNING]\n\u003e Container Cubby is still in development, and may be subject to frequent and unannounced breaking changes.\n\nContainer Cubby is a container registry that aims to implement the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md) while avoiding complex features and dependencies. It is single-tenant, and stores all container data as files in a local directory.\n\n## Getting started\n\n### Running as a container\n\nPre-built images are available from [cubby.no](https://cubby.no) (Which, of course, runs Container Cubby ✨).\n\n```bash\npodman pull cubby.no/rosvik/container-cubby:main\n```\n\n```bash\npodman run -d --name container-cubby -p 8602:8602 \\\n  -v ./data:/data \\\n  -e AUTH_MODE=write_only \\\n  -e USERNAME=admin \\\n  -e PASSWORD=hunter2 \\\n  cubby.no/rosvik/container-cubby:main\n```\n\n### Building from source\n\n[Install rust](https://rustup.rs/), then execute the following to create and run an optimized binary:\n\n```bash\ncargo build --release \u0026\u0026 ./target/release/container-cubby\n```\n\n## Environment variables\n\n| Variable     | Description                                     | Default     |\n| ------------ | ----------------------------------------------- | ---------   |\n| `HOST`       | The host to bind to.                            | `localhost` |\n| `PORT`       | The port to bind to.                            | `8602`      |\n| `DATA_DIR`   | The directory to store the container data in.   | `./data`    |\n| `USERNAME`   | The username to use for authentication.         |             |\n| `PASSWORD`   | The password to use for authentication.         |             |\n| `AUTH_MODE`  | The authentication mode to use. `none`, `write_only` or `read_write`.  | Required |\n| `PRUNE_CRON` | A cron expression that sets the schedule for pruning the database. | Disabled |\n\nSee [`.env.example`](.env.example) for a starting point.\n\n### `AUTH_MODE`\n\nContainer Cubby implements the following authentication modes:\n\n- `none`: No authentication is required for reading or writing. Not recommended if the registry is publicly accessible.\n- `write_only`: Authentication is required for writing, but not for reading.\n- `read_write`: Authentication is required for both reading and writing.\n\nThe only type of authentication that is supported is basic auth for a single user/password pair. If no username or password is provided, the registry will be set to read-only mode.\n\n### `PRUNE_CRON`\n\nTo avoid bloating the database with unused data, Container Cubby can be configured to delete untagged images. Images that are less than 24 hours old are not deleted to avoid issues with ongoing uploads.\n\nPruning is disabled by default. It is enabled by setting `PRUNE_CRON` as a [cron](https://en.wikipedia.org/wiki/Cron) expression. The following example will prune the database every day at midnight UTC:\n\n```bash\n# sec, min, hour, day of month, month, day of week\nPRUNE_CRON=\"0 0 0 * * *\"\n```\n\n## Storage\n\nContainer Cubby stores all container data in a local directory. The location of this directory can be set by the `DATA_DIR` environment variable.\n\nThis is implemented using:\n- directories to represent namespaces.\n  - E.g. containers under the `rosvik/container-cubby` namespace are stored in `\u003cDATA_DIR\u003e/containers/rosvik/container-cubby/`.\n- files to store manifest and blob data.\n  - Manifests are stored as `sha256:\u003cmanifest hash\u003e.json` in namespace folders.\n  - Blobs are stored in the `\u003cDATA_DIR\u003e/blobs` folder.\n- symbolic links to represent relations between files.\n  - Tags are represented as symlinks to manifest files.\n  - Instead of storing blobs per namespace, the namespace directories contains symlinks to the blob directory. This way, when two namespaces refers to blobs with the same hash, only one blob file is stored.\n- [extended attributes](https://wiki.archlinux.org/title/Extended_attributes) to store file metadata.\n  - The `user.mime_type` extended attribute is used to store the media type of manifests.\n\nAs an example, if the image `rosvik/container-cubby:latest` is created as one manifest which points to two blobs with hashes `sha256:abcdef123456` and `sha256:123456abcdef`, then the following files will be created:\n\n```\n\u003cDATA_DIR\u003e/\n├── containers/\n│   └── rosvik/\n│       └── container-cubby/\n│           ├── latest.json                      [SYMLINK]\n│           ├── sha256:\u003cmanifest hash\u003e.json\n│           ├── sha256:abcdef123456.blob         [SYMLINK]\n│           └── sha256:123456abcdef.blob         [SYMLINK]\n└── blobs/\n    ├── 12/\n    │   └── 3456abcdef.blob\n    └── ab/\n        └── cdef123456.blob\n```\n\nHere, `latest.json` is a symlink to `sha256:\u003cmanifest hash\u003e.json`, and `sha256:abcdef123456.blob` is a symlink to `blobs/ab/cdef123456.blob`.\n\n\u003e [!NOTE]\n\u003e Since symlinks and extended attributes are OS-specific features, Container Cubby is not guaranteed to work on all operating systems. It is periodically tested and expected to work on MacOS, Debian, Ubuntu and Arch Linux. To verify that your OS is supported, run `cargo test` and check that all tests pass.\n\n### Handling of the data directory\n\nDue to the use of symlinks and extended attributes, some caveats apply when you want to move or backup the data directory. For example, the `cp` command doesn't preserve extended attributes, and the `--archive` parameter should be used to preserve both symlinks and extended attributes.\n\n```bash\ncp --archive data/ data-backup/\n```\n\nYou can read more about this on ArchWiki under [Extended Attributes \u003e Preserving extended attributes](https://wiki.archlinux.org/title/Extended_attributes#Preserving_extended_attributes).\n\n## Spec conformance\n\nThe endpoints as defined by the [OCI Distribution Spec](https://specs.opencontainers.org/distribution-spec/#endpoints), and the project's current progress is as follows:\n\n| ID      | Method   | API Endpoint                                                 | Implemented |\n| ------- | -------- | ------------------------------------------------------------ | ----------- |\n| end-1   | GET      | `/v2/`                                                       | ✅          |\n| end-2   | GET/HEAD | `/v2/\u003cname\u003e/blobs/\u003cdigest\u003e`                                  | ✅          |\n| end-3   | GET/HEAD | `/v2/\u003cname\u003e/manifests/\u003creference\u003e`                           | ✅          |\n| end-4a  | POST     | `/v2/\u003cname\u003e/blobs/uploads/`                                  | ✅          |\n| end-4b  | POST     | `/v2/\u003cname\u003e/blobs/uploads/?digest=\u003cdigest\u003e`                  | ✅          |\n| end-5   | PATCH    | `/v2/\u003cname\u003e/blobs/uploads/\u003creference\u003e`                       | ✅          |\n| end-6   | PUT      | `/v2/\u003cname\u003e/blobs/uploads/\u003creference\u003e?digest=\u003cdigest\u003e`       | ✅          |\n| end-7a  | PUT      | `/v2/\u003cname\u003e/manifests/\u003creference\u003e`                           | ✅          |\n| end-7b  | PUT      | `/v2/\u003cname\u003e/manifests/\u003cdigest\u003e?tag=1\u0026tag=2\u0026tag=3`            | ✅          |\n| end-8a  | GET      | `/v2/\u003cname\u003e/tags/list`                                       | ✅          |\n| end-8b  | GET      | `/v2/\u003cname\u003e/tags/list?n=\u003cinteger\u003e\u0026last=\u003ctagname\u003e`            | ✅          |\n| end-9   | DELETE   | `/v2/\u003cname\u003e/manifests/\u003creference\u003e`                           | ✅          |\n| end-10  | DELETE   | `/v2/\u003cname\u003e/blobs/\u003cdigest\u003e`                                  | ✅          |\n| end-11  | POST     | `/v2/\u003cname\u003e/blobs/uploads/?mount=\u003cdigest\u003e\u0026from=\u003cother_name\u003e` | ✅          |\n| end-12a | GET      | `/v2/\u003cname\u003e/referrers/\u003cdigest\u003e`                              | ❌          |\n| end-12b | GET      | `/v2/\u003cname\u003e/referrers/\u003cdigest\u003e?artifactType=\u003cartifactType\u003e`  | ❌          |\n| end-13  | GET      | `/v2/\u003cname\u003e/blobs/uploads/\u003creference\u003e`                       | ✅          |\n| end-14  | DELETE   | `/v2/\u003cname\u003e/blobs/uploads/\u003creference\u003e`                       | ❌          |\n\nThe referrers endpoints (end-12a and end-12b) are not implemented, mostly due to there not being an obvious way to support it without slowly reading all manifests per namespace on disk. See [this issue](https://github.com/rosvik/container-cubby/issues/23) for progress on this when/if a solution is being looked into.\n\nThis means the registry is not fully conformant with v1.1 of the spec. Conformance with v1.0 should be quite good, but see my fork of the spec conformance test suite for some nitpicks: [rosvik/oci-distribution-spec](https://github.com/rosvik/oci-distribution-spec)\n\nThat being said, there are plenty of details around pulling and pushing images that tools rely on that are not covered by the spec. So as a secondary goal, Container Cubby will try to support [Podman](https://podman.io/), [Skopeo](https://github.com/containers/skopeo), [Docker CLI](https://www.docker.com/products/cli/) and [Containerization](https://github.com/apple/containerization).\n\nIf you find any issues with these tools or spec compliance, feel free to open an issue!\n\n## Contributing\n\nContributions are very welcome! If you notice any bugs or have suggestions, please feel free to open an issue or make a PR.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosvik%2Fcontainer-cubby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frosvik%2Fcontainer-cubby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frosvik%2Fcontainer-cubby/lists"}