Documentation

Set up StyloBot: illustrated guide

Step-by-step guide Updated 24 August 2026

This is the ten-minute path to a working StyloBot gateway in front of an existing app, from a single Docker Compose file to a licensed, dashboard-managed fleet. Every command here was tested against the real gateway image — nothing in this guide documents a feature that does not exist.

The full reference pages live alongside this one: add to Docker Compose, running locally, configuration, how StyloBot works.

What you are building

flowchart LR
    client[Visitors] -->|public port 8080| gw[StyloBot gateway]
    gw -->|detection pipeline| app[Your app on the Compose network]
    gw -.observe mode: pass-through.-> client
    subgraph optional["Optional: commercial"]
      pg[(PostgreSQL)]
      gw <-->|persistence + fleet state| pg
      dash[Commercial dashboard]
      gw <-->|telemetry| dash
    end

The gateway is the only public HTTP port. Your app stops publishing its own port and lives on the internal Compose network; every request passes the detection pipeline first. Start in observe mode (detection runs, nothing is blocked), confirm traffic, then choose an enforcement policy.

1. Add the gateway to an existing compose stack

Take an existing compose.yml with an app service. Remove the app's ports: entry (keep expose:) and add the gateway service:

services:
  stylobot:
    image: scottgal/stylobot-gateway:latest
    ports:
      - "8080:8080"
    environment:
      ASPNETCORE_URLS: http://+:8080
      DEFAULT_UPSTREAM: http://app:3000
    depends_on:
      - app

  app:
    image: my-company/my-app:latest
    expose:
      - "3000"

DEFAULT_UPSTREAM is the zero-config entry point: the gateway builds a catch-all route to that URL. Replace app:3000 with your service name and port — the gateway calls the upstream by Compose service name, never localhost (that would be the gateway container itself). Do not publish both app and stylobot: callers could then bypass detection entirely.

docker compose up -d app stylobot
sequenceDiagram
    participant C as Visitor
    participant G as Stylobot gateway
    participant A as Your app
    C->>G: request
    G->>G: detection pipeline (67 detectors)
    alt observe mode
        G->>A: forward unchanged
    else enforce mode
        G-->>A: block / challenge / throttle
    end
    A-->>C: response

Point your existing reverse proxy, load balancer, or DNS at host port 8080. Your app receives the verdict in headers — X-Bot-Detected, X-Bot-Confidence, X-Bot-Detection-Probability — with zero latency overhead.

2. Variant A — zero-config default (no database)

Nothing to configure: with no DB_PROVIDER set, the gateway runs detection with in-process state. This is the whole story for one node — the same engine, the same detectors, no extra services:

services:
  stylobot:
    image: scottgal/stylobot-gateway:latest
    ports:
      - "8080:8080"
    environment:
      ASPNETCORE_URLS: http://+:8080
      DEFAULT_UPSTREAM: http://app:3000
    volumes:
      - stylobot-data:/app/data
    depends_on:
      - app

volumes:
  stylobot-data:

The /app/data volume keeps the gateway's certificates and logs across restarts. Observe mode is the default: BotDetection:BlockDetectedBots is false, so nothing is blocked until you say so. Watch the per-request verdicts in the container logs, then flip to enforcement (see the configuration reference for every key).

Kill switch — disable everything if it malfunctions

Two levels of shutoff, both effective immediately on restart:

  • Full disable — pass everything through untouched. The master switch: BotDetection:Enabled defaults to true; set it to false and the middleware does not run detection at all — requests pass straight to the upstream, no headers, no throttling:

    environment:
      BotDetection__Enabled: "false"
    
  • Observe-only — detection runs, nothing is ever blocked. This is the shipped default: BotDetection:BlockDetectedBots is false. The pipeline scores every request and injects the X-Bot-* headers, but never blocks, challenges, or throttles. Use this while you trust the verdicts, or as a softer rollback than the full switch.

Where SQLite fits: the standalone gateway's supported database providers are Postgres and SqlServer (set via DB_PROVIDER). The SQLite you see in the marketing copy is the ASP.NET pack's default store — embed StyloBot in a .NET app with add to ASP.NET Core and SQLite is the file-backed default there. Single Site, the entry commercial tier, ships that pack with SQLite out of the box (why Single Site).

3. Variant B — PostgreSQL

SQLite-free single-node in-memory is right for one host. When several gateways write shared session and signature state, or your history outgrows the process, move to PostgreSQL. The FOSS gateway takes its database from two env vars:

services:
  stylobot:
    image: scottgal/stylobot-gateway:latest
    ports:
      - "8080:8080"
    environment:
      ASPNETCORE_URLS: http://+:8080
      DEFAULT_UPSTREAM: http://app:3000
      DB_PROVIDER: Postgres
      DB_CONNECTION_STRING: Host=postgres;Database=stylobot;Username=stylobot;Password=${POSTGRES_PASSWORD}
    depends_on:
      - app
      - postgres

  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: stylobot
      POSTGRES_USER: stylobot
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Set POSTGRES_PASSWORD in .env}
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:

The commercial gateway (license-gated) uses its own persistence wiring — BotDetection__Commercial__Postgres__ConnectionString plus StyloBotDashboard__PostgreSQL__ConnectionString for the dashboard's telemetry store, with StyloBotDashboard__PostgreSQL__AutoInitializeSchema=true — see the dashboard setup below.

4. HTTPS — built-in LetsEncrypt, or your own certificates

The gateway terminates TLS itself — no Caddy, no separate reverse proxy required. Three TLS modes, all env-driven:

4a. Automatic LetsEncrypt certificates

Set the domain and an ACME account email; the gateway obtains and renews the certificate automatically, storing it in /app/data/certs:

services:
  stylobot:
    image: scottgal/stylobot-gateway:latest
    ports:
      - "443:8443"
    environment:
      ASPNETCORE_URLS: http://+:8080
      DEFAULT_UPSTREAM: http://app:3000
      GATEWAY_HTTPS_DOMAIN: gateway.example.com
      GATEWAY_HTTPS_ACME_EMAIL: you@example.com
      GATEWAY_HTTPS_ACME_CERT_STORE: /app/data/certs
    volumes:
      - stylobot-data:/app/data

The HTTPS listener is on GATEWAY_HTTPS_PORT (default 8443). DNS for gateway.example.com must already point at the host before the ACME challenge can complete.

4b. Existing certificates (files or PFX)

Bring your own cert as a PEM pair or a password-protected PFX:

services:
  stylobot:
    image: scottgal/stylobot-gateway:latest
    ports:
      - "443:8443"
    environment:
      ASPNETCORE_URLS: http://+:8080
      DEFAULT_UPSTREAM: http://app:3000
      GATEWAY_HTTPS_CERT_PATH: /certs/fullchain.pem
      GATEWAY_HTTPS_CERT_KEY_PATH: /certs/privkey.pem
      # or a PFX: GATEWAY_HTTPS_CERT_PATH=/certs/gateway.pfx + GATEWAY_HTTPS_CERT_PASSWORD=...
    volumes:
      - ./certs:/certs:ro

Certificates are read from the mounted files — renew them in place and restart the gateway.

4c. Upstreams over TLS

The upstream can be HTTPS too — DEFAULT_UPSTREAM: https://app:3000 works the same way. The usual pitfall is the internal upstream using a self-signed or internal-CA certificate; the gateway validates upstream certificates, so either present a certificate the gateway trusts, or terminate TLS at the gateway (4a/4b) and keep the internal hop plain HTTP — the recommended shape for Compose networks.

flowchart LR
    V[Visitor] -->|443 TLS| G[Gateway 8443]
    G -->|80 plain, internal| A[Your app]

5. Commercial dashboard — licensing and what it unlocks

The commercial gateway is license-gated. Everything underneath is the same AGPL engine; the license unlocks the management surface.

Get a license. A 30-day trial is issued from the site (start a free trial), or buy a plan (pricing). The portal mints an Ed25519-signed token bound to your account.

Activate it — set the token the gateway validates:

services:
  stylobot:
    image: scottgal/stylobot-gateway:latest
    environment:
      BotDetection__Commercial__LicenseToken: ${STYLOBOT_LICENSE_TOKEN}

The token's signed payload carries the tier, expiry, and feature flags; a gateway without a token (or with an expired one) runs the FOSS feature set.

What the license unlocks:

  • Live config editing with hot reload (edit policy in the dashboard, applied without restarting the gateway)
  • The reporting dashboard: traffic, sessions, fingerprints, per-domain policy
  • The ASP.NET, log, and OTel packs for a .NET stack
  • Postgres persistence, Redis pub/sub coordination, fleet management and the control plane

Tiers differ in scale and management, never in detection quality — the FOSS engine is identical on every tier. The tier pages spell out the differences: Single Site, Startup, Enterprise.

Next steps