Skip to main content
Kosli Capture is experimental. The configuration format may still change between releases. See the tutorial to get started.
Kosli Capture reads its policy from a single config.yaml at the repo root. make validates and converts the file to config.json at build time, so a malformed file fails the deploy rather than shipping. The file has three top-level sections — naming, scope, and types — plus eks_onboarding and a global include_scaling toggle.

naming

Controls how Kosli environment names are derived for each discovered resource.

Env-name precedence

Env names are resolved through a single precedence chain, used for whole resources and namespace slices alike: Within the template, {prefix} itself resolves in this order:
  1. kosli:prefix tag on the resource
  2. types.<type>.prefix
  3. naming.prefix
  4. aws-{account_id}
Keep {type} in the template — env names are unique per Kosli org, and a bucket could otherwise share a name with a cluster.

scope

Global filters applied to every type, combined with the per-type filters.
How filters combine with per-type blocks:
  • include = global per-type pairs; a resource must match all of them (empty = opt-out mode).
  • exclude = global per-type pairs; matching any pair excludes the resource.

include_scaling

Global default for whether replica-count-only changes produce a new snapshot. Per-type blocks can override this. Default false — Kosli only snapshots on actual software change, not scaling.

types

Every type block accepts the same fields, plus a few type-specific ones. Shorthand <type>: true = enabled with no extra filters.

ecs

Per-cluster env by default. Optional grouping for tag-based aggregation (see Grouping).

eks

Per-cluster env by default. Optional namespaces for per-namespace scoping (see EKS namespaces).

lambda

Optional grouping overrides both (see Grouping).

s3

S3 is intentionally opt-in. A Kosli s3 environment fingerprints bucket content (for deployment tracking), not a bucket inventory. types.s3.include_tags must be non-empty; otherwise Kosli Capture records a gap and skips S3.

Grouping (Lambda and ECS)

types.lambda.grouping and types.ecs.grouping map an exact env name to a set of tag pairs. Resources matching all pairs of an entry are reported together in one snapshot call — snapshot lambda --function-names a,b,c or snapshot ecs --clusters a,b,c — to that env.
Rules:
  • Grouping takes precedence — matched resources go to the named env.
  • Unmatched resources fall through unchanged (Lambda’s granularity, ECS’s per-cluster env).
  • If a resource matches more than one entry, the first entry wins.
  • An entry with no tag pairs never matches anything.
Grouping is available for Lambda and ECS only. S3 buckets and EKS clusters are always reported to their own environments.

EKS namespaces

By default each discovered EKS cluster gets one Kosli environment. Clusters listed under types.eks.namespaces (still subject to tag filters) are reported per namespace. "*" sets a default for every cluster; exact cluster names override it.
Value forms:
  • List → derived env names ({name} becomes <cluster>-<ns>). Entries may be regex patterns (kosli --namespaces supports them), which are sanitized for the derived name.
  • Map → explicit namespace: env-name pairs. Preferred for regex patterns because the derived name would otherwise be sanitized. Explicit map entries are precedence level 1 — they beat every tag override.
Derived namespace env names follow {prefix}-eks-<cluster>-<ns>.

eks_onboarding

Self-onboarding is IAM-fenced with eks:principalArn / eks:policyArn conditions so Kosli Capture can only grant that one policy to its own role. Clusters must have authentication mode API or API_AND_CONFIG_MAP.

Config sources at runtime

ConfigSource (CloudFormation parameter) decides where the Lambda reads its policy on each run: All three deliver the same config.json produced from config.yaml; the only difference is where it lands. make seed-config picks the right target from CONFIG_SOURCE and is a no-op for baked. Runtime sources fail closed: if a config fetch fails, Kosli Capture reuses the last-known-good config (when the Lambda sandbox is warm) or fails the run. It does not fall back to the baked copy, so a stale policy can never re-include resources you have excluded.
Keep the authoritative config.yaml in the repo and push versions via make seed-config (or CI) rather than hand-editing the SSM parameter or S3 object.

Complete example

Last modified on July 23, 2026