* [pve-devel] [PATCH proxmox-offline-mirror 0/2 RFC] allow key activation through URL
@ 2025-10-17 6:39 Hannes Laimer
2025-10-17 6:39 ` [pve-devel] [PATCH proxmox-offline-mirror 1/2] helper: allow URL as source for offline key activation Hannes Laimer
2025-10-17 6:39 ` [pve-devel] [PATCH proxmox-offline-mirror 2/2] docs: add section for activating key over HTTP Hannes Laimer
0 siblings, 2 replies; 3+ messages in thread
From: Hannes Laimer @ 2025-10-17 6:39 UTC (permalink / raw)
To: pve-devel
If the medium is served over HTTP we can also load the `.mirror-state`
file over HTTP. This adds support for that.
In case a http server is already setup, additionally requiring mounting
the medium directly anyway, at least for key activation, isn't
necesarry IMHO.
Sending as RFC, since I'm not sure if there's a reason to not allow this
from a security standpoint.
Hannes Laimer (2):
helper: allow URL as source for offline key activation
docs: add section for activating key over HTTP
docs/offline-media.rst | 12 +++++
src/bin/proxmox-offline-mirror-helper.rs | 63 ++++++++++++++++++------
2 files changed, 61 insertions(+), 14 deletions(-)
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
* [pve-devel] [PATCH proxmox-offline-mirror 1/2] helper: allow URL as source for offline key activation
2025-10-17 6:39 [pve-devel] [PATCH proxmox-offline-mirror 0/2 RFC] allow key activation through URL Hannes Laimer
@ 2025-10-17 6:39 ` Hannes Laimer
2025-10-17 6:39 ` [pve-devel] [PATCH proxmox-offline-mirror 2/2] docs: add section for activating key over HTTP Hannes Laimer
1 sibling, 0 replies; 3+ messages in thread
From: Hannes Laimer @ 2025-10-17 6:39 UTC (permalink / raw)
To: pve-devel
If the HTTP server is setup like in our exmaple, `.mirror-state` is
accessible over HTTP. With this the `offline-key` subcommand also
accepts an URL as a source. So instead of reading the `.mirror-state`
file directly from the fs, we'd load it over HTTP if an URL specified.
This removes to need for mounting the medium directly just for key
activation.
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
src/bin/proxmox-offline-mirror-helper.rs | 63 ++++++++++++++++++------
1 file changed, 49 insertions(+), 14 deletions(-)
diff --git a/src/bin/proxmox-offline-mirror-helper.rs b/src/bin/proxmox-offline-mirror-helper.rs
index 07537f0..849465c 100644
--- a/src/bin/proxmox-offline-mirror-helper.rs
+++ b/src/bin/proxmox-offline-mirror-helper.rs
@@ -5,6 +5,8 @@ use std::{collections::HashMap, path::Path};
use anyhow::{Error, bail, format_err};
+use proxmox_http::client::sync::Client;
+use proxmox_http::{HttpClient, HttpOptions, ProxyConfig};
use proxmox_offline_mirror::types::Snapshot;
use proxmox_subscription::{ProductType, SubscriptionInfo};
use proxmox_sys::command::run_command;
@@ -24,6 +26,48 @@ use proxmox_offline_mirror::helpers::tty::{
};
use proxmox_offline_mirror::medium::{self, MediumState, generate_repo_snippet};
+fn load_mirror_state(source: &str) -> Result<MediumState, Error> {
+ if source.starts_with("http://") || source.starts_with("https://") {
+ let state_url = if source.ends_with('/') {
+ format!("{}.mirror-state", source)
+ } else {
+ format!("{}/.mirror-state", source)
+ };
+
+ let options = HttpOptions {
+ user_agent: Some(
+ concat!("proxmox-offline-mirror-helper/", env!("CARGO_PKG_VERSION")).to_string(),
+ ),
+ proxy_config: ProxyConfig::from_proxy_env()?,
+ ..Default::default()
+ };
+ let client = Client::new(options);
+
+ let response = client.get(&state_url, None)?;
+ if !response.status().is_success() {
+ bail!(
+ "Failed to download mirror state from {}: {}",
+ state_url,
+ response.status()
+ );
+ }
+
+ let body: Vec<u8> = response.into_body();
+ serde_json::from_slice(&body).map_err(Error::from)
+ } else {
+ let mountpoint = Path::new(source);
+ if !mountpoint.exists() {
+ bail!("Medium mountpoint doesn't exist.");
+ }
+
+ let mut statefile = mountpoint.to_path_buf();
+ statefile.push(".mirror-state");
+
+ let raw = file_get_contents(&statefile)?;
+ serde_json::from_slice(&raw).map_err(Error::from)
+ }
+}
+
fn set_subscription_key(
product: &ProductType,
subscription: &SubscriptionInfo,
@@ -264,9 +308,9 @@ async fn setup(_param: Value) -> Result<(), Error> {
#[api(
input: {
properties: {
- mountpoint: {
+ source: {
type: String,
- description: "Path to medium mountpoint",
+ description: "Path to medium mountpoint or URL for key activation",
},
product: {
type: ProductType,
@@ -277,7 +321,7 @@ async fn setup(_param: Value) -> Result<(), Error> {
)]
/// Configures and offline subscription key
async fn setup_offline_key(
- mountpoint: String,
+ source: String,
product: Option<ProductType>,
_param: Value,
) -> Result<(), Error> {
@@ -288,17 +332,8 @@ async fn setup_offline_key(
);
}
- let mountpoint = Path::new(&mountpoint);
- if !mountpoint.exists() {
- bail!("Medium mountpoint doesn't exist.");
- }
-
- let mut statefile = mountpoint.to_path_buf();
- statefile.push(".mirror-state");
-
- println!("Loading state from {statefile:?}..");
- let raw = file_get_contents(&statefile)?;
- let state: MediumState = serde_json::from_slice(&raw)?;
+ println!("Loading state from {}..", source);
+ let state = load_mirror_state(&source)?;
println!(
"Last sync timestamp: {}",
epoch_to_rfc3339_utc(state.last_sync)?
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
* [pve-devel] [PATCH proxmox-offline-mirror 2/2] docs: add section for activating key over HTTP
2025-10-17 6:39 [pve-devel] [PATCH proxmox-offline-mirror 0/2 RFC] allow key activation through URL Hannes Laimer
2025-10-17 6:39 ` [pve-devel] [PATCH proxmox-offline-mirror 1/2] helper: allow URL as source for offline key activation Hannes Laimer
@ 2025-10-17 6:39 ` Hannes Laimer
1 sibling, 0 replies; 3+ messages in thread
From: Hannes Laimer @ 2025-10-17 6:39 UTC (permalink / raw)
To: pve-devel
Signed-off-by: Hannes Laimer <h.laimer@proxmox.com>
---
docs/offline-media.rst | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/docs/offline-media.rst b/docs/offline-media.rst
index f080581..7f02ad5 100644
--- a/docs/offline-media.rst
+++ b/docs/offline-media.rst
@@ -108,3 +108,15 @@ Activating an Subscription Key
To activate or update a subscription key offline, either use ``proxmox-offline-mirror-helper
offline-key`` directly or follow the respective step when doing the guided setup via the
``proxmox-offline-mirror-helper setup`` command.
+
+The ``offline-key`` command supports both local mountpoints and HTTP URLs. When using an HTTP
+server (as described in the `Local HTTP Server`_ section), you can activate subscription keys
+directly from the HTTP URL without needing to mount the medium locally:
+
+.. code-block:: console
+
+ proxmox-offline-mirror-helper offline-key --source http://proxmox-offline-mirror.domain.example/
+
+This is particularly useful when the mirror is served over HTTP and you only need to activate
+subscription keys. Other operations like the ``status`` command and repository configuration
+still require a local mountpoint.
--
2.47.3
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-10-17 6:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-10-17 6:39 [pve-devel] [PATCH proxmox-offline-mirror 0/2 RFC] allow key activation through URL Hannes Laimer
2025-10-17 6:39 ` [pve-devel] [PATCH proxmox-offline-mirror 1/2] helper: allow URL as source for offline key activation Hannes Laimer
2025-10-17 6:39 ` [pve-devel] [PATCH proxmox-offline-mirror 2/2] docs: add section for activating key over HTTP Hannes Laimer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox