2026-04-07 02:04:22 +05:30
|
|
|
"""YakPanel - Configuration"""
|
|
|
|
|
import os
|
|
|
|
|
from functools import lru_cache
|
2026-04-07 03:35:32 +05:30
|
|
|
from pathlib import Path
|
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
2026-04-07 02:04:22 +05:30
|
|
|
|
|
|
|
|
# Runtime config loaded from DB on startup (overrides Settings)
|
|
|
|
|
_runtime_config: dict[str, Any] = {}
|
|
|
|
|
|
2026-04-07 03:35:32 +05:30
|
|
|
_BACKEND_ROOT = Path(__file__).resolve().parent.parent
|
|
|
|
|
|
2026-04-07 02:04:22 +05:30
|
|
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
|
|
|
"""Application settings"""
|
2026-04-07 03:35:32 +05:30
|
|
|
|
|
|
|
|
model_config = SettingsConfigDict(
|
|
|
|
|
env_file=str(_BACKEND_ROOT / ".env"),
|
|
|
|
|
env_file_encoding="utf-8",
|
|
|
|
|
extra="ignore",
|
|
|
|
|
)
|
|
|
|
|
|
2026-04-07 02:04:22 +05:30
|
|
|
app_name: str = "YakPanel"
|
|
|
|
|
app_version: str = "1.0.0"
|
|
|
|
|
debug: bool = False
|
|
|
|
|
|
|
|
|
|
# Paths (Ubuntu/Debian default)
|
|
|
|
|
panel_path: str = "/www/server/YakPanel-server"
|
|
|
|
|
setup_path: str = "/www/server"
|
|
|
|
|
www_root: str = "/www/wwwroot"
|
|
|
|
|
www_logs: str = "/www/wwwlogs"
|
|
|
|
|
vhost_path: str = "/www/server/panel/vhost"
|
|
|
|
|
|
2026-04-07 02:26:06 +05:30
|
|
|
# Database (relative SQLite paths are resolved to backend/data/, not process CWD)
|
2026-04-07 02:04:22 +05:30
|
|
|
database_url: str = "sqlite+aiosqlite:///./data/default.db"
|
|
|
|
|
|
|
|
|
|
# Redis
|
|
|
|
|
redis_url: str = "redis://localhost:6379/0"
|
|
|
|
|
|
|
|
|
|
# Auth
|
|
|
|
|
secret_key: str = "YakPanel-server-secret-change-in-production"
|
|
|
|
|
algorithm: str = "HS256"
|
|
|
|
|
access_token_expire_minutes: int = 60 * 24 # 24 hours
|
|
|
|
|
|
|
|
|
|
# Panel
|
|
|
|
|
panel_port: int = 8888
|
|
|
|
|
webserver_type: str = "nginx" # nginx, apache, openlitespeed
|
|
|
|
|
|
|
|
|
|
# CORS (comma-separated origins, e.g. https://panel.example.com)
|
|
|
|
|
cors_extra_origins: str = ""
|
|
|
|
|
|
|
|
|
|
# Remote SSH installer (disabled by default — high risk; see docs)
|
|
|
|
|
enable_remote_installer: bool = False
|
|
|
|
|
remote_install_default_url: str = "https://www.yakpanel.com/YakPanel-server/install.sh"
|
|
|
|
|
remote_install_rate_limit_per_ip: int = 10
|
|
|
|
|
remote_install_rate_window_minutes: int = 60
|
|
|
|
|
# Comma-separated CIDRs; empty = no restriction (e.g. "10.0.0.0/8,192.168.0.0/16")
|
|
|
|
|
remote_install_allowed_target_cidrs: str = ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@lru_cache
|
|
|
|
|
def get_settings() -> Settings:
|
|
|
|
|
return Settings()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_runtime_config() -> dict[str, Any]:
|
|
|
|
|
"""Get effective panel config (Settings + DB overrides)."""
|
|
|
|
|
s = get_settings()
|
|
|
|
|
base = {
|
|
|
|
|
"panel_port": s.panel_port,
|
|
|
|
|
"www_root": s.www_root,
|
|
|
|
|
"setup_path": s.setup_path,
|
|
|
|
|
"www_logs": s.www_logs,
|
|
|
|
|
"vhost_path": s.vhost_path,
|
|
|
|
|
"webserver_type": s.webserver_type,
|
|
|
|
|
"mysql_root": "",
|
|
|
|
|
}
|
|
|
|
|
for k, v in _runtime_config.items():
|
|
|
|
|
if k in base:
|
|
|
|
|
if k == "panel_port":
|
|
|
|
|
try:
|
|
|
|
|
base[k] = int(v)
|
|
|
|
|
except (ValueError, TypeError):
|
|
|
|
|
pass
|
|
|
|
|
else:
|
|
|
|
|
base[k] = v
|
|
|
|
|
base["backup_path"] = os.path.join(base["setup_path"], "backup")
|
|
|
|
|
return base
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_runtime_config_overrides(overrides: dict[str, str]) -> None:
|
|
|
|
|
"""Set runtime config from DB (called on startup)."""
|
|
|
|
|
global _runtime_config
|
|
|
|
|
_runtime_config = dict(overrides)
|