Update Fedimint configuration and enhance onboarding process

- Upgraded Fedimint version to v0.10.0 in docker-compose.yml and manifest.yml, adding support for the built-in Guardian UI.
- Modified .gitignore to exclude deploy-config.sh script.
- Enhanced onboarding process in AuthManager to persist onboarding state and validate password strength during user setup.
- Updated API to handle onboarding completion and password change requests, ensuring a smoother user experience.
- Improved configuration management to support Nostr discovery and Tor proxy settings, enhancing node identity features.
This commit is contained in:
Dorian
2026-02-17 15:03:34 +00:00
parent 6035c93289
commit 1073d9fd2c
73 changed files with 5870 additions and 478 deletions

View File

@@ -53,11 +53,15 @@ impl DockerPackageScanner {
let mut ui_containers: HashMap<String, String> = HashMap::new();
for container in &containers {
if container.name.ends_with("-ui") {
// Map bitcoin-ui -> bitcoin, lnd-ui -> lnd
// Map fedimint-ui -> fedimint, lnd-ui -> lnd (normalize archy- prefix for lookup)
let parent_app = container.name.strip_suffix("-ui").unwrap_or(&container.name);
let canonical_id = parent_app
.strip_prefix("archy-")
.unwrap_or(parent_app)
.to_string();
if !container.ports.is_empty() {
if let Some(ui_address) = extract_lan_address(&container.ports) {
ui_containers.insert(parent_app.to_string(), ui_address);
ui_containers.insert(canonical_id, ui_address);
}
}
}
@@ -109,6 +113,14 @@ impl DockerPackageScanner {
// But web UI is always on port 8240
debug!("Tailscale detected, using port 8240");
Some("http://localhost:8240".to_string())
} else if app_id == "fedimint" {
// Fedimint built-in Guardian UI on port 8175
debug!("Using fedimint built-in Guardian UI: http://localhost:8175");
Some("http://localhost:8175".to_string())
} else if app_id == "mempool-electrs" || app_id == "electrs" {
// Electrs UI runs on host at port 50002
debug!("Using electrs-ui for mempool-electrs: http://localhost:50002");
Some("http://localhost:50002".to_string())
} else {
// Extract port from the main container
extract_lan_address(&container.ports)
@@ -119,6 +131,8 @@ impl DockerPackageScanner {
// Convert container state to package/service state
let (package_state, service_status) = convert_state(&container.state);
let tor_address = read_tor_address(&app_id);
let package = PackageDataEntry {
state: package_state.clone(),
static_files: StaticFiles {
@@ -143,11 +157,11 @@ impl DockerPackageScanner {
donation_url: None,
author: Some("Archipelago".to_string()),
website: lan_address.clone(),
interfaces: if lan_address.is_some() {
interfaces: if lan_address.is_some() || tor_address.is_some() {
Some(Interfaces {
main: Some(MainInterface {
ui: Some("true".to_string()),
tor_config: None,
tor_config: tor_address.clone(),
lan_config: None,
}),
})
@@ -159,13 +173,17 @@ impl DockerPackageScanner {
current_dependents: HashMap::new(),
current_dependencies: HashMap::new(),
last_backup: None,
interface_addresses: if let Some(addr) = lan_address {
interface_addresses: if lan_address.is_some() || tor_address.is_some() {
let mut addresses = HashMap::new();
// Only include tor_address if we have a real v3 .onion (not placeholder)
let tor = tor_address
.filter(|s| is_real_onion_address(s))
.unwrap_or_default();
addresses.insert(
"main".to_string(),
InterfaceAddress {
tor_address: format!("{}.onion", app_id),
lan_address: Some(addr),
tor_address: tor,
lan_address: lan_address,
},
);
addresses
@@ -227,7 +245,7 @@ fn get_app_metadata(app_id: &str) -> AppMetadata {
"fedimint" => AppMetadata {
title: "Fedimint".to_string(),
description: "Federated Bitcoin mint".to_string(),
icon: "/assets/img/icon-fedimint.jpeg".to_string(),
icon: "/assets/img/app-icons/fedimint.png".to_string(),
repo: "https://github.com/fedimint/fedimint".to_string(),
},
"morphos" | "morphos-server" => AppMetadata {
@@ -248,6 +266,12 @@ fn get_app_metadata(app_id: &str) -> AppMetadata {
icon: "/assets/img/app-icons/mempool.webp".to_string(),
repo: "https://github.com/mempool/mempool".to_string(),
},
"mempool-electrs" | "electrs" => AppMetadata {
title: "Electrs".to_string(),
description: "Electrum protocol indexer for Bitcoin. Powers Mempool and other Electrum clients.".to_string(),
icon: "/assets/img/app-icons/electrs.svg".to_string(),
repo: "https://github.com/romanz/electrs".to_string(),
},
"ollama" => AppMetadata {
title: "Ollama".to_string(),
description: "Run large language models locally".to_string(),
@@ -347,6 +371,40 @@ fn get_app_metadata(app_id: &str) -> AppMetadata {
}
}
/// Map app_id to Tor hidden service directory name.
/// "archipelago" is the main web UI (nginx port 80).
/// Supports container names from deploy (archy-*, btcpay-server, etc.).
fn tor_service_name(app_id: &str) -> Option<&'static str> {
match app_id {
"archipelago" => Some("archipelago"),
"lnd" | "lnd-ui" => Some("lnd"),
"btcpay" | "btcpay-server" | "btcpayserver" => Some("btcpay"),
"mempool" | "mempool-web" | "mempool-frontend" => Some("mempool"),
"fedimint" => Some("fedimint"),
_ => None,
}
}
/// V3 onion addresses are 56 base32 chars + ".onion". Placeholders like "btcpay.onion" are not real.
fn is_real_onion_address(s: &str) -> bool {
s.ends_with(".onion") && s.len() >= 60 && s.len() <= 70
}
/// Read real .onion address from Tor hidden service hostname file.
/// Service name "archipelago" is for the main web UI (nginx port 80).
/// Uses TOR_DATA_DIR env var if set, else /var/lib/archipelago/tor.
pub fn read_tor_address(app_id: &str) -> Option<String> {
let service = tor_service_name(app_id)?;
let base = std::env::var("TOR_DATA_DIR").unwrap_or_else(|_| "/var/lib/archipelago/tor".to_string());
let path = std::path::Path::new(&base)
.join(format!("hidden_service_{}", service))
.join("hostname");
std::fs::read_to_string(&path)
.ok()
.map(|s| s.trim().to_string())
.filter(|s| s.ends_with(".onion") && !s.is_empty())
}
fn extract_lan_address(ports: &[String]) -> Option<String> {
for port_str in ports {
// Parse port strings like "0.0.0.0:18443->18443/tcp" or "0.0.0.0:18443-18444->18443-18444/tcp"