Compare commits

...

2 Commits

Author SHA1 Message Date
Mike Reeves
350588f080 Change ulimits to structured dict format and add daemon.json ulimit support
Convert ulimits from flat strings to structured dicts with name, soft,
and hard fields for better UI experience. Add default_ulimits as a
configurable setting that dynamically renders into daemon.json, giving
two layers of control: global defaults via the daemon and per-container
overrides.
2026-03-17 16:51:04 -04:00
Mike Reeves
9a07a32a48 Add customizable ulimit settings for all Docker containers
Add ulimits as a configurable advanced setting for every container,
allowing customization through the web UI. Move hardcoded ulimits
from elasticsearch and zeek into defaults.yaml and fix elasticsearch
ulimits that were incorrectly nested under the environment key.
2026-03-17 15:14:34 -04:00
29 changed files with 243 additions and 52 deletions

View File

@@ -1,3 +1,4 @@
{% from 'docker/docker.map.jinja' import DOCKER -%}
{
"registry-mirrors": [
"https://:5000"
@@ -8,12 +9,16 @@
"base": "172.17.0.0/24",
"size": 24
}
],
]
{%- if DOCKER.default_ulimits %},
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Soft": 1048576,
"Hard": 1048576
}
{%- for ULIMIT in DOCKER.default_ulimits %}
"{{ ULIMIT.name }}": {
"Name": "{{ ULIMIT.name }}",
"Soft": {{ ULIMIT.soft }},
"Hard": {{ ULIMIT.hard }}
}{{ "," if not loop.last else "" }}
{%- endfor %}
}
{%- endif %}
}

View File

@@ -1,6 +1,10 @@
docker:
range: '172.17.1.0/24'
gateway: '172.17.1.1'
default_ulimits:
- name: nofile
soft: 1048576
hard: 1048576
containers:
'so-dockerregistry':
final_octet: 20
@@ -9,6 +13,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastic-fleet':
final_octet: 21
port_bindings:
@@ -16,6 +21,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elasticsearch':
final_octet: 22
port_bindings:
@@ -24,6 +30,16 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits:
- name: memlock
soft: -1
hard: -1
- name: nofile
soft: 65536
hard: 65536
- name: nproc
soft: 4096
hard: 4096
'so-influxdb':
final_octet: 26
port_bindings:
@@ -31,6 +47,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-kibana':
final_octet: 27
port_bindings:
@@ -38,6 +55,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-kratos':
final_octet: 28
port_bindings:
@@ -46,6 +64,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-hydra':
final_octet: 30
port_bindings:
@@ -54,6 +73,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-logstash':
final_octet: 29
port_bindings:
@@ -70,6 +90,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-nginx':
final_octet: 31
port_bindings:
@@ -81,6 +102,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-nginx-fleet-node':
final_octet: 31
port_bindings:
@@ -88,6 +110,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-redis':
final_octet: 33
port_bindings:
@@ -96,11 +119,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-sensoroni':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-soc':
final_octet: 34
port_bindings:
@@ -108,16 +133,19 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-backend':
final_octet: 36
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-filestream':
final_octet: 37
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-frontend':
final_octet: 38
port_bindings:
@@ -125,11 +153,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-manager':
final_octet: 39
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-gatekeeper':
final_octet: 40
port_bindings:
@@ -137,6 +167,7 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-strelka-coordinator':
final_octet: 41
port_bindings:
@@ -144,11 +175,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastalert':
final_octet: 42
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastic-fleet-package-registry':
final_octet: 44
port_bindings:
@@ -156,11 +189,13 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-idh':
final_octet: 45
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-elastic-agent':
final_octet: 46
port_bindings:
@@ -169,23 +204,34 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-telegraf':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []
'so-suricata':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits:
- memlock=524288000
- name: memlock
soft: 524288000
hard: 524288000
'so-zeek':
final_octet: 99
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits:
- name: core
soft: 0
hard: 0
- name: nofile
soft: 1048576
hard: 1048576
'so-kafka':
final_octet: 88
port_bindings:
@@ -196,3 +242,4 @@ docker:
custom_bind_mounts: []
extra_hosts: []
extra_env: []
ulimits: []

View File

@@ -7,6 +7,22 @@ docker:
description: Default docker IP range for containers.
helpLink: docker.html
advanced: True
default_ulimits:
description: Default ulimit settings applied to all containers via the Docker daemon. Each entry specifies a resource name (e.g. nofile, memlock, core, nproc) with soft and hard limits. Individual container ulimits override these defaults.
advanced: True
helpLink: docker.html
forcedType: "[]{}"
syntax: json
uiElements:
- field: name
label: Resource Name
required: True
- field: soft
label: Soft Limit
forcedType: int
- field: hard
label: Hard Limit
forcedType: int
containers:
so-dockerregistry: &dockerOptions
final_octet:
@@ -39,6 +55,22 @@ docker:
helpLink: docker.html
multiline: True
forcedType: "[]string"
ulimits:
description: Ulimit settings for the container. Each entry specifies a resource name (e.g. nofile, memlock, core, nproc) with optional soft and hard limits.
advanced: True
helpLink: docker.html
forcedType: "[]{}"
syntax: json
uiElements:
- field: name
label: Resource Name
required: True
- field: soft
label: Soft Limit
forcedType: int
- field: hard
label: Hard Limit
forcedType: int
so-elastic-fleet: *dockerOptions
so-elasticsearch: *dockerOptions
so-influxdb: *dockerOptions
@@ -62,42 +94,6 @@ docker:
so-idh: *dockerOptions
so-elastic-agent: *dockerOptions
so-telegraf: *dockerOptions
so-suricata:
final_octet:
description: Last octet of the container IP address.
helpLink: docker.html
readonly: True
advanced: True
global: True
port_bindings:
description: List of port bindings for the container.
helpLink: docker.html
advanced: True
multiline: True
forcedType: "[]string"
custom_bind_mounts:
description: List of custom local volume bindings.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
extra_hosts:
description: List of additional host entries for the container.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
extra_env:
description: List of additional ENV entries for the container.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
ulimits:
description: Ulimits for the container, in bytes.
advanced: True
helpLink: docker.html
multiline: True
forcedType: "[]string"
so-suricata: *dockerOptions
so-zeek: *dockerOptions
so-kafka: *dockerOptions

View File

@@ -51,6 +51,12 @@ so-elastalert:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastalert'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastalert'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- require:
- cmd: wait_for_elasticsearch
- file: elastarules

View File

@@ -45,6 +45,12 @@ so-elastic-fleet-package-registry:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastic-fleet-package-registry'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastic-fleet-package-registry'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
delete_so-elastic-fleet-package-registry_so-status.disabled:
file.uncomment:
- name: /opt/so/conf/so-status/so-status.conf

View File

@@ -54,6 +54,12 @@ so-elastic-agent:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastic-agent'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastic-agent'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- require:
- file: create-elastic-agent-config
- file: trusttheca

View File

@@ -133,6 +133,12 @@ so-elastic-fleet:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elastic-fleet'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elastic-fleet'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: trusttheca
- x509: etc_elasticfleet_key

View File

@@ -45,15 +45,17 @@ so-elasticsearch:
- discovery.type=single-node
{% endif %}
- ES_JAVA_OPTS=-Xms{{ GLOBALS.elasticsearch.es_heap }} -Xmx{{ GLOBALS.elasticsearch.es_heap }} -Des.transport.cname_in_publish_address=true -Dlog4j2.formatMsgNoLookups=true
ulimits:
- memlock=-1:-1
- nofile=65536:65536
- nproc=4096
{% if DOCKER.containers['so-elasticsearch'].extra_env %}
{% for XTRAENV in DOCKER.containers['so-elasticsearch'].extra_env %}
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-elasticsearch'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-elasticsearch'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- port_bindings:
{% for BINDING in DOCKER.containers['so-elasticsearch'].port_bindings %}
- {{ BINDING }}

View File

@@ -52,6 +52,12 @@ so-hydra:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-hydra'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-hydra'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- restart_policy: unless-stopped
- watch:
- file: hydraconfig

View File

@@ -39,6 +39,12 @@ so-idh:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-idh'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-idh'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: opencanary_config
- require:

View File

@@ -58,6 +58,12 @@ so-influxdb:
- {{ XTRAHOST }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-influxdb'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-influxdb'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: influxdbconf
- x509: influxdb_key

View File

@@ -60,6 +60,12 @@ so-kafka:
{% if KAFKA_EXTERNAL_ACCESS %}
- /opt/so/conf/kafka/kafka_server_jaas.conf:/opt/kafka/config/kafka_server_jaas.conf:ro
{% endif %}
{% if DOCKER.containers['so-kafka'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-kafka'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
{% for sc in ['server', 'client'] %}
- file: kafka_kraft_{{sc}}_properties

View File

@@ -51,6 +51,12 @@ so-kibana:
{% for BINDING in DOCKER.containers['so-kibana'].port_bindings %}
- {{ BINDING }}
{% endfor %}
{% if DOCKER.containers['so-kibana'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-kibana'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: kibanaconfig

View File

@@ -45,6 +45,12 @@ so-kratos:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-kratos'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-kratos'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- restart_policy: unless-stopped
- watch:
- file: kratosschema

View File

@@ -96,6 +96,12 @@ so-logstash:
- {{ BIND }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-logstash'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-logstash'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: lsetcsync
- file: trusttheca

View File

@@ -75,6 +75,12 @@ so-nginx:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers[container_config].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers[container_config].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- cap_add: NET_BIND_SERVICE
- port_bindings:
{% for BINDING in DOCKER.containers[container_config].port_bindings %}

View File

@@ -51,6 +51,12 @@ so-redis:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-redis'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-redis'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- entrypoint: "redis-server /usr/local/etc/redis/redis.conf"
- watch:
- file: trusttheca

View File

@@ -51,6 +51,12 @@ so-dockerregistry:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-dockerregistry'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-dockerregistry'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- retry:
attempts: 5
interval: 30

View File

@@ -40,6 +40,12 @@ so-sensoroni:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-sensoroni'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-sensoroni'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: /opt/so/conf/sensoroni/sensoroni.json
- require:

View File

@@ -78,6 +78,12 @@ so-soc:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-soc'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-soc'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: trusttheca
- file: /opt/so/conf/soc/*

View File

@@ -41,6 +41,12 @@ strelka_backend:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-strelka-backend'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-strelka-backend'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- restart_policy: on-failure
- watch:
- file: strelkasensorcompiledrules

View File

@@ -44,6 +44,12 @@ strelka_coordinator:
- {{ BIND }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-strelka-coordinator'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-strelka-coordinator'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
delete_so-strelka-coordinator_so-status.disabled:
file.uncomment:
- name: /opt/so/conf/so-status/so-status.conf

View File

@@ -41,6 +41,12 @@ strelka_filestream:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-strelka-filestream'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-strelka-filestream'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: filestream_config

View File

@@ -46,6 +46,12 @@ strelka_frontend:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-strelka-frontend'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-strelka-frontend'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: frontend_config

View File

@@ -43,7 +43,13 @@ strelka_gatekeeper:
{% for XTRAENV in DOCKER.containers['so-strelka-gatekeeper'].extra_env %}
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% endif %}
{% if DOCKER.containers['so-strelka-gatekeeper'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-strelka-gatekeeper'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
delete_so-strelka-gatekeeper_so-status.disabled:
file.uncomment:

View File

@@ -40,6 +40,12 @@ strelka_manager:
- {{ XTRAENV }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-strelka-manager'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-strelka-manager'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: manager_config

View File

@@ -29,7 +29,7 @@ so-suricata:
{% if SURICATAMERGED.config['af-packet'][0]['mmap-locked'] == "yes" and DOCKER.containers['so-suricata'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-suricata'].ulimits %}
- {{ ULIMIT }}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- binds:

View File

@@ -66,6 +66,12 @@ so-telegraf:
- {{ XTRAHOST }}
{% endfor %}
{% endif %}
{% if DOCKER.containers['so-telegraf'].ulimits %}
- ulimits:
{% for ULIMIT in DOCKER.containers['so-telegraf'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- watch:
- file: trusttheca
- x509: telegraf_crt

View File

@@ -18,9 +18,12 @@ so-zeek:
- image: {{ GLOBALS.registry_host }}:5000/{{ GLOBALS.image_repo }}/so-zeek:{{ GLOBALS.so_version }}
- start: True
- privileged: True
{% if DOCKER.containers['so-zeek'].ulimits %}
- ulimits:
- core=0
- nofile=1048576:1048576
{% for ULIMIT in DOCKER.containers['so-zeek'].ulimits %}
- {{ ULIMIT.name }}={{ ULIMIT.soft }}:{{ ULIMIT.hard }}
{% endfor %}
{% endif %}
- binds:
- /nsm/zeek/logs:/nsm/zeek/logs:rw
- /nsm/zeek/spool:/nsm/zeek/spool:rw