MiniSOC is a desktop-first SOC MVP built with React, FastAPI, SQLAlchemy, Alembic, and Electron. It supports two healthy operating modes:
- Web development mode for engineers working on the frontend and backend separately
- Desktop product mode for operators who launch one packaged app and get a local backend automatically
The project keeps the report-aligned MVP flows intact:
- Dashboard
- Alerts
- Incidents
- AI Analyst
- Users
- Admin runtime and audit visibility
MiniSOC is a self-hosted security operations workspace for small teams, labs, demos, and desktop deployments. It lets an operator sign in, triage alerts, promote alerts into incidents, investigate incidents, request contextual AI analysis, manage users, and inspect audit activity.
It is not positioned as a managed SIEM platform or a multi-tenant enterprise SOC.
Use this when actively building the product.
- Frontend runs with Vite
- Backend runs with FastAPI
- PostgreSQL is the normal database target
- OpenSearch is optional for live alert ingestion
- Wazuh API is optional for manager and agent telemetry
Use this when testing the Electron shell locally.
- Electron starts first
- Electron launches the local backend automatically
- SQLite is used by default
- First-run setup is handled in-app
- OpenSearch and Wazuh remain optional
Use this for end users.
- The user installs MiniSOC and launches
MiniSOC.exe - Electron starts the embedded backend automatically
- Electron waits for backend health before opening the main UI
- The packaged build uses a bundled backend executable, not a shipped raw Python virtual environment
- SQLite is used by default unless explicitly overridden
- Desktop config is stored under the app
userDatadirectory
flowchart TD
Operator["Operator"] --> Renderer["React renderer"]
Operator --> Electron["Electron main process"]
Electron --> Renderer
Electron --> Backend["Bundled FastAPI runtime"]
Renderer -->|REST + WebSocket| Backend
Backend --> DB[("PostgreSQL or SQLite")]
Backend --> OS["Optional OpenSearch"]
Backend --> WZ["Optional Wazuh API telemetry"]
Backend --> AI["Optional AI providers"]
- OpenSearch is the preferred source for live alert documents
- If OpenSearch is unavailable, MiniSOC serves clearly labeled fallback alerts
- Alert assignment, status, and incident linkage are persisted locally in the application database
Wazuh is supported as an optional manager telemetry integration, not as a full standalone SIEM ingestion pipeline.
What is implemented:
- Wazuh manager URL configuration
- Optional Wazuh API username and password
- Manager status polling
- Agent summary polling
- Health visibility in the Admin module panel
What is not claimed:
- Full Wazuh event ingestion through the Wazuh API
- Deep Wazuh workflow orchestration
- Replacement of OpenSearch as the main alert document source
MiniSOC supports contextual AI analysis for alerts and incidents.
groq,gemini, andollamaare supported provider targets- Ollama base URL is runtime-configurable
- AI write endpoints are limited to
adminandanalystroles - AI requests are optional and degrade safely if providers are not configured
- Playwright tests stub AI responses so E2E validation does not require external model access
Desktop config ownership is intentionally split by responsibility:
| Category | Source of truth |
|---|---|
| Desktop runtime settings | Electron-owned desktop config in userData/desktop-config.json |
| Sensitive desktop secrets | Electron safeStorage encrypted values when available |
| Effective backend runtime config in desktop mode | Environment variables injected by Electron into the embedded backend process |
| Web development config | Environment variables loaded by the backend and Vite |
| Session-scoped UI preferences | Frontend state stores |
Sensitive desktop fields are no longer stored as plain JSON when OS-backed secure storage is available. MiniSOC now protects these at rest:
- JWT signing secret
- Seeded admin password
- Groq API key
- Gemini API key
- Wazuh API password
Important boundary:
- Desktop secrets are protected at rest in config storage
- The embedded backend still receives secrets through environment variables at process start
- That means MiniSOC desktop mode is appropriate for trusted single-user or single-workstation deployments, not hostile multi-user desktops
- If Electron
safeStorageis unavailable, desktop setup fails closed unlessMINISOC_ALLOW_INSECURE_DESKTOP_STORAGE=1is set for local debugging only
See docs/security/desktop-security.md for the local threat model.
- Access tokens now include a database-backed session identifier (
jti) - Default access-token lifetime is 12 hours and can be changed with
ACCESS_TOKEN_EXPIRE_MINUTES /api/auth/logoutrevokes the current token session- WebSocket connections use
/api/auth/ws-ticketone-time tickets through theSec-WebSocket-Protocolheader instead of bearer tokens in query strings
Desktop mode now includes a guided /setup flow before login when the local runtime has not been finalized yet.
The setup flow covers:
- administrator password initialization
- OpenSearch host and TLS settings
- optional Wazuh API telemetry settings
- AI provider configuration
- secure storage readiness
The seeded admin identity is now re-synchronized from desktop config on desktop startup, so password setup and password rotation actually take effect.
The repository is organized around the runtime surfaces that matter in production and development:
src/contains the React renderer, routed MVP pages, shared UI, and frontend testsbackend/contains the FastAPI app, migrations, seed logic, and backend testselectron/contains the desktop shell, preload bridge, config encryption, and startup orchestrationscripts/contains build and test helpers used by npm scriptstests/e2e/contains Playwright end-to-end coverageinfra/docker/contains optional local infrastructure helpers for PostgreSQL and SIEM dependenciesdocs/contains architecture, security, reports, and archived planning material
End users of the packaged desktop app do not need these tools. Developers do.
- Node.js 20+
- Python 3.11+
- PostgreSQL for normal web mode
- Optional OpenSearch and Wazuh services for integration testing
Use .env.example as the starting point for local development.
Important backend variables:
DATABASE_URLSECRET_KEYDEMO_ADMIN_EMAILDEMO_ADMIN_PASSWORDDEFAULT_AI_MODELGROQ_API_KEYGEMINI_API_KEYOLLAMA_BASE_URLOPEN_SEARCH_*WAZUH_MANAGER_URLWAZUH_API_USERNAMEWAZUH_API_PASSWORDWAZUH_API_VERIFY_SSLWAZUH_API_TIMEOUT_SECONDS
Important frontend variable:
VITE_API_BASE_URL
npm install
cd backend
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
cd ..Optional helper Compose files live under:
infra/docker/postgres.compose.ymlinfra/docker/siem.compose.yml
Start PostgreSQL and optional services however you prefer, then:
cd backend
.venv\Scripts\activate
alembic upgrade head
python -m app.seed
uvicorn app.main:app --reloadIn a second terminal:
npm run devnpm run desktop:devThat command:
- starts the Vite renderer
- launches Electron
- has Electron start the backend automatically
- uses SQLite by default for the desktop runtime
npm run buildnpm run desktop:backend:buildThis produces a packaged backend executable under backend/dist-desktop/minisoc-backend/.
npm run desktop:buildnpm run desktop:distThe packaged Electron app includes:
- compiled renderer assets from
dist/ - Electron main and preload code
- a packaged backend runtime under
release/.../resources/backend-runtime/
It does not rely on shipping backend/.venv as the desktop runtime contract.
npm run testnpm run typechecknpm run lintnpm run test:backendnpm run test:electron-configInstall the browser once:
npx playwright install chromiumThen run:
npm run test:e2eThe Playwright harness boots:
- a disposable SQLite-backed backend
- Alembic migrations
- seed data
- a production preview renderer pointed at that backend
Covered flows include:
- login
- dashboard load
- alerts interaction
- incident workflow
- AI analyst basic flow
- admin page access
npm audit --audit-level=moderate
bandit -r backend/app
pip-audit -r backend/requirements.txtpip-audit is included in CI validation. If it is not installed locally, install it into a tooling environment rather than adding it to runtime dependencies.
After npm run desktop:build, Windows developers can run:
npm run desktop:smokeThe smoke runner launches the unpacked desktop app with isolated MINISOC_USER_DATA_DIR, enables MINISOC_DESKTOP_SMOKE=1, waits for the startup path to write desktop-smoke.json, and exits.
Check the backend log file under the MiniSOC app data directory. The Admin runtime panel also shows the current config path and backend log path.
Rebuild the renderer and desktop package:
npm run build
npm run desktop:buildMiniSOC expects Electron safeStorage to be available for desktop secret protection. If it is not available, desktop setup will block completion unless you explicitly allow insecure local debugging with:
MINISOC_ALLOW_INSECURE_DESKTOP_STORAGE=1Do not use that flag for distributed builds.
MiniSOC continues to operate with fallback alerts. The runtime status panel will mark OpenSearch as degraded.
MiniSOC still works. Wazuh health is optional and only affects manager and agent telemetry visibility.
MiniSOC is now substantially more hardened than a local-only demo:
- packaged desktop backend runtime instead of a raw shipped virtual environment
- OS-backed secret protection at rest for desktop config when available
- first-run setup flow
- database-backed token revocation and one-time WebSocket tickets
- SSRF-oriented URL validation for local service integrations
- backend health-gated Electron startup
- single-instance Electron guard
- SQLite self-bootstrap in desktop mode
- fallback behavior when OpenSearch is unavailable
- explicit Wazuh telemetry scope
- Playwright coverage for core operator flows
For a “done forever” program or a full enterprise SOC as that term is usually understood, MiniSOC is not complete at that bar, and this repository does not claim to be. The list below records concrete gaps rather than implied completeness.
Still not claimed as complete enterprise hardening:
- no refresh-token auth system
- no tamper-proof secret isolation from same-user malware on the desktop host
- no full Wazuh ingestion pipeline
- no code signing or auto-update infrastructure yet
- no HA or remote orchestration layer
README.mddocs/REPOSITORY_STRUCTURE.mddocs/security/desktop-security.mddocs/architecture/minisoc-complete-blueprint.mddocs/reports/miniguard-report-action-summary.md