config_ninja
Config Ninja 🥷
Similar to confd
, manage your system configuration files by populating Jinja2 templates with data from a remote provider.
The config-ninja
agent monitors the backend source for changes. When the source data is changed, the agent updates the local configuration file with the new data:
sequenceDiagram loop polling config-ninja->>backend: query for changes end backend->>+config-ninja: [backend changed] fetch config config-ninja->>-filesystem: write updated configuration file
Features
- ✅ Integration with AWS AppConfig for managing server configuration files
- ✅ Extensible design supports backends for new providers and formats
- ✅
jinja2
templating for arbitrary configuration file formats - ✅ Execute
poethepoet
tasks after updating files
Installation
config-ninja
is installed using the official installer or with pip
/ pipx
. After installation, you can enable config-ninja
as a systemd
service.
Official Installer
The recommended way to install config-ninja
is with the official installer:
curl -sSL https://config-ninja.github.io/config-ninja/install.py | python3 -
To view available installation options, run the installer with the --help
flag:
curl -sSL https://config-ninja.github.io/config-ninja/install.py | python3 - --help
usage: install [-h] [--version VERSION] [--pre] [--uninstall] [--force] [--path PATH] [--backends BACKENDS]
Installs the latest (or given) version of config-ninja
options:
-h, --help show this help message and exit
--version VERSION install named version
--pre allow pre-release versions to be installed
--uninstall uninstall config-ninja
--force respond 'yes' to confirmation prompts; overwrite existing installations
--path PATH install config-ninja to this directory
--backends BACKENDS comma-separated list of package extras to install, or 'none' to install no backends
With pip
/ pipx
Alternatively, use pip
/ pipx
to install all available backends (or choose a specific one):
pipx install 'config-ninja[all]'
With uv
uv tool install 'config-ninja[all]'
Enable the systemd
Service
After installing config-ninja
, enable it as a systemd
service for the current user:
# omit '--user' to install the agent at the system level
config-ninja self install --user
Multiple instances of the service can also be installed to reference different settings files. For example, the following command will create the service named etc-config--ninja-alternate.service
:
sudo config-ninja self install --config /etc/config-ninja/alternate.yaml
How It Works
To demonstrate how the mechanics work (using the local backend):
create a settings file for
config-ninja
:cat <<EOF >config-ninja-settings.yaml CONFIG_NINJA_OBJECTS: example-0: dest: format: json path: ./.local/settings.json source: backend: local format: toml init: kwargs: path: ./.local/config.toml EOF
run
config-ninja
in monitor mode:config-ninja apply --poll
in a separate shell, create the
config.toml
:cat <<EOF >./.local/config.toml [example-0] a = "first value" b = "second value EOF
Inspect the
settings.json
file created byconfig-ninja
:cat ./.local/settings.json
{ "example-0": { "a": "first value", "b": "second value" } }
Make changes to the data in
config.toml
, andconfig-ninja
will updatesettings.json
accordingly:cat <<EOF >>./.local/config.toml [example-1] c = "third value" d = "fourth value EOF cat ./.local/settings.json
{ "example-0": { "a": "first value", "b": "second value" }, "example-1": { "c": "third value", "d": "fourth value" } }
Chances are, you'll want to update the config-ninja-settings.yaml
file to use a remote backend (instead of local
). See config_ninja.contrib for a list of supported config providers.
Navigation
config_ninja.cli
Commands and CLI documentation.
config_ninja.contrib
For supported backends.
config_ninja.contrib.appconfig
Integrate with the AWS AppConfig service.
config_ninja.contrib.local
Use a local file as the backend.
config_ninja.contrib.secretsmanager
Integrate with the AWS SecretsManager service.
config_ninja.hooks
Execute poethepoet
tasks as callback hooks for backend updates.
config_ninja.settings
For settings and configuration.
config_ninja.systemd
Integration with systemd
.
1""".. include:: ../../README.md 2 3# Navigation 4 5## `config_ninja.cli` 6 7Commands and CLI documentation. 8 9## `config_ninja.contrib` 10 11For supported backends. 12 13### `config_ninja.contrib.appconfig` 14 15Integrate with the AWS AppConfig service. 16 17### `config_ninja.contrib.local` 18 19Use a local file as the backend. 20 21### `config_ninja.contrib.secretsmanager` 22 23Integrate with the AWS SecretsManager service. 24 25## `config_ninja.hooks` 26 27Execute [`poethepoet`](https://poethepoet.natn.io/) tasks as callback hooks for backend updates. 28 29## `config_ninja.settings` 30 31For settings and configuration. 32 33## `config_ninja.systemd` 34 35Integration with `systemd`. 36""" # noqa: D415 37 38from __future__ import annotations 39 40import sys 41import warnings 42from pathlib import Path 43from typing import Any 44 45import pyspry 46 47__version__ = '0.0.0' 48 49from config_ninja.settings import DEFAULT_PATHS, load 50from config_ninja.settings import resolve_path as resolve_settings_path 51 52__all__ = ['DEFAULT_SETTINGS_PATHS', 'load_settings', 'resolve_settings_path'] 53 54DEFAULT_SETTINGS_PATHS = DEFAULT_PATHS 55"""Check each of these locations for `config-ninja`_'s settings file. 56 57The following locations are checked (ordered by priority): 58 591. `./config-ninja-settings.yaml` 602. `~/config-ninja-settings.yaml` 613. `/etc/config-ninja/settings.yaml` 62 63.. _config-ninja: https://config-ninja.readthedocs.io/home.html 64""" 65 66 67def load_settings(path: Path) -> pyspry.Settings: # pragma: no cover 68 """(deprecated) Load the settings file at the given path. 69 70 This function is deprecated and will be removed in a future release. Use `config_ninja.settings.load()` instead. 71 """ 72 warnings.warn( 73 '`config_ninja.load_settings()` is deprecated and will be removed in a future release. Use ' 74 '`config_ninja.settings.load()` instead.', 75 DeprecationWarning, 76 stacklevel=2, 77 ) 78 return load(path).settings 79 80 81def main(*args: Any) -> None: # pylint: disable=missing-function-docstring 82 """Entrypoint for the `config-ninja` CLI. 83 84 When arguments are provided, they are used to replace `sys.argv[1:]`. 85 """ 86 if args: 87 sys.argv[1:] = list(args) 88 89 from config_ninja.cli import app 90 91 app(prog_name='config-ninja')
Check each of these locations for config-ninja's settings file.
The following locations are checked (ordered by priority):
./config-ninja-settings.yaml
~/config-ninja-settings.yaml
/etc/config-ninja/settings.yaml
68def load_settings(path: Path) -> pyspry.Settings: # pragma: no cover 69 """(deprecated) Load the settings file at the given path. 70 71 This function is deprecated and will be removed in a future release. Use `config_ninja.settings.load()` instead. 72 """ 73 warnings.warn( 74 '`config_ninja.load_settings()` is deprecated and will be removed in a future release. Use ' 75 '`config_ninja.settings.load()` instead.', 76 DeprecationWarning, 77 stacklevel=2, 78 ) 79 return load(path).settings
(deprecated) Load the settings file at the given path.
This function is deprecated and will be removed in a future release. Use config_ninja.settings.load()
instead.
137def resolve_path() -> Path: 138 """Return the first path in `DEFAULT_PATHS` that exists.""" 139 for path in DEFAULT_PATHS: 140 if path.is_file(): 141 return path 142 143 raise FileNotFoundError('Could not find config-ninja settings', DEFAULT_PATHS)
Return the first path in DEFAULT_PATHS
that exists.