Metadata-Version: 2.3
Name: config-ninja
Version: 1.7.0
Summary: Use special ninja powers to manage system configurations 🥷
License: # MIT License
         
         Copyright (c) 2025 Bryant Finney
         
         Permission is hereby granted, free of charge, to any person obtaining a copy
         of this software and associated documentation files (the "Software"), to deal
         in the Software without restriction, including without limitation the rights
         to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         copies of the Software, and to permit persons to whom the Software is
         furnished to do so, subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         SOFTWARE.
Author: Bryant Finney
Author-email: <bryant.finney@outlook.com>
Requires-Python: >=3.8.1,<4
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Provides-Extra: all
Provides-Extra: appconfig
Provides-Extra: local
Provides-Extra: poe
Requires-Dist: boto3 (>=1.34,<2.0) ; extra == "all"
Requires-Dist: boto3 (>=1.34,<2.0) ; extra == "appconfig"
Requires-Dist: jinja2 (>3.1.4,<4.0)
Requires-Dist: poethepoet (>=0.29,<0.31) ; extra == "all"
Requires-Dist: poethepoet (>=0.29,<0.31) ; extra == "poe"
Requires-Dist: pyspry (>=1.0.2,<1.1.0)
Requires-Dist: pyyaml (>=6.0,<7.0)
Requires-Dist: sdnotify (>=0.3.2,<0.4.0)
Requires-Dist: sh (>=2.0,<3.0) ; sys_platform != "win32"
Requires-Dist: tomlkit (>=0.12.3,<0.14.0)
Requires-Dist: typer (>=0.9,<0.16)
Requires-Dist: typing-extensions (>=4.7,<5.0) ; python_version < "3.9"
Requires-Dist: watchfiles (>=0.21,<0.25) ; extra == "all"
Requires-Dist: watchfiles (>=0.21,<0.25) ; extra == "local"
Project-URL: Documentation, https://config-ninja.github.io/config-ninja/config_ninja.html
Project-URL: Homepage, https://github.com/config-ninja/config-ninja
Project-URL: changelog, https://github.com/config-ninja/config-ninja/releases
Project-URL: issues, https://github.com/config-ninja/config-ninja/issues
Project-URL: readthedocs, https://config-ninja.readthedocs.org/home.html
Project-URL: source, https://github.com/config-ninja/config-ninja
Description-Content-Type: text/markdown

# Config Ninja 🥷

[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![🎨 poe (push)](https://github.com/config-ninja/config-ninja/actions/workflows/push-poe.yaml/badge.svg)](https://github.com/config-ninja/config-ninja/actions/workflows/push-poe.yaml)
[![pylint](https://config-ninja.github.io/config-ninja/reports/pylint.svg)](https://config-ninja.github.io/config-ninja/reports/pylint-report.txt)
[![codecov](https://codecov.io/gh/config-ninja/config-ninja/graph/badge.svg?token=R3DFDSNK9U)](https://codecov.io/gh/config-ninja/config-ninja)
[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/config-ninja/config-ninja/main.svg)](https://results.pre-commit.ci/latest/github/config-ninja/config-ninja/main)
[![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://config-ninja.github.io/config-ninja/reports/mypy-html)
[![docs: pdoc](https://img.shields.io/badge/docs-pdoc-blueviolet?logo=github)](https://config-ninja.github.io/config-ninja/config_ninja.html)
[![readthedocs](https://readthedocs.org/projects/config-ninja/badge/?version=latest)](https://config-ninja.readthedocs.io/en/latest/home.html)
[![PyPI version](https://badge.fury.io/py/config-ninja.svg)](https://badge.fury.io/py/config-ninja)
[![Downloads](https://static.pepy.tech/badge/config-ninja/month)](https://pepy.tech/project/config-ninja)

Similar to [`confd`](https://github.com/kelseyhightower/confd), manage your system configuration files by populating [Jinja2](https://jinja.palletsprojects.com/en/3.1.x/) 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:

```mermaid
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](https://jinja.palletsprojects.com/en/3.1.x/) for managing server configuration files
- ✅ Extensible design supports backends for new providers and formats
- ✅ [`jinja2`](https://jinja.palletsprojects.com/en/3.1.x/) templating for arbitrary configuration file formats
- ✅ Execute [`poethepoet`](https://poethepoet.natn.io/index.html) 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:

```sh
curl -sSL https://config-ninja.github.io/config-ninja/install.py | python3 -
```

To view available installation options, run the installer with the `--help` flag:

```sh
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](https://config-ninja.github.io/config-ninja/config_ninja/contrib.html#available-backends) (or choose a specific one):

```sh
pipx install 'config-ninja[all]'
```

#### With [`uv`](https://github.com/astral-sh/uv)

```sh
uv tool install 'config-ninja[all]'
```

### Enable the `systemd` Service

After installing `config-ninja`, enable it as a `systemd` service for the current user:

```sh
# 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`:

```sh
sudo config-ninja self install --config /etc/config-ninja/alternate.yaml
```

## How It Works

To demonstrate how the mechanics work (using the [local backend](https://config-ninja.readthedocs.io/en/latest/config_ninja/contrib/local.html)):

1. create a settings file for `config-ninja`:
   ```sh
   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
   ```
2. run `config-ninja` in monitor mode:
   ```sh
   config-ninja apply --poll
   ```
3. in a separate shell, create the `config.toml`:
   ```sh
   cat <<EOF >./.local/config.toml
   [example-0]
   a = "first value"
   b = "second value
   EOF
   ```
4. Inspect the `settings.json` file created by `config-ninja`:
   ```sh
   cat ./.local/settings.json
   ```
   ```json
   {
     "example-0": {
       "a": "first value",
       "b": "second value"
     }
   }
   ```
5. Make changes to the data in `config.toml`, and `config-ninja` will update `settings.json` accordingly:
   ```sh
   cat <<EOF >>./.local/config.toml
   [example-1]
   c = "third value"
   d = "fourth value
   EOF
   cat ./.local/settings.json
   ```
   ```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](https://config-ninja.github.io/config-ninja/config_ninja/contrib.html) for a list of supported config providers.

