| """Launcher for Odysseus (https://github.com/pewdiepie-archdaemon/odysseus). |
| |
| Odysseus is a self-hosted FastAPI/uvicorn app configured via a `.env` file and |
| its in-app Settings UI (SQLite-backed) — not a CLI gateway with flags. This |
| launcher seeds `.env` from odysseus.json on first boot (without touching an |
| existing one, so in-app Settings changes persist across restarts), runs the |
| one-time setup script, then execs uvicorn so supervisord can supervise it directly. |
| """ |
| import json |
| import os |
| import subprocess |
| import sys |
| from pathlib import Path |
|
|
| CONFIG_PATH = Path(os.environ.get("ODYSSEUS_CONFIG_PATH", "/app/odysseus.json")) |
| APP_DIR = Path(os.environ.get("ODYSSEUS_APP_DIR", "/app/odysseus")) |
| DEFAULT_PORT = os.environ.get("ODYSSEUS_PORT", "18796") |
|
|
|
|
| def _load_config() -> dict: |
| try: |
| return json.loads(CONFIG_PATH.read_text(encoding="utf-8")) |
| except Exception: |
| return {} |
|
|
|
|
| def _seed_env_file(config: dict, port: str) -> None: |
| env_path = APP_DIR / ".env" |
| if env_path.exists(): |
| return |
| env_vars = dict(config.get("env", {})) |
| env_vars.setdefault("APP_BIND", "127.0.0.1") |
| env_vars.setdefault("APP_PORT", port) |
| lines = [f"{key}={value}" for key, value in env_vars.items()] |
| env_path.write_text("\n".join(lines) + "\n", encoding="utf-8") |
|
|
|
|
| def main() -> None: |
| config = _load_config() |
| port = str(config.get("gateway", {}).get("port") or DEFAULT_PORT) |
| _seed_env_file(config, port) |
| os.chdir(APP_DIR) |
| subprocess.run([sys.executable, "setup.py"], check=False) |
| os.execvp( |
| sys.executable, |
| [sys.executable, "-m", "uvicorn", "app:app", "--host", "127.0.0.1", "--port", port], |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|