From 093484388f285cc90f77efc2dc1ee847252ec63c Mon Sep 17 00:00:00 2001 From: Johanna Larsson Date: Fri, 21 Aug 2026 09:43:28 +0100 Subject: [PATCH] Allow private IPs in dev Running tranquil with `just run-dev` using `pds.test` seems to be broken due to a recent change that blocks requests to private ips. Inside the compose network `pds.test` resolves to the traefik container's private IP. So it can't make requests to stuff like `https://pds.test/oauth-client-metadata.json` or the local plc. Introduces a new flag, default off, that allows connecting to private IPs, set to true for the dev compose. --- config.dev.toml | 1 + crates/tranquil-config/src/lib.rs | 4 ++++ crates/tranquil-oauth/src/client.rs | 6 +++--- crates/tranquil-pds/src/did.rs | 12 ++++++------ crates/tranquil-pds/src/plc/mod.rs | 12 ++++++------ crates/tranquil-pds/src/state.rs | 10 +++++++++- example.toml | 7 +++++++ 7 files changed, 36 insertions(+), 16 deletions(-) diff --git a/config.dev.toml b/config.dev.toml index 4d61216..e6eb979 100644 --- a/config.dev.toml +++ b/config.dev.toml @@ -1,6 +1,7 @@ [server] hostname = "pds.test" allow_http_proxy = true +allow_private_fetch = true invite_code_required = false disable_rate_limiting = true diff --git a/crates/tranquil-config/src/lib.rs b/crates/tranquil-config/src/lib.rs index 63176e0..ad23d96 100644 --- a/crates/tranquil-config/src/lib.rs +++ b/crates/tranquil-config/src/lib.rs @@ -465,6 +465,10 @@ pub struct ServerConfig { #[config(env = "DISABLE_RATE_LIMITING", default = false)] pub disable_rate_limiting: bool, + /// Allow outbound fetches to private network addresses. Useful for local development using docker compose. + #[config(env = "ALLOW_PRIVATE_FETCH", default = false)] + pub allow_private_fetch: bool, + /// Skip the verified-comms-channel gate for login and record writes. /// Please keep this off unless you're an invite-only PDS! #[config(env = "DISABLE_ACCOUNT_VERIFICATION_GATE", default = false)] diff --git a/crates/tranquil-oauth/src/client.rs b/crates/tranquil-oauth/src/client.rs index 04db0e6..34b3c76 100644 --- a/crates/tranquil-oauth/src/client.rs +++ b/crates/tranquil-oauth/src/client.rs @@ -75,7 +75,7 @@ pub struct ClientMetadataCache { } impl ClientMetadataCache { - pub fn new(cache: Arc, cache_ttl: Duration) -> Self { + pub fn new(cache: Arc, cache_ttl: Duration, fetch_policy: ReachPolicy) -> Self { Self { cache, http_client: { @@ -84,8 +84,8 @@ impl ClientMetadataCache { .connect_timeout(std::time::Duration::from_secs(10)) .pool_max_idle_per_host(10) .pool_idle_timeout(std::time::Duration::from_secs(90)) - .redirect(redirect_policy(ReachPolicy::DEBUG_LOOPBACK)) - .dns_resolver(dns_guard(ReachPolicy::DEBUG_LOOPBACK)) + .redirect(redirect_policy(fetch_policy)) + .dns_resolver(dns_guard(fetch_policy)) .user_agent(concat!( "Tranquil-PDS/", env!("CARGO_PKG_VERSION"), diff --git a/crates/tranquil-pds/src/did.rs b/crates/tranquil-pds/src/did.rs index 0a066d4..a7e055d 100644 --- a/crates/tranquil-pds/src/did.rs +++ b/crates/tranquil-pds/src/did.rs @@ -67,16 +67,16 @@ impl DidResolver { pub fn new(cache: Arc) -> Self { let cfg = tranquil_config::get(); + let fetch_policy = match cfg.server.allow_private_fetch { + true => tranquil_types::ReachPolicy::AllowPrivate, + false => tranquil_types::ReachPolicy::DEBUG_LOOPBACK, + }; let client = Client::builder() .timeout(Duration::from_secs(10)) .connect_timeout(Duration::from_secs(5)) .pool_max_idle_per_host(10) - .redirect(tranquil_types::redirect_policy( - tranquil_types::ReachPolicy::DEBUG_LOOPBACK, - )) - .dns_resolver(tranquil_types::dns_guard( - tranquil_types::ReachPolicy::DEBUG_LOOPBACK, - )) + .redirect(tranquil_types::redirect_policy(fetch_policy)) + .dns_resolver(tranquil_types::dns_guard(fetch_policy)) .build() .expect("failed to build DID resolver HTTP client"); diff --git a/crates/tranquil-pds/src/plc/mod.rs b/crates/tranquil-pds/src/plc/mod.rs index ea723f1..a529016 100644 --- a/crates/tranquil-pds/src/plc/mod.rs +++ b/crates/tranquil-pds/src/plc/mod.rs @@ -187,17 +187,17 @@ impl PlcClient { }); let timeout_secs = cfg.map_or(10, |c| c.plc.timeout_secs); let connect_timeout_secs = cfg.map_or(5, |c| c.plc.connect_timeout_secs); + let fetch_policy = match cfg.map_or(false, |c| c.server.allow_private_fetch) { + true => tranquil_types::ReachPolicy::AllowPrivate, + false => tranquil_types::ReachPolicy::DEBUG_LOOPBACK, + }; let client = Client::builder() .timeout(Duration::from_secs(timeout_secs)) .connect_timeout(Duration::from_secs(connect_timeout_secs)) .pool_max_idle_per_host(5) .pool_idle_timeout(Duration::from_secs(90)) - .redirect(tranquil_types::redirect_policy( - tranquil_types::ReachPolicy::DEBUG_LOOPBACK, - )) - .dns_resolver(tranquil_types::dns_guard( - tranquil_types::ReachPolicy::DEBUG_LOOPBACK, - )) + .redirect(tranquil_types::redirect_policy(fetch_policy)) + .dns_resolver(tranquil_types::dns_guard(fetch_policy)) .build() .expect("failed to build PLC directory HTTP client"); Self { diff --git a/crates/tranquil-pds/src/state.rs b/crates/tranquil-pds/src/state.rs index 19da343..3139a51 100644 --- a/crates/tranquil-pds/src/state.rs +++ b/crates/tranquil-pds/src/state.rs @@ -225,10 +225,18 @@ struct CacheBound { impl CacheBound { fn new(cache: &Arc, sso_config: &'static SsoConfig) -> Self { tranquil_lexicon::LexiconRegistry::global().set_shared_cache(cache.clone()); + let fetch_policy = match tranquil_config::get().server.allow_private_fetch { + true => tranquil_types::ReachPolicy::AllowPrivate, + false => tranquil_types::ReachPolicy::DEBUG_LOOPBACK, + }; Self { did_resolver: Arc::new(DidResolver::new(cache.clone())), cross_pds_oauth: Arc::new(CrossPdsOAuthClient::new(cache.clone())), - client_metadata_cache: ClientMetadataCache::new(cache.clone(), CLIENT_METADATA_TTL), + client_metadata_cache: ClientMetadataCache::new( + cache.clone(), + CLIENT_METADATA_TTL, + fetch_policy, + ), sso_manager: SsoManager::from_config(sso_config, cache.clone()), } } diff --git a/example.toml b/example.toml index 84b3baf..c972bc2 100644 --- a/example.toml +++ b/example.toml @@ -69,6 +69,13 @@ # Default value: false #disable_rate_limiting = false +# Allow outbound fetches to private network addresses. Useful for local development using docker compose. +# +# Can also be specified via environment variable `ALLOW_PRIVATE_FETCH`. +# +# Default value: false +#allow_private_fetch = false + # Skip the verified-comms-channel gate for login and record writes. # Please keep this off unless you're an invite-only PDS! #