Files

112 lines
4.0 KiB
Python

import os
import json
import secrets
from pathlib import Path
from typing import Dict, Any
# Project base directory: can be overridden via APP_DIR or auto-detected from file location
DEFAULT_APP_DIR = Path(__file__).resolve().parent.parent
BASE_DIR = Path(os.environ.get("APP_DIR", str(DEFAULT_APP_DIR)))
# Persistent data directory: holds settings, SSH keys, job history, and backup index
DATA_DIR = Path(os.environ.get("DATA_DIR", str(BASE_DIR / "data")))
CONFIG_FILE = DATA_DIR / "settings.json"
BACKUP_INDEX_FILE = DATA_DIR / "backups_index.json"
JOBS_FILE = DATA_DIR / "jobs_history.json"
DEFAULT_KEY_FILE = DATA_DIR / "id_ed25519"
DEFAULT_PUB_KEY_FILE = DATA_DIR / "id_ed25519.pub"
def get_default_backup_dir() -> str:
if "BACKUP_DIR" in os.environ and os.environ["BACKUP_DIR"].strip():
return os.environ["BACKUP_DIR"].strip()
if os.path.exists("/backups"):
return "/backups"
if os.path.exists("/mnt/user"):
return "/mnt/user/backups/pangolin"
if os.path.exists("/var/backups"):
return "/var/backups/pangolin"
return str(DATA_DIR / "backups")
DEFAULT_LOCAL_BACKUP = get_default_backup_dir()
DEFAULT_SETTINGS = {
"auth_enabled": True,
"admin_password_hash": "",
"admin_password_salt": "",
"jwt_secret": secrets.token_hex(32),
# Remote VPS Configuration
"vps_host": "", # IP or Hostname of the Pangolin VPS
"vps_port": 22, # SSH Port
"vps_user": "root", # SSH Username
"vps_auth_method": "key", # "key" or "password"
"vps_ssh_key_path": str(DEFAULT_KEY_FILE),
"vps_ssh_password": "", # SSH Password (if method == "password")
"vps_pangolin_dir": "/opt/pangolin", # Path to Pangolin on remote VPS
# Local Unraid Storage & Retention
"backup_dir": DEFAULT_LOCAL_BACKUP,
"retention_count": 10,
# Automation & Scheduler
"scheduled_backup_enabled": True,
"scheduled_backup_cron": "0 3 * * *",
"scheduled_backup_scope": "pangolin",
"scheduled_update_check_enabled": True,
# Webhooks
"webhook_url": "",
"webhook_type": "discord",
"telegram_bot_token": "",
"telegram_chat_id": "",
"notify_on_backup": True,
"notify_on_update": True,
# App daemon
"app_port": int(os.environ.get("PORT", 8888)),
"app_host": os.environ.get("HOST", "0.0.0.0")
}
def load_settings() -> Dict[str, Any]:
DATA_DIR.mkdir(parents=True, exist_ok=True)
if not CONFIG_FILE.exists():
save_settings(DEFAULT_SETTINGS)
return DEFAULT_SETTINGS.copy()
try:
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
data = json.load(f)
for k, v in DEFAULT_SETTINGS.items():
if k not in data:
data[k] = v
# Auto-heal SSH key path if configured path does not exist but default key does
cur_key_path = data.get("vps_ssh_key_path", "")
if (not cur_key_path or not os.path.exists(cur_key_path)) and DEFAULT_KEY_FILE.exists():
data["vps_ssh_key_path"] = str(DEFAULT_KEY_FILE)
# Auto-heal backup_dir if set to old non-existent path and /backups is mounted in container
cur_backup_dir = data.get("backup_dir", "")
if os.path.exists("/backups") and (not cur_backup_dir or not os.path.exists(cur_backup_dir)):
data["backup_dir"] = "/backups"
return data
except Exception as e:
print(f"Error loading settings: {e}. Using defaults.")
return DEFAULT_SETTINGS.copy()
def save_settings(settings: Dict[str, Any]) -> None:
DATA_DIR.mkdir(parents=True, exist_ok=True)
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(settings, f, indent=2)
def get_setting(key: str, default: Any = None) -> Any:
settings = load_settings()
return settings.get(key, default)
def update_setting(key: str, value: Any) -> None:
settings = load_settings()
settings[key] = value
save_settings(settings)