Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,226 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SEP - Services Enablement Platform

Table of Contents

Prerequisites

  • Python Version Requirements
  >=3.11.9, !=3.12.0, !=3.12.1, !=3.12.2, <3.14

You can start Casdoor on port 9999 with Docker by running

docker run --detach --name casdoor \
--volume casdoor-data:/var/lib/mysql:z,rw \
--publish 9999:8000/tcp \
casbin/casdoor-all-in-one

You can start PMM with Docker by running

docker run --detach --restart always \
--publish 8443:443 \
--volume pmm-data:/srv \
--name pmm-server \
percona/pmm-server:2

For the purpose of development, you can run Nomad with

sudo nomad agent -node="pmm-server" -dev \
        -bind 0.0.0.0 \
        -network-interface='{{ GetDefaultInterfaces | attr "name" }}'

You can start the Celery Worker with:

celery -A app.tasks.celery worker -l info

and the Celery Beart with:

celery -A app.tasks.celery beat -S sqlalchemy --loglevel=info

For development purposes, you can also start Celery with SEP.

Setup

  1. Clone the repository and enter the cloned folder:
git clone https://github.com/percona/SEP.git
cd SEP
  1. Create and activate a virtualenv with the required packages:
make venv
source venv/bin/activate

Tip

Use venv/bin/activate.fish if you're on a Fish shell.

  1. Create SEP's databases with make migrate:
make migrate
  1. Add your Redirect URL to the Casdoor application

In Casdoor's web interface, navigate to Identity > Applications > app-built-in (should be in this link) and scroll to Redirect URLs.

The Redirect URL you should add depends on how SEP is running (see Usage). For example, if you're running SEP in your localhost with HTTP in port 8000, you shoul add the URLs http://localhost:8000/oauth/callback and http://127.0.0.1:8000/oauth/callback.

image

  1. Create a .env file in the project root folder to store your secrets. See the secrets section of the README for more details.

Configuration

SEP will read settings in the following order of priority:

  1. Environment variables
  2. .env file
  3. Secret files
  4. Settings file

By default, the .env file is expected to be .env and the settings file settings.yaml. You can change that by using the environment variables ENV_FILE and SETTINGS_FILE. Secret files are read from the directory named by SECRETS_DIR, which is unset by default; when unset, no secret files are read. See the secrets section for how to name them.

The settings.yaml has base settings that you can (but don't need to) change.

Some settings are app-specific and you might not need them for running another app. These are some, but not all, the possible settings you can have, per app:

Name App Required Default settings.yaml (development)
BASE_URL all no Built from the user's request N/A
ALLOWED_HOSTS all yes N/A ["localhost", "127.0.0.1"]
ALLOW_CONCURRENT_SESSIONS all no False False
SSL_CAFILE all no null null
AUTH__PROVIDER__CASDOOR__ENDPOINT all yes N/A http://localhost:9999
AUTH__PROVIDER__CASDOOR__FRONT_ENDPOINT all no The same as AUTH__PROVIDER__CASDOOR__ENDPOINT //:9999
AUTH__PROVIDER__CASDOOR__CERTIFICATE_PATH all no null null
AUTH__PROVIDER__CASDOOR__ORGANIZATION_NAME all no built-in N/A
AUTH__PROVIDER__CASDOOR__APPLICATION_NAME all no app-built-in sep-app
AUTH__PROVIDER__CASDOOR__ALLOWED_ISSUERS all no [<ENDPOINT>] [http://localhost:9999, http://127.0.0.1:9999]
CELERY__BROKER_URL all no N/A filesystem://
CELERY__BEAT_DBURI all no N/A sqlite:///schedule.db
LOGGING all no WARNING N/A
BACKEND_CORS_ORIGINS all no [] [http://localhost:8000, http://127.0.0.1:8000]
TASKS__NOMAD__ENDPOINT tasks yes N/A http://127.0.0.1:4646
TASKS__NOMAD__SECURE tasks no False N/A
TASKS__NOMAD__VERIFY_SSL tasks no False True
TASKS__NOMAD__TIMEOUT tasks no 10 10
TASKS__NOMAD__MINIFY_PAYLOAD tasks no True True
TASKS__NOMAD__LOG_SOCKET_READ_TIMEOUT tasks no 10 10
TASKS__SYNC_LOCK_TTL tasks no 300 300
TASKS__ANONYMIZER__DEFAULT_ENTITIES tasks no seven high-confidence entities (see below) [] (anonymization disabled)
TASKS__EXECUTE_MODE tasks no background N/A
TASKS__DATABASE__ENGINE tasks no sqlite N/A
TASKS__DATABASE__NAME tasks no tasks.db N/A
TASKS__DATABASE__USER tasks no N/A N/A
TASKS__DATABASE__PASSWORD tasks no N/A N/A
TASKS__DATABASE__HOST tasks no "" ""
TASKS__DATABASE__PORT tasks no N/A N/A
SEP__INVENTORY_ENDPOINT sep yes N/A http://localhost:8000/api/inventory
SEP__TASKS_ENDPOINT sep yes N/A http://localhost:8000/api/tasks
SEP__OAUTH__REDIRECT_URI sep yes N/A /oauth/callback
SEP__OAUTH__POST_LOGIN_URI sep no / N/A
SEP__OAUTH__AUTH_LINK sep no CasdoorOptions.SYNC_SDK.get_auth_link(REDIRECT_URI) N/A
SEP__PROXY_HEADERS sep no False False
SEP__SYNC_REFRESH_TIME sep no 5 5
SEP__SESSION__COOKIE_NAME sep no authToken casdoorToken
SEP__SESSION__SECURE sep no False False
SEP__SESSION__HTTP_ONLY sep no True True
SEP__SESSION__SAME_SITE sep no lax lax
SEP__SESSION__MAX_AGE sep no 3600 3600
SEP__TEMPLATES_DIR sep no templates templates
SEP__STATIC_DIR sep no static N/A
SEP__SECURITY_HEADERS__CONTENT_SECURITY_POLICY_EXCLUDE_PATHS sep no [] [/api/docs, /api/inventory/docs, /api/tasks/docs]
ALERTING__SOURCE_SUFFIX all no "" ":dev"

The active authentication provider is configured under AUTH__PROVIDER__<NAME>__*, and exactly one provider may be configured. Casdoor is the built-in default, shipped as the AUTH.PROVIDER.casdoor entry in settings.yaml (AUTH__PROVIDER__CASDOOR__*). To use a different provider, replace that casdoor entry in settings.yaml with your provider's entry — configuring a second provider (e.g. adding AUTH__PROVIDER__CUSTOM__* on top of the shipped casdoor block) is rejected at startup, since only one provider may be active. An out-of-tree provider uses the CUSTOM name with AUTH__PROVIDER__CUSTOM__PROVIDER_CLASS (a dotted import path to a BaseAuthProvider subclass) plus that class's own fields. The legacy top-level CASDOOR__* variables are deprecated but still honored (a startup warning is logged); migrate to AUTH__PROVIDER__CASDOOR__*.

Path settings (AUTH__PROVIDER__CASDOOR__CERTIFICATE_PATH, TEMPLATES_DIR, STATIC_DIR, etc.) may have relative or absolute values. Relative paths will be resolved from the project root folder.

Session Management

SEP provides configurable session management through the SEP__SESSION section:

SEP:
  SESSION:
    COOKIE_NAME: casdoorToken
    SECURE: False
    HTTP_ONLY: True
    SAME_SITE: lax
    MAX_AGE: 3600
  • COOKIE_NAME: Name of the session cookie
  • SECURE: Whether the cookie should only be sent over HTTPS
  • HTTP_ONLY: Whether the cookie should be accessible only via HTTP(S)
  • SAME_SITE: SameSite attribute for the cookie (lax, strict, none)
  • MAX_AGE: Maximum age of the session in seconds

CSRF Protection

SEP uses double-submit cookie CSRF protection. The same token can be reused for multiple POST requests (e.g. from a React SPA), so you do not need to refetch a token after each request. Send the token in the X-CSRF-TOKEN header or in the form body as csrf-token. The token expires with the session (see Session Management).

CSRF token lifetime is tied to the session MAX_AGE. Use the same SEP__SESSION section to control how long the token stays valid:

SEP:
  SESSION:
    COOKIE_NAME: casdoorToken
    MAX_AGE: 604800   # 7 days (seconds); CSRF token expires after the same period

Security Headers

SEP supports configurable security headers through the SEP__SECURITY_HEADERS section:

SEP:
  SECURITY_HEADERS:
    CONTENT_SECURITY_POLICY_EXCLUDE_PATHS:
      - /api/docs
      - /api/inventory/docs
      - /api/tasks/docs

This allows you to exclude specific paths from Content Security Policy restrictions.

Anonymizer Configuration

The anonymizer plugin can be configured through the TASKS__ANONYMIZER section:

TASKS:
  ANONYMIZER:
    DEFAULT_ENTITIES:
      - CREDIT_CARD
      - EMAIL_ADDRESS
      - IBAN_CODE
      - IP_ADDRESS
      - PHONE_NUMBER
      - US_SSN
      - US_ITIN

The DEFAULT_ENTITIES setting specifies which Personally Identifiable Information (PII) entities should be anonymized by default when a task does not set an explicit anonymize_mask. The shipped default: profile uses the seven high-confidence entities above (checksum-validated or strong-regex recognizers). The development: profile sets DEFAULT_ENTITIES to an empty list so local task logs stay readable and no Presidio/spaCy engine is constructed.

Profile overlays merge onto default:: a non-empty list prepends to the inherited list, and an empty list clears it. To narrow the set relative to default:, edit the default: block or use a runtime settings override (do not rely on a shorter non-empty profile list alone). Operators can restore any of the fourteen PIIEntity members through settings.yaml or a runtime settings override without a code change. Use "*" to select every supported entity.

Sync Configuration

SEP provides several sync-related configuration options:

  • SEP__SYNC_REFRESH_TIME: Browser refresh interval during sync operations (in seconds)
  • TASKS__SYNC_LOCK_TTL: TaskHistory sync lock timeout (in seconds)

Nomad Advanced Configuration

Additional Nomad configuration options are available:

  • TASKS__NOMAD__MINIFY_PAYLOAD: Whether to minify payloads before dispatch
  • TASKS__NOMAD__LOG_SOCKET_READ_TIMEOUT: Socket read timeout for logs (in seconds)

Caution

*Do not store secrets in settings.yaml, as the file is shared in the git repository. See the secrets section of the README for more details.

Plugins

SEP works with modular plugins. Plugins are FastAPI routers that will be added to the application according to defined settings. Each plugin must have their own module in app.sep.plugins with a router inside. The following plugins are configured by default:

PLUGINS:
  - NAME: Schema Change
    MODULE_NAME: alters
    URI_PATH: /alters
    CSS_CLASS: alters
  - NAME: Inventory
    MODULE_NAME: inventory
    URI_PATH: /inventory
    CSS_CLASS: inventory
  - NAME: Archive
    MODULE_NAME: archives
    URI_PATH: /archives
    CSS_CLASS: archive
  - NAME: MySQL Backups
    MODULE_NAME: mysql_backups
    URI_PATH: /mysql_backups
    CSS_CLASS: mysql_backups
  - NAME: Checksums
    MODULE_NAME: checksums
    URI_PATH: /checksums
    CSS_CLASS: checksums
  - NAME: MongoDB Backups
    MODULE_NAME: backup_mongo
    URI_PATH: /backup_mongo
    CSS_CLASS: backup_mongo

Each plugin configuration includes:

  • NAME: Display name for the plugin
  • MODULE_NAME: Python module name in app.sep.plugins
  • URI_PATH: URL path where the plugin will be accessible
  • CSS_CLASS: CSS class for styling the plugin in the UI

Secrets

SEP needs some keys and secrets to interact with Casdoor. They are:

  • AUTH__PROVIDER__CASDOOR__CLIENT_ID
  • AUTH__PROVIDER__CASDOOR__CLIENT_SECRET

You can create a basic .env file template by running the following command in the project root folder:

echo -e "AUTH__PROVIDER__CASDOOR__CLIENT_ID=YOUR_CASDOOR_CLIENT_ID\nAUTH__PROVIDER__CASDOOR__CLIENT_SECRET=YOUR_CASDOOR_CLIENT_SECRET\n" > .env

Supplying a setting as a mounted file

Any setting can instead be supplied as a file inside the directory SECRETS_DIR names, which keeps the value out of the process environment. Name the file after the canonical __-nested variable the setting already uses — SECRET_KEY, SEP__DATABASE__PASSWORD, AUTH__PROVIDER__GRAFANA__SERVICE_ACCOUNT_TOKEN — and put the value in its contents. /run/secrets is the conventional mount point:

mkdir -p /run/secrets
openssl rand -hex 32 > /run/secrets/SECRET_KEY
SECRETS_DIR=/run/secrets uvicorn app.main:app

Surrounding whitespace is stripped, so a trailing newline is fine. A file only applies when nothing higher in the priority list supplies the same setting: an environment variable and a .env entry both still win over a file. A configured directory that does not exist logs a warning and is otherwise ignored, and a directory holding no matching file changes nothing.

Getting Casdoor's Client ID and Client Secret

  1. In a browser, open Casdoor's web interface and login (the default credentials are admin:123). If you followed the Docker tutorial, it should be in http://localhost:9999.

image

  1. Navigate to Identity > Applications > app-built-in. If you followed the Docker tutorial, it should be in http://localhost:9999/applications/built-in/app-built-in

image

  1. Copy the app's Client ID and Client Secret and replace the respective YOUR_CASDOOR_CLIENT_ID and YOUR_CASDOOR_CLIENT_SECRET in the .env file you created.

Environment

You can categorize settings by environments in settings.yaml:

default:
  # defaults settings shared by all environments
development:
  # development settings
production_docker:
  # production settings for Docker deployment

To switch environment, use the environment variable FASTAPI_ENV or add FASTAPI_ENV to your .env file.

Database Configuration

SEP supports multiple database engines for different components. Each component (SEP, Inventory, Tasks) can have its own database configuration:

SQLite Configuration (Development)

SEP:
  DATABASE:
    ENGINE: sqlite  # Database engine: sqlite, mysql, postgresql
    USER: null
    PASSWORD: null
    HOST: ""  # Database host (empty string for SQLite to avoid URL construction issues)
    PORT: null
    NAME: sep.db

INVENTORY:
  DATABASE:
    ENGINE: sqlite
    USER: null
    PASSWORD: null
    HOST: ""
    PORT: null
    NAME: inventory.db

TASKS:
  DATABASE:
    ENGINE: sqlite
    USER: null
    PASSWORD: null
    HOST: ""
    PORT: null
    NAME: tasks.db

MySQL/MariaDB Configuration

SEP:
  DATABASE:
    ENGINE: mysql
    USER: sep_user
    PASSWORD: your_secure_password
    HOST: localhost
    PORT: 3306
    NAME: sep_database

PostgreSQL Configuration

SEP:
  DATABASE:
    ENGINE: postgresql
    USER: sep_user
    PASSWORD: your_secure_password
    HOST: localhost
    PORT: 5432
    NAME: sep_database

Supported database engines:

  • sqlite: SQLite database (default for development)
  • mysql: MySQL/MariaDB database
  • postgresql: PostgreSQL database

Note

For SQLite databases, set HOST to an empty string to avoid URL construction issues.

Syncers

SEP features Inventory syncing with external services and APIs. You can choose the syncers you want to enable in the SEP.SYNCERS section of the configuration:

SEP:
  # ...
  SYNCERS:
    - SYNCER: PMMSyncer

Some syncers require additional configuration. PMM connection/auth config lives in the top-level PMM section (not under the syncer entry) — PMMSyncer reads it directly:

PMM:
  ENDPOINT: https://127.0.0.1:8443
  VERIFY_SSL: false

The PMM API key is a secret and should be set via an env var rather than settings.yaml:

PMM__API_KEY=<Your PMM API key>

Other syncers may take extra keyword arguments, defined globally through the SEP.SYNCER_EXTRA_KWARGS config (SEP__SYNCER_EXTRA_KWARGS for env settings).

PMMSyncer

Sync Nodes and Services with PMM. Requires the PMM setting with ENDPOINT, API_KEY, and optionally VERIFY_SSL, SSL_CAFILE, SSL_KEYFILE, and SSL_CERTFILE.

MySQLSyncer

Sync MySQL/MariaDB inventory (schemas and tables). Optional configuration under each MySQLSyncer entry in SEP.SYNCERS:

  • IGNORE_SCHEMAS: List of schema names to skip during sync (defaults typically include sys, performance_schema, mysql, information_schema).
  • DEFAULT_EXECUTOR_HOST: Nomad node name to use when the MySQL service host does not match any Nomad node. Set this when syncing RDS, DBaaS, or other remote MySQL instances: the sync payload runs on a Nomad client, so you must choose which client can reach the database. The value must match a node name (key) returned by /api/tasks/hosts/—not the node IP or address—otherwise task execution will fail. If unset, the first available Nomad host is used when there is no match.

Credentials are read on the Nomad client from ~/.my.cnf and ~/.mylogin.cnf. For each host the payload connects to, it looks up a login path by matching the RDS host: it tries a login path named like the host (e.g. host:port or host_port with colon replaced by underscore), then falls back to client. So for multiple RDS instances with different credentials, create a login path per host in ~/.mylogin.cnf (e.g. mysql_config_editor set --login-path=rds-a.region.rds.amazonaws.com:3306 --user=... --password --host=rds-a.region.rds.amazonaws.com --port=3306); the payload will use the matching path automatically.

Example for RDS/DBaaS:

SEP:
  SYNCERS:
    - SYNCER: MySQLSyncer
      IGNORE_SCHEMAS:
        - sys
        - performance_schema
        - mysql
        - information_schema
      DEFAULT_EXECUTOR_HOST: "ip-10-0-1-5.region.compute.internal"  # Nomad node name from /api/tasks/hosts/ that can reach RDS

MySQL Topology

Topology is a standalone, experimental Topology app that is shipped disabled by default. Enable it like any other plugin by activating its module in SEP.APPS:

SEP:
  APPS:
    - MODULE_NAME: topology
      ENABLED: true

When enabled, the app draws an interactive React Flow graph of every MySQL service the inventory knows about: replication chains (primary → replica with GTID/IO/SQL state), dual-primary pairs, and Percona XtraDB Cluster groups. It sources the MySQL host list from the Inventory service at request time. Topology data is collected live, on demand - there is no persisted snapshot in the database - by dispatching sharded run-python tasks (capped at 8 shards) to executor hosts via the Tasks API. Each shard runs the topology.py payload, which fans out per-host queries with a ThreadPoolExecutor and emits NDJSON events to stdout. The API polls the dispatched tasks (GET /result), merges their stdout into the graph, and the client polls that endpoint until every shard is finished. Results are cached client-side with TanStack Query, so re-opening the app is free until the user clicks Refresh.

Topology runtime limits live in api_routes.py as module constants: maximum shards is 8. Changing that value currently requires a code deploy; move it into inventory_settings first if it needs per-deployment tuning.

The payload reuses the same credential rules as MySQLSyncer - ~/.my.cnf and ~/.mylogin.cnf on the executor, with per-host login paths matched by host:port (or host_port) and a client fallback - so no additional configuration is required if you already have MySQLSyncer running against the same hosts.

SSL Configuration

SEP supports SSL/TLS configuration for secure communications. SSL settings can be configured at different levels:

Global SSL Settings

SSL_CAFILE: /path/to/ca-certificate.pem  # Global CA certificate file

Component-specific SSL Settings

SEP:
  SSL_KEYFILE: /path/to/sep-key.pem
  SSL_CERTFILE: /path/to/sep-cert.pem

INVENTORY:
  SSL_KEYFILE: /path/to/inventory-key.pem
  SSL_CERTFILE: /path/to/inventory-cert.pem

TASKS:
  SSL_KEYFILE: /path/to/tasks-key.pem
  SSL_CERTFILE: /path/to/tasks-cert.pem

Nomad SSL Configuration

TASKS:
  NOMAD:
    SSL_CAFILE: /path/to/nomad-ca.pem
    SSL_CERTFILE: /path/to/nomad-cert.pem
    SSL_KEYFILE: /path/to/nomad-key.pem

SSL certificate files should be in PEM format. Relative paths will be resolved from the project root folder.

Getting your PMM API Key
  1. In a browser, open PMM's web interface and login (the default credentials are admin:admin). If you followed the Docker tutorial, it should be in https://localhost.

image

  1. Navigate to Configuration > API keys. If you followed the Docker tutorial, it should be in https://localhost/graph/org/apikeys.

image

  1. Click the New API key button to create a new API key. Make sure the Role is set to Admin.

image

  1. Copy the generated API Key and replace the respective YOUR_PMM_API_KEY in your .env file.

image

Usage

  1. Enter the project folder:
cd SEP
  1. Activate your virtualenv:
source venv/bin/activate
  1. Start SEP:
LOGGING=debug python3 -m app.main

SEP will be available in http://localhost:8000.

image

Starting Celery with SEP for development

For development environments, you can start the Celery Worker and the Celery Beat with SEP by using the --start-celery flag:

LOGGING=debug python3 -m app.main --start-celery

Alternative: Use Docker Compose

You can also run sep with Docker Compose by following these steps:

  1. Enter the project folder:
cd SEP
  1. Generate the SSL certificates with the generate_certs.sh script:
./generate_certs.sh
  1. Generate Casdoor's init data with the generate_casdoor_init_data.sh script:
./generate_casdoor_init_data.sh

You can use the -p/--password argument to specify a password for the initial user:

./generate_casdoor_init_data.sh -p password

If no password is specified, a random one will be generated.

By now, your data folder should look something like this:

data
├── nomad.hcl
├── certs
│   ├── nomad
│   │   ├── global-client-nomad.pem
│   │   ├── global-server-nomad-key.pem
│   │   ├── global-client-nomad-key.pem
│   │   ├── global-client-nomad.p12
│   │   └── global-server-nomad.pem
│   ├── sep-ca-key.pem
│   ├── sep
│   │   ├── localhost-cert-key.pem
│   │   ├── inventory_api-cert-key.pem
│   │   ├── tasks_api-cert.pem
│   │   ├── localhost-cert.pem
│   │   ├── inventory_api-cert.pem
│   │   └── tasks_api-cert-key.pem
│   ├── casdoor
│   │   ├── sep_token_jwt_key.pem
│   │   ├── README.md
│   │   ├── sep_token_jwt_key.key
│   └── sep-ca.pem
├── mime.types
├── casdoor_init_data.json
├── http-tests
│   ├── inventory.http
│   ├── nomad.http
│   ├── task_history.http
│   └── tasks.http
└── nginx.conf
  1. Add your PMM API key to the .env.docker file

By now, a .env.docker file should have been created in your current directory. Open it and replace REPLACE_WITH_YOUR_PMM_API_KEY with your actual PMM API key.

  1. Start Nomad with the new generated config:
nomad agent -config /path/to/SEP/data/nomad.hcl

Replace /path/to/SEP with the path in which the project folder is stored in your computer.

Important

Make sure you're not running other Nomad instances.

  1. Build the Docker Compose services:
docker compose build
  1. Start the Docker Compose services:
docker compose up

SEP will be available in https://localhost. You can stop SEP with CTRL-C and later start it again with docker compose up.

Contributing

See our CONTRIBUTING guide.

Deployment

See our INSTALLER guide for deployment instructions.

About

Services Enablement Platform

Resources

Contributing

Stars

6 stars

Watchers

6 watching

Forks

Releases

Packages

Used by

Contributors

Languages