portier-broker is the Rust reference implementation of a self-hosted auth broker
Portier Broker reference implementation, written in Rust
At a glance
- What is it?
- Portier is specified so that anyone can run their own broker, and this repository is that broker in Rust, with a configuration file, a container image that runs unprivileged on port 3333 and a set of Cargo features that pick the TLS stack and the mail transports. The one thing the README is emphatic about is that the broker itself speaks plain HTTP, so a reverse proxy is part of the deployment.
- Who is it for?
- Adopt portier-broker when your applications need a Portier broker you operate yourself, and when you are prepared to put a reverse proxy in front of it. Do not deploy it as it ships, because it talks plain HTTP only, and do not expect the README to be a full operator guide, since the detail lives in the example configuration file and the docs directory.
- Can I use it commercially?
- Yes. Apache-2.0 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 last received commits 4 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A reference implementation of a protocol meant to be self-hosted
The repository states its purpose in one line, this is the Portier Broker reference implementation, and the README links the project on GitHub, the main Portier website and the Portier specification.
The reason a reference implementation exists in Rust is that Portier is specified such that everyone can run their own broker instance. You can point your Relying Parties at your own broker, so that you do not have to depend on the broker run by the Portier project. That is the design goal, and the implementation is deliberately one of several rather than the only one.
The package metadata gives the technical baseline. The package is `portier_broker`, the version is 0.15.1, the description is reference implementation of the Portier broker protocol, the licence is `MIT/Apache-2.0` with both `LICENSE-MIT` and `LICENSE-APACHE` in the repository root, the minimum Rust version is 1.89 and the edition is 2024. The binary is `portier-broker`, built from `src/main.rs`.
The release tags are v0.15.1 from 2026-03-11, v0.15.0 from 2026-03-06 and v0.14.0 from 2025-08-20, and the last push was on 2026-10-19, so the repository is still being worked on even though the tags move less often than the commits.
Binaries, images, or build it yourself
There are three routes to a running broker, and the README lists all three.
Binaries for the broker can be found on the GitHub releases page, and Docker images are available on Docker Hub. Alternatively you can build the broker yourself, with the instructions in `docs/build.md`.
That third route is the one that matters for a self-hosted deployment, because the build is reproducible by design. The release profile in the manifest sets `overflow-checks = true`, which is the kind of setting a project turns on when it would rather panic in development than silently wrap an arithmetic overflow in production, and the Dockerfile builds with `--release --locked` so the dependency versions come from the committed lock file.
The build is also shaped for caching. The Dockerfile build stage uses a Rust Alpine image, adds the build toolchain, copies the source and mounts caches for the Cargo registry and for the target directory, with the target cache shared and locked so parallel builds do not corrupt each other.
For an organisation with a normal release process, the locked build is the reproducible one, and the release binaries and the container image are the convenient ones.
Configuration by file or by environment
The broker can be configured using a configuration file or through environment variables, and the README says both are documented in the example configuration file, `config.toml.dist`.
Once you have prepared the configuration, you run the executable:
# From binaries:
./portier-broker[.exe] ./config.toml
# Using Docker:
docker run -v /srv/portier-broker:/data:ro portier/broker /data/config.tomlThe `.exe` suffix in the first line covers Windows, and the second line mounts the configuration directory read only into the container, which is the right way to give a container a configuration file it should not be able to write.
There is one interaction between the two configuration styles that is easy to get wrong. If you are using environment variables only, don't specify a configuration file on the command line. The Docker image sets `BROKER_LISTEN_IP` as an environment variable, so the environment path is the normal one in a container deployment, and passing a config file as well is the case the README warns against.
Systemd units are also included with the Linux binaries, which is the other thing that makes a hand rolled deployment viable rather than a demo.
The broker speaks plain HTTP, so a proxy is part of the plan
This is the single most important operational line in the README, and it is worth reading as a requirement rather than a note. The broker only talks plain HTTP, and not HTTPS. Using HTTPS is strongly recommended, but you'll need to add a reverse proxy in front of the broker to do this, and the README points at Apache or Nginx as the tools that can do it for you.
The reason a broker needs this is structural. A broker sits in front of your applications and handles the authentication flow, which means it handles the one part of a login where credentials and tokens are in play. A broker that terminates its own TLS is one that needs certificates, a renewal story and a key management story, and a reference implementation that lets you choose the proxy is the sensible way to keep that out of the project's scope.
The trade is that the deployment is now two components. You are running the broker and a proxy, and the configuration of the proxy, its certificate, its timeouts and its forwarding rules become part of your security surface. Teams that expected a single binary to put behind their load balancer are the ones that get caught by this.
If you deploy the container as the Dockerfile builds it, the image exposes port 3333 and sets the listen address to `::`, so the proxy in front of it has something concrete to target.
Cargo features pick the TLS stack and the mail transports
The feature list in the manifest is the configuration surface of the build, and it is worth reading as a whole:
[features]
default = ["rustls", "redis", "rusqlite", "lettre_smtp", "lettre_sendmail", "postmark", "mailgun", "sendgrid"]
insecure = []
lettre_smtp = ["lettre", "lettre/smtp-transport"]
lettre_sendmail = ["lettre", "lettre/sendmail-transport"]
postmark = []
mailgun = []
native-tls = ["reqwest/native-tls", "lettre?/native-tls"]
rustls = ["dep:rustls", "reqwest/rustls", "lettre?/rustls", "lettre?/rustls-platform-verifier", "lettre?/aws-lc-rs"]
sendgrid = []The default build is the `rustls` TLS stack, with Redis and SQLite support, and with several mail transports compiled in, the lettre SMTP and sendmail transports, Postmark, Mailgun and SendGrid. The `native-tls` feature switches the HTTP client and the mailer to the platform TLS stack, and `insecure` is an explicit opt-in flag that is off by default.
The other dependencies describe the shape of the service. `hyper` with the `http1` and `server` features is the HTTP server, `docopt` handles the command line, `mustache` renders the templates in the `tmpl/` directory, `gettext` handles the translations in `lang/`, `ipnetwork` handles address and network matching, `toml` and `serde_json` handle the two configuration shapes, and `listenfd` lets the broker inherit a listening socket from a supervisor.
Compiling every mail provider into the default build is a choice with a cost in image size, and the feature flags are there to let you cut it back down.
The container runs as a fixed user on port 3333
The Dockerfile is worth reading for two reasons, the port and the privilege model.
The image is built in four stages. The first compiles the broker in release mode on `rust:1-alpine` with the build toolchain installed and the Cargo caches mounted. The second prepares the data files, copying the `lang`, `res` and `tmpl` directories, with a build argument that lets you replace them with a downloaded archive instead, and the comment in the file explains why that is useful, since only the last stage matters for the output image. The third prepares a base Alpine system, and it is the one with the security decisions:
RUN set -x \
&& addgroup -S -g 2000 portier-broker \
&& adduser -S -G portier-broker -u 2000 portier-broker
# Set image settings.
WORKDIR /opt/portier-broker
ENTRYPOINT ["/opt/portier-broker/portier-broker"]
USER portier-broker
ENV BROKER_LISTEN_IP=::
EXPOSE 3333The group and the user are created with fixed identifiers, 2000 for both, and the comment explains the reason, that adding the user and group first makes sure their IDs get assigned consistently regardless of whatever dependencies get added later. Then the image sets the working directory, the entrypoint, drops to that unprivileged user, sets the listen address and exposes port 3333.
That is a good template for a broker image, and it also tells you what to expect in your own deployment, since the container is designed to run as a non-root user with a predictable port and a listen address you can override through the environment.
Editorial conclusion
Adopt portier-broker when your applications need a Portier broker you operate yourself, and when you are prepared to put a reverse proxy in front of it. Do not deploy it as it ships, because it talks plain HTTP only, and do not expect the README to be a full operator guide, since the detail lives in the example configuration file and the docs directory. Verify first that the Cargo features you enable match the TLS and mail providers you use, that your reverse proxy terminates TLS and forwards to the broker, that the container's listen address and exposed port match your deployment, and that the version you run matches the release you read, with v0.15.1 from 2026-03-11 the most recent tag.
Frequently asked questions
What is the Portier broker used for?
Portier is an authentication broker that applications, called Relying Parties, point at. The broker is specified so that everyone can run their own broker instance, which means your applications do not have to depend on the broker run by the Portier project. This repository is the Rust reference implementation.
How do I run the portier-broker?
The broker takes a configuration file or environment variables, both documented in config.toml.dist, and you run the executable with the file, for example `./portier-broker ./config.toml`, or `docker run -v /srv/portier-broker:/data:ro portier/broker /data/config.toml`. If you configure the broker entirely through environment variables, the README says not to pass a configuration file on the command line. Systemd units are included with the Linux binaries.
Does the portier-broker support HTTPS?
No. The broker only talks plain HTTP, and the README says using HTTPS is strongly recommended but requires a reverse proxy in front of the broker, with Apache or Nginx named as the tools that can do this.
Which TLS and mail options does the portier-broker support?
The default Cargo features include rustls, redis, rusqlite, the lettre SMTP and sendmail transports, Postmark, Mailgun and SendGrid. There is a native-tls feature for the platform TLS stack, and the rustls feature pulls in the rustls platform verifier and aws-lc-rs.
Official sources
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.
[](https://hysenlabs.com/projects/portier-portier-broker)Was this useful?