npmctl
npmctl is a Python CLI for automating Nginx Proxy Manager through its API.
npmctl is built as an AI-native operations tool. The repository includes a Codex skill at skills/nginx-proxy-manager/SKILL.md, so an AI agent can manage Nginx Proxy Manager with explicit safety rules, command shapes, and verification steps instead of guessing raw API calls.
It focuses on safe Proxy Host workflows: creating and updating hosts without clobbering unspecified fields, matching existing certificates, safely reissuing custom-manager certificates for replacement domain sets, managing raw advanced_config snippets, configuring custom locations, and validating changes. It also covers audit, proxy verify/lint, snapshot/diff/restore, and reusable presets so operators and agents can review and recover NPM state before making changes. When used with a custom multi-agent NPM manager build, it can also manage remote NPM agent nodes and send proxy/certificate operations to a selected node.
npmctl talks to Nginx Proxy Manager by sending requests to its REST API. It has been tested against Nginx Proxy Manager 2.14.0 and the user-maintained multi-agent NPM manager in this workspace; compatibility with other Nginx Proxy Manager versions is not guaranteed.
AI-Native Skill
The included nginx-proxy-manager skill teaches agents to use npmctl as the stable executor for Nginx Proxy Manager changes.
Key rules encoded in the skill:
- Never put URL paths in
forward_host; targets are origin URLs likehttp://host:port. - Use host-level
advanced_configfor host snippets and location-leveladvanced_configfor custom location snippets. - Preserve unspecified fields, existing snippets, and existing locations during updates.
- Verify mutations with
npmctl proxy get DOMAIN -o json,npmctl proxy verify DOMAIN, andnpmctl proxy test DOMAIN --scheme auto --fail-on-5xxfor public hosts. - Use audit/lint/snapshot/diff before risky changes before risky changes.
- Require explicit user intent for destructive actions such as delete, clearing snippets, restoring snapshots, or removing locations.
Install
With Homebrew:
brew tap NightWatcher314/homebrew-formula
brew install npmctl
With uv from PyPI:
uv tool install nginx-proxy-manager-ctl
For development:
UV_NO_CONFIG=1 UV_DEFAULT_INDEX=https://pypi.org/simple uv sync --locked
UV_NO_CONFIG=1 UV_DEFAULT_INDEX=https://pypi.org/simple uv run --locked npmctl --help
Configure
Create a profile and log in:
npmctl config profile add home --url https://nginx.example.com --use
npmctl auth login --identity admin@example.com
npmctl auth status
Use a specific profile for one command:
NPMCTL_PROFILE=home npmctl proxy list
Inspect the active configuration:
npmctl config get
npmctl doctor
npmctl doctor --agents -o yaml
Multi-Agent Manager Builds
Custom NPM manager builds can expose /api/agents plus agent_id forwarding for Nginx resources. npmctl supports those endpoints:
npmctl agent list -o json
npmctl agent add --name edge-114 --url http://REMOTE_NPM:81 --identity admin@example.com --password-stdin
npmctl agent test 1
Target one remote node for a command, a profile, or the current shell:
npmctl proxy list --agent-id 1
npmctl cert list --agent-id 1 -o json
npmctl config set-agent-id 1
NPMCTL_AGENT_ID=1 npmctl proxy apply app.example.com --to http://192.168.1.10:8080 --cert auto
Use npmctl config set-agent-id local to clear the profile default and operate on the manager itself. Remote agent credentials are stored by the manager; prefer a dedicated service/admin account on the remote node.
Proxy Hosts
List and inspect Proxy Hosts:
npmctl proxy list
npmctl proxy get app.example.com -o json
Create or update a host:
npmctl proxy apply app.example.com \
--to http://192.168.1.10:8080 \
--cert auto \
--force-ssl \
--websocket \
--http2
proxy apply preserves existing fields that are not specified on the command line. This is intended to make repeated automation safe.
Test a public host with a structured health result. --scheme auto tries HTTPS first and falls back to HTTP only when HTTPS cannot be reached. By default 5xx responses exit non-zero; use --expect-status when a specific status is required.
npmctl proxy test app.example.com --scheme auto --timeout 10 --expect-status 200 -o yaml
npmctl proxy test app.example.com --scheme https --allow-5xx -o json
Safety Workflows
Use these command families for safer agent-assisted operations. They are read-only by default except for explicit restore/preset apply operations.
Audit an NPM instance before a maintenance session:
npmctl audit run -o yaml
npmctl audit run --agent-id 1 -o json
Verify or lint proxy hosts after edits. proxy verify performs active checks of a specific host, while proxy lint performs static checks such as path-in-target mistakes, missing certificates, or risky snippet patterns:
npmctl proxy verify app.example.com --agent-id 1
npmctl proxy lint app.example.com -o yaml
Create a backup before larger changes, compare current state to a snapshot, and restore only with explicit intent:
npmctl proxy snapshot app.example.com --agent-id 1 --file npm-proxy-before.json
npmctl proxy diff app.example.com --agent-id 1 --file npm-proxy-before.json
npmctl proxy restore app.example.com --agent-id 1 --file npm-proxy-before.json --dry-run
npmctl proxy restore app.example.com --agent-id 1 --file npm-proxy-before.json --yes
Reusable presets cover common advanced_config snippets such as Authentik forward-auth, large uploads, long timeouts, SSE/token streaming, and root redirects:
npmctl preset list
npmctl preset show streaming-sse
npmctl preset apply app.example.com streaming-sse --dry-run
npmctl preset apply app.example.com large-upload --client-max-body-size 500m
Certificates
List certificates, find the best match for a domain, and safely reissue an existing certificate ID on custom NPM manager builds that support certificate reissue:
npmctl cert list -o json
npmctl cert match app.example.com -o json
npmctl cert reissue-analyze 12 --domains "app.example.com www.example.com" -o yaml
npmctl cert reissue 12 --domains "app.example.com www.example.com" --yes
cert reissue first performs the same safety analysis as cert reissue-analyze. If removing domains would uncover proxy/redirection/dead hosts, use --detach-uncovered-hosts only when you intentionally want those hosts to stop referencing the certificate. Stream hosts block reissue and must be handled manually in NPM.
Advanced Config
Set host-level advanced_config from stdin:
npmctl proxy advanced set app.example.com --stdin <<'NGINX'
if ($request_uri = "/") {
return 302 /management.html;
}
NGINX
Set a custom location and its location-level advanced_config:
npmctl proxy location apply app.example.com /api --to http://192.168.1.10:8081
npmctl proxy location advanced set app.example.com /api --stdin <<'NGINX'
proxy_set_header X-Forwarded-Prefix /api;
NGINX
Targets must be origin URLs such as http://host:port. Do not put URL paths in forward_host; use custom locations, forward_path, or Nginx snippets for path behavior.
Authentication and Storage
By default, npmctl saves API tokens but not passwords. To save a password in the active profile:
NPMCTL_PASSWORD='...' npmctl auth login --identity admin@example.com --save-password
Later logins can reuse the saved password:
npmctl auth login --use-saved-password
npmctl doctor --agents can diagnose configured remote agents. If manager or remote-agent credentials are stale, npmctl adds a JWT-expired hint that points to npmctl auth login for manager tokens or npmctl agent update AGENT_ID --password-stdin for remote agent credentials.
Remove only the saved plaintext password while keeping the profile and token:
npmctl auth forget-password
The config file is stored at ~/.config/npmctl/config.json with mode 0600, but saved passwords are still plaintext. Only use --save-password on machines you trust.
Publishing
PyPI releases use GitHub Trusted Publishing. After pushing an existing release
tag, dispatch .github/workflows/publish-pypi.yml with the tag name:
gh workflow run publish-pypi.yml --ref main -f tag=v0.5.3
The workflow verifies the tag and package versions, builds from that tag, and publishes with GitHub OIDC. Do not store a long-lived PyPI token in GitHub.
License
MIT
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 nginx_proxy_manager_ctl-0.5.3.tar.gz.
File metadata
- Download URL: nginx_proxy_manager_ctl-0.5.3.tar.gz
- Upload date:
- Size: 22.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac20c5d162278be4dab9b23359d295f2059207af8fddeb12c066bee3002e55d5
|
|
| MD5 |
225f1f7535c9a94eb4838c0ff6d209b6
|
|
| BLAKE2b-256 |
94472077d32f72dc28f226dbcb31c75098cb07fbd1de81a2afe07a279637927d
|
File details
Details for the file nginx_proxy_manager_ctl-0.5.3-py3-none-any.whl.
File metadata
- Download URL: nginx_proxy_manager_ctl-0.5.3-py3-none-any.whl
- Upload date:
- Size: 31.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e051e4fa53d42e4e88f9e475199c1680d5285d61ed3566cb583dc2e0372bcfc4
|
|
| MD5 |
cc243c420e98a8bc886769d26ad162a1
|
|
| BLAKE2b-256 |
5c891ed8b1b09bb8790e435c2f364a5f211e2a2e38fe9208db65c0a1be464ea6
|