Skip to content

SPOT Platform Deployment

Deploy SPOT (Spear-Phishing Overwatching Tool) on your server with automatic HTTPS.

Analyzers Required

SPOT requires external analyzer services to perform email analysis. The core platform provides orchestration only - without analyzers, all analysis jobs will fail with errors like:

  • No URL configured for analyzer: analyzer-nlp
  • Only 0 analyzers succeeded, minimum required: 2

See Installing plugins below for installation instructions.

Prerequisites

Requirement Version Check
Docker 20.10+ docker --version
Docker Compose 2.0+ docker compose version
Git 2.0+ git --version

A public domain pointed at the server is recommended for production (it's what lets Traefik issue real Let's Encrypt certificates), but strictly optional. For an evaluation install you can set DOMAIN=spot.local (or any non-public TLD) in .env, add a matching entry to /etc/hosts, and Traefik will fall back to its built-in self-signed cert — see the local DNS note under Quick Start.

System Requirements: 2GB RAM minimum (4GB recommended), 20GB disk space.

Quick Start

# Clone this repository
cd /opt
git clone https://codeberg.org/SPOT_Project/deploy.git spot
cd spot

# Configure domain and secrets
cp .env.example .env
vim .env  # Set all required variables

# Start SPOT
docker compose up -d

Docker Desktop on macOS: share /opt/spot

On Linux servers (the supported deployment target) this Just Works. On macOS — useful for an evaluation install — Docker Desktop only shares the user's home directory by default, so the api-gateway's bind-mount of ./docker-compose.yml (used by the System Updates page to detect compose drift) fails with mounts denied: The path /opt/spot/docker-compose.yml is not shared from the host. Two fixes:

  • Add /opt/spot to Docker Desktop -> Settings -> Resources -> File Sharing and Apply & Restart, or
  • Clone the repo under ~/spot instead of /opt/spot (Docker Desktop already shares $HOME). All other commands in this guide work the same; just substitute the path.

Production deployments belong on Linux; the macOS path is for quick evaluation only.

Local DNS (.local, .test, .localhost) and ACME

For an evaluation install pointed at a non-public domain (e.g. DOMAIN=spot.local resolved via /etc/hosts), Let's Encrypt refuses to issue with urn:ietf:params:acme:error:rejectedIdentifier :: Domain name does not end with a valid public suffix (TLD). Traefik logs the rejection on every router (traefik.${DOMAIN}, api.${DOMAIN}, the dashboard) and falls back to its built-in self-signed certificate, so the stack still serves over HTTPS — just expect a browser cert warning and the ACME error lines in docker compose logs traefik. Both are cosmetic on a non-public TLD; they go away once DOMAIN resolves to a real, publicly reachable name.

DNS Setup

Before starting, create DNS A and/or AAAA records pointing to your server:

Record Example
DOMAIN spot.example.com -> 1.2.3.4
api.DOMAIN api.spot.example.com -> 1.2.3.4

Traefik will automatically obtain Let's Encrypt certificates.

Using self-signed certificate

If the application is not publicly reachable, Traefik will not be able to generate Let's Encrypt certificate and will fall back to using self-signed certificate.

Verify Installation

# Check services
docker compose ps

# Expected: 9+ services, all healthy
#   spot-traefik
#   spot-postgres
#   spot-redis
#   spot-rabbitmq
#   spot-api-gateway
#   spot-analyzer-orchestrator
#   spot-mail-orchestrator
#   spot-web-dashboard
#   spot-knowledge
#   ...

# Test API (replace with your domain)
curl https://api.spot.example.com/health

# Access Dashboard
# Open https://spot.example.com

Create Admin User

On first start, create an admin user by setting these in .env:

SPOT_BOOTSTRAP_ADMIN=true
SPOT_ADMIN_USERNAME=admin
SPOT_ADMIN_PASSWORD=your_secure_password_12chars+
SPOT_ADMIN_EMAIL=admin@example.com

If you change this after having created the stack, simply recreate the api-gateway:

docker compose up -d api-gateway

Installing plugins

Required for Email Analysis

The SPOT platform is an orchestration layer that coordinates plugins. Without at least two analyzer plugins installed, no email analysis can be performed. Mail retriever and context provider plugins are optional.

SPOT has three kinds of plugins, all installed the same way:

Kind Purpose
analyzer Produces the phishing verdict.
context_provider Enriches emails with organisational data before analysis.
mail_retriever Pushes inbound mail into the platform.

The recommended way to install a plugin is from the dashboard's catalog. The CLI / manual flow is documented further down as a fallback for air-gapped or scripted deployments.

The official plugins are published on Docker Hub under the spotproject user (mirrored from Codeberg's SPOT_Project organisation). A fresh deployment seeds the Docker Hub source automatically on first start, so the catalog is populated as soon as the api-gateway is up ; no manual source registration and no auth required.

To install a plugin:

  1. Sign in to the dashboard as an admin.
  2. Go to Plugins -> Catalog.
  3. Pick a plugin (e.g. analyzer-nlp), open its detail page, click Install.
  4. SPOT pulls the container, registers the plugin in spot.yaml, applies its default settings, and starts it. The plugin then appears under Plugins -> Installed with a status chip.

Disabling the default source

The seed only runs when the source registry is empty, so deleting or replacing the default source from the UI is permanent. To skip the seed entirely on a fresh install, set SPOT_BOOTSTRAP_DEFAULT_PLUGIN_SOURCE=false in .env before the first start (typical for air-gapped deployments or operators using a custom registry).

Catalog detail page showing the Install button before installation

Catalog detail page for an analyzer plugin, before installation.

Installed detail page after installation, with status chip and Edit Settings action

Same plugin after installation: status chip, Edit Settings, Restart, Uninstall.

For day-to-day plugin operations (updates, settings, uninstall), see the dashboard's Operator guide.

Bundled official plugins

Plugin Kind Description
analyzer-nlp analyzer NLP-based analysis (DistilBERT, NER).
analyzer-llm analyzer LLM-based analysis via Ollama.
analyzer-rules analyzer Rule-based contextual analysis.
provider-employee-dir context_provider LDAP / Entra ID employee directory enrichment.
retriever-smtp mail_retriever Postfix content_filter integration. See Mail integration.

Use this only if the dashboard install is not an option

Manual install is for air-gapped deployments, custom registries, or pinning a plugin to a specific image tag outside the catalog. The dashboard flow is preferred because it tracks the install in spot.yaml, applies the plugin's settings schema, and integrates with update / uninstall.

The orchestrator finds plugins through the plugins: tree in core/config/spot.yaml. To add a plugin manually, edit that file:

plugins:
  analyzers:
    analyzer-nlp:
      enabled: true
      url: "http://analyzer-nlp:8000"
      settings: {}

Then run the analyzer container yourself on the spot-network so the orchestrator can reach it:

docker run -d --name analyzer-nlp \
  --network spot-network \
  --restart unless-stopped \
  spotproject/analyzer-nlp:latest

The orchestrator re-reads spot.yaml per job, so no restart is needed.

Verify

The dashboard's Health page lists every installed plugin and its current status. From the command line:

docker compose logs analyzer-orchestrator | grep -i analyzer

A healthy install logs the analyzer URL on first job. No URL configured for analyzer means the entry under plugins.analyzers.<name> is missing or its enabled flag is false.

Project Description Link
SPOT Core Platform architecture, CLI, API reference Core Documentation
SPOT SDK Analyzer development, API contracts, SDK usage SDK Documentation