More from MSP Reboot: depl0y · st0r
Architecture Documentation

System Architecture & Components

ClientSt0r is a Django-based web application designed for self-hosted deployment on Linux infrastructure. This page documents the core components, data flow, and deployment topology.

What ClientSt0r is built on.

The stack is chosen for operational familiarity in Linux-focused MSP environments. Nothing exotic — standard Python web stack, proven database, and a well-understood reverse proxy. All components are open source.

Component Technology Purpose
Web framework Django 6.0 (Python 3.12) Application logic, ORM, admin interface, authentication, and request routing. Django's ORM handles all database interactions — no raw SQL in application code.
Database MariaDB / MySQL Primary data store for all platform data — client organisations, assets, tickets, vault records (encrypted), audit logs, documents, and integrations. Runs locally or on a separate host.
Application server Gunicorn WSGI process manager. Runs the Django application with multiple worker processes. Binds to localhost only — not exposed externally. Worker count configurable based on server CPU count.
Reverse proxy Nginx TLS termination, static file serving, request routing to Gunicorn, rate limiting, and secure header injection. The only externally-facing component in a standard deployment.
Frontend Bootstrap 5 Responsive UI framework. Server-rendered templates with targeted JavaScript for interactive components. No heavy SPA framework — pages load fast on modest server hardware.
API REST + GraphQL Programmatic access to all major platform functions. REST for standard CRUD operations, GraphQL for flexible querying across related entities. JWT-authenticated with per-key scope controls.
Task queue Celery optional Background job processing for scheduled scans, email delivery, report generation, and RMM polling. Requires Redis as the message broker. Not required for core platform operation.
Cache / broker Redis optional Session storage and task broker for Celery. Used when Celery is enabled. Can run on the same server or a dedicated host in larger deployments. Not required for a minimal installation.

How a standard deployment is laid out.

Most deployments run on a single Linux server. The components are well-understood and the operational footprint is small. A multi-server layout is documented for larger environments.

Standard — single server

Ubuntu 22.04 LTS or Debian 12 (recommended)

  • Nginx listens on 443 (HTTPS) and proxies to Gunicorn on localhost
  • HTTP (80) redirects to HTTPS — no plaintext traffic accepted
  • Gunicorn runs the Django application with multiple workers on a localhost socket
  • MariaDB runs locally with a dedicated application database user
  • Static files (CSS, JS, images) served directly by Nginx — not proxied through Django
  • Media files (uploads, screenshots, attachments) stored on local filesystem
  • Systemd manages Gunicorn and Celery (if enabled) as services
  • Let's Encrypt / Certbot for TLS certificate management
Optional — multi-server

For larger environments or dedicated separation

  • Separate database server — MariaDB on its own host, reachable only by the application server
  • NFS or object storage (S3-compatible) for media files shared across application nodes
  • Redis on a separate host when Celery load justifies it
  • Load balancer in front of multiple Gunicorn nodes (sticky sessions required)
  • Database replication for read scaling or failover — standard MariaDB replication applies
  • Firewall rules between tiers — database host not reachable from internet at any point
Request flow — standard single-server deployment
Browser → HTTPS/443 → Nginx → proxy_pass → Gunicorn (127.0.0.1:8000) Django → ORM → MariaDB
Static files are served by Nginx directly — requests never reach Django or Gunicorn
Gunicorn socket is bound to 127.0.0.1 — not reachable outside the server
MariaDB binds to 127.0.0.1 in a standard deployment — no external DB port exposed
Celery workers (optional) connect to Redis and MariaDB on localhost for background tasks

How data is structured and organised.

The database is organised around organisations as the top-level tenant. Nearly all platform records are scoped to an organisation — there is no cross-org data leakage by design. The schema is Django ORM-managed and evolves through versioned migrations.

Core

Organisations

Multi-tenant client org structure. All major records — assets, vault entries, tickets, documents, contacts — are scoped to an organisation. Users are assigned to orgs with a role; platform-wide access requires explicit admin status.

Access Control

Users & Permissions

42-level RBAC system. User-to-org membership is a through-model carrying the assigned role. Permissions are checked per request — not cached in a way that survives permission revocation. Admin operations require the global admin flag independently of org roles.

Inventory

Assets

Hardware inventory, network devices, subnets and IPAM, rack layouts, network closets, and patch panels. Assets are typed and linked to their parent org. Network discovery results (via nmap) are reconciled against existing asset records.

Credential store

Vault

AES-256-GCM encrypted credential records with per-org key derivation. Credential fields are encrypted individually — the database stores ciphertext, not plaintext. Access is gated by RBAC and all interactions are audit-logged.

Knowledge base

Documents

Versioned knowledge base articles, embedded Draw.io network diagrams, MagicPlan floor plans, and attachments. Documents are org-scoped. Version history is stored to support rollback and change review. Search is full-text across document content.

Service desk

PSA

Tickets, SLA rules, queues, contracts, invoices, time entries, and recurring tasks. All records are linked to an org and an optional asset. Ticket workflow rules are stored as configurable rule sets — not hardcoded logic.

Compliance

Audit Log

Append-only log of all sensitive operations. Records include user identity, timestamp, action type, target object ID, and source IP. Logs are not modifiable through the application interface — only readable and exportable by administrators.

Integrations

Integration configs

Stored integration configurations for RMM, PSA, distributor, and identity provider connections. API keys and connection credentials for external systems are encrypted at rest using the same vault encryption scheme. Integration state and sync metadata stored per-config.

Programmatic access to the platform.

The API is designed for operational use — automation, integration with existing tooling, and reporting pipelines. REST handles standard operations; GraphQL handles complex querying across related data without multiple round trips.

REST API

Standard CRUD operations

RESTful endpoints covering organisations, assets, vault (write/metadata only), tickets, documents, users, and integrations. JSON request and response throughout. Consistent pagination and filtering patterns across resources.

GraphQL

Flexible querying

GraphQL endpoint for querying across related entities in a single request. Useful for reporting and dashboard integrations that need data from multiple resource types — assets with open tickets, org contacts with recent activity, and similar joined queries.

Authentication

JWT with configurable lifetime

JWT tokens issued at login with configurable expiry. Refresh token rotation supported. Token lifetime is admin-configurable — short-lived tokens for interactive use, longer-lived for automation accounts where appropriate.

Scope controls

Per-key access scoping

API keys can be scoped to specific resource types and operations. An automation key used for asset sync does not require — and should not have — access to vault or user management endpoints. Scope violations are logged in the audit log.

Audit coverage

API activity in audit log

All API activity is captured in the platform audit log with the API key identifier, endpoint, IP address, and response code. High-volume or anomalous API usage is visible to administrators without external log aggregation.

Documentation

Interactive API explorer

Swagger UI available in-app for authenticated users. Explore endpoints, review request/response schemas, and test calls directly from the browser. OpenAPI schema exportable for use in external tooling or documentation pipelines.

External systems ClientSt0r connects to.

Integrations are configured per-deployment from the admin interface. Connection credentials are encrypted at rest. Not all integrations are bidirectional — some are read-only ingestion, some support write-back. Integration depth varies by platform.

PSA Platforms
ConnectWise Manage Autotask HaloPSA Kaseya BMS Syncro Freshservice Zendesk ITFlow
Bidirectional ticket and asset sync where supported by the target platform API. Ticket status, contact records, and asset linkage are synchronised at configurable intervals.
RMM Providers
Tactical RMM NinjaOne Datto RMM Atera ConnectWise Automate
Asset and alert ingestion. Endpoint inventory from RMM is reconciled against ClientSt0r asset records. Alert events can trigger ticket creation via the configured workflow rules.
Network Controllers
UniFi TP-Link Omada Grandstream
Device discovery and inventory ingestion from network controller APIs. Connected devices, APs, switches, and VoIP hardware are reconciled against asset records and linked to the relevant client org.
Distributors
Ingram Micro Xvantage Pax8 TD Synnex
Catalogue and procurement integration. Product search, pricing, and order placement from within the platform. Purchase orders link to client orgs and can be tracked through to asset creation on receipt.
Identity Providers
Azure AD / Entra ID LDAP / Active Directory
SSO and directory sync. Users authenticate through the configured identity provider. Group membership can drive RBAC role assignment in ClientSt0r, reducing manual permission management.
Security Tools
Snyk HaveIBeenPwned ExploitHound
CVE and breach detection. Snyk for dependency scanning, HaveIBeenPwned for vault credential breach detection, and ExploitHound as an internal security intelligence platform used during development and ongoing security review.

Honest notes on scale and performance.

ClientSt0r is not benchmarked against arbitrary targets. Performance depends on your server hardware, database size, query patterns, and configuration. The notes below reflect what the architecture is designed for and where limits are likely to appear.

Target scale
Designed for MSP-scale environments — tens of client organisations, thousands of assets, years of ticket history. A typical 25-client MSP with several thousand asset records and active ticketing is well within the expected operating range on modest hardware.
Database indexing
Indexes are maintained on organisation ID, record status, and date fields — the fields most commonly used in filtering and ordering. The Django ORM generates queries that take advantage of these indexes for the standard page views and API calls.
Static and media files
Static assets (CSS, JS, images) and media files (user uploads, screenshots) are served directly by Nginx and do not pass through Django or Gunicorn. This removes a significant source of application server load for asset-heavy pages.
Gunicorn workers
Worker count is configurable and should be tuned to your server's CPU count. The standard recommendation is (2 × CPU cores) + 1. Sync workers are the default — async workers (gevent) can be used if your workload involves many long-held connections.
No benchmark claims
No specific request-per-second or concurrent-user numbers are published. Performance depends on your hardware, data volume, and configuration. If you need benchmarks, run them on your target server with a representative data set before committing to a production deployment.
Large deployments
For very large deployments — 100,000+ assets, many concurrent users, high ticket volumes — consider a dedicated database server, additional Gunicorn workers, Redis for session caching, and review of slow query logs. The architecture supports separation of these tiers; it does not require it for typical MSP scale.

Next steps:

Deployment Guide → Install Guide on GitHub →