Docs refreshed for Astervis v1 — now covering AI call analytics. What’s new
Astervis Docsv1.0
Getting Started

Architecture

How Astervis is assembled on your server.

Astervis is a small stack of Docker containers that runs on the same server as your PBX. It taps into the call records Asterisk already writes, copies them into its own analytics database, and serves a dashboard — without ever touching the cloud. This page is the mental model: what the pieces are, how data moves between them, and where the AI fits in.

Everything here lives on your server. Call records and recordings are replicated into a local database and never leave the machine — the one exception is optional AI analysis, which sends call audio to Google Gemini. See AI & privacy.

The data flow

A call finishes, Asterisk writes a CDR row into its MySQL/MariaDB database, and from there Astervis takes over. The CDC service notices the new row in the binary log, hands it to the replication consumer, and it lands in TimescaleDB. The backend and admin read from TimescaleDB and render the dashboard you open on port 8443.

If the call has a recording and AI is enabled, a second path kicks in: the queue picks up the audio, sends it to the AI gateway (Gemini on Vertex AI), and the resulting transcript and analysis are written back into the same database — so they show up on the call card alongside the metrics.

  ┌─────────────────────┐
  Asterisk / FreePBX   call ends CDR row + (optional) recording
   MySQL CDR  (host) │
  └──────────┬──────────┘
 binary log

  ┌─────────────────────┐
  litcdc  (CDC)      │   reads binlog, snapshots then streams
  └──────────┬──────────┘
 HTTP long-poll feed

  ┌─────────────────────┐
  replication   consumes feed writes rows
  └──────────┬──────────┘

  ┌─────────────────────┐        ┌──────────────────────────────┐
  TimescaleDB        │◀──────▶│  backend (app) + admin (web) │
  (Postgres + TS +        └───────────────┬──────────────┘
   pgvector)         │                        │
  └──────────┬──────────┘
                          ┌──────────────────┐
  recordings  nginx  :8443 you, the dashboard
                          └──────────────────┘
  ┌─────────────────────┐   audio    ┌──────────────────────────┐
  queue (BullMQ)     │───────────▶│  AI gateway (Gemini)     │
  └─────────────────────┘            └────────────┬─────────────┘
 transcript + analysis
             └─────────────────────────────────────┘  (back into TimescaleDB)

What gets installed

The installer renders a docker-compose.yml into /opt/astervis and brings up the following services. Only nginx is reachable from outside the machine; everything else binds to 127.0.0.1.

ServiceContainerWhat it doesHost port
timescaledbastervis-timescaledbPostgres 16 + TimescaleDB + pgvector — the analytics store127.0.0.1:5432
redisastervis-redisSession cache + BullMQ queue backend127.0.0.1:6380
migrateastervis-migrateOne-shot: applies DB migrations, then exits
appastervis-appBackend API (Elysia.js on Bun)127.0.0.1:5555
nextjsastervis-nextjsAdmin dashboard (Next.js / React)127.0.0.1:6464
queueastervis-queueBullMQ worker — AI jobs, syncs, insights
litcdcastervis-litcdcThe CDC service — reads the Asterisk binlog127.0.0.1:18088
replicationastervis-replicationConsumes the litcdc feed → TimescaleDB
nginxastervis-nginxReverse proxy + TLS termination8443

On disk it looks like this:

docker-compose.yml
.env

There is no Redpanda, Kafka, or Debezium in this list. Older versions of the stack used a Debezium connector plus a Redpanda broker for change capture — both were removed when litcdc landed (installer v0.0.82+). If you see a data/redpanda/ directory, it's a leftover from an old install and can be deleted.

litcdc — the CDC pipeline

CDC (change data capture) is how Astervis keeps its analytics database in lockstep with Asterisk without polling MySQL and without slowing the PBX down. The whole job is done by litcdc, a single Rust binary (~10–25 MiB resident) that reads the MySQL/MariaDB binary log directly.

It runs in two phases:

Consistent initial snapshot

On first run, litcdc takes a consistent snapshot of the existing cdr table — your full historical call backfill — using a brief FLUSH TABLES WITH READ LOCK to get a clean cut. This is why the CDC database user needs the LOCK TABLES grant.

Realtime streaming

Once the snapshot is done, litcdc switches to tailing the binlog and streams every new and changed row as it happens. Events are buffered in a durable, bounded local log so nothing is lost across a restart — and because the buffer survives reboots, litcdc never re-snapshots.

The replication consumer pulls those events over an HTTP long-poll feed (litcdc listens on litcdc:8088 inside the Docker network, published to 127.0.0.1:18088 on the host) and writes them into TimescaleDB. The buffer is capped at 64 MiB; once events are consumed past that cap they're truncated, and the writer pauses if nothing is draining — so a stalled consumer can never blow up disk usage.

litcdc replaced the old Debezium + Redpanda pipeline. That pair needed a JVM and a full message broker and cost roughly 640 MiB of RAM; litcdc does the same job — durable buffering, offsets, replay, backpressure — in around 30 MiB, with no broker and no JVM. That single change is why the whole stack now fits in ~0.6 GB and the RAM minimum dropped to 2 GB.

litcdc speaks a Debezium-compatible {schema, payload} envelope on its feed, so the replication consumer needed no rewrite when the broker was removed. The compatibility is purely on the wire — there is no Debezium or Kafka anywhere in the stack.

The AI pipeline (optional)

Analytics work fully on their own — the AI pipeline is a separate, optional layer that turns recordings into transcripts, QA scores, and searchable text. It only runs if you hold an AI license tier, and it's the only part of Astervis that sends data off the server.

When a CDR with a recording lands, the queue worker submits the audio to the AI gateway, which runs a single multimodal Gemini call on Google Vertex AI — transcription, speaker diarization, sentiment, category, and (if configured) rubric-based QA all in one request. Results come back via webhook into the ai_transcripts table, moving through pending → processing → completed. From there they're embedded with gemini-embedding-001 into pgvector for semantic search.

Nothing about AI is required. If your calls can't leave the building, simply don't enable it — the dashboards, CDR replication, and integrations all work without it.

Resource footprint

The full stack sits at roughly 0.6 GB of RAM at rest — most of the savings come from litcdc replacing the old broker-based CDC. The hard minimum to install is 2 GB of RAM, 1 CPU core, and 15 GB of free disk (checked on the Docker data partition, not /). 4 GB and 2 cores are recommended for comfortable headroom during the initial snapshot.

Network surface

This is the part worth internalizing for anyone hardening the box: Astervis exposes a single port.

PortServiceNotes
8443nginxHTTPS dashboard — https://<domain-or-IP>:8443

nginx terminates TLS and proxies to the backend and admin internally. This is the only port you open in a firewall.

Your data stays on your server. CDRs, recordings, transcripts, and the analytics database all live inside /opt/astervis on your machine. The product never runs in the cloud. The only outbound traffic is license verification and — if you turn it on — AI analysis to Google Gemini.

Where to go next

Last updated on

On this page