""" Configuration centralisée de l'application. Toutes les variables d'environnement et paramètres sont centralisés ici. """ import os from pathlib import Path from typing import Optional from pydantic import Field from pydantic_settings import BaseSettings class Settings(BaseSettings): """Configuration de l'application Homelab Automation.""" # === Chemins === base_dir: Path = Field(default_factory=lambda: Path(__file__).resolve().parent.parent) logs_dir: Path = Field(default_factory=lambda: Path(os.environ.get("LOGS_DIR", "/logs"))) @property def ansible_dir(self) -> Path: """Répertoire Ansible (relatif à base_dir.parent)""" return self.base_dir.parent / "ansible" @property def tasks_logs_dir(self) -> Path: """Répertoire des logs de tâches markdown""" return Path(os.environ.get("DIR_LOGS_TASKS", str(self.base_dir.parent / "tasks_logs"))) @property def db_path(self) -> Path: """Chemin de la base de données SQLite""" return self.logs_dir / "homelab.db" # === SSH === ssh_key_path: str = Field( default_factory=lambda: os.environ.get("SSH_KEY_PATH", str(Path.home() / ".ssh" / "id_rsa")) ) ssh_user: str = Field(default_factory=lambda: os.environ.get("SSH_USER", "automation")) ssh_remote_user: str = Field(default_factory=lambda: os.environ.get("SSH_REMOTE_USER", "root")) # === API === api_key: str = Field(default_factory=lambda: os.environ.get("API_KEY", "dev-key-12345")) api_title: str = "Homelab Automation Dashboard API" api_version: str = "1.0.0" api_description: str = "API REST moderne pour la gestion automatique d'homelab" # === JWT Authentication === jwt_secret_key: str = Field( default_factory=lambda: os.environ.get("JWT_SECRET_KEY", "dev-secret-key-change-in-production") ) jwt_expire_minutes: int = Field( default_factory=lambda: int(os.environ.get("JWT_EXPIRE_MINUTES", "1440")) ) jwt_algorithm: str = "HS256" # === Database === database_url: Optional[str] = Field(default=None) @property def async_database_url(self) -> str: """URL de connexion async pour SQLAlchemy""" if self.database_url: return self.database_url return f"sqlite+aiosqlite:///{self.db_path}" # === CORS === cors_origins: list = Field(default=["*"]) cors_allow_credentials: bool = True cors_allow_methods: list = Field(default=["*"]) cors_allow_headers: list = Field(default=["*"]) # === Notifications ntfy === ntfy_enabled: bool = Field( default_factory=lambda: os.environ.get("NTFY_ENABLED", "true").lower() == "true" ) ntfy_base_url: str = Field( default_factory=lambda: os.environ.get("NTFY_BASE_URL", "https://ntfy.sh") ) ntfy_default_topic: str = Field( default_factory=lambda: os.environ.get("NTFY_TOPIC", "homelab-automation") ) ntfy_timeout: int = Field( default_factory=lambda: int(os.environ.get("NTFY_TIMEOUT", "10")) ) ntfy_username: Optional[str] = Field( default_factory=lambda: os.environ.get("NTFY_USERNAME") ) ntfy_password: Optional[str] = Field( default_factory=lambda: os.environ.get("NTFY_PASSWORD") ) ntfy_token: Optional[str] = Field( default_factory=lambda: os.environ.get("NTFY_TOKEN") ) # === Scheduler === scheduler_timezone: str = Field( default_factory=lambda: os.environ.get("SCHEDULER_TIMEZONE", "America/Montreal") ) scheduler_misfire_grace_time: int = 300 # === Cache === hosts_cache_ttl: int = 60 # secondes inventory_cache_ttl: int = 60 # secondes logs_index_rebuild_interval: int = 60 # secondes # === Server === host: str = "0.0.0.0" port: int = 8008 reload: bool = Field( default_factory=lambda: os.environ.get("RELOAD", "true").lower() == "true" ) log_level: str = "info" class Config: env_file = ".env" env_file_encoding = "utf-8" extra = "ignore" # Instance singleton de la configuration settings = Settings()