c9c72be0b6
PR 4a of the runtime service registry change. - Remove addon pages (/addons/:addonId, AddonPage, addons/*) superseded by service pages. - Remove grafana_url/prometheus_url from backend config, compose, .env.example, and README (URLs now live on service records; VITE_ frontend deep-link vars retained). - Add Services page (/services) with create/list/delete + sidebar nav, so services are configurable in the tool itself and service pages are reachable. - Update docs/REQUIREMENTS.md service-registry section; add CHANGELOG.md with the breaking-upgrade note (MANAGE_ENCRYPTION_KEY required; grafana/prometheus env vars removed; default widget seeding removed). Verification: backend ruff clean, pytest 222 passed; frontend lint 0 errors, build success, 70 tests passed.
110 lines
3.2 KiB
Python
110 lines
3.2 KiB
Python
"""Backend configuration using pydantic-settings.
|
|
|
|
Reads from environment variables and .env file automatically.
|
|
Uses a flat settings model so that standard env vars like SSH_HOST,
|
|
JELLYFIN_URL etc. are picked up directly without nested-model complications.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from functools import lru_cache
|
|
from pathlib import Path
|
|
|
|
from pydantic_settings import BaseSettings
|
|
|
|
from media_library_viewer_api.logging_utils import describe_settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Flat application settings read from env vars / .env file."""
|
|
|
|
# Logging
|
|
log_level: str = "INFO"
|
|
log_format: str = "text" # "text" or "json"
|
|
|
|
# Auth / OIDC (Authentik-compatible JWT validation)
|
|
auth_enabled: bool = False
|
|
oidc_issuer_url: str = ""
|
|
oidc_audience: str = ""
|
|
oidc_jwks_url: str = ""
|
|
oidc_clock_skew_seconds: int = 30
|
|
|
|
# SMTP (optional, used for Users -> message popup)
|
|
smtp_host: str = ""
|
|
smtp_port: int = 587
|
|
smtp_username: str = ""
|
|
smtp_password: str = ""
|
|
smtp_from_address: str = ""
|
|
smtp_from_name: str = "Manage"
|
|
smtp_use_tls: bool = True
|
|
smtp_use_ssl: bool = False
|
|
smtp_timeout: int = 30
|
|
|
|
# Legacy SSH fallback (new preferred path is machine-specific settings)
|
|
ssh_host: str = ""
|
|
ssh_username: str = ""
|
|
ssh_port: int = 22
|
|
ssh_key_directory: str = ""
|
|
ssh_key_name: str = ""
|
|
ssh_password: str = ""
|
|
ssh_known_hosts_path: str = ""
|
|
|
|
# Observability
|
|
prometheus_enabled: bool = True
|
|
prometheus_file_sd_dir: str = "/app/backend/.cache/prometheus-file-sd"
|
|
alertmanager_url: str = "http://alertmanager:9093"
|
|
alertmanager_webhook_url: str = "" # Optional receiver for alertmanager webhook notifications
|
|
|
|
# Remote paths
|
|
remote_media_root: str = ""
|
|
remote_path_prefix: str = ""
|
|
|
|
# Derived convenience
|
|
@property
|
|
def media_root(self) -> str:
|
|
return self.remote_media_root or ""
|
|
|
|
@property
|
|
def path_prefix(self) -> str:
|
|
return self.remote_path_prefix or ""
|
|
|
|
@property
|
|
def ssh_key_path(self) -> str:
|
|
if not self.ssh_key_directory or not self.ssh_key_name:
|
|
return ""
|
|
return str(Path(self.ssh_key_directory) / self.ssh_key_name)
|
|
|
|
@property
|
|
def ssh_known_hosts_file(self) -> Path:
|
|
return Path(self.ssh_known_hosts_path or ".cache/media_library_viewer/known_hosts")
|
|
|
|
model_config = {"env_file": ".env", "env_file_encoding": "utf-8", "extra": "ignore"} # type: ignore[assignment]
|
|
|
|
|
|
def _find_env_file() -> str | None:
|
|
"""Look for .env in CWD, then parent directories up to the repo root."""
|
|
current = Path.cwd()
|
|
for directory in [current, *current.parents]:
|
|
candidate = directory / ".env"
|
|
if candidate.is_file():
|
|
return str(candidate)
|
|
if (directory / ".git").exists():
|
|
break
|
|
return None
|
|
|
|
|
|
@lru_cache
|
|
def get_settings() -> Settings:
|
|
"""Return a cached Settings instance."""
|
|
env_file = _find_env_file()
|
|
settings = Settings(_env_file=env_file) if env_file else Settings()
|
|
logger.info(
|
|
"Loaded backend settings from %s: %s",
|
|
env_file or "environment/defaults",
|
|
describe_settings(settings),
|
|
)
|
|
return settings
|