Skip to main content

Konfig

Quality Gate Status Reliability Rating Security Rating Maintainability Rating Vulnerabilities Bugs Lines of Code Duplicated Lines (%)

Settings management, pluggable secrets, and run-scoped logging for Python applications.

Konfig provides three foundational capabilities every Python application needs, with an optional lightweight app lifecycle context manager that ties them together. It is a clean-sheet replacement for dtPyAppFramework.

Features

  • Layered settings with system/user/env/runtime precedence and persistent writes
  • Pluggable secrets with OS keyring, AES-encrypted file, and AWS Secrets Manager backends
  • Run-scoped logging with historical retention, structured JSON mode, and stdio-safe output
  • Optional centralised log forwarding: one nominated collector gathers every container's logs over pinned TLS, discovered automatically through the shared secrets store
  • Platform-aware defaults for config, data, and log directories (macOS, Linux, Windows)
  • Optional app lifecycle via a sync/async context manager — no inheritance required
  • Python 3.10+

Installation

pip install konfig

For AWS Secrets Manager support:

pip install konfig[aws]

Secrets

AWS Secrets Manager (designated secret)

Point konfig at a single AWS secret that holds a JSON bundle of your secrets (the secret must already exist):

export KONFIG_AWS_SECRETS_MANAGER=arn:aws:secretsmanager:eu-west-1:123456789012:secret:myapp/secrets-AbCdEf
from konfig import Secrets

secrets = Secrets()               # env var selects the AWS bundle backend
api_key = secrets.get("api_key")
secrets.set("api_key", "sk-new")  # read-modify-write back to the bundle

Requires pip install konfig[aws].

AWS Secrets Manager settings document (KONFIG_AWS_SETTINGS)

Deliver an application's entire configuration as one JSON document held in a single Secrets Manager secret — no config file or per-setting environment variables needed in the task definition:

export KONFIG_AWS_SETTINGS=arn:aws:secretsmanager:eu-west-1:123456789012:secret:myapp/settings-AbCdEf

The secret's SecretString must be a JSON object holding the same nested settings tree a config file would. A plain secret name is also accepted; the region then comes from the default AWS provider chain (with an ARN it is taken from the ARN). An equivalent constructor argument exists for programmatic use — Settings(aws_settings=...) — with the environment variable winning when both are set. Requires pip install konfig[aws].

Precedence (highest to lowest): runtime -> env vars -> AWS settings -> user file -> system file -> defaults — environment variables remain the operator's immediate per-container override, while the AWS document overrides anything baked into the image.

Behaviour:

  • Read-only. settings.set(...) keeps writing to the runtime layer or config files exactly as before.
  • Fail fast. A missing/unreadable secret, non-JSON payload, or non-object top level raises at startup rather than silently degrading to defaults. Error messages name the secret, never its payload.
  • Fetched once. The document is read at construction and only re-fetched by settings.reload(); there is no background polling.
  • Composes with secrets. Values in the document may be secret:// URIs, resolved as usual by the active secrets backend.

This is independent of KONFIG_AWS_SECRETS_MANAGER. Pointing both at the same secret works, but keeping configuration and secret material in separate Secrets Manager entries is recommended so IAM can distinguish "may read config" from "may read credentials".

First boot on AWS: seeded stores

When konfig starts against empty stores (an empty or whitespace-only SecretString, or a bare {}), it writes a template for the operator instead of leaving them to transcribe documentation:

  • The KONFIG_AWS_SETTINGS settings secret is seeded with the application's defaults tree as pretty-printed JSON. Startup continues with reads resolving exactly as if the layer were absent.
  • The KONFIG_AWS_SECRETS_MANAGER bundle secret is seeded with a "CHANGEME" placeholder for every secret://<name> reference in the effective settings. Resolving an unpopulated placeholder logs a warning naming the key. AppContext runs this automatically at startup; when composing Settings and Secrets yourself, call secrets.seed_from(settings).

The intended first-boot flow: create the two (empty) secrets, grant secretsmanager:PutSecretValue on them for first boot, start once, edit the seeded documents, restart — and optionally drop the write grant again.

Seeding never touches a non-empty store (malformed payloads keep failing fast, and partial documents are never merged into), never creates secrets, and a failed seed write (for example AccessDenied under a read-only role) only logs a warning. Concurrent replicas racing the first boot are benign: every writer writes identical content. Operators who want no write attempt at all can disable seeding outright with KONFIG_AWS_SEED=false.

Running the LocalStack integration tests

The AWS integrations have opt-in integration tests that run against a local LocalStack container (no AWS account needed). They auto-skip when LocalStack is not running, so they never affect the normal test run.

docker compose up -d         # start LocalStack
pip install -e ".[dev,aws]"  # boto3 + dev tools
pytest -m localstack         # run only the integration test
docker compose down          # stop LocalStack

The tests look for LocalStack at http://127.0.0.1:4566, the port docker-compose.yml publishes. If it is published somewhere else, point the tests at it with KONFIG_TEST_LOCALSTACK_URL (an http(s) URL with a host and a port):

KONFIG_TEST_LOCALSTACK_URL=http://127.0.0.1:24566 pytest -m localstack

Quick Start

from konfig import AppContext

with AppContext(
    name="My Application",
    version="1.0.0",
    config_file="config.yaml",
    env_prefix="MYAPP",
) as ctx:
    host = ctx.settings.get("database.host", "localhost")
    api_key = ctx.secrets.get("api_key")
    ctx.logger.info("Starting with host=%s", host)

For async applications:

async with AppContext(name="My Server", version="2.0.0") as ctx:
    await run_server(ctx.settings)

Config file format

The config file format is chosen by the KONFIG_CONFIG_FORMAT environment variable (yaml, json, or sqlite). When unset, the format is detected from the file extension, defaulting to YAML. Reading, updating, and creating settings work in every format. (TOML config files are still supported by extension detection, but are read-only and cannot be selected via KONFIG_CONFIG_FORMAT.)

export KONFIG_CONFIG_FORMAT=sqlite   # store settings in a SQLite database file
from konfig import Settings

settings = Settings(config_file="config.db")
settings.set("database.host", "localhost", persist="user")  # written to SQLite
settings.set("debug", True)                                  # omit persist: in-memory only
host = settings.get("database.host")

Centralised log forwarding

To collect every container's logs in one place, nominate one instance as the collector and turn on forwarding everywhere else. Each instance keeps its own local logs as before:

# On the collector (needs a persistent volume at its log directory)
KONFIG_LOG_COLLECTOR=true
KONFIG_LOG_COLLECTOR_ADVERTISE=log-collector:9020

# On every other instance
KONFIG_LOG_CENTRAL=true
KONFIG_LOG_INSTANCE_LABEL=worker-3   # optional

AppContext does the rest. The collector generates a TLS certificate and an access token and publishes them in the shared secrets store, senders discover them, and every record lands, tagged with its instance, in <log_dir>/central/latest/central.log on the collector. See Centralised Log Forwarding.

Each subsystem (Settings, Secrets, LogManager) can also be used independently. See the full documentation in the docs/ directory:

Samples

Working examples are provided in the samples/ directory:

File Description
basic_settings.py Config files, defaults, env vars, overrides
secrets_usage.py Store, retrieve, and delete secrets
logging_demo.py Run-scoped logging with retention
app_context.py Full lifecycle with all subsystems
async_app.py Async context manager usage
custom_backend.py Implementing a custom SecretBackend
central_logging.py Centralised log forwarding: collector and sender roles

Development

CI installs the development tools from a hash-locked requirements file and then konfig itself. Do the same locally to get exactly the versions CI tests with (the lock covers Linux, macOS and Windows on Python 3.10 to 3.13, and includes the dev and aws extras):

python -m pip install --require-hashes --only-binary :all: -r requirements/dev.txt
python -m pip install --no-deps --no-build-isolation -e .

pip install -e ".[dev,aws]" still works when you do not need the locked versions.

The lock files are generated from the .in files beside them, together with pyproject.toml, by uv 0.13.6 (the version CI uses). Regenerate them from the repository root after changing a dependency in pyproject.toml or a .in file:

uv pip compile --universal --generate-hashes --python-version 3.10 requirements/build.in -o requirements/build.txt
uv pip compile --universal --generate-hashes --python-version 3.10 pyproject.toml requirements/dev.in --extra dev --extra aws -o requirements/dev.txt

uv keeps the versions already in the lock files; add --upgrade (or --upgrade-package <name>) to move them on. CI regenerates both files and fails if the result differs from what is committed.

The GitHub Actions in .github/workflows/ are pinned to full commit SHAs with the tag as a trailing comment; Dependabot (.github/dependabot.yml) proposes updates to them weekly, as one grouped pull request, and never touches the lock files.

pytest
pytest --cov=konfig
mypy src/konfig
black src/ tests/
isort src/ tests/

License

MIT License. See LICENSE for details.

Metadata

Release files for cognisn-konfig 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cognisn-konfig 0.5.0
File Size Uploaded Provenance Actions
cognisn_konfig-0.5.0.tar.gz 186.7 kB With provenance Details for cognisn_konfig-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for cognisn-konfig 0.5.0
File Interpreter ABI Platform Actions
cognisn_konfig-0.5.0-py3-none-any.whl Python 3 none any Details for cognisn_konfig-0.5.0-py3-none-any.whl

Total release size: 258.6 kB

Release files / cognisn_konfig-0.5.0.tar.gz

Download URL cognisn_konfig-0.5.0.tar.gz
Size 186.7 kB
Tags Source
SHA-256 checksum
How to use checksums
34e28552ca87645714b48a54c6e6e9dab775ab8a2a732ae1f39a42d058bf323f
BLAKE2b-256 checksum
How to use checksums
d43025f9b12f6ba5cbbcf1c00c17feba5d48ea59f2ea289a856e1548db2d52e2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Release files / cognisn_konfig-0.5.0-py3-none-any.whl

Download URL cognisn_konfig-0.5.0-py3-none-any.whl
Size 71.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
73797f62a4a53c96e2f7c957d900ec3885dd845820105972d5f0e871e106f44d
BLAKE2b-256 checksum
How to use checksums
61fb67072e36630e93ea15284ae72930c3b7e0b7ca454b5cb67541c9eec4a702
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Security for cognisn-konfig 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for cognisn_konfig-0.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page