# Kalandra Mirror your Git repositories. Kalandra fetches your repositories and syncs them to one or more destinations: - **Git remotes** — mirror branches and tags to another forge (e.g., [tangled.org](https://tangled.org)) or any Git server you can push to. - **S3-compatible object storage** — back up repositories as [`git bundle`](https://git-scm.com/docs/git-bundle) files to AWS S3, Cloudflare R2, etc. Uploads are skipped when a repository's refs haven't changed since the last backup. ## Usage Create a `kalandra.toml` (see [`kalandra.example.toml`](kalandra.example.toml)): ```toml [destinations.tangled] type = "git" url = "git@tangled.org:your-name/{name}" [destinations.r2] type = "s3" bucket = "git-backups" endpoint = "https://.r2.cloudflarestorage.com" region = "auto" [[repos]] name = "kalandra" source = "https://github.com/your-name/kalandra.git" destinations = ["tangled", "r2"] ``` Then sync everything: ```sh kalandra sync ``` Or just specific repositories: ```sh kalandra sync kalandra ``` ### Authentication - **Git**: Kalandra shells out to `git`, so pushes and fetches use your existing SSH keys and credential helpers. - **S3/R2**: credentials are read from the environment (`AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`) or any other source supported by the AWS SDK. ### Restoring from a backup Bundles are stored at `//-.bundle`, with `//latest.json` pointing at the most recent one. To restore: ```sh git clone repo.bundle restored-repo ``` ### Retention Each backup is a full, self-contained bundle, so old bundles can be expired freely. Use your bucket's lifecycle rules (e.g., R2 object lifecycle) to keep however much history you want.