Caddy NGINX Config Adapter

repository·master·Indexed 43 days ago

https://github.com/caddyserver/nginx-adapter

A Caddy config adapter that converts NGINX configuration files into Caddy's native JSON configuration format. It allows users to migrate NGINX configs or run Caddy directly using an NGINX config file via the `--adapter nginx` flag. The adapter supports a subset of NGINX directives across main, http, server, if, upstream, and location contexts, including mapping NGINX selection policies (random, least_conn, ip_hash, hash) to Caddy's reverseproxy module.

Tokens
2.4K
Snippets
8
Records
12
Agent score
56%

What's inside Caddy NGINX Adapter

  1. Install the Caddy NGINX Config Adapter

    master

    To use this adapter, you must build a custom version of Caddy using xcaddy with the nginx-adapter module included.

    Before building, ensure your GOROOT and GOPATH environment variables are correctly configured for your environment.

    $ xcaddy build --with github.com/caddyserver/nginx-adapter
  2. Use the NGINX Config Adapter with Caddy

    master

    You can use the adapter to convert NGINX configuration files into Caddy's native format. There are two primary ways to use it:

    1. Adapt the configuration: Use the caddy adapt command to preview the converted Caddy configuration.
    2. Run Caddy directly: You can run Caddy using an NGINX config file by specifying the --config flag and the --adapter nginx flag.

    Warning: Because this project is currently incomplete, using the adapter to run Caddy directly may result in warnings for unsupported directives. Use with caution.

    caddy run --config nginx.conf --adapter nginx
  3. Generate NGINX directive context files

    master

    The nginx-dirs.go tool parses the NGINX documentation XML files to restructure them. Instead of grouping directives by module, it groups them by context. This produces a set of text files named after each context, each containing an exhaustive list of directives allowed within that specific context. These files are used as a reference to ensure the adapter's coverage is complete.

    # 1. Clone the NGINX source repository
    git clone https://hg.nginx.org/nginx.org
    
    # 2. Run the generator pointing to the cloned directory
    go run nginx-dirs.go <path_to_cloned_nginx_repo>
  4. Map NGINX selection policies to Caddy

    master

    The adapter translates specific NGINX upstream directives into Caddy reverseproxy selection policies using the following mapping:

    NGINX DirectiveCaddy Policy Name
    randomrandom_choose
    least_connleast_conn
    ip_haship_hash
    hashheader

    Selection Logic Details

    • ip_hash: Uses reverseproxy.IPHashSelection{}.
    • random: Uses reverseproxy.RandomChoiceSelection{}.
    • least_conn: Uses reverseproxy.LeastConnSelection{}.
    • hash: Uses reverseproxy.HeaderHashSelection{} and requires a parameter specifying the header field to hash on.
  5. Supported NGINX directives in the adapter

    master

    The adapter currently supports a subset of NGINX directives organized by their context. Note that support is incomplete and being actively developed.

    main context

    • http

    http context

    • server
    • index
    • upstream

    server context

    • listen
    • server_name
    • location
    • root
    • index
    • access_log
    • rewrite
    • if

    if context

    • break
    • return
    • rewrite
    • set

    upstream context

    • server
    • hash
    • ip_hash
    • keepalive
    • keepalive_requests
    • keepalive_timeout
    • ntlm
    • least_conn
    • random

    location context

    • location
    • if
    • root
    • add_header
    • deny
    • allow
    • rewrite
    • fastcgi_pass
    • proxy_pass
    • expires
    • return

    if (inside location) context

    • root
    • gzip
    • add_header
    • expires
    • proxy_pass
  6. Use the NGINX Adapter to convert configs

    master

    The nginxconf.Adapter implements the caddyconfig.Adapter interface, allowing Caddy to ingest NGINX configuration files directly. It converts NGINX directives into Caddy's JSON configuration format.

    To use the adapter, call the Adapt method. You can optionally provide a filename in the options map to ensure that any warnings generated include the correct file path for debugging.

    import (
    	"github.com/caddyserver/caddyserver/nginx-adapter/nginxconf"
    )
    
    // ...
    
    adapter := nginxconf.Adapter{}
    // body is the []byte content of the nginx.conf
    // options can include "filename" to provide context for warnings
    options := map[string]interface{}{
    	"filename": "/etc/nginx/nginx.conf",
    }
    
    caddyJSON, warnings, err := adapter.Adapt(body, options)
    if err != nil {
    	// handle error
    }
    // caddyJSON is now ready to be used as Caddy configuration
  7. Adapt the NGINX Adapter

    master

    The Adapt method converts NGINX configuration bytes into Caddy JSON bytes. It parses the NGINX directives and maps them to Caddy's http application structure.

    Parameters:

    • body []byte: The raw content of the NGINX configuration file.
    • options map[string]interface{}: An optional map. If it contains a key "filename" (type string), the adapter will use that filename (resolved to an absolute path) to provide context in any returned warnings.

    Returns:

    • []byte: The resulting Caddy JSON configuration.
    • []caddyconfig.Warning: A list of warnings encountered during adaptation (e.g., unrecognized directives).
    • error: An error if the parsing or conversion process fails.
    func (Adapter) Adapt(body []byte, options map[string]interface{}) ([]byte, []caddyconfig.Warning, error)
  8. Configure Upstream Servers and Unix Sockets

    master

    The server directive defines the backend addresses. The adapter supports both TCP and UNIX domain sockets:

    • TCP: Standard host:port or domain name format.
    • UNIX Sockets: Use the unix: prefix (e.g., unix:/path/to/socket.sock).
    • Weight: You can specify a weight using the weight=<integer> parameter (e.g., server 127.0.0.1:8080 weight=5). Note that in the current implementation, weight is mapped to MaxRequests on the upstream object.
  9. Configure Upstream Keep-Alive settings

    master

    The adapter supports several NGINX directives to configure connection persistence within an upstream block:

    • keepalive <count>: Sets the MaxIdleConns in the Caddy KeepAlive configuration.
    • keepalive_requests <count>: Sets the MaxIdleConnsPerHost in the Caddy KeepAlive configuration.
    • keepalive_timeout <duration>: Sets the IdleConnTimeout using standard Go duration strings (e.g., 15s, 1m).
  10. Reference NGINX unsupported directives and errors

    master

    The adapter defines specific error messages for unsupported NGINX features. If these are encountered, the adaptation may fail or return warnings.

    • ErrUnrecognized: "unrecognized or unsupported nginx directive"
    • ErrNamedLocation: "named locations marked by @ are unnsupported"
    • ErrExpiresAtTime: "usage of expires @time is not supported"
    const (
    	ErrUnrecognized  = "unrecognized or unsupported nginx directive"
    	ErrNamedLocation = "named locations marked by @ are unnsupported"
    	ErrExpiresAtTime = "usage of `expires @time` is not supported"
    )
  11. The Upstream type for NGINX configuration

    master

    The Upstream struct is used to map NGINX upstream block configurations into Caddy's reverseproxy module structures. It encapsulates the pool of servers, selection policies (load balancing), NTLM support, and keep-alive settings.

    Fields

    • Servers: A reverseproxy.UpstreamPool containing the individual upstream server definitions.
    • NTLM: A boolean indicating if NTLM authentication is enabled.
    • SelectionPolicy: A struct defining how requests are distributed among servers:
      • Name: The name of the Caddy selection policy (mapped from NGINX policy names).
      • Selector: A reverseproxy.Selector implementation (e.g., IPHashSelection, RandomChoiceSelection).
    • KeepAlive: A pointer to a reverseproxy.KeepAlive configuration for managing idle connections.
    type Upstream struct {
    	Servers         reverseproxy.UpstreamPool
    	NTLM            bool
    	SelectionPolicy struct {
    		Name     string
    		Selector reverseproxy.Selector
    	}
    	KeepAlive *reverseproxy.KeepAlive
    }
  12. Use the Directive type to navigate NGINX configurations

    master

    The Directive type is the primary abstraction for representing an NGINX configuration directive. It captures the directive's name, its arguments, any nested blocks, and its location in the source file.

    Fields

    • Params []string: A slice containing the directive name followed by its arguments. Note: Params[0] is always the directive name.
    • Block []Directive: A slice of nested Directive objects if the directive contains a block (e.g., server { ... }).
    • File string: The filename where the directive was defined.
    • Line int: The line number in the source file.

    Methods

    • Name() string: Returns the directive name (the first element in Params).
    • Param(idx int) string: Returns the parameter at the specified index. If the index is out of bounds, it returns an empty string "".
    // Example of accessing a directive's properties
    dir := Directive{
        Params: []string{"listen", "80"},
        File:   "nginx.conf",
        Line:   10,
    }
    
    name := dir.Name()          // "listen"
    arg := dir.Param(1)         // "80"