An open source IT Service Management platform. Pick the modules you need, skip the ones you don't, and run it on your own infrastructure with full data isolation.
ModularITSM is built for IT teams that want a self-hosted alternative to ServiceNow, Freshservice, or Jira Service Management — without the enterprise pricing or the vendor lock-in.
- Incident Management — Create, assign, track, and resolve tickets with configurable status workflows and priority-based SLA tracking
- SLA Engine — Business hours schedules, holiday calendars, per-priority response and resolution targets, automatic clock pause/stop based on ticket state
- Role-Based Access Control — 30+ granular permissions, five built-in roles (admin, service owner, coordinator, technician, end user), plus custom roles
- Contact Management — Track external users and customers separately from internal staff
- Assignment Groups — Organize technicians into teams (Service Desk, Networking, etc.) with group-based ticket routing
- Audit Logging — 40+ tracked action types with SHA-256 integrity hashing, IP/user-agent metadata, and informational compliance framework evaluations
- System Announcements — Broadcast messages to all users
- Modular by Design — Enable only what you need. Each module is optional and independent.
Every deployment is a fully isolated instance — dedicated containers, dedicated database, dedicated subdomain. There's no shared infrastructure between customers. One instance, one customer, zero data leakage risk.
| Layer | Technology |
|---|---|
| Backend | Python 3.11, FastAPI 0.111, SQLAlchemy 2.0, Pydantic v2 |
| Database | PostgreSQL 16 with connection pooling |
| Auth | JWT (PyJWT), bcrypt password hashing, RBAC |
| fastapi-mail + Jinja2 templates | |
| Frontend | Bootstrap 5.3 SPA served by Nginx |
| Infrastructure | Docker Compose with health checks and resource limits |
You need Docker and Git. That's it — everything runs in containers.
git clone https://github.com/dedgar1/ModularITSM.git
cd ModularITSM
docker-compose up --buildOnce all services are healthy:
| Service | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Backend API | http://localhost:8000 |
| API Docs (Swagger) | http://localhost:8000/docs |
| MailHog (dev email) | http://localhost:8025 |
Default login: admin@modularitsm.local / Password1234!!
Change these immediately. The password policy enforces 14+ characters with complexity requirements.
All configuration is via environment variables in docker-compose.yml:
| Variable | Required | Description |
|---|---|---|
SECRET_KEY |
Yes | JWT signing key. Generate with: python -c "import secrets; print(secrets.token_hex(32))" |
DATABASE_URL |
Yes | PostgreSQL connection string |
CORS_ORIGINS |
Yes | Comma-separated allowed origins (restrict in production) |
MAIL_SERVER |
No | SMTP server for outbound email |
MAIL_PORT |
No | SMTP port (defaults to 587) |
MAIL_FROM |
No | Sender email address |
INSTANCE_BASE_URL |
No | Public URL of this instance (used in emails) |
ENVIRONMENT |
No | development or production |
backend/
app/
main.py # App init, startup migrations, seed data
api/routes/ # Route handlers (all require_permission() protected)
auth.py # Login, password change, token refresh
incidents.py # Ticket CRUD, status transitions, events/notes
users.py # User management and profiles
contacts.py # External contact management
groups.py # Assignment groups
settings.py # App settings, categories, statuses, modules
sla.py # SLA policies and business hours
attachments.py # File uploads on incidents
audit.py # Audit log queries
roles.py # Role and permission management
announcements.py # System announcements
presence.py # Real-time user presence on tickets
models/ # SQLAlchemy ORM models
core/ # Security, permissions, config, email, audit helpers
schemas/ # Pydantic request/response schemas
templates/ # Jinja2 email templates
db/database.py # Engine and session setup
frontend/
index.html # Current SPA (React rewrite planned)
nginx.conf # Nginx config with security headers
docker-compose.yml # Orchestrates all services
Security has been audited across 5 phases. Highlights:
- JWT auth with mandatory SECRET_KEY (app refuses to start without one)
- bcrypt password hashing with CIS Benchmark Level 1 policy
- Account lockout with exponential backoff (5 attempts, 15 min base, doubling to 60 min max)
- Rate limiting on auth endpoints (10 requests/minute)
- RBAC enforcement on all sensitive endpoints (108+)
- SQL injection protection via SQLAlchemy parameterized queries
- File upload security with extension whitelist and UUID-based naming
- Fernet encryption for stored credentials (SMTP, API keys)
- Security headers on both backend middleware and Nginx
- Tamper-evident audit logging with SHA-256 integrity hashing
The full security audit, known issues, and remediation plan are documented in CLAUDE.md.
Contributions are welcome! Whether it's bug reports, feature ideas, docs improvements, or code — see CONTRIBUTING.md for how to get started.
Some good entry points:
- React frontend rewrite — The current frontend is a monolithic
index.html. Migrating to React is the biggest open item. - Test coverage — pytest is set up but tests need to be written
- Documentation — API docs, deployment guides, module documentation
- React/Next.js frontend (replaces monolithic index.html)
- AWS deployment infrastructure with per-customer provisioning
- Alembic migration management
- Email notification workflows
- Dashboard and reporting
- Audit log hash chaining
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
You're free to use, modify, and self-host ModularITSM. If you modify it and offer it as a hosted service, you must release your changes under the same license. This protects the project from being taken proprietary without giving back.
Copyright (C) 2026 David Edgar