{"id":13491695,"url":"https://github.com/zrepl/zrepl","last_synced_at":"2026-02-16T00:24:49.870Z","repository":{"id":37851848,"uuid":"88215084","full_name":"zrepl/zrepl","owner":"zrepl","description":"One-stop ZFS backup \u0026 replication solution","archived":false,"fork":false,"pushed_at":"2025-03-23T09:23:42.000Z","size":2490,"stargazers_count":1003,"open_issues_count":195,"forks_count":102,"subscribers_count":37,"default_branch":"master","last_synced_at":"2025-03-23T10:25:28.724Z","etag":null,"topics":["backup","bookmark","go","golang","incremental","replication","snapshot","zfs"],"latest_commit_sha":null,"homepage":"https://zrepl.github.io","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zrepl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"docs/supporters.rst","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"problame","patreon":"zrepl","liberapay":"zrepl","custom":"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=R5QSXJVYHGX96","ko_fi":"problame"}},"created_at":"2017-04-13T23:40:49.000Z","updated_at":"2025-03-23T09:23:45.000Z","dependencies_parsed_at":"2023-10-15T16:23:10.672Z","dependency_job_id":"f57ace61-4108-4662-a6af-2ad8c1211b32","html_url":"https://github.com/zrepl/zrepl","commit_stats":{"total_commits":1047,"total_committers":41,"mean_commits":"25.536585365853657","dds":"0.11556829035339067","last_synced_commit":"5e4d4188f4ca15a0743746a475d98fbc419fe266"},"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/zrepl/zrepl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrepl%2Fzrepl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrepl%2Fzrepl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrepl%2Fzrepl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrepl%2Fzrepl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zrepl","download_url":"https://codeload.github.com/zrepl/zrepl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zrepl%2Fzrepl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28440989,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:55:22.719Z","status":"ssl_error","status_checked_at":"2026-01-15T00:55:20.945Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["backup","bookmark","go","golang","incremental","replication","snapshot","zfs"],"created_at":"2024-07-31T19:00:59.444Z","updated_at":"2026-02-16T00:24:49.862Z","avatar_url":"https://github.com/zrepl.png","language":"Go","funding_links":["https://github.com/sponsors/problame","https://patreon.com/zrepl","https://liberapay.com/zrepl","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=R5QSXJVYHGX96","https://ko-fi.com/problame","https://img.shields.io/badge/dynamic/json?color=yellow\u0026label=Patreon\u0026query=data.attributes.patron_count\u0026url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F3095079","https://liberapay.com/zrepl/donate"],"categories":["Go","golang"],"sub_categories":[],"readme":"[![GitHub license](https://img.shields.io/github/license/zrepl/zrepl.svg)](https://github.com/zrepl/zrepl/blob/master/LICENSE)\n[![Language: Go](https://img.shields.io/badge/lang-Go-6ad7e5.svg)](https://golang.org/)\n[![User Docs](https://img.shields.io/badge/docs-web-blue.svg)](https://zrepl.github.io)\n[![Support me on Patreon](https://img.shields.io/badge/dynamic/json?color=yellow\u0026label=Patreon\u0026query=data.attributes.patron_count\u0026url=https%3A%2F%2Fwww.patreon.com%2Fapi%2Fcampaigns%2F3095079)](https://patreon.com/zrepl)\n[![Donate via GitHub Sponsors](https://img.shields.io/static/v1?label=Sponsor\u0026message=%E2%9D%A4\u0026logo=GitHub\u0026style=flat\u0026color=yellow)](https://github.com/sponsors/problame)\n[![Donate via Liberapay](https://img.shields.io/liberapay/patrons/zrepl.svg?logo=liberapay)](https://liberapay.com/zrepl/donate)\n[![Donate via PayPal](https://img.shields.io/badge/donate-paypal-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=R5QSXJVYHGX96)\n[![Twitter](https://img.shields.io/twitter/url/https/github.com/zrepl/zrepl.svg?style=social)](https://twitter.com/intent/tweet?text=Wow:\u0026url=https%3A%2F%2Fgithub.com%2Fzrepl%2Fzrepl)\n[![Chat](https://img.shields.io/badge/chat-matrix-blue.svg)](https://matrix.to/#/#zrepl:matrix.org)\n\n# zrepl\nzrepl is a one-stop ZFS backup \u0026 replication solution.\n\n## User Documentation\n\n**User Documentation** can be found at [zrepl.github.io](https://zrepl.github.io).\n\n## Bug Reports\n\n1. If the issue is reproducible, enable debug logging, reproduce and capture the log.\n2. Open an issue on GitHub, with logs pasted as GitHub gists / inline.\n\n## Feature Requests\n\n1. Does your feature request require default values / some kind of configuration?\n   If so, think of an expressive configuration example.\n2. Think of at least one use case that generalizes from your concrete application.\n3. Open an issue on GitHub with example conf \u0026 use case attached.\n4. **Optional**: [Contact Christian Schwarz](https://cschwarz.com) for contract work.\n\nThe above does not apply if you already implemented everything.\nCheck out the *Coding Workflow* section below for details.\n\n## Development\n\nzrepl is written in [Go](https://golang.org) and uses [Go modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.\nThe documentation is written in [ReStructured Text](http://docutils.sourceforge.net/rst.html) using the [Sphinx](https://www.sphinx-doc.org) framework.\n\n### Building\n\n#### Go Code\n\nDependencies:\n\n* Go\n* GNU Make\n* Git\n* wget (`make generate`)\n* unzip (`make generate`)\n\nSome Go code is **generated**, and generated code is committed to the source tree.\nTherefore, building does not require having code generation tools set up.\nWhen making changes that require code to be (re-)generated, run `make generate`.\nI downloads and installs pinned versions of the code generation tools into `./build/install`.\nThere is a CI check that ensures Git state is clean, i.e., code generation has been done by a PR and is deterministic.\n\n#### Docs\n\nInstall [uv](https://docs.astral.sh/uv/getting-started/installation/), then run `make docs`.\nuv automatically manages Python and dependencies.\n\n### Testing\n\nThe **test suite** is split into pure **Go tests** (`make test-go`) and **platform tests** that interact with ZFS and thus generally **require root privileges** (`sudo make test-platform`).\nPlatform tests run on their own pool with the name `zreplplatformtest`, which is created using the file vdev in `/tmp`.\n\nFor a full **code coverage** profile, run `make test-go COVER=1 \u0026\u0026 sudo make test-platform \u0026\u0026 make cover-merge`.\nAn HTML report can be generated using `make cover-html`.\n\n### Circle CI\n\nWe use CircleCI for automated build \u0026 test pre- and post-merge.\n\nThere are two workflows:\n\n* `ci` runs for every commit / branch / tag pushed to GitHub.\n  It is supposed to run very fast (\u003c5min and provides quick feedback to developers).\n  It runs formatting checks, lints and tests on the most important OSes / architectures.\n\n* `release` runs\n  * on manual triggers through the CircleCI API (in order to produce a release)\n  * periodically on `master`\n\nArtifacts are stored in CircleCI.\n\n### Releasing\n\nAll zrepl releases are git-tagged and then published as a GitHub Release.\nThere is a git tag for each zrepl release, usually `vMAJOR.MINOR.0`.\nWe don't move git tags once the release has been published.\n\nThe procedure to issue a release is as follows:\n\n* Prepare the release (as a PR to `master`):\n  * Finalize `docs/changelog.rst` for the release.\n  * Update the supporters list based on contributors for this release:\n    ```bash\n    claude --permission-mode default '/update-supporters v0.6.1..v0.7.0'\n    ```\n    Replace version tags with the appropriate range for your release.\n  * Merge the PR. Docs are auto-published to zrepl.github.io on merge.\n* Tag the release:\n  * Git tag the release on the `master` branch (e.g., `vMAJOR.MINOR.0`).\n    ```\n    make tag-release ZREPL_TAG_VERSION=v0.7.0\n    ```\n  * Push the tag.\n* Build and publish:\n  * Run the `release` pipeline against the `master` branch (trigger via CircleCI UI).\n    This URL: https://app.circleci.com/pipelines/github/zrepl/zrepl?branch=master.\n    Example pipeline: https://app.circleci.com/pipelines/github/zrepl/zrepl/8547\n  * Download artifacts using this handy makefile target.\n    Note: `JOB_NUM` must be the **job number** from the `release-upload` job, **not the pipeline number**.\n    Find it via: pipeline → `release` workflow → `release-upload` job number.\n    Example URL: https://app.circleci.com/pipelines/github/zrepl/zrepl/8547/workflows/65feb2c9-15d7-46ab-a551-46d62a5769b0/jobs/66079/steps\n\n    ```\n    make download-circleci-release JOB_NUM=66079\n    ```\n  * Verify checksums and sign the checksums file:\n    ```\n    make verify-and-sign\n    ```\n  * Create GitHub draft release and upload artifacts:\n    ```bash\n    claude --permission-mode default '/draft-release v0.7.0'\n    ```\n    This command will verify that artifacts are ready, create the draft release, and upload all artifacts.\n  * Review the draft release on GitHub, then publish,\n    with the box checked to create a GitHub \"Discussion\" for the release.\n* Immediately after hitting publish.\n  * Update the release on GitHub to link to the discussion.\n  * Update `docs/changelog.rst` to link to the GitHub release.\n  * Update `docs/_templates/versions.html` to link to the GitHub release.\n  * Announce release in the zrepl Matrix channel \u0026 other socials as applicable.\n    Link to the GitHub release as the entrypoint.\n* After a couple of days\n  * Add the .rpm and .deb files to the official zrepl repos.\n    * Code for management of these repos: https://github.com/zrepl/package-repo-ops (private repo at this time)\n\n#### Patch releases, Go toolchain updates, APT/RPM Package rebuilds\n\n`vMAJOR.MINOR.0` is typically a tagged commit on `master`, because development velocity isn't high\nand thus release branches for stabilization aren't necessary.\n\nOccasionally though there is a need for patch changes to a release, e.g.\n- security issue in a dependency\n- Go toolchain update (e.g. security issue in standard library)\n\nThe procedure for this is the following\n- create a branch off the release tag we need to patch, named `releases/MAJOR.MINOR.X`\n- that branch will never be merged into `master`, it'll be a dead-end for this specific patch\n- make changes in that branch\n- make the final commit that bumps version numbers\n- create the git tag\n- follow general procedure for publishing the release (previous sectino\n\nFor Go toolchain updates and package rebuilds with no source code changes, leverage the APT/RPM package revision field.\nControl via the `ZREPL_PACKAGE_RELEASE` Makefile variable, see `origin/releases/0.6.1-2` for an example.\n\n\n### Updating Dependencies\n\n- Update the `go` directive and `toolchain` directive in `go.mod`\n  - `go` is the minimum supported version\n  - `toolchain` is the preferred toolchain version if `GOTOOLCHAIN` is not specified\n\nRun `go mod tidy` to ensure consistency.\n\nUpdate Go module dependencies:\n\n```bash\n# Update all other dependencies\ngo get -u -t ./...\ngo mod tidy\n\n# Above might fail if there are version selection conflicts.\n# Figure out what's going on by updating packages from error messages first.\n# Example:\ngo get -u google.golang.org/genproto google.golang.org/grpc google.golang.org/protobuf\n```\n\nUpdate codegen \u0026 lint tools\n- `protoc` =\u003e  `build/get_protoc.bash`\n  - GH releases publish sha256 sums\n- `golangci-lint` =\u003e `build/get_golangci_lint.bash`\n- bump versions in `build/tools.go`\n  - we use the tools.go trick:\n  - `go get -tags tools -u example.com/tool ; go mod tidy`\n  - review whether we're ready to switch to `go tool`: https://github.com/zrepl/zrepl/pull/909\n\nNow run `make generate`.\n\nRun `make lint` and `make vet`.\n\nUpdate the CI configuration `.circleci/config.yml`:\n- Update Go version references (we reference the minimum and max supported version)\n- Set `Makefile` `RELEASE_GOVERSION` to the new Go version\n- Update the pinned ZFS release tags in the `platformtest` matrix (`zfs_release` parameter) to the latest patch releases of each OpenZFS branch (currently 2.2, 2.3, 2.4)\n- Update the pinned Ubuntu machine image for `platformtest` (e.g. `ubuntu-2404:2025.09.1`) — this is pinned rather than `current` so the ZFS build cache stays valid across runs\n\nUpdate docs build tooling:\n- Update `uv` version in `.circleci/config.yml` (search for `astral.sh/uv/` and cache keys containing the version)\n- Check if there's now a CircleCI orb for uv that we could use\n- Update Python version in `docs/.python-version`\n\nUpdate docs dependencies (Sphinx, sphinx-rtd-theme):\n- Check current versions in `docs/pyproject.toml`\n- Review upstream changelogs for breaking changes\n- Update version constraints in `pyproject.toml` and the `uv` lockfile (see [uv docs on dependencies](https://docs.astral.sh/uv/concepts/projects/dependencies/)):\n- Test locally with `make docs`\n\nKick a full CI pipeline run (`do_ci=true` and `do_release=true`).\n\nMerge PR with merge commit.\n\n## Notes to Distro Package Maintainers\n\n* The `Makefile` in this project is not suitable for builds in distros.\n* Run the platform tests (Docs -\u003e Usage -\u003e Platform Tests) **on a test system** to validate that zrepl's abstractions on top of ZFS work with the system ZFS.\n* Ship a default config that adheres to your distro's `hier` and logging system.\n* Ship a service manager file and _please_ try to upstream it to this repository.\n  * `dist/systemd` contains a Systemd unit template.\n* Ship other material provided in `./dist`, e.g. in `/usr/share/zrepl/`.\n* Have a look at the `Makefile`'s `ZREPL_VERSION` variable and how it passed to Go's `ldFlags`.\n  This is how `zrepl version` knows what version number to show.\n  Your build system should set the `ldFlags` flags appropriately and add a prefix or suffix that indicates that the given zrepl binary is a distro build, not an official one.\n* Make sure you are informed about new zrepl versions, e.g. by subscribing to GitHub's release RSS feed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzrepl%2Fzrepl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzrepl%2Fzrepl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzrepl%2Fzrepl/lists"}