Nginx plugin for Certbot that enables automated SSL/TLS certificate management and deployment for Nginx web servers.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The NginxParser class handles the fine details of parsing and modifying nginx configuration files. It provides high-level operations for working with nginx server blocks, directives, and included files while maintaining the structure and formatting of configuration files.
Initialize the parser and load nginx configuration files into a parsed tree structure.
class NginxParser:
"""Class handles parsing nginx configuration files.
Args:
root: Absolute path to server root directory
Attributes:
parsed: dict[str, UnspacedList] - Mapping of file paths to parsed trees
root: str - Normalized absolute path to server root
config_root: str - Configuration root directory
"""
def __init__(self, root: str) -> None:
"""Initialize parser with server root directory."""
def load(self) -> None:
"""Load nginx files into parsed tree.
Parses nginx.conf and all included files recursively.
"""
@property
def http_path(self) -> str:
"""Path to file containing nginx http block.
Returns:
Filepath of file with http block
Raises:
errors.MisconfigurationError: No nginx http block found
"""Extract and manage virtual host information from nginx configuration.
def get_vhosts(self) -> list[VirtualHost]:
"""Get list of all virtual hosts found in nginx configuration.
Returns:
List of VirtualHost objects found in configuration
"""
def duplicate_vhost(self, vhost: VirtualHost,
remove_singleton_listen_params: bool = False,
only_directives: Optional[list[str]] = None) -> VirtualHost:
"""Duplicate a virtual host with optional filtering.
Args:
vhost: Virtual host to duplicate
remove_singleton_listen_params: Remove singleton listen parameters
only_directives: Only duplicate these directives if specified
Returns:
New duplicated VirtualHost object
"""Handle file paths and configuration structure navigation.
def abs_path(self, path: str) -> str:
"""Convert relative path to absolute path relative to root.
Args:
path: The path to convert
Returns:
Absolute path
"""Add, update, and remove directives from nginx server blocks.
def add_server_directives(self, vhost: VirtualHost, directives: list[list[str]],
insert_at_top: bool = False) -> None:
"""Add directives to server block.
Args:
vhost: Virtual host to modify
directives: List of directive lists to add
insert_at_top: Insert at top of server block if True
Raises:
errors.MisconfigurationError: Problem adding directives
"""
def update_or_add_server_directives(self, vhost: VirtualHost,
directives: list[list[str]]) -> None:
"""Update existing directives or add new ones.
Args:
vhost: Virtual host to modify
directives: List of directive lists to update/add
Raises:
errors.MisconfigurationError: Problem updating directives
"""
def remove_server_directives(self, vhost: VirtualHost, directive: str,
match_func: Optional[Callable[[Any], bool]] = None) -> None:
"""Remove server directives matching criteria.
Args:
vhost: Virtual host to modify
directive: Name of directive to remove
match_func: Optional function to match specific directives
Raises:
errors.MisconfigurationError: Problem removing directives
"""
def parse_server(self, server: UnspacedList) -> dict[str, Any]:
"""Parse server block directives and extract configuration.
Args:
server: Parsed server block as UnspacedList
Returns:
Dictionary containing parsed server configuration with keys:
- addrs: List of addresses the server listens on
- ssl: Boolean indicating if SSL is enabled
- names: Set of server names
Raises:
errors.MisconfigurationError: Invalid server block structure
"""Detect SSL-related configuration in virtual hosts.
def has_ssl_on_directive(self, vhost: VirtualHost) -> bool:
"""Check if virtual host has 'ssl on' directive.
Args:
vhost: Virtual host to check
Returns:
True if 'ssl on' directive is present
"""Write parsed configuration back to files with proper formatting.
def filedump(self, ext: str = 'tmp', lazy: bool = True) -> None:
"""Write parsed configuration back to files.
Args:
ext: File extension to use ('tmp' for temporary files, '' for original files)
lazy: Only dump files that have been modified if True
"""def _parse_recursively(self, filepath: str) -> None:
"""Parse nginx config files recursively by following include directives."""
def _parse_files(self, filepath: str) -> dict[str, UnspacedList]:
"""Parse files matching glob pattern."""
def _build_addr_to_ssl(self) -> dict[tuple[str, str], bool]:
"""Build map from address to SSL status."""
def _get_raw_servers(self) -> dict[str, Union[list[Any], UnspacedList]]:
"""Get map of unparsed server blocks."""
def _update_vhosts_addrs_ssl(self, vhosts: Iterable[VirtualHost]) -> None:
"""Update vhost addresses with global SSL status."""
def _get_included_directives(self, block: UnspacedList) -> UnspacedList:
"""Expand include directives by concatenating included file contents."""def get_best_match(target_name: str, names: Iterable[str]) -> tuple[Optional[str], Optional[str]]:
"""Get best matching server name for target.
Args:
target_name: Target domain name
names: Set of server names to match against
Returns:
Tuple of (match_type, matched_name) where match_type indicates
the type of match found and matched_name is the matching server name,
or (None, None) if no match is found
"""
def comment_directive(block: UnspacedList, index: int) -> None:
"""Comment out directive at specified index.
Args:
block: Configuration block
index: Index of directive to comment
"""from certbot_nginx._internal.parser import NginxParser
# Initialize parser
parser = NginxParser('/etc/nginx')
# Load configuration files
parser.load()
# Get all virtual hosts
vhosts = parser.get_vhosts()
print(f"Found {len(vhosts)} virtual hosts")
# Show virtual host details
for vhost in vhosts:
print(f"File: {vhost.filep}")
print(f"Names: {vhost.names}")
print(f"SSL: {vhost.ssl}")
print(f"Addresses: {[str(addr) for addr in vhost.addrs]}")# Select a virtual host
vhost = vhosts[0]
# Add SSL certificate directives
ssl_directives = [
['\n ', 'ssl_certificate', ' ', '/path/to/cert.pem'],
['\n ', 'ssl_certificate_key', ' ', '/path/to/key.pem']
]
parser.add_server_directives(vhost, ssl_directives)
# Write changes back to files
parser.filedump()# Duplicate a virtual host for SSL configuration
original_vhost = vhosts[0]
ssl_vhost = parser.duplicate_vhost(original_vhost)
# Add SSL-specific directives to the duplicate
ssl_config = [
['\n ', 'listen', ' ', '443', ' ', 'ssl'],
['\n ', 'ssl_certificate', ' ', '/path/to/cert.pem'],
['\n ', 'ssl_certificate_key', ' ', '/path/to/key.pem']
]
parser.add_server_directives(ssl_vhost, ssl_config)for vhost in vhosts:
has_ssl_on = parser.has_ssl_on_directive(vhost)
print(f"VHost {vhost.filep} has 'ssl on': {has_ssl_on}")Install with Tessl CLI
npx tessl i tessl/pypi-certbot-nginx