fix: BUILD_VERSION from Cargo.toml, kiosk scaling, new apps, Rust warnings
Some checks failed
Build Archipelago ISO (dev) / build-iso (push) Has been cancelled

Critical:
- BUILD_VERSION was hardcoded as "1.3.0-alpha" — now reads from Cargo.toml
  This caused ALL ISOs to show v1.3.0 regardless of actual binary version

Kiosk:
- Remove --disable-gpu flags (broke display scaling on some monitors)
- Add --start-fullscreen --window-size for reliable fullscreen

New apps:
- Nostr VPN, FIPS, Routstr, noStrudel, BotFights, NWNN, 484 Kitchen,
  Call the Operator, Arch Presentation, Syntropy Institute, T-0

Rust: suppress dead_code and unused_assignments warnings

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-04-03 00:35:52 +01:00
parent 8814b03e33
commit 449f47da49
15 changed files with 246 additions and 9 deletions

View File

@@ -124,6 +124,12 @@ pub(super) fn get_app_capabilities(app_id: &str) -> Vec<String> {
"--cap-add=DAC_OVERRIDE".to_string(),
"--cap-add=NET_BIND_SERVICE".to_string(),
],
// Nostr VPN and FIPS: mesh networking daemons need TUN + NET_ADMIN
// Note: --device=/dev/net/tun is added separately in install.rs
"nostr-vpn" | "fips" => vec![
"--cap-add=NET_ADMIN".to_string(),
"--cap-add=NET_RAW".to_string(),
],
// Default: standard capabilities for rootless podman containers
// Most apps need file ownership + port binding to function correctly
_ => vec![
@@ -239,6 +245,13 @@ pub(super) fn get_health_check_args(app_id: &str, _rpc_pass: &str) -> Vec<String
"30s",
"3",
),
"routstr" => (
"curl -sf http://localhost:8000/v1/models || exit 1",
"30s",
"3",
),
"nostr-vpn" => ("nvpn status || exit 1", "30s", "3"),
"fips" => ("fipsctl status || exit 1", "30s", "3"),
_ => return vec![],
};
@@ -279,6 +292,9 @@ pub(super) fn get_memory_limit(app_id: &str) -> &'static str {
"dwn" => "256m",
"portainer" => "256m",
"nostr-rs-relay" | "nostr-relay" => "256m",
"routstr" => "512m",
"nostr-vpn" => "256m",
"fips" => "256m",
"nginx-proxy-manager" => "256m",
// Databases
"archy-btcpay-db" | "archy-mempool-db" | "mysql-mempool" => "512m",
@@ -343,6 +359,9 @@ pub(super) fn all_container_names(package_id: &str) -> Vec<String> {
"penpot-postgres".into(), "penpot-valkey".into(),
"penpot-backend".into(), "penpot-exporter".into(), "penpot-frontend".into(),
],
"nostr-vpn" => vec!["nostr-vpn".into(), "archy-nostr-vpn".into()],
"fips" => vec!["fips".into(), "archy-fips".into()],
"routstr" => vec!["routstr".into(), "archy-routstr".into()],
// Default: exact name + archy- prefix
_ => vec![base, archy],
}
@@ -407,6 +426,21 @@ fn read_secret(name: &str, default: &str) -> String {
.unwrap_or_else(|_| default.to_string())
}
/// Read the node-level Nostr secret key (hex) for identity-aware apps.
/// Returns empty string if not yet generated.
fn read_nostr_secret_hex() -> String {
std::fs::read_to_string("/var/lib/archipelago/identity/nostr_secret")
.map(|s| s.trim().to_string())
.unwrap_or_default()
}
/// Read the node-level Nostr public key (hex).
fn read_nostr_pubkey_hex() -> String {
std::fs::read_to_string("/var/lib/archipelago/identity/nostr_pub")
.map(|s| s.trim().to_string())
.unwrap_or_default()
}
/// Get app-specific configuration
/// Returns: (ports, volumes, env_vars, custom_command, custom_args)
pub(super) async fn get_app_config(
@@ -771,6 +805,62 @@ pub(super) async fn get_app_config(
None,
None,
),
"routstr" => {
let nsec = read_nostr_secret_hex();
let mut env = vec![
"DATABASE_URL=sqlite:///app/data/keys.db".to_string(),
];
if !nsec.is_empty() {
env.push(format!("NSEC={}", nsec));
env.push(format!("NOSTR_PUBKEY={}", read_nostr_pubkey_hex()));
}
(
vec!["8200:8000".to_string()],
vec!["/var/lib/archipelago/routstr:/app/data".to_string()],
env,
None,
None,
)
}
"nostr-vpn" => {
let nsec = read_nostr_secret_hex();
let mut env = vec![];
if !nsec.is_empty() {
env.push(format!("NOSTR_SECRET={}", nsec));
env.push(format!("NOSTR_PUBKEY={}", read_nostr_pubkey_hex()));
}
(
vec!["51820:51820/udp".to_string()],
vec!["/var/lib/archipelago/nostr-vpn:/root/.config/nvpn".to_string()],
env,
None,
Some(vec![
"start".to_string(),
"--daemon".to_string(),
]),
)
}
"fips" => {
let nsec = read_nostr_secret_hex();
let mut env = vec![];
if !nsec.is_empty() {
env.push(format!("FIPS_NOSTR_SECRET={}", nsec));
env.push(format!("FIPS_NOSTR_PUBKEY={}", read_nostr_pubkey_hex()));
}
(
vec![
"2121:2121/udp".to_string(),
"8443:8443".to_string(),
],
vec![
"/var/lib/archipelago/fips/config:/etc/fips".to_string(),
"/var/lib/archipelago/fips/run:/run/fips".to_string(),
],
env,
None,
None,
)
}
"dwn" => (
vec!["3100:3000".to_string()],
vec!["/var/lib/archipelago/dwn:/dwn/data".to_string()],

View File

@@ -225,6 +225,11 @@ impl RpcHandler {
}
}
// TUN device for mesh networking apps
if matches!(package_id, "nostr-vpn" | "fips") {
run_args.push("--device=/dev/net/tun");
}
// Create data directories
self.create_data_dirs(package_id, &volumes).await;
@@ -259,6 +264,35 @@ impl RpcHandler {
}
}
// Pre-install: write Nostr identity key files for headless Nostr-aware apps
if matches!(package_id, "nostr-vpn" | "fips") {
let nostr_secret = std::fs::read_to_string("/var/lib/archipelago/identity/nostr_secret")
.map(|s| s.trim().to_string())
.unwrap_or_default();
if !nostr_secret.is_empty() {
let key_dir = match package_id {
"nostr-vpn" => "/var/lib/archipelago/nostr-vpn",
"fips" => "/var/lib/archipelago/fips/config",
_ => unreachable!(),
};
let key_path = match package_id {
"nostr-vpn" => format!("{}/nostr_secret", key_dir),
"fips" => format!("{}/fips.key", key_dir),
_ => unreachable!(),
};
tokio::fs::create_dir_all(key_dir).await.ok();
tokio::fs::write(&key_path, &nostr_secret).await.ok();
// Restrict permissions on key file
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
let perms = std::fs::Permissions::from_mode(0o600);
std::fs::set_permissions(&key_path, perms).ok();
}
info!("Wrote Nostr identity key for {}", package_id);
}
}
// Port mappings (skip for host-network containers)
if !is_tailscale {
for port in &ports {