# The complete env-file schema for `solace-util`. Copy to env/<name>.yaml, edit, and
# run any command with `-e <file>`. One file can drive all three platforms; each reads
# only the sections it needs. For a minimal starter, run
# `solace-util examples --platform kubernetes` (or docker, or podman).
#
# TEMPLATE with placeholder secrets: replace semp.adminPass, the image credentials and
# redundancy.psk before real use.
#
# Every secret key has a sibling *Env key naming an environment variable to read the
# value from instead -- `pass: CHANGE-ME` or `passEnv: SOLACE_ADMIN_PASS`, never both.
# With the *Env form this file carries no secret and is safe to commit.
#
# EVERY key the schema accepts appears below. A commented-out key is optional and shows
# the default that applies when omitted. Decoding is strict: an unknown or misspelled
# key is a hard error.

# timezone: Asia/Singapore          # omitted -> the broker keeps the image default

image:
  repo: solace-pubsub-standard      # mandatory
  tag: "10.26.0.8755"               # mandatory
  registry: registry.example.com    # optional prefix; omit for docker.io
  user: repo-user                   # registry login: Kubernetes builds the pull secret,
  pass: CHANGE-ME-registry          # docker/podman run `<runtime> login`. secret
  # passEnv: SOLACE_REGISTRY_PASS   # ...or name the variable holding it instead

# scaling: omit to take platform defaults. maxConnections is the Solace scaling tier and
# FIXES how many cores the broker gets on every platform -- there is no cpu COUNT key in
# this schema. It must be exactly one of the five values below; a value between tiers is
# rejected, not rounded. Memory is the tier's default and stays overridable, and on docker
# and podman so is WHICH cores (<docker|podman>.container.cpuset).
#
# Every key below is ALSO settable under the broker setting name this tool emits for it
# (e.g. `system_scaling_maxconnectioncount` for maxConnections) -- see docs/configuration.md
# for the full pairing. Both spellings write the same value; setting a key under both at
# once fails to load, naming both.
#
#   maxConnections | cores | cpuset | memory default
#   ---------------+-------+--------+----------------
#   100            | 2     | 0-1    | 3410Mi  (Kubernetes default tier)
#   1000           | 2     | 0-1    | 6898Mi  (container default tier)
#   10000          | 4     | 0-3    | 12435Mi
#   100000         | 8     | 0-7    | 30925Mi
#   200000         | 12    | 0-11   | 52581Mi
#
# scaling:
#   maxConnections: 100             # Kubernetes default 100, container default 1000
#   maxSpoolUsageMB: 10000          # Kubernetes default 10000, container default 100000
#   maxQueueMessages: 100
#   maxKafkaBridge: 0
#   maxKafkaConnections: 0
#   maxBridges: 25
#   maxSubscriptions: 50000
#   maxGuaranteedMsgMB: 10

# semp: the broker's management (SEMP/CLI) credentials. There is no username key: the
# built-in users are `admin` and `monitor` on every platform, which is the broker's own
# naming and what the Kubernetes operator requires.
semp:
  adminPass: CHANGE-ME-admin        # secret. Mandatory on docker/podman; on
                                    # Kubernetes, unset means kubernetes.adminSecret
                                    # is referenced, or the operator generates one
  # adminPassEnv: SOLACE_ADMIN_PASS # ...or name the variable holding it instead
  monitorPass: CHANGE-ME-monitor    # Kubernetes monitor user. secret; needs adminPass
  # monitorPassEnv: SOLACE_MON_PASS # ...or name the variable holding it instead
  # additionalUsers:                # extra CLI users beyond admin/monitor. Every field
  #   - username: appuser           # is required; password takes the same
  #     accessLevel: read-only      # literal-or-passwordEnv choice as above
  #     password: CHANGE-ME-appuser # accessLevel: none | read-only | mesh-manager |
  #   - username: rouser            #   read-write | admin
  #     accessLevel: mesh-manager   # Created at boot on every platform. Username must
  #     passwordEnv: SOLACE_ROPASS  # start with a letter or _, 1-32 chars; on Kubernetes
                                    # no . or - either (they ride the pod ENVIRONMENT
                                    # there, from <kubernetes.name>-additional-users --
                                    # the CRD cannot mount a Secret as files)

tls:                                # uncomment cert+certKey together once you have a
                                    # real pair: `broker generate` and `broker deploy`
                                    # build the TLS Secret from these files.
                                    #
                                    # Leave them out to use a Secret that already
                                    # exists -- name it in kubernetes.tlsServerSecret
                                    # and nothing here reads a certificate at all.
                                    # Kubernetes names the built Secret after
                                    # kubernetes.tlsServerSecret, or <name>-tls
                                    #
                                    # HOST paths. A relative one resolves against THIS
                                    # FILE's directory; an absolute one is used as-is
  # cert: certs/tls.crt             # server certificate, ALONE -- a file that also
                                    # holds its key is refused
  # certKey: certs/tls.key          # inseparable from cert on docker/podman: the
                                    # broker reads one file built from the pair
  # certPassphrase: CHANGE-ME-pass  # secret; only when the key is encrypted.
                                    # docker/podman ONLY -- the CRD has no passphrase
                                    # field, so `validate` warns and Kubernetes needs
                                    # an unencrypted key
  # certPassphraseEnv: SOLACE_TLS_PASS   # ...or name the variable holding it instead
  # cas:                            # the CA chain presented after cert, in order;
  #   - certs/intermediate.crt      # trusted CAs are broker.domainCerts instead

# The HA group: whether there is one, who is in it, and the key its members
# authenticate to each other with. Omitting `enabled` means false -- HA provisions three
# brokers, so it is opted into rather than inherited.
redundancy:
  enabled: true
  primary:
    name: solace-primary            # the broker's routername. MANDATORY on containers in
                                    # HA; in standalone it is optional and this host's own
                                    # hostname is used when omitted
    addr: 10.0.0.11                 # IP or resolvable name; mandatory on containers in HA.
                                    # Also how a host identifies ITSELF when its hostname
                                    # matches no name above -- the cloud case, where the
                                    # instance is called something like ip-10-0-0-11
  backup:
    name: solace-backup             # mandatory on containers in HA
    addr: 10.0.0.12                 # also reached from the primary at verify time by
                                    # `broker perform redundancy-test`
  monitor:
    name: solace-monitor            # mandatory on containers in HA
    addr: 10.0.0.13
  psk: CHANGE-ME-run-openssl-rand-base64-32
                                    # secret. YOU generate it -- nothing here does:
                                    #   openssl rand -base64 32
                                    #
                                    # MANDATORY on docker/podman -- nothing distributes a
                                    # key across three hosts, so each env file must carry
                                    # the SAME value, and an empty one is refused at load.
                                    # OPTIONAL on Kubernetes: left empty, the operator
                                    # generates and distributes its own; set, it becomes
                                    # the preshared_auth_key entry of the admin Secret
                                    # built from semp.adminPass, which it then needs.
  # pskEnv: SOLACE_REDUNDANCY_PSK   # ...or name the variable holding it instead

# broker: platform-neutral post-deployment settings, applied over the broker CLI.
# broker:
#   cliScriptsDir: cli               # the only folder cli-script/shell-script read; a
#                                    # relative one resolves against THIS FILE's directory
#   hostDiagnosticDir: diag-configs  # local folder for gathered diagnostics
#   productKeys: []                  # `broker configure product-keys`
#   domainCerts:                     # HOST paths. A relative one resolves against THIS
#                                    # FILE's directory; an absolute one is used as-is.
#                                    # A leading ~ expands to the home directory of the
#                                    # user RUNNING this tool, which makes such a path
#                                    # non-portable between operators -- write it out in
#                                    # full in any env file you share
#     dirs:                          # every matching file DIRECTLY inside each entry is
#                                    # loaded; subdirectories are NOT walked. A dir that
#                                    # cannot be read fails the command before anything
#                                    # is uploaded -- it is not skipped. Unset means no
#                                    # directories, which is a no-op like an empty files:
#       - /opt/solace/prod-cas       # plain path -> the default extensions cer, crt, pem
#       - path: /opt/solace/partner-cas    # ...or a mapping, to name your own set
#         fileExt: cer,crt,pem       # REPLACES the default for THIS dir only
#     files: {}                      # CA-NAME: FULL host path. Use it for a certificate
#                                    # whose derived name you do not want, or to load one
#                                    # file out of a directory of many, e.g.
#                                    # my-ca-name: /opt/solace/partner-cas/some-ca.pem
#                                    # The CA name is the operand of `create domain-
#                                    # certificate-authority` AND the filename inside the
#                                    # broker, so it is letters, digits, underscore, dash
#                                    # and period, 64 chars max. A name under dirs: is
#                                    # derived as <last-dir-element>_<filename>; two
#                                    # certificates resolving to one name is an error
#                                    # naming both source paths

# replication: a DR pair of SEPARATE brokers, per message-VPN -- each VPN active at one
# site and standby at the other. Not redundancy: that is one HA group, this is two of
# them. Omit the whole section unless this broker replicates.
#
# `broker configure data-replication` CONFIGURES this broker only: the mate addresses,
# replication enable/disable from the vpns list, and each VPN's state active|standby.
# `broker perform data-replication` VERIFIES and MOVES across both: it checks the mates
# and that every listed VPN is already enabled, then demotes and promotes. It writes no
# configuration of its own. Both take the short form `dr`.
#
# THIS BLOCK IS BYTE-IDENTICAL AT BOTH SITES. Nothing in it is written from one site's
# point of view: each broker reads its own `show router-name`, finds itself in sites:,
# and whichever entry is NOT itself is its mate. Copy it verbatim into the DR site's env
# file -- there is nothing to reverse. The rest of the file stays site-specific.
#
# replication:
#   sites:                          # exactly 2
#     - virtualRouterName: "v:tuas9csol1"   # the site's KEY: what activeAt references,
#                                   # and the operand the MATE is given as
#                                   # `replication mate virtual-router-name`. Mandatory,
#                                   # never derived. QUOTE IT -- the colon
#       routerNames: [tuas9csol1]   # what this broker ANSWERS TO, matched against its
#                                   # own `show router-name`. EVERY node of the site's
#                                   # HA group, so a backup node also finds itself
#       endpoints:                  # how the OTHER BROKER dials this one -- never
#                                   # dialled by this tool. At most 2 per transport;
#                                   # an omitted transport means plainText
#         - { host: 10.160.132.1, port: 55555 }
#         - { host: 10.160.132.1, port: 55003, transport: compressed }
#         - { host: 10.160.132.1, port: 55443, transport: ssl }
#       via:                        # how THIS TOOL reaches this site when it is the
#                                   # MATE. EXACTLY ONE child; the key present IS the
#                                   # mechanism. Read only by `perform data-replication`
#                                   # and only from the OTHER site's entry -- a broker
#                                   # never reads its own, it uses this file's
#                                   # kubernetes:/docker:/podman: section. Optional:
#                                   # `configure data-replication` needs none of it
#         kubernetes:
#           command: kubectl        # THIS FIELD RUNS A BINARY: same rule as
#                                   # kubernetes.command -- a bare name from
#                                   # {kubectl, oc} followed by flags only. Carry the
#                                   # cluster here: `kubectl --context sg`
#           namespace: solace-sg
#           name: solace            # the mate's PubSubPlusEventBroker name
#     - virtualRouterName: "v:tuas8csol1"
#       routerNames: [tuas8csol1]
#       endpoints:
#         - { host: 10.150.132.1, port: 55443, transport: ssl }
#       via:
#         semp:                     # curl, exec'd inside THIS broker's own container --
#                                   # no second kubeconfig anywhere
#           host: 10.150.132.1      # NOT derived from endpoints: replication runs on
#                                   # the message backbone, so a reachable endpoint
#                                   # proves nothing about SEMP reachability
#           port: 1943              # 1943 with tls, 8080 without
#           tls: true               # declared, never inferred from this broker's own
#                                   # posture. false is allowed and WARNS: the admin
#                                   # password then crosses a WAN in the clear
#           # insecure: false       # skip certificate verification (self-signed mate)
#           passEnv: SOLACE_DR_ADMIN_PASS   # exactly one of pass/passEnv/passSecret.
#                                   # The username is always the broker's own admin,
#                                   # and there is no prompt for the password
#           # pass: ""              # secret; discouraged, this file travels
#           # passSecret:           # a Secret read with this site's via.kubernetes
#           #   namespace: solace-dr    # command, or this file's kubernetes.command
#           #   name: dr-broker-admin   # the mate's admin Secret
#           #   key: username_admin_password
#   vpns:                           # listed = replication ENABLED at both sites. A VPN
#                                   # replicating on the broker but absent here is SHUT
#                                   # DOWN by `configure data-replication`
#     - { name: ORDERS,   activeAt: "v:tuas9csol1" }
#     - { name: PAYMENTS, activeAt: "v:tuas8csol1" }

# A real env file declares only the platform(s) it targets: the CLI detects the platform
# from which of kubernetes:/docker:/podman: is present, so an unused section must be left
# out entirely rather than emptied. A file declaring several requires --platform or a
# prompt. An empty section still counts -- `docker: {}` is enough. All three appear here
# only so every key has one place to look it up.
kubernetes:
  # command: kubectl                # the cluster CLI. A scalar is split on whitespace,
                                    # so it can carry a profile:
                                    # `kubectl --kubeconfig /path/.kubeconfig-dev`.
                                    # THIS FIELD RUNS A BINARY: restricted to a bare
                                    # name from {kubectl, oc} followed by flags only.
                                    # A wrapper such as `microk8s kubectl` needs
                                    # --allow-command microk8s per run.
                                    # A leading ~ expands to the home directory of the
                                    # user RUNNING this tool in every argument BUT the
                                    # first -- `--kubeconfig ~/solace/kubecontext` works,
                                    # `~/bin/kubectl` does not (the binary is a bare
                                    # name). Same non-portability as a path key
  name: dev-broker                  # mandatory
  namespace: solace                 # mandatory
  adminSecret: solace-admin-secret  # optional; unset derives <name>-admin when
                                    # semp.adminPass is set. WITH adminPass, this tool
                                    # builds the Secret (this name or the derived
                                    # default) and removes it on teardown; WITHOUT it, a
                                    # configured name must already exist and is only
                                    # referenced. Neither: the operator generates
                                    # <name>-pubsubplus-admin-creds itself
  # tlsServerSecret: solace-tls-secret  # optional; unset derives <name>-tls when
                                    # tls.cert/certKey are set. WITH them, this tool
                                    # builds the Secret (this name or the derived
                                    # default) and removes it on teardown; WITHOUT
                                    # them a configured name must already exist (made
                                    # by hand, or by cert-manager) and is only
                                    # referenced -- never read, written or deleted.
                                    # Neither: no tls block in the CR
  imagePullSecret: solace-image-pull   # optional; unset derives <name>-image-pull
                                    # when image.user/pass are set. WITH those
                                    # credentials, this tool builds the Secret (this
                                    # name or the derived default) and removes it on
                                    # teardown; WITHOUT them, a configured name is a
                                    # Secret that already exists and is only
                                    # referenced -- same rule as tlsServerSecret above
  # imagePullPolicy: IfNotPresent   # Always | IfNotPresent | Never
  updateStrategy: automatedRolling  # automatedRolling | manualPodRestart
  serviceAccount: solace-sa         # optional
  # securityContext:                # omitted entirely when unset. Ids are plain
                                    # decimal 0-2147483647; "0" means the operator's
                                    # default (1000001/1000002), or on OpenShift an
                                    # id the SCC assigns
  #   runAsUser: "1000001"
  #   fsGroup: "1000002"
  # containerSecurity:
  #   runAsUser: "1000001"
  #   runAsGroup: "1000002"
  storage:                          # two ways to get a data volume. Naming both is
                                    # refused: `class` PROVISIONS one, customVolumeMount
                                    # mounts one that already exists
    class: standard                 # StorageClass; omit to use the cluster default
    msgNodeSize: 30Gi               # mandatory unless customVolumeMount covers every node
  # monNodeSize: 5Gi               # monitor-node PVC; the monitor holds no spool
  #   customVolumeMount:            # mount PVCs YOU created. Every node in the
  #     primary: solace-primary-pvc # redundancy group or none; entries for nodes a
  #     backup: solace-backup-pvc   # standalone file does not deploy are ignored.
  #     monitor: solace-monitor-pvc # `broker remove --delete-data` NEVER deletes these
                                    # -- the volume may predate this broker
  # msgNode:                        # message-node pod resources. No cpu key: CPU is
  #   mem: 3410Mi                   # fixed by scaling.maxConnections, and setting one
                                    # is a load-time error
  # operator:                       # cluster-scoped EventBroker Operator
  #   image: solace/pubsubplus-eventbroker-operator:1.4.2   # unqualified on purpose:
                                    # image.registry is prefixed onto it, so a mirrored
                                    # operator needs no second registry key
  #   namespace: pubsubplus-operator-system
  #   watchNamespaces: ""           # comma-separated, de-duplicated. `operator deploy`
                                    # UNIONS this with what the installed operator
                                    # already watches, so several env files can share one
  #   watchBrokerNs: true           # also watch kubernetes.namespace. false with an
                                    # empty watchNamespaces watches EVERY namespace
  #   cpu: 500m
  #   mem: 512Mi
  loadBalancer:
    ip: 10.0.0.50                   # MetalLB requested IP (optional)
  #   ipPool: sample-ip-pool        # MetalLB address-pool name
  #   annotations:                  # extra service annotations, "key: value"
  #     - "external-dns.alpha.kubernetes.io/hostname: broker.example.com"
  # ports:                          # name=containerPort[:servicePort][/proto]. Unset,
                                    # the CR carries no service.ports and the operator's
                                    # own default applies -- for the bundled operator,
                                    # exactly the list below. Set, your list REPLACES it.
  #  - tcp-ssh=2222
  #  - tcp-semp=8080
  #  - tls-semp=1943
  #  - tcp-smf=55555
  #  - tcp-smfcomp=55003
  #  - tls-smf=55443
  #  - tcp-smfroute=55556
  #  - tcp-web=8008
  #  - tls-web=1443
  #  - tcp-rest=9000
  #  - tls-rest=9443
  #  - tcp-amqp=5672
  #  - tls-amqp=5671
  #  - tcp-mqtt=1883
  #  - tls-mqtt=8883
  #  - tcp-mqttweb=8000
  #  - tls-mqttweb=8443
  # podAnnotations:                 # key and value are quoted for you
  #   prometheus.io/scrape: "true"
  # podLabels:
  #   example.com/tier: messaging
  # placement:                      # optional pod scheduling. These are SELECTORS --
  #   labelsPrimary: ["nodetype: solace"]   # this tool never labels your nodes
  #   labelsBackup: []
  #   labelsMonitor: []
  #   tolerationsPrimary: ["dedicated=solace:NoSchedule"]
  #   tolerationsBackup: []
  #   tolerationsMonitor: []
  #   antiAffinityNamespaces: []    # default: [kubernetes.namespace]; drives the
  #   antiAffinityWeight: 100       # built-in one-broker-per-host spread
  #   nodeAffinity:                 # additive; unset leaves the CR as above
  #     preferred:                  # weight 1-100 + ANDed match expressions
  #       - weight: 80
  #         match:
  #           - {key: topology.kubernetes.io/zone, operator: In, values: [az-1]}
  #     required:                   # one ANDed term; operator In|NotIn|Exists|
  #       - {key: solace.com/broker, operator: Exists}   # DoesNotExist|Gt|Lt
  #   podAffinity: []               # terms: weight 0 = required, 1-100 = preferred;
  #   podAntiAffinity: []           # each needs topologyKey, plus optional
                                    # matchLabels and namespaces
  # Unsupported here -- edit the CR directly if you need them: monitoring (the
  # Prometheus exporter sidecar), service.type (always LoadBalancer), per-port
  # nodePort, extraEnvVars/extraEnvVarsCM/extraEnvVarsSecret. There is no Kubernetes
  # healthCheck either: the operator runs its own probes and gates traffic on them.

docker:
  # command: docker                 # a bare name from {docker, docker-compose, nerdctl}
                                    # then flags only. Same rules as kubernetes.command:
                                    # THIS FIELD RUNS A BINARY. A wrapper such as
                                    # `lima nerdctl` needs --allow-command lima.
                                    # sudo/doas/su/pkexec are never approvable -- run
                                    # `sudo solace-util broker deploy` instead
  # compose: docker compose         # omitted -> the runtime plus `compose`. Set to
                                    # `docker-compose` for the standalone v1 binary
  # composeFile: docker-compose.yml # path of the generated compose file. It names the
                                    # secrets it needs; `broker deploy` supplies the
                                    # values through the process environment, so no
                                    # secret is written beside it
  container:
    dataDir: /opt/solace/data       # mandatory, must be ABSOLUTE. Also what
                                    # `broker remove --delete-data` empties (the directory
                                    # itself stays)
  #   name: solace                  # container name; also prefixes this host's secret
                                    # names, so two brokers on one host cannot clash
  #   runUser: "1000001:0"          # uid:gid the container runs as; defaults to the
                                    # broker image's own user and group. "0:0" would be
                                    # host root here, since docker's engine is privileged
  #   mem: 6898m                    # docker's b|k|m|g suffix, NOT the Mi/Gi
                                    # kubernetes.msgNode.mem takes. Defaults to the
                                    # scaling tier's memory
  #   cpuset: 0-1                   # WHICH host cpus the MESSAGING nodes may use, in
                                    # the engines' own syntax (0-3, or 0,2,4). Defaults
                                    # to the tier's cores as 0-(cores-1), and must name
                                    # exactly that many: the count is the tier's
  #   monitorCpuset: 0              # WHICH cpu the HA monitor runs on, exactly one. It
                                    # arbitrates quorum and carries no spool, so it gets
                                    # a fixed 1 cpu and 2g whatever the tier
  #   ulimits:
  #     core: -1                    # core-dump size: -1 (unlimited, the default and
                                    # Solace's recommendation) or bytes. A dump copies
                                    # the broker's memory, secrets included, so 0 keeps
                                    # none on disk. nofile and memlock are fixed
  #   healthCheck:                  # opt-in; off leaves the artifact unchanged
  #     enabled: true               # polls the broker's readiness endpoint. REQUIRES
                                    # broker 10.26+ AND a version-numbered image.tag to
                                    # prove it; older or "latest" fails loud
  #     cmd: [curl, -fs, "http://localhost:8080/SEMP/v2/monitor"]
                                    # your own probe argv, run inside the container.
                                    # Setting it skips the version check. Podman renders
                                    # it as a command line, so avoid tokens with spaces
  #     interval: 5s                # the values shown are the defaults
  #     timeout: 5s
  #     retries: 3
  #     startPeriod: 60s
  # network:
  #   mode: bridge                  # bridge | host. bridge publishes network.ports and
                                    # nothing else. host is an opt-in widening: the
                                    # container shares this host's network, every
                                    # listener binds on every interface, and only the
                                    # host firewall decides what reaches it
  #   ports:                        # host:container, optionally [ip:] first and /tcp or
  #     - 8080:8080                 # /udp last; either side may be a lo-hi range.
  #     - 55555:55555               # NEVER defaulted: omitted, nothing is published.
  #     - 8300-8302:8300-8302       # An HA member also publishes 8300-8302 and 8741,
  #     - 8741:8741                 # and SEMP (8080, or 1943 with TLS) for its mate

podman:
  # command: podman                 # same rules as docker.command; only `podman`
  rootless: false                   # true = user systemd + `podman unshare` chown, and
                                    # runUser defaults to 1000:0 instead of 1000001:0.
                                    # Declared, then checked against who runs the
                                    # command: true refuses under sudo, false requires
                                    # it. `generate` alone does not check
  # quadletDir: /etc/containers/systemd   # rootless: $XDG_CONFIG_HOME/containers/systemd
  # baseDir: /opt/solace            # optional and UNUSED. Earlier builds wrote the
                                    # server-certificate bundle (the PRIVATE KEY) here;
                                    # it now rides podman's secret store. When set, must
                                    # be ABSOLUTE, and deploy/remove delete the old
                                    # <container.name>-tls-servercertificate.pem in it
  container:
    dataDir: /opt/solace/data       # mandatory, must be ABSOLUTE (see docker above)
  #   name: solace
  #   runUser: "1000:0"             # rootful defaults to the image's own 1000001:0;
                                    # ROOTLESS defaults to 1000:0, because a rootless
                                    # container's uids come out of this user's subuid
                                    # range and 1000001 would need 1000002 entries
                                    # against a stock 65536. Needs >= 1001 subuids, but
                                    # NO subgids: gid 0 maps to your own group. "0:0"
                                    # needs neither and maps container root to you, at
                                    # the cost of in-container isolation
  #   mem: 6898m                    # same rules as docker.container.mem
  #   cpuset: 0-1                   # same rules as docker.container.cpuset. Under
                                    # rootless: true the user@<uid>.service drop-in
                                    # must delegate the cpuset controller; deploy
                                    # refuses a host where it is missing
  #   monitorCpuset: 0              # same rules as docker.container.monitorCpuset
  #   ulimits:
  #     core: -1                    # same rules as docker.container.ulimits.core. Under
                                    # rootless: true user@<uid>.service must grant it
  #   healthCheck:                  # same shape as docker.container.healthCheck
  #     enabled: true               # built-in readiness probe; needs broker 10.26+
  # network:                        # same rules as docker.network
  #   mode: bridge
  #   ports:
  #     - 8080:8080
