rustls-native-roots-cache 0.0.1

Process-wide cache for rustls's native trust store, with platform-aware retry and sticky-failure semantics.
Documentation

Rustls Native Roots Cache

Process-wide cache for rustls's native trust store, with bounded retry on macOS Security framework transient errors and sticky failure semantics.

Features

rustls_native_certs::load_native_certs reaches into the OS keychain (Security framework on macOS, NSS / OpenSSL stores on Linux). On macOS the underlying Sec* APIs are not concurrency-safe under load — multiple threads calling them in parallel can return errSecIO (-36). Daemons that build many distinct rustls ClientConfigs (one per upstream-TLS fingerprint, for instance) hit this whenever a reload introduces a handful of new fingerprints concurrently.

This crate caches the trust store once per process behind an Arc<rustls::RootCertStore>. Concurrent first calls are serialised by OnceLock; subsequent calls are a cheap Arc::clone. The first load retries on transient failure with a small backoff (Apple documents errSecIO as recoverable), and the outcome is sticky — the cached error re-yields on subsequent calls so operators see consistent behaviour and can restart the process to retry.

Example

use rustls_native_roots_cache::native_roots;

# fn run() -> Result<(), Box<dyn std::error::Error>> {
let roots = native_roots()?;
let mut config = rustls::ClientConfig::builder()
    .with_root_certificates(rustls::RootCertStore::clone(&roots))
    .with_no_client_auth();
# Ok(())
# }

warm_native_roots() eagerly performs the first load — useful when a daemon's boot path wants to surface trust-store failure before the first TLS handshake.

License

Released under the MIT License © 2026 Canmi