* [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints
@ 2026-03-12 11:42 Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox v3 1/2] http: move http proxy schema from PBS to crate's api types Christian Ebner
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
This patch series exposes the nodes proxy config setting to the S3
clients for datastores backed by an S3 object store.
To honor crate boundaries, the proxy configuration is refactored to
be part of pbs-config instead of proxmox-backup. The API types are
move to pbs-api-types, inlining proxmox_backup::tools::config::from_property_string()
and NodeConfig::validate() to do so without creating additional unwanted
dependencies. The schema definition for the proxy is moved to proxmox-http
instead, already containing the proxy config definition.
Testing was performed by proxying traffic using https://www.mitmproxy.org/
Link to the bugtracker issue:
https://bugzilla.proxmox.com/show_bug.cgi?id=6716
Changes since version 2 (thanks @Fabian for review and suggestions):
- reworked completely by moving node config implementation and avoid
lookup/callback hack.
Changes since version 1:
- rebased onto current master
proxmox:
Christian Ebner (2):
http: move http proxy schema from PBS to crate's api types
pbs-api-types: move over NodeConfig and related api type from PBS
Cargo.toml | 1 +
pbs-api-types/Cargo.toml | 3 +
pbs-api-types/src/node.rs | 256 ++++++++++++++++++++++++++++++-
proxmox-http/Cargo.toml | 2 +
proxmox-http/debian/control | 18 +++
proxmox-http/src/lib.rs | 8 +-
proxmox-http/src/proxy_config.rs | 16 ++
7 files changed, 300 insertions(+), 4 deletions(-)
proxmox-backup:
Christian Ebner (6):
pbs-config: use http proxy schema moved to proxmox-http crate
config: inline NodeConfig::validate() to its only call side
config: use moved NodeConfig definitions in pbs-api-types
tools: drop unused from_property_string() helper
config: move node config into pbs-config, including helper tools
fix #6716: pass node http proxy config to s3 backend
Cargo.toml | 2 +-
pbs-config/Cargo.toml | 1 +
pbs-config/src/lib.rs | 2 +
pbs-config/src/node.rs | 55 +++++
{src => pbs-config/src}/tools/config.rs | 15 +-
pbs-config/src/tools/mod.rs | 1 +
pbs-datastore/src/datastore.rs | 4 +-
src/api2/admin/s3.rs | 2 +-
src/api2/config/remote.rs | 2 +-
src/api2/config/s3.rs | 2 +-
src/api2/node/apt.rs | 2 +-
src/api2/node/certificates.rs | 4 +-
src/api2/node/config.rs | 11 +-
src/api2/node/subscription.rs | 2 +-
src/api2/types/mod.rs | 11 -
src/bin/proxmox-backup-proxy.rs | 9 +-
src/bin/proxmox-daily-update.rs | 2 +-
src/config/mod.rs | 1 -
src/config/node.rs | 316 ------------------------
src/tools/mod.rs | 1 -
20 files changed, 81 insertions(+), 364 deletions(-)
create mode 100644 pbs-config/src/node.rs
rename {src => pbs-config/src}/tools/config.rs (94%)
create mode 100644 pbs-config/src/tools/mod.rs
delete mode 100644 src/config/node.rs
Summary over all repositories:
27 files changed, 381 insertions(+), 368 deletions(-)
--
Generated by murpp 0.9.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox v3 1/2] http: move http proxy schema from PBS to crate's api types
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox v3 2/2] pbs-api-types: move over NodeConfig and related api type from PBS Christian Ebner
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
The http proxy schema is used in combination with the ProxyConfig for
verification, the latter being part of the crate already.
Move also the schema to the crate and guard it behind a api-types
feature to allow for conditional compilation thereof.
This will easy refactoring the node config in PBS.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
proxmox-http/Cargo.toml | 2 ++
proxmox-http/debian/control | 18 ++++++++++++++++++
proxmox-http/src/lib.rs | 8 +++++---
proxmox-http/src/proxy_config.rs | 16 ++++++++++++++++
4 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/proxmox-http/Cargo.toml b/proxmox-http/Cargo.toml
index 61a45d1c..f8dde588 100644
--- a/proxmox-http/Cargo.toml
+++ b/proxmox-http/Cargo.toml
@@ -33,6 +33,7 @@ url = { workspace = true, optional = true }
proxmox-async = { workspace = true, optional = true }
proxmox-base64 = { workspace = true, optional = true }
proxmox-rate-limiter = { workspace = true, optional = true, features = [ "rate-limiter" ] }
+proxmox-schema = { workspace = true, optional = true, features = ["api-types"] }
proxmox-sys = { workspace = true, optional = true }
proxmox-io = { workspace = true, optional = true }
proxmox-lang = { workspace = true, optional = true }
@@ -89,6 +90,7 @@ client = [
client-sync = [ "client-trait", "http-helpers", "dep:ureq", "dep:native-tls" ]
client-trait = [ "dep:http" ]
http-helpers = [ "dep:http", "dep:proxmox-base64", "dep:proxmox-sys", "dep:serde_json", "dep:url" ]
+api-types = [ "dep:http", "dep:proxmox-schema", "dep:serde_json", "dep:url" ]
websocket = [
"dep:futures",
"dep:http",
diff --git a/proxmox-http/debian/control b/proxmox-http/debian/control
index 92daac47..b30c3e61 100644
--- a/proxmox-http/debian/control
+++ b/proxmox-http/debian/control
@@ -21,6 +21,7 @@ Depends:
${misc:Depends},
librust-anyhow-1+default-dev
Suggests:
+ librust-proxmox-http+api-types-dev (= ${binary:Version}),
librust-proxmox-http+body-dev (= ${binary:Version}),
librust-proxmox-http+client-dev (= ${binary:Version}),
librust-proxmox-http+client-sync-dev (= ${binary:Version}),
@@ -40,6 +41,23 @@ Provides:
Description: Proxmox HTTP library - Rust source code
Source code for Debianized Rust crate "proxmox-http"
+Package: librust-proxmox-http+api-types-dev
+Architecture: any
+Multi-Arch: same
+Depends:
+ ${misc:Depends},
+ librust-proxmox-http-dev (= ${binary:Version}),
+ librust-http-1+default-dev,
+ librust-proxmox-schema-5+api-types-dev (>= 5.0.1-~~),
+ librust-proxmox-schema-5+default-dev (>= 5.0.1-~~)
+Provides:
+ librust-proxmox-http-1+api-types-dev (= ${binary:Version}),
+ librust-proxmox-http-1.0+api-types-dev (= ${binary:Version}),
+ librust-proxmox-http-1.0.5+api-types-dev (= ${binary:Version})
+Description: Proxmox HTTP library - feature "api-types"
+ This metapackage enables feature "api-types" for the Rust proxmox-http crate,
+ by pulling in any additional dependencies needed by that feature.
+
Package: librust-proxmox-http+body-dev
Architecture: any
Multi-Arch: same
diff --git a/proxmox-http/src/lib.rs b/proxmox-http/src/lib.rs
index 406f5b8b..79caa23e 100644
--- a/proxmox-http/src/lib.rs
+++ b/proxmox-http/src/lib.rs
@@ -5,13 +5,15 @@
#[cfg(feature = "websocket")]
pub mod websocket;
-#[cfg(feature = "http-helpers")]
+#[cfg(any(feature = "http-helpers", feature = "api-types"))]
pub mod uri;
-#[cfg(feature = "http-helpers")]
+#[cfg(any(feature = "http-helpers", feature = "api-types"))]
pub mod proxy_config;
-#[cfg(feature = "http-helpers")]
+#[cfg(any(feature = "http-helpers", feature = "api-types"))]
pub use proxy_config::ProxyConfig;
+#[cfg(feature = "api-types")]
+pub use proxy_config::HTTP_PROXY_SCHEMA;
#[cfg(feature = "http-helpers")]
mod http_options;
diff --git a/proxmox-http/src/proxy_config.rs b/proxmox-http/src/proxy_config.rs
index 7ec68998..8bec3acd 100644
--- a/proxmox-http/src/proxy_config.rs
+++ b/proxmox-http/src/proxy_config.rs
@@ -6,6 +6,9 @@ use anyhow::{bail, format_err, Error};
use http::Uri;
+#[cfg(feature = "api-types")]
+use proxmox_schema::{ApiStringFormat, Schema, StringSchema};
+
use crate::uri::build_authority;
/// HTTP Proxy Configuration
@@ -88,3 +91,16 @@ impl ProxyConfig {
})
}
}
+
+#[cfg(feature = "api-types")]
+/// Schema for the http proxy configuration
+pub const HTTP_PROXY_SCHEMA: Schema =
+ StringSchema::new("HTTP proxy configuration [http://]<host>[:port]")
+ .format(&ApiStringFormat::VerifyFn(|s| {
+ ProxyConfig::parse_proxy_url(s)?;
+ Ok(())
+ }))
+ .min_length(1)
+ .max_length(128)
+ .type_text("[http://]<host>[:port]")
+ .schema();
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox v3 2/2] pbs-api-types: move over NodeConfig and related api type from PBS
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox v3 1/2] http: move http proxy schema from PBS to crate's api types Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 1/6] pbs-config: use http proxy schema moved to proxmox-http crate Christian Ebner
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
In preparation for refactoring the node config in PBS.
In order to move over the code, the previously used
proxmox_backup::tools::config::from_property_string()
helpers are replaced by analogous implementations by inlining the
serde_json::from_value() calls.
Further, the NodeConfig::validate() was only used by the node's
save_config() implementation and has therefore been inlined on the
PBS side to avoid a dependency on openssl crate.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
Cargo.toml | 1 +
pbs-api-types/Cargo.toml | 3 +
pbs-api-types/src/node.rs | 256 +++++++++++++++++++++++++++++++++++++-
3 files changed, 259 insertions(+), 1 deletion(-)
diff --git a/Cargo.toml b/Cargo.toml
index e66ffb78..7ad10ae5 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -144,6 +144,7 @@ zstd = "0.13"
# workspace dependencies
proxmox-access-control = { version = "1.3.0", path = "proxmox-access-control" }
+proxmox-acme-api = { version = "1.0.2", path = "proxmox-acme-api" }
proxmox-acme = { version = "1.1.0", path = "proxmox-acme", default-features = false }
proxmox-api-macro = { version = "1.4.3", path = "proxmox-api-macro" }
proxmox-apt = { version = "0.99.6", path = "proxmox-apt" }
diff --git a/pbs-api-types/Cargo.toml b/pbs-api-types/Cargo.toml
index 4eabe81e..01813f85 100644
--- a/pbs-api-types/Cargo.toml
+++ b/pbs-api-types/Cargo.toml
@@ -15,10 +15,13 @@ percent-encoding.workspace = true
regex.workspace = true
serde.workspace = true
serde_plain.workspace = true
+serde_json.workspace = true
+proxmox-acme-api.workspace = true
proxmox-auth-api = { workspace = true, features = [ "api-types" ] }
proxmox-apt-api-types.workspace = true
proxmox-fixed-string.workspace = true
+proxmox-http = { workspace = true, features = [ "api-types" ] }
proxmox-human-byte.workspace = true
proxmox-lang.workspace=true
proxmox-s3-client = { workspace = true, features = [ "api-types" ] }
diff --git a/pbs-api-types/src/node.rs b/pbs-api-types/src/node.rs
index e5b3526c..da3e4118 100644
--- a/pbs-api-types/src/node.rs
+++ b/pbs-api-types/src/node.rs
@@ -1,13 +1,19 @@
use std::ffi::OsStr;
+use anyhow::Error;
use serde::{Deserialize, Serialize};
+use proxmox_acme_api::{AcmeConfig, AcmeDomain, ACME_DOMAIN_PROPERTY_SCHEMA};
use proxmox_auth_api::types::Authid;
#[cfg(feature = "enum-fallback")]
use proxmox_fixed_string::FixedString;
+use proxmox_http::{ProxyConfig, HTTP_PROXY_SCHEMA};
use proxmox_schema::*;
-use crate::StorageStatus;
+use crate::{
+ StorageStatus, EMAIL_SCHEMA, MULTI_LINE_COMMENT_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA,
+ OPENSSL_CIPHERS_TLS_1_3_SCHEMA,
+};
#[api]
#[derive(Serialize, Deserialize, Default)]
@@ -199,3 +205,251 @@ pub struct NodeShellTicket {
/// user or authid encoded in the ticket
pub user: Authid,
}
+
+/// All available languages in Proxmox. Taken from proxmox-i18n repository.
+/// pt_BR, zh_CN, and zh_TW use the same case in the translation files.
+// TODO: auto-generate from available translations
+#[api]
+#[derive(Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum Translation {
+ /// Arabic
+ Ar,
+ /// Catalan
+ Ca,
+ /// Danish
+ Da,
+ /// German
+ De,
+ /// English
+ En,
+ /// Spanish
+ Es,
+ /// Euskera
+ Eu,
+ /// Persian (Farsi)
+ Fa,
+ /// French
+ Fr,
+ /// Galician
+ Gl,
+ /// Hebrew
+ He,
+ /// Hungarian
+ Hu,
+ /// Italian
+ It,
+ /// Japanese
+ Ja,
+ /// Korean
+ Kr,
+ /// Norwegian (Bokmal)
+ Nb,
+ /// Dutch
+ Nl,
+ /// Norwegian (Nynorsk)
+ Nn,
+ /// Polish
+ Pl,
+ /// Portuguese (Brazil)
+ #[serde(rename = "pt_BR")]
+ PtBr,
+ /// Russian
+ Ru,
+ /// Slovenian
+ Sl,
+ /// Swedish
+ Sv,
+ /// Turkish
+ Tr,
+ /// Chinese (simplified)
+ #[serde(rename = "zh_CN")]
+ ZhCn,
+ /// Chinese (traditional)
+ #[serde(rename = "zh_TW")]
+ ZhTw,
+}
+
+#[api(
+ properties: {
+ acme: {
+ optional: true,
+ type: String,
+ format: &ApiStringFormat::PropertyString(&AcmeConfig::API_SCHEMA),
+ },
+ acmedomain0: {
+ schema: ACME_DOMAIN_PROPERTY_SCHEMA,
+ optional: true,
+ },
+ acmedomain1: {
+ schema: ACME_DOMAIN_PROPERTY_SCHEMA,
+ optional: true,
+ },
+ acmedomain2: {
+ schema: ACME_DOMAIN_PROPERTY_SCHEMA,
+ optional: true,
+ },
+ acmedomain3: {
+ schema: ACME_DOMAIN_PROPERTY_SCHEMA,
+ optional: true,
+ },
+ acmedomain4: {
+ schema: ACME_DOMAIN_PROPERTY_SCHEMA,
+ optional: true,
+ },
+ "http-proxy": {
+ schema: HTTP_PROXY_SCHEMA,
+ optional: true,
+ },
+ "email-from": {
+ schema: EMAIL_SCHEMA,
+ optional: true,
+ },
+ "ciphers-tls-1.3": {
+ schema: OPENSSL_CIPHERS_TLS_1_3_SCHEMA,
+ optional: true,
+ },
+ "ciphers-tls-1.2": {
+ schema: OPENSSL_CIPHERS_TLS_1_2_SCHEMA,
+ optional: true,
+ },
+ "default-lang" : {
+ schema: Translation::API_SCHEMA,
+ optional: true,
+ },
+ "description" : {
+ optional: true,
+ schema: MULTI_LINE_COMMENT_SCHEMA,
+ },
+ "consent-text" : {
+ optional: true,
+ type: String,
+ max_length: 64 * 1024,
+ }
+ },
+)]
+#[derive(Deserialize, Serialize, Updater)]
+#[serde(rename_all = "kebab-case")]
+/// Node specific configuration.
+pub struct NodeConfig {
+ /// The acme account to use on this node.
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub acme: Option<String>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub acmedomain0: Option<String>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub acmedomain1: Option<String>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub acmedomain2: Option<String>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub acmedomain3: Option<String>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub acmedomain4: Option<String>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub http_proxy: Option<String>,
+
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub email_from: Option<String>,
+
+ /// List of TLS ciphers for TLS 1.3 that will be used by the proxy. (Proxy has to be restarted for changes to take effect)
+ #[serde(skip_serializing_if = "Option::is_none", rename = "ciphers-tls-1.3")]
+ pub ciphers_tls_1_3: Option<String>,
+
+ /// List of TLS ciphers for TLS <= 1.2 that will be used by the proxy. (Proxy has to be restarted for changes to take effect)
+ #[serde(skip_serializing_if = "Option::is_none", rename = "ciphers-tls-1.2")]
+ pub ciphers_tls_1_2: Option<String>,
+
+ /// Default language used in the GUI
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub default_lang: Option<String>,
+
+ /// Node description
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub description: Option<String>,
+
+ /// Maximum days to keep Task logs
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub task_log_max_days: Option<usize>,
+
+ /// Consent banner text
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub consent_text: Option<String>,
+}
+
+impl NodeConfig {
+ pub fn acme_config(&self) -> Result<AcmeConfig, Error> {
+ self.acme
+ .as_deref()
+ .map(|config| {
+ Ok(serde_json::from_value(
+ AcmeConfig::API_SCHEMA.parse_property_string(config)?,
+ )?)
+ })
+ .unwrap_or_else(|| proxmox_acme_api::parse_acme_config_string("account=default"))
+ }
+
+ pub fn acme_domains(&'_ self) -> AcmeDomainIter<'_> {
+ AcmeDomainIter::new(self)
+ }
+
+ /// Returns the parsed ProxyConfig
+ pub fn http_proxy(&self) -> Option<ProxyConfig> {
+ if let Some(http_proxy) = &self.http_proxy {
+ ProxyConfig::parse_proxy_url(http_proxy).ok()
+ } else {
+ None
+ }
+ }
+
+ /// Sets the HTTP proxy configuration
+ pub fn set_http_proxy(&mut self, http_proxy: Option<String>) {
+ self.http_proxy = http_proxy;
+ }
+}
+
+pub struct AcmeDomainIter<'a> {
+ config: &'a NodeConfig,
+ index: usize,
+}
+
+impl<'a> AcmeDomainIter<'a> {
+ fn new(config: &'a NodeConfig) -> Self {
+ Self { config, index: 0 }
+ }
+}
+
+impl Iterator for AcmeDomainIter<'_> {
+ type Item = Result<AcmeDomain, Error>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let domain = loop {
+ let index = self.index;
+ self.index += 1;
+
+ let domain = match index {
+ 0 => self.config.acmedomain0.as_deref(),
+ 1 => self.config.acmedomain1.as_deref(),
+ 2 => self.config.acmedomain2.as_deref(),
+ 3 => self.config.acmedomain3.as_deref(),
+ 4 => self.config.acmedomain4.as_deref(),
+ _ => return None,
+ };
+
+ if let Some(domain) = domain {
+ break domain;
+ }
+ };
+
+ Some(
+ AcmeDomain::API_SCHEMA
+ .parse_property_string(domain)
+ .and_then(|domain| Ok(serde_json::from_value(domain)?)),
+ )
+ }
+}
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox-backup v3 1/6] pbs-config: use http proxy schema moved to proxmox-http crate
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox v3 1/2] http: move http proxy schema from PBS to crate's api types Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox v3 2/2] pbs-api-types: move over NodeConfig and related api type from PBS Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 2/6] config: inline NodeConfig::validate() to its only call side Christian Ebner
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
The schema was move there in preparation for moving the node config
to the pbs-config crate. Use it and drop the local one.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
Cargo.toml | 2 +-
src/api2/types/mod.rs | 11 -----------
src/config/node.rs | 4 +---
3 files changed, 2 insertions(+), 15 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index ca0ee1761..542257535 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -64,7 +64,7 @@ proxmox-config-digest = "1"
proxmox-daemon = "1"
proxmox-fuse = "3"
proxmox-docgen = "1"
-proxmox-http = { version = "1.0.2", features = [ "client", "http-helpers", "websocket" ] } # see below
+proxmox-http = { version = "1.0.2", features = [ "client", "http-helpers", "api-types", "websocket" ] } # see below
proxmox-human-byte = "1"
proxmox-io = "1.0.1" # tools and client use "tokio" feature
proxmox-lang = "1.1"
diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs
index 341936853..40fe7302b 100644
--- a/src/api2/types/mod.rs
+++ b/src/api2/types/mod.rs
@@ -116,14 +116,3 @@ fn test_proxmox_user_id_schema() -> Result<(), anyhow::Error> {
Ok(())
}
-
-pub const HTTP_PROXY_SCHEMA: Schema =
- StringSchema::new("HTTP proxy configuration [http://]<host>[:port]")
- .format(&ApiStringFormat::VerifyFn(|s| {
- proxmox_http::ProxyConfig::parse_proxy_url(s)?;
- Ok(())
- }))
- .min_length(1)
- .max_length(128)
- .type_text("[http://]<host>[:port]")
- .schema();
diff --git a/src/config/node.rs b/src/config/node.rs
index a79bf5707..c01c6aa7a 100644
--- a/src/config/node.rs
+++ b/src/config/node.rs
@@ -9,14 +9,12 @@ use pbs_api_types::{
OPENSSL_CIPHERS_TLS_1_3_SCHEMA,
};
use proxmox_acme_api::{AcmeConfig, AcmeDomain, ACME_DOMAIN_PROPERTY_SCHEMA};
-use proxmox_http::ProxyConfig;
+use proxmox_http::{ProxyConfig, HTTP_PROXY_SCHEMA};
use proxmox_schema::{api, ApiStringFormat, ApiType, Updater};
use pbs_buildcfg::configdir;
use pbs_config::{open_backup_lockfile, BackupLockGuard};
-use crate::api2::types::HTTP_PROXY_SCHEMA;
-
const CONF_FILE: &str = configdir!("/node.cfg");
const LOCK_FILE: &str = configdir!("/.node.lck");
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox-backup v3 2/6] config: inline NodeConfig::validate() to its only call side
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
` (2 preceding siblings ...)
2026-03-12 11:42 ` [PATCH proxmox-backup v3 1/6] pbs-config: use http proxy schema moved to proxmox-http crate Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 3/6] config: use moved NodeConfig definitions in pbs-api-types Christian Ebner
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
Helps to avoid any dependency on the openssl crate when moving the
NodeConfig to the pbs-api-types crate, which is itself done in order
to move the node config implementation to pbs-config.
Having the implementation in pbs-config will allow to easily access
the node config from pbs-datastore, in order to read the node proxy
config.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
src/config/node.rs | 35 ++++++++++++++---------------------
1 file changed, 14 insertions(+), 21 deletions(-)
diff --git a/src/config/node.rs b/src/config/node.rs
index c01c6aa7a..93173e66f 100644
--- a/src/config/node.rs
+++ b/src/config/node.rs
@@ -34,7 +34,20 @@ pub fn config() -> Result<(NodeConfig, [u8; 32]), Error> {
/// Write the Node Config, requires the write lock to be held.
pub fn save_config(config: &NodeConfig) -> Result<(), Error> {
- config.validate()?;
+ let mut domains = HashSet::new();
+ for domain in config.acme_domains() {
+ let domain = domain?;
+ if !domains.insert(domain.domain.to_lowercase()) {
+ bail!("duplicate domain '{}' in ACME config", domain.domain);
+ }
+ }
+ let mut dummy_acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
+ if let Some(ciphers) = config.ciphers_tls_1_3.as_deref() {
+ dummy_acceptor.set_ciphersuites(ciphers)?;
+ }
+ if let Some(ciphers) = config.ciphers_tls_1_2.as_deref() {
+ dummy_acceptor.set_cipher_list(ciphers)?;
+ }
let raw = crate::tools::config::to_bytes(config, &NodeConfig::API_SCHEMA)?;
pbs_config::replace_backup_config(CONF_FILE, &raw)
@@ -246,26 +259,6 @@ impl NodeConfig {
pub fn set_http_proxy(&mut self, http_proxy: Option<String>) {
self.http_proxy = http_proxy;
}
-
- /// Validate the configuration.
- pub fn validate(&self) -> Result<(), Error> {
- let mut domains = HashSet::new();
- for domain in self.acme_domains() {
- let domain = domain?;
- if !domains.insert(domain.domain.to_lowercase()) {
- bail!("duplicate domain '{}' in ACME config", domain.domain);
- }
- }
- let mut dummy_acceptor = SslAcceptor::mozilla_intermediate_v5(SslMethod::tls()).unwrap();
- if let Some(ciphers) = self.ciphers_tls_1_3.as_deref() {
- dummy_acceptor.set_ciphersuites(ciphers)?;
- }
- if let Some(ciphers) = self.ciphers_tls_1_2.as_deref() {
- dummy_acceptor.set_cipher_list(ciphers)?;
- }
-
- Ok(())
- }
}
pub struct AcmeDomainIter<'a> {
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox-backup v3 3/6] config: use moved NodeConfig definitions in pbs-api-types
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
` (3 preceding siblings ...)
2026-03-12 11:42 ` [PATCH proxmox-backup v3 2/6] config: inline NodeConfig::validate() to its only call side Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 4/6] tools: drop unused from_property_string() helper Christian Ebner
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
These have been moved as preparation in an effort to move the node
config to pbs-config. That is required in order to read the node's
proxy config from the datastore implementation.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
src/api2/node/config.rs | 3 +-
src/config/node.rs | 259 +---------------------------------------
src/tools/config.rs | 4 +-
3 files changed, 6 insertions(+), 260 deletions(-)
diff --git a/src/api2/node/config.rs b/src/api2/node/config.rs
index 19ede24b7..619e2b022 100644
--- a/src/api2/node/config.rs
+++ b/src/api2/node/config.rs
@@ -5,10 +5,9 @@ use hex::FromHex;
use proxmox_router::{Permission, Router, RpcEnvironment};
use proxmox_schema::api;
-use pbs_api_types::{NODE_SCHEMA, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
+use pbs_api_types::{NodeConfig, NodeConfigUpdater, NODE_SCHEMA, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY};
use crate::api2::node::apt::update_apt_proxy_config;
-use crate::config::node::{NodeConfig, NodeConfigUpdater};
pub const ROUTER: Router = Router::new()
.get(&API_METHOD_GET_NODE_CONFIG)
diff --git a/src/config/node.rs b/src/config/node.rs
index 93173e66f..6e44495f8 100644
--- a/src/config/node.rs
+++ b/src/config/node.rs
@@ -2,15 +2,10 @@ use std::collections::HashSet;
use anyhow::{bail, Error};
use openssl::ssl::{SslAcceptor, SslMethod};
-use serde::{Deserialize, Serialize};
-use pbs_api_types::{
- EMAIL_SCHEMA, MULTI_LINE_COMMENT_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA,
- OPENSSL_CIPHERS_TLS_1_3_SCHEMA,
-};
-use proxmox_acme_api::{AcmeConfig, AcmeDomain, ACME_DOMAIN_PROPERTY_SCHEMA};
-use proxmox_http::{ProxyConfig, HTTP_PROXY_SCHEMA};
-use proxmox_schema::{api, ApiStringFormat, ApiType, Updater};
+use pbs_api_types::NodeConfig;
+use proxmox_http::ProxyConfig;
+use proxmox_schema::ApiType;
use pbs_buildcfg::configdir;
use pbs_config::{open_backup_lockfile, BackupLockGuard};
@@ -53,254 +48,6 @@ pub fn save_config(config: &NodeConfig) -> Result<(), Error> {
pbs_config::replace_backup_config(CONF_FILE, &raw)
}
-/// All available languages in Proxmox. Taken from proxmox-i18n repository.
-/// pt_BR, zh_CN, and zh_TW use the same case in the translation files.
-// TODO: auto-generate from available translations
-#[api]
-#[derive(Serialize, Deserialize)]
-#[serde(rename_all = "lowercase")]
-pub enum Translation {
- /// Arabic
- Ar,
- /// Catalan
- Ca,
- /// Danish
- Da,
- /// German
- De,
- /// English
- En,
- /// Spanish
- Es,
- /// Euskera
- Eu,
- /// Persian (Farsi)
- Fa,
- /// French
- Fr,
- /// Galician
- Gl,
- /// Hebrew
- He,
- /// Hungarian
- Hu,
- /// Italian
- It,
- /// Japanese
- Ja,
- /// Korean
- Kr,
- /// Norwegian (Bokmal)
- Nb,
- /// Dutch
- Nl,
- /// Norwegian (Nynorsk)
- Nn,
- /// Polish
- Pl,
- /// Portuguese (Brazil)
- #[serde(rename = "pt_BR")]
- PtBr,
- /// Russian
- Ru,
- /// Slovenian
- Sl,
- /// Swedish
- Sv,
- /// Turkish
- Tr,
- /// Chinese (simplified)
- #[serde(rename = "zh_CN")]
- ZhCn,
- /// Chinese (traditional)
- #[serde(rename = "zh_TW")]
- ZhTw,
-}
-
-#[api(
- properties: {
- acme: {
- optional: true,
- type: String,
- format: &ApiStringFormat::PropertyString(&AcmeConfig::API_SCHEMA),
- },
- acmedomain0: {
- schema: ACME_DOMAIN_PROPERTY_SCHEMA,
- optional: true,
- },
- acmedomain1: {
- schema: ACME_DOMAIN_PROPERTY_SCHEMA,
- optional: true,
- },
- acmedomain2: {
- schema: ACME_DOMAIN_PROPERTY_SCHEMA,
- optional: true,
- },
- acmedomain3: {
- schema: ACME_DOMAIN_PROPERTY_SCHEMA,
- optional: true,
- },
- acmedomain4: {
- schema: ACME_DOMAIN_PROPERTY_SCHEMA,
- optional: true,
- },
- "http-proxy": {
- schema: HTTP_PROXY_SCHEMA,
- optional: true,
- },
- "email-from": {
- schema: EMAIL_SCHEMA,
- optional: true,
- },
- "ciphers-tls-1.3": {
- schema: OPENSSL_CIPHERS_TLS_1_3_SCHEMA,
- optional: true,
- },
- "ciphers-tls-1.2": {
- schema: OPENSSL_CIPHERS_TLS_1_2_SCHEMA,
- optional: true,
- },
- "default-lang" : {
- schema: Translation::API_SCHEMA,
- optional: true,
- },
- "description" : {
- optional: true,
- schema: MULTI_LINE_COMMENT_SCHEMA,
- },
- "consent-text" : {
- optional: true,
- type: String,
- max_length: 64 * 1024,
- }
- },
-)]
-#[derive(Deserialize, Serialize, Updater)]
-#[serde(rename_all = "kebab-case")]
-/// Node specific configuration.
-pub struct NodeConfig {
- /// The acme account to use on this node.
- #[serde(skip_serializing_if = "Option::is_none")]
- pub acme: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub acmedomain0: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub acmedomain1: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub acmedomain2: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub acmedomain3: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub acmedomain4: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub http_proxy: Option<String>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub email_from: Option<String>,
-
- /// List of TLS ciphers for TLS 1.3 that will be used by the proxy. (Proxy has to be restarted for changes to take effect)
- #[serde(skip_serializing_if = "Option::is_none", rename = "ciphers-tls-1.3")]
- pub ciphers_tls_1_3: Option<String>,
-
- /// List of TLS ciphers for TLS <= 1.2 that will be used by the proxy. (Proxy has to be restarted for changes to take effect)
- #[serde(skip_serializing_if = "Option::is_none", rename = "ciphers-tls-1.2")]
- pub ciphers_tls_1_2: Option<String>,
-
- /// Default language used in the GUI
- #[serde(skip_serializing_if = "Option::is_none")]
- pub default_lang: Option<String>,
-
- /// Node description
- #[serde(skip_serializing_if = "Option::is_none")]
- pub description: Option<String>,
-
- /// Maximum days to keep Task logs
- #[serde(skip_serializing_if = "Option::is_none")]
- pub task_log_max_days: Option<usize>,
-
- /// Consent banner text
- #[serde(skip_serializing_if = "Option::is_none")]
- pub consent_text: Option<String>,
-}
-
-impl NodeConfig {
- pub fn acme_config(&self) -> Result<AcmeConfig, Error> {
- self.acme
- .as_deref()
- .map(|config| {
- crate::tools::config::from_property_string::<AcmeConfig>(
- config,
- &AcmeConfig::API_SCHEMA,
- )
- })
- .unwrap_or_else(|| proxmox_acme_api::parse_acme_config_string("account=default"))
- }
-
- pub fn acme_domains(&'_ self) -> AcmeDomainIter<'_> {
- AcmeDomainIter::new(self)
- }
-
- /// Returns the parsed ProxyConfig
- pub fn http_proxy(&self) -> Option<ProxyConfig> {
- if let Some(http_proxy) = &self.http_proxy {
- ProxyConfig::parse_proxy_url(http_proxy).ok()
- } else {
- None
- }
- }
-
- /// Sets the HTTP proxy configuration
- pub fn set_http_proxy(&mut self, http_proxy: Option<String>) {
- self.http_proxy = http_proxy;
- }
-}
-
-pub struct AcmeDomainIter<'a> {
- config: &'a NodeConfig,
- index: usize,
-}
-
-impl<'a> AcmeDomainIter<'a> {
- fn new(config: &'a NodeConfig) -> Self {
- Self { config, index: 0 }
- }
-}
-
-impl Iterator for AcmeDomainIter<'_> {
- type Item = Result<AcmeDomain, Error>;
-
- fn next(&mut self) -> Option<Self::Item> {
- let domain = loop {
- let index = self.index;
- self.index += 1;
-
- let domain = match index {
- 0 => self.config.acmedomain0.as_deref(),
- 1 => self.config.acmedomain1.as_deref(),
- 2 => self.config.acmedomain2.as_deref(),
- 3 => self.config.acmedomain3.as_deref(),
- 4 => self.config.acmedomain4.as_deref(),
- _ => return None,
- };
-
- if let Some(domain) = domain {
- break domain;
- }
- };
-
- Some(crate::tools::config::from_property_string(
- domain,
- &AcmeDomain::API_SCHEMA,
- ))
- }
-}
-
pub(crate) fn node_http_proxy_config() -> Result<Option<ProxyConfig>, Error> {
let (node_config, _digest) = self::config()?;
Ok(node_config.http_proxy())
diff --git a/src/tools/config.rs b/src/tools/config.rs
index 64fe981aa..2c1078676 100644
--- a/src/tools/config.rs
+++ b/src/tools/config.rs
@@ -177,7 +177,7 @@ fn test() {
use proxmox_schema::ApiType;
// let's just reuse some schema we actually have available:
- use crate::config::node::NodeConfig;
+ use pbs_api_types::NodeConfig;
const NODE_CONFIG: &str = "\
acme: account=pebble\n\
@@ -198,7 +198,7 @@ fn test_with_comment() {
use proxmox_schema::ApiType;
// let's just reuse some schema we actually have available:
- use crate::config::node::NodeConfig;
+ use pbs_api_types::NodeConfig;
const NODE_INPUT: &str = "\
#this should\n\
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox-backup v3 4/6] tools: drop unused from_property_string() helper
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
` (4 preceding siblings ...)
2026-03-12 11:42 ` [PATCH proxmox-backup v3 3/6] config: use moved NodeConfig definitions in pbs-api-types Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 5/6] config: move node config into pbs-config, including helper tools Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 6/6] fix #6716: pass node http proxy config to s3 backend Christian Ebner
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
Since the NodeConfig has been moved and there are no further call
sides it is safe to drop.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
src/tools/config.rs | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/src/tools/config.rs b/src/tools/config.rs
index 2c1078676..413ff3f9e 100644
--- a/src/tools/config.rs
+++ b/src/tools/config.rs
@@ -113,17 +113,6 @@ fn parse_value(value: &str, schema: Option<&'static Schema>) -> Result<Value, Er
}
}
-/// Parse a string as a property string into a deserializable type. This is just a short wrapper
-/// around deserializing the s
-pub fn from_property_string<T>(input: &str, schema: &'static Schema) -> Result<T, Error>
-where
- T: for<'de> Deserialize<'de>,
-{
- Ok(serde_json::from_value(
- schema.parse_property_string(input)?,
- )?)
-}
-
/// Serialize a data structure using a 'key: value' config file format.
pub fn to_bytes<T: Serialize>(value: &T, schema: &'static Schema) -> Result<Vec<u8>, Error> {
value_to_bytes(&serde_json::to_value(value)?, schema)
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox-backup v3 5/6] config: move node config into pbs-config, including helper tools
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
` (5 preceding siblings ...)
2026-03-12 11:42 ` [PATCH proxmox-backup v3 4/6] tools: drop unused from_property_string() helper Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 6/6] fix #6716: pass node http proxy config to s3 backend Christian Ebner
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
None of the helpers are required in proxmox-backup anymore, all
encapsulated in the pbs-config crate. Keep however the same
`tools::config` module layout.
Adapt all callsides to use pbs_config::node to interact with the node
config.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
pbs-config/Cargo.toml | 1 +
pbs-config/src/lib.rs | 2 ++
{src/config => pbs-config/src}/node.rs | 7 ++++---
{src => pbs-config/src}/tools/config.rs | 0
pbs-config/src/tools/mod.rs | 1 +
src/api2/config/remote.rs | 2 +-
src/api2/node/apt.rs | 2 +-
src/api2/node/certificates.rs | 4 ++--
src/api2/node/config.rs | 8 ++++----
src/api2/node/subscription.rs | 2 +-
src/bin/proxmox-backup-proxy.rs | 9 ++++-----
src/bin/proxmox-daily-update.rs | 2 +-
src/config/mod.rs | 1 -
src/tools/mod.rs | 1 -
14 files changed, 22 insertions(+), 20 deletions(-)
rename {src/config => pbs-config/src}/node.rs (89%)
rename {src => pbs-config/src}/tools/config.rs (100%)
create mode 100644 pbs-config/src/tools/mod.rs
diff --git a/pbs-config/Cargo.toml b/pbs-config/Cargo.toml
index 74afb3c64..2040be0b2 100644
--- a/pbs-config/Cargo.toml
+++ b/pbs-config/Cargo.toml
@@ -17,6 +17,7 @@ regex.workspace = true
serde.workspace = true
serde_json.workspace = true
+proxmox-http.workspace = true
proxmox-notify.workspace = true
proxmox-router = { workspace = true, default-features = false }
proxmox-s3-client.workspace = true
diff --git a/pbs-config/src/lib.rs b/pbs-config/src/lib.rs
index 1ed472385..9eb83ac6a 100644
--- a/pbs-config/src/lib.rs
+++ b/pbs-config/src/lib.rs
@@ -6,6 +6,7 @@ pub mod domains;
pub mod drive;
pub mod media_pool;
pub mod metrics;
+pub mod node;
pub mod notifications;
pub mod prune;
pub mod remote;
@@ -13,6 +14,7 @@ pub mod s3;
pub mod sync;
pub mod tape_job;
pub mod token_shadow;
+pub(crate) mod tools;
pub mod traffic_control;
pub mod user;
pub mod verify;
diff --git a/src/config/node.rs b/pbs-config/src/node.rs
similarity index 89%
rename from src/config/node.rs
rename to pbs-config/src/node.rs
index 6e44495f8..cb6158c30 100644
--- a/src/config/node.rs
+++ b/pbs-config/src/node.rs
@@ -8,7 +8,8 @@ use proxmox_http::ProxyConfig;
use proxmox_schema::ApiType;
use pbs_buildcfg::configdir;
-use pbs_config::{open_backup_lockfile, BackupLockGuard};
+
+use crate::{open_backup_lockfile, BackupLockGuard};
const CONF_FILE: &str = configdir!("/node.cfg");
const LOCK_FILE: &str = configdir!("/.node.lck");
@@ -45,10 +46,10 @@ pub fn save_config(config: &NodeConfig) -> Result<(), Error> {
}
let raw = crate::tools::config::to_bytes(config, &NodeConfig::API_SCHEMA)?;
- pbs_config::replace_backup_config(CONF_FILE, &raw)
+ crate::replace_backup_config(CONF_FILE, &raw)
}
-pub(crate) fn node_http_proxy_config() -> Result<Option<ProxyConfig>, Error> {
+pub fn node_http_proxy_config() -> Result<Option<ProxyConfig>, Error> {
let (node_config, _digest) = self::config()?;
Ok(node_config.http_proxy())
}
diff --git a/src/tools/config.rs b/pbs-config/src/tools/config.rs
similarity index 100%
rename from src/tools/config.rs
rename to pbs-config/src/tools/config.rs
diff --git a/pbs-config/src/tools/mod.rs b/pbs-config/src/tools/mod.rs
new file mode 100644
index 000000000..30e489dae
--- /dev/null
+++ b/pbs-config/src/tools/mod.rs
@@ -0,0 +1 @@
+pub(crate) mod config;
diff --git a/src/api2/config/remote.rs b/src/api2/config/remote.rs
index 1996ee91b..03eae24dc 100644
--- a/src/api2/config/remote.rs
+++ b/src/api2/config/remote.rs
@@ -320,7 +320,7 @@ pub fn remote_client_config(
options = options.rate_limit(limit);
}
if remote.config.use_node_proxy.unwrap_or(false) {
- let proxy = crate::config::node::node_http_proxy_config()?;
+ let proxy = pbs_config::node::node_http_proxy_config()?;
options = options.proxy(proxy);
}
diff --git a/src/api2/node/apt.rs b/src/api2/node/apt.rs
index c696adb1e..32dfe7def 100644
--- a/src/api2/node/apt.rs
+++ b/src/api2/node/apt.rs
@@ -15,7 +15,7 @@ use proxmox_sys::fs::{replace_file, CreateOptions};
use pbs_api_types::{NODE_SCHEMA, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, UPID_SCHEMA};
-use crate::config::node;
+use pbs_config::node;
#[api(
input: {
diff --git a/src/api2/node/certificates.rs b/src/api2/node/certificates.rs
index e5761e5f5..a69f6511f 100644
--- a/src/api2/node/certificates.rs
+++ b/src/api2/node/certificates.rs
@@ -328,7 +328,7 @@ fn spawn_certificate_worker(
// custom one too hard... We keep the parameter because the widget-toolkit may be using it...
let _ = force;
- let (node_config, _digest) = crate::config::node::config()?;
+ let (node_config, _digest) = pbs_config::node::config()?;
let auth_id = rpcenv.get_auth_id().unwrap();
@@ -381,7 +381,7 @@ fn spawn_certificate_worker(
/// Renew the current ACME certificate if it expires within 30 days (or always if the `force`
/// parameter is set).
pub fn revoke_acme_cert(rpcenv: &mut dyn RpcEnvironment) -> Result<String, Error> {
- let (node_config, _digest) = crate::config::node::config()?;
+ let (node_config, _digest) = pbs_config::node::config()?;
let cert_pem = get_certificate_pem()?;
diff --git a/src/api2/node/config.rs b/src/api2/node/config.rs
index 619e2b022..fbec79118 100644
--- a/src/api2/node/config.rs
+++ b/src/api2/node/config.rs
@@ -28,7 +28,7 @@ pub const ROUTER: Router = Router::new()
)]
/// Get the node configuration
pub fn get_node_config(rpcenv: &mut dyn RpcEnvironment) -> Result<NodeConfig, Error> {
- let (config, digest) = crate::config::node::config()?;
+ let (config, digest) = pbs_config::node::config()?;
rpcenv["digest"] = hex::encode(digest).into();
Ok(config)
}
@@ -104,8 +104,8 @@ pub fn update_node_config(
delete: Option<Vec<DeletableProperty>>,
digest: Option<String>,
) -> Result<(), Error> {
- let _lock = crate::config::node::lock()?;
- let (mut config, expected_digest) = crate::config::node::config()?;
+ let _lock = pbs_config::node::lock()?;
+ let (mut config, expected_digest) = pbs_config::node::config()?;
if let Some(digest) = digest {
// FIXME: GUI doesn't handle our non-inlined digest part here properly...
if !digest.is_empty() {
@@ -206,7 +206,7 @@ pub fn update_node_config(
config.consent_text = update.consent_text;
}
- crate::config::node::save_config(&config)?;
+ pbs_config::node::save_config(&config)?;
update_apt_proxy_config(config.http_proxy().as_ref())?;
diff --git a/src/api2/node/subscription.rs b/src/api2/node/subscription.rs
index 7d9678fc5..03d613ee2 100644
--- a/src/api2/node/subscription.rs
+++ b/src/api2/node/subscription.rs
@@ -12,10 +12,10 @@ use pbs_api_types::{
Authid, NODE_SCHEMA, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, SUBSCRIPTION_KEY_SCHEMA,
};
-use crate::config::node;
use crate::tools::{DEFAULT_USER_AGENT_STRING, PROXMOX_BACKUP_TCP_KEEPALIVE_TIME};
use pbs_buildcfg::PROXMOX_BACKUP_SUBSCRIPTION_FN;
+use pbs_config::node;
use pbs_config::CachedUserInfo;
const PRODUCT_URL: &str = "https://www.proxmox.com/en/proxmox-backup-server/pricing";
diff --git a/src/bin/proxmox-backup-proxy.rs b/src/bin/proxmox-backup-proxy.rs
index c1fe3ac15..b04eb7e8e 100644
--- a/src/bin/proxmox-backup-proxy.rs
+++ b/src/bin/proxmox-backup-proxy.rs
@@ -45,7 +45,6 @@ use pbs_api_types::{
};
use proxmox_backup::auth_helpers::*;
-use proxmox_backup::config;
use proxmox_backup::server::{self, metric_collection};
use proxmox_backup::tools::PROXMOX_BACKUP_TCP_KEEPALIVE_TIME;
@@ -80,7 +79,7 @@ fn get_language(headers: &hyper::http::HeaderMap) -> String {
match cookie_from_header(headers, "PBSLangCookie") {
Some(cookie_lang) if exists(&cookie_lang) => cookie_lang,
- _ => match config::node::config().map(|(cfg, _)| cfg.default_lang) {
+ _ => match pbs_config::node::config().map(|(cfg, _)| cfg.default_lang) {
Ok(Some(default_lang)) if exists(&default_lang) => default_lang,
_ => String::from(""),
},
@@ -145,7 +144,7 @@ async fn get_index_future(env: RestEnvironment, parts: Parts) -> Response<Body>
let theme = get_theme(&parts.headers);
- let consent = config::node::config()
+ let consent = pbs_config::node::config()
.ok()
.and_then(|config| config.0.consent_text)
.unwrap_or("".to_string());
@@ -430,7 +429,7 @@ fn make_tls_acceptor() -> Result<SslAcceptor, Error> {
let key_path = configdir!("/proxy.key");
let cert_path = configdir!("/proxy.pem");
- let (config, _) = config::node::config()?;
+ let (config, _) = pbs_config::node::config()?;
let ciphers_tls_1_3 = config.ciphers_tls_1_3;
let ciphers_tls_1_2 = config.ciphers_tls_1_2;
@@ -799,7 +798,7 @@ async fn schedule_task_log_rotate() {
let max_size = 512 * 1024 - 1; // an entry has ~ 100b, so > 5000 entries/file
let max_files = 20; // times twenty files gives > 100000 task entries
- let max_days = proxmox_backup::config::node::config()
+ let max_days = pbs_config::node::config()
.map(|(cfg, _)| cfg.task_log_max_days)
.ok()
.flatten();
diff --git a/src/bin/proxmox-daily-update.rs b/src/bin/proxmox-daily-update.rs
index 025eb47fd..c4d68e306 100644
--- a/src/bin/proxmox-daily-update.rs
+++ b/src/bin/proxmox-daily-update.rs
@@ -67,7 +67,7 @@ async fn do_update(rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
}
async fn check_acme_certificates(rpcenv: &mut dyn RpcEnvironment) -> Result<(), Error> {
- let (config, _) = proxmox_backup::config::node::config()?;
+ let (config, _) = pbs_config::node::config()?;
// do we even have any acme domains configures?
if config.acme_domains().next().is_none() {
diff --git a/src/config/mod.rs b/src/config/mod.rs
index f05af90d8..2de76bb14 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -15,7 +15,6 @@ use proxmox_lang::try_block;
use pbs_api_types::{PamRealmConfig, PbsRealmConfig};
use pbs_buildcfg::{self, configdir};
-pub mod node;
pub mod tfa;
/// Check configuration directory permissions
diff --git a/src/tools/mod.rs b/src/tools/mod.rs
index 6a975bde2..05225a843 100644
--- a/src/tools/mod.rs
+++ b/src/tools/mod.rs
@@ -13,7 +13,6 @@ use proxmox_http::{client::Client, HttpOptions, ProxyConfig};
use pbs_datastore::backup_info::{BackupDir, BackupInfo};
use pbs_datastore::manifest::BackupManifest;
-pub mod config;
pub mod disks;
pub mod fs;
pub mod statistics;
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH proxmox-backup v3 6/6] fix #6716: pass node http proxy config to s3 backend
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
` (6 preceding siblings ...)
2026-03-12 11:42 ` [PATCH proxmox-backup v3 5/6] config: move node config into pbs-config, including helper tools Christian Ebner
@ 2026-03-12 11:42 ` Christian Ebner
7 siblings, 0 replies; 9+ messages in thread
From: Christian Ebner @ 2026-03-12 11:42 UTC (permalink / raw)
To: pbs-devel
Read the current node proxy config and pass it to the s3 client on
instantiation. The given proxy config is then used for the rest of
the s3 client instance lifetime.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
pbs-datastore/src/datastore.rs | 4 ++--
src/api2/admin/s3.rs | 2 +-
src/api2/config/s3.rs | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/pbs-datastore/src/datastore.rs b/pbs-datastore/src/datastore.rs
index ef378c696..36f6b0c79 100644
--- a/pbs-datastore/src/datastore.rs
+++ b/pbs-datastore/src/datastore.rs
@@ -433,7 +433,7 @@ impl DataStore {
Some(bucket),
self.name().to_owned(),
Some(rate_limiter_options),
- None, //FIXME read from node.cfg
+ pbs_config::node::node_http_proxy_config()?,
);
let s3_client = S3Client::new(options)?;
DatastoreBackend::S3(Arc::new(s3_client))
@@ -2659,7 +2659,7 @@ impl DataStore {
Some(bucket),
datastore_config.name.to_owned(),
Some(rate_limiter_options),
- None, // FIXME read from node.cfg
+ pbs_config::node::node_http_proxy_config()?,
);
let s3_client = S3Client::new(options)
.context("failed to create s3 client")
diff --git a/src/api2/admin/s3.rs b/src/api2/admin/s3.rs
index d3b3b11e6..a739909ee 100644
--- a/src/api2/admin/s3.rs
+++ b/src/api2/admin/s3.rs
@@ -55,7 +55,7 @@ pub async fn check(
Some(bucket),
store_prefix,
None,
- None, // FIXME read from node.cfg once regular datastore operations do as well
+ pbs_config::node::node_http_proxy_config()?,
);
let test_object_key =
diff --git a/src/api2/config/s3.rs b/src/api2/config/s3.rs
index 9f1b4b5f7..e48c637d5 100644
--- a/src/api2/config/s3.rs
+++ b/src/api2/config/s3.rs
@@ -356,7 +356,7 @@ pub async fn list_buckets(
None,
empty_prefix,
None,
- None, // FIXME read from node.cfg once regular datastore operations do as well
+ pbs_config::node::node_http_proxy_config()?,
);
let client = S3Client::new(options).context("client creation failed")?;
let list_buckets_response = client
--
2.47.3
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-03-12 11:43 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-03-12 11:42 [PATCH proxmox{,-backup} v3 0/8] fix #6716: Add support for http proxy configuration for S3 endpoints Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox v3 1/2] http: move http proxy schema from PBS to crate's api types Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox v3 2/2] pbs-api-types: move over NodeConfig and related api type from PBS Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 1/6] pbs-config: use http proxy schema moved to proxmox-http crate Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 2/6] config: inline NodeConfig::validate() to its only call side Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 3/6] config: use moved NodeConfig definitions in pbs-api-types Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 4/6] tools: drop unused from_property_string() helper Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 5/6] config: move node config into pbs-config, including helper tools Christian Ebner
2026-03-12 11:42 ` [PATCH proxmox-backup v3 6/6] fix #6716: pass node http proxy config to s3 backend Christian Ebner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox