Command-line tool for managing Nginx Proxy Manager via API
Manage your NPM install via intuitive CLI commands. This tool was created for my personal workflow that uses Claude Code to manage my home lab. It probably has some gaps, and I'll happily accept issues or contributions.
- Proxy Host Management - Create, list, update, and delete proxy hosts via NPM API
- Proxy Cloning - Clone existing proxy hosts to new domains with automatic SSL certificate provisioning
- SSL Certificate Automation - End-to-end workflow: certificate creation, NPM integration, and attachment to proxy hosts
- Configuration Templates - Reusable patterns for common scenarios:
- Authentik forward authentication with SSO
- API/webhook bypass for unauthenticated endpoints
- VPN-only access restrictions
- WebSocket protocol support
- Combined Authentik + bypass patterns
- Tab Completion - ZSH autocomplete for commands, subcommands, and options
- Docker Integration - Automatic discovery and connection to NPM containers
- Rich CLI Output - Beautiful tables and formatted output using Rich
- Python 3.11 or higher
- uv package manager
- Running Nginx Proxy Manager instance
# Install as a tool (recommended)
uv tool install npm-cli
# Or install in a virtual environment
uv pip install npm-clinpm-cli --install-completion zshRestart your shell for completion to take effect. Tab completion will work for all commands and subcommands.
Configure connection to your NPM instance using environment variables:
export NPM_HOST=localhost # NPM host (default: localhost)
export NPM_PORT=81 # NPM port (default: 81)
export NPM_EMAIL=admin@example.com # NPM admin email
export NPM_PASSWORD=changeme # NPM admin passwordOr create a .env file in your project directory:
NPM_HOST=localhost
NPM_PORT=81
NPM_EMAIL=admin@example.com
NPM_PASSWORD=changemeAlternatively, use Docker auto-discovery (see Quick Start).
If NPM is running in Docker, auto-discover the container:
npm-cli config connectThis will find your NPM container and save connection details.
npm-cli config authThis caches an authentication token at ~/.config/npm-cli/token (valid for 24-48 hours).
npm-cli config statusVerify connection and authentication status.
npm-cli proxy listView all configured proxy hosts in a formatted table.
Quickly create similar proxy configurations by cloning:
# Clone with automatic SSL provisioning (if source has cert)
npm-cli proxy clone app.example.com app2.example.com
# Clone without SSL even if source has it
npm-cli proxy clone app.example.com test.example.com --no-ssl
# Clone by ID
npm-cli proxy clone 42 newapp.example.comThe clone command copies all configuration (backend, SSL settings, advanced config, templates) from the source proxy to new domain(s), automatically provisioning a new SSL certificate if the source has one attached.
Create a new proxy host:
npm-cli proxy create \
--domain example.com \
--forward-host 192.168.1.100 \
--forward-port 8080List all proxy hosts:
npm-cli proxy listShow proxy host details:
# By domain name
npm-cli proxy show example.com
# Or by ID
npm-cli proxy show 42Update a proxy host:
npm-cli proxy update example.com \
--forward-port 8081 \
--websockets-supportDelete a proxy host:
npm-cli proxy delete example.comClone an existing proxy to new domain(s) with automatic SSL provisioning:
# Clone by domain name (auto-provisions SSL if source has cert)
npm-cli proxy clone source.example.com new.example.com
# Clone by ID
npm-cli proxy clone 5 clone.example.com
# Clone without SSL certificate provisioning
npm-cli proxy clone app.example.com test.example.com --no-ssl
# Clone to multiple domains (comma-separated)
npm-cli proxy clone app.example.com "app1.local,app2.local"What gets cloned:
- All backend configuration (scheme, host, port)
- SSL settings (forced HTTPS, HSTS)
- Advanced nginx configuration
- WebSocket support
- Access lists
- All other proxy settings
What changes:
- Domain names (replaced with new domain)
- SSL certificate (new cert created if source has one, unless --no-ssl)
Create and attach a certificate:
# Create certificate with HTTP-01 challenge
npm-cli cert create --domain example.com
# Attach to proxy host
npm-cli cert attach --domain example.comList certificates:
npm-cli cert listShow certificate details:
# By domain name
npm-cli cert show example.com
# Or by ID
npm-cli cert show 5Create certificate with DNS challenge:
npm-cli cert create \
--domain example.com \
--provider cloudflare \
--credentials '{"api_token": "your-token"}'Apply production-tested nginx configuration templates to proxy hosts.
Authentik forward authentication:
npm-cli proxy template apply <proxy-id> authentik \
--backend http://app:3000API/webhook bypass (unauthenticated endpoints):
npm-cli proxy template apply <proxy-id> api-bypass \
--path "/api/" \
--path "/webhook/" \
--backend http://n8n:5678VPN-only access restrictions:
npm-cli proxy template apply <proxy-id> vpn-only \
--vpn-network 10.10.10.0/24 \
--lan-network 192.168.7.0/24WebSocket support:
npm-cli proxy template apply <proxy-id> websocketCombined Authentik + API bypass:
npm-cli proxy template apply <proxy-id> authentik-bypass \
--path "/api/" \
--path "/webhook/" \
--backend http://n8n:5678Auto-detect backend from proxy:
# CLI auto-constructs backend URL from proxy's forward_host:forward_port
npm-cli proxy template apply <proxy-id> authentikAppend to existing configuration:
# Use --append to add template to existing advanced_config
npm-cli proxy template apply <proxy-id> websocket --append| Template | Description | Required Options |
|---|---|---|
authentik |
Authentik forward auth with optional VPN/LAN restrictions | --backend (or auto-detect) |
api-bypass |
Unauthenticated bypass for API/webhook endpoints | --path (one or more), --backend |
vpn-only |
VPN and LAN network access restrictions | None (uses defaults) |
websocket |
WebSocket protocol upgrade headers | None |
authentik-bypass |
Combined Authentik auth + API bypass (most common) | --path (one or more), --backend |
Optional parameters:
--vpn-network- VPN network CIDR (default: 10.10.10.0/24)--lan-network- LAN network CIDR (default: 192.168.7.0/24)--vpn-only- Include VPN/LAN restrictions (default: true for authentik-bypass)--append- Append template to existing advanced_config instead of replacing
| Variable | Description | Default |
|---|---|---|
NPM_HOST |
NPM API host | localhost |
NPM_PORT |
NPM API port | 81 |
NPM_EMAIL |
NPM admin email | Required |
NPM_PASSWORD |
NPM admin password | Required |
Authentication tokens are cached at ~/.config/npm-cli/token and expire in 24-48 hours. Re-authenticate with:
npm-cli config authThe config connect command automatically discovers NPM containers using:
- Container name pattern (
nginx-proxy-manager,npm) - Container labels (
app=nginx-proxy-manager) - Image name pattern (
jc21/nginx-proxy-manager)
# Clone repository
git clone https://github.com/yourusername/npm-cli.git
cd npm-cli
# Install dependencies
uv sync
# Run CLI in development
uv run npm-cli --help# Run all tests
uv run pytest
# Run specific test file
uv run pytest tests/test_proxy.py
# Run with verbose output
uv run pytest -v
# Run with coverage
uv run pytest --cov=src/npm_cli# Check code with ruff
uv run ruff check src/
# Auto-fix issues
uv run ruff check src/ --fix
# Format code
uv run ruff format src/Building the package:
# Build wheel and source distribution
uv build
# Verify package contents
tar -tzf dist/npm_cli-*.tar.gzTest local installation:
# Create test environment
uv venv test-install
# Install from wheel
uv pip install dist/npm_cli-*.whl --python test-install/bin/python
# Test CLI
test-install/bin/npm-cli --help
test-install/bin/npm-cli version
# Clean up
rm -rf test-installPublish to PyPI:
# Set PyPI token
export PYPI_TOKEN="pypi-..."
# Publish
uv publish
# Create release tag
git tag -a v0.1.0 -m "Release v0.1.0 - Initial public release"
git push origin v0.1.0npm-cli/
├── src/npm_cli/
│ ├── __main__.py # CLI entry point, Typer app setup
│ ├── api/
│ │ └── models.py # Pydantic models for NPM API
│ ├── cli/
│ │ ├── proxy.py # Proxy host commands
│ │ ├── cert.py # SSL certificate commands
│ │ └── config.py # Configuration commands
│ ├── templates/
│ │ └── nginx.py # Nginx configuration templates
│ └── settings.py # Configuration management
├── tests/ # Test suite
└── pyproject.toml # Project metadata and dependencies
The project uses a three-tier testing approach:
- Unit Tests - Fast, isolated tests for template generation and model validation
- API Mocking - Tests CLI commands with mocked HTTP responses using pytest-httpx
- Manual Integration - End-to-end testing against a real NPM instance
# Run unit tests (fast)
uv run pytest tests/test_templates.py
# Run CLI tests with API mocking
uv run pytest tests/test_cli_*.py
# Run all tests
uv run pytestCurrent test suite includes:
- Template generation tests (16 test cases, 100% coverage)
- CLI command tests with mocked API responses
- Pydantic model validation tests
- Settings and configuration tests
- Python 3.11+ - Modern type hints and performance improvements
- uv - Fast, reliable package management (10-100x faster than pip)
- Typer - Type-safe CLI framework with automatic help generation
- Rich - Beautiful terminal output with tables and formatting
- Pydantic - Data validation with strict models
- httpx - Modern async-capable HTTP client
- docker-py - Docker container discovery and management
- API-First - Uses NPM API exclusively, no direct database access
- Type Safety - Comprehensive type hints with Pydantic validation
- Error Handling - Clear error messages with API response details
- Production Safety - Validation before applying changes
- Minimal Dependencies - Prefer stdlib where possible
The NPM API is undocumented. This tool uses:
- Reverse-engineered API endpoints from NPM source code
- Strict Pydantic models with
extra="ignore"for forward compatibility - Comprehensive error handling for API changes
MIT License - see LICENSE file for details
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Run linting and tests before committing
- Submit a pull request with clear description
- Built for managing Nginx Proxy Manager
- Inspired by production homelab automation needs
- Template patterns based on real-world configurations with Authentik SSO
Made with ❤️ for the NPM community
