# Languard Server Manager A multi-game server management platform with a Python/FastAPI backend and React/TypeScript frontend. Currently supports Arma 3 with an extensible adapter system for adding more games. ## Tech Stack ### Backend - **Python 3.12+** / **FastAPI** — async REST API - **SQLite** with WAL mode — zero-config database - **SQLAlchemy** — raw SQL via `text()` queries (no ORM) - **BattlEye RCon** — UDP protocol v2 for remote admin - **APScheduler** — background cleanup jobs - **psutil** — process monitoring and resource metrics - **JWT** (python-jose) + **bcrypt** — authentication - **Fernet** (cryptography) — sensitive config field encryption ### Frontend - **React 19** / **TypeScript 6** / **Vite 8** - **TanStack Query v5** — server state management - **Zustand 5** — client state (auth, UI) - **Tailwind CSS** — dark neumorphic design system - **Playwright** — E2E testing - **Vitest** + **React Testing Library** — unit tests (173 tests) ## Quick Start ### 1 — Backend setup ```bash cd backend # Create and activate a virtual environment python -m venv venv source venv/bin/activate # macOS / Linux # venv\Scripts\activate # Windows (cmd) # venv\Scripts\Activate.ps1 # Windows (PowerShell) pip install -r requirements.txt ``` **Generate required secrets** (one-time): ```bash # Secret key (JWT signing) openssl rand -hex 32 # Fernet encryption key (sensitive config fields at rest) python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" ``` Copy `.env.example` to `.env` and fill in the two keys: ```bash cp .env.example .env # then open .env in your editor ``` ```ini # .env — minimum required values LANGUARD_SECRET_KEY= LANGUARD_ENCRYPTION_KEY= LANGUARD_ARMA3_DEFAULT_EXE=C:/path/to/arma3server_x64.exe ``` **Start the backend** (development — auto-reload on file changes): ```bash uvicorn main:app --host 0.0.0.0 --port 8000 --reload ``` First run prints a randomly-generated admin password to the console. Log in and change it immediately via Settings → Change Password (or `PUT /api/auth/password`). - API root: `http://localhost:8000` - Interactive docs: `http://localhost:8000/docs` **Debug in VS Code:** add this `launch.json` configuration: ```json { "name": "Backend — uvicorn", "type": "debugpy", "request": "launch", "module": "uvicorn", "args": ["main:app", "--host", "0.0.0.0", "--port", "8000"], "cwd": "${workspaceFolder}/backend", "env": { "PYTHONDONTWRITEBYTECODE": "1" }, "jinja": true, "justMyCode": false } ``` --- ### 2 — Frontend setup ```bash cd frontend npm install npm run dev ``` The Vite dev server starts at `http://localhost:5173` and automatically proxies: - `/api/*` → `http://localhost:8000` (REST) - `/ws/*` → `ws://localhost:8000` (WebSocket) **Debug in VS Code:** install the [JavaScript Debugger](https://marketplace.visualstudio.com/items?itemName=ms-vscode.js-debug) extension (bundled by default), then add: ```json { "name": "Frontend — Vite (Chrome)", "type": "chrome", "request": "launch", "url": "http://localhost:5173", "webRoot": "${workspaceFolder}/frontend/src", "sourceMapPathOverrides": { "/@fs/*": "${workspaceFolder}/frontend/*" } } ``` Start the Vite dev server first (`npm run dev`), then launch this config to attach Chrome DevTools with source-map support. --- ## Running Tests ### Backend ```bash cd backend source venv/bin/activate # (if not already active) pytest # all tests pytest tests/adapters/arma3/ -v # adapter tests only pytest --tb=short -q # quiet output ``` ### Frontend unit tests ```bash cd frontend npm test # single run (CI-friendly) npm run test:watch # watch mode during development npx vitest run --coverage # with coverage report ``` ### Frontend E2E tests (Playwright) Start the backend and the Vite dev server first, then: ```bash cd frontend npm run test:e2e # all E2E tests (headless) npm run test:e2e:ui # Playwright UI mode (interactive, great for debugging) npx playwright test --headed # watch tests run in an actual browser ``` Integration tests (require a live backend) live in `tests-e2e/integration/`. All other tests use API mocks and run without a backend. ## Project Structure ``` languard-servers-manager/ ├── backend/ │ ├── main.py # FastAPI app factory, lifespan, middleware │ ├── config.py # Pydantic Settings (env vars) │ ├── database.py # SQLAlchemy engine, migration runner │ ├── dependencies.py # FastAPI deps: auth, admin, server, adapter │ ├── adapters/ # Game adapter system │ │ ├── protocols.py # Protocol definitions (7 capabilities) │ │ ├── registry.py # GameAdapterRegistry singleton │ │ ├── exceptions.py # Typed adapter exceptions │ │ └── arma3/ # Arma 3 adapter (7/7 capabilities) │ ├── core/ │ │ ├── auth/ # JWT auth, user CRUD │ │ ├── servers/ # Server service, routers, process manager │ │ ├── games/ # Game type discovery │ │ ├── system/ # Health and status endpoints │ │ ├── websocket/ # WS manager, broadcast thread │ │ ├── threads/ # Background thread registry │ │ ├── dal/ # Data access layer (repositories) │ │ ├── jobs/ # APScheduler cleanup jobs │ │ ├── utils/ # Crypto, file utils, port checker │ │ └── migrations/ # SQL migration scripts │ └── requirements.txt ├── frontend/ │ ├── src/ │ │ ├── App.tsx # Router + auth guard │ │ ├── pages/ # LoginPage, DashboardPage, ServerDetailPage, CreateServerPage, SettingsPage │ │ ├── components/ # Sidebar, ServerCard, ConfigEditor, PlayerTable, BanTable, MissionList, ModList, LogViewer, StatusLed │ │ ├── hooks/ # useServers, useServerDetail, useAuth, useGames, useWebSocket │ │ ├── store/ # auth.store, ui.store (Zustand) │ │ ├── lib/ # api.ts (Axios client) │ │ └── __tests__/ # Vitest unit tests (173 tests) │ ├── tests-e2e/ # Playwright E2E tests │ └── playwright.config.ts ├── API.md # REST + WebSocket API reference ├── ARCHITECTURE.md # System architecture overview ├── DATABASE.md # Database schema reference ├── FRONTEND.md # Frontend architecture and components ├── MODULES.md # Module-by-module reference └── THREADING.md # Background threading model ``` ## Environment Variables | Variable | Default | Description | |---|---|---| | `LANGUARD_SECRET_KEY` | (required) | JWT signing key | | `LANGUARD_ENCRYPTION_KEY` | (required) | Fernet key for sensitive config fields | | `LANGUARD_DB_PATH` | `./languard.db` | SQLite database path | | `LANGUARD_SERVERS_DIR` | `./servers` | Base directory for server data | | `LANGUARD_HOST` | `0.0.0.0` | Listen host | | `LANGUARD_PORT` | `8000` | Listen port | | `LANGUARD_CORS_ORIGINS` | `["http://localhost:5173"]` | CORS allowed origins | | `LANGUARD_LOG_RETENTION_DAYS` | `7` | Log cleanup retention | | `LANGUARD_METRICS_RETENTION_DAYS` | `30` | Metrics cleanup retention | | `LANGUARD_PLAYER_HISTORY_RETENTION_DAYS` | `90` | Player history retention | | `LANGUARD_JWT_EXPIRE_HOURS` | `24` | JWT token expiry | | `LANGUARD_ARMA3_DEFAULT_EXE` | (required for Arma 3) | Default Arma 3 executable path | ## Documentation - **[ARCHITECTURE.md](ARCHITECTURE.md)** — System design, component diagram, security model - **[API.md](API.md)** — Complete REST + WebSocket API reference - **[DATABASE.md](DATABASE.md)** — Schema, tables, indexes, migration system - **[FRONTEND.md](FRONTEND.md)** — React component tree, state management, design system - **[MODULES.md](MODULES.md)** — File-by-file module reference - **[THREADING.md](THREADING.md)** — Background thread model and concurrency