# Routinator validates RPKI data and hands it to routers over RTR

> NLnetLabs/routinator is a BSD-3-Clause Rust implementation of an RPKI relying party, a service that periodically downloads and verifies the signed repository data, then serves the result over an HTTPS API and over the RPKI to Router protocol, either from its own RTR server or through the separate RTRTR proxy. It installs from distribution packages, Docker or Cargo, and it is the reference implementation many routers are tested against.

**NLnetLabs/routinator** — An RPKI Validator and RTR server written in Rust

- Repository: https://github.com/NLnetLabs/routinator
- Website: https://nlnetlabs.nl/projects/routing/routinator/
- Stars: 576 · Forks: 90
- Language: Rust
- License: BSD-3-Clause
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/nlnetlabs-routinator

## A relying party is the part that checks the signatures

Routinator 3000 is described as free, open-source RPKI Relying Party software, and the project is written in Rust, a programming language designed for performance and memory safety. The role it plays is specific. RPKI is the system where route origin authorities certify which networks are entitled to originate which prefixes, and the data describing those authorisations is cryptographically signed. A relying party fetches that data, verifies the signatures and the chain of trust from the trust anchors down, and produces a statement for each prefix about whether it is authorised. The statement is a list of route origin authorisations, a validation cache that routers consult, and Routinator is the program that produces it. The project description in the repository is short, an RPKI relying party software, and the topics list gives the full vocabulary, including the five regional internet registries, route origin authorisation, trust anchor locator, the router protocol and the protocol used to fetch the data.

## A service that downloads, verifies, and serves

The mechanism is a periodic cycle rather than a query, and the README describes it as running as a service that periodically downloads and verifies RPKI data. That design has a consequence for operations, because the validator is the source of truth for every router that queries it, so the cycle has to be frequent enough to be useful and the resulting cache has to be available without a network round trip per lookup. On the serving side, the built-in HTTPS server offers a user interface, API endpoints for various file formats, as well as logging, status and Prometheus metrics. The metrics are worth singling out, because a validator that has silently stopped refreshing is a validator whose routers are still trusting stale data, and exposing the state of the refresh cycle is what lets an operator notice. The API endpoints for various file formats let the same validator feed tools that are not routers at all.

## RTR ships in two arrangements

The support for RPKI-to-Router is described as flexible, and there are two ways to use it. The first is the built-in RTR server, which lets routers fetch verified RPKI data directly from the validator. The second is to run RTR as a separate daemon using the RPKI data proxy RTRTR, which lets you centralise validation and securely distribute processed data to various locations. The distinction is a topology decision rather than a feature decision. With the built-in server, every router talks to the validator, which means the validator has to be reachable and the routers have to trust it directly. With the proxy, validation happens in one place and the distribution of the processed data is a separate concern, which is the arrangement for an operator with several sites and a need to keep the data path separate from the validation path. The README presents the proxy route as the way to centralise validation and securely distribute processed data to various locations, and it is a separate project from NLnet Labs, so it has its own release cadence.

## Packages, Docker or Cargo, and one documentation site

The getting started section is short because the packaging options are conventional. You install a binary package for either Debian and Ubuntu, or for Red Hat Enterprise Linux and compatible systems such as Rocky Linux. Alternatively you can run with Docker, or build from the source code using Cargo, which the README calls Rust's build system and package manager. The Docker route is not an afterthought, since the image is maintained with a pull count badge in the README alongside the crates.io version badge and the CI and packaging badges. The documentation is hosted on readthedocs, with a stable version, and the README points there rather than repeating configuration details, which is the right call for a project with this many options. The community support is a forum on Discourse and a Discord channel, and the project also offers professional support and consultancy services with a service level agreement from NLnet Labs, which is unusual for infrastructure software and is worth knowing about if you need a support contract rather than a mailing list.

## The dependency list describes the architecture

The manifest is a good map of what the program does, and the versions show a modern Rust project:

```toml
[package]
name = "routinator"
version = "0.15.3-dev"
edition = "2021"
rust-version = "1.86"
resolver = "3"
authors = ["NLnet Labs <rpki-team@nlnetlabs.nl>"]
description = "An RPKI relying party software."
license = "BSD-3-Clause"
```

Two dependencies carry most of the weight. The rpki crate at 0.19.3, with the repository, rrdp, rtr, serde and slurm features enabled, is the protocol library that does the fetching, the verification and the RPKI to Router encoding, so Routinator is the service and the cache around it. The second is the async runtime, tokio, with the io-util, macros, process, rt, rt-multi-thread, signal and sync features, plus hyper and hyper-util for the HTTP server and reqwest with the blocking, rustls-tls and gzip features for the outgoing connections. Rustls rather than the platform TLS stack is a choice worth noting, since it removes the OpenSSL dependency from the runtime, and the cryptography is handled by ring. The rest of the list is ordinary service plumbing, clap for the command line, serde and serde_json for output, chrono for timestamps, siphasher for hashing, tempfile for working files, listenfd for systemd socket activation and crossbeam-queue and arc-swap for the shared state between the refresh task and the serving tasks.

## The container image is a four stage build with a mode switch

The Dockerfile documents its own design in comments, which makes it a useful read. It is a multi-stage Dockerfile with a selectable first stage, and the reasoning is spelled out. The first benefit is separation of dependencies needed to build the app in the build stage and those needed to run the app in the final stage, so the build-time dependencies are not included in the final Docker image. The second is support for either building the app for the architecture of the base image using MODE=build, which is the default, or for externally built app binaries, for example cross-compiled ones, using MODE=copy. In total there are four stages, two possible first stages named build or copy, a special source stage which selects either build or copy as the source of binaries, and the final stage. The mode is passed as a build argument, with the values build as the default and copy, and the base image for the build path is alpine:3.23. For a deployment that cross-compiles elsewhere, the copy mode is the one that saves you from shipping a toolchain inside the image.

## Where Routinator is the wrong tool

Two cases stand out. The first is a network where the routers cannot speak RPKI to Router, because in that case the validator is running and answering queries nobody asks, and the filtering still has to be done by hand. The second is a requirement for policy beyond origin authorisation, since the data Routinator distributes says who is allowed to originate a prefix, and any decision about what to do with a prefix that is not authorised, or not covered by any authorisation, belongs to the router configuration. There is also an operational consequence that the README does not soften. The validator is a network service with a cache that routers depend on, so a validator that stops refreshing turns into a validator serving stale truth, and that is why the status and Prometheus metrics exist. The project itself is a good guide to that, since the security model, the SECURITY.md file, the fuzz directory in the repository and the professional support offering all point the same way, at a component that is trusted with the routing table.

## Open source with a support contract behind it

The licensing is the short part, because Routinator is liberally licensed under the BSD 3-Clause license, which is a permissive licence with an attribution requirement and the usual disclaimer. The maintenance picture is the interesting part. The release history shows three tagged versions in the last year, v0.15.0 on 2025-09-30, v0.15.1 on 2025-10-07 and v0.15.2 on 2026-06-08, and the manifest in the tree sits at 0.15.3-dev, so the development branch is ahead of the last published release. The repository is not archived and the last push was on 2026-10-19, so the work is current. The repository layout shows the same split between product and engineering, with src/, tals/ for the trust anchor locator data, pkg/ for packaging, contrib/, doc/, etc/, fuzz/ and test/ directories, alongside Cargo.toml, Cargo.lock, a build.rs, a Dockerfile and the Changelog. The documentation is at routinator.docs.nlnetlabs.nl with a stable version, and the homepage is the project page on nlnetlabs.nl.

## Conclusion

Adopt Routinator if you run a network and want to filter routes by origin authorisation, and you want a validator that runs on a small machine and gives routers a signed, machine readable answer over RTR. Do not adopt it as a policy engine, because it verifies and distributes the data and leaves the filtering decision to the router, which has to speak RTR for any of it to matter. Before you deploy, read the documentation for the configuration of your own data sources, decide whether to run the RTR server in the same process or split it out with RTRTR, and check the version you are pinning, since the manifest already sits at 0.15.3-dev while the newest published release is v0.15.2.

## FAQ

### What does Routinator do exactly?

It is an RPKI relying party written in Rust. It runs as a service that periodically downloads and verifies RPKI data, and its built-in HTTPS server offers a user interface, API endpoints for various file formats, logging, status and Prometheus metrics.

### How do I install Routinator?

Install a binary package for either Debian and Ubuntu, or for Red Hat Enterprise Linux and compatible systems such as Rocky Linux. Alternatively you can run it with Docker, or build from source using Cargo. The comprehensive documentation is at routinator.docs.nlnetlabs.nl.

### What is the difference between the built-in RTR server and RTRTR?

The built-in RTR server lets routers fetch verified RPKI data from the validator itself. Running RTR as a separate daemon with the RPKI data proxy RTRTR lets you centralise validation and securely distribute the processed data to various locations, which suits a network with several sites.

### Which Rust version does Routinator need?

The manifest declares edition 2021, rust-version 1.86 and resolver 3, with the crate version at 0.15.3-dev. The runtime dependencies include the rpki crate at 0.19.3 with the repository, rrdp, rtr, serde and slurm features, tokio for the async runtime, hyper for the HTTP server and reqwest with rustls-tls.

### How is the Routinator Docker image built?

It is a multi-stage Dockerfile with a selectable first stage. The default MODE=build compiles the application for the base image, while MODE=copy uses externally built binaries, for example cross-compiled ones, and the stages are two possible first stages named build or copy, a special source stage that selects between them, and the final stage. The build mode uses alpine:3.23 as its base image.

## Sources

- [License: BSD-3-Clause](https://github.com/NLnetLabs/routinator/blob/main/LICENSE)
- [NLnetLabs/routinator on GitHub](https://github.com/NLnetLabs/routinator)
- [Project website](https://nlnetlabs.nl/projects/routing/routinator/)
- [README](https://github.com/NLnetLabs/routinator/blob/main/README.md)
- [Releases](https://github.com/NLnetLabs/routinator/releases)

---

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