diff --git a/Cargo.lock b/Cargo.lock index 17b87db34..3481cafc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -765,6 +765,7 @@ dependencies = [ "deadpool-redis", "hex", "nostr", + "rustls", "serde_json", "sqlx", "tokio", @@ -1061,6 +1062,7 @@ dependencies = [ "redis", "reqwest 0.13.3", "rust-s3", + "rustls", "serde", "serde_json", "serde_yaml", @@ -6345,10 +6347,13 @@ dependencies = [ "num-bigint", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-native-certs", "ryu", "sha1_smol", "socket2", "tokio", + "tokio-rustls", "tokio-util", "url", "xxhash-rust", diff --git a/Cargo.toml b/Cargo.toml index 03cba4ee7..e4c979da3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ sqlx = { version = "0.9", features = [ ] } # Redis -redis = { version = "1.0", features = ["tokio-comp", "connection-manager"] } +redis = { version = "1.0", features = ["tokio-comp", "connection-manager", "tokio-rustls-comp"] } deadpool-redis = { version = "0.23", features = ["rt_tokio_1"] } # Nostr diff --git a/crates/buzz-admin/Cargo.toml b/crates/buzz-admin/Cargo.toml index c890ef24d..7a69e146b 100644 --- a/crates/buzz-admin/Cargo.toml +++ b/crates/buzz-admin/Cargo.toml @@ -26,6 +26,11 @@ serde_json = { workspace = true } anyhow = { workspace = true } hex = { workspace = true } deadpool-redis = { workspace = true } +# Redis TLS (rediss://, e.g. ElastiCache) uses rustls, which needs a process +# CryptoProvider installed at startup. The workspace redis TLS feature compiles +# both aws-lc-rs and ring in transitively, so rustls can't auto-select one — we +# install ring explicitly in main(). Mirrors buzz-relay's setup. +rustls = { version = "0.23", default-features = false, features = ["ring", "std"] } tracing = { workspace = true } sqlx = { workspace = true } url = { workspace = true } diff --git a/crates/buzz-admin/src/main.rs b/crates/buzz-admin/src/main.rs index f04960f65..1000b3616 100644 --- a/crates/buzz-admin/src/main.rs +++ b/crates/buzz-admin/src/main.rs @@ -92,6 +92,14 @@ enum Command { #[tokio::main] async fn main() { + // Install the ring CryptoProvider for rustls. The workspace redis TLS + // feature compiles both aws-lc-rs and ring in transitively, so rustls can't + // auto-select a provider and would panic on the first rediss:// (ElastiCache) + // Redis TLS connection without this. Mirrors buzz-relay's main(). + rustls::crypto::ring::default_provider() + .install_default() + .expect("failed to install rustls crypto provider"); + let cli = Cli::parse(); let code = match run(cli).await { diff --git a/crates/buzz-relay/Cargo.toml b/crates/buzz-relay/Cargo.toml index c9b80d53f..ae087c152 100644 --- a/crates/buzz-relay/Cargo.toml +++ b/crates/buzz-relay/Cargo.toml @@ -44,6 +44,11 @@ dashmap = { workspace = true } futures-util = { workspace = true } deadpool-redis = { workspace = true } redis = { workspace = true } +# Redis TLS (rediss://, e.g. ElastiCache) uses rustls, which needs a process +# CryptoProvider installed at startup. Both aws-lc-rs and ring are compiled in +# transitively, so rustls can't auto-select one — we install ring explicitly in +# main(). Mirrors buzz-acp's rustls setup for wss://. +rustls = { version = "0.23", default-features = false, features = ["ring", "std"] } sqlx = { workspace = true } base64 = "0.22" buzz-sdk = { workspace = true } diff --git a/crates/buzz-relay/src/main.rs b/crates/buzz-relay/src/main.rs index eaa484165..9223a0305 100644 --- a/crates/buzz-relay/src/main.rs +++ b/crates/buzz-relay/src/main.rs @@ -27,6 +27,14 @@ fn buzz_auto_migrate_enabled(value: Option<&str>) -> bool { #[tokio::main] async fn main() -> anyhow::Result<()> { + // Install the ring CryptoProvider for rustls. Required before any rustls + // TLS connection (rediss:// to ElastiCache, wss://, S3 over TLS): both + // aws-lc-rs and ring are compiled in transitively, so rustls can't + // auto-select a provider and would panic at first use without this. + rustls::crypto::ring::default_provider() + .install_default() + .expect("failed to install rustls crypto provider"); + // JSON-only structured logs — simple, machine-parseable, CAKE-compatible. tracing_subscriber::registry() .with(fmt::layer().json().flatten_event(true))