End of Sale Notice:
F5 NGINX is announcing the End of Sale (EoS) for NGINX Controller API Management Module, effective January 1, 2024.
F5 maintains generous lifecycle policies that allow customers to continue support and receive product updates. Existing NGINX Controller API- Management customers can continue to use the product past the EoS date. License renewals are not available after September 30, 2024.
See our End of Sale announcement for more details.
End of Sale Notice:
F5 NGINX is announcing the End of Sale (EoS) for NGINX Controller Application Delivery Module, effective January 1, 2024.
F5 maintains generous lifecycle policies that allow customers to continue support and receive product updates. Existing NGINX Controller Application Delivery customers can continue to use the product past the EoS date. License renewals are not available after September 30, 2024.
See our End of Sale announcement for more details.
About Snippets
Overview
The F5 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:
TheuriSnippets
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 module with NGINX Controller, you need to useload_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:
Theerror_log
andaccesslog
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 themain
level, and you add anerror_log
directive to aserver
orlocation
block that uses local logging, the local logging configuration overrides the remote logging configured at themain
level.
Manage IPv6 Addresses
You can use Snippets to manage IPv6 addresses for HTTP and TCP/UDP use cases. IPv6 address management is supported in both Gateway and Component Snippets.
- Be sure to set the
reuseport
option for all IPv6 listen directives. Failure to do so can cause bind errors. - NGINX Controller’s post-processing logic removes the
reuseport
option in certain cases. This is a known issue when the IPv6 port matches an IPv4 port and the IPv4 listen directive does not specify an IP address (in other words, a wildcard IP). To change the IPv6 listen directive’s IP address, remove the Snippet, then re-add the Snippet with a new IPv6 address.
If you need to support IPv6 addresses for the NGINX listen directive, you can use a snippet similar to the ones shown below to achieve it.
HTTP Gateway with IPv6
For HTTP, use the Gateway URI Snippets block to add an IPv6 listen
directive to the server
blocks.
{
"metadata": {
"name": "<gateway-name>"
},
"desiredState": {
"configSnippets": {
"uriSnippets": [
{
"directives": [
{
"directive": "listen",
"args": [
"[::]:80",
"reuseport"
]
},
{
"directive": "listen",
"args": [
"[<IPv6-address>]:80",
"reuseport"
]
}
]
}
]
},
"ingress": {
"placement": {
"instanceRefs": [
{
"ref": "/infrastructure/locations/unspecified/instances/<instance-name>"
}
]
},
"uris": {
"http://example.com:80": {}
}
}
}
}
Note:
You cannot add IPv6listen
directives to a server block when the FQDN is defined in the Component URI (for example,http://{FQDN}/{PATH}
).
TCP/UDP Component with IPv6
For TCP/UDP, use the Component URI Snippets block to add an IPv6 listen
directive to the server
blocks.
TCP Component
{
"metadata": {
"name": "<component-name>"
},
"desiredState": {
"configSnippets": {
"uriSnippets": [
{
"directives": [
{
"directive": "listen",
"args": [
"[::]:9090",
"reuseport"
]
}
]
}
]
},
"backend": {
"workloadGroups": {
"wg": {
"uris": {
"tcp://<workload-host>:9090": {}
},
}
}
},
"componentType": "TCPUDP",
"ingress": {
"gatewayRefs": [
{
"ref": "/services/environments/<env-name>/gateways/<gateway-name>"
}
],
"uris": {
"tcp://*:9090": {}
}
}
}
}
UDP Component
{
"metadata": {
"name": "<component-name>"
},
"desiredState": {
"configSnippets": {
"uriSnippets": [
{
"directives": [
{
"directive": "listen",
"args": [
"[<IPv6-Address>]:9053",
"udp",
"reuseport"
]
}
]
}
]
},
"backend": {
"workloadGroups": {
"wg": {
"uris": {
"udp://<workload-host>:9053": {}
}
}
}
},
"componentType": "TCPUDP",
"ingress": {
"gatewayRefs": [
{
"ref": "/services/environments/<env-name>/gateways/<gateway-name>"
}
],
"uris": {
"udp://*:9053": {}
}
}
}
}
IPv6-only Server Block
To add an IPv6-only server
block, define the entire block in the Gateway HTTP or the Stream Snippets block.
UI Config
Add listen
directives with parameters in URI Snippets. To learn more about what the listen
directive does and what parameters it accepts, refer to the following topics:
Note:
Thereuseport
parameter creates an individual listening socket for each worker process. Seereuseport
option.
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.