CT-OpsCT-Ops
Home
Getting Started
Architecture
Features
Deployment
GitHub
GitHub
Home
Getting Started
Architecture
Features
Deployment
GitHub
GitHub
  • Introduction
  • Getting Started

    • Installation
    • Configuration
    • Offline Agent Install Bundle
  • Architecture

    • Architecture Overview
    • Agent Architecture
    • Ingest Service
    • Deployment Profiles
  • Features

    • Hosts & Inventory
    • Host Groups
    • Networks
    • Monitoring
    • Certificate Management
    • SSL Certificate Checker
    • Alerts
    • Notifications
    • Reports
    • Terminal
    • Service Accounts & Identity
    • Directory User Lookup
    • Tasks & Runbooks
    • Scheduled Tasks
    • Tags
    • Notes
  • Deployment

    • Docker Compose Deployment
    • Air-Gap Deployment
    • Load Testing
  • Development

    • End-to-end testing
  • Licensing
  • Security

Architecture Overview

CT-Ops is a monorepo composed of several independently deployable services. This page describes the high-level architecture and how data flows through the system.


System Diagram

System Diagram


Components

Go Agent

A statically compiled Go binary. Runs on each monitored host with no runtime dependencies. Communicates exclusively via gRPC over mTLS (port 443 or 9443). See Agent Architecture for the full registration and heartbeat flow.

Ingest Service

A stateless gRPC server that sits between the agents and the database. Responsibilities:

  • Validates enrolment tokens for new registrations
  • Issues RS256 JWTs to approved agents
  • Accepts bidirectional heartbeat streams
  • Writes agent vitals and status to PostgreSQL
  • Publishes events to the internal queue

The ingest service is stateless (except for the RSA signing key on disk) — multiple instances can run behind a load balancer sharing the same database.

Queue

The queue is abstracted behind an interface, allowing the implementation to be swapped via configuration:

ProfileQueue typeWhen to use
smallIn-process (Go channels + WAL)< 50 hosts
standardRedpanda single nodeMost organisations
haRedpanda clusterHigh availability required

Consumers

Separate Go binaries that consume from the queue and write to PostgreSQL. Independently scalable.

ConsumerWrites to
consumers/metricsTimescaleDB time-series tables
consumers/alertsAlert instances, evaluates alert rules
consumers/eventsEvents spine, triggers webhooks

Web Application

A Next.js 15 (App Router) application. Reads directly from PostgreSQL via Drizzle ORM. Writes via Server Actions. All data fetching uses TanStack Query on the client side.

The web app never talks directly to the ingest service in the request path — it reads the same database that consumers write to. The only real-time connection is a WebSocket to the ingest service for live agent status updates.


Data Flow

image

Database

PostgreSQL with the TimescaleDB extension. Used for:

  • TimescaleDB hypertables — metrics time-series (CPU, memory, disk, network)
  • Standard tables — hosts, agents, certificates, alerts, notifications, events

TimescaleDB provides continuous aggregates for efficient querying of historical metric data without full table scans.


Authentication

Better Auth handles session management, email/password auth, TOTP MFA, and API keys. LDAP/Active Directory integration syncs domain accounts for service account inventory. SAML/OIDC (enterprise tier) is structured but not yet active.


Further Reading

  • Agent Architecture — Registration flow, identity model, reconnection
  • Ingest Service — gRPC API, JWT issuance, JWKS endpoint
  • Deployment Profiles — single / standard / HA
Edit this page on GitHub
Last Updated: 4/18/26, 10:33 PM
Contributors: Simon Carr, Claude Sonnet 4.6, Copilot, simonjcarr, Claude Opus 4.7
Next
Agent Architecture