Configuration
All configuration is loaded from a YAML file and can be overridden by environment variables. The application looks for config.yaml in the following locations, in order:
- Current working directory (
./config.yaml) ./configs/config.yaml
Environment variables take precedence over the file. The prefix is EASM_, dots in the key path are replaced with underscores (e.g. database.dsn → EASM_DATABASE_DSN).
The full example file lives at backend/configs/config.yaml.
Contents
- app
- server
- database
- redis
- jwt
- log
- storage
- updates
- tools
- Full example
- Docker Compose environment variables
app
Application version metadata shared by the API and frontend.
app:
version: "0.1.6 Sirius"
| Key | Default | Description |
|---|---|---|
app.version |
release value | Current application version shown by GET /api/v1/version and used by Update Center unless overridden |
Environment variable: EASM_APP_VERSION
For normal releases, update app.version only. updates.current_version should remain empty unless you need a temporary override.
server
Controls the HTTP API listen address. Used by the api service only; the worker ignores this section.
server:
host: 0.0.0.0 # interface to bind; use 127.0.0.1 to restrict to localhost
port: "8080" # TCP port (string)
| Key | Default | Description |
|---|---|---|
server.host |
0.0.0.0 |
Bind address |
server.port |
8080 |
Listen port |
Environment variables: EASM_SERVER_HOST, EASM_SERVER_PORT
database
PostgreSQL connection string. Both the API and the worker require this.
database:
dsn: postgres://easm:easm@postgres:5432/easm?sslmode=disable
| Key | Default | Description |
|---|---|---|
database.dsn |
postgres://easm:easm@postgres:5432/easm?sslmode=disable |
Full libpq connection URI |
Environment variable: EASM_DATABASE_DSN
The DSN format is:
postgres://<user>:<password>@<host>:<port>/<database>?<options>
Common options:
| Option | Purpose |
|---|---|
sslmode=disable |
No TLS (development / internal networks) |
sslmode=require |
Require TLS |
sslmode=verify-full |
Require TLS + verify server certificate |
connect_timeout=10 |
Connection timeout in seconds |
The API runs all pending Goose migrations automatically on startup. No manual goose up is required.
redis
Redis is used as the scan job queue and for future caching. Both the API and the worker require this.
redis:
addr: redis:6379
password: ""
db: 0
| Key | Default | Description |
|---|---|---|
redis.addr |
redis:6379 |
host:port of the Redis instance |
redis.password |
(empty) | AUTH password; leave empty if Redis has no password |
redis.db |
0 |
Redis database index (0–15) |
Environment variables: EASM_REDIS_ADDR, EASM_REDIS_PASSWORD, EASM_REDIS_DB
jwt
JSON Web Token settings used by the API for authentication. The worker does not use JWTs.
jwt:
secret: change-me-in-production
access_token_ttl: 15 # minutes
refresh_token_ttl: 7 # days
| Key | Default | Description |
|---|---|---|
jwt.secret |
change-me-in-production |
HMAC-SHA256 signing key — must be changed in production |
jwt.access_token_ttl |
15 |
Access token lifetime in minutes |
jwt.refresh_token_ttl |
7 |
Refresh token lifetime in days |
Environment variables: EASM_JWT_SECRET, EASM_JWT_ACCESS_TOKEN_TTL, EASM_JWT_REFRESH_TOKEN_TTL
Recommendations:
- Generate a secret with openssl rand -hex 32
- Keep access_token_ttl short (≤ 30 minutes)
- Longer refresh_token_ttl improves UX; shorter improves security
log
Controls log output format and verbosity. Logs are written to stdout as JSON (zerolog).
log:
level: info
| Key | Default | Description |
|---|---|---|
log.level |
info |
One of: debug, info, warn, error |
Environment variable: EASM_LOG_LEVEL
storage
S3-compatible object storage for screenshots, raw outputs, evidence files, report exports, and other file artifacts. Both the API and worker use this section.
storage:
provider: s3
endpoint: http://minio:9000
region: us-east-1
bucket: easm-files
access_key: easm
secret_key: easm-password
use_ssl: false
public_base_url: http://localhost:9000
| Key | Default | Description |
|---|---|---|
storage.provider |
s3 |
Storage backend. Current implementation expects S3-compatible storage |
storage.endpoint |
http://minio:9000 |
Internal S3/MinIO endpoint used by API and worker |
storage.region |
us-east-1 |
S3 region value |
storage.bucket |
easm-files |
Bucket for uploaded artifacts |
storage.access_key |
easm |
S3 access key |
storage.secret_key |
easm-password |
S3 secret key; change in production |
storage.use_ssl |
false |
Use HTTPS/TLS for the S3 endpoint |
storage.public_base_url |
(empty) | Browser-visible endpoint used when generating presigned download URLs |
Environment variables:
EASM_STORAGE_PROVIDEREASM_STORAGE_ENDPOINTEASM_STORAGE_REGIONEASM_STORAGE_BUCKETEASM_STORAGE_ACCESS_KEYEASM_STORAGE_SECRET_KEYEASM_STORAGE_USE_SSLEASM_STORAGE_PUBLIC_BASE_URL
storage.public_base_url is important for MinIO/S3 deployments behind Docker or a reverse proxy. It must match the host the browser opens, otherwise presigned URLs can fail with SignatureDoesNotMatch. For local Docker Compose, http://localhost:9000 is typically correct.
See files.md for file artifact behavior and storage flow.
updates
Admin-only GitHub release checks for the Update Center. This subsystem is informational only: it does not run shell commands, pull images, update files, or restart containers.
updates:
enabled: true
github_owner: "fedoik"
github_repo: "hx0110-EASM"
github_token: ""
check_interval_minutes: 360
current_version: ""
allow_prereleases: false
| Key | Default | Description |
|---|---|---|
updates.enabled |
true |
Enables GitHub release checks |
updates.github_owner |
(empty) | GitHub owner or organization |
updates.github_repo |
(empty) | GitHub repository name |
updates.github_token |
(empty) | Optional token for private repositories; prefer env var |
updates.check_interval_minutes |
360 |
Cache TTL for automatic/status checks |
updates.current_version |
(empty) | Optional override; leave empty to use app.version |
updates.allow_prereleases |
false |
Whether prerelease versions may be considered |
Environment variables:
EASM_UPDATES_ENABLEDEASM_UPDATES_GITHUB_OWNEREASM_UPDATES_GITHUB_REPOEASM_UPDATES_GITHUB_TOKENEASM_UPDATES_CHECK_INTERVAL_MINUTESEASM_UPDATES_CURRENT_VERSIONEASM_UPDATES_ALLOW_PRERELEASES
For private GitHub repositories, create a fine-grained read-only token with access to the repository and set it through .env or the deployment environment:
EASM_UPDATES_GITHUB_TOKEN=github_pat_...
Do not commit real tokens. GitHub may return 404 when a private repository token is missing, invalid, lacks access, or when no published GitHub Release exists. A git tag alone is not enough for /releases/latest; publish a release in GitHub.
See updates.md for API behavior, UI behavior, private repository troubleshooting, and manual update commands.
scan_profile_order and scan_profiles
Defines the scan profiles returned by GET /api/v1/scan-profiles and used by the worker to resolve plugin execution order.
scan_profile_order controls the display/API order. If it is present, it must include every configured profile exactly once.
scan_profile_order:
- quick
- default
- custom_tls
scan_profiles:
custom_tls:
name: Custom TLS Audit
description: Custom certificate inventory
plugins:
- subfinder
- dnsx
- httpx
- tlsx
| Field | Required | Description |
|---|---|---|
| profile ID | yes | Stable identifier stored on scans. Use lowercase letters, numbers, _, or - |
name |
yes | Human-readable label returned to the frontend |
description |
no | Human-readable description returned to the frontend |
plugins |
yes | Ordered list of registered plugin IDs |
Validation runs at API and worker startup:
scan_profilesmust not be empty.- Every profile must have a non-empty
nameand at least one plugin. - Empty or duplicate plugin names inside one profile are rejected.
- Every plugin must be registered in the plugin registry.
scan_profile_order, when set, must match the profile set exactly.
After editing scan profiles, restart both API and worker. Future scans can only use configured profile IDs. Historical scans keep their stored profile ID even if a profile is later removed.
tools
Defines which CLI security tools the worker installs at startup. Each key is the tool name as it should appear in $PATH (i.e. the binary filename).
Tools already present in $PATH are always skipped. Installation runs once per worker startup.
tools:
<tool-name>:
enabled: <bool>
install_method: <"apk" | "binary" | "skip">
# method-specific fields below
install_method: apk
Runs apk add --no-cache <apk_package>. Only works on Alpine Linux (the default container base image).
tools:
nmap:
enabled: true
install_method: apk
apk_package: nmap
| Field | Required | Description |
|---|---|---|
enabled |
yes | false skips this tool entirely |
install_method |
yes | "apk" |
apk_package |
yes | Package name as known to apk |
install_method: binary
Downloads a file from binary_url, extracts the binary named binary_name, and places it in install_dir.
Supported archive formats: .zip, .tar.gz / .tgz, or raw binary (no extension).
tools:
subfinder:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/subfinder/releases/download/v2.6.6/subfinder_2.6.6_linux_amd64.zip
binary_name: subfinder
install_dir: /usr/local/bin
| Field | Required | Description |
|---|---|---|
enabled |
yes | false skips this tool entirely |
install_method |
yes | "binary" |
binary_url |
yes | Direct download URL (zip, tar.gz, or raw binary) |
binary_name |
no | Filename to extract. Defaults to the tool key name |
install_dir |
no | Destination directory. Defaults to /usr/local/bin |
install_method: skip
Does nothing. The worker logs a warning if the binary is not found in $PATH but continues running.
tools:
amass:
enabled: true
install_method: skip
Built-in tool defaults
The following tools are pre-configured in configs/config.yaml:
| Tool | Enabled | Method | Notes |
|---|---|---|---|
nmap |
yes | apk |
Port scanner; Alpine packages nmap nmap-scripts |
subfinder |
yes | binary |
Subdomain discovery; ProjectDiscovery |
httpx |
yes | binary |
HTTP probe and screenshot source; ProjectDiscovery |
nuclei |
yes | binary |
Vulnerability scanner; ProjectDiscovery |
amass |
yes | binary |
Attack surface mapping; OWASP |
dnsx |
yes | binary |
DNS resolver/prober; ProjectDiscovery |
naabu |
yes | binary |
Port discovery; ProjectDiscovery |
tlsx |
yes | binary |
TLS/certificate discovery; ProjectDiscovery |
katana |
yes | binary |
Web crawling/path discovery; ProjectDiscovery |
alterx |
no | binary |
Experimental permutation tool; disabled by default |
shuffledns |
no | skip |
Experimental DNS brute force; resolver/wordlist setup required |
asnmap |
no | binary |
ASN mapping; disabled by default |
uncover |
no | binary |
Provider-backed discovery; disabled by default |
Update binary_url values when upgrading tool versions. Always use the linux_amd64 build for the default worker image.
Full example
app:
version: "0.1.6 Sirius"
server:
host: 0.0.0.0
port: "8080"
database:
dsn: postgres://easm:easm@postgres:5432/easm?sslmode=disable
redis:
addr: redis:6379
password: ""
db: 0
jwt:
secret: change-me-in-production
access_token_ttl: 15
refresh_token_ttl: 7
log:
level: info
storage:
provider: s3
endpoint: http://minio:9000
region: us-east-1
bucket: easm-files
access_key: easm
secret_key: easm-password
use_ssl: false
public_base_url: http://localhost:9000
updates:
enabled: true
github_owner: "fedoik"
github_repo: "hx0110-EASM"
github_token: ""
check_interval_minutes: 360
current_version: ""
allow_prereleases: false
tools:
nmap:
enabled: true
install_method: apk
apk_package: nmap
subfinder:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/subfinder/releases/download/v2.6.6/subfinder_2.6.6_linux_amd64.zip
binary_name: subfinder
install_dir: /usr/local/bin
httpx:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/httpx/releases/download/v1.6.8/httpx_1.6.8_linux_amd64.zip
binary_name: httpx
install_dir: /usr/local/bin
nuclei:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/nuclei/releases/download/v3.2.9/nuclei_3.2.9_linux_amd64.zip
binary_name: nuclei
install_dir: /usr/local/bin
amass:
enabled: true
install_method: binary
binary_url: https://github.com/owasp-amass/amass/releases/download/v4.2.0/amass_Linux_amd64.zip
binary_name: amass
install_dir: /usr/local/bin
dnsx:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/dnsx/releases/download/v1.2.2/dnsx_1.2.2_linux_amd64.zip
binary_name: dnsx
install_dir: /usr/local/bin
naabu:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/naabu/releases/download/v2.3.3/naabu_2.3.3_linux_amd64.zip
binary_name: naabu
install_dir: /usr/local/bin
tlsx:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/tlsx/releases/download/v1.1.9/tlsx_1.1.9_linux_amd64.zip
binary_name: tlsx
install_dir: /usr/local/bin
katana:
enabled: true
install_method: binary
binary_url: https://github.com/projectdiscovery/katana/releases/download/v1.1.2/katana_1.1.2_linux_amd64.zip
binary_name: katana
install_dir: /usr/local/bin
alterx:
enabled: false
install_method: binary
binary_url: https://github.com/projectdiscovery/alterx/releases/download/v0.0.4/alterx_0.0.4_linux_amd64.zip
binary_name: alterx
install_dir: /usr/local/bin
shuffledns:
enabled: false
install_method: skip
binary_url: ""
binary_name: shuffledns
install_dir: /usr/local/bin
asnmap:
enabled: false
install_method: binary
binary_url: https://github.com/projectdiscovery/asnmap/releases/download/v1.1.1/asnmap_1.1.1_linux_amd64.zip
binary_name: asnmap
install_dir: /usr/local/bin
uncover:
enabled: false
install_method: binary
binary_url: https://github.com/projectdiscovery/uncover/releases/download/v1.0.9/uncover_1.0.9_linux_amd64.zip
binary_name: uncover
install_dir: /usr/local/bin
Docker Compose environment variables
In docker-compose.yml, settings are passed as environment variables. The YAML config file is mounted read-only for the worker.
services:
api:
environment:
- EASM_SERVER_PORT=8080
- EASM_DATABASE_DSN=postgres://easm:easm@postgres:5432/easm?sslmode=disable
- EASM_REDIS_ADDR=redis:6379
- EASM_JWT_SECRET=${JWT_SECRET:-change-me-in-production}
- EASM_JWT_ACCESS_TOKEN_TTL=15
- EASM_JWT_REFRESH_TOKEN_TTL=7
- EASM_LOG_LEVEL=info
- EASM_STORAGE_ENDPOINT=http://minio:9000
- EASM_STORAGE_BUCKET=easm-files
- EASM_STORAGE_ACCESS_KEY=easm
- EASM_STORAGE_SECRET_KEY=${MINIO_ROOT_PASSWORD:-easm-password}
- EASM_STORAGE_PUBLIC_BASE_URL=http://localhost:9000
- EASM_UPDATES_GITHUB_TOKEN=${EASM_UPDATES_GITHUB_TOKEN}
worker:
environment:
- EASM_DATABASE_DSN=postgres://easm:easm@postgres:5432/easm?sslmode=disable
- EASM_REDIS_ADDR=redis:6379
- EASM_LOG_LEVEL=info
- EASM_STORAGE_ENDPOINT=http://minio:9000
- EASM_STORAGE_BUCKET=easm-files
- EASM_STORAGE_ACCESS_KEY=easm
- EASM_STORAGE_SECRET_KEY=${MINIO_ROOT_PASSWORD:-easm-password}
- EASM_STORAGE_PUBLIC_BASE_URL=http://localhost:9000
- EASM_TEST_MODE=false
volumes:
- ./backend/configs:/app/configs:ro # tool config
To set secrets from a .env file:
# .env
JWT_SECRET=your-very-long-random-secret-here
MINIO_ROOT_PASSWORD=change-this-minio-password
EASM_UPDATES_GITHUB_TOKEN=github_pat_...
docker compose --env-file .env up -d
Variable reference
| Variable | Config key | Component |
|---|---|---|
EASM_APP_VERSION |
app.version |
API |
EASM_SERVER_HOST |
server.host |
API |
EASM_SERVER_PORT |
server.port |
API |
EASM_DATABASE_DSN |
database.dsn |
API, Worker |
EASM_REDIS_ADDR |
redis.addr |
API, Worker |
EASM_REDIS_PASSWORD |
redis.password |
API, Worker |
EASM_REDIS_DB |
redis.db |
API, Worker |
EASM_JWT_SECRET |
jwt.secret |
API |
EASM_JWT_ACCESS_TOKEN_TTL |
jwt.access_token_ttl |
API |
EASM_JWT_REFRESH_TOKEN_TTL |
jwt.refresh_token_ttl |
API |
EASM_LOG_LEVEL |
log.level |
API, Worker |
EASM_STORAGE_PROVIDER |
storage.provider |
API, Worker |
EASM_STORAGE_ENDPOINT |
storage.endpoint |
API, Worker |
EASM_STORAGE_REGION |
storage.region |
API, Worker |
EASM_STORAGE_BUCKET |
storage.bucket |
API, Worker |
EASM_STORAGE_ACCESS_KEY |
storage.access_key |
API, Worker |
EASM_STORAGE_SECRET_KEY |
storage.secret_key |
API, Worker |
EASM_STORAGE_USE_SSL |
storage.use_ssl |
API, Worker |
EASM_STORAGE_PUBLIC_BASE_URL |
storage.public_base_url |
API, Worker |
EASM_UPDATES_ENABLED |
updates.enabled |
API |
EASM_UPDATES_GITHUB_OWNER |
updates.github_owner |
API |
EASM_UPDATES_GITHUB_REPO |
updates.github_repo |
API |
EASM_UPDATES_GITHUB_TOKEN |
updates.github_token |
API |
EASM_UPDATES_CHECK_INTERVAL_MINUTES |
updates.check_interval_minutes |
API |
EASM_UPDATES_CURRENT_VERSION |
updates.current_version |
API |
EASM_UPDATES_ALLOW_PRERELEASES |
updates.allow_prereleases |
API |
EASM_TEST_MODE |
(env only) | Worker |