ProjectOperations CLI · 2026
Nginx Proxy Manager CLI
Command-line management of Nginx Proxy Manager proxy hosts, certificates, streams, users, and settings, so reverse-proxy changes can be scripted and reviewed.
- Go
- Nginx Proxy Manager API
- JSON
nginxpm proxy list1 api.example.com -> 10.0.0.4:8080 ssl enabled2 docs.example.com -> 10.0.0.9:3000 ssl enabled nginxpm cert test-http api.example.comapi.example.com reachable on port 80 nginxpm proxy update 1 -f proxy.jsonproxy host 1 updatedOperations CLI · Project
Nginx Proxy Manager CLI drives an instance from the terminal. It covers proxy hosts, redirection hosts, TCP and UDP streams, dead hosts, SSL certificates, access lists, users, the audit log and settings. I built it so a reverse-proxy change could live in a file, be reviewed, and be applied the same way twice.
Nginx Proxy Manager is a web admin panel, and a panel makes every change a form. The form is fine the first time. It is much less fine when a host has to be recreated after a rebuild. It is worse when two instances have drifted apart and the only way to compare them is to open both and read.
Same verbs everywhere
Every resource in the panel gets a command group. The groups share one lifecycle of list, get, create, update and delete, plus enable and disable wherever the panel has a toggle. Create and update take -f with JSON or YAML, and -f - reads a definition from standard input. Reads take -o table, -o json or -o yaml, and nginxpm config set defaults.output json makes JSON the standing default.
| Resource | Aliases |
|---|---|
proxy | proxy-host, ph |
redirect | redirection, redir, rh |
dead | dead-host, dh, 404 |
stream | streams, st |
cert | certificate, ssl |
access | access-list, acl |
Credentials and the token
The panel authenticates with an email and a password, and returns a JWT. The CLI exchanges credentials for a token on every invocation, and a saved profile stores the credentials rather than the token. Nothing expiring is ever written to disk, and there is no refresh path to get wrong. The cost is a password at rest in ~/.config/nginxpm-cli/config.yaml, created at mode 0600, which is why environment variables are the documented path for CI. Flags beat environment variables, which beat the profile. nginxpm status is the exception to all of this. It needs only the URL, reports server status, version and setup state, and never authenticates.
Where certificates surprise you
Certificates get verbs the other resources do not, because certificate work is where the surprises are. cert renew handles a Let’s Encrypt renewal by ID. cert dns-providers lists the DNS challenge providers the panel supports, and always returns JSON whatever -o says, because the response is a provider catalog rather than a table. cert test-http example.com www.example.com asks whether those domains answer on port 80 at all. That question is worth settling before blaming the proxy or the certificate, and it is the reason the command exists. Everything else is the ordinary lifecycle.
Choices and their cost
- The command tree mirrors the panel instead of improving on it. Anyone who knows the web UI already knows where a command lives. The cost is inheriting the panel vocabulary, including a resource genuinely called
deadfor a 404 host. - Definitions come from files, never from a wall of flags. A proxy host has too many fields to give each one a flag, and a file can be reviewed and committed. The trade-off is that creating a host means writing a JSON body, so a first run involves looking up the shape.
--read-onlyis the safety boundary and--no-inputis not.--no-inputonly removes prompts, so an unconfirmed delete fails rather than proceeding. Outside read-only mode,--confirmis what lets a delete through.- Storing credentials rather than a token is the decision I would revisit. If the panel ever issued a long lived API token, a scoped token on disk would beat a password that can change every setting.
Recreating a host
export NGINXPM_URL=https://npm.example.com
export [email protected] NGINXPM_PASSWORD=changeme
nginxpm status -o json | jq -r .version
nginxpm proxy list -o json | jq '.[] | {id, domains: .domain_names}'
nginxpm cert test-http api.example.com
nginxpm proxy update 1 -f proxy.json
nginxpm audit list -o json
That is the sequence after a rebuild. Check that the server answers at all, then read what already exists. Prove the domain responds on port 80, apply the definition kept in the repository, and confirm the audit log recorded the change. Run the same lines with NGINXPM_READ_ONLY=true and the update is refused while the four reads still work.
Where it stops
The CLI drives the Nginx Proxy Manager API. It does not write nginx configuration, and it cannot express anything the panel cannot. There is no plan or diff step: update applies the file it is handed, so comparing two instances means exporting both and diffing them yourself. cert dns-providers ignores the output flag. --insecure exists for a panel behind a certificate that cannot be verified, and is documented as unsuitable for production. It is MIT licensed and ships as one binary for macOS, Linux and Windows.
Next projectWeb Development