CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-certbot-nginx

Nginx plugin for Certbot that enables automated SSL/TLS certificate management and deployment for Nginx web servers.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

nginxparser.mddocs/

Low-level Configuration Parser

Low-level nginx configuration parser based on pyparsing that handles the complete nginx configuration syntax. Provides parsing, modification, and serialization capabilities for nginx configuration files.

Capabilities

Raw Configuration Parsing

Parse nginx configuration files into structured data with complete syntax support.

class RawNginxParser:
    """Raw nginx configuration parser using pyparsing.
    
    Args:
        source: Nginx configuration source string
        
    Attributes:
        source: str - Configuration source content
    """
    
    def __init__(self, source: str) -> None:
        """Initialize parser with configuration source."""
    
    def parse(self) -> ParseResults:
        """Parse nginx configuration.
        
        Returns:
            Parsed configuration tree as ParseResults
        """
    
    def as_list(self) -> list[Any]:
        """Convert parsed tree to list representation.
        
        Returns:
            Parsed tree as nested list structure
        """

Configuration Serialization

Convert parsed configuration back to nginx configuration format.

class RawNginxDumper:
    """Dumps nginx configuration from parsed tree.
    
    Args:
        blocks: Parsed configuration blocks
        
    Attributes:
        blocks: list[Any] - Configuration blocks to dump
    """
    
    def __init__(self, blocks: list[Any]) -> None:
        """Initialize dumper with configuration blocks."""
    
    def __iter__(self, blocks: Optional[list[Any]] = None) -> Iterator[str]:
        """Iterate over dumped nginx content.
        
        Args:
            blocks: Optional blocks to iterate (uses self.blocks if None)
            
        Yields:
            Configuration content strings
        """
    
    def __str__(self) -> str:
        """Convert parsed blocks to nginx configuration string.
        
        Returns:
            Complete nginx configuration as string
        """

Whitespace-Aware List Handling

Special list implementation that manages whitespace in nginx configuration.

class UnspacedList(list[Any]):
    """List wrapper that makes whitespace entries invisible.
    
    Maintains both spaced and unspaced representations of configuration
    data while preserving original formatting and structure.
    
    Args:
        list_source: Source list or iterable to wrap
        
    Attributes:
        spaced: list[Any] - Original list with whitespace preserved
        dirty: bool - Whether list has been modified
    """
    
    def __init__(self, list_source: Iterable[Any]) -> None:
        """Initialize with source list, removing whitespace from main list."""

List Modification Operations

Modified list operations that maintain whitespace structure.

def insert(self, i: SupportsIndex, x: Any) -> None:
    """Insert object before index.
    
    Args:
        i: Index position for insertion
        x: Object to insert
    """

def append(self, x: Any) -> None:
    """Append object to end of list.
    
    Args:
        x: Object to append
    """

def extend(self, x: Any) -> None:
    """Extend list by appending elements from iterable.
    
    Args:
        x: Iterable to extend with
    """

def __add__(self, other: list[Any]) -> "UnspacedList":
    """Add lists together.
    
    Args:
        other: List to add
        
    Returns:
        New UnspacedList with combined contents
    """

High-Level Parser Functions

Convenience functions for parsing and dumping nginx configurations.

def load(file_: IO[Any]) -> UnspacedList:
    """Parse nginx configuration from file object.
    
    Args:
        file_: File-like object to parse from
        
    Returns:
        Parsed configuration as UnspacedList
        
    Raises:
        ParseException: If configuration syntax is invalid
    """

def loads(source: str) -> UnspacedList:
    """Parse nginx configuration from string.
    
    Args:
        source: Configuration string
        
    Returns:
        Parsed configuration as UnspacedList
        
    Raises:
        ParseException: If configuration syntax is invalid
    """

def dump(parsed_obj: UnspacedList, output: IO[str]) -> None:
    """Write parsed configuration to file.
    
    Args:
        parsed_obj: Parsed configuration object
        output: File-like object for output
    """

def dumps(parsed_obj: UnspacedList) -> str:
    """Convert parsed configuration to string.
    
    Args:
        parsed_obj: Parsed configuration object
        
    Returns:
        Configuration as nginx format string
    """

Utility Functions

Helper functions for working with configuration elements.

def spacey(x: Any) -> bool:
    """Check if x is empty string or whitespace.
    
    Args:
        x: Object to check
        
    Returns:
        True if x is whitespace or empty string
    """

Internal Implementation Details

The parser uses pyparsing to define nginx configuration grammar:

# Grammar components (read-only attributes)
space: Optional[White]           # Optional whitespace
required_space: White           # Required whitespace  
left_bracket: Literal          # Opening brace
right_bracket: Literal         # Closing brace with space
semicolon: Literal            # Semicolon
dquoted: QuotedString         # Double-quoted strings
squoted: QuotedString         # Single-quoted strings
quoted: Union                 # Any quoted string
token: Union                  # Configuration tokens
assignment: ParseElement      # Directive assignments
comment: ParseElement         # Comment lines
block: Forward               # Configuration blocks
contents: Group              # Block contents
script: ZeroOrMore           # Complete configuration

Usage Examples

Basic Configuration Parsing

from certbot_nginx._internal import nginxparser

# Parse configuration from file
with open('/etc/nginx/nginx.conf', 'r') as f:
    config = nginxparser.load(f)
print(f"Parsed {len(config)} top-level blocks")

# Parse configuration from string
config_str = """
server {
    listen 80;
    server_name example.com;
    location / {
        return 200 "Hello World";
    }
}
"""
parsed = nginxparser.loads(config_str)
print(f"Parsed: {parsed}")

Configuration Modification

# Load and modify configuration
with open('/etc/nginx/sites-available/default', 'r') as f:
    config = nginxparser.load(f)

# Find server block
for block in config:
    if isinstance(block, list) and block[0] == ['server']:
        server_block = block[1]
        
        # Add new directive
        new_directive = ['listen', '443', 'ssl']
        server_block.append(new_directive)
        
        # Add SSL certificate directives
        ssl_cert = ['ssl_certificate', '/path/to/cert.pem']
        ssl_key = ['ssl_certificate_key', '/path/to/key.pem']  
        server_block.extend([ssl_cert, ssl_key])

# Write back to file
with open('/etc/nginx/sites-available/default', 'w') as f:
    nginxparser.dump(config, f)

Working with UnspacedList

from certbot_nginx._internal.nginxparser import UnspacedList

# Create UnspacedList from regular list
original = ['  ', 'server', ' ', '{', '\n', '    ', 'listen', ' ', '80', ';', '\n', '}']
unspaced = UnspacedList(original)

print(f"Original length: {len(original)}")      # Shows all elements including whitespace
print(f"Unspaced length: {len(unspaced)}")      # Shows only non-whitespace elements
print(f"Unspaced content: {unspaced}")          # ['server', '{', 'listen', '80', ';', '}']

# Modifications maintain spacing
unspaced.append(['server_name', 'example.com'])
print(f"Modified: {unspaced}")

# Access original spaced version
print(f"Spaced version: {unspaced.spaced}")

Advanced Parsing with Error Handling

import pyparsing

try:
    with open('/etc/nginx/nginx.conf', 'r') as f:
        config = nginxparser.load(f)
    
    # Process configuration blocks
    for block in config:
        if isinstance(block, list) and len(block) >= 2:
            if block[0] == ['http']:
                print("Found HTTP block")
                http_contents = block[1]
                
                # Look for server blocks within HTTP
                for item in http_contents:
                    if isinstance(item, list) and item[0] == ['server']:
                        print(f"Found server block with {len(item[1])} directives")
                        
except FileNotFoundError:
    print("Configuration file not found")
except pyparsing.ParseException as e:
    print(f"Parse error: {e}")
except Exception as e:
    print(f"Error processing configuration: {e}")

Configuration Generation

# Build configuration programmatically
config = UnspacedList([])

# Create server block
server_block = UnspacedList([
    ['listen', '80'],
    ['server_name', 'example.com'],
    ['location', '/', [
        ['return', '200', '"Hello World"']
    ]]
])

# Add to main configuration
config.append(['server', server_block])

# Convert to string
config_str = nginxparser.dumps(config)
print(config_str)

This produces nginx configuration like:

server {
    listen 80;
    server_name example.com;
    location / {
        return 200 "Hello World";
    }
}

Install with Tessl CLI

npx tessl i tessl/pypi-certbot-nginx

docs

configurator.md

constants.md

display-ops.md

http-01.md

index.md

nginxparser.md

objects.md

parser.md

tile.json