Operator track

Self-host overview

Run the full Smartizy backend in your own environment. Five Docker Compose stacks make up the platform: two datastores, the ingest receiver, the admin console, and an edge proxy. This page explains how they fit together and the order to bring them up.

Self-hosting puts every beacon and every dashboard query inside your own infrastructure. The browser SDK and the dashboards are unchanged, so this track is purely about deploying and wiring the backend. If you only want to instrument a site against the hosted service, start at Quickstart instead.

How the stacks fit together #

Each stack lives under docker/<stack>/ and is one independent docker compose unit. The build context for every app image is the repo root, so the Dockerfiles can copy from src/. The five stacks are:

  • ClickHouse (docker/clickhouse): the analytics datastore. Holds the rum.events table and the rollups that power the dashboards.
  • PostgreSQL (docker/pg): the config datastore. Holds tenants, apps, ingest tokens, policies, and routing in the rum_config database.
  • Ingest receiver (docker/ingest): accepts beacons at /v1/events and serves the collector bundle at /v1/rum/*. Writes events to ClickHouse and reads its per-app config from Postgres.
  • Admin console (docker/admin): one image carrying the control-plane API and the SPA. Reads and writes Postgres, and reads ClickHouse for dashboards.
  • Edge proxy (docker/front): terminates TLS and routes by Host header to the admin console and the ingest receiver.

The two app stacks (ingest, admin) talk to the datastores; the edge proxy sits in front of both app stacks. Browsers reach the ingest receiver to send beacons, and operators reach the admin console through the same edge proxy.

Prerequisites #

  • A host with Docker Engine and the Docker Compose plugin.
  • The repository checked out. The build context for the app images is the repo root.
  • An OIDC issuer for the admin console (the admin stack validates tokens against it).
  • A TLS certificate in Azure Key Vault if you use the edge proxy (docker/front).

Deployment order #

Bring the stacks up in dependency order. Datastores first, then the apps, then the edge.

Create the shared network

Every stack joins an externally created Docker network so containers reach each other by service name.

Shell bash
# Create the shared network once, before bringing up any stack.
docker network create ambilobe

Start the datastores

Bring up docker/clickhouse and docker/pg. ClickHouse bootstraps the rum schema on first start; Postgres boots an empty rum_config database. See Datastores.

Start the ingest receiver

Build and start docker/ingest. It applies pending rum_config migrations on startup and begins accepting beacons. See Ingest receiver.

Start the admin console

Build and start docker/admin. It also applies pending migrations on startup and serves the SPA plus the control-plane API. See Admin console.

Start the edge proxy

Build and start docker/front to terminate TLS and route public traffic. See Edge & TLS.

The per-stack flow is the same everywhere:

Shell bash
# Each stack follows the same flow from the repo root.
cd docker/<stack>
cp .env.example .env   # first time only, then fill in credentials
docker compose build   # only for the app images (ingest, admin, front)
docker compose up -d

The shared Docker network #

Every stack attaches to one external network named ambilobe. Containers address each other by service name over it: the ingest receiver reaches Postgres at host postgres and ClickHouse at host clickhouse; the edge proxy reaches the apps at admin and ingest. Create the network once before the first docker compose up, or every stack will fail to start.

What stays the same #

Self-hosting changes only where the data lives. Apps still embed the same browser SDK, and analysts still read the same dashboards. Once the receiver is up, register it as an ingest service and point apps at it, then embed the snippet exactly as the hosted track describes in Install the snippet. The link between a deployed receiver and the snippet an app embeds is covered in Routing.