#!/usr/bin/env python3 """Hugging Face Spaces launcher for the upstream FreeLLMAPI container. FreeLLMAPI itself is a Node.js/React application. This small Python launcher prepares the Space environment and explicitly forwards the server command to the upstream privilege-dropping entrypoint. """ from __future__ import annotations import os import secrets import sys from pathlib import Path def prepare_environment() -> None: data_dir = Path(os.environ.get("FREELLMAPI_DATA_DIR", "/data")) data_dir.mkdir(parents=True, exist_ok=True) os.environ.setdefault("NODE_ENV", "production") os.environ.setdefault("PORT", os.environ.get("SPACE_PORT", "7860")) os.environ.setdefault("FREEAPI_DB_PATH", str(data_dir / "freeapi.db")) # Keep a stable generated key beside the DB if a Space Secret was not set. # For a persistent deployment, mount a writable bucket at /data. if not os.environ.get("ENCRYPTION_KEY"): key_file = Path( os.environ.get("ENCRYPTION_KEY_FILE", str(data_dir / ".encryption-key")) ) if not key_file.is_file() or key_file.stat().st_size == 0: key_file.parent.mkdir(parents=True, exist_ok=True) try: descriptor = os.open( key_file, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600, ) except FileExistsError: # Another startup process created it first. pass else: with os.fdopen(descriptor, "w", encoding="utf-8") as handle: handle.write(secrets.token_hex(32)) handle.write("\n") os.environ["ENCRYPTION_KEY"] = key_file.read_text(encoding="utf-8").strip() def main() -> None: prepare_environment() # Dockerfile supplies this CMD explicitly. Keep the fallback to avoid ever # calling setpriv with an empty command (the error seen in the Space logs). command = sys.argv[1:] or ["node", "server/dist/index.js"] upstream_entrypoint = "/usr/local/bin/docker-entrypoint.sh" if not os.path.isfile(upstream_entrypoint): raise FileNotFoundError( f"Expected upstream FreeLLMAPI entrypoint at {upstream_entrypoint}" ) os.execv(upstream_entrypoint, [upstream_entrypoint, *command]) if __name__ == "__main__": main()