Compare commits

...

2 Commits

Author SHA1 Message Date
archipelago
d91b858d9b chore: release v1.7.62-alpha 2026-05-17 22:40:36 -04:00
archipelago
19f2125a4d fix(apps): repair stale nginx proxy manager ports 2026-05-17 22:38:04 -04:00
7 changed files with 139 additions and 40 deletions

View File

@ -1,5 +1,12 @@
# Changelog # Changelog
## v1.7.62-alpha (2026-05-18)
- Nginx Proxy Manager start and restart now repair stale Podman containers that still publish the admin UI on host port `81`, which conflicts with host nginx on updated nodes.
- The repair recreates only the stale Nginx Proxy Manager container metadata while preserving `/var/lib/archipelago/nginx-proxy-manager` data and using the current `8081:81`, `8084:80`, and `8444:443` mappings.
- Runtime stale-listener cleanup for Nginx Proxy Manager is shared across start and restart paths so rootless port helper leftovers are still cleared before lifecycle retries.
- Validation passed with `cargo fmt --all --check --manifest-path core/Cargo.toml` and `cargo check -p archipelago --manifest-path core/Cargo.toml`.
## v1.7.61-alpha (2026-05-18) ## v1.7.61-alpha (2026-05-18)
- Multi-container stack installs now keep their app card in the `Installing` state for up to 20 minutes while dependency containers are being pulled and prepared. - Multi-container stack installs now keep their app card in the `Installing` state for up to 20 minutes while dependency containers are being pulled and prepared.

View File

@ -1,6 +1,6 @@
[package] [package]
name = "archipelago" name = "archipelago"
version = "1.7.61-alpha" version = "1.7.62-alpha"
edition = "2021" edition = "2021"
description = "Archipelago Bitcoin Node OS - Native backend" description = "Archipelago Bitcoin Node OS - Native backend"
authors = ["Archipelago Team"] authors = ["Archipelago Team"]

View File

@ -1,4 +1,7 @@
use super::config::{get_containers_for_app, get_data_dirs_for_app, is_valid_docker_image}; use super::config::{
get_app_capabilities, get_containers_for_app, get_data_dirs_for_app, get_health_check_args,
get_memory_limit, is_valid_docker_image,
};
use super::dependencies::ordered_containers_for_start; use super::dependencies::ordered_containers_for_start;
use super::install::install_log; use super::install::install_log;
use super::validation::validate_app_id; use super::validation::validate_app_id;
@ -863,11 +866,98 @@ async fn repair_before_package_start(container_name: &str) {
repair_nextcloud_dirs().await; repair_nextcloud_dirs().await;
cleanup_stale_pasta_port("8085").await; cleanup_stale_pasta_port("8085").await;
} }
"nginx-proxy-manager" => repair_nginx_proxy_manager_container().await,
"gitea" => cleanup_gitea_stale_ports().await, "gitea" => cleanup_gitea_stale_ports().await,
_ => {} _ => {}
} }
} }
async fn repair_nginx_proxy_manager_container() {
if !nginx_proxy_manager_has_legacy_admin_port().await {
cleanup_nginx_proxy_manager_ports().await;
return;
}
install_log(
"START REPAIR: nginx-proxy-manager - recreating stale container using host port 8081",
)
.await;
let _ = podman_control(&["rm", "-f", "nginx-proxy-manager"]).await;
cleanup_nginx_proxy_manager_ports().await;
if let Err(err) = recreate_nginx_proxy_manager_container().await {
tracing::warn!(error = %err, "failed to recreate stale nginx-proxy-manager container");
}
}
async fn nginx_proxy_manager_has_legacy_admin_port() -> bool {
let Ok(output) = podman_control(&["port", "nginx-proxy-manager", "81/tcp"]).await else {
return false;
};
if !output.status.success() {
return false;
}
String::from_utf8_lossy(&output.stdout).lines().any(|line| {
line.rsplit(':')
.next()
.is_some_and(|port| port.trim() == "81")
})
}
async fn recreate_nginx_proxy_manager_container() -> Result<()> {
tokio::process::Command::new("sudo")
.args([
"mkdir",
"-p",
"/var/lib/archipelago/nginx-proxy-manager/data",
"/var/lib/archipelago/nginx-proxy-manager/letsencrypt",
])
.output()
.await
.context("failed to create nginx-proxy-manager data directories")?;
let image = crate::container::image_versions::pinned_image_for_app("nginx-proxy-manager")
.unwrap_or_else(|| "docker.io/jc21/nginx-proxy-manager:latest".to_string());
let mut args = vec![
"run".to_string(),
"-d".to_string(),
"--name".to_string(),
"nginx-proxy-manager".to_string(),
"--restart=unless-stopped".to_string(),
"--network=slirp4netns:allow_host_loopback=true".to_string(),
"--cap-drop=ALL".to_string(),
"--security-opt=no-new-privileges:true".to_string(),
"--pids-limit=4096".to_string(),
];
args.extend(get_app_capabilities("nginx-proxy-manager"));
args.extend([
"-p".to_string(),
"8081:81".to_string(),
"-p".to_string(),
"8084:80".to_string(),
"-p".to_string(),
"8444:443".to_string(),
"-v".to_string(),
"/var/lib/archipelago/nginx-proxy-manager/data:/data".to_string(),
"-v".to_string(),
"/var/lib/archipelago/nginx-proxy-manager/letsencrypt:/etc/letsencrypt".to_string(),
"--memory".to_string(),
get_memory_limit("nginx-proxy-manager").to_string(),
"--cpus=2".to_string(),
]);
args.extend(get_health_check_args("nginx-proxy-manager", ""));
args.push(image);
let refs = args.iter().map(String::as_str).collect::<Vec<_>>();
let output = podman_control(&refs).await?;
if !output.status.success() {
anyhow::bail!(
"podman run nginx-proxy-manager failed: {}",
String::from_utf8_lossy(&output.stderr).trim()
);
}
Ok(())
}
async fn ensure_runtime_host_port_listener(container_name: &str) -> Result<()> { async fn ensure_runtime_host_port_listener(container_name: &str) -> Result<()> {
let Some(port) = runtime_required_host_port(container_name) else { let Some(port) = runtime_required_host_port(container_name) else {
return Ok(()); return Ok(());
@ -1075,15 +1165,17 @@ async fn cleanup_start_conflict(container_name: &str, stderr: &str) {
"homeassistant" | "home-assistant" => cleanup_stale_pasta_port("8123").await, "homeassistant" | "home-assistant" => cleanup_stale_pasta_port("8123").await,
"vaultwarden" => cleanup_stale_pasta_port("8082").await, "vaultwarden" => cleanup_stale_pasta_port("8082").await,
"nextcloud" => cleanup_stale_pasta_port("8085").await, "nextcloud" => cleanup_stale_pasta_port("8085").await,
"nginx-proxy-manager" => { "nginx-proxy-manager" => cleanup_nginx_proxy_manager_ports().await,
cleanup_stale_pasta_port("8081").await;
cleanup_stale_pasta_port("8084").await;
cleanup_stale_pasta_port("8444").await;
}
_ => {} _ => {}
} }
} }
async fn cleanup_nginx_proxy_manager_ports() {
cleanup_stale_pasta_port("8081").await;
cleanup_stale_pasta_port("8084").await;
cleanup_stale_pasta_port("8444").await;
}
async fn cleanup_stale_pasta_port(port: &str) { async fn cleanup_stale_pasta_port(port: &str) {
let kill_listener = format!( let kill_listener = format!(
"ss -ltnp 'sport = :{}' 2>/dev/null | sed -n 's/.*pid=\\([0-9]*\\).*/\\1/p' | xargs -r kill 2>/dev/null || true", "ss -ltnp 'sport = :{}' 2>/dev/null | sed -n 's/.*pid=\\([0-9]*\\).*/\\1/p' | xargs -r kill 2>/dev/null || true",

View File

@ -1,12 +1,12 @@
{ {
"name": "neode-ui", "name": "neode-ui",
"version": "1.7.61-alpha", "version": "1.7.62-alpha",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "neode-ui", "name": "neode-ui",
"version": "1.7.61-alpha", "version": "1.7.62-alpha",
"dependencies": { "dependencies": {
"@types/dompurify": "^3.0.5", "@types/dompurify": "^3.0.5",
"@vue-leaflet/vue-leaflet": "^0.10.1", "@vue-leaflet/vue-leaflet": "^0.10.1",

View File

@ -1,7 +1,7 @@
{ {
"name": "neode-ui", "name": "neode-ui",
"private": true, "private": true,
"version": "1.7.61-alpha", "version": "1.7.62-alpha",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "./start-dev.sh", "start": "./start-dev.sh",

View File

@ -1,28 +1,28 @@
{ {
"version": "1.7.61-alpha", "version": "1.7.62-alpha",
"release_date": "2026-05-18", "release_date": "2026-05-17",
"changelog": [ "changelog": [
"Multi-container stack installs now keep their app card in the `Installing` state for up to 20 minutes while dependency containers are being pulled and prepared.", "Nginx Proxy Manager start and restart now repair stale Podman containers that still publish the admin UI on host port `81`, which conflicts with host nginx on updated nodes.",
"BTCPay Server installs no longer appear to vanish or fail after two minutes while Postgres and NBXplorer are still being created before the primary `btcpay-server` container exists.", "The repair recreates only the stale Nginx Proxy Manager container metadata while preserving `/var/lib/archipelago/nginx-proxy-manager` data and using the current `8081:81`, `8084:80`, and `8444:443` mappings.",
"The stale-transition escape hatch remains short for start, stop, restart, update, and removal operations, so genuinely wedged lifecycle actions still recover quickly.", "Runtime stale-listener cleanup for Nginx Proxy Manager is shared across start and restart paths so rootless port helper leftovers are still cleared before lifecycle retries.",
"Live validation on `100.70.96.88` confirmed BTCPay Server completed installation and responds on port `23000` with the expected HTTP redirect." "Validation passed with `cargo fmt --all --check --manifest-path core/Cargo.toml` and `cargo check -p archipelago --manifest-path core/Cargo.toml`."
], ],
"components": [ "components": [
{ {
"name": "archipelago", "name": "archipelago",
"current_version": "1.7.61-alpha", "current_version": "1.7.62-alpha",
"new_version": "1.7.61-alpha", "new_version": "1.7.62-alpha",
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago", "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.62-alpha/archipelago",
"sha256": "5b08f66aa9a685475b86cdcbabe96c3132f3cc0e72d8daaeb0ddd52a01ca87b6", "sha256": "5b08f66aa9a685475b86cdcbabe96c3132f3cc0e72d8daaeb0ddd52a01ca87b6",
"size_bytes": 42738544 "size_bytes": 42738544
}, },
{ {
"name": "archipelago-frontend-1.7.61-alpha.tar.gz", "name": "archipelago-frontend-1.7.62-alpha.tar.gz",
"current_version": "1.7.61-alpha", "current_version": "1.7.62-alpha",
"new_version": "1.7.61-alpha", "new_version": "1.7.62-alpha",
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago-frontend-1.7.61-alpha.tar.gz", "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.62-alpha/archipelago-frontend-1.7.62-alpha.tar.gz",
"sha256": "80c5bef31460ece8c1416a8f4e5e88626d1ef4103d40fec0e4872aafb3332dcc", "sha256": "5923368c4cd00cfcc40c0fc2eccc9d086b5ff450ae9da3e09bede48d434dc95e",
"size_bytes": 166470847 "size_bytes": 166467764
} }
] ]
} }

View File

@ -1,28 +1,28 @@
{ {
"version": "1.7.61-alpha", "version": "1.7.62-alpha",
"release_date": "2026-05-18", "release_date": "2026-05-17",
"changelog": [ "changelog": [
"Multi-container stack installs now keep their app card in the `Installing` state for up to 20 minutes while dependency containers are being pulled and prepared.", "Nginx Proxy Manager start and restart now repair stale Podman containers that still publish the admin UI on host port `81`, which conflicts with host nginx on updated nodes.",
"BTCPay Server installs no longer appear to vanish or fail after two minutes while Postgres and NBXplorer are still being created before the primary `btcpay-server` container exists.", "The repair recreates only the stale Nginx Proxy Manager container metadata while preserving `/var/lib/archipelago/nginx-proxy-manager` data and using the current `8081:81`, `8084:80`, and `8444:443` mappings.",
"The stale-transition escape hatch remains short for start, stop, restart, update, and removal operations, so genuinely wedged lifecycle actions still recover quickly.", "Runtime stale-listener cleanup for Nginx Proxy Manager is shared across start and restart paths so rootless port helper leftovers are still cleared before lifecycle retries.",
"Live validation on `100.70.96.88` confirmed BTCPay Server completed installation and responds on port `23000` with the expected HTTP redirect." "Validation passed with `cargo fmt --all --check --manifest-path core/Cargo.toml` and `cargo check -p archipelago --manifest-path core/Cargo.toml`."
], ],
"components": [ "components": [
{ {
"name": "archipelago", "name": "archipelago",
"current_version": "1.7.61-alpha", "current_version": "1.7.62-alpha",
"new_version": "1.7.61-alpha", "new_version": "1.7.62-alpha",
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago", "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.62-alpha/archipelago",
"sha256": "5b08f66aa9a685475b86cdcbabe96c3132f3cc0e72d8daaeb0ddd52a01ca87b6", "sha256": "5b08f66aa9a685475b86cdcbabe96c3132f3cc0e72d8daaeb0ddd52a01ca87b6",
"size_bytes": 42738544 "size_bytes": 42738544
}, },
{ {
"name": "archipelago-frontend-1.7.61-alpha.tar.gz", "name": "archipelago-frontend-1.7.62-alpha.tar.gz",
"current_version": "1.7.61-alpha", "current_version": "1.7.62-alpha",
"new_version": "1.7.61-alpha", "new_version": "1.7.62-alpha",
"download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago-frontend-1.7.61-alpha.tar.gz", "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.62-alpha/archipelago-frontend-1.7.62-alpha.tar.gz",
"sha256": "80c5bef31460ece8c1416a8f4e5e88626d1ef4103d40fec0e4872aafb3332dcc", "sha256": "5923368c4cd00cfcc40c0fc2eccc9d086b5ff450ae9da3e09bede48d434dc95e",
"size_bytes": 166470847 "size_bytes": 166467764
} }
] ]
} }