Submit templates
This guide explains how to submit templates to render and deploy NGINX configurations, and how to manage existing submissions using the Templates API.
Before submitting templates, you need to import them into NGINX One Console.
- See the Import Templates Guide for instructions on creating and importing templates.
- For guidance on writing templates, see the Template Authoring Guide.
Template submission allows you to compose templates that generate a complete NGINX configuration and deploy it to a target. The process involves:
- Discovering templates - Find base and augment templates that match your infrastructure needs
- Understanding capabilities - Review what contexts and features the base template supports
- Selecting augments - Choose augments for additional features (CORS, rate limiting, SSL, etc.)
- Providing values - Supply values for all template variables
- Submit - Submit the composed request to render the NGINX configuration and create a staged config
To review the rendered configuration before committing, use preview mode with preview_only=true. See Save rendered config as staged config for the preview-first workflow.
Before creating a submission, find base and augment templates that match your infrastructure needs.
Use the List Templates API operation to find templates organized by use case.
Example response:
{
"count": 3,
"items": [
{
"allowed_in_contexts": [
"http/server/location"
],
"augment_includes": [],
"created_at": "2025-09-25T18:22:18.149122Z",
"description": "",
"name": "cors-headers",
"object_id": "tmpl_AFVNBQcoRDeV9jk9panxbw",
"type": "augment"
},
{
"allowed_in_contexts": [
"http/server"
],
"augment_includes": [],
"created_at": "2025-09-25T19:13:07.977943Z",
"description": "",
"name": "health-check",
"object_id": "tmpl_rT6Ul8RvQtSZPkNfsIExPQ",
"type": "augment"
},
{
"allowed_in_contexts": [],
"augment_includes": [
"http",
"http/server",
"http/server/location"
],
"created_at": "2025-09-25T19:20:47.473955Z",
"description": "",
"name": "reverse-proxy-base",
"object_id": "tmpl_0rQSkSNSTamthLQVtSZb1g",
"type": "base"
}
],
"items_per_page": 100,
"start_index": 1,
"total": 3
}Use Case Identification:
- Base templates represent primary NGINX use cases (reverse proxy, load balancer, static site, API gateway)
- Template descriptions help identify which base template matches your infrastructure need
- augment_includes shows what additional features each base template supports
Information Available In API Response:
- object_id - A unique identifier of a template to use in submission requests
- type - Identifies base templates (use exactly one) vs augment templates (use zero or more)
- allowed_in_contexts - Shows where augment templates can be applied within a base template
- augment_includes - Shows which contexts the base template supports for augments
- is_f5_default - When
true, the template is provided by F5 and is immutable. These templates are also identified in the NGINX One Console by the F5 logo icon in the templates list.
The API response contains all information needed for creating a submission to render NGINX configurations. You need template details only if you want to examine the actual template content or variable requirements.
Use the Retrieve a Template API operation only when you need to examine template content or detailed variable requirements.
When to use template details:
- Review the actual template code and structure
- Examine detailed schema definitions for variable validation
- Understand specific variable names and constraints
- Debug template behavior or compatibility issues
Example response:
{
"allowed_in_contexts": [],
"augment_includes": [
"http",
"http/server",
"http/server/location"
],
"created_at": "2025-09-25T19:20:47.473955Z",
"description": "",
"items": [
{
"contents": "user nginx;\nworker_processes auto;\n\nhttp {\n {{ augment_includes \"http\" . }}\n \n server {\n listen 80;\n server_name _;\n\n {{ augment_includes \"http/server\" . }}\n \n location / {\n proxy_pass {{ .backend_url }};\n {{ augment_includes \"http/server/location\" . }}\n }\n }\n}\n",
"ctime": "2025-09-25T19:20:47.473955Z",
"file_format": "FILE_FORMAT_PLAIN",
"file_type": "FILE_TYPE_TEMPLATE",
"mime_type": "FILE_MIME_TYPE_TEXT",
"name": "reverse-proxy.tmpl",
"size": 338
},
{
"contents": "$schema: \"http://json-schema.org/draft-07/schema#\"\ntype: object\nproperties:\n backend_url:\n type: string\n description: \"Backend server URL\"\nrequired:\n - backend_url\nadditionalProperties: false\n",
"ctime": "2025-09-25T19:20:47.473955Z",
"file_format": "FILE_FORMAT_PLAIN",
"file_type": "FILE_TYPE_SCHEMA",
"mime_type": "FILE_MIME_TYPE_YAML",
"name": "schema.yaml",
"size": 200
}
],
"name": "reverse-proxy-base",
"object_id": "tmpl_0rQSkSNSTamthLQVtSZb1g",
"type": "base"
}Details:
- Template content - Shows
augment_includesplaceholders and variable usage (e.g.,{{ .backend_url }}) - Schema definition - Shows required variables (
backend_url) and their validation rules - Variable constraints - Data types, descriptions, and any pattern requirements
Use the Submit templates for previewing NGINX configuration API operation to render NGINX configurations from templates.
The preview_only query parameter controls the mode:
preview_only |
Behavior | Response |
|---|---|---|
false (default) |
Renders the configuration, creates a persistent submission, and publishes to the target(s). | 202 Accepted with submission object_id and target results. |
true |
Renders the configuration for inspection without creating a submission or publishing. | 200 OK with the rendered NGINX configuration. |
The following sections describe what you need for the request.
ImportantThis path determines where augment configurations are rendered:
- Base template → renders to the exact
conf_path- Augment templates → render to
{base_dir}/conf.d/augments/{filename}.{hash}.confWhere
base_diris derived fromconf_path:
conf_path: /etc/nginx/nginx.conf→ augments in/etc/nginx/conf.d/augments/conf_path: /opt/nginx/nginx.conf→ augments in/opt/nginx/conf.d/augments/
Required. The absolute path where the main NGINX configuration file should be placed.
Examples:
/etc/nginx/nginx.conf(standard installation)/opt/nginx/nginx.conf(custom installation)
Base Template:
object_id- Template version unique identifier (tmplv_...) for the version to usevalues- Key-value pairs for template variables
Augment Templates:
object_id- Template version unique identifier (tmplv_...)target_context- NGINX context where the augment should be appliedvalues- Key-value pairs for template variables (optional if template has no variables)child_augments- Optional nested augments that render within this augment’s output
Augment templates must specify a target_context that determines where the augment will be placed in the base template.
Validation:
- The augment’s
target_contextmust be listed in the augment template’sallowed_in_contexts(specified during import)
Available Contexts:
See the Template Authoring Guide for detailed information about context paths and how they map to NGINX configuration structure.
Rendering Behavior:
- If the base template has an
augment_includesplaceholder for the target context, the augment content is injected there - If the base template doesn’t have a matching placeholder, the augment is ignored (no error)
- If the base template has placeholders but no matching augments are provided, those placeholders render as empty strings
- Augments are applied in the order specified in the request.
For more information, see Understanding Rendering Order.
Use the Submit Templates API operation without preview_only=true (or explicitly with preview_only=false) to render and persist a submission.
Current limitation: Submission targets are currently limited to staged configurations. Targeting Config Sync Groups or instances directly is not yet supported.
Omit target_object_ids from the request body. The API renders the configuration and automatically creates a new staged config.
Required fields:
conf_path- Configuration file pathbase_template- Base template version and valuesaugments- Ordered list of augment templates (can be empty)description- A description for the submission (required in submission mode)
Request body:
{
"conf_path": "/etc/nginx/nginx.conf",
"description": "Reverse proxy with rate limiting",
"base_template": {
"object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw",
"values": {
"backend_url": "http://example.com:8080"
}
},
"augments": [
{
"object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw",
"target_context": "http",
"values": {
"zone_name": "req_limit",
"memory": "10m",
"rate": "10r/s"
}
}
]
}Successful response (202 Accepted):
{
"object_id": "tmplsm_frBobKIAQ_21grAwV83VYz",
"target_results": [
{
"staged_config_status": {
"status": "succeeded"
},
"target_object_id": "sc_cEoiYCVJRuekVpYOvV1raA"
}
]
}The object_id in the response is your submission ID (tmplsm_...). Save this value — it is used to retrieve, update, or delete the submission later. The target_object_id is the newly created staged config.
Include target_object_ids in the request body with the ID of an existing staged config. The API renders the configuration and publishes it to the specified target.
Request body:
{
"conf_path": "/etc/nginx/nginx.conf",
"description": "Reverse proxy with rate limiting - updated",
"base_template": {
"object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw",
"values": {
"backend_url": "http://example.com:8080"
}
},
"augments": [
{
"object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw",
"target_context": "http",
"values": {
"zone_name": "req_limit",
"memory": "10m",
"rate": "10r/s"
}
}
],
"target_object_ids": ["sc_cEoiYCVJRuekVpYOvV1raA"]
}Add ?preview_only=true to the request URL to render the configuration for inspection without creating a submission or publishing to any target. This is useful for validating your template values before committing.
Here’s an example of what you need to include with the API request:
{
"conf_path": "/etc/nginx/nginx.conf",
"base_template": {
"object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw",
"values": {
"backend_url": "http://example.com:8080"
}
},
"augments": [
{
"object_id": "tmplv_AFVNBQcoRDeV9jk9panxbw",
"target_context": "http/server/location",
"values": {
"cors_allowed_origins": "https://app.example.com",
"cors_allowed_methods": "GET, POST, PUT, DELETE, OPTIONS"
}
},
{
"object_id": "tmplv_rT6Ul8RvQtSZPkNfsIExPQ",
"target_context": "http/server"
}
]
}{
"config": {
"aux": [],
"conf_path": "/etc/nginx/nginx.conf",
"config_version": "17qlLiPmAqIWhhYxmVieE9mC5t92e+/7gIvz0GFRj/E=",
"configs": [
{
"files": [
{
"contents": "<base64_encoded_nginx_conf>",
"mtime": "0001-01-01T00:00:00Z",
"name": "nginx.conf",
"size": 371
}
],
"name": "/etc/nginx"
},
{
"files": [
{
"contents": "<base64_encoded_nginx_conf>",
"mtime": "0001-01-01T00:00:00Z",
"name": "cors-headers.tmpl.4aaf36d4a643.conf",
"size": 159
},
{
"contents": "<base64_encoded_nginx_conf>",
"mtime": "0001-01-01T00:00:00Z",
"name": "health-check.tmpl.78346de4dae4.conf",
"size": 109
}
],
"name": "/etc/nginx/conf.d/augments"
}
]
},
"errors": null
}If the rendered configuration has NGINX syntax errors, you can use this information to debug and correct your submission request.
CautionParse errors indicate the rendered configuration has NGINX syntax issues, often due to missing include files or incomplete template logic. See Template Limitations.
{
"config": {
"aux": [],
"conf_path": "/etc/nginx/nginx.conf",
"config_version": "17qlLiPmAqIWhhYxmVieE9mC5t92e+/7gIvz0GFRj/E=",
"configs": [
{
"files": [
{
"contents": "<base64_encoded_nginx_conf>",
"mtime": "0001-01-01T00:00:00Z",
"name": "nginx.conf",
"size": 371
}
],
"name": "/etc/nginx"
}
]
},
"errors": [
{
"file": "nginx.conf",
"line": 3,
"error": "upstream \"backend\" has no servers in /etc/nginx/nginx.conf:3"
}
]
}Submissions are persistent objects that store the template composition and input values used to generate a configuration. Each submission tracks its target(s) and can be retrieved, updated, or deleted.
Use the Get a Template Submission API operation (GET /templates/submissions/{submissionObjectID}) to retrieve the full details of a submission, including the templates used, their input values, and target object IDs.
Example response:
{
"object_id": "tmplsm_frBobKIAQ_21grAwV83VYz",
"description": "Reverse proxy with rate limiting",
"target_object_ids": ["sc_cEoiYCVJRuekVpYOvV1raA"],
"created_at": "2025-09-25T19:20:47.473955Z",
"modified_at": "2025-09-25T19:20:47.473955Z",
"templates": [
{
"template_object_id": "tmpl_-uvR3F2TQGm18jnl7bpaGw",
"template_version_object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw",
"name": "reverse-proxy-base",
"type": "base",
"state": "final",
"version": 1,
"latest_version": 1,
"values": {
"backend_url": "http://example.com:8080"
}
}
]
}Use the Update a Template Submission API operation (PUT /templates/submissions/{submissionObjectID}) to fully replace the input values and payloads for all templates in the submission.
The conf_path and target object IDs are preserved from the original submission and cannot be changed through this endpoint. After the update, the configuration is re-rendered and re-published to the existing target(s).
Request body:
{
"base_template": {
"object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw",
"values": {
"backend_url": "http://new-backend.example.com:9090"
}
},
"augments": [
{
"object_id": "tmplv_-abR3F2TQGm18jnl7bpaXw",
"target_context": "http",
"values": {
"zone_name": "req_limit",
"memory": "20m",
"rate": "20r/s"
}
}
]
}Successful response (202 Accepted):
{
"object_id": "tmplsm_frBobKIAQ_21grAwV83VYz",
"target_results": [
{
"staged_config_status": {
"status": "succeeded"
},
"target_object_id": "sc_cEoiYCVJRuekVpYOvV1raA"
}
]
}To preview the updated configuration before persisting, add ?preview_only=true to the request. The response returns the re-rendered configuration as a 200 OK without saving any changes.
Use the Update a single template’s values in a submission API operation (PUT /templates/{templateObjectID}/submissions/{submissionObjectID}) to update the input values for one specific template within a submission, without changing any other template’s values.
All other templates in the submission retain their stored values. Payloads, target objects, and conf_path are preserved. The full configuration is re-rendered using the merged values and re-published to the existing target(s).
This is useful when only one template’s configuration needs to change — for example, updating a rate limiting zone name without resubmitting the full composition.
Request body:
{
"values": {
"zone_name": "api_limit",
"memory": "10m",
"rate": "5r/s"
}
}Successful response (202 Accepted): Same shape as the full update — the submission object_id and updated target results.
To preview the change before persisting, add ?preview_only=true. The response returns the re-rendered configuration as a 200 OK without saving any changes.
Use the Delete a Template Submission API operation (DELETE /templates/submissions/{submissionObjectID}) to permanently remove a submission.
CautionDeleting a submission is irreversible and removes all stored input values and payloads for that submission. The target staged config is not affected — only the submission record is deleted.
Successful response: 204 No Content
When templates are successfully rendered, the system creates multiple files:
- File: Exact path specified in
conf_path - Content: Rendered base template with augment content injected at
augment_includespoints
- Location:
{base_dir}/conf.d/augments/ - Filename:
{template-name}.{content-hash}.conf - Content: Individual augment template rendered output
Example structure:
/etc/nginx/
├── nginx.conf # Base template output
└── conf.d/
└── augments/
├── rate-limiting-http.abc123.conf # HTTP context augment
├── rate-limiting-location.def456.conf # Location context augment
└── cors-headers.ghi789.conf # Location context augmentNGINX configuration:
This is the output of nginx -T when such configuration is published to a data plane:
# configuration file /etc/nginx/nginx.conf:
user nginx;
worker_processes auto;
events {
worker_connections 1048;
}
http {
server {
listen 80;
server_name _;
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
location / {
proxy_pass http://example:8080;
add_header 'Access-Control-Allow-Origin' 'https://app.example.com' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
}
}
}Template rendering follows predictable ordering rules at two levels:
Directives render in the exact order they appear in the template file. This includes the placement of {{ augment_includes "context_path" . }} extension points.
Example:
http {
# This renders first
upstream backend { }
# Augments targeting "http" context render here
{{ augment_includes "http" . }}
# This renders after augments
server { }
}When multiple augments target the same context, they render in the order specified in the submission request’s augments array.
Example submission:
{
"conf_path": "/etc/nginx/nginx.conf",
"base_template": {
"object_id": "tmplv_-uvR3F2TQGm18jnl7bpaGw",
"values": {
"backend_url": "http://example.com:8080"
}
},
"augments": [
{
"object_id": "tmplv_rate_limit_zone",
"target_context": "http"
},
{
"object_id": "tmplv_upstream_definition",
"target_context": "http"
}
]
}Rendered output:
http {
# First augment renders first
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
# Second augment renders second
upstream custom_backend {
server 10.0.1.10:8080;
}
}Some NGINX directives must appear before others.
For example:
- Rate limit zones must be defined before they’re used
- Upstream blocks should be defined before server blocks reference them
- Map directives typically appear early in the http block
When composing template submissions, arrange your augments array to match the required directive order for valid NGINX configuration.