About Snippets

Overview

The NGINX Controller Application Delivery (AD) module lets you configure NGINX directives that aren’t represented in the NGINX Controller API via “config snippets”, or “Snippets”. You can do so by using either the user interface (UI) or the Application Delivery REST API.

Caution:

When you use Snippets to customize your NGINX configuration, your changes are applied to the nginx.conf file as is. NGINX Controller does not verify that your configuration is valid before applying the snippet.

We strongly recommend verifying Snippets in a lab environment before making any changes in production.

Types of Snippets

There are five types of Snippets, which you can configure for gateways or components. This lets you add custom directives into the corresponding NGINX configuration blocks generated by the gateways and components for the associated URIs.

Note:
The uriSnippets can’t be used for TCP/UDP components.
Snippet Description Corresponding API Endpoint
httpSnippet Adds directives to the http block. Gateway
mainSnippet Adds directives to the main block. Gateway
streamSnippet Adds directives to the stream block. Gateway
uriSnippets Adds directives to the component’s server and location blocks. Component
uriSnippets Adds directives to the gateway’s server blocks. Gateway
workloadGroupSnippets Adds directives to the upstream blocks. Component

Best Practices

Gateway Partitions

It’s important to avoid adding conflicting snippets to the same context in your NGINX configuration file. We recommend that you create one stand-alone Gateway to hold the main, http, and stream snippets. Doing so lets you share the configuration for these contexts across Gateways that define the URIs (server blocks) for particular instances while reducing the risk of duplicate or conflicting settings.

NGINX Variables

NGINX configurations commonly use NGINX variables or custom variables. If you prefer to configure NGINX Controller by using the REST API, you may run into problems with variable expansion when sending JSON as part of a curl request using th -d flag. The recommended best practice for this is to reference the JSON in a data file instead of sending the string as part of the request. An alternative is to redefine the variable to itself, which allows the variable to pass through to the NGINX configuration. If you’re using the NGINX $host variable in your JSON data – represented by the <data> placeholder in the example below – you would define the variable before the curl request as follows:

host='$host' curl -s -k -H "Content-Type: application/json" -X PUT -d "<data>" https://192.168.100.10:80/

Usage Examples

Caution:
The examples provided here are intended for demonstration purposes only. We strongly recommend verifying Snippets in a lab environment before making any changes in production.

Add HTTP Strict Transport Security Headers

If you want to implement a HTTP Strict Transport Security (HSTS) policy, you can add a snippet to your gateway. For example:

{
    "metadata": {
        "name": "<gateway-name>"
    },
    "desiredState": {
        "configSnippets": {
            "uriSnippets": [
                {
                    "applicableUris": [
                        {
                            "uri": "http://172.16.0.238:81"
                        }
                    ],
                    "directives": [
                        {
                            "directive": "add_header",
                            "args": ["Strict-Transport-Security", "max-age=31536000; includeSubDomains", "always"] 
                        }
                    ]
                }
            ]
        },
        "ingress": {
            "uris": {
                "http://example.com:8020": {}
            },
            "placement":  {
                "instanceRefs": [
                    {
                        "ref": "/infrastructure/locations/unspecified/instances/<instance-name>"
                    }
                ]
            }
        }
    }
}

Allow or Deny IP Addresses

You can add IP addresses to your allow- or deny-list by using the allow or deny directives in a gateway snippet. For example:

{
    "metadata": {
        "name": "<gateway-name>"
    },
    "desiredState": {
        "configSnippets": {
            "uriSnippets": [
                {
                    "applicableUris": [
                        {
                            "uri": "<gateway URI>"
                        }
                    ],
                    "directives": [
                        {
                            "directive": "deny",
                            "args": ["192.0.2.2"] 
                        },
                        {
                            "directive": "allow",
                            "args": ["192.0.2.1/24"] 
                        },    
                                                {
                            "directive": "allow",
                            "args": ["2001:0db8::/32"] 
                        },    
                                                {
                            "directive": "deny",
                            "args": ["all"] 
                        }          
                    ]
                }
            ]
        },
        "ingress": {
            "uris": {
                "http://example.com:8020": {}
            },
            "placement":  {
                "instanceRefs": [
                    {
                        "ref": "/infrastructure/locations/unspecified/instances/<instance-name>"
                    }
                ]
            }
        }
    }
}

Load the NGINX Prometheus Module

In order to use the [NGINX Prometheus-njs]https://docs.nginx.com/nginx/admin-guide/dynamic-modules/prometheus-njs/) module with NGINX Controller, you need to use load_module in the main context, js_import in the http context, and js_content in the location. NGINX Controller automatically enables the location api location /api, which is also required for metrics reporting.

After installing the module, add the following Snippets to your gateway. This will add load_module and js_import:

{
    "metadata": {
        "name": "<gateway-name>"
    },
    "desiredState": {
        "configSnippets": {
            "mainSnippet": {
                "directives": [
                    {
                        "directive": "load_module",
                        "args": ["modules/ngx_http_js_module.so"]
                    }
                ]
            },
                "httpSnippet":{
                "directives": [
                    {
                        "directive": "js_import",
                        "args": ["/usr/share/nginx-plus-module-prometheus/prometheus.js"]
                    }
                ]
            }
        },
        "ingress": {
            "uris": {
                "http://example.com:8020": {}
            },
            "placement":  {
                "instanceRefs": [
                    {
                        "ref": "/infrastructure/locations/unspecified/instances/<instance-name>"
                    }
                ]
            }
        }
    }
}

Then, you’d add a config snippet similar to the example below to your component.

{
    "metadata": {
        "name": "<gateway-name>"
    },
    "desiredState": {
        "configSnippets": {
            "uriSnippets": [
                {
                    "applicableUris": [
                        {
                            "uri": "/metrics"
                        }
                    ],
                    "directives": [
                        {
                            "directive":"js_content",
                            "args": ["prometheus.metrics"]
                        }
                    ]
                }
            ]
        },
        "ingress": {
            "uris": {
                "http://example.com:8020": {}
            },
            "placement":  {
                "instanceRefs": [
                    {
                        "ref": "/infrastructure/locations/unspecified/instances/<instance-name>"
                    }
                ]
            }
        }
    }
}

NGINX as a WebSocket Proxy

If you want to use NGINX Controller to configure NGINX as a WebSocket Proxy, you can customize your nginx.conf by using Snippets and header programmability.

In the gateway, provide an http snippet that defines the map directive and the server configuration:

{
    "metadata": {
        "name": "<gateway-name>"
    },
    "desiredState": {
        "configSnippets": {
            "httpSnippet": {
                "directives": [
                    {
                        "directive": "map",
                        "args": ["$http_upgrade", "$connection_upgrade"],
                        "block": [
                            {
                                "directive": "default",
                                "args": ["upgrade"]
                            },
                            {
                                "directive": "''",
                                "args": ["close"]
                            }
                        ]
                    }
                ]
            }
        },
        "ingress": {
            "uris": {
                "http://example.com:8020": {}
            },
            "placement":  {
                "instanceRefs": [
                    {
                        "ref": "/infrastructure/locations/unspecified/instances/<instance-name>"
                    }
                ]
            }
        }
    }
}

Then, add the two required headers to the component using requestHeaderModifications. For example:

{
    "metadata": {
        "name": "<component-name>",
    },
    "desiredState": {
        "ingress": {
            "uris": {
                "/": {}
            },
            "gatewayRefs": [
                {"ref": "/services/environments/${env}/gateways/<gateway-name>"}
            ]
        },
        "programmability": {
            "requestHeaderModifications": [
                {
                    "action": "ADD",
                    "headerName": "Upgrade",
                    "headerValue": "$http_upgrade"
                },
                {
                    "action": "ADD",
                    "headerName": "Connection",
                    "headerValue": "$connection_upgrade"
                }
            ]
        },
        "backend": {
            "workloadGroups": {
                "websocket": {
                    "uris": {
                        "http://<data-host-name>:8010": {}
                    }
                }
            }
        }
    }
}

Forward Errors Logs to Remote Syslog

If you want to forward HTML error logs to syslog, you can add the error_log directive snippet to your gateway. For example:

{
    "metadata": {
        "name": "<gateway-name>"
    },
    "desiredState": {
        "configSnippets": {
            "httpSnippet": {
                "directives": [
                    {
                        "directive": "error_log",
                        "args": ["syslog:server=<data-host-name>", "debug"]
                    }
                ]
            }
        },
        "ingress": {
            "uris": {
                "http://example.com:8000": {}
            },
            "placement":  {
                "instanceRefs": [
                    {
                        "ref": "/infrastructure/locations/unspecified/instances/<instance-name>"
                    }
                ]
            }
        }
    }
}
Note:
The error_log and accesslog directives can appear at various block levels (main, http, stream, server, location, etc.). NGINX Controller adds these directives to control logging to the local file. When using Snippets to add additional logging capabilities, the inner blocks override the outer block definitions. For example, if you enable remote logging for errors at the main level, and you add an error_log directive to a server or location block that uses local logging, the local logging configuration overrides the remote logging configured at the main level.

Extend App Security with Snippets

When adding NGINX Controller App Security to your components, you can use Snippets to add NGINX App Protect directives that aren’t represented in the NGINX Controller API. You can also use Snippets to tune your NGINX App Protect WAF performance.

Refer to Extend App Security with Snippets for more information and examples.


This documentation applies to the following versions of NGINX Controller App Delivery module: 3.22, 3.22.1 and 3.22.2.