Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,10 @@ server_manager/target/
.venv/
__pycache__/
*.pyc

# Generated artifacts
server_manager/secrets.yaml
server_manager/docker-compose.yml
server_manager/config/
server_manager/media/
server_manager/transcode/
13 changes: 12 additions & 1 deletion server_manager/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ async fn run_install() -> Result<()> {
docker::install()?;

// 6. Initialize Services
configure_services(&hw, &secrets)?;
initialize_services(&hw, &secrets)?;

// 7. Generate Compose
Expand Down Expand Up @@ -118,11 +119,21 @@ async fn run_generate() -> Result<()> {
// For generate, we might not be in /opt/server_manager, but let's try to load secrets from CWD.
// We propagate the error because generating a compose file with empty passwords is bad.
let secrets = secrets::Secrets::load_or_create().context("Failed to load or create secrets.yaml")?;
configure_services(&hw, &secrets)?;
generate_compose(&hw, &secrets).await
}

fn configure_services(hw: &hardware::HardwareInfo, secrets: &secrets::Secrets) -> Result<()> {
info!("Configuring services (generating config files)...");
let services = services::get_all_services();
for service in services {
service.configure(hw, secrets).with_context(|| format!("Failed to configure service: {}", service.name()))?;
}
Ok(())
}

fn initialize_services(hw: &hardware::HardwareInfo, secrets: &secrets::Secrets) -> Result<()> {
info!("Initializing services...");
info!("Initializing services (system setup)...");
let services = services::get_all_services();
for service in services {
service.initialize(hw, secrets).with_context(|| format!("Failed to initialize service: {}", service.name()))?;
Expand Down
27 changes: 27 additions & 0 deletions server_manager/src/services/apps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use super::Service;
use crate::core::hardware::{HardwareInfo, HardwareProfile};
use crate::core::secrets::Secrets;
use std::collections::HashMap;
use std::fs;
use std::path::Path;
use anyhow::{Result, Context};

pub struct VaultwardenService;
impl Service for VaultwardenService {
Expand Down Expand Up @@ -98,6 +101,30 @@ impl Service for NextcloudService {
fn name(&self) -> &'static str { "nextcloud" }
fn image(&self) -> &'static str { "lscr.io/linuxserver/nextcloud:latest" }
fn ports(&self) -> Vec<String> { vec!["4443:443".to_string()] }
fn configure(&self, _hw: &HardwareInfo, secrets: &Secrets) -> Result<()> {
let config_dir = Path::new("./config/nextcloud");
fs::create_dir_all(config_dir).context("Failed to create nextcloud config dir")?;

let db_pass = secrets.nextcloud_db_password.clone().unwrap_or_default();
let admin_pass = secrets.nextcloud_admin_password.clone().unwrap_or_default();

let php_config = format!(r#"<?php
$AUTOCONFIG = array(
"dbtype" => "mysql",
"dbname" => "nextcloud",
"dbuser" => "nextcloud",
"dbpass" => "{}",
"dbhost" => "mariadb",
"directory" => "/data",
"adminlogin" => "admin",
"adminpass" => "{}",
);
"#, db_pass, admin_pass);

fs::write(config_dir.join("autoconfig.php"), php_config).context("Failed to write autoconfig.php")?;
Ok(())
}

fn env_vars(&self, _hw: &HardwareInfo, secrets: &Secrets) -> HashMap<String, String> {
let mut vars = HashMap::new();
vars.insert("PUID".to_string(), "1000".to_string());
Expand Down
2 changes: 1 addition & 1 deletion server_manager/src/services/infra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl Service for MariaDBService {
fn image(&self) -> &'static str { "lscr.io/linuxserver/mariadb:latest" }
fn ports(&self) -> Vec<String> { vec!["3306:3306".to_string()] }

fn initialize(&self, _hw: &HardwareInfo, secrets: &Secrets) -> Result<()> {
fn configure(&self, _hw: &HardwareInfo, secrets: &Secrets) -> Result<()> {
let init_dir = Path::new("./config/mariadb/initdb.d");
fs::create_dir_all(init_dir).context("Failed to create mariadb initdb.d")?;

Expand Down
4 changes: 4 additions & 0 deletions server_manager/src/services/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ pub trait Service: Send + Sync {
fn name(&self) -> &'static str;
fn image(&self) -> &'static str;

/// Generates configuration files (safe to run without side effects on system services)
fn configure(&self, _hw: &HardwareInfo, _secrets: &Secrets) -> Result<()> { Ok(()) }

/// Performs system initialization (e.g., stopping conflicting services). May require root.
fn initialize(&self, _hw: &HardwareInfo, _secrets: &Secrets) -> Result<()> { Ok(()) }

fn ports(&self) -> Vec<String> { vec![] }
Expand Down
Loading