Skip to content

Server overview

The Scouter server is a Rust-based server designed to run independent of the Python client. It handles the event system (via Kafka, RabbitMQ, Redis, or the default HTTP queue), database CRUD operations, background drift detection, Agent evaluation, and alerting.

Features:

  • Event System - Supports Kafka, RabbitMQ, Redis, and a built-in HTTP queue for sending monitoring events to the server
  • Database Storage - Leverages Postgres (sqlx) for short-term data storage and DataFusion (Parquet/object store) for long-term archival
  • Alerting - Integrates with OpsGenie and Slack for alerting
  • Data Retention and Partitioning - Built-in retention and partitioning strategies via pg_partman and pg_cron
  • Authentication - Built-in JWT authentication system
  • gRPC + HTTP - Dual-protocol server (Axum HTTP on port 8000, Tonic gRPC on port 50051)

This section is for developers who want to run Scouter locally for development or testing.

  • Rust (stable toolchain)
  • Docker + Docker Compose
  • uv (for Python client work)
  • Git
Terminal window
git clone https://github.com/demml/scouter.git
cd scouter

This spins up PostgreSQL, Kafka, RabbitMQ, and Redis via Docker Compose:

Terminal window
make build.all_backends

This uses the server-backends Docker Compose profile which starts all services and waits until they are healthy before returning.

Terminal window
make start.server

This will:

  1. Kill any existing process on port 8000
  2. Start all backend services (if not already running)
  3. Build the server binary with all event bus features enabled
  4. Start the server in the background with Kafka, RabbitMQ, and Redis configured

The server will be available at http://localhost:8000.

Terminal window
curl http://localhost:8000/healthcheck

After making any Rust changes, rebuild the Python extension:

Terminal window
cd py-scouter
make setup.project

Then configure the client to point at your local server:

Terminal window
export SCOUTER_SERVER_URI=http://localhost:8000
export SCOUTER_USERNAME=admin
export SCOUTER_PASSWORD=admin
Terminal window
make build.shutdown
Terminal window
# Unit tests — no Docker required
make test.unit
# Integration tests — requires backends running
make build.all_backends
make test.needs_sql
# Python unit tests
cd py-scouter && make test.unit
# Python integration tests — requires running server
cd py-scouter && make test.integration

There are a few different ways to deploy the Scouter server in production.

Scouter requires a PostgreSQL 16.3+ database with the pg_partman and pg_cron extensions. See the PostgreSQL setup guide for details.

Set the following environment variable before starting the server:

Terminal window
export DATABASE_URI=postgresql://<user>:<password>@<host>:<port>/<db>

Pre-built Docker images are published on every release for the following platforms:

Amd64 (x86_64-unknown-linux-gnu)

ImageTag SuffixFeatures
ubuntuubuntuKafka, RabbitMQ
alpinealpineKafka, RabbitMQ
scratchscratchKafka, RabbitMQ
debiandebianKafka, RabbitMQ
distrolessdistrolessKafka, RabbitMQ

Arm64 (aarch64-unknown-linux-gnu)

ImageTag SuffixFeatures
ubuntuubuntuKafka, RabbitMQ
alpinealpineKafka, RabbitMQ
scratchscratchKafka, RabbitMQ
debiandebianKafka, RabbitMQ
distrolessdistrolessKafka, RabbitMQ
Terminal window
docker pull demml/scouter:ubuntu-amd64-kafka-latest
Terminal window
docker run -d \
--name scouter \
-p 8000:8000 \
-e DATABASE_URI=postgresql://user:pass@host:5432/db \
-e SCOUTER_ENCRYPT_SECRET=<your-32-byte-secret> \
-e SCOUTER_REFRESH_SECRET=<your-32-byte-secret> \
-e SCOUTER_BOOTSTRAP_KEY=<your-32-byte-key> \
demml/scouter:ubuntu-amd64-kafka-latest

Binaries for various architectures are published on every release. Download and run the binary directly:

Terminal window
# Download from GitHub releases
curl -L https://github.com/demml/scouter/releases/latest/download/scouter-server-linux-amd64 -o scouter-server
chmod +x scouter-server
./scouter-server

Binaries can be found here.

Terminal window
# Default build (HTTP queue only)
cargo build -p scouter-server --release
# With Kafka support
cargo build -p scouter-server --release --features "kafka"
# With RabbitMQ support
cargo build -p scouter-server --release --features "rabbitmq"
# With Redis support
cargo build -p scouter-server --release --features "redis_events"
# With all event bus features
cargo build -p scouter-server --release --all-features
FlagDescription
kafkaEnables Kafka consumer via the rdkafka crate
rabbitmqEnables RabbitMQ consumer via the lapin crate
redis_eventsEnables Redis Pub/Sub consumer

VariableDescriptionDefault
DATABASE_URIPostgreSQL connection stringpostgresql://postgres:postgres@localhost:5432/postgres
MAX_POOL_SIZEMaximum DB connections in the pool200
MIN_POOL_SIZEMinimum DB connections in the pool20
DB_ACQUIRE_TIMEOUT_SECONDSTimeout (seconds) to acquire a connection10
DB_IDLE_TIMEOUT_SECONDSIdle connection timeout (seconds)300
DB_MAX_LIFETIME_SECONDSMaximum connection lifetime (seconds)1800
DB_TEST_BEFORE_ACQUIRETest connections before acquiring from pooltrue
DATA_RETENTION_PERIODDays to retain data in the DB before archiving to long-term storage30
TRACE_FLUSH_INTERVAL_SECONDSHow often (seconds) to flush trace spans to the DB15
TRACE_STALE_THRESHOLD_SECONDSHow long (seconds) before an open trace span is considered stale30
TRACE_CACHE_MAX_SIZEMaximum number of trace spans to hold in memory10000
ENTITY_CACHE_MAX_SIZEMaximum number of entity definitions to cache in memory1000

Background workers that run scheduled drift detection and alerting.

VariableDescriptionDefault
POLLING_WORKER_COUNTNumber of drift detection/alerting worker threads4
MAX_RETRIESMaximum retries for failed polling tasks3

Background workers for asynchronous Agent evaluation.

VariableDescriptionDefault
GENAI_WORKER_COUNTNumber of agent evaluation worker threads2
GENAI_MAX_RETRIESMaximum retries for failed agent evaluation tasks3
GENAI_TRACE_WAIT_TIMEOUT_SECSSeconds to wait for a trace to arrive before timing out10
GENAI_TRACE_BACKOFF_MILLISBackoff delay (ms) between trace polling attempts100
GENAI_TRACE_RESCHEDULE_DELAY_SECSDelay (seconds) before rescheduling a failed agent evaluation task30

For the built-in HTTP event consumer (default transport, no extra setup required).

VariableDescriptionDefault
HTTP_CONSUMER_WORKER_COUNTNumber of HTTP consumer worker threads1

Enabled when KAFKA_BROKERS is set and the kafka feature flag is compiled in.

VariableDescriptionDefault
KAFKA_BROKERSComma-separated list of Kafka broker addresseslocalhost:9092
KAFKA_WORKER_COUNTNumber of Kafka consumer worker threads3
KAFKA_TOPICKafka topic(s) to consume (comma-separated)scouter_monitoring
KAFKA_GROUPKafka consumer group IDscouter
KAFKA_OFFSET_RESETOffset reset policyearliest
KAFKA_USERNAMESASL username
KAFKA_PASSWORDSASL password
KAFKA_SECURITY_PROTOCOLSecurity protocol (PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL)SASL_SSL
KAFKA_SASL_MECHANISMSASL mechanismPLAIN
KAFKA_CERT_LOCATIONPath to CA certificate file

Enabled when RABBITMQ_ADDR is set and the rabbitmq feature flag is compiled in.

VariableDescriptionDefault
RABBITMQ_ADDRRabbitMQ AMQP addressamqp://guest:[email protected]:5672/%2f
RABBITMQ_CONSUMER_COUNTNumber of RabbitMQ consumers3
RABBITMQ_PREFETCH_COUNTMessages to prefetch per consumer10
RABBITMQ_QUEUEQueue namescouter_monitoring
RABBITMQ_CONSUMER_TAGConsumer tagscouter

Enabled when REDIS_ADDR is set and the redis_events feature flag is compiled in.

VariableDescriptionDefault
REDIS_ADDRRedis server addressredis://127.0.0.1:6379
REDIS_CONSUMER_COUNTNumber of Redis consumer workers3
REDIS_CHANNELRedis Pub/Sub channel namescouter_monitoring

Scouter uses JWT-based authentication. For production deployments, always set all three secrets to strong random values — if any are unset, Scouter will fall back to a deterministic default key which is unsafe.

VariableDescription
SCOUTER_ENCRYPT_SECRETSigns JWT access tokens. Must be a base64-encoded PBKDF2-HMAC-SHA256 key (32 bytes).
SCOUTER_REFRESH_SECRETSigns JWT refresh tokens. Same format as above.
SCOUTER_BOOTSTRAP_KEYUsed to create the initial admin user on first startup. Also serves as a shared key for inter-service authentication (e.g. OpsML integration). Same format as above.

To generate a suitable secret:

Terminal window
openssl rand -base64 32

Controls where archived data (expired from PostgreSQL) is written for long-term storage.

VariableDescriptionDefault
SCOUTER_STORAGE_URIObject store URI. Supports s3://, gs://, az://, or a local path./scouter_storage
AWS_REGIONAWS region (required for S3)us-east-1
GOOGLE_ACCOUNT_JSON_BASE64Base64-encoded GCP service account JSON (optional, for GCS)

URI examples:

Terminal window
# AWS S3
export SCOUTER_STORAGE_URI=s3://my-scouter-bucket
# Google Cloud Storage
export SCOUTER_STORAGE_URI=gs://my-scouter-bucket
# Azure Blob Storage
export SCOUTER_STORAGE_URI=az://my-scouter-container
# Local filesystem (default)
export SCOUTER_STORAGE_URI=./scouter_storage

See the object-store crate docs for provider-specific credential configuration:

These are used by the Python client (ScouterClient, ScouterQueue) to connect to the server.

VariableDescriptionDefault
SCOUTER_SERVER_URIHTTP server addresshttp://localhost:8000
SCOUTER_GRPC_URIgRPC server addresshttp://localhost:50051
SCOUTER_USERNAMEUsername for authenticationguest
SCOUTER_PASSWORDPassword for authenticationguest
SCOUTER_AUTH_TOKENPre-issued auth token (alternative to username/password)