From dbff2889476a46a85fbd2e17bc1d32f3489264bc Mon Sep 17 00:00:00 2001 From: Mike Jang <3287976+mjang@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:14:05 -0700 Subject: [PATCH 1/7] Content from F5 user vrmare in internal repo --- .../nginx-configs/config-templates/_index.md | 6 + .../config-templates/add-multiple-services.md | 303 ++++++++ .../config-templates/author-templates.md | 688 ++++++++++++++++++ .../config-templates/import-templates.md | 375 ++++++++++ .../config-templates/save-as-staged-config.md | 108 +++ .../config-templates/submit-templates.md | 488 +++++++++++++ 6 files changed, 1968 insertions(+) create mode 100644 content/nginx-one/nginx-configs/config-templates/_index.md create mode 100644 content/nginx-one/nginx-configs/config-templates/add-multiple-services.md create mode 100644 content/nginx-one/nginx-configs/config-templates/author-templates.md create mode 100644 content/nginx-one/nginx-configs/config-templates/import-templates.md create mode 100644 content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md create mode 100644 content/nginx-one/nginx-configs/config-templates/submit-templates.md diff --git a/content/nginx-one/nginx-configs/config-templates/_index.md b/content/nginx-one/nginx-configs/config-templates/_index.md new file mode 100644 index 000000000..8394c9f16 --- /dev/null +++ b/content/nginx-one/nginx-configs/config-templates/_index.md @@ -0,0 +1,6 @@ +--- +description: +title: Manage config templates +weight: 400 +url: /nginx-one/nginx-configs/config-templates +--- diff --git a/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md b/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md new file mode 100644 index 000000000..6bf32c52c --- /dev/null +++ b/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md @@ -0,0 +1,303 @@ +--- +nd-docs: null +title: Add service-specific locations +toc: true +weight: 400 +type: +- how-to +--- + +# Overview + +This guide shows how to extend working submission from the [Submit Templates Guide]({{< ref "submit-templates.md" >}}) by adding server augments for new services with dedicated location augments. + +**Note: With current limitation to not being able to retrieve previous submissions, you must provide entire request including any updates.** + +## Import template + +If there aren't existing augment templates that fit your needs, you will need to create and import them. + +### New server augment template + +Since we don't have a server augment yet, we need to create one. This template creates dedicated server blocks for each service. + +`http-server.tmpl` + +```text +server { + listen {{ .listen_port }}; + server_name{{ range .server_names }} {{ . }}{{ end }}; + + {{ augment_includes "http/server/location" . }} +} +``` + +`schema.yaml` + +```text +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + listen_port: + type: integer + description: "Port for the server to listen on" + minimum: 1 + maximum: 65535 + default: 80 + server_names: + type: array + description: "Array of domain names for this server" + items: + type: string + minItems: 1 +required: + - listen_port + - server_names +additionalProperties: false +``` + +#### Import parameters + +When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this template: + +- name: `http-server` +- type: `augment` +- allowed_in_contexts: `["http"]` + +### New location augment template + +We also need a location augment template to create location blocks within each server. + +{{< call-out "note" >}} +You may already have a "health-check" location augment from previous steps which can be added to these new servers as well.* +{{< /call-out >}} + +`location-proxy.tmpl` + +```text +location {{ .path }} { + proxy_pass {{ .upstream_url }}; + proxy_connect_timeout {{ .proxy_timeout }}; + proxy_read_timeout {{ .proxy_read_timeout }}; +} +``` + +`schema.yaml` + +```text +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + path: + type: string + description: "Location path (e.g., /api, /admin)" + pattern: "^/.*$" + upstream_url: + type: string + description: "Backend service URL" + pattern: "^https?://[^\\s]+$" + proxy_timeout: + type: string + description: "Proxy connection timeout" + pattern: "^\\d+[smhd]?$" + default: "30s" + proxy_read_timeout: + type: string + description: "Proxy read timeout" + pattern: "^\\d+[smhd]?$" + default: "60s" +required: + - path + - upstream_url +additionalProperties: false +``` + +#### Import parameters +When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this template: + +- name: `location-proxy` +- type: `augment` +- allowed_in_contexts: `["http/server/location"]` + +## Submit to add multiple services + +### Request structure + +Here's an example of what you need to include with the API request: + +```json +{ + "conf_path": "/etc/nginx/nginx.conf", + "base_template": { + "object_id": "", + "values": { + "backend_url": "http://example.com:8080" + } + }, + "augments": [ + { + "object_id": "", + "target_context": "http/server/location", + "values": { + "cors_allowed_origins": "https://app.example.com", + "cors_allowed_methods": "GET, POST, PUT, DELETE, OPTIONS" + } + }, + { + "object_id": "", + "target_context": "http/server" + }, + { + "object_id": "", + "target_context": "http", + "values": { + "listen_port": 80, + "server_names": ["admin.example.com"] + }, + "child_augments": [ + { + "object_id": "", + "target_context": "http/server/location", + "values": { + "path": "/admin", + "upstream_url": "http://admin-backend:8080" + } + }, + { + "object_id": "", + "target_context": "http/server/location", + "values": { + "health_check_path": "/admin/health" + } + } + ] + } + ] +} +``` + +### What's in your new config template + +- **Existing augments remain:** Your CORS headers and health check continue to apply to the main server +- **New server augments:** You'll see an additional server block +- **Service-specific routing:** You'll find the new `admin.example.com` server name with its own location blocks and routing rules + +### Response format + +When you submit the request, you'll see the following results if you're successful, along with the rendered NGINX configuration: + +#### Successful response (200 OK) + +```json +{ + "config": { + "aux": [], + "conf_path": "/etc/nginx/nginx.conf", + "config_version": "nuZ4+d1T159/0vVV9vKaajrEw7QXc6T3fAnxKcVkC6I=", + "configs": [ + { + "files": [ + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "nginx.conf", + "size": 483 + } + ], + "name": "/etc/nginx" + }, + { + "files": [ + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "cors-headers.tmpl.4aaf36d4a643.conf", + "size": 159 + }, + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "health-check.tmpl.78346de4dae4.conf", + "size": 109 + }, + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "http-server.tmpl.81761e94d463.conf", + "size": 145 + }, + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "location-proxy.tmpl.66ebf3e1dfd9.conf", + "size": 121 + } + ], + "name": "/etc/nginx/conf.d/augments" + } + ] + }, + "errors": null +} +``` + +#### Rendered NGINX configuration + +```nginx +# configuration file /etc/nginx/nginx.conf: +user nginx; +worker_processes auto; + +events { + worker_connections 1048; +} + +http { + server { + listen 80; + server_name admin.example.com; + + location /admin { + proxy_pass http://admin-backend:8080; + proxy_connect_timeout 30s; + proxy_read_timeout 60s; + } + + } + + + 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.com:8080; + add_header 'Access-Control-Allow-Origin' 'https://app.example.com' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always; + + } + } +} +``` + +## Child augments + +Child augments allow you to nest augments within other augments, creating hierarchical configurations. This is commonly used when an augment creates a container (like a server block) that needs its own specific sub-configurations (like location blocks). + +**How Child Augments Work:** + +When an augment template includes an `{{ augment_includes "context_path" . }}` extension point, you can provide child augments that target that context path. The child augments render only within their parent augment's output. + +**Key Behavior:** +- Child locations only apply to their specific parent server +- Multiple servers can have different location configurations +- Each server operates independently with its own routing rules + +For information on designing templates with extension points, see the [Template Authoring Guide]({{< ref "author-templates.md" >}}). \ No newline at end of file diff --git a/content/nginx-one/nginx-configs/config-templates/author-templates.md b/content/nginx-one/nginx-configs/config-templates/author-templates.md new file mode 100644 index 000000000..f4e4a1fd4 --- /dev/null +++ b/content/nginx-one/nginx-configs/config-templates/author-templates.md @@ -0,0 +1,688 @@ +--- +nd-docs: null +title: Author templates +toc: true +weight: 10 +type: +- how-to +--- + +# Overview + +This guide explains how to write NGINX configuration templates for NGINX One Console, including Go template syntax, schema definitions, and platform-specific features. + +## General terms + +{{}} +| Term | Definition | +|-------------|-------------| +| **Template** | A reusable NGINX configuration file written using Go template syntax that can accept variables for customization. Templates can be either base templates (complete configurations) or augment templates (modular additions). Templates must use the `.tmpl` file extension and are imported into NGINX One Console for use in submissions. | +| **Base Template** | A template that defines the complete structure of an NGINX configuration file, including top-level directives and main configuration hierarchy. Contains directives like `user`, `worker_processes`, and `events` blocks. Renders to the main NGINX configuration file path. Only one base template can be used per submission. | +| **Augment Template** | A template that adds functionality to base templates. Contains NGINX directives for specific contexts (like headers or location blocks). Gets inserted at extension points in base templates and renders to separate files in `/etc/nginx/conf.d/augments/`. Multiple augments can be used in a single submission. | +| **Child Augment** | An augment nested within another augment, creating hierarchical configurations. Child augments render only within their parent augment's output and are specified in the `child_augments` property during submission. | +| **Context Path** | A path notation representing the hierarchical structure of NGINX configuration blocks (e.g., `http`, `http/server`, `http/server/location`). Used to specify where augments can be inserted in base templates via `augment_includes` and where augments target during submission via `target_context`. | +| **Extension Point** | A placeholder in a template using `{{ augment_includes "context_path" . }}` that marks where augment content can be inserted during rendering. Base templates use extension points to enable modular composition with augments. | +| **Schema** | A JSON Schema Draft 7 file (YAML or JSON format) that defines template variables, their types, descriptions, and validation rules. Required for templates that use variables. Schema properties become available as template variables via dot notation. | +| **Template Submission** | The process of composing base and augment templates with values to render a complete NGINX configuration. Submissions are currently preview-only and generate rendered configurations that can be saved as Staged Configs. | +| **Template Variable** | A placeholder in a template (e.g., `{{ .backend_url }}`) that gets replaced with user-provided values during rendering. All variables must be defined in the template's schema and provided during submission if marked as required. | +{{}} + +## Template types + +NGINX One supports two template types that serve different purposes. Understanding which type to use is critical since the system does not validate template type during import. You must correctly identify the type based on your template's content. + +### Base templates + +Base templates define the complete structure of an NGINX configuration file, including top-level directives and the main configuration hierarchy. + +**Characteristics:** +- Contains top-level NGINX directives (`user`, `worker_processes`, `events`) +- Defines the main configuration structure (`http`, `stream`, `events` blocks) +- Renders to the main NGINX configuration file path (e.g., `/etc/nginx/nginx.conf`) +- Only one base template can be used per [Submission]({{< ref "submit-templates.md" >}}) + +**Rule of Thumb:** If your template looks like a complete `nginx.conf` file with an `events {}` block and top-level directives, it's a base template. + +**Example Structure:** +```nginx +user nginx; +worker_processes auto; + +events { + worker_connections 1024; +} + +http { + server { + listen 80; + location / { + proxy_pass http://backend:8080; + } + } +} +``` + +### Augment templates + +Augment templates add functionality to existing configuration structures. They contain NGINX directives that fit within specific contexts. + +**Characteristics:** +- Contains context-specific directives (location blocks, headers, upstream definitions) +- Gets inserted at extension points in base templates +- Renders to separate files in `/etc/nginx/conf.d/augments/` +- Multiple augments can be used in a single submission + +**Rule of Thumb:** If your template contains only directives that would normally go inside an NGINX block (like inside `http`, `server`, or `location`), it's an augment template. + +**Example:** +```nginx +add_header 'Access-Control-Allow-Origin' '*' always; +add_header 'Access-Control-Allow-Methods' 'GET, POST' always; +``` + +### Type declaration during import + +When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) templates, you must explicitly declare the type. + +## Go template syntax + +NGINX One templates use Go's built-in template engine. For complete Go template syntax, please refer to the [official Go template documentation](https://pkg.go.dev/text/template). + +**NGINX One Console Specifics:** +- Standard Go template syntax is fully supported +- Custom functions are documented in [Making Templates Extensible](#making-templates-extensible) +- [Sprig Functions](https://masterminds.github.io/sprig/) are NOT supported + +### Validation timing + +Template syntax is validated during [Import]({{< ref "import-templates.md" >}}). NGINX directive syntax is validated when configurations are rendered during [Submission]({{< ref "submit-templates.md" >}}) preview. + +{{< call-out "note" >}} +When any unsupported template syntax is used, you will see a validation error during the import operation +{{< /call-out >}} + +### Template design best practices + +**Keep templates focused:** +- Each template should have a single, clear purpose +- Keep conditional logic simple +- Use variables for configuration, not behavior changes + +**Use descriptive variable names:** +```nginx +# Good +proxy_pass {{ .backend_url }}; +server_name {{ .primary_domain }}; + +# Avoid +proxy_pass {{ .url }}; +server_name {{ .name }}; +``` + +## Schema definitions + +Templates that use variables must include schema files for validation and UI generation. Schemas use JSON Schema Draft 7 format and can be written in YAML or JSON. + +### Schema requirements + +- Schema files are optional only if the template has no variables +- If variables are used in the template, schema file is required +- All variables used in the template must be defined in the schema +- Use required array to specify variables that must be provided during submission +- Variables not in the required array are optional; if not provided, they render as empty strings + +{{< call-out "important" >}} +All variables used in your template must be explicitly provided during submission if they are in the `required` array. Optional variables (not in `required`) will render as empty strings if not provided - ensure your template handles this appropriately using Go template conditionals if needed. +{{< /call-out >}} + +### Basic schema structure + +```yaml +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + # Variable definitions +required: + # Required variables +additionalProperties: false # Disallow properties not defined in schema +``` + +The `additionalProperties: false` setting ensures strict validation. Only variables explicitly defined in properties can be provided by the user. This catches typos and configuration errors early. + +### Schema-to-template mapping + +Variables defined in your schema become available in your template through Go's template syntax using dot (`.`) notation. + +**How it works:** +1. Each property in your schema's `properties` section becomes a template variable +2. Access variables in templates using `{{ .property_name }}`. If `property_name` has nested properties, you can access them using further dot notation, like `{{ .property_name.nested_property_name }}`. +3. The `.` represents the data object containing all schema-defined variables + +**Example:** + +**schema.yaml:** +```yaml +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + backend_url: + type: string + description: "Backend server URL" + listen_port: + type: integer + description: "Port number" +required: + - backend_url + - listen_port +additionalProperties: false +``` + +In your template: + +```text +server { + listen {{ .listen_port }}; + location / { + proxy_pass {{ .backend_url }}; + } +} +``` + +During [Submission]({{< ref "submit-templates.md" >}}), users provide values for these variables, which are then inserted into the template during rendering. + +{{< call-out "important" >}} +- Every variable used in your template must be defined in the schema +- All variables used in templates must be provided during submission +{{< /call-out >}} + +### Variable Types + +**String:** +```yaml +properties: + backend_url: + type: string + description: "Backend server URL" +``` + +**Integer:** +```yaml +properties: + listen_port: + type: integer + description: "Port number" +``` + +**Boolean:** +```yaml +properties: + enable_ssl: + type: boolean + description: "Enable SSL/TLS" +``` + +**Array:** +```yaml +properties: + server_names: + type: array + description: "List of server names" + items: + type: string +``` + +### Schema design best practices + +**Provide clear descriptions:** +```yaml +backend_url: + type: string + description: "Backend server URL (e.g., http://api-service:8080)" +listen_port: + type: integer + description: "Port number (1-65535)" +``` + +**Use snake_case for variable names:** +```yaml +properties: + server_names: + type: array + description: "List of server names" + items: + type: string +``` + +## Simple base template example + +Here's a complete, self-contained base template that requires no augmentation. This template is complete and ready to use. It includes all necessary configuration for a reverse proxy with load balancing, health checks, and proxy settings. Users provide values for variables during submission, and the template renders a fully functional NGINX configuration. + +**reverse-proxy.tmpl:** +```nginx +user nginx; +worker_processes {{ .worker_processes }}; + +events { + worker_connections {{ .worker_connections }}; +} + +http { + # Logging + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + # Basic settings + sendfile on; + tcp_nopush on; + keepalive_timeout 65; + + # Upstream backend + upstream backend { + {{- range .upstream_servers }} + server {{ . }}; + {{- end }} + } + + # Main server + server { + listen {{ .listen_port }}; + server_name{{ range .server_names }} {{ . }}{{ end }}; + + # Health check endpoint + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + + # Proxy to backend + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_connect_timeout {{ .proxy_timeout }}; + proxy_read_timeout {{ .proxy_timeout }}; + } + } +} +``` + +**schema.yaml:** +```yaml +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + worker_processes: + type: integer + description: "Number of worker processes" + worker_connections: + type: integer + description: "Worker connections limit" + listen_port: + type: integer + description: "Port to listen on" + server_names: + type: array + description: "Server domain names" + items: + type: string + upstream_servers: + type: array + description: "Backend server addresses (host:port)" + items: + type: string + proxy_timeout: + type: string + description: "Proxy timeout value" +required: + - worker_processes + - worker_connections + - listen_port + - server_names + - upstream_servers + - proxy_timeout +additionalProperties: false +``` + +## Making templates extensible + +If you want to allow others to extend your base template with additional functionality, you can add extension points using the `augment_includes` custom function. + +**You don't need extensibility if:** +- Creating a single-purpose, self-contained configuration +- All behavior is controlled through template variables + +**You need extensibility if:** +- Building a template system that others can enhance +- Want to enable optional features (CORS, rate limiting, auth) without bloating the base +- Creating reusable templates with plug-in architecture + +**When in doubt:** Start without extension points. You can always create a new version of your template with extension points added later. It's easier to add extensibility than to remove it once others depend on it. + +### `augment_includes` Custom Function + +**Syntax:** +```nginx +{{ augment_includes "context_path" . }} +``` + +**Parameters:** +1. `"context_path"` (string) - The NGINX context where augments can be inserted +2. `.` (required) - Content for an augment template file must always be provided + +### Config templates contexts + +Contexts define hierarchy within NGINX configuration where augments can be inserted. NGINX One Console uses a path notation to represent the hierarchical structure of NGINX configuration blocks. This notation maps directly to NGINX's directive contexts. + +```text +# NGINX Configuration + # main (root level) +http { # http + upstream backend { } # http/upstream + + server { # http/server + location / { } # http/server/location + } +} + +stream { # stream + upstream backend { } # stream/upstream + + server { } # stream/server +} +``` + +**Available Template Context Paths:** +- `main` - Main (root) level +- `http` - HTTP block level +- `http/server` - Server block within HTTP +- `http/server/location` - Location block within server +- `http/upstream` - Upstream block within HTTP +- `stream` - Stream block level +- `stream/server` - Server block within stream +- `stream/upstream` - Upstream block within stream + +**Context Hierarchy:** +``` +main (root) +├── http +│ ├── upstream +│ └── server +│ └── location +└── stream + ├── upstream + └── server +``` + +**Why This Matters:** +When NGINX directive documentation says a directive is valid in "http, server, location" contexts, you would specify `allowed_in_contexts: ["http", "http/server", "http/server/location"]` using path notation. The slash separators (`/`) represent the nesting hierarchy in your actual NGINX configuration. + +### Modifying the simple base template + +Here's how to add extension points to the simple base template from the previous section: + +**reverse-proxy.tmpl** (with augmentation support): +```nginx +user nginx; +worker_processes {{ .worker_processes }}; + +events { + worker_connections {{ .worker_connections }}; +} + +http { + # Logging + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + # Basic settings + sendfile on; + tcp_nopush on; + keepalive_timeout 65; + + # HTTP-level augments (rate limiting zones, upstream blocks, etc.) + {{ augment_includes "http" . }} + + # Upstream backend + upstream backend { + {{- range .upstream_servers }} + server {{ . }}; + {{- end }} + } + + # Main server + server { + listen {{ .listen_port }}; + server_name{{ range .server_names }} {{ . }}{{ end }}; + + # Server-level augments (SSL config, logging, error pages, etc.) + {{ augment_includes "http/server" . }} + + # Health check endpoint + location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; + } + + # Proxy to backend + location / { + proxy_pass http://backend; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_connect_timeout {{ .proxy_timeout }}; + proxy_read_timeout {{ .proxy_timeout }}; + + # Location-level augments (CORS, auth, caching, etc.) + {{ augment_includes "http/server/location" . }} + } + } +} +``` + +**What Changed:** +- Added `{{ augment_includes "http" . }}` in the http block for HTTP-level extensions +- Added `{{ augment_includes "http/server" . }}` in the server block for server-level extensions +- Added `{{ augment_includes "http/server/location" . }}` in the location block for location-level extensions +- Schema remains unchanged - extension points don't require schema modifications + +**Extension Points Provided:** +- `http` - For rate limiting zones, additional upstream blocks, global HTTP settings +- `http/server` - For SSL configuration, custom logging, error pages +- `http/server/location` - For CORS headers, authentication, caching policies + +### Extension point best practices + +**Document extension points:** +```nginx +# Allow custom location-level configurations (CORS, auth, caching) +{{ augment_includes "http/server/location" . }} +``` + +**Strategic placement:** +- Place `augment_includes` where functionality commonly varies +- Consider NGINX directive ordering (order matters for some directives) +- Don't add extension points "just in case" - add them for known use cases + +**Always pass the dot:** +```nginx +# ✅ Correct +{{ augment_includes "http/server" . }} + +# ❌ Wrong - will cause errors +{{ augment_includes "http/server" }} +``` + +## Writing augment templates + +Once a base template provides extension points, you can write augment templates that target those contexts. + +### Determining allowed contexts + +When writing an augment template, you must identify which NGINX contexts your directives are valid in. This determines where the augment can be inserted. + +This is a required input while [Importing Templates]({{< ref "import-templates.md" >}}) augment templates in Nginx One Console using the `allowed_in_contexts` parameter. + +**Why This Matters :** + +The contexts you specify constrain where users can place your augment during submission. Your choice affects flexibility and correctness: + +- Specific contexts (e.g., ["http/server/location"]) - Ensures proper placement for endpoint-specific features like CORS headers, but limits where users can apply it. Essentially making this too restrictive. +- Multiple contexts (e.g., ["http", "http/server", "http/server/location"]) - Gives users flexibility to place the augment at different levels, but requires your directives to be valid in all those contexts. Essentially making this too permissive. + +Best practice is to specify all contexts where your directives are technically valid according to NGINX documentation, then let users decide the appropriate level during submission. + +Check the [NGINX directive documentation](https://nginx.org/en/docs/dirindex.html) for each directive you use. Each directive page specifies its valid contexts (e.g., "Context: http, server, location"). + +### Context determination rules + +#### Single context + +If your directives are only valid in one context, specify only that context: +```nginx +# Only valid in http block +limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; +``` +Allowed contexts: `["http"]` + +#### Multiple valid contexts + +If your directives work in multiple contexts, list all valid ones: +```nginx +# Valid in http, server, and location blocks +add_header X-Custom-Header "value"; +``` +Allowed contexts: `["http", "http/server", "http/server/location"]` + +### How augments are rendered + +When submitted together, augment content is inserted at matching `augment_includes` context paths in the base template. + +For complete details on the submission and rendering process, see [Understanding Rendering Order]({{< ref "submit-templates.md#understanding-rendering-order" >}}). + +### Complete augment examples + +Refer to [NGINX directive index](https://nginx.org/en/docs/dirindex.html) for all directives used in the examples below. + +**CORS Headers:** + +NGINX docs show `add_header` directive is valid in `http`, `server`, or `location` contexts. + +**cors-headers.tmpl:** +```nginx +add_header 'Access-Control-Allow-Origin' '{{ .cors_allowed_origins }}' always; +add_header 'Access-Control-Allow-Methods' '{{ .cors_allowed_methods }}' always; +add_header 'Access-Control-Allow-Headers' '{{ .cors_allowed_headers }}' always; +``` + +**schema.yaml:** +```yaml +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + cors_allowed_origins: + type: string + description: "Allowed origins for CORS" + cors_allowed_methods: + type: string + description: "Allowed HTTP methods" + cors_allowed_headers: + type: string + description: "Allowed headers" +required: + - cors_allowed_origins + - cors_allowed_methods + - cors_allowed_headers +additionalProperties: false +``` + +**Import with:** `allowed_in_contexts: ["http", "http/server", "http/server/location"]` + +--- + +**Rate Limiting Zone:** + +NGINX docs show `limit_req_zone` is valid in `http` context only. + +**rate-limit-zone.tmpl:** +```nginx +limit_req_zone $binary_remote_addr zone={{ .zone_name }}:{{ .zone_memory }} rate={{ .rate_limit }}; +``` + +**schema.yaml:** +```yaml +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + zone_name: + type: string + description: "Rate limit zone name" + zone_memory: + type: string + description: "Memory size for zone" + rate_limit: + type: string + description: "Rate limit (e.g., 10r/s)" +required: + - zone_name + - zone_memory + - rate_limit +additionalProperties: false +``` + +**Import with:** `allowed_in_contexts: ["http"]` + +--- + +**Server Block:** + +NGINX docs show `server` blocks appear in `http` or `stream` contexts. + +**server-block.tmpl:** +```nginx +server { + listen {{ .listen_port }}; + server_name{{ range .server_names }} {{ . }}{{ end }}; + + {{ augment_includes "http/server/location" . }} +} +``` + +**schema.yaml:** +```yaml +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + listen_port: + type: integer + description: "Port to listen on" + server_names: + type: array + description: "Server domain names" + items: + type: string +required: + - listen_port + - server_names +additionalProperties: false +``` + +**Import with:** `allowed_in_contexts: ["http", "stream"]` + +## Template Limitations + +- Template files must use the `.tmpl` file extension +- Templates cannot reference external files - all configuration must be contained within the template content +- External file references (such as `include /etc/nginx/mime.types`) are not supported + +## See also + +- [Import Templates]({{< ref "import-templates.md" >}}) +- [Submit Templates Guide]({{< ref "submit-templates.md" >}}) + diff --git a/content/nginx-one/nginx-configs/config-templates/import-templates.md b/content/nginx-one/nginx-configs/config-templates/import-templates.md new file mode 100644 index 000000000..591f343df --- /dev/null +++ b/content/nginx-one/nginx-configs/config-templates/import-templates.md @@ -0,0 +1,375 @@ +--- +nd-docs: null +title: Import templates +toc: true +weight: 100 +type: +- how-to +--- + +## Overview + +This guide explains how to work with configuration templates in NGINX One Console. + +In this guide, you will learn how to: + +- Import base and augment templates into NGINX One Console +- Submit templates with values for preview rendering +- Review the rendered configuration and any validation errors +- Save the configuration as a new Staged Config in NGINX One Console + +## Before you start + +- You have access to the NGINX One Console in your organization. For details, see [Before you begin]({{< ref "/nginx-one/getting-started.md#before-you-begin" >}}) in our Get started guide. +- API credentials to use the Templates API. For more information, see [Authenticate with the API]({{< ref "/nginx-one/api/authentication.md" >}}). +- Access to the `tar` command. +- The **absolute path** for your NGINX configuration file (for example, `/etc/nginx/nginx.conf`). This is required when submitting templates for preview. + +## Create template archives + +This section provides step-by-step instructions to create template archives. You can import these archives into NGINX One Console with the Templates API. + +### Archive structure requirements + +Each template archive must contain: +- **Exactly one `.tmpl` file** (required) - contains your NGINX configuration template +- **One `schema.yaml` or `schema.json` file** (optional) - required only if your template uses variables. For more information, see [Schema Definitions]({{< ref "author-templates.md#schema-definitions" >}}) +- **No other files** - additional files will be ignored or cause import failure + +```text +.tar.gz +│ +├── .tmpl +└── .yaml +``` + +### Naming conventions +Use the following convention for archive and template file names: + +#### Archive names +Name your archives to clearly reflect their specific use case: + +**Good Examples:** +- `load-balancer-base.tar.gz` - Base template for load balancing +- `reverse-proxy-base.tar.gz` - Base template for reverse proxy +- `cors-headers.tar.gz` - Augment for Cross-Origin Resource Sharing (CORS) header configuration +- `ssl-termination.tar.gz` - Augment for SSL/TLS termination +- `rate-limiting-http.tar.gz` - Rate limiting for HTTP context +- `rate-limiting-location.tar.gz` - Rate limiting for location context + +**Avoid Generic Names:** +- `template.tar.gz` +- `config.tar.gz` +- `nginx.tar.gz` + +#### Template file names + +**Base Templates:** +- The `.tmpl` filename extension doesn't affect the rendered output +- Content always renders to the main NGINX config path specified during submission +- Use descriptive names like `reverse-proxy.tmpl` + +**Augment Templates:** +- The `.tmpl` filename becomes part of the rendered config filename. For example, filename as `cors-headers.tmpl` will render as `/etc/nginx/conf.d/augments/cors-headers.{hash}.conf`. +- Use clear, descriptive names that indicate the augment's purpose + +### Step-by-Step archive creation + +Before creating template archives, see the [Template Authoring Guide]({{< ref "author-templates.md" >}}) for guidance on: +- Choosing between base and augment template types +- Using Go template syntax +- Defining schema files for template variables +- Creating extensible templates with `augment_includes` Go custom function + +#### 1. Create template directory structure + +Create a dedicated directory for each template to ensure clean archives: + +```bash +# Create your template workspace +mkdir -p templates/reverse-proxy-base +cd templates/reverse-proxy-base +``` + +#### 2. Add template files + +Create your template and schema files in the directory: + +```bash +# Create template file +cat > reverse-proxy.tmpl << 'EOF' +user nginx; +worker_processes auto; + +events { + worker_connections 1048; +} + +http { + server { + listen 80; + server_name _; + + location / { + proxy_pass {{ .backend_url }}; + proxy_set_header Host $host; + } + } +} +EOF + +# Create schema file (only if template uses variables) +cat > schema.yaml << 'EOF' +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + backend_url: + type: string + description: "Backend server URL" +required: + - backend_url +additionalProperties: false +EOF +``` + +#### 3. Create the archive + +{{< call-out "important" >}} +Always create archives from within the template directory to ensure files are at the root level. +{{< /call-out >}} + +```bash +# Create archive with files at root level +tar -czf ../reverse-proxy-base.tar.gz * + +# Verify archive contents (should show files at root, no directories) +tar -tzf ../reverse-proxy-base.tar.gz +``` + +#### 4. Verify Archive Structure + +Before importing, verify your archive structure: + +```bash +# Check archive contents +tar -tzf reverse-proxy-base.tar.gz + +# Extract to temporary location for verification +mkdir -p /tmp/verify-archive +tar -xzf reverse-proxy-base.tar.gz -C /tmp/verify-archive +ls -la /tmp/verify-archive/ +``` + +**Expected contents of the compressed archive:** +``` +reverse-proxy.tmpl +schema.yaml +``` + +### Complete example workflow + +Here's a complete example creating multiple related templates: + +```bash +# Create workspace +mkdir -p templates && cd templates + +# Create base template +mkdir reverse-proxy-base && cd reverse-proxy-base +cat > reverse-proxy.tmpl << 'EOF' +user nginx; +worker_processes auto; + +events { + worker_connections 1048; +} + +http { + {{ augment_includes "http" . }} + + server { + listen 80; + server_name _; + + {{ augment_includes "http/server" . }} + + location / { + proxy_pass {{ .backend_url }}; + {{ augment_includes "http/server/location" . }} + } + } +} +EOF + +cat > schema.yaml << 'EOF' +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + backend_url: + type: string + description: "Backend server URL" +required: + - backend_url +additionalProperties: false +EOF + +tar -czf ../reverse-proxy-base.tar.gz * +cd .. + +# Create CORS augment template +mkdir cors-headers && cd cors-headers +cat > cors-headers.tmpl << 'EOF' +add_header 'Access-Control-Allow-Origin' '{{ .cors_allowed_origins }}' always; +add_header 'Access-Control-Allow-Methods' '{{ .cors_allowed_methods }}' always; +EOF + +cat > schema.yaml << 'EOF' +$schema: "http://json-schema.org/draft-07/schema#" +type: object +properties: + cors_allowed_origins: + type: string + default: "*" + cors_allowed_methods: + type: string + default: "GET, POST, PUT, DELETE, OPTIONS" +required: + - cors_allowed_origins + - cors_allowed_methods +additionalProperties: false +EOF + +tar -czf ../cors-headers.tar.gz * +cd .. + +# Create simple augment without variables +mkdir health-check && cd health-check +cat > health-check.tmpl << 'EOF' +location /health { + access_log off; + return 200 "healthy\n"; + add_header Content-Type text/plain; +} +EOF +# No schema.yaml needed - template has no variables + +tar -czf ../health-check.tar.gz * +cd .. + +# Final structure +ls -la *.tar.gz +``` + +### Tips + +1. **Do not create nested directories in archives** + ```bash + # Avoid - nested directory structure is not supported + tar -czf template.tar.gz template-dir/ + + # Correct - keep files at root level + cd template-dir && tar -czf ../template.tar.gz * + ``` + +2. **Do not include unnecessary files** + ```bash + # Avoid - hidden files, backups or other file extensions will be ignored + tar -czf template.tar.gz *~ .* *.bak *.tmpl schema.yaml + + # Correct - only include required files + tar -czf template.tar.gz *.tmpl schema.yaml + ``` + +3. **Include schema for templates with variables** + - If your `.tmpl` file contains `{{ .variable }}`, you must include a schema file + - Import will be rejected without proper schema + +4. **Do not include multiple template files in one archive** + - Each archive must contain exactly one `.tmpl` file + - Create separate archives for related templates + +### Ready to import + +Once you have created your archives, you can import them using the [Import a template API]({{< ref "/nginx-one/api/api-reference-guide/#operation/importTemplate" >}}) operation. + +#### Required API parameters + +In addition to your template archive, the import API requires several parameters. Read the API specification for full details, but the key parameters include: + +**name** (required): +- A unique name for the template within your organization. Use the same as the archive name for clarity without the extension (e.g., `reverse-proxy-base`, `cors-headers`, `health-check`). + +**type** (required): +- `base` - For main NGINX configuration templates +- `augment` - For templates that extend base configurations + +**For Augment Templates Only**: +- **allowed_in_contexts** - Specify which contexts this augment can be included in (e.g., `http`, `http/server`, `http/server/location`). Understanding where your augment fits within NGINX configuration structure is crucial for proper integration. See the [Template Authoring Guide]({{< ref "author-templates.md" >}}) for detailed information on contexts and how to design augments that integrate correctly with base templates. + +#### Import validation + +During import, the system will validate: +- Archive structure (one .tmpl file, optional schema) +- Template syntax +- Schema validity (if provided) +- Variable references match schema definitions + +{{< call-out "caution" >}} +The `allowed_in_contexts` parameter is required when importing augment templates. The import process validates that this parameter is provided, but does not validate whether the contexts are valid for your template's NGINX directives. Context validation occurs during template submission. Ensure your specified contexts match where your NGINX directives can legally appear to avoid submission errors. +{{< /call-out >}} + +### Response format + +#### Successful response (200 OK) + +When import is successful, you will receive a response similar to the following: + +```json +{ + "allowed_in_contexts": [], + "augment_includes": [ + "http", + "http/server", + "http/server/location" + ], + "created_at": "2025-09-25T19:20:47.473935Z", + "description": "", + "name": "reverse-proxy-base", + "object_id": "tmpl_0rQSkSNSTamthLQVtSZb1g", + "type": "base" +} +``` + +```json +{ + "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" +} +``` + +```json +{ + "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" +} +``` + +## See also + +- [Template Authoring Guide]({{< ref "author-templates.md" >}}) +- [Submit Templates Guide]({{< ref "submit-templates.md" >}}) + diff --git a/content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md b/content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md new file mode 100644 index 000000000..6ca2b19e8 --- /dev/null +++ b/content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md @@ -0,0 +1,108 @@ +--- +nd-docs: null +title: Save rendered config as staged config +toc: true +weight: 300 +type: +- how-to +--- + +# Overview + +This guide explains how to save a [Submission]({{< ref "submit-templates.md#make-the-request" >}}) response as a new [Staged Config]({{< ref "/nginx-one/nginx-configs/staged-configs" >}}). + +# How to save + +The workflow involves two main steps: + +1. **Submit templates for preview** - Use the [Submit Templates Guide]({{< ref "submit-templates.md" >}}) to render configuration +2. **Save as staged config** - Create a staged configuration object from the preview + +## Step 1: Submit templates for preview + +First, use the [Submit templates]({{< ref "submit-templates.md#make-the-request" >}}) API operation to preview the configuration. + +## Step 2: Save as staged configuration + +{{< call-out "tip" >}} +You can save an NGINX configuration preview as staged config even if it contains parse errors. +{{< /call-out >}} + +Use the `config` object from the API response in step 1 to create a staged configuration. + +### Make the request + +Use the [Create a staged config]({{< ref "/nginx-one/api/api-reference-guide/#operation/createStagedConfig" >}}) API operation. + +### Request body + +Take the entire `config` object from the template submission response and wrap it with a `name` field. + +**Required fields:** +- `name` - Descriptive name for the staged configuration +- `config` - The complete `config` object from the template submission response + +**Optional fields:** +- `description` - Details about the configuration purpose or changes + +Here's an example of what you need to include with the API request: + +```json +{ + "name": "API Gateway", + "description": "Reverse proxy configuration with CORS headers and health check endpoint", + "config": { + "aux": [], + "conf_path": "/etc/nginx/nginx.conf", + "config_version": "17qlLiPmAqIWhhYxmVieE9mC5t92e+/7gIvz0GFRj/E=", + "configs": [ + { + "name": "/etc/nginx", + "files": [ + { + "name": "nginx.conf", + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "size": 371 + } + ] + }, + { + "name": "/etc/nginx/conf.d/augments", + "files": [ + { + "name": "cors-headers.tmpl.4aaf36d4a643.conf", + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "size": 159 + }, + { + "name": "health-check.tmpl.78346de4dae4.conf", + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "size": 109 + } + ] + } + ] + } +} +``` + +### Response format + +**Successful response (201 Created):** + +```json +{ + "name": "API Gateway", + "object_id": "sc_lGsm5mn2SW2dWUe8CmOOOg" +} +``` + +## See also + +- [Submit Templates Guide]({{< ref "submit-templates.md" >}}) +- [Staged Configs]({{< ref "/nginx-one/nginx-configs/staged-configs" >}}) + + diff --git a/content/nginx-one/nginx-configs/config-templates/submit-templates.md b/content/nginx-one/nginx-configs/config-templates/submit-templates.md new file mode 100644 index 000000000..7e97d3b7a --- /dev/null +++ b/content/nginx-one/nginx-configs/config-templates/submit-templates.md @@ -0,0 +1,488 @@ +--- +nd-docs: null +title: Submit templates +toc: true +weight: 200 +type: +- how-to +--- + +# Template submission and preview guide + +This guide explains how to submit templates for rendering NGINX configurations and preview the results using the Templates API. + +Before submitting templates for preview, you need to import templates into NGINX One Console. +- See the [Import Templates Guide]({{< ref "import-templates.md" >}}) for instructions on creating templates. +- For guidance on writing templates, see the [Template Authoring Guide]({{< ref "author-templates.md" >}}). + +## Overview + +Template submission allows you to compose templates that generate complete NGINX configuration. The process involves: + +1. **Discovering templates** - Find base and augment templates that match your infrastructure needs +2. **Understanding capabilities** - Review what contexts and features the base template supports +3. **Selecting augments** - Choose augments for additional features (CORS, rate limiting, SSL, etc.) +4. **Providing values** - Supply values for all template variables +5. **Preview and validate** - Generate and review the complete NGINX configuration +6. **Save as staged config** - Use NGINX One Console to save the preview as a staged configuration for deployment + +## Current limitations + +- **Preview only:** Template submission currently only supports preview mode (`preview_only=true`) +- **No submission persistence:** Submissions are not saved as objects (planned for future release) +- **Manual staged config creation:** After preview, use the NGINX One Console to manually save the rendered configuration as a staged config for deployment to instances or Config Sync Groups +- **Static includes:** Templates cannot include external static files (planned for future release) + +## Template discovery + +Before creating a submission, find base and augment templates that match your infrastructure needs. + +### List available templates + +Use the [List Templates]({{< ref "/nginx-one/api/api-reference-guide/#operation/listTemplates" >}}) API operation to find templates organized by use case. + +**Example Response:** +```json +{ + "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.473935Z", + "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 + +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. + +### Get template details (optional) + +Use the [Retrieve a Template]({{< ref "/nginx-one/api/api-reference-guide/#operation/getTemplate" >}}) 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:** +```json +{ + "allowed_in_contexts": [], + "augment_includes": [ + "http", + "http/server", + "http/server/location" + ], + "created_at": "2025-09-25T19:20:47.473935Z", + "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.473935Z", + "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.473935Z", + "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_includes` placeholders 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 + +## API endpoint + +Use the [Submit templates for previewing NGINX configuration]({{< ref "/nginx-one/api/api-reference-guide/#operation/submitTemplates" >}}) API operation to render and preview NGINX configurations from templates. + +## Request structure + +The following sections describe what you need for the request: + +### Required parameters + +**Query Parameter:** +- `preview_only=true` - Currently the only supported mode. Renders configuration for preview without creating a submission object. + +### Configuration path (`conf_path`) + +**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) + +**Important:** This 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}.conf` + +Where `base_dir` is derived from `conf_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/` + +### Template properties + +**Base Template:** +- `object_id` - Template unique identifier (use a template where `type` is `base`) +- `values` - Key-value pairs for template variables + +**Augment Templates:** +- `object_id` - Template unique identifier (use a template where `type` is `augment`) +- `target_context` - NGINX context where the augment should be applied +- `values` - Key-value pairs for template variables (optional if template has no variables) +- `child_augments` - Optional nested augments that render within this augment's output + +### Context paths + +Augment templates must specify a `target_context` that determines where the augment will be placed in the base template. + +**Validation:** +- The augment's `target_context` must be listed in the augment template's `allowed_in_contexts` (specified during import) + +**Available Contexts:** + +See the [Template Authoring Guide]({{< ref "author-templates.md#config-templates-contexts" >}}) for detailed information about context paths and how they map to NGINX configuration structure. + +**Rendering Behavior:** +- If the base template has an `augment_includes` placeholder 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](#understanding-rendering-order). + +## Make the request + +Use the [Submit Templates]({{< ref "/nginx-one/api/api-reference-guide/#operation/submitTemplates" >}}) API operation with your composed request and the required `preview_only=true` parameter. + +### Request body + +Here's an example of what you need to include with the API request: + +```json +{ + "conf_path": "/etc/nginx/nginx.conf", + "base_template": { + "object_id": "", + "values": { + "backend_url": "http://example.com:8080" + } + }, + "augments": [ + { + "object_id": "", + "target_context": "http/server/location", + "values": { + "cors_allowed_origins": "https://app.example.com", + "cors_allowed_methods": "GET, POST, PUT, DELETE, OPTIONS" + } + }, + { + "object_id": "", + "target_context": "http/server" + } + ] +} +``` + +### Response format + +#### Successful response (200 OK) + +```json +{ + "config": { + "aux": [], + "conf_path": "/etc/nginx/nginx.conf", + "config_version": "17qlLiPmAqIWhhYxmVieE9mC5t92e+/7gIvz0GFRj/E=", + "configs": [ + { + "files": [ + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "nginx.conf", + "size": 371 + } + ], + "name": "/etc/nginx" + }, + { + "files": [ + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "cors-headers.tmpl.4aaf36d4a643.conf", + "size": 159 + }, + { + "contents": "", + "mtime": "0001-01-01T00:00:00Z", + "name": "health-check.tmpl.78346de4dae4.conf", + "size": 109 + } + ], + "name": "/etc/nginx/conf.d/augments" + } + ] + }, + "errors": null +} +``` + +#### Response with parse errors (200 OK) + +If the rendered configuration has NGINX syntax errors. You can use this information to debug and correct your submission request. + +{{< call-out "caution" >}} +Parse errors indicate the rendered configuration has NGINX syntax issues, often due to missing include files or incomplete template logic. See [Template Limitations]({{< ref "author-templates.md#template-limitations" >}}). +{{< /call-out >}} + +```json +{ + "config": { + "aux": [], + "conf_path": "/etc/nginx/nginx.conf", + "config_version": "17qlLiPmAqIWhhYxmVieE9mC5t92e+/7gIvz0GFRj/E=", + "configs": [ + { + "files": [ + { + "contents": "dXNlciBuZ2lueDsKd29ya2VyX3Byb2Nlc3NlcyBhdXRvOwoKaHR0cCB7CiAgICAKICAgIAogICAgc2VydmVyIHsKICAgICAgICBsaXN0ZW4gODA7CiAgICAgICAgc2VydmVyX25hbWUgXzsKCiAgICAgICAgaW5jbHVkZSAvZXRjL25naW54L2NvbmYuZC9hdWdtZW50cy9oZWFsdGgtY2hlY2sudG1wbC43ODM0NmRlNGRhZTQuY29uZjsKCiAgICAgICAgCiAgICAgICAgbG9jYXRpb24gLyB7CiAgICAgICAgICAgIHByb3h5X3Bhc3MgaHR0cDovL2FwaS1zZXJ2aWNlOjgwODA7CiAgICAgICAgICAgIGluY2x1ZGUgL2V0Yy9uZ2lueC9jb25mLmQvYXVnbWVudHMvY29ycy1oZWFkZXJzLnRtcGwuNGFhZjM2ZDRhNjQzLmNvbmY7CgogICAgICAgIH0KICAgIH0KfQo=", + "mtime": "0001-01-01T00:00:00Z", + "name": "nginx.conf", + "size": 371 + } + ], + "name": "/etc/nginx" + }, + { + "files": [ + { + "contents": "YWRkX2hlYWRlciAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJyAnaHR0cHM6Ly9hcHAuZXhhbXBsZS5jb20nIGFsd2F5czsKYWRkX2hlYWRlciAnQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcycgJ0dFVCwgUE9TVCwgUFVULCBERUxFVEUsIE9QVElPTlMnIGFsd2F5czsK", + "mtime": "0001-01-01T00:00:00Z", + "name": "cors-headers.tmpl.4aaf36d4a643.conf", + "size": 159 + }, + { + "contents": "bG9jYXRpb24gL2hlYWx0aCB7CiAgICBhY2Nlc3NfbG9nIG9mZjsKICAgIHJldHVybiAyMDAgImhlYWx0aHlcbiI7CiAgICBhZGRfaGVhZGVyIENvbnRlbnQtVHlwZSB0ZXh0L3BsYWluOwp9Cg==", + "mtime": "0001-01-01T00:00:00Z", + "name": "health-check.tmpl.78346de4dae4.conf", + "size": 109 + } + ], + "name": "/etc/nginx/conf.d/augments" + } + ] + }, + "errors": [ + { + "file": "nginx.conf", + "line": 3, + "error": "upstream \"backend\" has no servers in /etc/nginx/nginx.conf:3" + } + ] +} +``` + +## Rendered file structure + +When templates are successfully rendered, the system creates multiple files: + +### Base template output +- **File:** Exact path specified in `conf_path` +- **Content:** Rendered base template with augment content injected at `augment_includes` points + +### Augment template outputs +- **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 augment +``` + +**NGINX configuration:** + +This is the output of `nginx -T` when such configuration is published to a data plane: + +```nginx +# 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; + + } + } +} +``` + +## Understanding rendering order + +Template rendering follows predictable ordering rules at two levels: + +### Directive order within templates + +Directives render in the exact order they appear in the template file. This includes the placement of `{{ augment_includes "context_path" . }}` extension points. + +**Example:** +```nginx +http { + # This renders first + upstream backend { } + + # Augments targeting "http" context render here + {{ augment_includes "http" . }} + + # This renders after augments + server { } +} +``` + +### Augment render in submissions + +When multiple augments target the same context, they render in the order specified in the submission request's augments array. + +**Example submission:** +```json +{ + "conf_path": "/etc/nginx/nginx.conf", + "base_template": { + "object_id": "", + "values": { + "backend_url": "http://example.com:8080" + } + }, + "augments": [ + { + "object_id": "tmpl_rate_limit_zone", + "target_context": "http" + }, + { + "object_id": "tmpl_upstream_definition", + "target_context": "http" + } + ] +} +``` + +**Rendered output:** +```text +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; + } +} +``` + +### Why order matters + +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 templates submissions, arrange your augments array to match the required directive order for valid NGINX configuration. + +## See also + +- [Template Authoring Guide]({{< ref "author-templates.md" >}}) +- [Add More Services]({{< ref "add-multiple-services.md" >}}) From 8b23ff23ae8569da009418b8472222878cfe4bb7 Mon Sep 17 00:00:00 2001 From: Mike Jang <3287976+mjang@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:37:48 -0700 Subject: [PATCH 2/7] Update content/nginx-one/nginx-configs/config-templates/author-templates.md --- .../nginx-configs/config-templates/author-templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/nginx-one/nginx-configs/config-templates/author-templates.md b/content/nginx-one/nginx-configs/config-templates/author-templates.md index f4e4a1fd4..44cdb3f06 100644 --- a/content/nginx-one/nginx-configs/config-templates/author-templates.md +++ b/content/nginx-one/nginx-configs/config-templates/author-templates.md @@ -253,7 +253,7 @@ properties: type: string ``` -## Simple base template example +## Base template example Here's a complete, self-contained base template that requires no augmentation. This template is complete and ready to use. It includes all necessary configuration for a reverse proxy with load balancing, health checks, and proxy settings. Users provide values for variables during submission, and the template renders a fully functional NGINX configuration. From bbda9a024946ccdfd1fe04db21e789a9712a5af9 Mon Sep 17 00:00:00 2001 From: Mike Jang <3287976+mjang@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:38:59 -0700 Subject: [PATCH 3/7] Update content/nginx-one/nginx-configs/config-templates/import-templates.md --- .../nginx-configs/config-templates/import-templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/nginx-one/nginx-configs/config-templates/import-templates.md b/content/nginx-one/nginx-configs/config-templates/import-templates.md index 591f343df..4dd5bfa8c 100644 --- a/content/nginx-one/nginx-configs/config-templates/import-templates.md +++ b/content/nginx-one/nginx-configs/config-templates/import-templates.md @@ -242,7 +242,7 @@ EOF tar -czf ../cors-headers.tar.gz * cd .. -# Create simple augment without variables +# Create augment without variables mkdir health-check && cd health-check cat > health-check.tmpl << 'EOF' location /health { From 3b22f5a81bc44fbed8fef5c10ea2c29903a0218a Mon Sep 17 00:00:00 2001 From: Mike Jang <3287976+mjang@users.noreply.github.com> Date: Thu, 2 Oct 2025 12:39:42 -0700 Subject: [PATCH 4/7] Update content/nginx-one/nginx-configs/config-templates/author-templates.md --- .../nginx-configs/config-templates/author-templates.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/nginx-one/nginx-configs/config-templates/author-templates.md b/content/nginx-one/nginx-configs/config-templates/author-templates.md index 44cdb3f06..f2bcc29d1 100644 --- a/content/nginx-one/nginx-configs/config-templates/author-templates.md +++ b/content/nginx-one/nginx-configs/config-templates/author-templates.md @@ -420,7 +420,7 @@ main (root) **Why This Matters:** When NGINX directive documentation says a directive is valid in "http, server, location" contexts, you would specify `allowed_in_contexts: ["http", "http/server", "http/server/location"]` using path notation. The slash separators (`/`) represent the nesting hierarchy in your actual NGINX configuration. -### Modifying the simple base template +### Modifying the base template Here's how to add extension points to the simple base template from the previous section: From fe985c9d7a3be45e6558a227a9a4bee2d6821b97 Mon Sep 17 00:00:00 2001 From: Mike Jang <3287976+mjang@users.noreply.github.com> Date: Thu, 2 Oct 2025 14:03:14 -0700 Subject: [PATCH 5/7] Add changelog --- content/nginx-one/changelog.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/content/nginx-one/changelog.md b/content/nginx-one/changelog.md index 7f00c3b53..871dd59a5 100644 --- a/content/nginx-one/changelog.md +++ b/content/nginx-one/changelog.md @@ -30,6 +30,13 @@ h2 { Stay up-to-date with what's new and improved in the F5 NGINX One Console. +## October 2, 2025 + +### You can now set up config templates + +- Start with how you can [Author templates]({{< ref "/nginx-one/nginx-configs/config-templates/author-templates.md" >}}) +- Automate with our **experimental** endpoints for [NGINX One Console templates]({{< ref "/nginx-one/api/api-reference-guide/#tag/Templates" >}}) + ## September 16, 2025 ### IPv6 endpoints for NGINX Agent and NGINX Plus usage reporting From 20936f1c0ee921b269bdb89951c2ceb9940664e2 Mon Sep 17 00:00:00 2001 From: Mike Jang <3287976+mjang@users.noreply.github.com> Date: Thu, 2 Oct 2025 16:07:58 -0700 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: Travis Martin <33876974+travisamartin@users.noreply.github.com> --- .../config-templates/add-multiple-services.md | 55 ++++++++++--------- .../config-templates/import-templates.md | 38 +++++++------ .../config-templates/save-as-staged-config.md | 5 +- 3 files changed, 53 insertions(+), 45 deletions(-) diff --git a/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md b/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md index 6bf32c52c..0dec52152 100644 --- a/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md +++ b/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md @@ -5,13 +5,14 @@ toc: true weight: 400 type: - how-to +nd-product: NGINX One Console --- # Overview -This guide shows how to extend working submission from the [Submit Templates Guide]({{< ref "submit-templates.md" >}}) by adding server augments for new services with dedicated location augments. +This guide shows how to extend a working submission from the [Submit Templates Guide]({{< ref "submit-templates.md" >}}) by adding server augments for new services with dedicated location augments. -**Note: With current limitation to not being able to retrieve previous submissions, you must provide entire request including any updates.** +{{< call-out "note" "Note" >}}Because you can’t retrieve previous submissions, you must include the full request with any updates.{{< /call-out >}} ## Import template @@ -19,7 +20,7 @@ If there aren't existing augment templates that fit your needs, you will need to ### New server augment template -Since we don't have a server augment yet, we need to create one. This template creates dedicated server blocks for each service. +Because there isn’t a server augment yet, you need to create one. This template creates dedicated server blocks for each service. `http-server.tmpl` @@ -66,10 +67,10 @@ When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this templat ### New location augment template -We also need a location augment template to create location blocks within each server. +Create a location augment template to add location blocks within each server. -{{< call-out "note" >}} -You may already have a "health-check" location augment from previous steps which can be added to these new servers as well.* +{{< call-out "note" "Note" >}} +If you already have a "health-check" location augment from earlier steps, you can add it to the new servers. {{< /call-out >}} `location-proxy.tmpl` @@ -90,7 +91,7 @@ type: object properties: path: type: string - description: "Location path (e.g., /api, /admin)" + description: "Location path (for example, /api, /admin)" pattern: "^/.*$" upstream_url: type: string @@ -123,20 +124,20 @@ When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this templat ### Request structure -Here's an example of what you need to include with the API request: +Example API request: ```json { "conf_path": "/etc/nginx/nginx.conf", "base_template": { - "object_id": "", + "object_id": "", "values": { "backend_url": "http://example.com:8080" } }, "augments": [ { - "object_id": "", + "object_id": "", "target_context": "http/server/location", "values": { "cors_allowed_origins": "https://app.example.com", @@ -144,11 +145,11 @@ Here's an example of what you need to include with the API request: } }, { - "object_id": "", + "object_id": "", "target_context": "http/server" }, { - "object_id": "", + "object_id": "", "target_context": "http", "values": { "listen_port": 80, @@ -156,7 +157,7 @@ Here's an example of what you need to include with the API request: }, "child_augments": [ { - "object_id": "", + "object_id": "", "target_context": "http/server/location", "values": { "path": "/admin", @@ -164,7 +165,7 @@ Here's an example of what you need to include with the API request: } }, { - "object_id": "", + "object_id": "", "target_context": "http/server/location", "values": { "health_check_path": "/admin/health" @@ -176,15 +177,15 @@ Here's an example of what you need to include with the API request: } ``` -### What's in your new config template +### New config template contents -- **Existing augments remain:** Your CORS headers and health check continue to apply to the main server -- **New server augments:** You'll see an additional server block -- **Service-specific routing:** You'll find the new `admin.example.com` server name with its own location blocks and routing rules +- **Existing augments remain:** CORS headers and the health-check location still apply to the main server. +- **New server augments** Adds an extra server block. +- **Service-specific routing:** The new `admin.example.com` server name has its own location blocks and routing rules. ### Response format -When you submit the request, you'll see the following results if you're successful, along with the rendered NGINX configuration: +If the request succeeds, the response includes the following output and the rendered NGINX configuration: #### Successful response (200 OK) @@ -289,15 +290,15 @@ http { ## Child augments -Child augments allow you to nest augments within other augments, creating hierarchical configurations. This is commonly used when an augment creates a container (like a server block) that needs its own specific sub-configurations (like location blocks). +Child augments let you nest one augment inside another, creating hierarchical configurations. This is often used when a parent augment creates a container (such as a server block) that requires specific sub-configurations (such as location blocks). -**How Child Augments Work:** +**How child augments work** -When an augment template includes an `{{ augment_includes "context_path" . }}` extension point, you can provide child augments that target that context path. The child augments render only within their parent augment's output. +When an augment template includes an `{{ augment_includes "context_path" . }}` extension point, you can provide child augments that target that context path. The child augments render only within their parent augment’s output. -**Key Behavior:** -- Child locations only apply to their specific parent server -- Multiple servers can have different location configurations -- Each server operates independently with its own routing rules +**Key behaviors** +- Child location augments apply only to their parent server. +- Different servers can have different location configurations. +- Each server runs independently with its own routing rules. -For information on designing templates with extension points, see the [Template Authoring Guide]({{< ref "author-templates.md" >}}). \ No newline at end of file +For details on designing templates with extension points, see the [Template Authoring Guide]({{< ref "author-templates.md" >}}). \ No newline at end of file diff --git a/content/nginx-one/nginx-configs/config-templates/import-templates.md b/content/nginx-one/nginx-configs/config-templates/import-templates.md index 4dd5bfa8c..8fba1a2f0 100644 --- a/content/nginx-one/nginx-configs/config-templates/import-templates.md +++ b/content/nginx-one/nginx-configs/config-templates/import-templates.md @@ -5,6 +5,7 @@ toc: true weight: 100 type: - how-to +nd-product: NGINX One Console --- ## Overview @@ -20,10 +21,12 @@ In this guide, you will learn how to: ## Before you start -- You have access to the NGINX One Console in your organization. For details, see [Before you begin]({{< ref "/nginx-one/getting-started.md#before-you-begin" >}}) in our Get started guide. -- API credentials to use the Templates API. For more information, see [Authenticate with the API]({{< ref "/nginx-one/api/authentication.md" >}}). -- Access to the `tar` command. -- The **absolute path** for your NGINX configuration file (for example, `/etc/nginx/nginx.conf`). This is required when submitting templates for preview. +Make sure you have the following: + +- Access to the NGINX One Console in your organization. See [Before you begin]({{< ref "/nginx-one/getting-started.md#before-you-begin" >}}) in the Get started guide. +- API credentials for the Templates API. See [Authenticate with the API]({{< ref "/nginx-one/api/authentication.md" >}}). +- The `tar` command installed. +- The **absolute path** to your NGINX configuration file (for example, `/etc/nginx/nginx.conf`). This path is required when submitting templates for preview. ## Create template archives @@ -32,6 +35,7 @@ This section provides step-by-step instructions to create template archives. You ### Archive structure requirements Each template archive must contain: + - **Exactly one `.tmpl` file** (required) - contains your NGINX configuration template - **One `schema.yaml` or `schema.json` file** (optional) - required only if your template uses variables. For more information, see [Schema Definitions]({{< ref "author-templates.md#schema-definitions" >}}) - **No other files** - additional files will be ignored or cause import failure @@ -44,9 +48,11 @@ Each template archive must contain: ``` ### Naming conventions + Use the following convention for archive and template file names: #### Archive names + Name your archives to clearly reflect their specific use case: **Good Examples:** @@ -134,7 +140,7 @@ EOF #### 3. Create the archive -{{< call-out "important" >}} +{{< call-out "important" "Important" >}} Always create archives from within the template directory to ensure files are at the root level. {{< /call-out >}} @@ -161,10 +167,10 @@ ls -la /tmp/verify-archive/ ``` **Expected contents of the compressed archive:** -``` + +``` text reverse-proxy.tmpl schema.yaml -``` ### Complete example workflow @@ -280,9 +286,9 @@ ls -la *.tar.gz tar -czf template.tar.gz *.tmpl schema.yaml ``` -3. **Include schema for templates with variables** - - If your `.tmpl` file contains `{{ .variable }}`, you must include a schema file - - Import will be rejected without proper schema +3. **Include a schema for templates with variables** + - If your `.tmpl` file contains `{{ .variable }}`, you must include a schema file. + - The import is rejected without a valid schema. 4. **Do not include multiple template files in one archive** - Each archive must contain exactly one `.tmpl` file @@ -290,21 +296,21 @@ ls -la *.tar.gz ### Ready to import -Once you have created your archives, you can import them using the [Import a template API]({{< ref "/nginx-one/api/api-reference-guide/#operation/importTemplate" >}}) operation. +After creating the archives, import them using the [Import a template API]({{< ref "/nginx-one/api/api-reference-guide/#operation/importTemplate" >}}) operation. #### Required API parameters In addition to your template archive, the import API requires several parameters. Read the API specification for full details, but the key parameters include: **name** (required): -- A unique name for the template within your organization. Use the same as the archive name for clarity without the extension (e.g., `reverse-proxy-base`, `cors-headers`, `health-check`). +- A unique name for the template within your organization. For clarity, use the same name as the archive (without the extension), for example, `reverse-proxy-base`, `cors-headers`, or `health-check`. **type** (required): - `base` - For main NGINX configuration templates - `augment` - For templates that extend base configurations **For Augment Templates Only**: -- **allowed_in_contexts** - Specify which contexts this augment can be included in (e.g., `http`, `http/server`, `http/server/location`). Understanding where your augment fits within NGINX configuration structure is crucial for proper integration. See the [Template Authoring Guide]({{< ref "author-templates.md" >}}) for detailed information on contexts and how to design augments that integrate correctly with base templates. +- **allowed_in_contexts** - Specify which contexts this augment can be included in (for example, `http`, `http/server`, or `http/server/location`). Knowing where an augment fits in the NGINX configuration structure is crucial for integration. See the [Template Authoring Guide]({{< ref "author-templates.md" >}}) for details on contexts and designing augments that integrate with base templates. #### Import validation @@ -314,15 +320,15 @@ During import, the system will validate: - Schema validity (if provided) - Variable references match schema definitions -{{< call-out "caution" >}} -The `allowed_in_contexts` parameter is required when importing augment templates. The import process validates that this parameter is provided, but does not validate whether the contexts are valid for your template's NGINX directives. Context validation occurs during template submission. Ensure your specified contexts match where your NGINX directives can legally appear to avoid submission errors. +{{< call-out "important" "Important" >}} +The `allowed_in_contexts` parameter is required to import augment templates. The import process checks that this parameter is included, but it doesn’t confirm whether the contexts are valid for your template’s NGINX directives. Context validation happens during template submission. Ensure your specified contexts match where your NGINX directives are allowed to appear to avoid submission errors. {{< /call-out >}} ### Response format #### Successful response (200 OK) -When import is successful, you will receive a response similar to the following: +If the import succeeds, you'll receive a response like this: ```json { diff --git a/content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md b/content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md index 6ca2b19e8..33eca8f72 100644 --- a/content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md +++ b/content/nginx-one/nginx-configs/config-templates/save-as-staged-config.md @@ -5,6 +5,7 @@ toc: true weight: 300 type: - how-to +nd-product: NGINX One Console --- # Overview @@ -25,7 +26,7 @@ First, use the [Submit templates]({{< ref "submit-templates.md#make-the-request" ## Step 2: Save as staged configuration {{< call-out "tip" >}} -You can save an NGINX configuration preview as staged config even if it contains parse errors. +You can save an NGINX configuration preview as a staged config, even if it contains parse errors. {{< /call-out >}} Use the `config` object from the API response in step 1 to create a staged configuration. @@ -36,7 +37,7 @@ Use the [Create a staged config]({{< ref "/nginx-one/api/api-reference-guide/#op ### Request body -Take the entire `config` object from the template submission response and wrap it with a `name` field. +Take the entire `config` object from the template submission response and wrap it in a `name` field. **Required fields:** - `name` - Descriptive name for the staged configuration From a0c0de2ead50149b117b7565374381d71a3ee51e Mon Sep 17 00:00:00 2001 From: Mike Jang <3287976+mjang@users.noreply.github.com> Date: Thu, 2 Oct 2025 16:12:08 -0700 Subject: [PATCH 7/7] Apply suggestions from code review --- .../nginx-configs/config-templates/add-multiple-services.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md b/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md index 0dec52152..aae80a8ba 100644 --- a/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md +++ b/content/nginx-one/nginx-configs/config-templates/add-multiple-services.md @@ -59,7 +59,7 @@ additionalProperties: false #### Import parameters -When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this template: +When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this template allows you to set up: - name: `http-server` - type: `augment` @@ -114,7 +114,7 @@ additionalProperties: false ``` #### Import parameters -When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this template: +When [Importing]({{< ref "import-templates.md#ready-to-import" >}}) this template allows you to: - name: `location-proxy` - type: `augment`