A self-hosted application observability and incident management platform.
CloudOps AI collects telemetry (metrics, logs, and traces) from your applications, presents it in a unified dashboard, and helps teams detect, investigate, and resolve incidents, with AI assistance from locally hosted open-source models. No paid third-party APIs required.
🚧 Early setup. The backend skeleton is in place: a FastAPI app with a
GET /health endpoint, tests, linting/type checking, and CI. No product features
or frontend have been built yet.
- Telemetry ingestion: metrics, logs, and traces via OpenTelemetry
- Dashboards: visualize service health and performance
- Incident management: create, track, and resolve incidents
- AI assistance: local open-source models to help summarize and investigate incidents
| Area | Technologies |
|---|---|
| Frontend | Next.js, TypeScript, Tailwind CSS |
| Backend | Python, FastAPI |
| Database | PostgreSQL |
| Observability | OpenTelemetry, Prometheus, Loki, Tempo |
| Infrastructure | Docker, Kubernetes, GitHub Actions |
| AI | Locally hosted open-source models |
Technologies are introduced incrementally, only when they are needed.
cloudops-ai/
├── .github/
│ └── workflows/
│ └── ci.yml # CI: lint, format check, type check, tests
├── .pre-commit-config.yaml # Git hooks run on every commit
├── .gitleaks.toml # Gitleaks secret scan settings
├── trivy.yaml # Trivy security scan settings
├── compose.yaml # Local infrastructure entry point (includes infra/*/compose.yaml)
├── infra/
│ └── postgres/ # PostgreSQL: compose.yaml, .env.example, README
├── backend/ # Python backend service (managed with uv)
│ ├── app/
│ │ ├── main.py # FastAPI app factory (create_app)
│ │ ├── api/
│ │ │ ├── main.py # Combines all routers into api_router
│ │ │ └── routes/ # HTTP routers only
│ │ ├── core/ # App-wide settings (config.py)
│ │ ├── schemas/ # Pydantic request/response models
│ │ ├── services/ # Business logic
│ │ └── utils/ # Small shared helpers
│ ├── tests/ # pytest tests
│ ├── pyproject.toml # Dependencies and tool config
│ └── uv.lock # Exact locked dependency versions
├── CLAUDE.md # Instructions for AI-assisted development
├── DEVLOG.md # Running log of changes, one entry per task
├── LICENSE # Apache License 2.0
├── NOTICE # Copyright notice
└── README.md
A frontend/ directory will be added as development progresses.
- Git
- uv: Python package and environment manager
- Docker with Compose v2.20+ (Docker Desktop includes it) for local services such as PostgreSQL
Install uv (you don't need to install Python separately; uv handles it):
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"Needed later:
- Node.js (LTS) for the frontend
git clone https://github.com/ANI717/cloudops-ai.git
cd cloudops-aiSupporting services run in Docker. Each lives in its own infra/<service>/ folder
with a compose.yaml, .env.example, and README. The root
compose.yaml includes them all, so from the repository root:
cp infra/postgres/.env.example infra/postgres/.env # once
docker compose up -d postgres # start one service
docker compose ps # status ("healthy" when ready)
docker compose down # stop everything (data is kept)| Service | Folder | Address |
|---|---|---|
| PostgreSQL | infra/postgres/ |
127.0.0.1:5432 |
See each service's README for logs, shell access, and resetting data.
All backend commands run from the backend/ directory.
1. Set up the environment
cd backend
uv syncuv sync installs the pinned Python version (3.14) if needed, creates a virtual
environment in backend/.venv, and installs the exact dependencies from uv.lock,
including dev tools (pytest, ruff, mypy, pre-commit). Re-run it after pulling changes.
Then install the git hooks (once per clone):
uv run pre-commit installFrom then on, every git commit runs basic file checks, ruff (lint + format),
a uv.lock consistency check, and mypy on the staged files (configured in
.pre-commit-config.yaml). If a hook fails or fixes a
file, the commit is stopped: review the changes, git add them, and commit again.
Run all hooks on every file with uv run pre-commit run --all-files.
Create the local config file (gitignored) from the template. Its database values
match infra/postgres/.env.example, so it works with the local PostgreSQL as is:
cp .env.example .envSettings are read from environment variables prefixed with CLOUDOPS_, then from
backend/.env, then from defaults in app/core/config.py. Invalid values stop
the app at startup with a clear error.
| Variable | Default | Description |
|---|---|---|
CLOUDOPS_ENVIRONMENT |
development |
development, test, or production (production disables /docs) |
CLOUDOPS_APP_NAME |
CloudOps AI |
Display name in the API docs |
CLOUDOPS_POSTGRES_HOST / _PORT |
127.0.0.1 / 5432 |
PostgreSQL server |
CLOUDOPS_POSTGRES_USER / _DB |
cloudops / cloudops |
PostgreSQL user and database |
CLOUDOPS_POSTGRES_PASSWORD |
(required) | PostgreSQL password; no default in code |
Database migrations. Start PostgreSQL first (see Local infrastructure), then apply the schema with Alembic:
uv run alembic upgrade head # apply all migrations
uv run alembic revision --autogenerate -m "message" # new migration from model changes
uv run alembic check # fail if models and migrations differModels live in app/models/ and migrations in alembic/versions/. Always review
an autogenerated migration before committing it.
2. Run the development server
uv run fastapi dev app/main.pyThe server auto-reloads on code changes. Stop it with Ctrl+C.
- Health check (process is up): http://127.0.0.1:8000/health
- Readiness check (database reachable, else 503): http://127.0.0.1:8000/ready
- Interactive API docs: http://127.0.0.1:8000/docs
curl http://127.0.0.1:8000/health # {"status":"ok"}
curl http://127.0.0.1:8000/ready # {"status":"ready"}3. Run the tests
Tests need the local PostgreSQL running and backend/.env in place. They use a
separate cloudops_test database (created automatically and rebuilt from the
migrations on every run), so your development data is never touched.
uv run pytest # add -v for one line per testRun the tests with coverage (lists uncovered lines and fails below 80%):
uv run pytest --covCoverage is configured under [tool.coverage.*] in backend/pyproject.toml. Add
--cov-report=html to browse line-by-line results in htmlcov/index.html.
4. Lint, format, and type-check (configured in backend/pyproject.toml)
uv run ruff check . # lint (add --fix to auto-fix safe issues)
uv run ruff format . # format code (use --check to verify only)
uv run mypy # strict static type checking5. Run all CI checks locally
The same checks CI runs on every push to main and
every pull request:
uv sync --locked && uv run ruff check . && uv run ruff format --check . && uv run mypy && uv run alembic upgrade head && uv run alembic check && uv run pytest --covCI runs two free, open-source scanners in a separate Security scans job:
- Gitleaks checks the full git history for accidentally committed secrets (API keys, tokens, passwords).
- Trivy checks dependencies (
backend/uv.lock, including dev tools) for known HIGH/CRITICAL vulnerabilities that have a fix available, and infrastructure files (Dockerfiles, Kubernetes manifests) for misconfigurations. Settings live intrivy.yaml.
To run them locally, install the tools once:
# Windows
winget install Gitleaks.Gitleaks AquaSecurity.Trivy
# macOS
brew install gitleaks trivyThen, from the repository root:
gitleaks git . --redact # scan all commits for secrets
gitleaks dir . --redact # also scan uncommitted files (skips .venv, see .gitleaks.toml)
trivy fs . # scan dependencies and config files (reads trivy.yaml)Each command exits non-zero if it finds a problem. The first Trivy run downloads its vulnerability database (about 1 minute).
Copyright 2026 Animesh Bala Ani
Licensed under the Apache License, Version 2.0. See NOTICE for attribution details.