Configure the deployment
The config.yml file describes the environment that the self-hosted-controller (SHC) deploys. For Sekoia Self-Hosted 1.0.1, start from a built-in sizing profile and provide the site-specific values described on this page.
The SHC combines the built-in defaults, the selected sizing profile, and your config.yml into one computed configuration. It validates the result before installation and rejects missing required fields, invalid values, and unsupported keys.
This page explains every required field, the settings whose default value is a placeholder, and the most common optional settings. To inspect every other supported setting, use the SHC configuration commands.
Validation does not catch every incorrect value
CheckLocalConfig rejects a required field that is missing or empty, but it does not check the optional fields that your environment needs. For example, the S3 credentials of the online mode are optional for the validator: when they are empty, the installation fails later, when DownloadReleaseFiles runs in the checks stage. In the same way, when backups are enabled, a missing encryption key stops the installation only in the platform stage. To confirm that every value your deployment needs is present and correct, inspect the computed configuration with config show, with the precautions described in Inspect the configuration with the SHC.
Create the configuration file
Use the following configuration as a starting point. Replace every example value before running the SHC.
global:
inherit_config: sizing/500gb-day.yaml
host: "app.example.com"
delivery_host: "admin.example.com"
kube_manager_host: "kubernetes.example.com"
forward_dns: "10.0.0.100"
platform_storage:
region: "${env.STORAGE_S3_REGION}"
endpoint: "${env.STORAGE_S3_ENDPOINT}"
access_key: "${env.STORAGE_S3_ACCESS_KEY}"
secret_key: "${env.STORAGE_S3_SECRET_KEY}"
version:
platform:
version: "v1.0.1"
logging:
file: /opt/sekoia/logs/self-hosted-controller.log
utils:
ansible:
ssh-key: "${env.SERVERS_SSH_KEY}"
user: debian
inventory:
managers:
- 10.0.0.1
- 10.0.0.2
- 10.0.0.3
workers:
- 10.0.0.10
- 10.0.0.11
- 10.0.0.12
git:
repo_url: "https://git.example.com/sekoia/self-hosted.git"
oci_registry:
host: "registry.example.com"
project: "sekoia-self-hosted"
username: "${env.REGISTRY_USERNAME}"
password: "${env.REGISTRY_PASSWORD}"
modules:
platform_configuration:
config:
global:
instance_public_key: "${env.SEKOIA_INSTANCE_PUBLIC_KEY}"
References such as ${env.STORAGE_S3_REGION} read values from environment variables when the SHC loads the file. Use this syntax for credentials instead of storing secrets directly in config.yml. The former env.VARIABLE_NAME syntax is not supported.
Protect the configuration and the credentials
config.yml and these environment variables give access to your nodes, registry, Git repository, and storage. Restrict config.yml, the SSH private key, and any file that stores the variables to the accounts that need them, for example with chmod 600. The SHC container runs as UID 1000 and must still be able to read config.yml: when another account owns the file, give UID 1000 read access to it. Do not type a secret value on the command line, for example in export VARIABLE=value, because the shell history keeps it. Load the values from a protected file instead, for example with set -a; . /path/to/shc.env; set +a.
Set these environment variables before running the SHC:
| Variable | Purpose |
|---|---|
STORAGE_S3_REGION |
Region of the S3-compatible storage used by the platform. |
STORAGE_S3_ENDPOINT |
Endpoint of the S3-compatible storage used by the platform. |
STORAGE_S3_ACCESS_KEY |
Access key for platform storage. |
STORAGE_S3_SECRET_KEY |
Secret key for platform storage. |
SERVERS_SSH_KEY |
SSH private key used to configure the Kubernetes nodes. |
REGISTRY_USERNAME |
Username for the OCI registry. |
REGISTRY_PASSWORD |
Password for the OCI registry. |
GIT_HTTP_USERNAME |
Username for the Git repository, read by utils.git.http.username. |
GIT_HTTP_PASSWORD |
Password or access token for the Git repository, read by utils.git.http.password. |
SEKOIA_INSTANCE_PUBLIC_KEY |
Base64-encoded instance public key provided by Sekoia. |
TRAEFIK_PUBKEY |
Platform certificate in PEM format. See TLS certificate. |
TRAEFIK_PRIVKEY |
Private key of the platform certificate in PEM format. |
SERVERS_SUDO_PASSWORD |
Optional. Password that sudo asks for on the nodes, if any. See Node access. |
S3_ACCESS_KEY |
Online mode only. Access key for the Sekoia release bucket, provided by Sekoia. |
S3_SECRET_KEY |
Online mode only. Secret key for the Sekoia release bucket, provided by Sekoia. |
BACKUP_VAULT_CRYPT_KEY |
Required when Vault backups are enabled. Encryption key of the Vault snapshots, at least 16 characters. See Backups. |
BACKUP_ARANGO_CRYPT_KEY |
Required when ArangoDB backups are enabled. Passphrase of the ArangoDB backups, at least 16 characters. |
BACKUP_CLICKHOUSE_CRYPT_KEY |
Required when ClickHouse backups are enabled. AES-256 key of the ClickHouse backups: exactly 64 hexadecimal characters, for example the output of openssl rand -hex 32. |
The deployment guide shows how to pass these variables to the SHC container. Pass every variable you set, including the BACKUP_* variables when you enable backups.
Select and adjust a sizing profile
global.inherit_config selects a sizing profile shipped with the SHC image. A profile provides the base values of the platform capacity: service replicas, resource allocations, storage sizes, and Kafka partitions. Your config.yml overrides these base values case by case, as described in Override the values of a profile.
The SHC image ships three sizing profiles. They adjust only the resources whose load grows with the ingestion volume: Kafka, ExaLog, the KeyDB workflow cache, the intake and ingestion workers, Sigma Workflow, and asset discovery. Every other value comes from the built-in defaults.
| Profile | global.inherit_config value |
Target |
|---|---|---|
| 500 GB/day | sizing/500gb-day.yaml |
Deployment ingesting around 500 GB of events per day. |
| 1 TB/day | sizing/1tb-day.yaml |
Mid-range deployment ingesting around 1 TB of events per day. |
| 2 TB/day | sizing/2tb-day.yaml |
Deployment ingesting around 2 TB of events per day. |
The sizing/ path resolves against the configuration directory shipped in the SHC image, wherever you mount your own config.yml.
The values of the profiles are initial estimates, pending performance validation: the throughput that a profile sustains depends on the events of your site. Once the platform ingests your events, check the consumer lag of the ingestion and detection workers in the monitoring dashboards. Asset discovery can fall behind even when event ingestion keeps up.
A profile sets the resources and the replicas of the services, not the number of nodes: size the servers and the object storage with Cluster sizing. The 500 GB/day and 2 TB/day profiles target the daily volumes of the Small and Medium sizes of that table. No profile targets the Large size: size it with Sekoia.
The 500 GB/day profile keeps the Kafka partitions, the volume sizes, and the database redundancy of the 1 TB/day profile. An installed 1 TB/day platform can move to it without shrinking its storage.
Contact Sekoia before you select the 2 TB/day profile
The 2 TB/day profile runs 12 ExaLog indexing pipelines per community, and the Kafka topic of each community needs at least 12 partitions. The SHC does not set these partitions, and it applies the number of pipelines only to the communities created after the change. Sekoia makes these changes with you.
Override the values of a profile
A profile is a starting point, not a universal production recommendation. Sekoia adjusts it with you, case by case, to match your event sizes, events per second, daily ingestion volume, retention requirements, and volume of search queries.
A value that you set in config.yml replaces the value of the profile. The values that you do not set keep the value of the profile. For example, to run three ExaLog indexers instead of the two of the 500 GB/day profile:
global:
inherit_config: sizing/500gb-day.yaml
modules:
platform_configuration:
config:
quickwit:
indexer:
replicaCount: "3"
The value is an example, not a sizing recommendation. Use config help to identify the supported overrides, and config show to review the result after inheritance. Do not copy undocumented keys into your configuration: the SHC rejects unsupported fields. To change the replica counts of the workers, see Worker replica counts.
Worker replica counts
modules.scale_services.deploy.<namespace>.<deployment> sets the target replica count of an existing Kubernetes Deployment. ScaleServices applies these values directly through the Kubernetes API, after InstanceBootstrap at the end of Install. They are not rendered into region-config.yaml. This is how the SHC scales workers such as ingestworker1 and sigma-workflow-worker1, whose replica counts are not exposed as Helm values.
To override selected workers, merge the following section into your existing config.yml:
modules:
scale_services:
deploy:
sic:
ingestworker1: "4"
sigma-workflow-worker1: "6"
The counts are examples, not a sizing recommendation. Choose them with Sekoia and ensure that the cluster has enough CPU and memory for the additional pods. Use non-negative whole numbers. A value of 0 stops every pod of that Deployment and its processing.
The SHC merges this mapping with the built-in defaults and the selected sizing profile. Deployments that you do not override keep their inherited target counts: omitting one does not remove it from the scaling plan. Review the complete mapping with config show modules.scale_services.deploy before applying it. ScaleServices processes every entry in that mapping, not only your overrides.
For replica-only changes on an installed platform, follow Change worker replica counts. For a sizing change that also modifies resources, storage, or other platform settings, use the general configuration-change procedure.
Required fields
Platform endpoints
| Field | Description |
|---|---|
global.host |
Primary FQDN used to access the Sekoia platform, for example app.example.com. Configure DNS and the load balancer so this hostname reaches the platform. |
global.delivery_host |
Public FQDN used by delivery services, including the administrator portal, for example admin.example.com. |
global.kube_manager_host |
IP address or hostname of the Kubernetes API endpoint, without a port. The SHC, the nodes that join the cluster, and the Cilium network layer all reach the API through this address. For a highly available deployment, use the address of a TCP load balancer that forwards port 6443 to the three manager nodes. Otherwise, use the IP address of the first manager node. A hostname must resolve on every node and on the orchestration node. |
global.forward_dns |
DNS server to which CoreDNS forwards every name outside the Kubernetes cluster. To use several servers, separate their addresses with a space, for example "10.0.0.10 10.0.0.11". |
The platform services resolve names outside the cluster only through global.forward_dns: they do not read the /etc/hosts file of the nodes. The Git repository, the OCI registry, the S3 storage, and the SMTP server must resolve through this DNS server, or be configured with their IP address.
Platform storage
The platform stores the ExaLog indexes in S3-compatible object storage. These credentials must allow the platform to use the ExaLog event buckets. The platform does not create these buckets; see Event storage buckets.
| Field | Description |
|---|---|
global.platform_storage.region |
Region configured by your S3-compatible storage provider. |
global.platform_storage.endpoint |
Endpoint used to access the S3-compatible storage. Include the URL scheme, for example https://s3.example.com. |
global.platform_storage.access_key |
Access key for the S3-compatible storage. Use an environment-variable reference. |
global.platform_storage.secret_key |
Secret key for the S3-compatible storage. Use an environment-variable reference. |
ExaLog storage configuration is derived from global.platform_storage. Some computed configuration keys retain quickwit in their names, but they configure the ExaLog capability.
The following optional fields adjust how the platform reaches the storage:
| Field | Description | Default |
|---|---|---|
global.platform_storage.force_path_style_access |
true to send path-style requests, so bucket names do not need DNS records. Set it to false only when your storage requires virtual-hosted-style requests. |
true |
modules.platform_configuration.config.quickwit.searcher.s3_max_get_object_connections |
Maximum number of concurrent S3 GET connections of each ExaLog searcher. Lower it to limit the load that searches put on the storage. The limit applies to each searcher, so the total grows with the number of searchers, set in quickwit.searcher.replicaCount. |
1024 |
Release
| Field | Description |
|---|---|
global.version.platform.version |
Sekoia Self-Hosted release to deploy. Set it to v1.0.1 for this GA documentation. |
Kubernetes node access
| Field | Description |
|---|---|
utils.ansible.ssh-key |
Private key used by the self-hosted-controller (SHC) to connect to and configure every Kubernetes node. Use an environment-variable reference. |
utils.ansible.user |
SSH user used on every Kubernetes node. The account must meet the requirements in Node access. |
utils.ansible.inventory.managers |
List of the IPv4 addresses of the manager nodes. Hostnames and IPv6 addresses are rejected. Set exactly three managers: this is the supported production topology. |
The validator only rejects an empty list of managers: it accepts any other number. Do not deploy another number in production. With one or two managers, etcd has no fault tolerance, and the loss of a single manager stops the Kubernetes API. The manager nodes also run platform workloads, like the worker nodes. See Cluster sizing.
Worker nodes are configured under utils.ansible.inventory.workers, with their IPv4 addresses. The field is not required by the configuration validator, but production sizing profiles require workers to provide the expected capacity: when you omit it, the SHC installs a cluster of manager nodes only, without any error.
Git repository
| Field | Description |
|---|---|
utils.git.repo_url |
URL of the customer-managed Git repository in which the self-hosted-controller (SHC) publishes the ArgoCD stack manifests. |
The SHC publishes the stacks to a branch of this repository, and ArgoCD tracks the same branch for the root and child applications. To choose the branch, set the following optional field:
| Field | Description | Default |
|---|---|---|
modules.push_argo_stacks.base_branch |
Branch to publish the stacks to and to track in ArgoCD. Required when the repository is empty. Otherwise, the branch must already exist. | Default branch of the repository |
Empty repository
If the repository has no commit yet, set modules.push_argo_stacks.base_branch. Without it, PushArgoStacks fails. PushArgoStacks also fails, without overwriting anything, when its local checkout has uncommitted changes or when the local and remote branches have diverged.
If the repository requires authentication, use config help utils.git to inspect the supported HTTP authentication settings. ArgoCD connects to the repository with a username and a password over HTTP or HTTPS.
The repository must meet the following conditions:
- It is reached over HTTP or HTTPS, from the orchestration node and from every Kubernetes node. Git over SSH is not supported: ArgoCD receives only the username and the password.
- With HTTPS, its certificate is signed by a public certificate authority. The SHC has no setting to trust a private certificate authority for Git.
- The SHC account can push directly to the branch. A protected branch that requires a merge request or a review makes
PushArgoStacksfail. - The SHC owns the
argocd/directory of the repository and replaces it at each push. Do not store other files in this directory.
OCI registry
| Field | Description |
|---|---|
utils.oci_registry.host |
Registry hostname, with an optional port and without a URL scheme, for example registry.example.com or registry.example.com:5000. |
utils.oci_registry.project |
Registry project or namespace in which the self-hosted-controller (SHC) publishes Sekoia artifacts, for example sekoia-self-hosted. The project must exist before the installation. Use lowercase letters, digits, -, and _, starting with a letter or a digit: CheckLocalConfig rejects / and .. |
utils.oci_registry.username |
Username with push, pull, and delete permissions in the registry project, including the creation of new repositories in it. Use an environment-variable reference. |
utils.oci_registry.password |
Password or token for the registry account. Use an environment-variable reference. |
The registry must serve HTTPS: ArgoCD pulls the Helm charts over HTTPS, even when utils.oci_registry.scheme is http. The SHC derives the registry URL and the repositories used for checks, charts, and images from these values. Do not set the derived url, check_repo, chart_repo, or image_repo fields directly for a standard deployment. Override them only for a special registry layout or while debugging with guidance from Sekoia.
The registry must meet the following conditions:
- It uses token (Bearer) authentication. When a client connects without a token, the registry answers
401with aWWW-Authenticate: Bearerheader. The SHC rejects a registry that answers withWWW-Authenticate: Basic. To check your registry, runcurl -sk -o /dev/null -D - https://<REGISTRY_HOST>/v2/ | grep -i www-authenticate. - A self-signed certificate is accepted: the SHC, the Kubernetes nodes, and ArgoCD do not verify the certificate of the registry.
- The orchestration node reaches the registry without a proxy. The SHC has no proxy setting for the registry.
The SHC publishes the images under <project>/images/, the Helm charts under <project>/charts/, and checks the account permissions with a temporary <project>/shc-probe image that it pushes, pulls, and deletes.
Instance license
| Field | Description |
|---|---|
modules.platform_configuration.config.global.instance_public_key |
Base64-encoded public key used to validate the Sekoia instance license. Sekoia provides this value. Use an environment-variable reference. |
TLS certificate
Traefik serves the platform with your certificate on HTTPS and on the syslog and RELP intake ports. Provide the certificate and its private key in PEM format. The SHC reads them from two environment variables, and the execution script passes both to the SHC container.
| Field | Environment variable | Description |
|---|---|---|
modules.platform_configuration.config.traefik.custom_cert.crt |
TRAEFIK_PUBKEY |
Certificate chain in PEM format. |
modules.platform_configuration.config.traefik.custom_cert.key |
TRAEFIK_PRIVKEY |
Private key of the certificate in PEM format, without a passphrase. |
The certificate must meet the following conditions:
- It is valid for every hostname the platform serves:
global.host,global.delivery_host, andglobal.alternative_hosts. Each name is in its Subject Alternative Name, directly or through a wildcard. - The file starts with the server certificate, followed by the intermediate certificates.
- When a private certificate authority signs it, the file ends with the root certificate of this authority. The platform services trust this file, in addition to the public authorities, when they call the platform through
global.hostand when they connect to your SMTP server. If your SMTP server uses a certificate from a private authority, append the root certificate of this authority too.
To load the certificate and its key on the orchestration node, run:
export TRAEFIK_PUBKEY="$(cat /path/to/certificate.pem)"
export TRAEFIK_PRIVKEY="$(cat /path/to/private-key.pem)"
A certificate is required
Sekoia Self-Hosted 1.0.1 does not support an installation without a certificate. When TRAEFIK_PUBKEY is empty, the CustomCA step of the installation fails with Custom CA not defined. When the variables are not passed to the SHC container at all, the SHC only logs an Unresolved template marker warning: the certificate secret of Traefik then holds no valid certificate, Traefik serves its own default certificate, and the console and ingest diagnostics report the certificate secret as critical. For a test platform, generate a self-signed certificate that covers the platform hostnames.
To check the certificate that the platform serves on HTTPS, syslog, and RELP, see Check the load balancer listeners. To renew or replace the certificate after the installation, see Rotate the certificate and credentials.
Settings with placeholder defaults
The following settings are not required by the validator, but their default values are examples that do not match your environment. CheckLocalConfig accepts them as they are, so review each one before the installation.
Replace the placeholder values
With the default values, the platform sends its emails to a server named mail.server.local and builds the Grafana links on admin.sekoia.local. Set the values for your domain before you run Install.
Email notifications
The platform sends notifications and user invitation emails through your SMTP server.
| Field | Description | Default |
|---|---|---|
modules.platform_configuration.config.email.email_sender |
Sender address of the platform emails. | noreply@sekoia.local |
modules.platform_configuration.config.email.smtp.host |
Hostname of the SMTP server. | mail.server.local |
modules.platform_configuration.config.email.smtp.port |
Port of the SMTP server. | 25 |
modules.platform_configuration.config.email.smtp.user |
SMTP username. | smtp-user |
modules.platform_configuration.config.email.smtp.password |
SMTP password. Use an environment-variable reference. | smtp-password |
modules.platform_configuration.config.email.smtp.tls |
"True" to open the connection with implicit TLS, commonly on port 465. |
"False" |
modules.platform_configuration.config.email.smtp.starttls |
"True" to upgrade the connection with STARTTLS, commonly on port 587. |
"True" |
The tls and starttls fields accept only the strings "True" and "False", with an uppercase first letter.
Grafana URL
| Field | Description | Default |
|---|---|---|
modules.platform_configuration.config.grafana.root_url |
Public URL of Grafana. Grafana is served under the /grafana path of global.delivery_host, so set it to https://<global.delivery_host>/grafana. |
https://admin.sekoia.local/grafana |
Alternative hostname
| Field | Description | Default |
|---|---|---|
global.alternative_hosts |
Additional FQDN accepted by the platform alongside global.host. It accepts one hostname. Set it to a hostname of your domain and create its DNS record. |
api.sekoia.local |
Placeholder settings in config.yml
global:
alternative_hosts: "api.example.com"
modules:
platform_configuration:
config:
grafana:
root_url: "https://admin.example.com/grafana"
email:
email_sender: "noreply@example.com"
smtp:
host: "smtp.example.com"
port: "587"
user: "sekoia"
password: "${env.SMTP_PASSWORD}"
tls: "False"
starttls: "True"
Pass every environment variable you reference to the SHC container. For example, add -e SMTP_PASSWORD="$SMTP_PASSWORD" to the docker run command of the execution script.
Optional settings
Release download and security content
The SHC reads the platform release and the security content bundles from local directories. In online mode, it first downloads them from the Sekoia S3 bucket at https://self-hosted.delivery.sekoia.io, with the S3_ACCESS_KEY and S3_SECRET_KEY credentials provided by Sekoia. In air-gapped mode, it uses the files extracted from the release archive.
| Field | Description | Default |
|---|---|---|
global.version.fetch.offline |
true to skip every download from the Sekoia S3 bucket. Set it to true for an air-gapped deployment. |
false |
global.version.fetch.endpoint |
Online mode only. Endpoint of the Sekoia release bucket. Set it to https://self-hosted.delivery.sekoia.io: the default value is not the customer delivery endpoint. |
Not applicable |
global.version.fetch.connect-timeout |
Online mode only. Seconds to wait for a connection to the S3 endpoint, per attempt. | 10 |
global.version.fetch.read-timeout |
Online mode only. Seconds to wait for data from the S3 endpoint, per attempt. Increase it behind a slow proxy. | 60 |
global.version.fetch.max-attempts |
Online mode only. Total attempts per S3 request, first try included. | 3 |
global.version.platform.path |
Local directory of the platform release files. | /opt/sekoia/platform/ |
global.version.data.detection-rules.version |
Online mode only. Detection rules bundle to download: latest, or the release ID of a bundle to pin. |
latest |
global.version.data.intake-formats.version |
Online mode only. Intake formats bundle to download: latest, or the release ID of a bundle to pin. |
latest |
global.version.data.playbook-library.version |
Online mode only. Playbook library bundle to download: latest, or the release ID of a bundle to pin. |
latest |
global.version.data.cti.version |
CTI export imported by ImportArangoCollection: latest, a day such as 2026-09-03, or an exact export such as 2026-09-03T09. See Import the CTI database. |
latest |
global.version.data.<TYPE>.path |
Local directory of the bundles of each type. The bundles are stored in a <TYPE> subdirectory. |
/opt/sekoia/data/ |
Online mode in config.yml
global:
version:
fetch:
endpoint: "https://self-hosted.delivery.sekoia.io"
The SHC reads the bucket credentials from the S3_ACCESS_KEY and S3_SECRET_KEY environment variables. The execution script passes them to the container.
The release ID of a bundle is its file name without the <TYPE>- prefix and the .tar.gz extension. For example, the file detection-rules-2.20260813-31688094717-35a441d88ed9c2b23b078e476fb35a6c2a40df84.tar.gz has the release ID 2.20260813-31688094717-35a441d88ed9c2b23b078e476fb35a6c2a40df84.
Bundle selection in air-gapped mode
In air-gapped mode, the version fields of the bundles are ignored. The SHC uses the bundle named in the latest file of each data/<TYPE>/ directory.
Proxy
Configure these fields when the platform, the container runtime, or the SHC reaches external services through an HTTP or HTTPS proxy. Each component uses its own settings.
| Field | Description | Default |
|---|---|---|
modules.platform_configuration.config.proxy.http_proxy |
HTTP proxy URL used by the platform components that reach external services: ArgoCD, ExaLog indexing, the threat intelligence backend, and playbook actions. | Empty |
modules.platform_configuration.config.proxy.https_proxy |
HTTPS proxy URL used by the platform components. | Empty |
modules.platform_configuration.config.proxy.no_proxy |
Comma-separated destinations that the platform components reach without the proxy. Keep the default value and use additional_no_proxy for your own entries. |
127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.cluster.local,.lab |
modules.platform_configuration.config.proxy.additional_no_proxy |
Comma-separated destinations appended to no_proxy when the SHC generates the platform configuration. Set your Git, OCI registry, and S3 hostnames here when they are reachable without the proxy. |
Empty |
modules.platform_configuration.config.proxy.no_proxy_include_platform_domain |
true to append the platform FQDNs (global.host, global.alternative_hosts, and global.delivery_host) to no_proxy, so that the platform components reach their own endpoints without the proxy. |
true |
modules.k3s_install.pull_images_with_proxy |
Routes the container image pulls of the Kubernetes nodes through a proxy. | false |
modules.k3s_install.k3s_http_proxy |
HTTP proxy URL used for image pulls when pull_images_with_proxy is true. |
Empty |
modules.k3s_install.k3s_https_proxy |
HTTPS proxy URL used for image pulls when pull_images_with_proxy is true. |
Empty |
modules.k3s_install.k3s_no_proxy |
Destinations reached without the proxy for image pulls. | 127.0.0.0/8,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.cluster.local,.lab |
utils.git.http.proxy |
Proxy URL used by the SHC for Git operations over HTTP or HTTPS. | Empty |
Keep the default exclusions
To exclude more destinations from the proxy, set them in additional_no_proxy instead of editing no_proxy. The default no_proxy list keeps the cluster-internal and private addresses out of the proxy, and the platform FQDNs are added automatically. Add your Git, OCI registry, and S3 hostnames when they are reachable without the proxy: an address range does not match a hostname.
The SHC computes the final no_proxy value when PlatformConfigurationFile runs, by concatenating three lists:
- The value of
no_proxy. - The platform FQDNs, when
no_proxy_include_platform_domainistrue. - The value of
additional_no_proxy.
Duplicate entries are removed. These three fields only apply to the platform components. The image pulls of the nodes use modules.k3s_install.k3s_no_proxy, which is applied as is.
Proxy configuration in config.yml
modules:
platform_configuration:
config:
proxy:
http_proxy: "http://proxy.example.com:3128"
https_proxy: "http://proxy.example.com:3128"
additional_no_proxy: "git.example.com,registry.example.com,s3.example.com"
Traefik service IP
Traefik is the HTTP entry point of the platform. The SHC gives its Kubernetes service a fixed cluster-internal IP. Inside the cluster, CoreDNS resolves the platform FQDNs to that IP: global.host, global.alternative_hosts, and global.delivery_host. The platform components therefore reach each other without leaving the cluster.
| Field | Description | Default |
|---|---|---|
modules.platform_configuration.config.traefik.service_ip |
Fixed ClusterIP of the Traefik service, inside the K3s service network 10.43.0.0/16. Leave empty to let Kubernetes assign one. |
10.43.111.111 |
Empty value disables the internal resolution of the platform FQDNs
When the field is empty, HelmInstall adds no entry to CoreDNS, so the platform FQDNs resolve inside the cluster through the DNS servers of global.forward_dns only.
SHC log file
Every SHC run, in CLI or TUI mode, writes its log lines to a dedicated file. The SHC takes the directory and file name from global.logging.file, and prefixes the file name with the start time of the run, for example 20261023-153000_self-hosted-controller.log, so that successive runs never overwrite each other. Sekoia support asks for this file when you escalate an issue.
| Field | Description | Default |
|---|---|---|
global.logging.file |
Path of the per-run log file, inside the SHC container. Set it under /opt/sekoia, the mount point of $SEKOIA_LOCAL_DIR, to keep the file on the orchestration node. The field does not appear in config help. |
/tmp/self-hosted-controller.log |
The default path loses the file
The execution script runs the container with --rm and mounts only $SEKOIA_CONFIG_FILE and $SEKOIA_LOCAL_DIR. With the default value, the file is written to /tmp inside the container and deleted when the command exits. Set the field in every deployment.
Log file on the orchestration node in config.yml
global:
logging:
file: /opt/sekoia/logs/self-hosted-controller.log
With this value, the log of a run started on 23 October 2026 at 15:30:00 is kept at $SEKOIA_LOCAL_DIR/logs/20261023-153000_self-hosted-controller.log on the orchestration node.
The SHC creates the directory if it does not exist. If it cannot create the file, it starts without file logging: the CLI reports nothing, and the TUI displays log: (disabled) at the bottom of the interface. Give UID 1000 write access to $SEKOIA_LOCAL_DIR, as described in the container user note of the deployment guide.
Database storage
These fields set the disk size of each instance of the PostgreSQL clusters of the platform. Each cluster runs three instances. The asset management, alerts, workflow engine, playbooks, and ExaLog metastore databases grow with platform usage.
Storage size can only increase
CloudNativePG cannot shrink a volume. Set a value equal to or larger than the current size of the cluster volumes.
| Field | Description | Default |
|---|---|---|
modules.platform_configuration.config.assetmanagement.database.storage.size |
Storage size of the asset management database. | 1Ti |
modules.platform_configuration.config.sicalertapi.database.storage.size |
Storage size of the alerts database. | 50Gi |
modules.platform_configuration.config.quickwit.database.storage.size |
Storage size of the ExaLog metastore database. | 50Gi |
modules.platform_configuration.config.hatchet.database.storage.size |
Storage size of the workflow engine database. | 30Gi |
modules.platform_configuration.config.symphony.database.storage.size |
Storage size of the playbooks database. | 30Gi |
modules.platform_configuration.config.communityapi.database.storage.size |
Storage size of the community and user database. | 20Gi |
modules.platform_configuration.config.crmapi.database.storage.size |
Storage size of the crmapi database. |
20Gi |
modules.platform_configuration.config.dashboardapi.database.storage.size |
Storage size of the dashboards database. | 20Gi |
modules.platform_configuration.config.notificationapi.database.storage.size |
Storage size of the notifications database. | 20Gi |
modules.platform_configuration.config.taskapi.database.storage.size |
Storage size of the tasks database. | 20Gi |
modules.platform_configuration.config.ingest.database.storage.size |
Storage size of the ingestion database. | 20Gi |
modules.platform_configuration.config.xdr-agent-api.database.storage.size |
Storage size of the xdr-agent-api database. The service is deployed but not supported in 1.0.1. |
20Gi |
The asset management database also defaults to 2 CPUs and 4 GiB of memory per instance, set in assetmanagement.database.resources.cpu and assetmanagement.database.resources.memory.
Ceph storage devices
By default, Ceph uses every unused raw disk of every node, as described in Dedicated storage disk. To use only the disks or the LVM logical volumes that you select, set the manual mode:
| Field | Description | Default |
|---|---|---|
modules.platform_configuration.config.rook.storage.mode |
auto to use every unused raw disk, or manual to use only the devices listed in nodes. |
auto |
modules.platform_configuration.config.rook.storage.nodes |
Manual mode only. List of nodes, each with a name, the hostname of the node, and a devices list of name entries, the /dev/ paths of the selected devices. Must be empty in auto mode. |
[] |
Manual Ceph storage in config.yml
modules:
platform_configuration:
config:
rook:
storage:
mode: manual
nodes:
- name: node-01
devices:
- name: /dev/sdb
- name: node-02
devices:
- name: /dev/vg-ceph/lv-ceph
In manual mode, the following conditions apply:
- Each
nameis the hostname of one node of the inventory, in lowercase.CheckServerSpecfails when a name matches no node. - Each device is a whole raw disk or an LVM logical volume that you created and activated, 200 GB or larger, writable, not mounted, and without a filesystem, a partition table, or another signature.
CheckServerSpecchecks every selected device before the installation. lvm2is already installed on every node that has a selected device:CheckServerSpecchecks it before the SHC installs any package.- Ceph creates one unencrypted OSD per device.
WipeStorageDisksdoes not wipe the selected devices and does not remove/var/lib/rookfrom the nodes. After aPlatformDestroy, clean them yourself before you reuse them.
Feed compilation batch size
The feed compiler of Sigma Workflow compiles the indicators of the threat intelligence feeds that the detection rules use, in batches. On nodes with limited CPU, a large batch can keep the compiler busy long enough for its health probes to time out: Kubernetes then restarts the sigma-workflow-feed-compiler pod of the sic namespace. To keep the probes responsive, lower the batch size:
| Field | Description | Default |
|---|---|---|
modules.platform_configuration.config.sigma-workflow.sigma-workflow-feed-compiler.feed_refresh_limit |
Maximum number of indicators per compilation batch, as a positive whole number. | 2000 |
Smaller batches in config.yml
modules:
platform_configuration:
config:
sigma-workflow:
sigma-workflow-feed-compiler:
feed_refresh_limit: "500"
A smaller batch skips no indicator: the compiler fetches more batches to compile the whole feed. To apply the change on an installed platform, follow Apply a configuration change.
Backups
Backups are disabled by default. To back up Vault, the PostgreSQL databases, ArangoDB, and ClickHouse to S3, set modules.platform_configuration.config.backups.enabled to true. Before you enable backups:
- Create the backup bucket,
exalog-self-hosted-backupsby default, on your S3-compatible storage. See Backup bucket. - Set the
BACKUP_VAULT_CRYPT_KEY,BACKUP_ARANGO_CRYPT_KEY, andBACKUP_CLICKHOUSE_CRYPT_KEYenvironment variables, and pass them to the SHC container. Keep a copy of each key outside the platform.
Missing backup keys stop the installation late
CheckLocalConfig does not report a missing backup encryption key. When backups are enabled and a key is empty, PlatformConfigurationFile stops the installation in the platform stage, after Kubernetes is installed.
For the per-component settings, the schedules, the retention, and the backup status check, see Back up the platform.
Inspect the configuration with the SHC
Use the SHC itself to discover supported optional fields and verify the computed configuration.
Note
These commands require the SHC Docker image and the execution script. If you have not prepared them yet, complete the Preparation steps of the deployment guide, then come back to this section before you start the installation.
To list supported configuration fields, run:
config help
Add a prefix to focus on one section:
config help global.platform_storage
config help utils.oci_registry
Protect resolved secrets
config show prints every resolved value in clear text, including the S3 keys, the registry and Git passwords, the SSH private key, the private key of the certificate, and the backup encryption keys. It has no option to mask them. Prefer displaying a section that holds no secret, such as config show utils.ansible.inventory. Do not paste its output into tickets, chat messages, or logs. Redact all secrets before sharing it with Sekoia support. To check for missing or invalid values without printing them, run exec CheckLocalConfig instead.
To display the configuration after defaults, inheritance, environment references, and derived values have been resolved, run:
config show
You can also display one section:
config show utils.ansible.inventory
Finally, validate the configuration before starting an installation:
exec CheckLocalConfig
The command reports missing required values, invalid formats, and unsupported keys. It names the configuration key of each error, without printing its value. Correct every error before continuing.
Related links
- Deploy the platform: Prepare the SHC execution script and install the platform.
- Apply a configuration change: Change
config.ymlafter the installation and apply it withInstall. - Use the SHC interface: Run configuration commands from the interactive interface.
- Debug your deployment: Resolve configuration and connectivity failures.