# Sōzu: a Rust reverse proxy you reconfigure over a unix socket

> Sōzu is an AGPL-3.0 HTTP reverse proxy written in Rust that takes configuration changes at runtime through a unix command socket and upgrades itself without dropping requests. It suits operators who need TLS termination and live reconfiguration; it is a poor fit for anyone wanting a drop-in nginx replacement.

**sozu-proxy/sozu** — Sōzu HTTP reverse proxy, configurable at runtime, fast and safe, built in Rust. It is awesome!

- Repository: https://github.com/sozu-proxy/sozu
- Website: https://www.sozu.io/
- Stars: 3,734 · Forks: 216
- Language: Rust
- License: AGPL-3.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/sozu-proxy-sozu

## The problem Sōzu targets: changing a proxy without restarting it

Most reverse proxies treat configuration as something you write to a file and then load. Changing a route means editing the file and triggering a reload, and a reload means either a brief gap in service or a graceful-drain dance you have to build yourself. Sōzu takes the opposite position. The README describes it as "a lightweight, fast, always-up reverse proxy server", and the always-up part is the design centre: configuration arrives at runtime over secure unix sockets, and the proxy applies it without reloading. The same idea extends to the binary itself. The README states that Sōzu upgrades itself while still processing requests, which is a different operational model from restarting a process behind a load balancer and hoping the connection draining works.

The audience follows from that. This is a tool for platform and infrastructure teams who already have automation that can speak to a socket, and who would rather push a route change than redeploy an edge tier. It is also aimed at teams that want TLS terminated at the proxy so backend servers do not carry certificate handling. If your workflow is a checked-in config file plus a systemd reload, Sōzu asks you to build something new instead of reusing what you have. That is the trade, and it is a real one.

## How the master, workers and the command socket fit together

The Cargo workspace splits the project into crates with distinct jobs, and the split explains the runtime model. The `lib/` crate, `sozu-lib`, holds the proxy itself: a single-threaded mio event loop, the HTTP/1.1 parser (Kawa) and an HTTP/2 multiplexer, TCP, UDP and TLS protocol handling, routing, per-IP rate limiting, sockets, metrics and a buffer pool. The `bin/` crate wraps that library in a master/worker supervisor, exposes the unix command socket, and orchestrates hot reconfiguration and zero-downtime upgrades. The `command/` crate, `sozu-command-lib`, carries the protobuf IPC schema, the configuration parser and the replicated state.

So the data flow has two planes. Requests go through workers running the event loop in `sozu-lib`. Configuration and control go through the command socket into the master, which decides what workers should be running and coordinates the transition. Because the IPC schema is protobuf and lives in a published crate, an external controller can be written against it rather than shelling out to a CLI. The README also notes workers are sandboxed, so an exploited worker is contained rather than owning the machine. Two dependencies are called out as deliberately optimised: Kawa parses and translates HTTP messages with zero copy, and Rustls encrypts and decrypts with as little intermediate memory as possible. Those are the mechanisms behind the performance claim, and they are specific enough to be checkable in the source.

## Installing Sōzu from a signed tarball

Prebuilt Linux binaries are attached to every tagged release, and the README says the ten tarballs cover a cross-product of target and crypto provider. The published targets are `x86_64-unknown-linux-gnu`, `x86_64-unknown-linux-musl` and `aarch64-unknown-linux-gnu`; `aarch64-unknown-linux-musl` builds from source but is not in the prebuilt matrix, because the README says `jemalloc-sys 0.5.4`'s cross-compile probe cannot link its atomics tests against the `musl-tools` wrapper on the arm64 runner. Tarball names follow `sozu-<VERSION>-<TARGET>-<PROVIDER>.tar.gz`. The default for operators without a compliance constraint is `crypto-ring` on `linux-gnu`.

Each release also carries `SHA256SUMS`, a sigstore keyless signature pair (`SHA256SUMS.sig` plus `SHA256SUMS.pem`) and SLSA build-provenance attestations. The README's verification sequence requires cosign 2.4.1 or later, and it pins the expected certificate identity to the release workflow rather than accepting any signature:

```bash
TARGET=x86_64-unknown-linux-gnu
PROVIDER=crypto-ring

curl -LO https://github.com/sozu-proxy/sozu/releases/download/<VERSION>/sozu-<VERSION>-${TARGET}-${PROVIDER}.tar.gz
curl -LO https://github.com/sozu-proxy/sozu/releases/download/<VERSION>/SHA256SUMS
curl -LO https://github.com/sozu-proxy/sozu/releases/download/<VERSION>/SHA256SUMS.sig
curl -LO https://github.com/sozu-proxy/sozu/releases/download/<VERSION>/SHA256SUMS.pem

cosign verify-blob \
  --certificate SHA256SUMS.pem \
  --signature SHA256SUMS.sig \
  --certificate-identity-regexp '^https://github\\.com/sozu-proxy/sozu/\\.github/workflows/release\\.yml@refs/tags/[0-9]+\\.[0-9]+\\.[0-9]+(-rc\\.[0-9]+)?$' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-github-workflow-repository sozu-proxy/sozu \
  --certificate-github-workflow-ref refs/tags/<VERSION> \
  SHA256SUMS
```

After the signature check, the README verifies the tarball against the signed sums and unpacks it. A successful run prints the `SHA256SUMS` line for the file you fetched, then extracts the archive.

```bash
sha256sum -c SHA256SUMS --ignore-missing
tar -xzf sozu-<VERSION>-${TARGET}-${PROVIDER}.tar.gz
```

Build provenance can be inspected separately with `gh attestation verify sozu-<VERSION>-<TARGET>-<PROVIDER>.tar.gz --owner sozu-proxy`. Pre-release tags of the form `X.Y.Z-rc.N` are published as GitHub pre-releases, so a tag matching that pattern is not a stable release.

## Building from source and starting the proxy

A source build needs `protoc` and a Rust toolchain pinned via the `rust-toolchain` file, which the README identifies as Rust 1.91. The workspace manifest lists five members (`lib`, `command`, `bin`, `e2e`, `sim`) and sets edition 2024 with MSRV 1.91. Once prerequisites are in place, the README gives a two-command quickstart:

```bash
cargo build -p sozu --release --locked
target/release/sozu start -c bin/config.toml
```

The `bin/config.toml` file is the in-tree sample config. The README says to copy it next to your TLS certificates and edit the listener and cluster blocks before going to production. That instruction matters more than it looks: the sample is a starting point, not a production profile, and the configuration reference lives in `doc/configure.md`. There is also a live operator dashboard behind a cargo feature:

```bash
cargo build -p sozu --release --locked --features tui
target/release/sozu top
```

The README describes `sozu top` as a btop/htop-style dashboard over the existing command socket, with sparklines, sortable cluster and backend tables, H2 flood-mitigation counters and a colour-coded event tail in one screen. Its documentation is in `doc/sozu-top.md`. The dashboard is worth noting for a different reason: it is a client of the same command socket your automation would use, so it doubles as a working reference for what that socket exposes.

## Docker images are not byte-equivalent to the signed tarballs

The Docker path looks simpler and carries a caveat the README states plainly. Images are published to Docker Hub as `clevercloud/sozu:<VERSION>` and `clevercloud/sozu:latest`, with stable tags only for `latest`. The image is built from source by the same release workflow, but inside an Alpine builder stage that uses the distro's `cargo` and `rust` packages rather than the `dtolnay/rust-toolchain@1.93.1` pin used for the Linux tarballs. The image therefore links musl libc and is not byte-equivalent to either the `gnu` or `musl` tarball covered by the cosign-signed `SHA256SUMS`. SLSA build provenance currently covers the tarballs only, and the README notes a from-tarball Docker image is tracked as a follow-up.

If your compliance story depends on the attested binary, that is the deciding detail: extract `sozu-<VERSION>-x86_64-unknown-linux-musl.tar.gz` and run `sozu` directly instead of using the image. The repository's own Dockerfile confirms the shape of the image build. It builds with `--no-default-features --features jemallocator,${CRYPTO_PROVIDER}`, defaults `CRYPTO_PROVIDER` to `crypto-ring`, declares `EXPOSE 80` and `EXPOSE 443`, marks `/etc/sozu` and `/run/sozu` as volumes, and sets the entrypoint to `sozu` with `CMD ["start", "-c", "/etc/sozu/config.toml"]`. The config baked into the image comes from `os-build/config.toml`, not from `bin/config.toml`, so the two paths do not ship the same sample.

## Where Sōzu is the wrong tool

The clearest limitation is the licence. Sōzu is AGPL-3.0. If you embed it in a product you distribute, or run a modified version as a network service, the copyleft terms reach further than a permissive proxy licence would. That is a legal question for your own counsel, not something this article can settle, but the licence is a genuine adoption gate rather than a footnote.

The second limitation is the configuration model itself. There is no documented declarative reload path in the README: the documented interface for runtime change is the unix command socket, and the configuration file is read at start. Teams whose deployment tooling writes a file and sends SIGHUP have to build a socket client instead. The README does not document rollback, so it is not clear how you would revert a bad runtime change, or whether the replicated state in `sozu-command-lib` keeps a previous generation you can return to. Treat that as unverified until you read the command crate.

The third is the build matrix. `aarch64-unknown-linux-musl` is supported from source but excluded from prebuilt binaries for a specific dependency reason, so ARM64 Alpine users are compiling. The `fips` provider is gnu-only and the README states there is no SLA for it per project policy, which is an unusual thing to publish and worth reading before anyone plans a FIPS deployment around it. Finally, this is a proxy, not a service mesh or an ingress controller. It has no Kubernetes integration in the documentation reviewed, and nothing suggests it manages certificates for you.

## How Sōzu differs from nginx and Envoy

The comparison that matters is with nginx. nginx reads a configuration file and applies it on reload; the reload is a well-understood operation, and the ecosystem around templating and validating those files is enormous. Sōzu inverts the direction: state lives in the running process and changes arrive over a socket. You gain the ability to change routing without a reload and to upgrade the binary in place. You lose the ability to diff a config file in a pull request, and you take on writing the client that pushes changes. Neither model is strictly better; they fail in different ways. A bad nginx config fails at reload and you keep the old one. A bad socket command has no documented rollback in the README, which is the sharper edge.

Envoy is the closer architectural relative, since it also exposes a dynamic configuration API and is designed to be driven by a control plane. The difference in approach is scope and language. Envoy's dynamic API is a documented, versioned xDS protocol with a large ecosystem of control planes; Sōzu's control surface is a protobuf IPC schema in `sozu-command-lib` over a unix socket, and the README points at `doc/sozu-top.md` and `doc/configure.md` rather than at a specification for external implementers. If you want an off-the-shelf control plane, Envoy has one. If you want a smaller Rust proxy whose internals you can read in an afternoon and whose control socket you drive yourself, Sōzu is the more direct fit. The crypto backends are a third axis: ring by default, AWS-LC with post-quantum and FIPS 140-3 options, and OpenSSL, all selected at compile time. That choice is made when you build, not when you run.

## Conclusion

Adopt Sōzu if you terminate TLS at the edge, change routing often, and can drive a unix command socket from your own tooling; the prebuilt tarballs and the AGPL-3.0 licence are the two things to settle before you commit. Do not adopt it if you need a declarative config file plus a reload signal, or if AGPL-3.0 is incompatible with how you ship. Verify first that your Rust toolchain matches the pinned rust-toolchain file, that protoc is installed for a source build, and that you can reproduce the cosign verification of SHA256SUMS on the tarball you download.

## FAQ

### How do I implement a reverse proxy in Rust, and where does Sōzu fit?

Sōzu is an existing implementation rather than a tutorial: the `lib/` crate, `sozu-lib`, contains the mio event loop, HTTP/1.1 and HTTP/2 handling, TLS, routing and per-IP rate limiting, and the `bin/` crate wraps it in a master/worker supervisor. If you want to write your own, reading `lib/` is a reasonable starting point; if you want to run one, install a release tarball or build the `sozu` binary.

### Does Sōzu need a restart to apply configuration changes?

No. The README states that Sōzu receives configuration changes at runtime through secure unix sockets without having to reload, and that it upgrades itself while still processing requests. The documented interface for those changes is the command socket, not a config file reload.

### Which TLS backends can Sōzu use?

The README lists three cryptographic backends selected at compile time: ring (the default), AWS-LC (with post-quantum and FIPS 140-3 options) and OpenSSL. In the prebuilt matrix, `crypto-ring` and `crypto-aws-lc-rs` cover all three published targets, while `crypto-openssl` and `fips` are gnu targets only.

### Is the Sōzu Docker image the same binary as the release tarball?

No. The README states that `clevercloud/sozu:<VERSION>` is built inside an Alpine builder stage using the distro's cargo and rust packages rather than the toolchain pin used for the tarballs, so it links musl libc and is not byte-equivalent to either tarball. SLSA build provenance currently covers the tarballs only.

### What is the Sōzu licence and what does it mean for adoption?

Sōzu is licensed AGPL-3.0. That is a copyleft licence whose network-use terms go beyond permissive licences, so whether it fits your distribution or hosted-service model is a question for your own legal review rather than something the README answers.

## Sources

- [License: AGPL-3.0](https://github.com/sozu-proxy/sozu/blob/main/LICENSE)
- [Project website](https://www.sozu.io/)
- [README](https://github.com/sozu-proxy/sozu/blob/main/README.md)
- [Releases](https://github.com/sozu-proxy/sozu/releases)
- [sozu-proxy/sozu on GitHub](https://github.com/sozu-proxy/sozu)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sozu-proxy-sozu
