feat: dynamic app catalog, Gitea app polish, registry sync
App catalog served from Gitea repos (app-catalog) with 35 apps. Nodes fetch catalog dynamically — new apps appear without frontend rebuild. Test app added and removed to verify pipeline. Gitea manifest updated with internal_port/nginx_proxy for iframe. Updated catalog.json, nginx configs, app session configs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
1147dbd882
commit
3078d4b69e
@@ -214,7 +214,7 @@ pub(super) fn get_health_check_args(app_id: &str, _rpc_pass: &str) -> Vec<String
|
||||
),
|
||||
"ollama" => ("curl -sf http://localhost:11434/ || exit 1", "30s", "3"),
|
||||
"fedimint" => (
|
||||
"curl -sf http://localhost:8174/health || exit 1",
|
||||
"curl -sf http://localhost:8175/ || exit 1",
|
||||
"60s",
|
||||
"3",
|
||||
),
|
||||
@@ -894,8 +894,10 @@ pub(super) async fn get_app_config(
|
||||
None,
|
||||
)
|
||||
}
|
||||
// Gitea binds to 3001 internally. Nginx on port 3000 strips X-Frame-Options
|
||||
// so Gitea works in Archipelago's iframe. See nginx-gitea-iframe.conf.
|
||||
"gitea" => (
|
||||
vec!["3000:3000".to_string(), "2222:22".to_string()],
|
||||
vec!["3001:3000".to_string(), "2222:22".to_string()],
|
||||
vec![
|
||||
"/var/lib/archipelago/gitea/data:/data".to_string(),
|
||||
"/var/lib/archipelago/gitea/config:/etc/gitea".to_string(),
|
||||
@@ -912,6 +914,32 @@ pub(super) async fn get_app_config(
|
||||
None,
|
||||
None,
|
||||
),
|
||||
_ => (vec![], vec![], vec![], None, None),
|
||||
_ => {
|
||||
// Unknown app: try to load config from /var/lib/archipelago/app-configs/{id}.json
|
||||
// This allows dynamic apps from the remote catalog to be installed
|
||||
// without hardcoding their config here.
|
||||
let config_path = format!("/var/lib/archipelago/app-configs/{}.json", app_id);
|
||||
if let Ok(data) = tokio::fs::read_to_string(&config_path).await {
|
||||
if let Ok(cfg) = serde_json::from_str::<serde_json::Value>(&data) {
|
||||
let ports = cfg.get("ports")
|
||||
.and_then(|v| v.as_array())
|
||||
.map(|a| a.iter().filter_map(|v| v.as_str().map(String::from)).collect())
|
||||
.unwrap_or_default();
|
||||
let volumes = cfg.get("volumes")
|
||||
.and_then(|v| v.as_array())
|
||||
.map(|a| a.iter().filter_map(|v| v.as_str().map(String::from)).collect())
|
||||
.unwrap_or_default();
|
||||
let env_vars = cfg.get("env")
|
||||
.and_then(|v| v.as_array())
|
||||
.map(|a| a.iter().filter_map(|v| v.as_str().map(String::from)).collect())
|
||||
.unwrap_or_default();
|
||||
tracing::info!("Loaded dynamic config for app: {}", app_id);
|
||||
return (ports, volumes, env_vars, None, None);
|
||||
}
|
||||
}
|
||||
// No config found — use minimal defaults (container's own EXPOSE/VOLUME)
|
||||
tracing::warn!("No config found for app: {} — using minimal defaults", app_id);
|
||||
(vec![], vec![], vec![], None, None)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user