feat: IndeedHub multi-container stack installer
Installs all 7 containers (postgres, redis, minio, relay, api, ffmpeg, frontend) on indeedhub-net with proper env vars and volumes. Fixes pull timeout to cover stderr reader. Catalog registry set to 23.182.128.160:3000. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
6ff347a503
commit
f1243c62e4
@ -87,6 +87,9 @@ impl RpcHandler {
|
|||||||
if matches!(package_id, "mempool" | "mempool-web") {
|
if matches!(package_id, "mempool" | "mempool-web") {
|
||||||
return self.install_mempool_stack().await;
|
return self.install_mempool_stack().await;
|
||||||
}
|
}
|
||||||
|
if package_id == "indeedhub" {
|
||||||
|
return self.install_indeedhub_stack().await;
|
||||||
|
}
|
||||||
|
|
||||||
// Dependency checks
|
// Dependency checks
|
||||||
let deps = detect_running_deps().await?;
|
let deps = detect_running_deps().await?;
|
||||||
|
|||||||
@ -707,4 +707,178 @@ impl RpcHandler {
|
|||||||
"container_id": String::from_utf8_lossy(&run.stdout).trim().to_string(),
|
"container_id": String::from_utf8_lossy(&run.stdout).trim().to_string(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Install the IndeedHub multi-container stack.
|
||||||
|
pub(super) async fn install_indeedhub_stack(&self) -> Result<serde_json::Value> {
|
||||||
|
|
||||||
|
let registry = crate::container::registry::load_registries(&self.config.data_dir)
|
||||||
|
.await
|
||||||
|
.unwrap_or_default()
|
||||||
|
.registries
|
||||||
|
.into_iter()
|
||||||
|
.find(|r| r.enabled)
|
||||||
|
.map(|r| r.url)
|
||||||
|
.unwrap_or_else(|| "23.182.128.160:3000/lfg2025".to_string());
|
||||||
|
|
||||||
|
let user_tmp = format!(
|
||||||
|
"{}/.local/share/containers/tmp",
|
||||||
|
std::env::var("HOME").unwrap_or_else(|_| "/home/archipelago".to_string())
|
||||||
|
);
|
||||||
|
let _ = std::fs::create_dir_all(&user_tmp);
|
||||||
|
|
||||||
|
install_log("INSTALL START: indeedhub stack").await;
|
||||||
|
info!("Installing IndeedHub stack from {}", registry);
|
||||||
|
|
||||||
|
// Pull all images
|
||||||
|
let images = [
|
||||||
|
format!("{}/postgres:16.13-alpine", registry),
|
||||||
|
format!("{}/redis:7.4.8-alpine", registry),
|
||||||
|
format!("{}/minio:RELEASE.2024-11-07T00-52-20Z", registry),
|
||||||
|
format!("{}/nostr-rs-relay:0.9.0", registry),
|
||||||
|
format!("{}/indeedhub-api:1.0.0", registry),
|
||||||
|
format!("{}/indeedhub-ffmpeg:1.0.0", registry),
|
||||||
|
format!("{}/indeedhub:1.0.0", registry),
|
||||||
|
];
|
||||||
|
|
||||||
|
for img in &images {
|
||||||
|
info!("Pulling {}", img);
|
||||||
|
let status = tokio::process::Command::new("podman")
|
||||||
|
.args(["pull", img, "--tls-verify=false"])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.status()
|
||||||
|
.await;
|
||||||
|
if !status.map(|s| s.success()).unwrap_or(false) {
|
||||||
|
tracing::warn!("Failed to pull {}", img);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create indeedhub-net
|
||||||
|
let _ = tokio::process::Command::new("podman")
|
||||||
|
.args(["network", "create", "indeedhub-net"])
|
||||||
|
.status()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// Generate secrets
|
||||||
|
let db_pass = super::config::read_or_generate_secret("indeedhub-db-password").await;
|
||||||
|
let jwt_secret = super::config::read_or_generate_secret("indeedhub-jwt").await;
|
||||||
|
let minio_user = "indeeadmin";
|
||||||
|
let minio_pass = super::config::read_or_generate_secret("indeedhub-minio-password").await;
|
||||||
|
|
||||||
|
// 1. Postgres
|
||||||
|
let _ = tokio::process::Command::new("podman")
|
||||||
|
.args(["run", "-d", "--name", "indeedhub-postgres",
|
||||||
|
"--network", "indeedhub-net", "--network-alias", "postgres",
|
||||||
|
"--restart", "unless-stopped",
|
||||||
|
"-e", &format!("POSTGRES_DB=indeedhub"),
|
||||||
|
"-e", &format!("POSTGRES_USER=indeedhub"),
|
||||||
|
"-e", &format!("POSTGRES_PASSWORD={}", db_pass),
|
||||||
|
"-v", "indeedhub-postgres-data:/var/lib/postgresql/data",
|
||||||
|
&format!("{}/postgres:16.13-alpine", registry)])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.status().await;
|
||||||
|
|
||||||
|
// 2. Redis
|
||||||
|
let _ = tokio::process::Command::new("podman")
|
||||||
|
.args(["run", "-d", "--name", "indeedhub-redis",
|
||||||
|
"--network", "indeedhub-net", "--network-alias", "redis",
|
||||||
|
"--restart", "unless-stopped",
|
||||||
|
"-v", "indeedhub-redis-data:/data",
|
||||||
|
&format!("{}/redis:7.4.8-alpine", registry)])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.status().await;
|
||||||
|
|
||||||
|
// 3. MinIO
|
||||||
|
let _ = tokio::process::Command::new("podman")
|
||||||
|
.args(["run", "-d", "--name", "indeedhub-minio",
|
||||||
|
"--network", "indeedhub-net", "--network-alias", "minio",
|
||||||
|
"--restart", "unless-stopped",
|
||||||
|
"-e", &format!("MINIO_ROOT_USER={}", minio_user),
|
||||||
|
"-e", &format!("MINIO_ROOT_PASSWORD={}", minio_pass),
|
||||||
|
"-v", "indeedhub-minio-data:/data",
|
||||||
|
&format!("{}/minio:RELEASE.2024-11-07T00-52-20Z", registry),
|
||||||
|
"server", "/data"])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.status().await;
|
||||||
|
|
||||||
|
// 4. Nostr relay
|
||||||
|
let _ = tokio::process::Command::new("podman")
|
||||||
|
.args(["run", "-d", "--name", "indeedhub-relay",
|
||||||
|
"--network", "indeedhub-net", "--network-alias", "relay",
|
||||||
|
"--restart", "unless-stopped",
|
||||||
|
"-v", "indeedhub-relay-data:/usr/src/app/db",
|
||||||
|
&format!("{}/nostr-rs-relay:0.9.0", registry)])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.status().await;
|
||||||
|
|
||||||
|
// 5. API
|
||||||
|
let _ = tokio::process::Command::new("podman")
|
||||||
|
.args(["run", "-d", "--name", "indeedhub-api",
|
||||||
|
"--network", "indeedhub-net", "--network-alias", "api",
|
||||||
|
"--restart", "unless-stopped",
|
||||||
|
"-e", "PORT=4000",
|
||||||
|
"-e", &format!("DATABASE_HOST=postgres"),
|
||||||
|
"-e", &format!("DATABASE_USER=indeedhub"),
|
||||||
|
"-e", &format!("DATABASE_PASSWORD={}", db_pass),
|
||||||
|
"-e", &format!("DATABASE_NAME=indeedhub"),
|
||||||
|
"-e", &format!("REDIS_HOST=redis"),
|
||||||
|
"-e", &format!("S3_ENDPOINT=http://minio:9000"),
|
||||||
|
"-e", &format!("AWS_ACCESS_KEY={}", minio_user),
|
||||||
|
"-e", &format!("AWS_SECRET_KEY={}", minio_pass),
|
||||||
|
"-e", &format!("S3_PUBLIC_BUCKET_NAME=indeedhub-public"),
|
||||||
|
"-e", &format!("S3_PUBLIC_BUCKET_URL=/storage"),
|
||||||
|
"-e", &format!("NOSTR_JWT_SECRET={}", jwt_secret),
|
||||||
|
"-e", "ENVIRONMENT=production",
|
||||||
|
&format!("{}/indeedhub-api:1.0.0", registry)])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.status().await;
|
||||||
|
|
||||||
|
// 6. FFmpeg worker
|
||||||
|
let _ = tokio::process::Command::new("podman")
|
||||||
|
.args(["run", "-d", "--name", "indeedhub-ffmpeg",
|
||||||
|
"--network", "indeedhub-net",
|
||||||
|
"--restart", "unless-stopped",
|
||||||
|
"-e", &format!("DATABASE_HOST=postgres"),
|
||||||
|
"-e", &format!("DATABASE_USER=indeedhub"),
|
||||||
|
"-e", &format!("DATABASE_PASSWORD={}", db_pass),
|
||||||
|
"-e", &format!("DATABASE_NAME=indeedhub"),
|
||||||
|
"-e", &format!("QUEUE_HOST=redis"),
|
||||||
|
"-e", &format!("S3_ENDPOINT=http://minio:9000"),
|
||||||
|
"-e", &format!("AWS_ACCESS_KEY={}", minio_user),
|
||||||
|
"-e", &format!("AWS_SECRET_KEY={}", minio_pass),
|
||||||
|
"-e", &format!("AWS_REGION=us-east-1"),
|
||||||
|
"-e", &format!("S3_PUBLIC_BUCKET_NAME=indeedhub-public"),
|
||||||
|
"-e", "ENVIRONMENT=production",
|
||||||
|
"-e", "AES_MASTER_SECRET=0123456789abcdef0123456789abcdef",
|
||||||
|
&format!("{}/indeedhub-ffmpeg:1.0.0", registry)])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.status().await;
|
||||||
|
|
||||||
|
// Wait for backend services to start
|
||||||
|
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||||
|
|
||||||
|
// 7. Frontend (nginx)
|
||||||
|
let run = tokio::process::Command::new("podman")
|
||||||
|
.args(["run", "-d", "--name", "indeedhub",
|
||||||
|
"--network", "indeedhub-net",
|
||||||
|
"--restart", "unless-stopped",
|
||||||
|
"-p", "7778:7777",
|
||||||
|
&format!("{}/indeedhub:1.0.0", registry)])
|
||||||
|
.env("TMPDIR", &user_tmp)
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.context("Failed to create indeedhub container")?;
|
||||||
|
|
||||||
|
if !run.status.success() {
|
||||||
|
let err = String::from_utf8_lossy(&run.stderr);
|
||||||
|
return Err(anyhow::anyhow!("IndeedHub frontend failed: {}", err));
|
||||||
|
}
|
||||||
|
|
||||||
|
install_log("INSTALL OK: indeedhub stack").await;
|
||||||
|
info!("IndeedHub stack installed");
|
||||||
|
Ok(serde_json::json!({
|
||||||
|
"success": true,
|
||||||
|
"package_id": "indeedhub",
|
||||||
|
"message": "IndeedHub stack installed (7 containers)",
|
||||||
|
}))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user