Library / SDK
gokrazy/rsync avatar
gokrazy/rsync

gokrazy rsync: a Go rsync server that limits what it can reach

rsync in Go! implements client and server, which can send or receive files (upload, download, all directions supported)

876 stars71 forksGoBSD-3-Clause

At a glance

What is it?
gokrazy/rsync reimplements the rsync protocol in Go, shipping a client, a daemon and two reusable packages. Its differentiator is containment, through Go's os.Root file API and Linux Landlock, offset by a README that admits the implementation is less tested than the original.
Who is it for?
Adopt gokrazy rsync when you want an rsync daemon you can expose to the internet, because the Landlock and os.Root design makes a hostile client a far smaller risk than with a conventional rsync server. Do not adopt it as a drop-in replacement for a production mirror, because the project itself states it is not as well tested as the original tridge implementation and that it still has few users.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A second rsync implementation, aimed at servers that expose themselves

gokrazy/rsync is described in the README as an Rsync program and reusable library written in the Go programming language, originally part of the gokrazy Go appliance platform project. The project topics list the roles it covers: client, daemon, download, file-transfer, network, protocol, receiver, sender, server and upload. That spread is the point. This is not a library that only speaks the algorithm, it is a working client and a working server.

The repository ships a single Go module named github.com/gokrazy/rsync, and the go.mod file requires Go 1.25.0. Among the direct dependencies are github.com/mmcloughlin/md4 for the checksum function the protocol depends on, github.com/BurntSushi/toml for configuration, github.com/coreos/go-systemd for service integration, github.com/google/renameio/v2 for atomic file replacement, and the landlock-lsm/go-landlock package for the sandboxing work.

The audience is narrow and specific. People who want to run a public or private rsync server, in daemon mode or over SSH, anonymous or authorized, and who would rather have that server be a small Go binary with a modern containment story than a decades-old C daemon. The README also lists embedding as a first class use case, and the notable users section names NVIDIA/OSMA, a gokrazy appliance backup workflow, a demo of rsync file transfer over gRPC, and a RIPE 90 presentation on Go for rsync diversity.

Wire compatibility stops at protocol version 27

The README states that gokrazy/rsync is wire-compatible with the original tridge Rsync. The compatibility boundary is precise, because the project maintains a survey of other implementations and records the maximum protocol version each one handles.

The original C implementation from the Samba project, now at RsyncProject/rsync, reaches protocol 32. OpenBSD's kristapsdz/openrsync reaches 27, the same ceiling as this project. Several other Go implementations are listed as client or receiver only, with no server mode at all, including jbreiding/rsync-go, kaiakz/rsync-os, the knight42 proxy gist, and c4milo/gsync.

That gap of five protocol versions between 27 and 32 is the most concrete limitation in the whole repository, because it is the one place where a peer that speaks the newer protocol cannot be satisfied. A client and server that both speak 27 or lower will interoperate. A peer that needs 28 or above will not, and the README does not enumerate which features those later protocol versions add, so you cannot easily predict whether a given transfer hits the wall.

For most file synchronization the older ceiling is enough, since the basics are the ones that matter. For a mirror of a specific upstream that has adopted newer protocol features, verify before you rely on it.

os.Root and Landlock narrow what a hostile client can reach

The security story is the reason to look at this project, and it rests on two specific mechanisms rather than on general hardening advice.

The first is Go's traversal-resistant file API, os.Root, referenced in the README as a way to steer clear of vulnerabilities. The second is Linux Landlock Unprivileged Sandboxing, which confines the process through the kernel's unprivileged LSM. The project also supports mount namespaces in server settings, so the daemon can see a restricted view of the filesystem, and it can be locked down further with systemd's various hardening options.

The homepage link in the repository listing points to a write-up on minimal memory safe Go rsync vulnerabilities, which frames the project's motivation directly: a memory-safe language removes one class of memory corruption bugs, but an rsync server still parses attacker-controlled protocol data, so language choice alone is not the answer. Containment is the other half.

Two limits are worth keeping in view. Landlock is a Linux facility, so the containment story is Linux specific, and the repository layout shows both a systemd/ directory and a fsroot_windows.go file, which suggests a Windows build exists but with a different containment story. The README does not describe the Windows path in detail.

The Makefile is the install guide, and it comes with the maintainer's paths in it

There is no installation section in the README. The build path lives in the Makefile at the repository root, and the default target installs the command packages with CGO disabled:

bash
CGO_ENABLED=0 go install github.com/gokrazy/rsync/cmd/...

The cmd/ directory holds the binaries, and the README names two of them: gokr-rsync for the client and server, and gokr-rsyncd for the daemon. After the install, the binary lands in your Go bin directory, and a first local run is a single command, as the run target shows:

bash
sudo ~/go/bin/gokr-rsyncd -modulemap=default=/etc/default

The modulemap flag points the daemon at a directory tree of modules, in this case the system default configuration directory. The Makefile ships with absolute paths and private hostnames baked in, including /home/michael/go/bin for the systemd target and machine names such as router7.lan and gokrazy.lan for the router7 and raspi targets. Those are the maintainer's own deployment recipes, so treat them as templates rather than as instructions, and adjust the paths to your machine before running them.

The test target runs the whole suite without privileges:

bash
GOGC=off CGO_ENABLED=0 go test -fullpath ./...

The privileged-test target is the interesting one, since it exercises the interop and receiver suites under sudo, which is where a server-side implementation is most likely to meet a real client.

Container images and systemd units are the supported deployment shapes

Two deployment paths are visible in the Makefile and the repository layout. The first is a container image. The docker target builds the daemon with a pinned GOBIN and then builds the image:

bash
CGO_ENABLED=0 GOBIN=$$PWD/docker go install github.com/gokrazy/rsync/cmd/gokr-rsyncd

The image is tagged stapelberg/gokrazy-rsync, and a docker/ directory sits at the top of the repository, so the Dockerfile lives alongside it. A container is a natural fit for Landlock, since the sandbox and the container both narrow what the process can reach.

The second path is systemd, and the systemd/ directory holds two unit files, gokr-rsyncd.socket and gokr-rsyncd.service. The Makefile systemd target copies the daemon binary to /usr/bin/, copies both unit files into /etc/systemd/system/, reloads the daemon, and restarts the socket. The presence of a socket unit alongside the service unit indicates socket activation, so the daemon is started on demand by systemd rather than run permanently. The README's mention of systemd hardening options applies to these units.

Neither path is documented in prose in the README, so both are reconstructed from the build files. That is a fair summary of this project's documentation style overall: the automation is clear and the explanation is sparse.

rsynccmd and rsyncd turn the daemon into a library

The README presents embedding as one of the supported use cases, and the repository layout backs that up with two top-level packages. The rsynccmd package lets you embed rsync in your own program, and the rsyncd package lets you implement your own rsync server. There is also an rsyncclient/ directory at the root, alongside internal/ for the protocol internals, integration/ for the test suites, and testdata/ for fixtures.

This is the part of the project that is genuinely different from a rewritten command line tool. A Go program that needs to push or pull a directory can call into the library rather than shell out to rsync, and a service that wants to offer rsync as one of several transfer protocols can implement the server side on top of rsyncd with its own authentication and policy. The gRPC transfer demo linked from the README is an example of that kind of composition.

The catch is the same one that applies to the binaries. The README says plainly that this implementation "is not as well-tested as the original" and that the project "doesn't have many users yet", and contributions are merged as time permits on a best effort basis. A library you embed inherits that testing profile, so the surface you call should be the one you exercise yourself.

MD4 protects file contents, and nothing else

The README answers the question "How do I know this project won't eat my data?" with a layered argument, and the layering is the point.

The base layer is checksum integrity: the rsync protocol uses MD4 checksums over file contents, so on the README's reasoning, file contents should never be able to be corrupted by the transfer. Above that sits the honest caveat. The protocol carries a good deal of other functionality, including delta transfers, file metadata, special files such as symlinks or devices, and directory structures, and the README states plainly that this creates opportunities for bugs to hide. Content checksums do not cover a wrongly created symlink or a misapplied permission bit.

The advice that follows is also concrete: check that your transfers work, and report any issues you run into. The protocol version of 27 and the explicit statement that this implementation is less tested than the Samba original reinforce the same point, and the project asks users to report problems directly.

On maintenance, the record is active rather than quiet. The last push was on 2026-10-06, and the three most recent releases listed are v0.3.6 on 2026-08-07, v0.3.7 on 2026-09-07 and v0.3.8 on 2026-09-23. The version number shows this is still a pre-1.0 project, and the BSD-3-Clause licence keeps reuse terms simple. Neither point reduces the testing gap, but both mean the code is moving and the licence will not surprise you.

Editorial conclusion

Adopt gokrazy rsync when you want an rsync daemon you can expose to the internet, because the Landlock and os.Root design makes a hostile client a far smaller risk than with a conventional rsync server. Do not adopt it as a drop-in replacement for a production mirror, because the project itself states it is not as well tested as the original tridge implementation and that it still has few users. Before you commit, run the interop and receiver suites in the privileged-test target against your real client, and check whether your peer requires protocol features above version 27, which the original implementation supports and this one does not.

Frequently asked questions

Is gokrazy rsync compatible with the original rsync implementation?

The README states that gokrazy/rsync is wire-compatible with the original tridge Rsync. The survey in the README records a maximum protocol version of 27 for this project, against 32 for the original implementation, so peers needing a newer protocol will not interoperate.

How do I build gokrazy rsync from source?

The Makefile has a default target that installs the command packages with CGO disabled, and the module requires Go 1.25.0. The docker and systemd targets cover the container and service deployment shapes.

Does gokrazy rsync support server mode?

Yes. The gokr-rsyncd command runs the daemon, in daemon mode or over SSH, and the README describes setting up a public or private rsync server that is anonymous or authorized. You can also embed the server using the rsyncd package.

How does gokrazy rsync protect the server from malicious clients?

It uses Go's traversal-resistant file API os.Root together with Linux Landlock unprivileged sandboxing, and in server mode it supports mount namespaces and further lockdown through systemd hardening options. The README links to a post on minimal memory safe Go rsync vulnerabilities for the reasoning behind that design.

How mature is gokrazy rsync compared to the original?

The README states that this implementation is not as well-tested as the original tridge implementation from the Samba project, that it was started in 2021, and that it does not have many users yet. The last push was on 2026-10-06 and the most recent release listed is v0.3.8 from 2026-09-23.

Official sources

  1. gokrazy/rsync on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/gokrazy-rsync.svg)](https://hysenlabs.com/projects/gokrazy-rsync)

Was this useful?