Owner-scoped plan/apply/adopt controller for Nginx Proxy Manager resources.
Project description
npmctl
Owner-scoped GitOps for Nginx Proxy Manager
Validate desired-state YAML, plan safe owner-scoped changes, apply clean reconciles, and adopt existing NPM resources only when you ask for it.
npmctl is the Python package and console script for declarative, owner-scoped Nginx Proxy Manager automation. It manages proxy hosts, certificates, access lists, redirection hosts, dead hosts, streams, users, settings, and provider-backed DNS records without silently mutating foreign-owned resources.
Supported Python Versions
npmctl supports Python 3.10, 3.11, 3.12, 3.13, and 3.14.
Why npmctl
- Owner-scoped reconciliation instead of global mutable state
- Explicit
plan,apply, andadoptflows instead of ad hoc API scripting - Safe reference handling for certificates and access lists
- Fail-closed behavior when the target NPM schema does not support a required operation
- CLI-first workflows that fit GitOps, CI, and controlled repair operations
FAQ
What is npmctl?
Answer: npmctl is a GitOps-style controller for Nginx Proxy Manager that reads desired-state YAML, compares it to the live NPM API, and produces safe owner-scoped plans before any mutation happens.
What problem does npmctl solve?
Answer: npmctl replaces manual NPM clicking and one-off API scripts with repeatable desired state, explicit adoption, conflict detection, and controlled reconciliation for reverse-proxy resources.
Does npmctl modify resources it does not own?
Answer: No. npmctl treats NPM resources as owner-scoped, refuses to mutate foreign-owned resources, and only attaches metadata to unmanaged resources when you run npmctl adopt.
How does npmctl handle certificate issuance and rotation?
Answer: npmctl treats certificates as declarative resources in the same desired state as proxy hosts. Issuance happens when a desired certificate must be created, and rotation happens through explicit reconcile policy rather than hidden mutation of unrelated resources.
Can npmctl adopt existing manually created NPM resources?
Answer: Yes. npmctl adopt can attach npmctl ownership metadata to compatible unmanaged resources so future plans and applies can manage them under explicit owner scope.
Install
Use pipx for an isolated CLI install:
pipx install npmctl
npmctl --version
Use uv if you manage tools with uv:
uv tool install npmctl
npmctl --help
Use pip inside an existing virtual environment:
python -m venv .venv
. .venv/bin/activate
python -m pip install npmctl
npmctl --help
PowerShell activation:
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install npmctl
npmctl --help
Configure NPM
Set Nginx Proxy Manager API credentials as environment variables:
export NPM_BASE_URL=http://127.0.0.1:81/api
export NPM_IDENTITY=admin@example.com
export NPM_SECRET=changeme
Or pass them directly:
npmctl --base-url http://127.0.0.1:81/api --identity admin@example.com --secret changeme health
Quick Start
Validate desired state without touching the API:
npmctl validate ./desired-state
npmctl --output json validate ./desired-state
Plan owner-scoped changes:
npmctl plan ./desired-state --owner workload-a
Apply a clean plan:
npmctl apply ./desired-state --owner workload-a
Adopt unmanaged matching resources:
npmctl adopt ./desired-state --owner workload-a
npmctl adopt ./desired-state --owner workload-a --allow-field-drift
Desired State
Every managed resource needs npmctl ownership metadata:
apiVersion: npmctl.com/v1
schemaVersion: 2
proxy_hosts:
- domain_names: [app.example.com]
forward_scheme: http
forward_host: app
forward_port: 3000
meta:
managed_by: npmctl
owner: workload-a
resource_id: proxy.app
References use resource_id values:
apiVersion: npmctl.com/v1
schemaVersion: 2
certificates:
- name: wildcard-example
domain_names: ["*.example.com", example.com]
certificate_type: letsencrypt
api_payload:
provider: letsencrypt
meta:
managed_by: npmctl
owner: workload-a
resource_id: cert.wildcard-example
access_lists:
- name: private-admins
api_payload:
satisfy_any: 0
items: []
clients: []
meta:
managed_by: npmctl
owner: workload-a
resource_id: acl.private-admins
proxy_hosts:
- domain_names: [app.example.com]
forward_host: app
forward_port: 3000
certificate_ref: cert.wildcard-example
access_list_ref: acl.private-admins
ssl_forced: 1
allow_websocket_upgrade: 1
caching_enabled: 1
block_exploits: 1
meta:
managed_by: npmctl
owner: workload-a
resource_id: proxy.app
More Documentation
- Related PyPI package: https://pypi.org/project/npmctl-namecheap/
- Repository: https://github.com/groupsum/npmctl
- Examples: https://github.com/groupsum/npmctl/tree/master/examples/desired-state
- Docs: https://github.com/groupsum/npmctl/tree/master/docs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file npmctl-0.3.8.tar.gz.
File metadata
- Download URL: npmctl-0.3.8.tar.gz
- Upload date:
- Size: 44.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b69deb3ef523ca2701d40d4588560f8d96c6430a32b74b5ac00e0ad8b23d4a82
|
|
| MD5 |
d64e811679e55b93368ea03546d18f3d
|
|
| BLAKE2b-256 |
0fb08d7d46c9a1749807bff9458ec9bd574be3692a0f1575aaf839ac2bca4489
|
Provenance
The following attestation bundles were made for npmctl-0.3.8.tar.gz:
Publisher:
release.yml on groupsum/npmctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
npmctl-0.3.8.tar.gz -
Subject digest:
b69deb3ef523ca2701d40d4588560f8d96c6430a32b74b5ac00e0ad8b23d4a82 - Sigstore transparency entry: 1570951882
- Sigstore integration time:
-
Permalink:
groupsum/npmctl@42c29a79cce118deda2eff0305982d84e0598e38 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/groupsum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@42c29a79cce118deda2eff0305982d84e0598e38 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file npmctl-0.3.8-py3-none-any.whl.
File metadata
- Download URL: npmctl-0.3.8-py3-none-any.whl
- Upload date:
- Size: 56.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8024c946b336a4e28ee7da28b9b6c4799c44d9b588bd4e3ed91b8ff5bc5f3ce
|
|
| MD5 |
9d1c836eebd7642f47b31db0fa04b16d
|
|
| BLAKE2b-256 |
61ba220a5b29cf677197418cb005a39b0cbda6b8c2d724c95c57a15a8843e3fa
|
Provenance
The following attestation bundles were made for npmctl-0.3.8-py3-none-any.whl:
Publisher:
release.yml on groupsum/npmctl
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
npmctl-0.3.8-py3-none-any.whl -
Subject digest:
e8024c946b336a4e28ee7da28b9b6c4799c44d9b588bd4e3ed91b8ff5bc5f3ce - Sigstore transparency entry: 1570952356
- Sigstore integration time:
-
Permalink:
groupsum/npmctl@42c29a79cce118deda2eff0305982d84e0598e38 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/groupsum
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@42c29a79cce118deda2eff0305982d84e0598e38 -
Trigger Event:
workflow_dispatch
-
Statement type: