mirror of
https://github.com/b3nw/nginx-proxy-manager-mcp.git
synced 2026-05-20 07:35:47 -05:00
feat: Add configurable defaults via NPM_PROXY_DEFAULTS env var
- Add NPM_PROXY_DEFAULTS JSON environment variable for default settings - Merge user overrides with base defaults (certificate_id, ssl_forced, etc.) - Update create_proxy_host to use None defaults and pull from config - Update env.example with documentation and examples
This commit is contained in:
@@ -7,3 +7,8 @@ NPM_SECRET=changeme
|
|||||||
NPM_MCP_HOST=0.0.0.0
|
NPM_MCP_HOST=0.0.0.0
|
||||||
NPM_MCP_PORT=8000
|
NPM_MCP_PORT=8000
|
||||||
NPM_MCP_TRANSPORT=stdio # stdio or http
|
NPM_MCP_TRANSPORT=stdio # stdio or http
|
||||||
|
|
||||||
|
# Proxy Host Creation Defaults (JSON)
|
||||||
|
# Set default values for create_proxy_host tool parameters
|
||||||
|
# Example with wildcard cert: NPM_PROXY_DEFAULTS='{"certificate_id": 24, "ssl_forced": true}'
|
||||||
|
# NPM_PROXY_DEFAULTS='{"certificate_id": 0, "ssl_forced": true, "block_exploits": true, "allow_websocket_upgrade": true}'
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
"""Configuration management using pydantic-settings."""
|
"""Configuration management using pydantic-settings."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from pydantic import field_validator
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
# Default values for proxy host creation
|
||||||
|
DEFAULT_PROXY_SETTINGS: dict[str, Any] = {
|
||||||
|
"forward_scheme": "http",
|
||||||
|
"certificate_id": 0,
|
||||||
|
"ssl_forced": True,
|
||||||
|
"block_exploits": True,
|
||||||
|
"allow_websocket_upgrade": True,
|
||||||
|
"access_list_id": 0,
|
||||||
|
"advanced_config": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Settings(BaseSettings):
|
class Settings(BaseSettings):
|
||||||
"""Application settings loaded from environment variables."""
|
"""Application settings loaded from environment variables."""
|
||||||
@@ -23,5 +37,30 @@ class Settings(BaseSettings):
|
|||||||
mcp_port: int = 8000
|
mcp_port: int = 8000
|
||||||
mcp_transport: str = "stdio" # "stdio" or "http"
|
mcp_transport: str = "stdio" # "stdio" or "http"
|
||||||
|
|
||||||
|
# Proxy host creation defaults (JSON string)
|
||||||
|
# Example: '{"certificate_id": 24, "ssl_forced": true}'
|
||||||
|
proxy_defaults: dict[str, Any] = {}
|
||||||
|
|
||||||
|
@field_validator("proxy_defaults", mode="before")
|
||||||
|
@classmethod
|
||||||
|
def parse_proxy_defaults(cls, v: Any) -> dict[str, Any]:
|
||||||
|
"""Parse JSON string to dict, or pass through if already dict."""
|
||||||
|
if isinstance(v, dict):
|
||||||
|
return v
|
||||||
|
if isinstance(v, str) and v.strip():
|
||||||
|
import json
|
||||||
|
|
||||||
|
try:
|
||||||
|
return json.loads(v)
|
||||||
|
except json.JSONDecodeError as e:
|
||||||
|
raise ValueError(f"Invalid JSON in NPM_PROXY_DEFAULTS: {e}") from e
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def get_proxy_defaults(self) -> dict[str, Any]:
|
||||||
|
"""Get merged proxy defaults (base defaults + user overrides)."""
|
||||||
|
merged = DEFAULT_PROXY_SETTINGS.copy()
|
||||||
|
merged.update(self.proxy_defaults)
|
||||||
|
return merged
|
||||||
|
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|||||||
@@ -291,13 +291,13 @@ async def create_proxy_host(
|
|||||||
domain_names: list[str],
|
domain_names: list[str],
|
||||||
forward_host: str,
|
forward_host: str,
|
||||||
forward_port: int,
|
forward_port: int,
|
||||||
forward_scheme: str = "http",
|
forward_scheme: str | None = None,
|
||||||
certificate_id: int = 0,
|
certificate_id: int | None = None,
|
||||||
ssl_forced: bool = True,
|
ssl_forced: bool | None = None,
|
||||||
block_exploits: bool = True,
|
block_exploits: bool | None = None,
|
||||||
allow_websocket_upgrade: bool = True,
|
allow_websocket_upgrade: bool | None = None,
|
||||||
access_list_id: int = 0,
|
access_list_id: int | None = None,
|
||||||
advanced_config: str = "",
|
advanced_config: str | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
"""Create a new proxy host in Nginx Proxy Manager.
|
"""Create a new proxy host in Nginx Proxy Manager.
|
||||||
|
|
||||||
@@ -305,18 +305,22 @@ async def create_proxy_host(
|
|||||||
domain_names: List of domain names (e.g., ["app.ext.ben.io"])
|
domain_names: List of domain names (e.g., ["app.ext.ben.io"])
|
||||||
forward_host: Backend host/IP to forward to (e.g., "192.168.1.100" or "container-name")
|
forward_host: Backend host/IP to forward to (e.g., "192.168.1.100" or "container-name")
|
||||||
forward_port: Backend port to forward to (e.g., 8080)
|
forward_port: Backend port to forward to (e.g., 8080)
|
||||||
forward_scheme: Backend protocol - "http" or "https" (default: "http")
|
forward_scheme: Backend protocol - "http" or "https" (default from config)
|
||||||
certificate_id: SSL certificate ID. Use list_certificates to find available certs.
|
certificate_id: SSL certificate ID. Use list_certificates to find available certs.
|
||||||
Use 0 for no SSL, or the ID of a matching wildcard cert.
|
Use 0 for no SSL, or the ID of a wildcard cert. (default from config)
|
||||||
ssl_forced: Force HTTPS redirect (default: True)
|
ssl_forced: Force HTTPS redirect (default from config)
|
||||||
block_exploits: Enable common exploit blocking (default: True)
|
block_exploits: Enable common exploit blocking (default from config)
|
||||||
allow_websocket_upgrade: Allow WebSocket connections (default: True)
|
allow_websocket_upgrade: Allow WebSocket connections (default from config)
|
||||||
access_list_id: Access list ID for authentication. Use list_access_lists to find.
|
access_list_id: Access list ID for authentication. Use list_access_lists to find.
|
||||||
Use 0 for no access restrictions (default: 0)
|
Use 0 for no access restrictions. (default from config)
|
||||||
advanced_config: Custom nginx configuration block (default: "")
|
advanced_config: Custom nginx configuration block (default from config)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
JSON with created proxy host details including the new host ID.
|
Details of the created proxy host including the new host ID.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
Default values can be configured via NPM_PROXY_DEFAULTS environment variable.
|
||||||
|
Example: NPM_PROXY_DEFAULTS='{"certificate_id": 24, "ssl_forced": true}'
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
create_proxy_host(
|
create_proxy_host(
|
||||||
@@ -324,22 +328,36 @@ async def create_proxy_host(
|
|||||||
forward_host="10.0.0.50",
|
forward_host="10.0.0.50",
|
||||||
forward_port=3000,
|
forward_port=3000,
|
||||||
certificate_id=24, # *.ext.ben.io wildcard
|
certificate_id=24, # *.ext.ben.io wildcard
|
||||||
ssl_forced=True
|
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
# Get defaults from config, then override with provided values
|
||||||
|
defaults = settings.get_proxy_defaults()
|
||||||
|
|
||||||
client = get_client()
|
client = get_client()
|
||||||
host = await client.create_proxy_host(
|
host = await client.create_proxy_host(
|
||||||
domain_names=domain_names,
|
domain_names=domain_names,
|
||||||
forward_host=forward_host,
|
forward_host=forward_host,
|
||||||
forward_port=forward_port,
|
forward_port=forward_port,
|
||||||
forward_scheme=forward_scheme,
|
forward_scheme=forward_scheme
|
||||||
certificate_id=certificate_id,
|
if forward_scheme is not None
|
||||||
ssl_forced=ssl_forced,
|
else defaults["forward_scheme"],
|
||||||
block_exploits=block_exploits,
|
certificate_id=certificate_id
|
||||||
allow_websocket_upgrade=allow_websocket_upgrade,
|
if certificate_id is not None
|
||||||
access_list_id=access_list_id,
|
else defaults["certificate_id"],
|
||||||
advanced_config=advanced_config,
|
ssl_forced=ssl_forced if ssl_forced is not None else defaults["ssl_forced"],
|
||||||
|
block_exploits=block_exploits
|
||||||
|
if block_exploits is not None
|
||||||
|
else defaults["block_exploits"],
|
||||||
|
allow_websocket_upgrade=allow_websocket_upgrade
|
||||||
|
if allow_websocket_upgrade is not None
|
||||||
|
else defaults["allow_websocket_upgrade"],
|
||||||
|
access_list_id=access_list_id
|
||||||
|
if access_list_id is not None
|
||||||
|
else defaults["access_list_id"],
|
||||||
|
advanced_config=advanced_config
|
||||||
|
if advanced_config is not None
|
||||||
|
else defaults["advanced_config"],
|
||||||
)
|
)
|
||||||
|
|
||||||
domains = ", ".join(host.domain_names)
|
domains = ", ".join(host.domain_names)
|
||||||
|
|||||||
Reference in New Issue
Block a user