Module Reference
Backend Modules
main.py — Application Factory
create_app() — FastAPI app with lifespan, CORS middleware, rate limiter, exception handler
lifespan() — Startup: init DB, register adapters, create WebSocket manager, create broadcast thread, create ThreadRegistry, recover processes, reattach threads, seed admin, start scheduler. Shutdown: stop threads, stop broadcast, stop scheduler.
config.py — Settings
Settings class (Pydantic BaseSettings) with LANGUARD_ env prefix
- 13 configurable settings: SECRET_KEY, ENCRYPTION_KEY, DB_PATH, SERVERS_DIR, HOST, PORT, CORS_ORIGINS, log/metrics/player retention days, JWT expiry, Arma3 default exe
database.py — Database Engine
get_engine() — Creates SQLite engine with WAL mode and foreign keys
run_migrations(engine) — Applies numbered .sql migration files from core/migrations/
get_db() — FastAPI dependency yielding a DB connection
get_thread_db() — Thread-local DB connection for background threads
dependencies.py — FastAPI Dependencies
get_current_user(token) — Decodes JWT, validates user exists
require_admin(user) — Returns 403 if user role is not admin
get_server_or_404(server_id, db) — Loads server row or raises 404
get_adapter_for_server(server_id, db) — Loads server + resolves its game adapter
adapters/protocols.py — Adapter Protocols
7 runtime-checkable Protocol classes:
ConfigGenerator — Render config files, build launch args
ProcessConfig — Allowed executables, port conventions, directory layout
LogParser — Parse log lines, resolve latest log file
RemoteAdmin — Connect, send commands, get/kick/ban players
MissionManager — List, upload, delete mission files
ModManager — Scan mods, set enabled mods, build CLI args
BanManager — Sync bans between DB and file
- Composite
GameAdapter — Aggregates all protocols, plus has_capability(), get_additional_routers(), get_custom_thread_factories()
adapters/registry.py — Game Adapter Registry
GameAdapterRegistry — Class-level singleton dict (game_type → adapter instance)
- Methods:
register(), get(), all(), list_game_types(), is_registered()
adapters/exceptions.py — Typed Exceptions
AdapterError, ConfigWriteError, ConfigValidationError, ConfigMigrationError, LaunchArgsError, RemoteAdminError, ExeNotAllowedError
adapters/__init__.py — Adapter Loading
initialize_adapters() — Imports built-in adapters (Arma3), then scans importlib.metadata entry points under "languard.adapters" for third-party plugins
adapters/arma3/ — Arma 3 Adapter
All 7 capabilities implemented:
| Module |
Class |
Purpose |
adapter.py |
Arma3Adapter |
Composite adapter declaring all capabilities |
config_generator.py |
Arma3ConfigGenerator |
5 Pydantic config models, writes server.cfg/basic.cfg/Arma3Profile/beserver.cfg, builds launch args, get_ui_schema() for per-field widget hints |
process_config.py |
Arma3ProcessConfig |
Allowed executables, port conventions (game+1/+2/+3), directory layout |
log_parser.py |
RPTParser |
Regex-based .rpt log parser, log file resolver, list_log_files(), get_log_file_path() |
rcon_client.py |
BERConClient |
BattlEye RCon v2 UDP protocol implementation |
remote_admin.py |
Arma3RemoteAdmin + Arma3RemoteAdminFactory |
Implements RemoteAdmin protocol using BERConClient |
mission_manager.py |
Arma3MissionManager |
.pbo upload, delete, list, rotation config generation |
mod_manager.py |
Arma3ModManager |
@-prefixed mod scanning, enabled-mod persistence, -mod/-serverMod args; _parse_mod_cpp()/_parse_meta_cpp() for display_name/workshop_id |
ban_manager.py |
Arma3BanManager |
BattlEye bans.txt file sync + DB sync |
core/auth/ — Authentication
| Module |
Purpose |
router.py |
7 endpoints: login, logout, me, change password, user CRUD |
service.py |
AuthService — login, create_user, change_password, seed_admin_if_empty |
schemas.py |
Pydantic models: LoginRequest, CreateUserRequest, ChangePasswordRequest |
utils.py |
JWT creation/validation (HS256), bcrypt password hashing |
core/servers/ — Server Management
| Module |
Purpose |
router.py |
Server CRUD, lifecycle (start/stop/restart/kill), config read/write/preview, RCon command |
players_router.py |
Player list, player history, kick/ban by slot_id |
logfiles_router.py |
List, download, and delete historical .rpt log files |
bans_router.py |
Ban CRUD with bans.txt file sync |
missions_router.py |
Mission list, .pbo upload (500MB), delete, GET/PUT rotation |
mods_router.py |
List mods, set enabled mods |
service.py |
ServerService — orchestrates all lifecycle operations, config writes, thread management |
schemas.py |
Pydantic models: CreateServerRequest, UpdateServerRequest, StopServerRequest |
process_manager.py |
ProcessManager singleton — subprocess.Popen lifecycle, PID recovery via psutil |
core/games/ — Game Type Discovery
| Module |
Purpose |
router.py |
4 endpoints: list game types, get game details, config schema, defaults |
core/system/ — System Health
| Module |
Purpose |
router.py |
/health (public) + /status (authed) |
core/websocket/ — Real-Time Events
| Module |
Purpose |
router.py |
/ws endpoint with JWT auth via query param |
manager.py |
WebSocketManager — asyncio connection registry with server_id subscriptions |
broadcast_thread.py |
BroadcastThread — bridges queue.Queue to asyncio event loop |
core/threads/ — Background Threads
| Module |
Purpose |
base_thread.py |
BaseServerThread — abstract base with stop event, thread-local DB, exception backoff |
thread_registry.py |
ThreadRegistry — manages per-server thread bundles, start/stop/reattach; get_rcon_client(server_id) class method exposes live RCon client |
log_tail.py |
LogTailThread — tails log files, parses lines, persists to DB, broadcasts |
process_monitor.py |
ProcessMonitorThread — detects crashes, triggers auto-restart |
metrics_collector.py |
MetricsCollectorThread — psutil CPU/RAM collection every 10s |
remote_admin_poller.py |
RemoteAdminPollerThread — polls player list via RCon, syncs join/leave events |
core/jobs/ — Scheduled Tasks
| Module |
Purpose |
scheduler.py |
APScheduler BackgroundScheduler singleton |
cleanup_jobs.py |
3 cron jobs: old logs (daily 03:00), old metrics (6h), old events (weekly Sun 04:00) |
core/dal/ — Data Access Layer
| Module |
Purpose |
base_repository.py |
BaseRepository — thin wrapper around SQLAlchemy text() queries |
server_repository.py |
ServerRepository — CRUD, status updates, running servers, restart count |
config_repository.py |
ConfigRepository — Per-section upsert with Fernet encryption and optimistic locking |
player_repository.py |
PlayerRepository — Upsert/clear players, player_history queries, get_by_slot(server_id, slot_id) |
ban_repository.py |
BanRepository — Ban CRUD with active/inactive flag |
event_repository.py |
EventRepository — Insert server events, query, cleanup |
log_repository.py |
LogRepository — Insert parsed log entries, query with filters, cleanup |
metrics_repository.py |
MetricsRepository — Insert CPU/RAM metrics, query by time range, cleanup |
core/utils/ — Utilities
| Module |
Purpose |
crypto.py |
Fernet field-level encryption: encrypt(), decrypt(), is_encrypted() |
file_utils.py |
get_server_dir(), ensure_server_dirs(), sanitize_filename(), safe_delete_file() |
port_checker.py |
Port availability checks with cross-server conflict detection |
Frontend Modules
src/main.tsx — Entry Point
Renders <App /> into #root with React StrictMode.
src/App.tsx — Root Component
- Creates
QueryClient with stale time 10s, retry 2, refetchOnWindowFocus false
- Wraps app in
QueryClientProvider, BrowserRouter, ReactQueryDevtools
- Routes:
/login → LoginPage, /* → ProtectedLayout (auth guard)
ProtectedLayout checks isAuthenticated from Zustand, redirects to /login if false
src/lib/api.ts — API Client
- Axios instance with
baseURL from VITE_API_URL env, 30s timeout
- Request interceptor: reads
languard_token from localStorage, adds Authorization: Bearer header
- Response interceptor: on 401, checks URL prefix — non-auth 401s clear token and redirect to
/login; auth 401s (login) are left for the component to handle
- Exports
ApiResponse<T> type: { success, data, error? }
src/store/auth.store.ts — Auth Store (Zustand + persist)
- Persisted to
localStorage under key languard-auth
onRehydrateStorage sets isAuthenticated: true if token exists
partialize stores only token and user
setAuth(token, user) also writes languard_token to localStorage
clearAuth() removes both storage keys
src/store/ui.store.ts — UI Store (Zustand, in-memory)
sidebarOpen, activeServerId, notifications[]
addNotification(type, message) creates toast with auto-remove (5s timeout)
removeNotification(id) for manual dismiss
src/hooks/useServers.ts — Server Data Hooks
7 TanStack Query hooks: useServers, useServer, useStartServer, useStopServer, useRestartServer, useCreateServer, useDeleteServer
Server interface with all fields
useServers refetches every 30s
- Mutations invalidate relevant cache keys on success
src/hooks/useWebSocket.ts — WebSocket Hook
- Connects to
ws://localhost:8000/ws?token=...&server_id=...
- Exponential backoff reconnect (2s → 30s max)
- Close code 4001 = explicit logout (no reconnect)
- Invalidates TanStack Query caches on server_status, metrics, log, players events
- Cleans up on unmount (closes WebSocket, clears reconnect timeout)
src/pages/LoginPage.tsx — Login Page
- React Hook Form + Zod validation (username/password required)
apiClient.post("/api/auth/login") on submit
setAuth(token, user) + navigate to / on success
- Error display from catch block
- Loading state: button changes to "Signing in..."
src/pages/DashboardPage.tsx — Dashboard Page
useServers() for data, useWebSocket() for real-time updates
- Loading state, error state, empty state, content with server grid
- Server cards rendered via
ServerCard inside Link components
- "X servers configured" counter
- "Languard Server Manager" branding
- Dashboard link with LayoutDashboard icon
- Dynamic server list from
useServers() with StatusLed dots
- Settings link at bottom
- Active server highlighting via URL params
- Displays: server name,
StatusLed, game type badge
- 3-column stat grid: Players (current/max), Port, Restarts
- Action buttons based on server status:
- Stopped: Start button only
- Running: Stop + Restart buttons
- Starting/Restarting: Stop + Restart (disabled)
e.preventDefault() + e.stopPropagation() on buttons to prevent parent Link navigation
- Success/error notifications via
useUIStore
src/components/ui/StatusLed.tsx — Status LED
- Colored dot with CSS class
status-led-{status} (5 statuses)
- Sizes:
sm (6px), md (8px)
- Optional label text via
showLabel prop
- Uses
clsx for conditional class merging