From 5ffae197331a14a1279a0c57e5f0c3ee9e4712f2 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Thu, 27 Aug 2026 15:14:25 -0700 Subject: [PATCH 01/19] added view recent usage doc --- .../view-recent-usage.md | 274 ++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 content/nim/licensing-and-reporting/view-recent-usage.md diff --git a/content/nim/licensing-and-reporting/view-recent-usage.md b/content/nim/licensing-and-reporting/view-recent-usage.md new file mode 100644 index 000000000..39eb5a37d --- /dev/null +++ b/content/nim/licensing-and-reporting/view-recent-usage.md @@ -0,0 +1,274 @@ +--- +title: View recent NGINX usage +description: "View raw, per-record NGINX usage telemetry in NGINX Instance Manager to verify billing data and support compliance audits." +weight: 350 +toc: true +f5-docs: +f5-personas: +- devops +- netops +- secops +- support +f5-content-type: how-to +f5-product: NGINX Instance Manager +f5-summary: > + View and export raw, unaggregated NGINX usage telemetry for NGINX Plus, NGINX Ingress Controller, and NGINX Gateway Fabric instances in NGINX Instance Manager. + This audit-grade record view lets you independently verify billing data and support compliance reviews, separately from the usage reports NGINX Instance Manager sends to F5. +--- + +## Overview + +The **Recent Usage** screen shows the raw usage telemetry that F5 NGINX Instance Manager collects from your instances. This includes F5 NGINX Plus, F5 NGINX Ingress Controller, and F5 NGINX Gateway Fabric. + +Each row is one telemetry record, exactly as your instance reported it. NGINX Instance Manager doesn't aggregate or transform records. Use this screen to independently verify the data behind your F5 billing and to support compliance audits. + +This screen doesn't require NGINX Agent. Your instances report usage data directly. + +### Instances and Clusters views + +The screen has two views: + +- **Instances**: Shows records from standalone NGINX Plus instances running on VMs or bare metal. +- **Clusters**: Shows records from NGINX deployments running in Kubernetes, including NGINX Ingress Controller and NGINX Gateway Fabric. + +By default, the screen shows the last 7 days of records, sorted by end time with the most recent first. Records are available for the last 120 days by default. You can change this retention window. See [Configure the retention window](#configure-the-retention-window). + +--- + +## Before you begin + +Before you view usage records, make sure you have: + +- **NGINX Plus R33 or later**: NGINX Plus R33 and later include the `ngx_mgmt_module` module. Earlier versions can't report usage to NGINX Instance Manager. +- **NGINX Plus configured to report usage**: Each NGINX Plus instance needs the `usage_report` directive set to your NGINX Instance Manager host. See [Configure NGINX Plus to report usage to NGINX Instance Manager]({{< ref "nim/licensing-and-reporting/report-usage-connected-deployment.md#configure-nginx-plus-to-report-usage-to-nginx-instance-manager" >}}). +- **The NGINX Plus Usage permission**: Your user account needs this RBAC permission to view usage records in the dashboard or through the API. + +--- + +## View and filter usage records + +### View records in the dashboard + +To view raw usage records: + +1. Log in to NGINX Instance Manager (`https:///ui/`). +2. In the left navigation, select **Usage**, then select **Recent Usage**. +3. Select the **Instances** or **Clusters** tab. + +By default, the dashboard shows records from the last 7 days, sorted by end time with the most recent first. + +{{< call-out class="note" title="Note: Fields not shown in the table" >}} +The dashboard's summary table does not display every field from a usage record — for example, reporting start time. Select a row to view the full record, including fields not shown as table columns. +{{< /call-out >}} + +### View record details + +Select a row to open a side panel showing all fields for that record. + +### Filter records + +Select **Add Filter** to narrow your results by: + +{{}} +| Filter | Description | +|---|---| +| Date range | Filters by reporting end time. Defaults to the last 7 days. Maximum range is 365 days. | +| NGINX Instance ID | Filters by a specific NGINX instance UUID. | +| Cluster ID | Filters by a Kubernetes cluster UUID. Available on the **Clusters** tab only. | +| Product type | Filters by product: NGINX Plus, NGINX Ingress Controller, NGINX Gateway Fabric, or Unspecified. Select multiple types. | +| Subscription token | Filters by JWT token ID (`jti`). | +{{
}} + +#### Find filter values + +If you don't already have the identifiers used in these filters: + +- **NGINX Instance ID**: NGINX Plus stores this in `/var/lib/nginx/nginx.id` on each instance. You can also find it in the **NGINX UID** column, or by selecting a row to open the detail panel. +- **Cluster ID**: Visible in the **K8s Cluster ID** column on the Clusters tab. NGINX Ingress Controller and NGINX Gateway Fabric generate this ID at installation and store it in the deployment's Kubernetes secret. +- **Subscription token (jti)**: A claim inside your subscription JWT (`license.jwt`). Paste the JWT contents into [jwt.io](https://jwt.io) and look for the `jti` field. You can also find it in the **JWT ID** column. + +### Export records as CSV + +To export usage records for offline auditing or compliance: + +1. Apply the filters you need. +2. Select **Export CSV**. + +The CSV file downloads with all records matching your current filters. Field values in the export match the raw stored data exactly, with no rounding or aggregation. + +(Optional) If the export is slow, apply additional filters to narrow the result set before exporting. + +The following table lists which columns appear in each tab's CSV export. + +{{}} +| Field | Instances tab | Clusters tab | +|---|---|---| +| `nginx_uid` | Yes | Yes | +| `product_type` | Yes | Yes | +| `nginx_version` | Yes | Yes | +| `start_time` | Yes | Yes | +| `end_time` | Yes | Yes | +| `nap` | Yes | Yes | +| `jwt_token_id` | Yes | Yes | +| `jwt_expiration` | Yes | Yes | +| `jwt_order_type` | Yes | Yes | +| `workers` | Yes | Yes | +| `user_agent` | Yes | Yes | +| `uptime` | Yes | Yes | +| `reloads` | Yes | Yes | +| `installation_id` | No | Yes | +| `cluster_id` | No | Yes | +| `cluster_node_count` | No | Yes | +{{
}} + +{{< call-out class="note" title="Note: If your export is truncated" >}} +See [CSV export produces a truncated file](#csv-export-produces-a-truncated-file). +{{< /call-out >}} + +--- + +## Configure the retention window + +NGINX Instance Manager automatically removes usage records older than the configured retention period. A background job runs once at startup and then every 24 hours to purge expired records. + +{{}} +| Setting | Value | +|---|---| +| Default retention | 120 days | +| Allowed range | 0–365 days | +| Configuration key | `nginx_raw_usage_retention_days` (under `dpm:`) | +{{
}} + +To change the retention period: + +1. Open `/etc/nms/nms.conf` on the NGINX Instance Manager server. +2. Add or update the setting under the `dpm:` block: + + ```yaml + dpm: + nginx_raw_usage_retention_days: 180 + ``` + +3. Restart NGINX Instance Manager: + + ```shell + sudo systemctl restart nms + ``` + +{{< call-out class="important" title="Important: Retention value limits" >}} +NGINX Instance Manager normalizes retention values on startup. It caps any value above 365 to 365 and ignores negative values, falling back to the default (120 days) instead. A value of 0 blocks local storage: NGINX Instance Manager doesn't write new records and purges existing records on the next run. This doesn't affect usage reporting to F5. +{{< /call-out >}} + +If NGINX Instance Manager clamps or rejects your configured value, it logs a `[RAW-USAGE]` warning so you can confirm the value wasn't used as entered. + +### Estimate storage for extended retention + +{{< call-out class="important" title="Important: Content pending" >}} +Blocked on storage-size-per-instance figures from engineering (TECHDOCS-5506 open items, and the companion tech-specs.md ticket). Do not publish this page until this subsection is filled in — the story explicitly calls for covering 4–12 month retention, and customers extending retention need this to plan disk capacity. +{{< /call-out >}} + +Storage usage grows with the number of NGINX instances reporting and the length of your retention window. Each instance generates approximately one record per hour. + + + +--- + +## Validate a record from the CLI + +{{< call-out class="important" title="Important: Content pending" >}} +Blocked on CLI validation commands from engineering (Kamal Chaturvedi or Amardeep Chawla — TECHDOCS-5506 open items). The runbook's REST API list/filter examples are a reasonable starting point, but the ticket specifically calls for validating a record's Cluster ID and nginx_uid for Kubernetes deployments, which needs a worked example we don't have — for example, confirming a cluster's ID from a running NGINX Gateway Fabric deployment and cross-checking it against a record returned by the API. +{{< /call-out >}} + + + +--- + +## What's shown + +{{}} +| Field | Description | +|---|---| +| NGINX Instance ID | UUID identifying the NGINX instance. | +| Product type | NGINX Plus, NGINX Ingress Controller, NGINX Gateway Fabric, or Unspecified. | +| NGINX version | The NGINX version string, for example `1.29.8`. | +| Reporting window | Start and end timestamps of the reporting period. | +| F5 WAF status | Whether F5 WAF for NGINX is active or inactive. | +| Subscription token | JWT token ID (`jti`) and expiration date. | +| Workers | Number of active NGINX worker processes. | +| Uptime | Seconds since the last NGINX restart. | +| Reloads | Number of configuration reloads during the reporting period. | +| Cluster ID | Kubernetes cluster identifier. Kubernetes deployments only. | +| Cluster node count | Number of nodes in the Kubernetes cluster. Kubernetes deployments only. | +{{
}} + +{{< call-out class="note" title="Note: No personally identifiable information" >}} +Usage records contain only UUIDs, timestamps, and numeric counters. They don't include hostnames, IP addresses, or other personally identifiable information. +{{< /call-out >}} + +--- + +## How this differs from usage reporting to F5 + +The **Recent Usage** screen is a local, on-demand audit view. It's different from the usage reports NGINX Instance Manager automatically sends to F5 for billing. + +{{}} +| | **Recent Usage** screen | Usage reporting to F5 | +|---|---|---| +| Purpose | Local audit and verification | Billing and entitlement | +| Data | Raw, per-record, unaggregated | Aggregated for submission | +| Retention | Configurable, 0–365 days (120 default) | Not applicable | +| Where to configure | This page | [Report usage data to F5 (connected)]({{< ref "nim/licensing-and-reporting/report-usage-connected-deployment.md" >}}) or [Report usage data to F5 (disconnected)]({{< ref "nim/licensing-and-reporting/report-usage-disconnected-deployment.md" >}}) | +{{
}} + +Viewing or exporting records on this screen doesn't affect usage reporting to F5. The two pipelines operate independently. + +This screen works the same way in connected and disconnected deployments. Your instances keep reporting locally, and existing records stay fully browsable, even without internet access. + +--- + +## Troubleshooting + +### No records appear in the dashboard + +**Symptom**: The usage dashboard shows no records. + +**Cause**: One of the following: + +- NGINX Plus isn't configured to report usage to NGINX Instance Manager. +- Your NGINX Plus version is earlier than R33. +- The date range filter is too narrow. +- Your account doesn't have the NGINX Plus Usage permission. + +**Fix**: Confirm the `usage_report` directive is set in the `mgmt` block of your NGINX Plus configuration. Confirm your NGINX Plus version is R33 or later. Expand the date range or reset it to the default (last 7 days). Confirm your RBAC role includes the NGINX Plus Usage permission. + +### CSV export produces a truncated file + +**Symptom**: The exported CSV file appears incomplete. + +**Cause**: The CSV export streams data directly from the server. A dropped connection during the export leaves the file incomplete. + +**Fix**: Re-export the file. Use narrower date filters to reduce the export size if your connection is slow or unreliable. + +### A record's reporting window spans more than one hour + +**Symptom**: A record's reporting window is longer than expected, for example 09:00–11:00 instead of 09:00–10:00. + +**Cause**: A previous report failed. NGINX Plus combined the missed window with the next scheduled report. This is expected behavior. It ensures no usage data is lost. + +**Fix**: No action needed. NGINX Instance Manager retains both the extended record and any partially persisted original record. + +### Dashboard loads slowly with a large date range + +**Symptom**: The dashboard takes several seconds to load with a wide date range or no filters applied. + +**Cause**: Large date ranges return more records to retrieve and count, especially with thousands of instances. + +**Fix**: Narrow the date range or apply additional filters, such as instance, cluster, or product type. The default 7-day view typically loads within a few seconds. + +--- + +## References + +- [Report usage data to F5 (connected)]({{< ref "nim/licensing-and-reporting/report-usage-connected-deployment.md" >}}) +- [Report usage data to F5 (disconnected)]({{< ref "nim/licensing-and-reporting/report-usage-disconnected-deployment.md" >}}) +- [Change telemetry settings]({{< ref "nim/licensing-and-reporting/change-telemetry-settings.md" >}}) \ No newline at end of file From 701664eb0f31e365fc065f100d63e70eff6401c0 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Fri, 28 Aug 2026 10:33:59 -0700 Subject: [PATCH 02/19] docs(TECHDOCS-5505): add NGF security event export and visibility - Add "View NGINX Gateway Fabric security events" concept page under NIM Security Monitoring - Add "Export security logs to F5 NGINX Instance Manager" section to NGF policy-sources.md, under a renamed "Console integration" heading - Add troubleshooting entries for NIM-side and NGF-side event delivery failures - Add a version-requirement pointer to NGF technical specifications - Copy edit policy-sources.md: fix bare "WAF" mentions, correct the garbled NIM heading, split long/passive sentences per style guide Files touched: - content/nim/security-monitoring/ngf-security-events.md (new) - content/nim/security-monitoring/troubleshooting.md - content/ngf/waf-integration/troubleshooting.md - content/ngf/overview/technical-specifications.md - content/ngf/waf-integration/policy-sources.md --- .../ngf/overview/technical-specifications.md | 3 + content/ngf/waf-integration/policy-sources.md | 110 +++++++++++++----- .../ngf/waf-integration/troubleshooting.md | 23 ++++ .../ngf-security-events.md | 50 ++++++++ .../security-monitoring/troubleshooting.md | 31 +++++ 5 files changed, 191 insertions(+), 26 deletions(-) create mode 100644 content/nim/security-monitoring/ngf-security-events.md diff --git a/content/ngf/overview/technical-specifications.md b/content/ngf/overview/technical-specifications.md index da4f83528..ada341ce2 100644 --- a/content/ngf/overview/technical-specifications.md +++ b/content/ngf/overview/technical-specifications.md @@ -32,6 +32,9 @@ The following table lists the software versions NGINX Gateway Fabric supports. O | 1.3.0 | 1.1.0 | 1.25+ | 1.27.0 | R32 | --- | --- | | 1.2.0 | 1.0.0 | 1.23+ | 1.25.4 | R31 | --- | --- | +{{< call-out class="note" title="Note: NGINX Instance Manager integration" >}} +For version requirements to export F5 WAF for NGINX security events to NGINX Instance Manager, see [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}).{{< /call-out >}} + ### OpenShift Compatibility The following table lists the OpenShift versions and Operator versions compatible with NGINX Gateway Fabric. diff --git a/content/ngf/waf-integration/policy-sources.md b/content/ngf/waf-integration/policy-sources.md index 4208ed5ff..fcc0cc650 100644 --- a/content/ngf/waf-integration/policy-sources.md +++ b/content/ngf/waf-integration/policy-sources.md @@ -7,21 +7,21 @@ f5-product: NGINX Gateway Fabric f5-description: Configure WAFPolicy to fetch compiled bundles from F5 NGINX Instance Manager, F5 NGINX One Console, or an HTTP server. --- -NGINX Gateway Fabric supports three policy source types for fetching compiled WAF bundles: F5 NGINX Instance Manager, F5 NGINX One Console, and direct HTTP/HTTPS URLs. For a quick start walkthrough using the HTTP source, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started.md" >}}). +F5 NGINX Gateway Fabric supports three policy source types for fetching compiled F5 WAF bundles: F5 NGINX Instance Manager, F5 NGINX One Console, and direct HTTP/HTTPS URLs. For a quick start walkthrough using the HTTP source, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started.md" >}}). -Before configuring a policy source, ensure that WAF is [enabled on the NginxProxy]({{< ref "/ngf/waf-integration/overview.md#enable-waf-on-the-nginxproxy" >}}) — either per Gateway or globally via Helm values. +Before configuring a policy source, make sure F5 WAF is enabled on the NginxProxy, either per Gateway or globally via Helm values. For version requirements, see [Technical specifications]({{< ref "/ngf/overview/technical-specifications.md" >}}). -{{< call-out class="tip" >}} By default, NGINX Gateway Fabric retries transient fetch failures up to 3 times with exponential backoff, and each fetch attempt times out after 30 seconds. You can tune these using the `retryAttempts` and `timeout` fields on `policySource` or `logSource`. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Fetch retry behavior" >}} By default, NGINX Gateway Fabric retries transient fetch failures up to 3 times with exponential backoff, and each fetch attempt times out after 30 seconds. You can tune these using the `retryAttempts` and `timeout` fields on `policySource` or `logSource`. {{< /call-out >}} --- -## NGINX Instance Manager (NGINX Instance Manager) +## F5 NGINX Instance Manager -Use this option when you manage WAF policies through NGINX Instance Manager. For details on creating and compiling policies in NGINX Instance Manager, see [How WAF policy management works]({{< ref "/nim/waf-integration/overview.md" >}}) and [Create a security policy bundle]({{< ref "/nim/waf-integration/policies-and-logs/bundles/create-bundle.md" >}}). +Use this option when you manage F5 WAF policies through F5 NGINX Instance Manager. For details on creating and compiling policies in NGINX Instance Manager, see [How WAF policy management works]({{< ref "/nim/waf-integration/overview.md" >}}) and [Create a security policy bundle]({{< ref "/nim/waf-integration/policies-and-logs/bundles/create-bundle.md" >}}). **Workflow:** -1. Author and compile a policy in NGINX Instance Manager using the NGINX Instance Manager console or API. Verify that compilation succeeded before proceeding — NGINX Gateway Fabric cannot detect compilation failures in NGINX Instance Manager. +1. Author and compile a policy in NGINX Instance Manager using the NGINX Instance Manager console or API. Verify that compilation succeeded before proceeding. NGINX Gateway Fabric cannot detect compilation failures in NGINX Instance Manager. 2. Create a Secret with your NGINX Instance Manager credentials. 3. Create a `WAFPolicy` referencing the compiled policy by name. @@ -92,13 +92,13 @@ EOF Replace `https://nim.example.com` with your NGINX Instance Manager base URL, and `ngfBlocking` with your compiled policy name. -{{< call-out class="tip" >}} To skip TLS certificate verification when fetching bundles (for testing only - not recommended for production), uncomment 'insecureSkipVerify: true'. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Testing with self-signed certificates" >}} To skip TLS certificate verification when fetching bundles (for testing only - not recommended for production), uncomment 'insecureSkipVerify: true'. {{< /call-out >}} -{{< call-out class="tip" >}} To pin a specific policy version, use `policyUID` instead of `policyName`. Find the UID in the NGINX Instance Manager console or API. A pinned UID always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, use `policyUID` instead of `policyName`. Find the UID in the NGINX Instance Manager console or API. A pinned UID always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. {{< /call-out >}} ### Apply a route-level override (optional) -To apply a different policy to a specific route — for example, a data-guard policy — create a route-level `WAFPolicy`: +To apply a different policy to a specific route, such as a data-guard policy, create a route-level `WAFPolicy`: ```yaml kubectl apply -f - <}}). + --- ## F5 NGINX One Console -Use this option when you manage WAF policies through F5 NGINX One Console. For details on creating and compiling policies in NGINX One Console, see [Manage policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}). +Use this option when you manage F5 WAF policies through F5 NGINX One Console. For details on creating and compiling policies in NGINX One Console, see [Manage policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}). **Workflow:** -1. Author and compile a policy in the NGINX One Console console or API. If no compiled bundle for a given policy exists yet, NGINX Gateway Fabric triggers compilation via the NGINX One Console API when it first reconciles the WAFPolicy and waits for it to complete. -2. Create a Secret with your NGINX One Console API token. -3. Create a `WAFPolicy` referencing the compiled policy. +1. Author and compile a policy in the NGINX One Console console or API. +2. If no compiled bundle exists yet, NGINX Gateway Fabric triggers compilation through the NGINX One Console API. This happens the first time NGINX Gateway Fabric reconciles the `WAFPolicy` resource. NGINX Gateway Fabric waits for compilation to finish before continuing. +3. Create a Secret with your NGINX One Console API token. +4. Create a `WAFPolicy` referencing the compiled policy. ### Create the credentials Secret @@ -202,37 +205,91 @@ EOF Replace `` with your NGINX One Console tenant hostname. The `namespace` field refers to the NGINX One Console namespace where the policy resides. -{{< call-out class="tip" >}} To pin a specific policy version, set `policyVersionID`. A pinned version always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. If you use only `policyName` or `policyObjectID` without a version pin, the latest compiled bundle is fetched on each reconciliation or poll cycle. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, set `policyVersionID`. A pinned version always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. If you use only `policyName` or `policyObjectID` without a version pin, the latest compiled bundle is fetched on each reconciliation or poll cycle. {{< /call-out >}} --- ## HTTP/HTTPS server -Use this option when you compile WAF policies using the F5 WAF compiler CLI or a CI/CD pipeline and host the resulting bundle on an HTTP/HTTPS server. For details on using the compiler, see [Build and use the compiler tool]({{< ref "/waf/configure/compiler.md" >}}). +Use this option when you compile F5 WAF policies using the F5 WAF compiler CLI or a CI/CD pipeline and host the resulting bundle on an HTTP/HTTPS server. For details on using the compiler, see [Build and use the compiler tool]({{< ref "/waf/configure/compiler.md" >}}). For a complete walkthrough including policy compilation and a bundle server deployment, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started.md" >}}). -For production environments, you would typically host compiled bundles on an HTTPS server with authentication. See [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) for details on adding credentials, custom CA certificates, and checksum verification to your `policySource`. +In production environments, host compiled bundles on an HTTPS server with authentication. See [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) for details on adding credentials, custom CA certificates, and checksum verification to your `policySource`. --- -## Management console visibility +## Console integration + +NGINX Instance Manager and NGINX One Console don't show which F5 WAF policies are deployed to NGINX Gateway Fabric. Neither console shows which compiled bundle version NGINX Gateway Fabric has fetched. + +This is intentional. NGINX Gateway Fabric pulls compiled bundles from the management plane and deploys them directly in Kubernetes using native manifests, not through NGINX Instance Manager or NGINX One Console. This design lets you create and compile policies, then make them available to NGINX Gateway Fabric through the API, without a console-managed deployment step. + +F5 plans to add policy association visibility for NGINX Instance Manager and NGINX One Console in a future release. In the meantime, use `kubectl describe wafpolicy ` to check deployment status. + +### Export security logs to F5 NGINX Instance Manager + +F5 NGINX Instance Manager's Security Monitoring dashboard doesn't show which policies you've deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to NGINX Instance Manager. Exporting these events gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the dashboard. + +{{< call-out class="important" title="Important: Version requirement" >}} +This integration requires NGINX Instance Manager 2.23 or later. +{{< /call-out >}} + +To export these events, configure a `securityLogs` entry on the `WAFPolicy` resource. This entry sends events to the syslog listener NGINX Agent runs inside the NGINX pod. NGINX Agent's built-in OpenTelemetry collector transforms the events and exports them to NGINX Instance Manager. + +```yaml +kubectl apply -f - < -This is by design: NGINX Gateway Fabric pulls compiled bundles from the management plane using a pull model and deploys them directly in Kubernetes using native Kubernetes manifests, rather than through the NGINX Instance Manager or NGINX One Console console. This workflow ensures that policies can be created, compiled, and made available to NGINX Gateway Fabric via API without requiring console-managed deployment flows. +{{< call-out class="note" title="Note: Log profile must exist in NGINX Instance Manager" >}} +The `profileName: "secops_dashboard_ngf_otel"` log profile must exist in NGINX Instance Manager and match the `WAFPolicy` exactly. +{{< /call-out >}} -Policy association visibility for NGINX Instance Manager and NGINX One Console will be added in a future release. In the meantime, use `kubectl describe wafpolicy ` to check deployment status. +{{< call-out class="tip" title="Tip: Testing with self-signed certificates" >}} +To test with self-signed certificates, add `insecureSkipVerify: true` to `policySource` and `logSource`. Don't use this setting in production. See [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) for adding CA certificates and credentials. +{{< /call-out >}} ### Connect NGINX Gateway Fabric to F5 NGINX One Console -Ensure that NGINX Gateway Fabric is configured to connect to NGINX One Console. Follow the guidance at [Connect NGINX Gateway Fabric with Helm]({{< ref "/nginx-one-console/k8s/add-ngf-helm.md" >}}) or [Connect NGINX Gateway Fabric with Manifests]({{< ref "/nginx-one-console/k8s/add-ngf-manifests.md" >}}) before continuing. +Configure NGINX Gateway Fabric to connect to NGINX One Console before continuing. Follow [Connect NGINX Gateway Fabric with Helm]({{< ref "/nginx-one-console/k8s/add-ngf-helm.md" >}}) or [Connect NGINX Gateway Fabric with Manifests]({{< ref "/nginx-one-console/k8s/add-ngf-manifests.md" >}}). ### Export security logs to F5 NGINX One Console -Although the NGINX One Console console does not display which policies are deployed to NGINX Gateway Fabric data planes, you can export WAF security events to the NGINX One Console security dashboard. This gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the console. +NGINX One Console doesn't show which policies are deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to the NGINX One Console security dashboard. This gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the console. -To enable this, configure a `securityLogs` entry that sends events to the NGINX Agent's built-in OpenTelemetry collector, which forwards them to NGINX One Console. Use a log profile compiled for the NGINX One Console security dashboard: +To export these events, configure a `securityLogs` entry that sends events to NGINX Agent's built-in OpenTelemetry collector, which forwards them to NGINX One Console. Use a log profile compiled for the NGINX One Console security dashboard: ```yaml kubectl apply -f - <}} The `profileName: "secops_dashboard"` log profile must exist in your NGINX One Console namespace. This profile is required for events to appear correctly in the NGINX One Console security dashboard. {{< /call-out >}} +{{< call-out class="note" title="Note: Log profile must exist in NGINX One Console" >}} The `profileName: "secops_dashboard"` log profile must exist in your NGINX One Console namespace. This profile is required for events to appear correctly in the NGINX One Console security dashboard. {{< /call-out >}} --- @@ -281,4 +338,5 @@ The `localhost:1514` syslog destination points to the NGINX Agent's OpenTelemetr - [F5 WAF for NGINX overview]({{< ref "/ngf/waf-integration/overview.md" >}}) - [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) - [Troubleshoot WAFPolicy status]({{< ref "/ngf/waf-integration/troubleshooting.md" >}}) -- [WAFPolicy and NginxProxy API reference]({{< ref "/ngf/reference/api.md" >}}) +- [Technical specifications]({{< ref "/ngf/overview/technical-specifications.md" >}}) +- [WAFPolicy and NginxProxy API reference]({{< ref "/ngf/reference/api.md" >}}) \ No newline at end of file diff --git a/content/ngf/waf-integration/troubleshooting.md b/content/ngf/waf-integration/troubleshooting.md index 56faaec85..9966555a7 100644 --- a/content/ngf/waf-integration/troubleshooting.md +++ b/content/ngf/waf-integration/troubleshooting.md @@ -105,6 +105,29 @@ To resolve the conflict, choose one of the following approaches: --- +### Security events aren't reaching NGINX Instance Manager + +F5 WAF for NGINX generates security events, but they don't appear in the NGINX Instance Manager Security Monitoring dashboard, even though the `WAFPolicy` resource shows `Programmed`. + +**How to identify the problem:** + +Check whether the event reached NGINX Agent inside the pod: + +```shell +kubectl exec -n -c nginx -- \ + tail -100 /var/log/nginx-agent/opentelemetry-collector-agent.log +``` + +If the event isn't in this log, F5 WAF for NGINX isn't reaching NGINX Agent. If the event is in the log but not in NGINX Instance Manager, the export from NGINX Agent is failing. + +**Resolution:** + +- **Event missing from the NGINX Agent log:** Confirm the `WAFPolicy` `securityLogs.destination.syslog.server` field is set to exactly `localhost:1514`. Any other value prevents the event from reaching NGINX Agent, which listens on `127.0.0.1:1514` inside the `nginx` container. +- **Event in the log but export fails:** Check the log for `Unauthenticated` errors. A JWT authentication failure between NGINX Agent and NGINX Instance Manager causes this error. +- **Export succeeds but NGINX Instance Manager shows nothing:** Confirm NGINX Instance Manager's embedded OpenTelemetry collector is running and reachable on port `4317`. See [Troubleshooting]({{< ref "/nim/security-monitoring/troubleshooting.md" >}}) for the NGINX Instance Manager–side checks. + +--- + ## See also - [F5 WAF for NGINX overview]({{< ref "/ngf/waf-integration/overview.md" >}}) diff --git a/content/nim/security-monitoring/ngf-security-events.md b/content/nim/security-monitoring/ngf-security-events.md new file mode 100644 index 000000000..bff3d801d --- /dev/null +++ b/content/nim/security-monitoring/ngf-security-events.md @@ -0,0 +1,50 @@ +--- +title: View NGINX Gateway Fabric security events +weight: 150 +toc: true +f5-content-type: concept +f5-product: NGINX Instance Manager +f5-docs: +description: "View F5 WAF security events from NGINX Gateway Fabric deployments in F5 NGINX Instance Manager's Security Dashboard." +f5-summary: > + View F5 WAF security events from NGINX Gateway Fabric deployments in F5 NGINX Instance Manager's Security Dashboard. + NGINX Gateway Fabric's NGINX Agent v3 exports security events directly to NGINX Instance Manager, giving you unified event visibility alongside F5 NGINX Ingress Controller. +--- + +## Overview + +F5 NGINX Instance Manager shows F5 WAF security events from NGINX Gateway Fabric deployments in the **Security Dashboard**. NGINX Gateway Fabric's NGINX Agent v3 includes a built-in OpenTelemetry collector that exports security events directly to NGINX Instance Manager. You don't need NGINX Agent v2 to see F5 WAF activity on your NGINX Gateway Fabric instances. + +You can view: + +- F5 WAF security violations +- Bot detection events +- Policy violations +- Attack patterns +- Security event history + +{{< call-out class="important" title="Important: Event visibility only" >}} +This integration covers security event visibility only. NGINX Instance Manager can't manage NGINX Gateway Fabric instances, instance groups, or F5 WAF policy deployments. F5 plans to add full NGINX Agent v3 support for these capabilities in a future release. +{{< /call-out >}} + +## Requirements + +- NGINX Instance Manager 2.23 or later +- NGINX Gateway Fabric running F5 WAF for NGINX with NGINX Agent v3 +- Security Monitoring turned on in NGINX Instance Manager + +## Set up event export from NGINX Gateway Fabric + +NGINX Gateway Fabric generates and exports security events. NGINX Instance Manager doesn't pull or request them. Configure the export on the NGINX Gateway Fabric side. + +See [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}). + +## View events in the dashboard + +Go to **WAF** > **Security Dashboard** in NGINX Instance Manager. + +## See also + +- [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}) +- [Add user access to Security Monitoring dashboards]({{< ref "/nim/security-monitoring/give-access-to-security-monitoring-dashboards.md" >}}) +- [Troubleshooting]({{< ref "/nim/security-monitoring/troubleshooting.md" >}}) \ No newline at end of file diff --git a/content/nim/security-monitoring/troubleshooting.md b/content/nim/security-monitoring/troubleshooting.md index 8ca527d98..6684c4b41 100644 --- a/content/nim/security-monitoring/troubleshooting.md +++ b/content/nim/security-monitoring/troubleshooting.md @@ -43,6 +43,37 @@ F5 WAF for NGINX supports logging to multiple destinations. You can send logs to --- +## NGINX Gateway Fabric security events don't appear in the dashboard + +### Description + +If NGINX Instance Manager doesn't receive security events from a NGINX Gateway Fabric deployment, the Security Monitoring dashboard shows no data for that deployment. + +### Resolution + +Check the following on NGINX Instance Manager, in order: + +1. Confirm the embedded OpenTelemetry collector is turned on. In `nms.conf`, verify `collector_config.enable` is set to `true`: + + ```yaml + collector_config: + enable: true + ``` + + If you change this setting, restart the service: + + ```shell + sudo systemctl restart nms + ``` + +2. Confirm NGINX Instance Manager is reachable from the Kubernetes cluster on port `4317` (gRPC). + +3. Confirm the log profile referenced in the `WAFPolicy` resource exists in NGINX Instance Manager and matches exactly. A mismatched or missing profile name causes events to arrive without expected fields, or not arrive at all. + +If these checks pass and events still don't appear, the problem is likely on the NGINX Gateway Fabric side. See [Security events aren't reaching NGINX Instance Manager]({{< ref "/ngf/waf-integration/troubleshooting.md#security-events-arent-reaching-nginx-instance-manager" >}}) and [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}). + +--- + ## How to get support {{< include "nim/support/how-to-get-support.md" >}} From 1cddade3a234573f1987b211e8ad265c1dac71a8 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Fri, 28 Aug 2026 14:03:19 -0700 Subject: [PATCH 03/19] edits to ngf-security-events.md --- content/nim/security-monitoring/ngf-security-events.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/content/nim/security-monitoring/ngf-security-events.md b/content/nim/security-monitoring/ngf-security-events.md index bff3d801d..c400561fb 100644 --- a/content/nim/security-monitoring/ngf-security-events.md +++ b/content/nim/security-monitoring/ngf-security-events.md @@ -37,11 +37,17 @@ This integration covers security event visibility only. NGINX Instance Manager c NGINX Gateway Fabric generates and exports security events. NGINX Instance Manager doesn't pull or request them. Configure the export on the NGINX Gateway Fabric side. +This integration doesn't require changes to Gateway API resources. + See [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}). ## View events in the dashboard -Go to **WAF** > **Security Dashboard** in NGINX Instance Manager. +Go to **WAF** > **Security Dashboard** in NGINX Instance Manager. The dashboard has four tabs: Main, Bots, Advanced, and Event Logs. These tabs cover aggregate attack statistics, bot activity, signature and threat detail, and individual events. + +Use **Event Logs** for individual event details, including source IP, URI, and Support ID. + +You can filter events across all four tabs by fields including instance, instance group, IP address, policy, signature, severity, and Support ID. ## See also From c229d86ae173ae278c05dc213e0c28bbbb61844b Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Mon, 31 Aug 2026 10:03:54 -0700 Subject: [PATCH 04/19] edits, updates to tech spec guide --- content/nim/fundamentals/tech-specs.md | 190 ++++++++++-------- .../view-recent-usage.md | 108 +++++++--- 2 files changed, 188 insertions(+), 110 deletions(-) diff --git a/content/nim/fundamentals/tech-specs.md b/content/nim/fundamentals/tech-specs.md index af40df16e..ff9f1db90 100644 --- a/content/nim/fundamentals/tech-specs.md +++ b/content/nim/fundamentals/tech-specs.md @@ -1,11 +1,11 @@ --- f5-docs: DOCS-805 -title: Technical Specifications +title: Technical specifications toc: true weight: 20 f5-content-type: reference f5-product: NGINX Instance Manager -description: "Technical specifications for F5 NGINX Instance Manager, including supported operating systems, Kubernetes distributions, NGINX versions, browsers, and hardware requirements." +description: "Technical specifications for F5 NGINX Instance Manager. Covers supported operating systems, Kubernetes distributions, NGINX versions, browsers, and hardware requirements." f5-summary: > Check the technical specifications for F5 NGINX Instance Manager before you install it. This reference lists supported operating systems, Kubernetes distributions, NGINX versions, browsers, and hardware requirements. @@ -13,7 +13,9 @@ f5-summary: > ## Overview -F5 NGINX Instance Manager provides centralized management for NGINX Open Source and NGINX Plus instances across various environments, including bare metal, containers, public clouds (AWS, Azure, Google Cloud), and virtual machines. It supports several Linux distributions, including Amazon Linux, CentOS, Debian, RHEL, and Ubuntu. This guide outlines the technical specifications, minimum requirements, and supported platforms for deploying NGINX Instance Manager, ensuring optimal performance in both small and large environments. +F5 NGINX Instance Manager provides centralized management for NGINX Open Source and NGINX Plus instances. Supported environments are bare metal, containers, public clouds, and virtual machines. Supported public clouds are AWS, Microsoft Azure, and Google Cloud Platform. NGINX Instance Manager supports several Linux distributions: Amazon Linux, CentOS, Debian, RHEL, and Ubuntu. + +This guide outlines the technical specifications, minimum requirements, and supported platforms for NGINX Instance Manager deployments. These specifications help you achieve optimal performance in small and large environments. ## Supported deployment environments {#supported-environments} @@ -24,42 +26,42 @@ You can deploy NGINX Instance Manager in the following environments: - **Public cloud**: AWS, Google Cloud Platform, Microsoft Azure - **Virtual machine** -## Supported Linux Distributions {#supported-distributions} +## Supported Linux distributions {#supported-distributions} {{< include "nim/tech-specs/supported-distros.md" >}} ## Supported NGINX Instance Manager versions {#supported-nginx-instance-manager-versions} -We recommend using the latest version of NGINX Instance Manager to take advantage of the newest features, improvements, and security fixes. +F5 recommends the latest version of NGINX Instance Manager. It includes the newest features, improvements, and security fixes. [Technical support](https://www.f5.com/support) is available for the current release and for any version released within two years of the current version's release date. -Use the table below to check the end-of-support (EoS) dates for recent versions. +The following table shows end-of-support (EoS) dates for recent versions. -| NGINX Instance Manager | End of Support (EoS) | -|------------------------|----------------------| -| 2.22.x | April 27, 2028 | -| 2.21.x | November 07, 2027 | -| 2.20.x | June 16, 2027 | -| 2.19.x | February 06, 2027 | -| 2.18.x | November 08, 2026 | -| 2.17.x | July 10, 2026 | -| 2.16.x | April 18, 2026 | -| 2.15.x | December 12, 2025 | +| NGINX Instance Manager | End of support (EoS) | +|------------------------|-----------------------| +| 2.22.x | April 27, 2028 | +| 2.21.x | November 07, 2027 | +| 2.20.x | June 16, 2027 | +| 2.19.x | February 06, 2027 | +| 2.18.x | November 08, 2026 | +| 2.17.x | July 10, 2026 | +| 2.16.x | April 18, 2026 | +| 2.15.x | December 12, 2025 | -## Supported NGINX Versions {#nginx-versions} +## Supported NGINX versions {#nginx-versions} {{< include "nim/tech-specs/supported-nginx-versions.md" >}} -## Sizing recommendations for Managing NGINX Instances {#system-sizing} +## Sizing recommendations for managing NGINX instances {#system-sizing} -The following recommendations provide the minimum guidelines for NGINX Instance Manager. These guidelines ensure adequate performance, but for optimal results, we strongly recommend using solid-state drives (SSDs) for storage. If you set up [deployments with F5 WAF for NGINX](#system-sizing-app-protect), you may need additional memory and CPU. +The following recommendations are minimum guidelines for NGINX Instance Manager. For optimal results, F5 recommends solid-state drives (SSDs) for storage. If you set up [deployments with F5 WAF for NGINX](#system-sizing-app-protect), you may need additional memory and CPU. ### Standard NGINX configuration deployments -This section outlines the recommendations for NGINX Instance Manager deployments with data plane instances using standard configurations, without F5 WAF for NGINX. **Standard configurations** typically support up to **40 upstream servers** with associated location and server blocks, and up to **350 certificates**. This is ideal for medium-sized environments or applications with moderate traffic. +This section outlines recommendations for NGINX Instance Manager deployments with data plane instances that use standard configurations, without F5 WAF for NGINX. Standard configurations typically support up to 40 upstream servers with associated location and server blocks, and up to 350 certificates. This fits medium-sized environments or applications with moderate traffic. -We recommend using SSDs to enhance storage performance. +F5 recommends SSDs to improve storage performance. {{}} | Number of Data Plane Instances | CPU | Memory | Network | Storage | @@ -69,11 +71,11 @@ We recommend using SSDs to enhance storage performance. | 1000 | 4 vCPU | 8 GB RAM | 1 GbE NIC | 3 TB | {{
}} -These values represent the minimum resources needed for deployments that fall under standard configurations. +These values are the minimum resources for deployments under standard configurations. ### Large NGINX configuration deployments -For environments requiring more resources, **large configurations** are suitable. These configurations can support up to **300 upstream servers** and are designed for enterprise environments or applications handling high traffic and complex configurations, without F5 WAF for NGINX. +For environments that need more resources, large configurations are suitable. These configurations can support up to 300 upstream servers. They're designed for enterprise environments or applications that handle high traffic and complex configurations, without F5 WAF for NGINX. {{}} | Number of Data Plane Instances | CPU | Memory | Network | Storage | @@ -84,107 +86,127 @@ For environments requiring more resources, **large configurations** are suitable ### NGINX configuration deployments with F5 WAF for NGINX {#system-sizing-app-protect} -If using F5 WAF for NGINX features in NGINX Instance Manager, this requires additional CPU and Memory for policy compilation and security monitoring features. At a minimum, 8gb Memory and 4 CPUs are required for a standard F5 WAF for NGINX use case (under 20 NGINX Plus instances). The requirements are heavily dependent on the number of policies being managed, the frequency of updates and the number of events being that occur in the security monitoring feature. +If you use F5 WAF for NGINX features in NGINX Instance Manager, you need additional CPU and memory for policy compilation and security monitoring. A standard F5 WAF for NGINX use case (under 20 NGINX Plus instances) requires a minimum of 8 GB of memory and 4 CPUs. + +Requirements depend on the number of policies you manage, how often you update them, and how many events occur in the security monitoring feature. ### Lightweight mode {#lightweight-mode} -(New in 2.20.0) You can run NGINX Instance Manager without installing ClickHouse. This setup is useful if you don’t need monitoring data or prefer a simpler deployment. It reduces system requirements and removes the need to manage a metrics database. You can add ClickHouse later if your needs change. For instructions, see [Disable metrics collection]({{< ref "nim/system-configuration/configure-clickhouse.md#disable-metrics-collection" >}}). +(New in 2.20.0) You can run NGINX Instance Manager without ClickHouse. If you don't need monitoring data or want a simpler deployment, use this setup. It reduces system requirements and removes the need to manage a metrics database. If your needs change, you can add ClickHouse later. For instructions, see [Disable metrics collection]({{< ref "nim/system-configuration/configure-clickhouse.md#disable-metrics-collection" >}}). + +F5 tested Lightweight mode with ten managed NGINX instances and configuration publishing. Without F5 WAF for NGINX, it ran with as little as 1 CPU core and 1 GB of memory. With F5 WAF for NGINX enabled, NGINX Instance Manager needed 2 CPU cores and 4 GB of memory to compile policies. -In Lightweight mode, we tested NGINX Instance Manager with ten managed NGINX instances and configuration publishing. It ran with as little as 1 CPU core and 1 GB of memory (without App Protect). When App Protect was enabled, we needed 2 CPU cores and 4 GB of memory to compile policies. +These figures reflect the minimum tested configuration. If you experience performance issues, allocate more system resources. -These figures are guidelines only. They reflect the minimum tested configuration and may cause performance issues depending on your setup. For better performance, consider allocating more system resources. +{{< call-out class="note" title="Note: Raw usage record storage" >}} +These figures don't include storage or memory for raw usage records. If your NGINX Plus instances report usage data, see [Configure the retention window]({{< ref "nim/licensing-and-reporting/view-recent-nginx-usage.md#configure-the-retention-window" >}}) for sizing guidance based on your instance count and retention period. +{{< /call-out >}} ### License and usage reporting only {#reporting-sizing} -This section applies when you’ve set up NGINX Instance Manager to handle licensing and usage reporting only. In this setup, NGINX instances report license and usage data in an "unmanaged" way. Each instance sends periodic updates to NGINX Instance Manager for counting purposes only. +This section applies when you use NGINX Instance Manager only for licensing and usage reporting. In this setup, NGINX instances report license and usage data in an "unmanaged" way. Each instance sends periodic updates to NGINX Instance Manager for counting purposes only. For details on how to configure this setup, see [Prepare your environment for reporting]({{< ref "/solutions/about-subscription-licenses.md#set-up-environment" >}}). -When used only for licensing and usage reporting, NGINX Instance Manager has minimal system requirements. We recommend using [Lightweight mode](#lightweight-mode) in this case to avoid the ClickHouse dependency, especially if you don’t plan to use other features. +If you use NGINX Instance Manager only for licensing and usage reporting, it needs minimal CPU and network resources. Regardless of fleet size, this means 2 vCPU and a 1 GbE NIC. F5 recommends [Lightweight mode](#lightweight-mode) for this case, to avoid the ClickHouse dependency, especially if you don't plan to use other features. + +Memory and storage depend on your instance count and the retention period you configure for raw usage records, from 0 to 365 days (120-day default). The following table shows estimates at the default 120-day retention and the maximum 365-day (1-year) retention. These figures assume NGINX Plus's default cadence of one usage report per instance per hour. {{
}} -| Number of Data Plane Instances | CPU | Memory | Network | Storage | -|--------------------------------|--------|----------|-----------|---------| -| n/a | 2 vCPU | 4 GB RAM | 1 GbE NIC | 20 GB | +| Instances | 120-day storage | 120-day working memory | 1-year storage | 1-year working memory | +|-----------|------------------|--------------------------|------------------|--------------------------| +| 50 | ~0.13 GB | ~2.4 GB | ~0.4 GB | ~2.9 GB | +| 100 | ~0.26 GB | ~2.6 GB | ~0.8 GB | ~3.5 GB | +| 500 | ~1.3 GB | ~4.2 GB | ~4.0 GB | ~8.3 GB | +| 800 | ~2.1 GB | ~5.4 GB | ~6.3 GB | ~11.7 GB | +| 1,000 | ~2.6 GB | ~6.2 GB | ~7.9 GB | ~14.1 GB | {{
}} +{{< call-out class="note" title="Note: Tested range" >}} +NGINX Instance Manager's scale testing for 1-year retention covered up to 800 instances. The 1,000-instance figures in this table extrapolate beyond that tested point. +{{< /call-out >}} + +For retention periods between 120 days and 1 year, memory and storage scale roughly linearly with the number of days you configure. See [Estimate storage for extended retention]({{< ref "nim/licensing-and-reporting/view-recent-nginx-usage.md#estimate-storage-for-extended-retention" >}}) for host-sizing guidance and the per-record storage model behind these figures. + ### Sizing benchmarks for storage -The following benchmarks focus on **disk storage** requirements for NGINX Instance Manager. Storage needs depend on the **number of instances** and **data retention periods** (in days). The benchmarks are divided into three configuration sizes: +The following benchmarks focus on disk storage requirements for NGINX Instance Manager. Storage needs depend on the number of instances and data retention periods (in days). These benchmarks group into three configuration sizes: -- **Small configuration**: Typically supports about **15 servers**, **50 locations**, and **30 upstreams/backends**. Each instance generates **3,439 metrics per minute**. -- **Medium configuration**: Usually includes about **50 servers**, **200 locations**, and **200 upstreams/backends**. Each instance generates **16,766 metrics per minute**. -- **Generic Large configuration**: Handles up to **100 servers**, **1,000 locations**, and **900 upstreams/backends**. In **NGINX Plus**, each instance generates **59,484 metrics per minute**. +- **Small configuration**: Supports about 15 servers, 50 locations, and 30 upstreams or backends. Each instance generates 3,439 metrics per minute. +- **Medium configuration**: Includes about 50 servers, 200 locations, and 200 upstreams or backends. Each instance generates 16,766 metrics per minute. +- **Generic large configuration**: Handles up to 100 servers, 1,000 locations, and 900 upstreams or backends. In NGINX Plus, each instance generates 59,484 metrics per minute. #### Storage requirements for NGINX Plus -The table below provides storage estimates for **NGINX Plus** based on configuration size, number of instances, and a 14-day data retention period. Larger configurations and longer retention periods will require proportionally more storage. +The following table provides storage estimates for NGINX Plus, based on configuration size, instance count, and a 14-day data retention period. Larger configurations and longer retention periods will require proportionally more storage. {{}} -| Config Size | Instances | Retention (days) | Estimated Disk Usage (NGINX Plus) | -|------------------------|-----------|------------------|-----------------------------------| -| **Small Size** | 10 | 14 | 5 GiB | -| | 50 | 14 | 25 GiB | -| | 100 | 14 | 45 GiB | -| | 1000 | 14 | 450 GiB | -| **Medium Size** | 10 | 14 | 25 GiB | -| | 50 | 14 | 126 GiB | -| | 100 | 14 | 251 GiB | -| | 500 | 14 | 1.157 TiB | -| **Generic Large Size** | 10 | 14 | 100 GiB | -| | 50 | 14 | 426 GiB | -| | 100 | 14 | 850 GiB | -| | 250 | 14 | 2 TiB | +| Config size | Instances | Retention (days) | Estimated disk usage (NGINX Plus) | +|------------------------|-----------|-------------------|------------------------------------| +| **Small size** | 10 | 14 | 5 GiB | +| | 50 | 14 | 25 GiB | +| | 100 | 14 | 45 GiB | +| | 1000 | 14 | 450 GiB | +| **Medium size** | 10 | 14 | 25 GiB | +| | 50 | 14 | 126 GiB | +| | 100 | 14 | 251 GiB | +| | 500 | 14 | 1.157 TiB | +| **Generic large size** | 10 | 14 | 100 GiB | +| | 50 | 14 | 426 GiB | +| | 100 | 14 | 850 GiB | +| | 250 | 14 | 2 TiB | {{
}} -{{< call-out class="note" title="Note" >}}MiB (mebibyte), GiB (gibibyte), and TiB (tebibyte) are units of data storage. MiB equals 1,024^2 (2^20) bytes, GiB equals 1,024^3 (2^30) bytes, and TiB equals 1,024^4 (2^40) bytes. These are often used in computing to represent binary data storage capacities, as opposed to MB (megabyte), GB (gigabyte), and TB (terabyte), which use decimal units.{{< /call-out >}} +{{< call-out class="note" title="Note" >}} +MiB (mebibyte), GiB (gibibyte), and TiB (tebibyte) measure data storage in binary units: MiB equals 1,024² (2²⁰) bytes, GiB equals 1,024³ (2³⁰) bytes, and TiB equals 1,024⁴ (2⁴⁰) bytes. MB (megabyte), GB (gigabyte), and TB (terabyte) measure storage in decimal units instead. +{{< /call-out >}} -#### Storage requirements for NGINX OSS +#### Storage requirements for NGINX Open Source -**NGINX OSS** collects fewer metrics per instance compared to NGINX Plus. This is because NGINX OSS lacks the advanced features of NGINX Plus, such as the NGINX Plus API, which limits the amount of operational data collected and stored. For example, in the **Generic Large configuration**, NGINX OSS generates only **167 metrics per minute per instance**, compared to **59,484 metrics per minute** in NGINX Plus. +NGINX Open Source collects fewer metrics per instance than NGINX Plus. This is because NGINX Open Source lacks advanced features such as the NGINX Plus API, which limits the operational data it collects and stores. For example, in the generic large configuration, NGINX Open Source generates only 167 metrics per minute per instance, compared to 59,484 metrics per minute in NGINX Plus. -The table below shows the estimated storage requirements for **NGINX OSS**, based on the number of instances and a 14-day retention period. +The following table shows estimated storage requirements for NGINX Open Source, based on instance count and a 14-day retention period. {{}} -| Config Size | Instances | Retention (days) | Estimated Disk Usage (NGINX OSS) | -|------------------------|-----------|------------------|----------------------------------| -| **Generic Large Size** | 10 | 14 | 200 MiB | -| | 50 | 14 | 850 MiB | -| | 100 | 14 | 1.75 GiB | -| | 250 | 14 | 4 GiB | +| Config size | Instances | Retention (days) | Estimated disk usage (NGINX Open Source) | +|------------------------|-----------|-------------------|--------------------------------------------| +| **Generic large size** | 10 | 14 | 200 MiB | +| | 50 | 14 | 850 MiB | +| | 100 | 14 | 1.75 GiB | +| | 250 | 14 | 4 GiB | {{
}} -## Directory Requirements for NGINX Instance Manager +## Directory requirements for NGINX Instance Manager -Below are the directory requirements and storage recommendations for fresh, minimal, and moderate usage (<100 instances) of NGINX Instance Manager (NIM). +The following directory requirements and storage recommendations apply to fresh, minimal, and moderate NGINX Instance Manager deployments (under 100 instances). {{< call-out class="important" >}} -These recommendations apply if you are using NGINX Agent to connect NGINX instances to NIM for full management capabilities, including: +These recommendations apply if you use NGINX Agent to connect NGINX instances to NGINX Instance Manager for full management capabilities: -- Managing configurations -- Viewing metrics -- Applying WAF policies -- Managing certificates +- Manage configurations +- View metrics +- Apply F5 WAF for NGINX policies +- Manage certificates -If you're concerned solely on usage reporting, you do not need NGINX Agent. Required resources needed are significantly reduced. For usage reporting-only deployments, NIM receives and stores usage data sent directly from the instances. +If you're interested only in usage reporting, you don't need NGINX Agent. Usage reporting needs significantly fewer resources. For usage-reporting-only deployments, NGINX Instance Manager receives and stores usage data sent directly from the instances. {{< /call-out >}} {{}} -| Directory path | Content | Recommendation | -|------------------------|-------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------| -| /usr/bin | Stores NIM binaries | 500MB | -| /var/lib/nms/dqlite | Stores DQLite database data | 2GiB without F5 WAF for NGINX; 5GiB with F5 WAF for NGINX enabled and large compiled bundles | -| /var/lib/nms/streaming | Stores NATS streaming messages | 500MiB | -| /var/lib/nms/secrets | Stores secrets for LLM license handshakes | 10MiB | -| /var/lib/nms/modules | Stores static content like manager.json | 100KiB (12KiB minimum) | -| /var/lib/clickhouse | Stores ClickHouse metrics data | recommend 2.5GB per instance (25GB for 10 instances, 250GB for 100 instances). This is only required if ClickHouse metrics are enabled | -| /var/log/nms | Stores logs for NIM with rotation enabled | recommended 50MiB per week if archived once a month | -| /etc/nms/ | Stores NIM configuration files | 50MiB | -| /etc/nginx | Stores NGINX configuration files | typical size is 10MiB-50MiB | +| Directory path | Content | Recommendation | +|------------------------|---------------------------------------------|-----------------------------------------------------------------------------------------------| +| /usr/bin | Stores NGINX Instance Manager binaries | 500 MB | +| /var/lib/nms/dqlite | Stores DQLite database data | 2 GiB without F5 WAF for NGINX. 5 GiB with F5 WAF for NGINX enabled and large compiled bundles. | +| /var/lib/nms/streaming | Stores NATS streaming messages | 500 MiB | +| /var/lib/nms/secrets | Stores secrets for LLM license handshakes | 10 MiB | +| /var/lib/nms/modules | Stores static content like manager.json | 100 KiB (12 KiB minimum) | +| /var/lib/clickhouse | Stores ClickHouse metrics data | Recommended: 2.5 GB per instance (25 GB for 10 instances, 250 GB for 100 instances). This applies only if you enable ClickHouse metrics. | +| /var/log/nms | Stores NGINX Instance Manager logs with rotation enabled | Recommended: 50 MiB per week if you archive logs once a month. | +| /etc/nms/ | Stores NGINX Instance Manager configuration files | 50 MiB | +| /etc/nginx | Stores NGINX configuration files | Typical size is 10-50 MiB. | {{
}} ## ClickHouse tuning {#clickhouse-tuning} @@ -195,13 +217,13 @@ The default ClickHouse configuration works efficiently with NGINX Instance Manag NGINX Instance Manager and NGINX Agent use the Unix domain socket by default and proxy through the gateway on port `443`. -To ensure smooth communication, make sure port 443 is open on any firewalls between NGINX Instance Manager, NGINX Agent, and other systems they need to communicate with. This allows secure HTTPS traffic to pass through. +Make sure port 443 is open on any firewalls between NGINX Instance Manager, NGINX Agent, and the systems they communicate with. Port 443 carries secure HTTPS traffic between these systems. ## Logging {#logging} -NGINX Instance Manager stores its log files in `/var/log/nms`. To prevent your system from running out of disk space as logs grow, we recommend either creating a separate partition for logs or enabling [log rotation](http://nginx.org/en/docs/control.html#logs). +NGINX Instance Manager stores its log files in `/var/log/nms`. As logs grow, your system can run out of disk space. To prevent this, create a separate log partition, or enable [log rotation](http://nginx.org/en/docs/control.html#logs). -## Supported Browsers {#supported-browsers} +## Supported browsers {#supported-browsers} The NGINX Instance Manager web interface works best on the latest versions of these browsers: @@ -218,4 +240,4 @@ The NGINX Instance Manager web interface works best on the latest versions of th ### Data plane requirements -- **Supported distributions**: The NGINX Agent can run on most environments. For the supported distributions, see the [NGINX Agent Technical Specs](https://docs.nginx.com/nginx-agent/technical-specifications/) guide. +- **Supported distributions**: NGINX Agent can run on most environments. For the supported distributions, see the [NGINX Agent technical specifications](https://docs.nginx.com/nginx-agent/technical-specifications/) guide. \ No newline at end of file diff --git a/content/nim/licensing-and-reporting/view-recent-usage.md b/content/nim/licensing-and-reporting/view-recent-usage.md index 39eb5a37d..3e5b10135 100644 --- a/content/nim/licensing-and-reporting/view-recent-usage.md +++ b/content/nim/licensing-and-reporting/view-recent-usage.md @@ -28,8 +28,8 @@ This screen doesn't require NGINX Agent. Your instances report usage data direct The screen has two views: -- **Instances**: Shows records from standalone NGINX Plus instances running on VMs or bare metal. -- **Clusters**: Shows records from NGINX deployments running in Kubernetes, including NGINX Ingress Controller and NGINX Gateway Fabric. +- **Instances**: Shows records from standalone NGINX Plus instances that run on VMs or bare metal. +- **Clusters**: Shows records from NGINX deployments that run in Kubernetes. This covers NGINX Ingress Controller and NGINX Gateway Fabric. By default, the screen shows the last 7 days of records, sorted by end time with the most recent first. Records are available for the last 120 days by default. You can change this retention window. See [Configure the retention window](#configure-the-retention-window). @@ -41,7 +41,7 @@ Before you view usage records, make sure you have: - **NGINX Plus R33 or later**: NGINX Plus R33 and later include the `ngx_mgmt_module` module. Earlier versions can't report usage to NGINX Instance Manager. - **NGINX Plus configured to report usage**: Each NGINX Plus instance needs the `usage_report` directive set to your NGINX Instance Manager host. See [Configure NGINX Plus to report usage to NGINX Instance Manager]({{< ref "nim/licensing-and-reporting/report-usage-connected-deployment.md#configure-nginx-plus-to-report-usage-to-nginx-instance-manager" >}}). -- **The NGINX Plus Usage permission**: Your user account needs this RBAC permission to view usage records in the dashboard or through the API. +- **The NGINX Plus Usage permission**: Your user account needs this role-based access control (RBAC) permission to view usage records in the dashboard or through the API. --- @@ -52,13 +52,14 @@ Before you view usage records, make sure you have: To view raw usage records: 1. Log in to NGINX Instance Manager (`https:///ui/`). -2. In the left navigation, select **Usage**, then select **Recent Usage**. -3. Select the **Instances** or **Clusters** tab. +2. In the left navigation, select **Usage**. +3. Select **Recent Usage**. +4. Select the **Instances** or **Clusters** tab. By default, the dashboard shows records from the last 7 days, sorted by end time with the most recent first. {{< call-out class="note" title="Note: Fields not shown in the table" >}} -The dashboard's summary table does not display every field from a usage record — for example, reporting start time. Select a row to view the full record, including fields not shown as table columns. +The dashboard's summary table doesn't show every field from a usage record. For example, it doesn't show the reporting start time. Select a row to view the full record and see every field. {{< /call-out >}} ### View record details @@ -87,16 +88,16 @@ If you don't already have the identifiers used in these filters: - **Cluster ID**: Visible in the **K8s Cluster ID** column on the Clusters tab. NGINX Ingress Controller and NGINX Gateway Fabric generate this ID at installation and store it in the deployment's Kubernetes secret. - **Subscription token (jti)**: A claim inside your subscription JWT (`license.jwt`). Paste the JWT contents into [jwt.io](https://jwt.io) and look for the `jti` field. You can also find it in the **JWT ID** column. -### Export records as CSV +### Export usage records to a file -To export usage records for offline auditing or compliance: +To export usage records for an offline review or compliance check: 1. Apply the filters you need. 2. Select **Export CSV**. -The CSV file downloads with all records matching your current filters. Field values in the export match the raw stored data exactly, with no rounding or aggregation. +The exported file downloads in CSV (comma-separated values) format. It includes all records matching your current filters, with no rounding or aggregation. -(Optional) If the export is slow, apply additional filters to narrow the result set before exporting. +(Optional) If the export is slow, apply additional filters to narrow the result set before you export. The following table lists which columns appear in each tab's CSV export. @@ -122,7 +123,7 @@ The following table lists which columns appear in each tab's CSV export. {{}} {{< call-out class="note" title="Note: If your export is truncated" >}} -See [CSV export produces a truncated file](#csv-export-produces-a-truncated-file). +See [An exported file is truncated](#an-exported-file-is-truncated). {{< /call-out >}} --- @@ -155,31 +156,85 @@ To change the retention period: sudo systemctl restart nms ``` +A retention change takes effect after this restart. Because the purge job runs immediately on startup, records outside the new window are removed right away, not on the next scheduled 24-hour cycle. + {{< call-out class="important" title="Important: Retention value limits" >}} -NGINX Instance Manager normalizes retention values on startup. It caps any value above 365 to 365 and ignores negative values, falling back to the default (120 days) instead. A value of 0 blocks local storage: NGINX Instance Manager doesn't write new records and purges existing records on the next run. This doesn't affect usage reporting to F5. +NGINX Instance Manager normalizes retention values on startup. It caps any value above 365 to 365. It ignores negative values and uses the default (120 days) instead. A value of 0 blocks local storage: NGINX Instance Manager doesn't write new records and purges existing records on the next run. This doesn't affect usage reporting to F5. {{< /call-out >}} If NGINX Instance Manager clamps or rejects your configured value, it logs a `[RAW-USAGE]` warning so you can confirm the value wasn't used as entered. ### Estimate storage for extended retention -{{< call-out class="important" title="Important: Content pending" >}} -Blocked on storage-size-per-instance figures from engineering (TECHDOCS-5506 open items, and the companion tech-specs.md ticket). Do not publish this page until this subsection is filled in — the story explicitly calls for covering 4–12 month retention, and customers extending retention need this to plan disk capacity. +Storage and memory scale with your instance count and configured retention period. Each usage record takes about 0.9 KB on disk. This includes its database index. + +The following table shows estimated storage and working memory at two retention periods: the default 120 days, and the maximum 365 days (1 year). These figures assume NGINX Plus's default cadence of one usage report per instance per hour. + +{{}} +| Instances | 120-day storage | 120-day working memory | 1-year storage | 1-year working memory | +|---|---|---|---|---| +| 50 | ~0.13 GB | ~2.4 GB | ~0.4 GB | ~2.9 GB | +| 100 | ~0.26 GB | ~2.6 GB | ~0.8 GB | ~3.5 GB | +| 500 | ~1.3 GB | ~4.2 GB | ~4.0 GB | ~8.3 GB | +| 800 | ~2.1 GB | ~5.4 GB | ~6.3 GB | ~11.7 GB | +| 1,000 | ~2.6 GB | ~6.2 GB | ~7.9 GB | ~14.1 GB | +{{
}} + +{{< call-out class="note" title="Note: Tested range" >}} +NGINX Instance Manager's scale testing for 1-year retention covered up to 800 instances (about 7 million records). The 1,000-instance figures in this table extrapolate beyond that tested point. {{< /call-out >}} -Storage usage grows with the number of NGINX instances reporting and the length of your retention window. Each instance generates approximately one record per hour. +For retention periods between 120 days and 1 year, storage and working memory scale roughly linearly with the number of days you configure. If you halve your retention period, you roughly halve both storage and memory. + +To size a host: + +- **Memory**: Provision enough RAM to cover the working memory estimate for your fleet size and retention period. Size by RAM, not by a specific vendor instance type. +- **Disk**: Budget headroom beyond the storage estimate for database indexes, snapshots, write-ahead logs, and NGINX Instance Manager's other services. For large fleets at extended retention, budget tens of GB of SSD storage. +- **Alternative to over-provisioning**: Lower `nginx_raw_usage_retention_days` rather than add more host resources. If you reduce retention, you shrink stored data and memory use proportionally. This doesn't affect usage reporting to F5. - +This sizing applies even in Lightweight mode. NGINX Instance Manager stores usage records independently of ClickHouse. As a result, instance count and retention affect your storage needs, even in deployments used only for licensing and usage reporting. --- -## Validate a record from the CLI +## Validate a record from the command line -{{< call-out class="important" title="Important: Content pending" >}} -Blocked on CLI validation commands from engineering (Kamal Chaturvedi or Amardeep Chawla — TECHDOCS-5506 open items). The runbook's REST API list/filter examples are a reasonable starting point, but the ticket specifically calls for validating a record's Cluster ID and nginx_uid for Kubernetes deployments, which needs a worked example we don't have — for example, confirming a cluster's ID from a running NGINX Gateway Fabric deployment and cross-checking it against a record returned by the API. -{{< /call-out >}} +Use the REST API to retrieve usage records and confirm the identifiers in a specific record. All endpoints are available at `/api/platform/v1/usage-records`. + +### Retrieve records for a specific instance or cluster - +Query by `nginxUid` to retrieve every record for a specific NGINX Plus instance: + +```shell +curl -k -u : \ + "https:///api/platform/v1/usage-records?deploymentType=vm&nginxUid=" +``` + +Query by `clusterId` to retrieve every record for a specific Kubernetes cluster: + +```shell +curl -k -u : \ + "https:///api/platform/v1/usage-records?deploymentType=cluster&clusterId=" +``` + +### What each identifier means + +{{}} +| Field | Description | Where it comes from | Applies to | +|---|---|---|---| +| `nginx_uid` | UUID that uniquely identifies the NGINX Plus instance. | Generated by NGINX Plus. | All records | +| `product_type` | Integration type: `NGINX_PLUS`, `NIC`, `NGF`, or `UNSPECIFIED`. | Reported by the instance. | All records | +| `jwt_token_id` | The `jti` claim of the F5 subscription token the instance uses for reporting. | Derived from the F5 subscription token. | Records with subscription metadata | +| `jwt_expiration` | Subscription end date from the F5 subscription token. | Derived from the F5 subscription token. | Records with subscription metadata | +| `cluster_id` | UUID of the Kubernetes cluster where the instance runs. | Provided by NGINX Ingress Controller or NGINX Gateway Fabric. | Kubernetes records | +| `installation_id` | UUID identifying an individual NGINX Ingress Controller or NGINX Gateway Fabric installation. | Provided by NGINX Ingress Controller or NGINX Gateway Fabric. | Kubernetes records | +| `cluster_node_count` | Number of nodes in the Kubernetes cluster. | Provided by NGINX Ingress Controller or NGINX Gateway Fabric. | Kubernetes records | +{{
}} + +NGINX Instance Manager stores and displays these values exactly as your instances report them. It doesn't generate or modify them. + +{{< call-out class="note" title="Note: To confirm an identifier on a running instance" >}} +This page shows you how to view identifiers as NGINX Instance Manager received them. To independently confirm a value like Cluster ID directly on a running Kubernetes deployment, see the NGINX Ingress Controller or NGINX Gateway Fabric documentation for that identifier. +{{< /call-out >}} --- @@ -188,7 +243,7 @@ Blocked on CLI validation commands from engineering (Kamal Chaturvedi or Amardee {{}} | Field | Description | |---|---| -| NGINX Instance ID | UUID identifying the NGINX instance. | +| NGINX Instance ID | UUID that identifies the NGINX instance. | | Product type | NGINX Plus, NGINX Ingress Controller, NGINX Gateway Fabric, or Unspecified. | | NGINX version | The NGINX version string, for example `1.29.8`. | | Reporting window | Start and end timestamps of the reporting period. | @@ -220,7 +275,7 @@ The **Recent Usage** screen is a local, on-demand audit view. It's different fro | Where to configure | This page | [Report usage data to F5 (connected)]({{< ref "nim/licensing-and-reporting/report-usage-connected-deployment.md" >}}) or [Report usage data to F5 (disconnected)]({{< ref "nim/licensing-and-reporting/report-usage-disconnected-deployment.md" >}}) | {{
}} -Viewing or exporting records on this screen doesn't affect usage reporting to F5. The two pipelines operate independently. +When you view or export records on this screen, usage reporting to F5 doesn't change. The two pipelines operate independently. This screen works the same way in connected and disconnected deployments. Your instances keep reporting locally, and existing records stay fully browsable, even without internet access. @@ -241,13 +296,13 @@ This screen works the same way in connected and disconnected deployments. Your i **Fix**: Confirm the `usage_report` directive is set in the `mgmt` block of your NGINX Plus configuration. Confirm your NGINX Plus version is R33 or later. Expand the date range or reset it to the default (last 7 days). Confirm your RBAC role includes the NGINX Plus Usage permission. -### CSV export produces a truncated file +### An exported file is truncated **Symptom**: The exported CSV file appears incomplete. **Cause**: The CSV export streams data directly from the server. A dropped connection during the export leaves the file incomplete. -**Fix**: Re-export the file. Use narrower date filters to reduce the export size if your connection is slow or unreliable. +**Fix**: Re-export the file. If your connection is slow or unreliable, use narrower date filters to reduce the export size. ### A record's reporting window spans more than one hour @@ -271,4 +326,5 @@ This screen works the same way in connected and disconnected deployments. Your i - [Report usage data to F5 (connected)]({{< ref "nim/licensing-and-reporting/report-usage-connected-deployment.md" >}}) - [Report usage data to F5 (disconnected)]({{< ref "nim/licensing-and-reporting/report-usage-disconnected-deployment.md" >}}) -- [Change telemetry settings]({{< ref "nim/licensing-and-reporting/change-telemetry-settings.md" >}}) \ No newline at end of file +- [Change telemetry settings]({{< ref "nim/licensing-and-reporting/change-telemetry-settings.md" >}}) +- [System requirements for licensing and usage reporting only]({{< ref "nim/fundamentals/tech-specs.md#reporting-sizing" >}}) \ No newline at end of file From 472219513870aa5507040aa584907b7f2d321e1b Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Mon, 31 Aug 2026 10:48:27 -0700 Subject: [PATCH 05/19] expanded LLM acronym --- content/nim/fundamentals/tech-specs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/nim/fundamentals/tech-specs.md b/content/nim/fundamentals/tech-specs.md index ff9f1db90..9b2a47c98 100644 --- a/content/nim/fundamentals/tech-specs.md +++ b/content/nim/fundamentals/tech-specs.md @@ -201,7 +201,7 @@ If you're interested only in usage reporting, you don't need NGINX Agent. Usage | /usr/bin | Stores NGINX Instance Manager binaries | 500 MB | | /var/lib/nms/dqlite | Stores DQLite database data | 2 GiB without F5 WAF for NGINX. 5 GiB with F5 WAF for NGINX enabled and large compiled bundles. | | /var/lib/nms/streaming | Stores NATS streaming messages | 500 MiB | -| /var/lib/nms/secrets | Stores secrets for LLM license handshakes | 10 MiB | +| /var/lib/nms/secrets | Stores secrets for LLM (Local License Manager) license handshakes | 10 MiB | | /var/lib/nms/modules | Stores static content like manager.json | 100 KiB (12 KiB minimum) | | /var/lib/clickhouse | Stores ClickHouse metrics data | Recommended: 2.5 GB per instance (25 GB for 10 instances, 250 GB for 100 instances). This applies only if you enable ClickHouse metrics. | | /var/log/nms | Stores NGINX Instance Manager logs with rotation enabled | Recommended: 50 MiB per week if you archive logs once a month. | From 3959c067f93d166cd591740ba90c489b3f1f33da Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Tue, 1 Sep 2026 10:22:07 -0700 Subject: [PATCH 06/19] added connect-ngf.md topic, copy edits to touched topics. --- content/ngf/waf-integration/policy-sources.md | 44 +++++---- content/nim/connect-kubernetes/_index.md | 11 +++ content/nim/connect-kubernetes/connect-ngf.md | 94 +++++++++++++++++++ .../ngf-security-events.md | 4 +- 4 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 content/nim/connect-kubernetes/_index.md create mode 100644 content/nim/connect-kubernetes/connect-ngf.md diff --git a/content/ngf/waf-integration/policy-sources.md b/content/ngf/waf-integration/policy-sources.md index fcc0cc650..57acf5147 100644 --- a/content/ngf/waf-integration/policy-sources.md +++ b/content/ngf/waf-integration/policy-sources.md @@ -4,12 +4,12 @@ weight: 300 toc: true f5-content-type: how-to f5-product: NGINX Gateway Fabric -f5-description: Configure WAFPolicy to fetch compiled bundles from F5 NGINX Instance Manager, F5 NGINX One Console, or an HTTP server. +description: Configure WAFPolicy to fetch compiled bundles from F5 NGINX Instance Manager, F5 NGINX One Console, or an HTTP server. --- F5 NGINX Gateway Fabric supports three policy source types for fetching compiled F5 WAF bundles: F5 NGINX Instance Manager, F5 NGINX One Console, and direct HTTP/HTTPS URLs. For a quick start walkthrough using the HTTP source, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started.md" >}}). -Before configuring a policy source, make sure F5 WAF is enabled on the NginxProxy, either per Gateway or globally via Helm values. For version requirements, see [Technical specifications]({{< ref "/ngf/overview/technical-specifications.md" >}}). +Before you configure a policy source, make sure F5 WAF is turned on for the NginxProxy — either per Gateway or globally through Helm values. For version requirements, see [Technical specifications]({{< ref "/ngf/overview/technical-specifications.md" >}}). {{< call-out class="tip" title="Tip: Fetch retry behavior" >}} By default, NGINX Gateway Fabric retries transient fetch failures up to 3 times with exponential backoff, and each fetch attempt times out after 30 seconds. You can tune these using the `retryAttempts` and `timeout` fields on `policySource` or `logSource`. {{< /call-out >}} @@ -21,7 +21,7 @@ Use this option when you manage F5 WAF policies through F5 NGINX Instance Manage **Workflow:** -1. Author and compile a policy in NGINX Instance Manager using the NGINX Instance Manager console or API. Verify that compilation succeeded before proceeding. NGINX Gateway Fabric cannot detect compilation failures in NGINX Instance Manager. +1. Author and compile a policy in NGINX Instance Manager using the NGINX Instance Manager console or API. Verify that compilation succeeded. NGINX Gateway Fabric can't detect compilation failures in NGINX Instance Manager. 2. Create a Secret with your NGINX Instance Manager credentials. 3. Create a `WAFPolicy` referencing the compiled policy by name. @@ -92,9 +92,9 @@ EOF Replace `https://nim.example.com` with your NGINX Instance Manager base URL, and `ngfBlocking` with your compiled policy name. -{{< call-out class="tip" title="Tip: Testing with self-signed certificates" >}} To skip TLS certificate verification when fetching bundles (for testing only - not recommended for production), uncomment 'insecureSkipVerify: true'. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Testing with self-signed certificates" >}} To skip TLS certificate verification when fetching bundles, uncomment `insecureSkipVerify: true`. Don't use this in production. {{< /call-out >}} -{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, use `policyUID` instead of `policyName`. Find the UID in the NGINX Instance Manager console or API. A pinned UID always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, use `policyUID` instead of `policyName`. Find the UID in the NGINX Instance Manager console or API. A pinned UID always resolves to the same compiled bundle. Turn off polling to avoid unnecessary network requests. {{< /call-out >}} ### Apply a route-level override (optional) @@ -141,8 +141,8 @@ Use this option when you manage F5 WAF policies through F5 NGINX One Console. Fo **Workflow:** -1. Author and compile a policy in the NGINX One Console console or API. -2. If no compiled bundle exists yet, NGINX Gateway Fabric triggers compilation through the NGINX One Console API. This happens the first time NGINX Gateway Fabric reconciles the `WAFPolicy` resource. NGINX Gateway Fabric waits for compilation to finish before continuing. +1. Author and compile a policy in the NGINX One Console or API. +2. If no compiled bundle exists yet, NGINX Gateway Fabric triggers compilation through the NGINX One Console API the first time it reconciles the `WAFPolicy` resource. NGINX Gateway Fabric waits for compilation to finish. 3. Create a Secret with your NGINX One Console API token. 4. Create a `WAFPolicy` referencing the compiled policy. @@ -205,7 +205,7 @@ EOF Replace `` with your NGINX One Console tenant hostname. The `namespace` field refers to the NGINX One Console namespace where the policy resides. -{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, set `policyVersionID`. A pinned version always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. If you use only `policyName` or `policyObjectID` without a version pin, the latest compiled bundle is fetched on each reconciliation or poll cycle. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, set `policyVersionID`. A pinned version always resolves to the same compiled bundle. Turn off polling to avoid unnecessary network requests. If you use only `policyName` or `policyObjectID` without a version pin, NGINX Gateway Fabric fetches the latest compiled bundle on each reconciliation or poll cycle. {{< /call-out >}} --- @@ -219,7 +219,7 @@ In production environments, host compiled bundles on an HTTPS server with authen --- -## Console integration +## Policy deployment visibility NGINX Instance Manager and NGINX One Console don't show which F5 WAF policies are deployed to NGINX Gateway Fabric. Neither console shows which compiled bundle version NGINX Gateway Fabric has fetched. @@ -227,15 +227,25 @@ This is intentional. NGINX Gateway Fabric pulls compiled bundles from the manage F5 plans to add policy association visibility for NGINX Instance Manager and NGINX One Console in a future release. In the meantime, use `kubectl describe wafpolicy ` to check deployment status. -### Export security logs to F5 NGINX Instance Manager +--- + +## Security event monitoring + +### NGINX Instance Manager + +#### Connect NGINX Gateway Fabric to F5 NGINX Instance Manager -F5 NGINX Instance Manager's Security Monitoring dashboard doesn't show which policies you've deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to NGINX Instance Manager. Exporting these events gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the dashboard. +Configure NGINX Gateway Fabric to connect to NGINX Instance Manager before continuing. Follow [Connect NGINX Gateway Fabric to NGINX Instance Manager]({{< ref "/nim/connect-kubernetes/connect-ngf.md" >}}). + +#### Export security logs to F5 NGINX Instance Manager + +The Security Monitoring dashboard in NGINX Instance Manager doesn't show which F5 WAF policies are deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to NGINX Instance Manager. Exporting these events gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the dashboard. {{< call-out class="important" title="Important: Version requirement" >}} This integration requires NGINX Instance Manager 2.23 or later. {{< /call-out >}} -To export these events, configure a `securityLogs` entry on the `WAFPolicy` resource. This entry sends events to the syslog listener NGINX Agent runs inside the NGINX pod. NGINX Agent's built-in OpenTelemetry collector transforms the events and exports them to NGINX Instance Manager. +To export these events, configure a `securityLogs` entry on the `WAFPolicy` resource. The entry sends events to the syslog listener that NGINX Agent runs inside the NGINX pod. NGINX Agent's built-in OpenTelemetry collector transforms the events and exports them to NGINX Instance Manager. ```yaml kubectl apply -f - <}}) for adding CA certificates and credentials. {{< /call-out >}} -### Connect NGINX Gateway Fabric to F5 NGINX One Console +### NGINX One Console + +#### Connect NGINX Gateway Fabric to F5 NGINX One Console Configure NGINX Gateway Fabric to connect to NGINX One Console before continuing. Follow [Connect NGINX Gateway Fabric with Helm]({{< ref "/nginx-one-console/k8s/add-ngf-helm.md" >}}) or [Connect NGINX Gateway Fabric with Manifests]({{< ref "/nginx-one-console/k8s/add-ngf-manifests.md" >}}). -### Export security logs to F5 NGINX One Console +#### Export security logs to F5 NGINX One Console -NGINX One Console doesn't show which policies are deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to the NGINX One Console security dashboard. This gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the console. +NGINX One Console doesn't show which F5 WAF policies are deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to the NGINX One Console security dashboard. Your security operations team can then view blocked attacks, violations, and traffic patterns directly in the console. To export these events, configure a `securityLogs` entry that sends events to NGINX Agent's built-in OpenTelemetry collector, which forwards them to NGINX One Console. Use a log profile compiled for the NGINX One Console security dashboard: @@ -329,7 +341,7 @@ EOF The `localhost:1514` syslog destination points to NGINX Agent's OpenTelemetry collector, which runs as a sidecar in the NGINX pod. NGINX Agent forwards the security events to NGINX One Console, where they appear in the security monitoring dashboard. -{{< call-out class="note" title="Note: Log profile must exist in NGINX One Console" >}} The `profileName: "secops_dashboard"` log profile must exist in your NGINX One Console namespace. This profile is required for events to appear correctly in the NGINX One Console security dashboard. {{< /call-out >}} +{{< call-out class="note" title="Note: Log profile must exist in NGINX One Console" >}} The `profileName: "secops_dashboard"` log profile must exist in your NGINX One Console namespace. Events don't appear correctly in the NGINX One Console security dashboard without this profile. {{< /call-out >}} --- diff --git a/content/nim/connect-kubernetes/_index.md b/content/nim/connect-kubernetes/_index.md new file mode 100644 index 000000000..84120bace --- /dev/null +++ b/content/nim/connect-kubernetes/_index.md @@ -0,0 +1,11 @@ +--- +title: Connect Kubernetes deployments +weight: 85 +url: /nginx-instance-manager/connect-kubernetes/ +f5-product: NGINX Instance Manager +f5-content-type: landing-page +description: "Connect Kubernetes-based NGINX deployments, such as NGINX Gateway Fabric, to F5 NGINX Instance Manager." +f5-summary: > + Connect Kubernetes-based NGINX deployments to F5 NGINX Instance Manager. + This section covers connecting NGINX Gateway Fabric for usage and licensing reporting. +--- \ No newline at end of file diff --git a/content/nim/connect-kubernetes/connect-ngf.md b/content/nim/connect-kubernetes/connect-ngf.md new file mode 100644 index 000000000..e6b47635a --- /dev/null +++ b/content/nim/connect-kubernetes/connect-ngf.md @@ -0,0 +1,94 @@ +--- +title: Connect NGINX Gateway Fabric to NGINX Instance Manager +weight: 100 +toc: true +f5-content-type: how-to +f5-product: NGINX Instance Manager +f5-docs: +description: "Connect NGINX Gateway Fabric to F5 NGINX Instance Manager to export F5 WAF security events to the Security Dashboard." +f5-summary: > + Connect NGINX Gateway Fabric to F5 NGINX Instance Manager to set up the control plane connection NGINX Gateway Fabric uses to export F5 WAF security events to NGINX Instance Manager. + This page covers the NGINX Plus JWT, the Secret for the NGINX Instance Manager dataplane key, and the Helm values needed to point NGINX Gateway Fabric at your NGINX Instance Manager deployment. +--- + + + +## Overview + +Connect NGINX Gateway Fabric to NGINX Instance Manager to set up the control plane connection required for NGINX Gateway Fabric to export F5 WAF security events to the NGINX Instance Manager Security Dashboard. + +--- + +## Before you begin + +Before you begin, verify that you have: + +- Administrator access to a Kubernetes cluster +- Helm and kubectl installed locally +- An NGINX Plus subscription + +--- + +## Download your NGINX Plus JWT + +{{< include "/ngf/installation/nginx-plus/download-jwt.md" >}} + +--- + +## Create the NGINX Plus Secret + +{{< include "/ngf/installation/nginx-plus/nginx-plus-secret.md" >}} + +This Secret is required to run NGINX Plus, with or without F5 WAF for NGINX. + +--- + +## Create the NGINX Instance Manager dataplane key Secret + + + +Rename your NGINX Plus JWT file to `dataplane.key`, then create a Secret from it: + +```shell +cp license.jwt dataplane.key +kubectl create secret generic nim-dp-key --from-file=dataplane.key -n nginx-gateway +rm dataplane.key +``` + +This creates a Secret named `nim-dp-key` in the `nginx-gateway` namespace. The Secret contains your NGINX Plus JWT under the required `dataplane.key` filename. The Secret name and filename are fixed. NGINX Gateway Fabric expects the key to be named `dataplane.key` inside the Secret. + +--- + +## Install Gateway API resources + +{{< include "/ngf/installation/install-gateway-api-resources.md" >}} + +--- + +## Install NGINX Gateway Fabric + + + +This integration requires NGINX Plus with F5 WAF for NGINX. There is only one supported install path. + +```shell +helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ + --set nginx.image.repository=private-registry.nginx.com/nginx-gateway-fabric/nginx-plus \ + --set nginx.plus=true \ + --set nginx.config.waf.enable=true \ + --set nginx.imagePullSecret=nginx-plus-registry-secret \ + --set nginx.usage.secretName=nplus-license \ + --set nginx.nginxInstanceManager.dataplaneKeySecretName=nim-dp-key \ + --set nginx.nginxInstanceManager.endpointHost= \ + -n nginx-gateway +``` + +Replace `` with your NGINX Instance Manager hostname. + +--- + +## See also + +- [Deploy a Gateway for data plane instances]({{< ref "/ngf/install/deploy-data-plane.md" >}}) +- [Configure policy sources]({{< ref "/ngf/waf-integration/policy-sources.md" >}}) +- [View NGINX Gateway Fabric security events]({{< ref "/nim/security-monitoring/ngf-security-events.md" >}}) \ No newline at end of file diff --git a/content/nim/security-monitoring/ngf-security-events.md b/content/nim/security-monitoring/ngf-security-events.md index c400561fb..f79c9316e 100644 --- a/content/nim/security-monitoring/ngf-security-events.md +++ b/content/nim/security-monitoring/ngf-security-events.md @@ -30,8 +30,8 @@ This integration covers security event visibility only. NGINX Instance Manager c ## Requirements - NGINX Instance Manager 2.23 or later -- NGINX Gateway Fabric running F5 WAF for NGINX with NGINX Agent v3 -- Security Monitoring turned on in NGINX Instance Manager +- NGINX Gateway Fabric running F5 WAF for NGINX with NGINX Agent v3, connected to NGINX Instance Manager. See [Connect NGINX Gateway Fabric to NGINX Instance Manager]({{< ref "/nim/connect-kubernetes/connect-ngf.md" >}}). +- Security Monitoring turned on in NGINX Instance Manager ## Set up event export from NGINX Gateway Fabric From e01ae7c109df3a0508e64a29a41c47ffc6fb3654 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Tue, 1 Sep 2026 10:52:40 -0700 Subject: [PATCH 07/19] edits --- content/ngf/waf-integration/policy-sources.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/content/ngf/waf-integration/policy-sources.md b/content/ngf/waf-integration/policy-sources.md index 57acf5147..c1de88a5a 100644 --- a/content/ngf/waf-integration/policy-sources.md +++ b/content/ngf/waf-integration/policy-sources.md @@ -281,10 +281,11 @@ spec: EOF ``` -The `localhost:1514` syslog destination points to NGINX Agent's OpenTelemetry collector, which runs as a sidecar in the NGINX pod. NGINX Agent exports the security events to NGINX Instance Manager over gRPC on port `4317`, authenticated with a JWT. +The `localhost:1514` syslog destination points to NGINX Agent's OpenTelemetry collector, which runs as a sidecar in the NGINX pod. NGINX Agent exports the security events to NGINX Instance Manager over gRPC on port `4317`, authenticated using the same NGINX Plus JWT referenced in the `nim-dp-key` Secret from [Connect NGINX Gateway Fabric to NGINX Instance Manager]({{< ref "/nim/connect-kubernetes/connect-ngf.md" >}}). NGINX Gateway Fabric handles this authentication internally — no separate credential is required for log export. -{{< call-out class="note" title="Note: Log profile must exist in NGINX Instance Manager" >}} -The `profileName: "secops_dashboard_ngf_otel"` log profile must exist in NGINX Instance Manager and match the `WAFPolicy` exactly. +{{< call-out class="note" title="Note: Network requirements" >}} +- Port `1514` (local syslog): NGINX Agent listens on this port inside the NGINX pod. This traffic doesn't leave the pod. +- Port `4317` (gRPC): NGINX Agent uses this port to export events to NGINX Instance Manager. Make sure this port is reachable from your cluster. {{< /call-out >}} {{< call-out class="tip" title="Tip: Testing with self-signed certificates" >}} From b397cecc4a24f623abf115da6ad6d114bf9e2860 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Tue, 1 Sep 2026 10:56:13 -0700 Subject: [PATCH 08/19] edits --- content/ngf/waf-integration/troubleshooting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/ngf/waf-integration/troubleshooting.md b/content/ngf/waf-integration/troubleshooting.md index 9966555a7..47f70f669 100644 --- a/content/ngf/waf-integration/troubleshooting.md +++ b/content/ngf/waf-integration/troubleshooting.md @@ -123,7 +123,7 @@ If the event isn't in this log, F5 WAF for NGINX isn't reaching NGINX Agent. If **Resolution:** - **Event missing from the NGINX Agent log:** Confirm the `WAFPolicy` `securityLogs.destination.syslog.server` field is set to exactly `localhost:1514`. Any other value prevents the event from reaching NGINX Agent, which listens on `127.0.0.1:1514` inside the `nginx` container. -- **Event in the log but export fails:** Check the log for `Unauthenticated` errors. A JWT authentication failure between NGINX Agent and NGINX Instance Manager causes this error. +- **Event in the log but export fails:** Check the log for `Unauthenticated` errors. A JWT authentication failure between NGINX Agent and NGINX Instance Manager causes this error. This is the same NGINX Plus subscription JWT used to create the `nim-dp-key` Secret in [Connect NGINX Gateway Fabric to NGINX Instance Manager]({{< ref "/nim/connect-kubernetes/connect-ngf.md" >}}). If the JWT has expired or was revoked, download a new one from [MyF5](https://my.f5.com/manage/s/) and repeat the steps to recreate the `nim-dp-key` Secret. - **Export succeeds but NGINX Instance Manager shows nothing:** Confirm NGINX Instance Manager's embedded OpenTelemetry collector is running and reachable on port `4317`. See [Troubleshooting]({{< ref "/nim/security-monitoring/troubleshooting.md" >}}) for the NGINX Instance Manager–side checks. --- From 2604f679faaded701140062280011d056d853efd Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Tue, 1 Sep 2026 13:17:05 -0700 Subject: [PATCH 09/19] docs(TECHDOCS-5505): address shaun-nx review on connect-ngf.md - Confirm connection scope is security event export only, not F5 WAF policy fetching; state this explicitly in the Overview and remove the now-resolved SME REVIEW comment that flagged it as unconfirmed - Remove the "Create the NGINX Instance Manager dataplane key Secret" section; NGINX Gateway Fabric now reuses the existing nplus-license Secret instead of a separate nim-dp-key Secret - Simplify the Helm install command accordingly: drop --set nginx.nginxInstanceManager.dataplaneKeySecretName=nim-dp-key - Note in "Create the NGINX Plus Secret" that this Secret now also authenticates the NGINX Gateway Fabric to NGINX Instance Manager connection, since it's doing that job in addition to its original purpose - Update f5-summary to match: drop the dataplane-key reference, align first sentence with the Overview's wording - Remove the two pending-change SME REVIEW comments that existed to flag this exact update as outstanding Resolves all three review comments from shaun-nx on PR #316. --- content/nim/connect-kubernetes/connect-ngf.md | 33 ++++--------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/content/nim/connect-kubernetes/connect-ngf.md b/content/nim/connect-kubernetes/connect-ngf.md index e6b47635a..2b3d81c95 100644 --- a/content/nim/connect-kubernetes/connect-ngf.md +++ b/content/nim/connect-kubernetes/connect-ngf.md @@ -7,15 +7,15 @@ f5-product: NGINX Instance Manager f5-docs: description: "Connect NGINX Gateway Fabric to F5 NGINX Instance Manager to export F5 WAF security events to the Security Dashboard." f5-summary: > - Connect NGINX Gateway Fabric to F5 NGINX Instance Manager to set up the control plane connection NGINX Gateway Fabric uses to export F5 WAF security events to NGINX Instance Manager. - This page covers the NGINX Plus JWT, the Secret for the NGINX Instance Manager dataplane key, and the Helm values needed to point NGINX Gateway Fabric at your NGINX Instance Manager deployment. + Connect NGINX Gateway Fabric to F5 NGINX Instance Manager to export F5 WAF security events to the Security Dashboard. + This page covers the NGINX Plus JWT, the NGINX Plus Secret, and the Helm values required to configure the connection. --- - - ## Overview -Connect NGINX Gateway Fabric to NGINX Instance Manager to set up the control plane connection required for NGINX Gateway Fabric to export F5 WAF security events to the NGINX Instance Manager Security Dashboard. +Connect NGINX Gateway Fabric to NGINX Instance Manager to export F5 WAF security events to the Security Dashboard. + +This connection supports security event export only. F5 WAF policy fetching uses a separate credential flow. See [Configure policy sources]({{< ref "/ngf/waf-integration/policy-sources.md" >}}). --- @@ -39,23 +39,7 @@ Before you begin, verify that you have: {{< include "/ngf/installation/nginx-plus/nginx-plus-secret.md" >}} -This Secret is required to run NGINX Plus, with or without F5 WAF for NGINX. - ---- - -## Create the NGINX Instance Manager dataplane key Secret - - - -Rename your NGINX Plus JWT file to `dataplane.key`, then create a Secret from it: - -```shell -cp license.jwt dataplane.key -kubectl create secret generic nim-dp-key --from-file=dataplane.key -n nginx-gateway -rm dataplane.key -``` - -This creates a Secret named `nim-dp-key` in the `nginx-gateway` namespace. The Secret contains your NGINX Plus JWT under the required `dataplane.key` filename. The Secret name and filename are fixed. NGINX Gateway Fabric expects the key to be named `dataplane.key` inside the Secret. +This Secret is required to run NGINX Plus, with or without F5 WAF for NGINX. It also authenticates the connection from NGINX Gateway Fabric to NGINX Instance Manager. --- @@ -67,9 +51,7 @@ This creates a Secret named `nim-dp-key` in the `nginx-gateway` namespace. The S ## Install NGINX Gateway Fabric - - -This integration requires NGINX Plus with F5 WAF for NGINX. There is only one supported install path. +This integration requires NGINX Plus with F5 WAF for NGINX. Install NGINX Gateway Fabric using the following Helm command: ```shell helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ @@ -78,7 +60,6 @@ helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ --set nginx.config.waf.enable=true \ --set nginx.imagePullSecret=nginx-plus-registry-secret \ --set nginx.usage.secretName=nplus-license \ - --set nginx.nginxInstanceManager.dataplaneKeySecretName=nim-dp-key \ --set nginx.nginxInstanceManager.endpointHost= \ -n nginx-gateway ``` From fe7a1a77c01ebe4375e993be7435d3f7540f64dd Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Tue, 1 Sep 2026 14:43:02 -0700 Subject: [PATCH 10/19] edits --- .../view-recent-usage.md | 63 +++++++++---------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/content/nim/licensing-and-reporting/view-recent-usage.md b/content/nim/licensing-and-reporting/view-recent-usage.md index 3e5b10135..c45a4877f 100644 --- a/content/nim/licensing-and-reporting/view-recent-usage.md +++ b/content/nim/licensing-and-reporting/view-recent-usage.md @@ -13,25 +13,25 @@ f5-content-type: how-to f5-product: NGINX Instance Manager f5-summary: > View and export raw, unaggregated NGINX usage telemetry for NGINX Plus, NGINX Ingress Controller, and NGINX Gateway Fabric instances in NGINX Instance Manager. - This audit-grade record view lets you independently verify billing data and support compliance reviews, separately from the usage reports NGINX Instance Manager sends to F5. + Use this audit-grade record view to independently verify billing data and support compliance reviews, separately from the usage reports NGINX Instance Manager sends to F5. --- ## Overview -The **Recent Usage** screen shows the raw usage telemetry that F5 NGINX Instance Manager collects from your instances. This includes F5 NGINX Plus, F5 NGINX Ingress Controller, and F5 NGINX Gateway Fabric. +The **Usage Overview** page shows the raw usage telemetry that F5 NGINX Instance Manager collects from your instances. This includes F5 NGINX Plus, F5 NGINX Ingress Controller, and F5 NGINX Gateway Fabric. NGINX Open Source instances don't appear in usage records. They don't include the `ngx_mgmt_module` that NGINX Plus uses to report usage. -Each row is one telemetry record, exactly as your instance reported it. NGINX Instance Manager doesn't aggregate or transform records. Use this screen to independently verify the data behind your F5 billing and to support compliance audits. +Each row is one telemetry record, exactly as your instance reported it. NGINX Instance Manager doesn't aggregate or transform records. Use this page to independently verify the data behind your F5 billing and to support compliance audits. -This screen doesn't require NGINX Agent. Your instances report usage data directly. +NGINX Agent isn't required. Your instances send usage data directly to NGINX Instance Manager. -### Instances and Clusters views +### Instances and Clusters tabs -The screen has two views: +The page has two tabs: - **Instances**: Shows records from standalone NGINX Plus instances that run on VMs or bare metal. -- **Clusters**: Shows records from NGINX deployments that run in Kubernetes. This covers NGINX Ingress Controller and NGINX Gateway Fabric. +- **Clusters**: Shows records from NGINX deployments that run in Kubernetes. This includes records from NGINX Ingress Controller and NGINX Gateway Fabric. -By default, the screen shows the last 7 days of records, sorted by end time with the most recent first. Records are available for the last 120 days by default. You can change this retention window. See [Configure the retention window](#configure-the-retention-window). +By default, the page shows the last 7 days of records, sorted by end time with the most recent first. NGINX Instance Manager keeps records for the last 120 days by default. You can change this retention period. See [Configure the retention period](#configure-the-retention-period). --- @@ -52,9 +52,8 @@ Before you view usage records, make sure you have: To view raw usage records: 1. Log in to NGINX Instance Manager (`https:///ui/`). -2. In the left navigation, select **Usage**. -3. Select **Recent Usage**. -4. Select the **Instances** or **Clusters** tab. +2. In the left navigation, select **Usage > Usage Overview**. +3. Select the **Instances** or **Clusters** tab. By default, the dashboard shows records from the last 7 days, sorted by end time with the most recent first. @@ -64,7 +63,7 @@ The dashboard's summary table doesn't show every field from a usage record. For ### View record details -Select a row to open a side panel showing all fields for that record. +Select a row to open a side panel that shows all fields for that record. ### Filter records @@ -84,7 +83,7 @@ Select **Add Filter** to narrow your results by: If you don't already have the identifiers used in these filters: -- **NGINX Instance ID**: NGINX Plus stores this in `/var/lib/nginx/nginx.id` on each instance. You can also find it in the **NGINX UID** column, or by selecting a row to open the detail panel. +- **NGINX Instance ID**: NGINX Plus stores this in `/var/lib/nginx/nginx.id` on each instance. You can also find it in the **NGINX UID** column or in the detail panel. - **Cluster ID**: Visible in the **K8s Cluster ID** column on the Clusters tab. NGINX Ingress Controller and NGINX Gateway Fabric generate this ID at installation and store it in the deployment's Kubernetes secret. - **Subscription token (jti)**: A claim inside your subscription JWT (`license.jwt`). Paste the JWT contents into [jwt.io](https://jwt.io) and look for the `jti` field. You can also find it in the **JWT ID** column. @@ -97,7 +96,7 @@ To export usage records for an offline review or compliance check: The exported file downloads in CSV (comma-separated values) format. It includes all records matching your current filters, with no rounding or aggregation. -(Optional) If the export is slow, apply additional filters to narrow the result set before you export. +If the export is slow, apply additional filters to narrow the result set before you export. The following table lists which columns appear in each tab's CSV export. @@ -128,7 +127,7 @@ See [An exported file is truncated](#an-exported-file-is-truncated). --- -## Configure the retention window +## Configure the retention period NGINX Instance Manager automatically removes usage records older than the configured retention period. A background job runs once at startup and then every 24 hours to purge expired records. @@ -145,30 +144,30 @@ To change the retention period: 1. Open `/etc/nms/nms.conf` on the NGINX Instance Manager server. 2. Add or update the setting under the `dpm:` block: - ```yaml - dpm: + ```yaml + dpm: nginx_raw_usage_retention_days: 180 - ``` + ``` 3. Restart NGINX Instance Manager: - ```shell - sudo systemctl restart nms - ``` + ```shell + sudo systemctl restart nms + ``` -A retention change takes effect after this restart. Because the purge job runs immediately on startup, records outside the new window are removed right away, not on the next scheduled 24-hour cycle. +A retention change takes effect after this restart. Because the purge job runs immediately on startup, it removes records outside the new window right away, not on the next scheduled 24-hour cycle. {{< call-out class="important" title="Important: Retention value limits" >}} NGINX Instance Manager normalizes retention values on startup. It caps any value above 365 to 365. It ignores negative values and uses the default (120 days) instead. A value of 0 blocks local storage: NGINX Instance Manager doesn't write new records and purges existing records on the next run. This doesn't affect usage reporting to F5. {{< /call-out >}} -If NGINX Instance Manager clamps or rejects your configured value, it logs a `[RAW-USAGE]` warning so you can confirm the value wasn't used as entered. +If NGINX Instance Manager clamps or rejects your configured value, it logs a `[RAW-USAGE]` warning so you know the configured value wasn't applied. ### Estimate storage for extended retention -Storage and memory scale with your instance count and configured retention period. Each usage record takes about 0.9 KB on disk. This includes its database index. +Storage and memory scale with your instance count and configured retention period. Each usage record takes about 0.9 KB on disk. This estimate includes the database index. -The following table shows estimated storage and working memory at two retention periods: the default 120 days, and the maximum 365 days (1 year). These figures assume NGINX Plus's default cadence of one usage report per instance per hour. +The following table shows estimated storage and working memory at two retention periods: the default 120 days, and the maximum 365 days (1 year). These figures assume the default NGINX Plus reporting cadence of one report per instance per hour. {{}} | Instances | 120-day storage | 120-day working memory | 1-year storage | 1-year working memory | @@ -181,7 +180,7 @@ The following table shows estimated storage and working memory at two retention {{
}} {{< call-out class="note" title="Note: Tested range" >}} -NGINX Instance Manager's scale testing for 1-year retention covered up to 800 instances (about 7 million records). The 1,000-instance figures in this table extrapolate beyond that tested point. +NGINX Instance Manager's scale testing for 1-year retention covered up to 800 instances. The 1,000-instance figures in this table extrapolate beyond that tested point. {{< /call-out >}} For retention periods between 120 days and 1 year, storage and working memory scale roughly linearly with the number of days you configure. If you halve your retention period, you roughly halve both storage and memory. @@ -264,10 +263,10 @@ Usage records contain only UUIDs, timestamps, and numeric counters. They don't i ## How this differs from usage reporting to F5 -The **Recent Usage** screen is a local, on-demand audit view. It's different from the usage reports NGINX Instance Manager automatically sends to F5 for billing. +The **Usage Overview** page is a local, on-demand audit view. It's different from the usage reports NGINX Instance Manager automatically sends to F5 for billing. {{}} -| | **Recent Usage** screen | Usage reporting to F5 | +| | **Usage Overview** page | Usage reporting to F5 | |---|---|---| | Purpose | Local audit and verification | Billing and entitlement | | Data | Raw, per-record, unaggregated | Aggregated for submission | @@ -275,9 +274,9 @@ The **Recent Usage** screen is a local, on-demand audit view. It's different fro | Where to configure | This page | [Report usage data to F5 (connected)]({{< ref "nim/licensing-and-reporting/report-usage-connected-deployment.md" >}}) or [Report usage data to F5 (disconnected)]({{< ref "nim/licensing-and-reporting/report-usage-disconnected-deployment.md" >}}) | {{
}} -When you view or export records on this screen, usage reporting to F5 doesn't change. The two pipelines operate independently. +When you view or export records on this page, usage reporting to F5 doesn't change. The two pipelines operate independently. -This screen works the same way in connected and disconnected deployments. Your instances keep reporting locally, and existing records stay fully browsable, even without internet access. +This page works the same way in connected and disconnected deployments. Your instances keep reporting locally, and existing records stay fully browsable, even without internet access. --- @@ -294,7 +293,7 @@ This screen works the same way in connected and disconnected deployments. Your i - The date range filter is too narrow. - Your account doesn't have the NGINX Plus Usage permission. -**Fix**: Confirm the `usage_report` directive is set in the `mgmt` block of your NGINX Plus configuration. Confirm your NGINX Plus version is R33 or later. Expand the date range or reset it to the default (last 7 days). Confirm your RBAC role includes the NGINX Plus Usage permission. +**Fix**: Make sure the `usage_report` directive is set in the `mgmt` block of your NGINX Plus configuration. Make sure your NGINX Plus version is R33 or later. Expand the date range or reset it to the default (last 7 days). Make sure your RBAC role includes the NGINX Plus Usage permission. ### An exported file is truncated @@ -308,7 +307,7 @@ This screen works the same way in connected and disconnected deployments. Your i **Symptom**: A record's reporting window is longer than expected, for example 09:00–11:00 instead of 09:00–10:00. -**Cause**: A previous report failed. NGINX Plus combined the missed window with the next scheduled report. This is expected behavior. It ensures no usage data is lost. +**Cause**: A previous report failed. NGINX Plus combined the missed window with the next scheduled report. This is expected behavior. No usage data is lost. **Fix**: No action needed. NGINX Instance Manager retains both the extended record and any partially persisted original record. From 278154b62fc5cae6540c2137cd6ead2320d9c090 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Tue, 1 Sep 2026 14:51:47 -0700 Subject: [PATCH 11/19] fixed broken links --- content/nim/fundamentals/tech-specs.md | 4 ++-- content/nim/licensing-and-reporting/view-recent-usage.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/nim/fundamentals/tech-specs.md b/content/nim/fundamentals/tech-specs.md index 9b2a47c98..12f78a9c7 100644 --- a/content/nim/fundamentals/tech-specs.md +++ b/content/nim/fundamentals/tech-specs.md @@ -99,7 +99,7 @@ F5 tested Lightweight mode with ten managed NGINX instances and configuration pu These figures reflect the minimum tested configuration. If you experience performance issues, allocate more system resources. {{< call-out class="note" title="Note: Raw usage record storage" >}} -These figures don't include storage or memory for raw usage records. If your NGINX Plus instances report usage data, see [Configure the retention window]({{< ref "nim/licensing-and-reporting/view-recent-nginx-usage.md#configure-the-retention-window" >}}) for sizing guidance based on your instance count and retention period. +These figures don't include storage or memory for raw usage records. If your NGINX Plus instances report usage data, see [Configure the retention window]({{< ref "nim/licensing-and-reporting/view-recent-usage.md#configure-the-retention-window" >}}) for sizing guidance based on your instance count and retention period. {{< /call-out >}} ### License and usage reporting only {#reporting-sizing} @@ -126,7 +126,7 @@ Memory and storage depend on your instance count and the retention period you co NGINX Instance Manager's scale testing for 1-year retention covered up to 800 instances. The 1,000-instance figures in this table extrapolate beyond that tested point. {{< /call-out >}} -For retention periods between 120 days and 1 year, memory and storage scale roughly linearly with the number of days you configure. See [Estimate storage for extended retention]({{< ref "nim/licensing-and-reporting/view-recent-nginx-usage.md#estimate-storage-for-extended-retention" >}}) for host-sizing guidance and the per-record storage model behind these figures. +For retention periods between 120 days and 1 year, memory and storage scale roughly linearly with the number of days you configure. See [Estimate storage for extended retention]({{< ref "nim/licensing-and-reporting/view-recent-usage.md#estimate-storage-for-extended-retention" >}}) for host-sizing guidance and the per-record storage model behind these figures. ### Sizing benchmarks for storage diff --git a/content/nim/licensing-and-reporting/view-recent-usage.md b/content/nim/licensing-and-reporting/view-recent-usage.md index c45a4877f..3180ef2e5 100644 --- a/content/nim/licensing-and-reporting/view-recent-usage.md +++ b/content/nim/licensing-and-reporting/view-recent-usage.md @@ -31,7 +31,7 @@ The page has two tabs: - **Instances**: Shows records from standalone NGINX Plus instances that run on VMs or bare metal. - **Clusters**: Shows records from NGINX deployments that run in Kubernetes. This includes records from NGINX Ingress Controller and NGINX Gateway Fabric. -By default, the page shows the last 7 days of records, sorted by end time with the most recent first. NGINX Instance Manager keeps records for the last 120 days by default. You can change this retention period. See [Configure the retention period](#configure-the-retention-period). +By default, the page shows the last 7 days of records, sorted by end time with the most recent first. NGINX Instance Manager keeps records for the last 120 days by default. You can change this retention period. See [Configure the retention window](#configure-the-retention-window). --- @@ -127,7 +127,7 @@ See [An exported file is truncated](#an-exported-file-is-truncated). --- -## Configure the retention period +## Configure the retention window NGINX Instance Manager automatically removes usage records older than the configured retention period. A background job runs once at startup and then every 24 hours to purge expired records. From 0cb3eb4e93d3959524083e537d984ade1b4d3b9b Mon Sep 17 00:00:00 2001 From: Travis Martin <33876974+travisamartin@users.noreply.github.com> Date: Wed, 2 Sep 2026 08:57:52 -0700 Subject: [PATCH 12/19] docs (TECHDOCS-5507): deploy NIM rootless Docker image (#317) --- .../docker/build-nim-rootless-docker-image.md | 291 +++++++++++++ .../deploy-nim-rootless-docker-compose.md | 405 ++++++++++++------ 2 files changed, 556 insertions(+), 140 deletions(-) create mode 100644 content/nim/deploy/docker/build-nim-rootless-docker-image.md diff --git a/content/nim/deploy/docker/build-nim-rootless-docker-image.md b/content/nim/deploy/docker/build-nim-rootless-docker-image.md new file mode 100644 index 000000000..a047c39f5 --- /dev/null +++ b/content/nim/deploy/docker/build-nim-rootless-docker-image.md @@ -0,0 +1,291 @@ +--- +description: Build your own rootless NGINX Instance Manager Docker image from source, for air-gapped environments or custom image requirements. +title: Build a custom rootless Docker image +toc: true +weight: 160 +f5-docs: +f5-content-type: how-to +f5-product: NGINX Instance Manager +f5-summary: > + Build your own rootless F5 NGINX Instance Manager Docker image from source using your NGINX + subscription certificate and key. Use this path if you can't pull images from an external + registry, or if you need to customize the image. +--- + + + +## Overview + +This guide shows you how to build your own rootless F5 NGINX Instance Manager Docker image from source and deploy it with Docker Compose. All container processes run as a non-root user (`nms`). This follows the principle of least privilege for production environments. + +{{< call-out class="note" title="Note: Most deployments don't need this" >}} If you can pull images from an external registry, use an [official F5-maintained image]({{< ref "nim/deploy/docker/deploy-nim-rootless-docker-compose.md" >}}) instead. It's faster to deploy, and F5 maintains it for you. If you can't pull third-party images into your environment, or you need to customize the image, build your own instead. {{< /call-out >}} + +A key capability of this deployment is runtime configuration injection. To change NGINX Instance Manager settings, edit the environment variable files and restart the stack. You don't need to rebuild the Docker image. + +This deployment has the following key characteristics: + +- Rootless by design. All processes run as `nms` (non-root). This reduces the attack surface and satisfies security hardening requirements. +- Runtime configuration. You change NGINX Instance Manager settings by updating `docker-compose/.env` and `docker-compose.yaml`. You don't need to rebuild the image. +- Production-hardened. Startup scripts are idempotent and avoid fragile patterns, such as recursive permission changes. +- Flexible licensing. This deployment supports both connected and disconnected license modes, switchable at runtime. + +--- + +## What you need + +Before you begin, make sure you have the following: + +- [Docker Engine](https://docs.docker.com/get-docker/) 20.10 or later installed on a Linux host (amd64 or arm64). +- [Docker Compose plugin](https://docs.docker.com/compose/install/) v2 or later. +- A valid NGINX Instance Manager license file, base64-encoded. +- An NGINX certificate and private key, required to download NGINX Instance Manager packages during image build. +- Basic familiarity with Docker Compose and YAML syntax. + +--- + +## Before you start + +Clone the deployment repository to your host machine: + +```shell +git clone https://github.com/nginx/nginx-demos.git +cd nginx-demos/nginx-instance-manager/docker-deployment +``` + +--- + +## Build the NGINX Instance Manager image + +Run the build script with your NGINX certificate, key, and a name for the resulting image: + +```shell +./build.sh -C -K -t +``` + +Replace the placeholders: + +- ``: Path to your NGINX TLS certificate file. +- ``: Path to your NGINX TLS private key file. +- ``: Your preferred Docker image tag, for example `nim:latest`. + +The build script downloads NGINX Instance Manager packages from the NGINX repository. It uses your certificate and key, and produces a self-contained rootless image. + +--- + +## Configure environment variables + +Edit `docker-compose/.env` and set the following values: + +```shell +NIM_IMAGE= +NIM_LICENSE= +NIM_USERNAME= +NIM_PASSWORD= +NIM_CLICKHOUSE_ADDRESSPORT=docker-compose-clickhouse-1:9000 +NIM_CLICKHOUSE_USERNAME= +NIM_CLICKHOUSE_PASSWORD= +NIM_LICENSE_MODE_OF_OPERATION=connected +``` + +Replace `` with the tag used in the build step, and `` with your base64-encoded NGINX Instance Manager license. Set `NIM_LICENSE_MODE_OF_OPERATION` to `connected` or `disconnected`, based on your environment. See [License modes](#license-modes). + +{{< call-out class="note" title="Note: Set production credentials" >}} Before you deploy to production, change `NIM_USERNAME` and `NIM_PASSWORD` to values appropriate for your environment. {{< /call-out >}} + +--- + +## Verify docker-compose.yaml environment mappings + +Open `docker-compose.yaml` and confirm that the `nim` service passes all required variables into the container: + +```yaml +environment: + - NIM_LICENSE=${NIM_LICENSE} + - NIM_USERNAME=${NIM_USERNAME} + - NIM_PASSWORD=${NIM_PASSWORD} + - NIM_CLICKHOUSE_ADDRESSPORT=${NIM_CLICKHOUSE_ADDRESSPORT} + - NIM_CLICKHOUSE_USERNAME=${NIM_CLICKHOUSE_USERNAME} + - NIM_CLICKHOUSE_PASSWORD=${NIM_CLICKHOUSE_PASSWORD} + - NIM_LICENSE_MODE_OF_OPERATION=${NIM_LICENSE_MODE_OF_OPERATION} +``` + +If you add new configuration variables later, add a corresponding line here to make the value available inside the container. + +--- + +## Start the stack + +Start NGINX Instance Manager and its dependencies (including ClickHouse) with: + +```shell +docker compose -f docker-compose.yaml up -d +``` + +--- + +## Access the NGINX Instance Manager web interface + +After the containers start, open a browser and go to: + +```text +https://localhost/ +``` + +If prompted, accept the self-signed TLS certificate warning. Log in with the `NIM_USERNAME` and `NIM_PASSWORD` values you set in `docker-compose/.env`. + +--- + +## How runtime configuration injection works + +When the NGINX Instance Manager container starts, `startNIM.sh` reads the environment variables that Docker Compose passes in. It writes their values into the NGINX Instance Manager configuration files with `yq`, a YAML processor. The two configuration files are: + +- `/etc/nms/nms.conf` +- `/etc/nms/nms-sm-conf.yaml` + +This means NGINX Instance Manager applies fresh configuration on every container start. To change a setting, update the variable in `docker-compose/.env` and restart the stack. You don't need to rebuild the image. + +The script exposes two helper functions: + +- `set_nms_conf`: writes a value to a key path in `nms.conf`. +- `set_nms_sm`: writes a value to a key path in `nms-sm-conf.yaml`. + +--- + +## Add or change NGINX Instance Manager configuration + +To inject a new or changed configuration value, complete these steps: + +1. Add the variable to `docker-compose/.env`: + + ```shell + MY_NEW_SETTING=myvalue + ``` + +2. Pass the variable into the container in `docker-compose.yaml`: + + ```yaml + environment: + - MY_NEW_SETTING=${MY_NEW_SETTING} + ``` + +3. Map the variable to a config key in `startNIM.sh`: + + ```shell + # For nms.conf: + set_nms_conf '.path.to.config.key' MY_NEW_SETTING + + # For nms-sm-conf.yaml: + set_nms_sm '.path.to.config.key' MY_NEW_SETTING + ``` + +4. Restart the stack to apply the change: + + ```shell + docker compose -f docker-compose.yaml up -d + ``` + +You don't need to rebuild the image. + +--- + +## License modes {#license-modes} + +NGINX Instance Manager supports two license operating modes. The correct choice depends on whether your host has outbound internet access to the NGINX licensing service. + +### Connected mode + +NGINX Instance Manager contacts the NGINX licensing service directly over the internet. When the host has reliable outbound HTTPS access, use this mode. + +Set in `docker-compose/.env`: + +```shell +NIM_LICENSE_MODE_OF_OPERATION=connected +``` + +### Disconnected mode + +NGINX Instance Manager operates without outbound internet access and validates the license locally. Use this mode for air-gapped or restricted environments. + +Set in `docker-compose/.env`: + +```shell +NIM_LICENSE_MODE_OF_OPERATION=disconnected +``` + +### Switch modes at runtime + +To change the license mode without an image rebuild: + +1. Update `NIM_LICENSE_MODE_OF_OPERATION` in `docker-compose/.env`. +2. Confirm the variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. +3. Confirm the mapping exists in `startNIM.sh`: + + ```shell + set_nms_conf '.integrations.license.mode_of_operation' NIM_LICENSE_MODE_OF_OPERATION + ``` + +4. Restart the stack: + + ```shell + docker compose -f docker-compose.yaml up -d + ``` + +--- + +## Stop or remove services + +Stop the stack: + +```shell +docker compose -f docker-compose.yaml stop +``` + +Stop and remove containers and networks: + +```shell +docker compose -f docker-compose.yaml down +``` + +--- + +## Troubleshooting + +### Permission errors on startup + +All processes run as the `nms` non-root user. If you see permission errors, check that any host-mounted volumes are readable and writable by the `nms` user. Avoid recursive `chown` or `chmod` commands, because these can interfere with rootless operation. + +### Configuration changes don't take effect + +If an updated variable has no effect after a restart, verify all of the following: + +- Confirm the variable is defined in `docker-compose/.env` with the correct value. +- Confirm the variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. +- Confirm a `set_nms_conf` or `set_nms_sm` call for that variable exists in `startNIM.sh`. +- Confirm you fully restarted the stack. `docker compose up -d` re-creates containers on config change. + +### View container logs + +To inspect startup output and verify configuration injection ran successfully: + +```shell +docker compose -f docker-compose.yaml logs nim +docker compose -f docker-compose.yaml logs clickhouse +``` + +### Check container status + +```shell +docker compose -f docker-compose.yaml ps +``` + +--- + +## See also + +- [Deploy rootless using Docker Compose]({{< ref "nim/deploy/docker/deploy-nim-rootless-docker-compose.md" >}}): Use an official F5-maintained image. You don't need to build your own. +- [Deploy using Docker Compose]({{< ref "nim/deploy/docker/deploy-nginx-instance-manager-docker-compose.md" >}}): Standard, non-rootless Docker Compose deployment. +- [NGINX Instance Manager Documentation](https://docs.nginx.com/nginx-instance-manager/) +- [yq YAML Processor](https://mikefarah.gitbook.io/yq/) +- [Docker Compose Documentation](https://docs.docker.com/compose/) \ No newline at end of file diff --git a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md index 3cd08e6ba..09c3d78c0 100644 --- a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md +++ b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md @@ -1,29 +1,39 @@ --- -description: Deploy F5 NGINX Instance Manager in a rootless Docker environment using Docker Compose, with runtime configuration injection using environment variables. +description: Deploy F5 NGINX Instance Manager using an official, F5-maintained rootless Docker image and Docker Compose. title: Deploy rootless using Docker Compose toc: true weight: 150 -f5-docs: DOCS-NIM-ROOTLESS +f5-docs: f5-content-type: how-to f5-product: NGINX Instance Manager f5-summary: > - Deploy F5 NGINX Instance Manager in a secure, rootless Docker Compose environment where all - processes run as a non-root user. Change NGINX Instance Manager configuration at runtime using environment - variables—no image rebuild required. + Deploy F5 NGINX Instance Manager using an official, F5-maintained rootless Docker image and + Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. --- + + ## Overview -This guide shows you how to deploy F5 NGINX Instance Manager using Docker Compose in a **rootless** configuration. In this setup, all container processes run as a non-root user (`nms`), following the principle of least privilege for production environments. +This guide shows you how to deploy F5 NGINX Instance Manager using an official rootless Docker image and Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. All container processes run as a non-root user (`nms`). + +The image includes NGINX Instance Manager, Security Monitoring, and the latest F5 WAF for NGINX compiler. -A key capability of this deployment is **runtime configuration injection**: you can change NGINX Instance Manager settings by editing environment variable files and restarting the stack. You don't need to rebuild the Docker image. +{{< call-out class="note" title="Note: Building your own image" >}} If you can't pull images from an external registry, or you need to customize the image, see [Build a custom rootless Docker image]({{< ref "nim/deploy/docker/build-nim-rootless-docker-image.md" >}}) instead. {{< /call-out >}} -Key characteristics of this deployment: +This deployment has the following key characteristics: -- **Rootless by design** — All processes run as `nms` (non-root), reducing the attack surface and satisfying security hardening requirements. -- **Runtime configuration** — Change NGINX Instance Manager settings by updating `.env` and `docker-compose.yaml`. You don't need to rebuild the image. -- **Production-hardened** — Startup scripts are idempotent and avoid fragile patterns such as recursive permission changes. -- **Flexible licensing** — Supports both connected and disconnected license modes, switchable at runtime. +- Rootless by design. All processes run as `nms`. The container needs no elevated privileges at runtime. +- Single persistent volume. NGINX Instance Manager stores its database, certificates, and credentials under one `/data` volume. +- First-boot initialization. On first start, the container seeds certificates and credentials automatically. +- Maintenance mode. Start the container without NGINX Instance Manager services. This lets you back up, restore, or debug safely. +- Built-in watchdog. The watchdog monitors critical NGINX Instance Manager processes. If one fails, the watchdog stops the container cleanly. --- @@ -31,253 +41,368 @@ Key characteristics of this deployment: Before you begin, make sure you have the following: -- [Docker Engine](https://docs.docker.com/get-docker/) 20.10 or later installed on a Linux host (amd64 or arm64). -- Docker Compose plugin v2 or later. -- A valid NGINX Instance Manager license file, base64-encoded. -- An NGINX certificate and private key, required to download NGINX Instance Manager packages during image build. -- Basic familiarity with Docker Compose and YAML syntax. +- [Docker Engine](https://docs.docker.com/get-docker/) 20.10 or later on a Linux host. +- [Docker Compose plugin](https://docs.docker.com/compose/install/) v2 or later. +- A JWT from your [MyF5 subscriptions page](https://my.f5.com/manage/s/subscriptions), to authenticate with the F5 image registry. +- {{}} {{}} +- ClickHouse. This compose file starts it as a bundled service. +- At least 4 CPU cores and 4 GB of memory. --- ## Before you start -Clone the deployment repository to your host machine: +Create the admin password file in the same directory as `docker-compose-rootless.yaml`: + +```shell +echo "" > admin_password.txt +``` + +Don't commit this file to version control. + +Log in to the F5 image registry with your JWT: ```shell -git clone https://github.com/nginx/nginx-demos.git -cd nginx-demos/nginx-instance-manager/docker-deployment +docker login private-registry.nginx.com --username= --password=none ``` --- -## Build the NGINX Instance Manager image +## Deploy NGINX Instance Manager -Run the build script, supplying your NGINX certificate, key, and a name for the resulting image: +Start the stack: ```shell -./build.sh -C -K -t +docker compose -f docker-compose-rootless.yaml up -d ``` -Replace the placeholders: +NGINX Instance Manager is available at `https://localhost:8443`. Log in with the admin credentials you configured. -- `` — Path to your NGINX TLS certificate file. -- `` — Path to your NGINX TLS private key file. -- `` — Your preferred Docker image tag (for example, `nim:latest`). +--- -The build script downloads NGINX Instance Manager packages from the NGINX repository using your certificate and key, and produces a self-contained rootless image. +## Supported environment variables + +{{}} +| Variable | Required | Description | +|---|---|---| +| `NIM_CLICKHOUSE_ADDRESSPORT` | Yes | ClickHouse address and port, for example `clickhouse:9000`. | +| `NIM_USERNAME` | Yes | Admin username, set on first boot. | +| `NIM_PASSWORD` | Yes | Admin password, set on first boot. | +| `NIM_CLICKHOUSE_USERNAME` | No | ClickHouse username. | +| `NIM_CLICKHOUSE_PASSWORD` | No | ClickHouse password. | +| `NIM_LICENSE` | No | Base64-encoded license. Activates on first boot if set. Otherwise, activate manually in the UI after deployment. | +| `NIM_LOG_LEVEL` | No | Logging verbosity: `INFO`, `DEBUG`, and so on. | +| `NIM_METRICS_TTL` | No | Metrics retention, in days (integer). | +| `NIM_EVENTS_TTL` | No | Events retention, in days (integer). | +| `NIM_SECURITY_TTL` | No | Security events retention, in days (integer). | +| `NIM_WATCHDOG_TIMEOUT` | No | Watchdog timeout, in seconds (integer). | +| `NIM_LICENSE_MODE_OF_OPERATION` | No | `connected` (default) or `disconnected`. | +| `NIM_MAINTENANCE` | No | Set to `true` to start in maintenance mode. No services launch. | +| `ENABLE_METRICS` | No | `true` or `false`. | +| `PROXY_ENABLE` | No | `true` or `false`. Turns on a forward proxy. | +| `PROXY_HOST` | No | Hostname or IP address of the proxy server. | +| `PROXY_PORT` | No | Proxy port. Default is `3128`. | +| `PROXY_PROTOCOL` | No | `http` (default) or `https`. | +| `PROXY_AUTH_REQUIRED` | No | `true` or `false`. | +| `PROXY_AUTH_USERNAME` | No | Proxy username. | +| `PROXY_PASSWORD` | No | Proxy password. Set this in your `.env` file. Don't hardcode it. | +| `PROXY_SSL_VERIFY` | No | `true` (default) or `false`. | +{{
}} --- -## Configure environment variables +## Secrets + +The admin password is required. Configure it as a Docker secret: + +```yaml +secrets: + nim_admin_password: + file: admin_password.txt +``` + +Two secrets are optional: + +Custom `.htpasswd` credentials file: + +```yaml +secrets: + nim_credential_file: + file: nim_creds.txt +``` + +Custom TLS certificates for the ingress proxy: -Edit `docker-compose/.env` and set the following values: +```yaml +secrets: + nim_proxy_cert_file: + file: ./certs/nim_cert.pem + nim_proxy_cert_key: + file: ./certs/nim_key.pem + nim_proxy_ca_cert: + file: ./certs/nim_ca.pem +``` + +--- + +## License modes + +NGINX Instance Manager supports two license operating modes, set with `NIM_LICENSE_MODE_OF_OPERATION`. A license isn't required to deploy. You can activate it later in the UI. + +Connected mode: NGINX Instance Manager contacts the NGINX licensing service directly over the internet. When the host has outbound HTTPS access, use this mode. ```shell -NIM_IMAGE= -NIM_LICENSE= -NIM_USERNAME= -NIM_PASSWORD= -NIM_CLICKHOUSE_ADDRESSPORT=docker-compose-clickhouse-1:9000 -NIM_CLICKHOUSE_USERNAME= -NIM_CLICKHOUSE_PASSWORD= NIM_LICENSE_MODE_OF_OPERATION=connected ``` -Replace `` with the tag used in the build step, and `` with your base64-encoded NGINX Instance Manager license. Set `NIM_LICENSE_MODE_OF_OPERATION` to `connected` or `disconnected` depending on your environment (see [License modes](#license-modes) below). +Disconnected mode: NGINX Instance Manager validates the license locally, without outbound internet access. Use this mode for air-gapped or restricted environments. -{{< call-out class="note" >}} Change `NIM_USERNAME` and `NIM_PASSWORD` to values appropriate for your environment before deploying to production. {{< /call-out >}} +```shell +NIM_LICENSE_MODE_OF_OPERATION=disconnected +``` --- -## Verify docker-compose.yaml environment mappings +## Stop or remove services -Open `docker-compose.yaml` and confirm that the `nim` service passes all required variables into the container: +Stop the stack without removing data: -```yaml -environment: - - NIM_LICENSE=${NIM_LICENSE} - - NIM_USERNAME=${NIM_USERNAME} - - NIM_PASSWORD=${NIM_PASSWORD} - - NIM_CLICKHOUSE_ADDRESSPORT=${NIM_CLICKHOUSE_ADDRESSPORT} - - NIM_CLICKHOUSE_USERNAME=${NIM_CLICKHOUSE_USERNAME} - - NIM_CLICKHOUSE_PASSWORD=${NIM_CLICKHOUSE_PASSWORD} - - NIM_LICENSE_MODE_OF_OPERATION=${NIM_LICENSE_MODE_OF_OPERATION} +```shell +docker compose -f docker-compose-rootless.yaml stop +``` + +Stop and remove containers and networks. Named volumes are preserved: + +```shell +docker compose -f docker-compose-rootless.yaml down ``` -If you add new configuration variables later, add a corresponding line here to make the value available inside the container. +{{< call-out class="warning" title="Warning: Data loss with docker compose down -v" >}} Never run `docker compose down -v`. This destroys every named volume, including the database, certificates, and credentials. {{< /call-out >}} --- -## Start the stack +## Backup and restore -Start NGINX Instance Manager and its dependencies (including ClickHouse) with: +### Back up NGINX Instance Manager ```shell -docker compose -f docker-compose.yaml up -d +docker exec nim-nim-1 nim-backup ``` ---- +This creates a backup at `/data/backup/nim-backup-.tgz` inside the container. To find it on the host: + +```shell +docker inspect volume nim_nim-data | jq '.[0].Mountpoint' +sudo ls -l /var/lib/docker/volumes/nim_nim-data/_data/backup +``` -## Access the NGINX Instance Manager web interface +### Restore NGINX Instance Manager -When the containers are running, open a browser and go to: +1. In `docker-compose-rootless.yaml`, set `NIM_MAINTENANCE: "true"` and restart the stack. +2. Run the restore command: -```text -https://localhost/ +```shell + docker exec nim-nim-1 nim-restore /data/backup/nim-backup-.tgz ``` -Accept the self-signed TLS certificate warning if prompted. Log in using the `NIM_USERNAME` and `NIM_PASSWORD` values you set in `.env`. +3. Set `NIM_MAINTENANCE: "false"` and restart the stack again. --- -## How runtime configuration injection works +## Storage -When the NGINX Instance Manager container starts, `startNIM.sh` reads the environment variables that Docker Compose passes in. It writes their values into the NGINX Instance Manager configuration files using `yq`, a YAML processor. The two configuration files are: +{{}} +| Volume | Purpose | +|---|---| +| `nim-data` | All NGINX Instance Manager persistent state: database, secrets, streaming state, credentials. | +| `nim-logs` | NGINX Instance Manager log files. | +| `nim-certs` | TLS certificates for the ingress proxy. | +| `proxy-certs` | Custom CA certificates for outbound proxy connections. | +| `clickhouse-data` | ClickHouse metrics and events database. | +| `nim-nap-compiler` | F5 WAF for NGINX compiler artifacts, mounted at `/opt/nms-nap-compiler`. | +{{
}} -- `/etc/nms/nms.conf` -- `/etc/nms/nms-sm-conf.yaml` +To use NFS-backed volumes, add `driver_opts` to the volumes section in `docker-compose-rootless.yaml`: -This means NGINX Instance Manager applies fresh configuration on every container start. You change a setting by updating the variable in `.env` and restarting the stack. You don't need to rebuild the image. +```yaml +volumes: + nim-data: + driver: local + driver_opts: + type: "nfs" + o: "addr=,rw" + device: ":/mnt/nfs_share/data" + clickhouse-data: + driver: local + driver_opts: + type: "nfs" + o: "addr=,rw" + device: ":/mnt/nfs_share/clickhouse" +``` + +--- -The script exposes two helper functions: +## Troubleshooting -- `set_nms_conf` — writes a value to a key path in `nms.conf`. -- `set_nms_sm` — writes a value to a key path in `nms-sm-conf.yaml`. +### Container exits immediately ---- +Get the logs and check the last line before exit: -## Add or change NGINX Instance Manager configuration +```shell +docker compose -f docker-compose-rootless.yaml logs nim +docker compose -f docker-compose-rootless.yaml ps -a +``` -To inject a new or changed configuration value, complete these steps: +{{}} +| Symptom | Fix | +|---|---| +| `admin_password.txt: no such file or directory` | Create the file: `echo "" > admin_password.txt` | +| `Error: Clickhouse TTL value must be an integer` | Set `NIM_METRICS_TTL`, `NIM_EVENTS_TTL`, or `NIM_SECURITY_TTL` to a plain integer, for example `"7"`. | +| `Error: NIM_WATCHDOG_TIMEOUT value must be an integer` | Set it to a plain integer in seconds, for example `"60"`. | +| `Error: ENABLE_METRICS value must be either true or false` | Correct the value in your compose file. | +| `Process nms- has stopped. Stopping container.` | See [NMS service crashes](#nms-service-crashes). | +{{
}} -1. **Add the variable to `.env`** +### Permission errors - ```shell - MY_NEW_SETTING=myvalue - ``` +The image sets ownership on all NGINX Instance Manager paths to `nms:nms` at build time. A host volume owned by root overrides this. -2. **Pass the variable into the container in `docker-compose.yaml`** +Check ownership: - ```yaml - environment: - - MY_NEW_SETTING=${MY_NEW_SETTING} - ``` +```shell +docker compose -f docker-compose-rootless.yaml exec nim ls -la /data +``` -3. **Map the variable to a config key in `startNIM.sh`** +Every entry must be owned by `nms`. If root owns the entries, someone pre-populated the volume as root before first boot. - ```shell - # For nms.conf: - set_nms_conf '.path.to.config.key' MY_NEW_SETTING +- Named volumes (recommended): Don't pre-create the directory as root. Docker assigns ownership to the first writer (`nms`). +- Bind mounts: Run `sudo chown -R 101:101 /path/to/nim-data`. UID 101 is the `nms` user. - # For nms-sm-conf.yaml: - set_nms_sm '.path.to.config.key' MY_NEW_SETTING - ``` +### ClickHouse not reachable -Then restart the stack to apply the change: +If startup loops on `Waiting for ClickHouse...`: ```shell -docker compose -f docker-compose.yaml up -d +docker compose -f docker-compose-rootless.yaml ps clickhouse +docker compose -f docker-compose-rootless.yaml logs clickhouse +docker compose -f docker-compose-rootless.yaml exec nim nc -zv clickhouse 9000 ``` -You don't need to rebuild the image. +Both services must share the same Docker network. ---- +### Port binding failure + +Symptom: `bind() to 0.0.0.0:443 failed (13: Permission denied)`. -## License modes {#license-modes} +Check that the NGINX binary has the required capability: + +```shell +docker compose -f docker-compose-rootless.yaml exec nim getcap $(which nginx) +``` -NGINX Instance Manager supports two license operating modes. The correct choice depends on whether your host has outbound internet access to the NGINX licensing service. +The expected output is `/usr/sbin/nginx cap_net_bind_service=ep`. If it's missing, contact F5 Support. You can't fix this at runtime, and you can't rebuild this image yourself. -### Connected mode +### Certificate issues -NGINX Instance Manager contacts the NGINX licensing service directly over the internet. Use this mode when the host has reliable outbound HTTPS access. +Symptom: a certificate error in your browser, or NGINX fails with TLS errors, on first access. -Set in `.env`: +Verify the certificates exist: ```shell -NIM_LICENSE_MODE_OF_OPERATION=connected +docker compose -f docker-compose-rootless.yaml exec nim ls -la /data/certs/ ``` -### Disconnected mode +You should see `manager-server.pem`, `manager-server.key`, and `ca.pem`. Then verify the symlink: + +```shell +docker compose -f docker-compose-rootless.yaml exec nim ls -la /etc/nms/certs +``` -NGINX Instance Manager operates without outbound internet access and validates the license locally. Use this mode for air-gapped or restricted environments. +The expected output shows `/etc/nms/certs -> /data/certs`. If the symlink is missing, gather the container logs and [contact F5 Support](https://www.f5.com/support). -Set in `.env`: +### NMS service crashes + +Symptom: `Process nms- has stopped. Stopping container.` + +The watchdog monitors `nms-dpm`, `nms-core`, `nms-integrations`, and `nms-ingestion` every 5 seconds. `nms-sm` (Security Monitor) isn't part of the watchdog. It can crash, and the container keeps running. + +Identify the crashing service: ```shell -NIM_LICENSE_MODE_OF_OPERATION=disconnected +docker compose -f docker-compose-rootless.yaml logs nim --tail=200 | grep -E "nms-(core|dpm|integrations|ingestion|sm)" ``` -### Switch modes at runtime +- If `nms-ingestion` crashes, ClickHouse is likely unavailable. See [ClickHouse not reachable](#clickhouse-not-reachable). +- If `nms-core`, `nms-dpm`, or `nms-integrations` restarts repeatedly, restore from a recent backup. See [Backup and restore](#backup-and-restore). -To change the license mode without rebuilding the image: +### License activation failures -1. Update `NIM_LICENSE_MODE_OF_OPERATION` in `docker-compose/.env`. -2. Confirm the variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. -3. Confirm the mapping exists in `startNIM.sh`: +Symptom: the license isn't active, even though you set `NIM_LICENSE`. - ```shell - set_nms_conf '.integrations.license.mode_of_operation' NIM_LICENSE_MODE_OF_OPERATION - ``` +Verify the license is valid base64: -4. Restart the stack: +```shell +echo "$NIM_LICENSE" | base64 -d | head -5 +``` - ```shell - docker compose -f docker-compose.yaml up -d - ``` +Check for errors in the logs: ---- +```shell +docker compose -f docker-compose-rootless.yaml logs nim | grep -i license +``` -## Stop or remove services +If activation fails, activate the license manually from the UI. For connected mode, confirm NGINX Console is reachable. See [Proxy misconfiguration](#proxy-misconfiguration). -To stop the running stack: +### Proxy misconfiguration + +Symptom: outbound traffic (telemetry, license) fails when `PROXY_ENABLE` is set to `true`. + +Confirm that the container applied the proxy settings: ```shell -docker compose -f docker-compose.yaml stop +docker compose -f docker-compose-rootless.yaml exec nim cat /etc/nms/nms.conf | grep -A 6 proxy_config ``` -To stop and remove containers and networks: +Test proxy reachability from inside the container. A `200` or `400` response means the proxy is reachable. A `000` response means it isn't. ```shell -docker compose -f docker-compose.yaml down +docker compose -f docker-compose-rootless.yaml exec nim curl -x http://: -sS -o /dev/null -w "%{http_code}" https://product.connect.nginx.com/api/nginx-usage/batch ``` ---- - -## Troubleshooting +If your proxy uses a corporate CA, mount the PEM certificates into `/usr/local/share/ca-certificates` with the `proxy-certs` volume. For testing only, set `PROXY_SSL_VERIFY=false`. -### Permission errors on startup +### Maintenance mode -All processes run as the `nms` non-root user. If you see permission errors, check that any host-mounted volumes are readable and writable by the `nms` user. Avoid using recursive `chown` or `chmod` commands, because these can interfere with rootless operation. +Use maintenance mode to back up, restore, or debug a container that won't start. In maintenance mode, the container initializes storage but doesn't start NGINX Instance Manager services or NGINX. -### Configuration changes not taking effect +To turn it on, set `NIM_MAINTENANCE: "true"` in `docker-compose-rootless.yaml`, then restart: -If an updated variable has no effect after a restart, verify all three steps were completed: +```shell +docker compose -f docker-compose-rootless.yaml up -d +``` -- The variable is defined in `.env` with the correct value. -- The variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. -- A `set_nms_conf` or `set_nms_sm` call for that variable exists in `startNIM.sh`. -- The stack was fully restarted (`docker compose up -d` re-creates containers on config change). +Get shell access: -### View container logs +```shell +docker compose -f docker-compose-rootless.yaml exec nim bash +``` -To inspect startup output and verify configuration injection ran successfully: +To turn it off, remove `NIM_MAINTENANCE` or set it to `false`, then restart: ```shell -docker compose -f docker-compose.yaml logs nim -docker compose -f docker-compose.yaml logs clickhouse +docker compose -f docker-compose-rootless.yaml restart nim ``` -### Check running container state +### Gather support data ```shell -docker compose -f docker-compose.yaml ps +docker compose -f docker-compose-rootless.yaml logs --since 24h > nim-logs-$(date +%Y-%m-%d).txt +docker exec nim-nim-1 nim-backup ``` --- ## See also -- [Deploy using Docker Compose]({{< ref "nim/deploy/docker/deploy-nginx-instance-manager-docker-compose.md" >}}) — Standard (non-rootless) Docker Compose deployment. -- [NGINX Instance Manager Documentation](https://docs.nginx.com/nginx-instance-manager/) -- [yq YAML Processor](https://mikefarah.gitbook.io/yq/) -- [Docker Compose Documentation](https://docs.docker.com/compose/) +- [Build a custom rootless Docker image]({{< ref "nim/deploy/docker/build-nim-rootless-docker-image.md" >}}): Build your own rootless image from source, for air-gapped or custom-image environments. +- [Deploy using Docker Compose]({{< ref "nim/deploy/docker/deploy-nginx-instance-manager-docker-compose.md" >}}): Standard, non-rootless Docker Compose deployment. \ No newline at end of file From 4f1762caa57fe68b9428af6447751ae75801ae4a Mon Sep 17 00:00:00 2001 From: Travis Martin <33876974+travisamartin@users.noreply.github.com> Date: Wed, 2 Sep 2026 09:00:19 -0700 Subject: [PATCH 13/19] docs(TECHDOCS-5505): add NGF security event export and visibility (#316) * docs(TECHDOCS-5505): add NGF security event export and visibility - Add "View NGINX Gateway Fabric security events" concept page under NIM Security Monitoring - Add "Export security logs to F5 NGINX Instance Manager" section to NGF policy-sources.md, under a renamed "Console integration" heading - Add troubleshooting entries for NIM-side and NGF-side event delivery failures - Add a version-requirement pointer to NGF technical specifications - Copy edit policy-sources.md: fix bare "WAF" mentions, correct the garbled NIM heading, split long/passive sentences per style guide Files touched: - content/nim/security-monitoring/ngf-security-events.md (new) - content/nim/security-monitoring/troubleshooting.md - content/ngf/waf-integration/troubleshooting.md - content/ngf/overview/technical-specifications.md - content/ngf/waf-integration/policy-sources.md * edits to ngf-security-events.md * added connect-ngf.md topic, copy edits to touched topics. * edits * edits * docs(TECHDOCS-5505): address shaun-nx review on connect-ngf.md - Confirm connection scope is security event export only, not F5 WAF policy fetching; state this explicitly in the Overview and remove the now-resolved SME REVIEW comment that flagged it as unconfirmed - Remove the "Create the NGINX Instance Manager dataplane key Secret" section; NGINX Gateway Fabric now reuses the existing nplus-license Secret instead of a separate nim-dp-key Secret - Simplify the Helm install command accordingly: drop --set nginx.nginxInstanceManager.dataplaneKeySecretName=nim-dp-key - Note in "Create the NGINX Plus Secret" that this Secret now also authenticates the NGINX Gateway Fabric to NGINX Instance Manager connection, since it's doing that job in addition to its original purpose - Update f5-summary to match: drop the dataplane-key reference, align first sentence with the Overview's wording - Remove the two pending-change SME REVIEW comments that existed to flag this exact update as outstanding Resolves all three review comments from shaun-nx on PR #316. * edits per tech review feedback --- .../ngf/overview/technical-specifications.md | 3 + content/ngf/waf-integration/policy-sources.md | 129 ++++++++++++++---- .../ngf/waf-integration/troubleshooting.md | 23 ++++ content/nim/connect-kubernetes/_index.md | 11 ++ content/nim/connect-kubernetes/connect-ngf.md | 75 ++++++++++ .../ngf-security-events.md | 56 ++++++++ .../security-monitoring/troubleshooting.md | 31 +++++ 7 files changed, 299 insertions(+), 29 deletions(-) create mode 100644 content/nim/connect-kubernetes/_index.md create mode 100644 content/nim/connect-kubernetes/connect-ngf.md create mode 100644 content/nim/security-monitoring/ngf-security-events.md diff --git a/content/ngf/overview/technical-specifications.md b/content/ngf/overview/technical-specifications.md index da4f83528..ada341ce2 100644 --- a/content/ngf/overview/technical-specifications.md +++ b/content/ngf/overview/technical-specifications.md @@ -32,6 +32,9 @@ The following table lists the software versions NGINX Gateway Fabric supports. O | 1.3.0 | 1.1.0 | 1.25+ | 1.27.0 | R32 | --- | --- | | 1.2.0 | 1.0.0 | 1.23+ | 1.25.4 | R31 | --- | --- | +{{< call-out class="note" title="Note: NGINX Instance Manager integration" >}} +For version requirements to export F5 WAF for NGINX security events to NGINX Instance Manager, see [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}).{{< /call-out >}} + ### OpenShift Compatibility The following table lists the OpenShift versions and Operator versions compatible with NGINX Gateway Fabric. diff --git a/content/ngf/waf-integration/policy-sources.md b/content/ngf/waf-integration/policy-sources.md index 4208ed5ff..c1de88a5a 100644 --- a/content/ngf/waf-integration/policy-sources.md +++ b/content/ngf/waf-integration/policy-sources.md @@ -4,24 +4,24 @@ weight: 300 toc: true f5-content-type: how-to f5-product: NGINX Gateway Fabric -f5-description: Configure WAFPolicy to fetch compiled bundles from F5 NGINX Instance Manager, F5 NGINX One Console, or an HTTP server. +description: Configure WAFPolicy to fetch compiled bundles from F5 NGINX Instance Manager, F5 NGINX One Console, or an HTTP server. --- -NGINX Gateway Fabric supports three policy source types for fetching compiled WAF bundles: F5 NGINX Instance Manager, F5 NGINX One Console, and direct HTTP/HTTPS URLs. For a quick start walkthrough using the HTTP source, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started.md" >}}). +F5 NGINX Gateway Fabric supports three policy source types for fetching compiled F5 WAF bundles: F5 NGINX Instance Manager, F5 NGINX One Console, and direct HTTP/HTTPS URLs. For a quick start walkthrough using the HTTP source, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started.md" >}}). -Before configuring a policy source, ensure that WAF is [enabled on the NginxProxy]({{< ref "/ngf/waf-integration/overview.md#enable-waf-on-the-nginxproxy" >}}) — either per Gateway or globally via Helm values. +Before you configure a policy source, make sure F5 WAF is turned on for the NginxProxy — either per Gateway or globally through Helm values. For version requirements, see [Technical specifications]({{< ref "/ngf/overview/technical-specifications.md" >}}). -{{< call-out class="tip" >}} By default, NGINX Gateway Fabric retries transient fetch failures up to 3 times with exponential backoff, and each fetch attempt times out after 30 seconds. You can tune these using the `retryAttempts` and `timeout` fields on `policySource` or `logSource`. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Fetch retry behavior" >}} By default, NGINX Gateway Fabric retries transient fetch failures up to 3 times with exponential backoff, and each fetch attempt times out after 30 seconds. You can tune these using the `retryAttempts` and `timeout` fields on `policySource` or `logSource`. {{< /call-out >}} --- -## NGINX Instance Manager (NGINX Instance Manager) +## F5 NGINX Instance Manager -Use this option when you manage WAF policies through NGINX Instance Manager. For details on creating and compiling policies in NGINX Instance Manager, see [How WAF policy management works]({{< ref "/nim/waf-integration/overview.md" >}}) and [Create a security policy bundle]({{< ref "/nim/waf-integration/policies-and-logs/bundles/create-bundle.md" >}}). +Use this option when you manage F5 WAF policies through F5 NGINX Instance Manager. For details on creating and compiling policies in NGINX Instance Manager, see [How WAF policy management works]({{< ref "/nim/waf-integration/overview.md" >}}) and [Create a security policy bundle]({{< ref "/nim/waf-integration/policies-and-logs/bundles/create-bundle.md" >}}). **Workflow:** -1. Author and compile a policy in NGINX Instance Manager using the NGINX Instance Manager console or API. Verify that compilation succeeded before proceeding — NGINX Gateway Fabric cannot detect compilation failures in NGINX Instance Manager. +1. Author and compile a policy in NGINX Instance Manager using the NGINX Instance Manager console or API. Verify that compilation succeeded. NGINX Gateway Fabric can't detect compilation failures in NGINX Instance Manager. 2. Create a Secret with your NGINX Instance Manager credentials. 3. Create a `WAFPolicy` referencing the compiled policy by name. @@ -92,13 +92,13 @@ EOF Replace `https://nim.example.com` with your NGINX Instance Manager base URL, and `ngfBlocking` with your compiled policy name. -{{< call-out class="tip" >}} To skip TLS certificate verification when fetching bundles (for testing only - not recommended for production), uncomment 'insecureSkipVerify: true'. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Testing with self-signed certificates" >}} To skip TLS certificate verification when fetching bundles, uncomment `insecureSkipVerify: true`. Don't use this in production. {{< /call-out >}} -{{< call-out class="tip" >}} To pin a specific policy version, use `policyUID` instead of `policyName`. Find the UID in the NGINX Instance Manager console or API. A pinned UID always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, use `policyUID` instead of `policyName`. Find the UID in the NGINX Instance Manager console or API. A pinned UID always resolves to the same compiled bundle. Turn off polling to avoid unnecessary network requests. {{< /call-out >}} ### Apply a route-level override (optional) -To apply a different policy to a specific route — for example, a data-guard policy — create a route-level `WAFPolicy`: +To apply a different policy to a specific route, such as a data-guard policy, create a route-level `WAFPolicy`: ```yaml kubectl apply -f - <}}). + --- ## F5 NGINX One Console -Use this option when you manage WAF policies through F5 NGINX One Console. For details on creating and compiling policies in NGINX One Console, see [Manage policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}). +Use this option when you manage F5 WAF policies through F5 NGINX One Console. For details on creating and compiling policies in NGINX One Console, see [Manage policies]({{< ref "/nginx-one-console/waf-integration/policy/_index.md" >}}). **Workflow:** -1. Author and compile a policy in the NGINX One Console console or API. If no compiled bundle for a given policy exists yet, NGINX Gateway Fabric triggers compilation via the NGINX One Console API when it first reconciles the WAFPolicy and waits for it to complete. -2. Create a Secret with your NGINX One Console API token. -3. Create a `WAFPolicy` referencing the compiled policy. +1. Author and compile a policy in the NGINX One Console or API. +2. If no compiled bundle exists yet, NGINX Gateway Fabric triggers compilation through the NGINX One Console API the first time it reconciles the `WAFPolicy` resource. NGINX Gateway Fabric waits for compilation to finish. +3. Create a Secret with your NGINX One Console API token. +4. Create a `WAFPolicy` referencing the compiled policy. ### Create the credentials Secret @@ -202,37 +205,104 @@ EOF Replace `` with your NGINX One Console tenant hostname. The `namespace` field refers to the NGINX One Console namespace where the policy resides. -{{< call-out class="tip" >}} To pin a specific policy version, set `policyVersionID`. A pinned version always resolves to the same compiled bundle, so polling should be disabled to avoid unnecessary network requests. If you use only `policyName` or `policyObjectID` without a version pin, the latest compiled bundle is fetched on each reconciliation or poll cycle. {{< /call-out >}} +{{< call-out class="tip" title="Tip: Pin a policy version" >}} To pin a specific policy version, set `policyVersionID`. A pinned version always resolves to the same compiled bundle. Turn off polling to avoid unnecessary network requests. If you use only `policyName` or `policyObjectID` without a version pin, NGINX Gateway Fabric fetches the latest compiled bundle on each reconciliation or poll cycle. {{< /call-out >}} --- ## HTTP/HTTPS server -Use this option when you compile WAF policies using the F5 WAF compiler CLI or a CI/CD pipeline and host the resulting bundle on an HTTP/HTTPS server. For details on using the compiler, see [Build and use the compiler tool]({{< ref "/waf/configure/compiler.md" >}}). +Use this option when you compile F5 WAF policies using the F5 WAF compiler CLI or a CI/CD pipeline and host the resulting bundle on an HTTP/HTTPS server. For details on using the compiler, see [Build and use the compiler tool]({{< ref "/waf/configure/compiler.md" >}}). For a complete walkthrough including policy compilation and a bundle server deployment, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started.md" >}}). -For production environments, you would typically host compiled bundles on an HTTPS server with authentication. See [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) for details on adding credentials, custom CA certificates, and checksum verification to your `policySource`. +In production environments, host compiled bundles on an HTTPS server with authentication. See [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) for details on adding credentials, custom CA certificates, and checksum verification to your `policySource`. + +--- + +## Policy deployment visibility + +NGINX Instance Manager and NGINX One Console don't show which F5 WAF policies are deployed to NGINX Gateway Fabric. Neither console shows which compiled bundle version NGINX Gateway Fabric has fetched. + +This is intentional. NGINX Gateway Fabric pulls compiled bundles from the management plane and deploys them directly in Kubernetes using native manifests, not through NGINX Instance Manager or NGINX One Console. This design lets you create and compile policies, then make them available to NGINX Gateway Fabric through the API, without a console-managed deployment step. + +F5 plans to add policy association visibility for NGINX Instance Manager and NGINX One Console in a future release. In the meantime, use `kubectl describe wafpolicy ` to check deployment status. --- -## Management console visibility +## Security event monitoring + +### NGINX Instance Manager + +#### Connect NGINX Gateway Fabric to F5 NGINX Instance Manager + +Configure NGINX Gateway Fabric to connect to NGINX Instance Manager before continuing. Follow [Connect NGINX Gateway Fabric to NGINX Instance Manager]({{< ref "/nim/connect-kubernetes/connect-ngf.md" >}}). + +#### Export security logs to F5 NGINX Instance Manager + +The Security Monitoring dashboard in NGINX Instance Manager doesn't show which F5 WAF policies are deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to NGINX Instance Manager. Exporting these events gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the dashboard. + +{{< call-out class="important" title="Important: Version requirement" >}} +This integration requires NGINX Instance Manager 2.23 or later. +{{< /call-out >}} + +To export these events, configure a `securityLogs` entry on the `WAFPolicy` resource. The entry sends events to the syslog listener that NGINX Agent runs inside the NGINX pod. NGINX Agent's built-in OpenTelemetry collector transforms the events and exports them to NGINX Instance Manager. + +```yaml +kubectl apply -f - <}}). NGINX Gateway Fabric handles this authentication internally — no separate credential is required for log export. -When using NGINX Instance Manager or NGINX One Console as your policy source, be aware that neither management console currently displays WAF policy deployments to NGINX Gateway Fabric, nor does it show which compiled bundle versions NGINX Gateway Fabric has fetched. +{{< call-out class="note" title="Note: Network requirements" >}} +- Port `1514` (local syslog): NGINX Agent listens on this port inside the NGINX pod. This traffic doesn't leave the pod. +- Port `4317` (gRPC): NGINX Agent uses this port to export events to NGINX Instance Manager. Make sure this port is reachable from your cluster. +{{< /call-out >}} -This is by design: NGINX Gateway Fabric pulls compiled bundles from the management plane using a pull model and deploys them directly in Kubernetes using native Kubernetes manifests, rather than through the NGINX Instance Manager or NGINX One Console console. This workflow ensures that policies can be created, compiled, and made available to NGINX Gateway Fabric via API without requiring console-managed deployment flows. +{{< call-out class="tip" title="Tip: Testing with self-signed certificates" >}} +To test with self-signed certificates, add `insecureSkipVerify: true` to `policySource` and `logSource`. Don't use this setting in production. See [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) for adding CA certificates and credentials. +{{< /call-out >}} -Policy association visibility for NGINX Instance Manager and NGINX One Console will be added in a future release. In the meantime, use `kubectl describe wafpolicy ` to check deployment status. +### NGINX One Console -### Connect NGINX Gateway Fabric to F5 NGINX One Console +#### Connect NGINX Gateway Fabric to F5 NGINX One Console -Ensure that NGINX Gateway Fabric is configured to connect to NGINX One Console. Follow the guidance at [Connect NGINX Gateway Fabric with Helm]({{< ref "/nginx-one-console/k8s/add-ngf-helm.md" >}}) or [Connect NGINX Gateway Fabric with Manifests]({{< ref "/nginx-one-console/k8s/add-ngf-manifests.md" >}}) before continuing. +Configure NGINX Gateway Fabric to connect to NGINX One Console before continuing. Follow [Connect NGINX Gateway Fabric with Helm]({{< ref "/nginx-one-console/k8s/add-ngf-helm.md" >}}) or [Connect NGINX Gateway Fabric with Manifests]({{< ref "/nginx-one-console/k8s/add-ngf-manifests.md" >}}). -### Export security logs to F5 NGINX One Console +#### Export security logs to F5 NGINX One Console -Although the NGINX One Console console does not display which policies are deployed to NGINX Gateway Fabric data planes, you can export WAF security events to the NGINX One Console security dashboard. This gives your security operations team visibility into blocked attacks, violations, and traffic patterns directly in the console. +NGINX One Console doesn't show which F5 WAF policies are deployed to NGINX Gateway Fabric data planes. You can still export F5 WAF security events to the NGINX One Console security dashboard. Your security operations team can then view blocked attacks, violations, and traffic patterns directly in the console. -To enable this, configure a `securityLogs` entry that sends events to the NGINX Agent's built-in OpenTelemetry collector, which forwards them to NGINX One Console. Use a log profile compiled for the NGINX One Console security dashboard: +To export these events, configure a `securityLogs` entry that sends events to NGINX Agent's built-in OpenTelemetry collector, which forwards them to NGINX One Console. Use a log profile compiled for the NGINX One Console security dashboard: ```yaml kubectl apply -f - <}} The `profileName: "secops_dashboard"` log profile must exist in your NGINX One Console namespace. This profile is required for events to appear correctly in the NGINX One Console security dashboard. {{< /call-out >}} +{{< call-out class="note" title="Note: Log profile must exist in NGINX One Console" >}} The `profileName: "secops_dashboard"` log profile must exist in your NGINX One Console namespace. Events don't appear correctly in the NGINX One Console security dashboard without this profile. {{< /call-out >}} --- @@ -281,4 +351,5 @@ The `localhost:1514` syslog destination points to the NGINX Agent's OpenTelemetr - [F5 WAF for NGINX overview]({{< ref "/ngf/waf-integration/overview.md" >}}) - [Configure WAF settings]({{< ref "/ngf/waf-integration/configuration.md" >}}) - [Troubleshoot WAFPolicy status]({{< ref "/ngf/waf-integration/troubleshooting.md" >}}) -- [WAFPolicy and NginxProxy API reference]({{< ref "/ngf/reference/api.md" >}}) +- [Technical specifications]({{< ref "/ngf/overview/technical-specifications.md" >}}) +- [WAFPolicy and NginxProxy API reference]({{< ref "/ngf/reference/api.md" >}}) \ No newline at end of file diff --git a/content/ngf/waf-integration/troubleshooting.md b/content/ngf/waf-integration/troubleshooting.md index 56faaec85..beb83de8e 100644 --- a/content/ngf/waf-integration/troubleshooting.md +++ b/content/ngf/waf-integration/troubleshooting.md @@ -105,6 +105,29 @@ To resolve the conflict, choose one of the following approaches: --- +### Security events aren't reaching NGINX Instance Manager + +F5 WAF for NGINX generates security events, but they don't appear in the NGINX Instance Manager Security Monitoring dashboard, even though the `WAFPolicy` resource shows `Programmed`. + +**How to identify the problem:** + +Check whether the event reached NGINX Agent inside the pod: + +```shell +kubectl exec -n -c nginx -- \ + tail -100 /var/log/nginx-agent/opentelemetry-collector-agent.log +``` + +If the event isn't in this log, F5 WAF for NGINX isn't reaching NGINX Agent. If the event is in the log but not in NGINX Instance Manager, the export from NGINX Agent is failing. + +**Resolution:** + +- **Event missing from the NGINX Agent log:** Confirm the `WAFPolicy` `securityLogs.destination.syslog.server` field is set to exactly `localhost:1514`. Any other value prevents the event from reaching NGINX Agent, which listens on `127.0.0.1:1514` inside the `nginx` container. +- **Event in the log but export fails:** Check the log for `Unauthenticated` errors. A JWT authentication failure between NGINX Agent and NGINX Instance Manager causes this error. This is the same NGINX Plus subscription JWT used to create the NGINX Plus Secret in [Connect NGINX Gateway Fabric to NGINX Instance Manager]({{< ref "/nim/connect-kubernetes/connect-ngf.md" >}}). If the JWT has expired or was revoked, download a new one from [MyF5](https://my.f5.com/manage/s/) and repeat the steps to recreate the Secret. NGINX Gateway Fabric doesn't pick up a rotated Secret automatically. Restart the Gateway pod after recreating it. +- **Export succeeds but NGINX Instance Manager shows nothing:** Confirm NGINX Instance Manager's embedded OpenTelemetry collector is running and reachable on port `4317`. See [Troubleshooting]({{< ref "/nim/security-monitoring/troubleshooting.md" >}}) for the NGINX Instance Manager–side checks. + +--- + ## See also - [F5 WAF for NGINX overview]({{< ref "/ngf/waf-integration/overview.md" >}}) diff --git a/content/nim/connect-kubernetes/_index.md b/content/nim/connect-kubernetes/_index.md new file mode 100644 index 000000000..84120bace --- /dev/null +++ b/content/nim/connect-kubernetes/_index.md @@ -0,0 +1,11 @@ +--- +title: Connect Kubernetes deployments +weight: 85 +url: /nginx-instance-manager/connect-kubernetes/ +f5-product: NGINX Instance Manager +f5-content-type: landing-page +description: "Connect Kubernetes-based NGINX deployments, such as NGINX Gateway Fabric, to F5 NGINX Instance Manager." +f5-summary: > + Connect Kubernetes-based NGINX deployments to F5 NGINX Instance Manager. + This section covers connecting NGINX Gateway Fabric for usage and licensing reporting. +--- \ No newline at end of file diff --git a/content/nim/connect-kubernetes/connect-ngf.md b/content/nim/connect-kubernetes/connect-ngf.md new file mode 100644 index 000000000..2b3d81c95 --- /dev/null +++ b/content/nim/connect-kubernetes/connect-ngf.md @@ -0,0 +1,75 @@ +--- +title: Connect NGINX Gateway Fabric to NGINX Instance Manager +weight: 100 +toc: true +f5-content-type: how-to +f5-product: NGINX Instance Manager +f5-docs: +description: "Connect NGINX Gateway Fabric to F5 NGINX Instance Manager to export F5 WAF security events to the Security Dashboard." +f5-summary: > + Connect NGINX Gateway Fabric to F5 NGINX Instance Manager to export F5 WAF security events to the Security Dashboard. + This page covers the NGINX Plus JWT, the NGINX Plus Secret, and the Helm values required to configure the connection. +--- + +## Overview + +Connect NGINX Gateway Fabric to NGINX Instance Manager to export F5 WAF security events to the Security Dashboard. + +This connection supports security event export only. F5 WAF policy fetching uses a separate credential flow. See [Configure policy sources]({{< ref "/ngf/waf-integration/policy-sources.md" >}}). + +--- + +## Before you begin + +Before you begin, verify that you have: + +- Administrator access to a Kubernetes cluster +- Helm and kubectl installed locally +- An NGINX Plus subscription + +--- + +## Download your NGINX Plus JWT + +{{< include "/ngf/installation/nginx-plus/download-jwt.md" >}} + +--- + +## Create the NGINX Plus Secret + +{{< include "/ngf/installation/nginx-plus/nginx-plus-secret.md" >}} + +This Secret is required to run NGINX Plus, with or without F5 WAF for NGINX. It also authenticates the connection from NGINX Gateway Fabric to NGINX Instance Manager. + +--- + +## Install Gateway API resources + +{{< include "/ngf/installation/install-gateway-api-resources.md" >}} + +--- + +## Install NGINX Gateway Fabric + +This integration requires NGINX Plus with F5 WAF for NGINX. Install NGINX Gateway Fabric using the following Helm command: + +```shell +helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \ + --set nginx.image.repository=private-registry.nginx.com/nginx-gateway-fabric/nginx-plus \ + --set nginx.plus=true \ + --set nginx.config.waf.enable=true \ + --set nginx.imagePullSecret=nginx-plus-registry-secret \ + --set nginx.usage.secretName=nplus-license \ + --set nginx.nginxInstanceManager.endpointHost= \ + -n nginx-gateway +``` + +Replace `` with your NGINX Instance Manager hostname. + +--- + +## See also + +- [Deploy a Gateway for data plane instances]({{< ref "/ngf/install/deploy-data-plane.md" >}}) +- [Configure policy sources]({{< ref "/ngf/waf-integration/policy-sources.md" >}}) +- [View NGINX Gateway Fabric security events]({{< ref "/nim/security-monitoring/ngf-security-events.md" >}}) \ No newline at end of file diff --git a/content/nim/security-monitoring/ngf-security-events.md b/content/nim/security-monitoring/ngf-security-events.md new file mode 100644 index 000000000..f79c9316e --- /dev/null +++ b/content/nim/security-monitoring/ngf-security-events.md @@ -0,0 +1,56 @@ +--- +title: View NGINX Gateway Fabric security events +weight: 150 +toc: true +f5-content-type: concept +f5-product: NGINX Instance Manager +f5-docs: +description: "View F5 WAF security events from NGINX Gateway Fabric deployments in F5 NGINX Instance Manager's Security Dashboard." +f5-summary: > + View F5 WAF security events from NGINX Gateway Fabric deployments in F5 NGINX Instance Manager's Security Dashboard. + NGINX Gateway Fabric's NGINX Agent v3 exports security events directly to NGINX Instance Manager, giving you unified event visibility alongside F5 NGINX Ingress Controller. +--- + +## Overview + +F5 NGINX Instance Manager shows F5 WAF security events from NGINX Gateway Fabric deployments in the **Security Dashboard**. NGINX Gateway Fabric's NGINX Agent v3 includes a built-in OpenTelemetry collector that exports security events directly to NGINX Instance Manager. You don't need NGINX Agent v2 to see F5 WAF activity on your NGINX Gateway Fabric instances. + +You can view: + +- F5 WAF security violations +- Bot detection events +- Policy violations +- Attack patterns +- Security event history + +{{< call-out class="important" title="Important: Event visibility only" >}} +This integration covers security event visibility only. NGINX Instance Manager can't manage NGINX Gateway Fabric instances, instance groups, or F5 WAF policy deployments. F5 plans to add full NGINX Agent v3 support for these capabilities in a future release. +{{< /call-out >}} + +## Requirements + +- NGINX Instance Manager 2.23 or later +- NGINX Gateway Fabric running F5 WAF for NGINX with NGINX Agent v3, connected to NGINX Instance Manager. See [Connect NGINX Gateway Fabric to NGINX Instance Manager]({{< ref "/nim/connect-kubernetes/connect-ngf.md" >}}). +- Security Monitoring turned on in NGINX Instance Manager + +## Set up event export from NGINX Gateway Fabric + +NGINX Gateway Fabric generates and exports security events. NGINX Instance Manager doesn't pull or request them. Configure the export on the NGINX Gateway Fabric side. + +This integration doesn't require changes to Gateway API resources. + +See [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}). + +## View events in the dashboard + +Go to **WAF** > **Security Dashboard** in NGINX Instance Manager. The dashboard has four tabs: Main, Bots, Advanced, and Event Logs. These tabs cover aggregate attack statistics, bot activity, signature and threat detail, and individual events. + +Use **Event Logs** for individual event details, including source IP, URI, and Support ID. + +You can filter events across all four tabs by fields including instance, instance group, IP address, policy, signature, severity, and Support ID. + +## See also + +- [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}) +- [Add user access to Security Monitoring dashboards]({{< ref "/nim/security-monitoring/give-access-to-security-monitoring-dashboards.md" >}}) +- [Troubleshooting]({{< ref "/nim/security-monitoring/troubleshooting.md" >}}) \ No newline at end of file diff --git a/content/nim/security-monitoring/troubleshooting.md b/content/nim/security-monitoring/troubleshooting.md index 8ca527d98..6684c4b41 100644 --- a/content/nim/security-monitoring/troubleshooting.md +++ b/content/nim/security-monitoring/troubleshooting.md @@ -43,6 +43,37 @@ F5 WAF for NGINX supports logging to multiple destinations. You can send logs to --- +## NGINX Gateway Fabric security events don't appear in the dashboard + +### Description + +If NGINX Instance Manager doesn't receive security events from a NGINX Gateway Fabric deployment, the Security Monitoring dashboard shows no data for that deployment. + +### Resolution + +Check the following on NGINX Instance Manager, in order: + +1. Confirm the embedded OpenTelemetry collector is turned on. In `nms.conf`, verify `collector_config.enable` is set to `true`: + + ```yaml + collector_config: + enable: true + ``` + + If you change this setting, restart the service: + + ```shell + sudo systemctl restart nms + ``` + +2. Confirm NGINX Instance Manager is reachable from the Kubernetes cluster on port `4317` (gRPC). + +3. Confirm the log profile referenced in the `WAFPolicy` resource exists in NGINX Instance Manager and matches exactly. A mismatched or missing profile name causes events to arrive without expected fields, or not arrive at all. + +If these checks pass and events still don't appear, the problem is likely on the NGINX Gateway Fabric side. See [Security events aren't reaching NGINX Instance Manager]({{< ref "/ngf/waf-integration/troubleshooting.md#security-events-arent-reaching-nginx-instance-manager" >}}) and [Export security logs to F5 NGINX Instance Manager]({{< ref "/ngf/waf-integration/policy-sources.md#export-security-logs-to-f5-nginx-instance-manager" >}}). + +--- + ## How to get support {{< include "nim/support/how-to-get-support.md" >}} From 119f93eb24c5f587ec0c5a190a5019a5878583f0 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Wed, 2 Sep 2026 09:15:26 -0700 Subject: [PATCH 14/19] edits per tech review --- .../deploy-nim-rootless-docker-compose.md | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md index 09c3d78c0..14c431877 100644 --- a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md +++ b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md @@ -11,14 +11,6 @@ f5-summary: > Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. --- - - ## Overview This guide shows you how to deploy F5 NGINX Instance Manager using an official rootless Docker image and Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. All container processes run as a non-root user (`nms`). @@ -292,15 +284,22 @@ Both services must share the same Docker network. ### Port binding failure -Symptom: `bind() to 0.0.0.0:443 failed (13: Permission denied)`. +Symptom: `bind() to 0.0.0.0:443 failed (13: Permission denied)`, or a similar bind error. + + -Check that the NGINX binary has the required capability: +Check whether another process on your host already uses the port: ```shell -docker compose -f docker-compose-rootless.yaml exec nim getcap $(which nginx) +sudo lsof -i :8443 ``` -The expected output is `/usr/sbin/nginx cap_net_bind_service=ep`. If it's missing, contact F5 Support. You can't fix this at runtime, and you can't rebuild this image yourself. +If it does, stop that process, or change the port mapping in `docker-compose-rootless.yaml` to an available port. Restart the stack to apply the change. ### Certificate issues From 46ab407a8c0990b940de60d028d3af2869a4816a Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Wed, 2 Sep 2026 09:54:36 -0700 Subject: [PATCH 15/19] Revert "edits per tech review" This reverts commit 119f93eb24c5f587ec0c5a190a5019a5878583f0. --- .../deploy-nim-rootless-docker-compose.md | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md index 14c431877..09c3d78c0 100644 --- a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md +++ b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md @@ -11,6 +11,14 @@ f5-summary: > Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. --- + + ## Overview This guide shows you how to deploy F5 NGINX Instance Manager using an official rootless Docker image and Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. All container processes run as a non-root user (`nms`). @@ -284,22 +292,15 @@ Both services must share the same Docker network. ### Port binding failure -Symptom: `bind() to 0.0.0.0:443 failed (13: Permission denied)`, or a similar bind error. - - +Symptom: `bind() to 0.0.0.0:443 failed (13: Permission denied)`. -Check whether another process on your host already uses the port: +Check that the NGINX binary has the required capability: ```shell -sudo lsof -i :8443 +docker compose -f docker-compose-rootless.yaml exec nim getcap $(which nginx) ``` -If it does, stop that process, or change the port mapping in `docker-compose-rootless.yaml` to an available port. Restart the stack to apply the change. +The expected output is `/usr/sbin/nginx cap_net_bind_service=ep`. If it's missing, contact F5 Support. You can't fix this at runtime, and you can't rebuild this image yourself. ### Certificate issues From 00e6f98e3b757d3697ef17c439b6428d5da245b5 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Wed, 2 Sep 2026 09:54:55 -0700 Subject: [PATCH 16/19] Revert "docs (TECHDOCS-5507): deploy NIM rootless Docker image (#317)" This reverts commit 0cb3eb4e93d3959524083e537d984ade1b4d3b9b. --- .../docker/build-nim-rootless-docker-image.md | 291 ------------- .../deploy-nim-rootless-docker-compose.md | 405 ++++++------------ 2 files changed, 140 insertions(+), 556 deletions(-) delete mode 100644 content/nim/deploy/docker/build-nim-rootless-docker-image.md diff --git a/content/nim/deploy/docker/build-nim-rootless-docker-image.md b/content/nim/deploy/docker/build-nim-rootless-docker-image.md deleted file mode 100644 index a047c39f5..000000000 --- a/content/nim/deploy/docker/build-nim-rootless-docker-image.md +++ /dev/null @@ -1,291 +0,0 @@ ---- -description: Build your own rootless NGINX Instance Manager Docker image from source, for air-gapped environments or custom image requirements. -title: Build a custom rootless Docker image -toc: true -weight: 160 -f5-docs: -f5-content-type: how-to -f5-product: NGINX Instance Manager -f5-summary: > - Build your own rootless F5 NGINX Instance Manager Docker image from source using your NGINX - subscription certificate and key. Use this path if you can't pull images from an external - registry, or if you need to customize the image. ---- - - - -## Overview - -This guide shows you how to build your own rootless F5 NGINX Instance Manager Docker image from source and deploy it with Docker Compose. All container processes run as a non-root user (`nms`). This follows the principle of least privilege for production environments. - -{{< call-out class="note" title="Note: Most deployments don't need this" >}} If you can pull images from an external registry, use an [official F5-maintained image]({{< ref "nim/deploy/docker/deploy-nim-rootless-docker-compose.md" >}}) instead. It's faster to deploy, and F5 maintains it for you. If you can't pull third-party images into your environment, or you need to customize the image, build your own instead. {{< /call-out >}} - -A key capability of this deployment is runtime configuration injection. To change NGINX Instance Manager settings, edit the environment variable files and restart the stack. You don't need to rebuild the Docker image. - -This deployment has the following key characteristics: - -- Rootless by design. All processes run as `nms` (non-root). This reduces the attack surface and satisfies security hardening requirements. -- Runtime configuration. You change NGINX Instance Manager settings by updating `docker-compose/.env` and `docker-compose.yaml`. You don't need to rebuild the image. -- Production-hardened. Startup scripts are idempotent and avoid fragile patterns, such as recursive permission changes. -- Flexible licensing. This deployment supports both connected and disconnected license modes, switchable at runtime. - ---- - -## What you need - -Before you begin, make sure you have the following: - -- [Docker Engine](https://docs.docker.com/get-docker/) 20.10 or later installed on a Linux host (amd64 or arm64). -- [Docker Compose plugin](https://docs.docker.com/compose/install/) v2 or later. -- A valid NGINX Instance Manager license file, base64-encoded. -- An NGINX certificate and private key, required to download NGINX Instance Manager packages during image build. -- Basic familiarity with Docker Compose and YAML syntax. - ---- - -## Before you start - -Clone the deployment repository to your host machine: - -```shell -git clone https://github.com/nginx/nginx-demos.git -cd nginx-demos/nginx-instance-manager/docker-deployment -``` - ---- - -## Build the NGINX Instance Manager image - -Run the build script with your NGINX certificate, key, and a name for the resulting image: - -```shell -./build.sh -C -K -t -``` - -Replace the placeholders: - -- ``: Path to your NGINX TLS certificate file. -- ``: Path to your NGINX TLS private key file. -- ``: Your preferred Docker image tag, for example `nim:latest`. - -The build script downloads NGINX Instance Manager packages from the NGINX repository. It uses your certificate and key, and produces a self-contained rootless image. - ---- - -## Configure environment variables - -Edit `docker-compose/.env` and set the following values: - -```shell -NIM_IMAGE= -NIM_LICENSE= -NIM_USERNAME= -NIM_PASSWORD= -NIM_CLICKHOUSE_ADDRESSPORT=docker-compose-clickhouse-1:9000 -NIM_CLICKHOUSE_USERNAME= -NIM_CLICKHOUSE_PASSWORD= -NIM_LICENSE_MODE_OF_OPERATION=connected -``` - -Replace `` with the tag used in the build step, and `` with your base64-encoded NGINX Instance Manager license. Set `NIM_LICENSE_MODE_OF_OPERATION` to `connected` or `disconnected`, based on your environment. See [License modes](#license-modes). - -{{< call-out class="note" title="Note: Set production credentials" >}} Before you deploy to production, change `NIM_USERNAME` and `NIM_PASSWORD` to values appropriate for your environment. {{< /call-out >}} - ---- - -## Verify docker-compose.yaml environment mappings - -Open `docker-compose.yaml` and confirm that the `nim` service passes all required variables into the container: - -```yaml -environment: - - NIM_LICENSE=${NIM_LICENSE} - - NIM_USERNAME=${NIM_USERNAME} - - NIM_PASSWORD=${NIM_PASSWORD} - - NIM_CLICKHOUSE_ADDRESSPORT=${NIM_CLICKHOUSE_ADDRESSPORT} - - NIM_CLICKHOUSE_USERNAME=${NIM_CLICKHOUSE_USERNAME} - - NIM_CLICKHOUSE_PASSWORD=${NIM_CLICKHOUSE_PASSWORD} - - NIM_LICENSE_MODE_OF_OPERATION=${NIM_LICENSE_MODE_OF_OPERATION} -``` - -If you add new configuration variables later, add a corresponding line here to make the value available inside the container. - ---- - -## Start the stack - -Start NGINX Instance Manager and its dependencies (including ClickHouse) with: - -```shell -docker compose -f docker-compose.yaml up -d -``` - ---- - -## Access the NGINX Instance Manager web interface - -After the containers start, open a browser and go to: - -```text -https://localhost/ -``` - -If prompted, accept the self-signed TLS certificate warning. Log in with the `NIM_USERNAME` and `NIM_PASSWORD` values you set in `docker-compose/.env`. - ---- - -## How runtime configuration injection works - -When the NGINX Instance Manager container starts, `startNIM.sh` reads the environment variables that Docker Compose passes in. It writes their values into the NGINX Instance Manager configuration files with `yq`, a YAML processor. The two configuration files are: - -- `/etc/nms/nms.conf` -- `/etc/nms/nms-sm-conf.yaml` - -This means NGINX Instance Manager applies fresh configuration on every container start. To change a setting, update the variable in `docker-compose/.env` and restart the stack. You don't need to rebuild the image. - -The script exposes two helper functions: - -- `set_nms_conf`: writes a value to a key path in `nms.conf`. -- `set_nms_sm`: writes a value to a key path in `nms-sm-conf.yaml`. - ---- - -## Add or change NGINX Instance Manager configuration - -To inject a new or changed configuration value, complete these steps: - -1. Add the variable to `docker-compose/.env`: - - ```shell - MY_NEW_SETTING=myvalue - ``` - -2. Pass the variable into the container in `docker-compose.yaml`: - - ```yaml - environment: - - MY_NEW_SETTING=${MY_NEW_SETTING} - ``` - -3. Map the variable to a config key in `startNIM.sh`: - - ```shell - # For nms.conf: - set_nms_conf '.path.to.config.key' MY_NEW_SETTING - - # For nms-sm-conf.yaml: - set_nms_sm '.path.to.config.key' MY_NEW_SETTING - ``` - -4. Restart the stack to apply the change: - - ```shell - docker compose -f docker-compose.yaml up -d - ``` - -You don't need to rebuild the image. - ---- - -## License modes {#license-modes} - -NGINX Instance Manager supports two license operating modes. The correct choice depends on whether your host has outbound internet access to the NGINX licensing service. - -### Connected mode - -NGINX Instance Manager contacts the NGINX licensing service directly over the internet. When the host has reliable outbound HTTPS access, use this mode. - -Set in `docker-compose/.env`: - -```shell -NIM_LICENSE_MODE_OF_OPERATION=connected -``` - -### Disconnected mode - -NGINX Instance Manager operates without outbound internet access and validates the license locally. Use this mode for air-gapped or restricted environments. - -Set in `docker-compose/.env`: - -```shell -NIM_LICENSE_MODE_OF_OPERATION=disconnected -``` - -### Switch modes at runtime - -To change the license mode without an image rebuild: - -1. Update `NIM_LICENSE_MODE_OF_OPERATION` in `docker-compose/.env`. -2. Confirm the variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. -3. Confirm the mapping exists in `startNIM.sh`: - - ```shell - set_nms_conf '.integrations.license.mode_of_operation' NIM_LICENSE_MODE_OF_OPERATION - ``` - -4. Restart the stack: - - ```shell - docker compose -f docker-compose.yaml up -d - ``` - ---- - -## Stop or remove services - -Stop the stack: - -```shell -docker compose -f docker-compose.yaml stop -``` - -Stop and remove containers and networks: - -```shell -docker compose -f docker-compose.yaml down -``` - ---- - -## Troubleshooting - -### Permission errors on startup - -All processes run as the `nms` non-root user. If you see permission errors, check that any host-mounted volumes are readable and writable by the `nms` user. Avoid recursive `chown` or `chmod` commands, because these can interfere with rootless operation. - -### Configuration changes don't take effect - -If an updated variable has no effect after a restart, verify all of the following: - -- Confirm the variable is defined in `docker-compose/.env` with the correct value. -- Confirm the variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. -- Confirm a `set_nms_conf` or `set_nms_sm` call for that variable exists in `startNIM.sh`. -- Confirm you fully restarted the stack. `docker compose up -d` re-creates containers on config change. - -### View container logs - -To inspect startup output and verify configuration injection ran successfully: - -```shell -docker compose -f docker-compose.yaml logs nim -docker compose -f docker-compose.yaml logs clickhouse -``` - -### Check container status - -```shell -docker compose -f docker-compose.yaml ps -``` - ---- - -## See also - -- [Deploy rootless using Docker Compose]({{< ref "nim/deploy/docker/deploy-nim-rootless-docker-compose.md" >}}): Use an official F5-maintained image. You don't need to build your own. -- [Deploy using Docker Compose]({{< ref "nim/deploy/docker/deploy-nginx-instance-manager-docker-compose.md" >}}): Standard, non-rootless Docker Compose deployment. -- [NGINX Instance Manager Documentation](https://docs.nginx.com/nginx-instance-manager/) -- [yq YAML Processor](https://mikefarah.gitbook.io/yq/) -- [Docker Compose Documentation](https://docs.docker.com/compose/) \ No newline at end of file diff --git a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md index 09c3d78c0..3cd08e6ba 100644 --- a/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md +++ b/content/nim/deploy/docker/deploy-nim-rootless-docker-compose.md @@ -1,39 +1,29 @@ --- -description: Deploy F5 NGINX Instance Manager using an official, F5-maintained rootless Docker image and Docker Compose. +description: Deploy F5 NGINX Instance Manager in a rootless Docker environment using Docker Compose, with runtime configuration injection using environment variables. title: Deploy rootless using Docker Compose toc: true weight: 150 -f5-docs: +f5-docs: DOCS-NIM-ROOTLESS f5-content-type: how-to f5-product: NGINX Instance Manager f5-summary: > - Deploy F5 NGINX Instance Manager using an official, F5-maintained rootless Docker image and - Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. + Deploy F5 NGINX Instance Manager in a secure, rootless Docker Compose environment where all + processes run as a non-root user. Change NGINX Instance Manager configuration at runtime using environment + variables—no image rebuild required. --- - - ## Overview -This guide shows you how to deploy F5 NGINX Instance Manager using an official rootless Docker image and Docker Compose. F5 builds and maintains this image, so you don't need to build it yourself. All container processes run as a non-root user (`nms`). - -The image includes NGINX Instance Manager, Security Monitoring, and the latest F5 WAF for NGINX compiler. +This guide shows you how to deploy F5 NGINX Instance Manager using Docker Compose in a **rootless** configuration. In this setup, all container processes run as a non-root user (`nms`), following the principle of least privilege for production environments. -{{< call-out class="note" title="Note: Building your own image" >}} If you can't pull images from an external registry, or you need to customize the image, see [Build a custom rootless Docker image]({{< ref "nim/deploy/docker/build-nim-rootless-docker-image.md" >}}) instead. {{< /call-out >}} +A key capability of this deployment is **runtime configuration injection**: you can change NGINX Instance Manager settings by editing environment variable files and restarting the stack. You don't need to rebuild the Docker image. -This deployment has the following key characteristics: +Key characteristics of this deployment: -- Rootless by design. All processes run as `nms`. The container needs no elevated privileges at runtime. -- Single persistent volume. NGINX Instance Manager stores its database, certificates, and credentials under one `/data` volume. -- First-boot initialization. On first start, the container seeds certificates and credentials automatically. -- Maintenance mode. Start the container without NGINX Instance Manager services. This lets you back up, restore, or debug safely. -- Built-in watchdog. The watchdog monitors critical NGINX Instance Manager processes. If one fails, the watchdog stops the container cleanly. +- **Rootless by design** — All processes run as `nms` (non-root), reducing the attack surface and satisfying security hardening requirements. +- **Runtime configuration** — Change NGINX Instance Manager settings by updating `.env` and `docker-compose.yaml`. You don't need to rebuild the image. +- **Production-hardened** — Startup scripts are idempotent and avoid fragile patterns such as recursive permission changes. +- **Flexible licensing** — Supports both connected and disconnected license modes, switchable at runtime. --- @@ -41,368 +31,253 @@ This deployment has the following key characteristics: Before you begin, make sure you have the following: -- [Docker Engine](https://docs.docker.com/get-docker/) 20.10 or later on a Linux host. -- [Docker Compose plugin](https://docs.docker.com/compose/install/) v2 or later. -- A JWT from your [MyF5 subscriptions page](https://my.f5.com/manage/s/subscriptions), to authenticate with the F5 image registry. -- {{}} {{}} -- ClickHouse. This compose file starts it as a bundled service. -- At least 4 CPU cores and 4 GB of memory. +- [Docker Engine](https://docs.docker.com/get-docker/) 20.10 or later installed on a Linux host (amd64 or arm64). +- Docker Compose plugin v2 or later. +- A valid NGINX Instance Manager license file, base64-encoded. +- An NGINX certificate and private key, required to download NGINX Instance Manager packages during image build. +- Basic familiarity with Docker Compose and YAML syntax. --- ## Before you start -Create the admin password file in the same directory as `docker-compose-rootless.yaml`: - -```shell -echo "" > admin_password.txt -``` - -Don't commit this file to version control. - -Log in to the F5 image registry with your JWT: +Clone the deployment repository to your host machine: ```shell -docker login private-registry.nginx.com --username= --password=none +git clone https://github.com/nginx/nginx-demos.git +cd nginx-demos/nginx-instance-manager/docker-deployment ``` --- -## Deploy NGINX Instance Manager +## Build the NGINX Instance Manager image -Start the stack: +Run the build script, supplying your NGINX certificate, key, and a name for the resulting image: ```shell -docker compose -f docker-compose-rootless.yaml up -d +./build.sh -C -K -t ``` -NGINX Instance Manager is available at `https://localhost:8443`. Log in with the admin credentials you configured. +Replace the placeholders: ---- +- `` — Path to your NGINX TLS certificate file. +- `` — Path to your NGINX TLS private key file. +- `` — Your preferred Docker image tag (for example, `nim:latest`). -## Supported environment variables - -{{}} -| Variable | Required | Description | -|---|---|---| -| `NIM_CLICKHOUSE_ADDRESSPORT` | Yes | ClickHouse address and port, for example `clickhouse:9000`. | -| `NIM_USERNAME` | Yes | Admin username, set on first boot. | -| `NIM_PASSWORD` | Yes | Admin password, set on first boot. | -| `NIM_CLICKHOUSE_USERNAME` | No | ClickHouse username. | -| `NIM_CLICKHOUSE_PASSWORD` | No | ClickHouse password. | -| `NIM_LICENSE` | No | Base64-encoded license. Activates on first boot if set. Otherwise, activate manually in the UI after deployment. | -| `NIM_LOG_LEVEL` | No | Logging verbosity: `INFO`, `DEBUG`, and so on. | -| `NIM_METRICS_TTL` | No | Metrics retention, in days (integer). | -| `NIM_EVENTS_TTL` | No | Events retention, in days (integer). | -| `NIM_SECURITY_TTL` | No | Security events retention, in days (integer). | -| `NIM_WATCHDOG_TIMEOUT` | No | Watchdog timeout, in seconds (integer). | -| `NIM_LICENSE_MODE_OF_OPERATION` | No | `connected` (default) or `disconnected`. | -| `NIM_MAINTENANCE` | No | Set to `true` to start in maintenance mode. No services launch. | -| `ENABLE_METRICS` | No | `true` or `false`. | -| `PROXY_ENABLE` | No | `true` or `false`. Turns on a forward proxy. | -| `PROXY_HOST` | No | Hostname or IP address of the proxy server. | -| `PROXY_PORT` | No | Proxy port. Default is `3128`. | -| `PROXY_PROTOCOL` | No | `http` (default) or `https`. | -| `PROXY_AUTH_REQUIRED` | No | `true` or `false`. | -| `PROXY_AUTH_USERNAME` | No | Proxy username. | -| `PROXY_PASSWORD` | No | Proxy password. Set this in your `.env` file. Don't hardcode it. | -| `PROXY_SSL_VERIFY` | No | `true` (default) or `false`. | -{{
}} +The build script downloads NGINX Instance Manager packages from the NGINX repository using your certificate and key, and produces a self-contained rootless image. --- -## Secrets - -The admin password is required. Configure it as a Docker secret: - -```yaml -secrets: - nim_admin_password: - file: admin_password.txt -``` - -Two secrets are optional: - -Custom `.htpasswd` credentials file: - -```yaml -secrets: - nim_credential_file: - file: nim_creds.txt -``` - -Custom TLS certificates for the ingress proxy: +## Configure environment variables -```yaml -secrets: - nim_proxy_cert_file: - file: ./certs/nim_cert.pem - nim_proxy_cert_key: - file: ./certs/nim_key.pem - nim_proxy_ca_cert: - file: ./certs/nim_ca.pem -``` - ---- - -## License modes - -NGINX Instance Manager supports two license operating modes, set with `NIM_LICENSE_MODE_OF_OPERATION`. A license isn't required to deploy. You can activate it later in the UI. - -Connected mode: NGINX Instance Manager contacts the NGINX licensing service directly over the internet. When the host has outbound HTTPS access, use this mode. +Edit `docker-compose/.env` and set the following values: ```shell +NIM_IMAGE= +NIM_LICENSE= +NIM_USERNAME= +NIM_PASSWORD= +NIM_CLICKHOUSE_ADDRESSPORT=docker-compose-clickhouse-1:9000 +NIM_CLICKHOUSE_USERNAME= +NIM_CLICKHOUSE_PASSWORD= NIM_LICENSE_MODE_OF_OPERATION=connected ``` -Disconnected mode: NGINX Instance Manager validates the license locally, without outbound internet access. Use this mode for air-gapped or restricted environments. +Replace `` with the tag used in the build step, and `` with your base64-encoded NGINX Instance Manager license. Set `NIM_LICENSE_MODE_OF_OPERATION` to `connected` or `disconnected` depending on your environment (see [License modes](#license-modes) below). -```shell -NIM_LICENSE_MODE_OF_OPERATION=disconnected -``` +{{< call-out class="note" >}} Change `NIM_USERNAME` and `NIM_PASSWORD` to values appropriate for your environment before deploying to production. {{< /call-out >}} --- -## Stop or remove services +## Verify docker-compose.yaml environment mappings -Stop the stack without removing data: +Open `docker-compose.yaml` and confirm that the `nim` service passes all required variables into the container: -```shell -docker compose -f docker-compose-rootless.yaml stop -``` - -Stop and remove containers and networks. Named volumes are preserved: - -```shell -docker compose -f docker-compose-rootless.yaml down +```yaml +environment: + - NIM_LICENSE=${NIM_LICENSE} + - NIM_USERNAME=${NIM_USERNAME} + - NIM_PASSWORD=${NIM_PASSWORD} + - NIM_CLICKHOUSE_ADDRESSPORT=${NIM_CLICKHOUSE_ADDRESSPORT} + - NIM_CLICKHOUSE_USERNAME=${NIM_CLICKHOUSE_USERNAME} + - NIM_CLICKHOUSE_PASSWORD=${NIM_CLICKHOUSE_PASSWORD} + - NIM_LICENSE_MODE_OF_OPERATION=${NIM_LICENSE_MODE_OF_OPERATION} ``` -{{< call-out class="warning" title="Warning: Data loss with docker compose down -v" >}} Never run `docker compose down -v`. This destroys every named volume, including the database, certificates, and credentials. {{< /call-out >}} +If you add new configuration variables later, add a corresponding line here to make the value available inside the container. --- -## Backup and restore +## Start the stack -### Back up NGINX Instance Manager +Start NGINX Instance Manager and its dependencies (including ClickHouse) with: ```shell -docker exec nim-nim-1 nim-backup +docker compose -f docker-compose.yaml up -d ``` -This creates a backup at `/data/backup/nim-backup-.tgz` inside the container. To find it on the host: - -```shell -docker inspect volume nim_nim-data | jq '.[0].Mountpoint' -sudo ls -l /var/lib/docker/volumes/nim_nim-data/_data/backup -``` +--- -### Restore NGINX Instance Manager +## Access the NGINX Instance Manager web interface -1. In `docker-compose-rootless.yaml`, set `NIM_MAINTENANCE: "true"` and restart the stack. -2. Run the restore command: +When the containers are running, open a browser and go to: -```shell - docker exec nim-nim-1 nim-restore /data/backup/nim-backup-.tgz +```text +https://localhost/ ``` -3. Set `NIM_MAINTENANCE: "false"` and restart the stack again. +Accept the self-signed TLS certificate warning if prompted. Log in using the `NIM_USERNAME` and `NIM_PASSWORD` values you set in `.env`. --- -## Storage +## How runtime configuration injection works -{{}} -| Volume | Purpose | -|---|---| -| `nim-data` | All NGINX Instance Manager persistent state: database, secrets, streaming state, credentials. | -| `nim-logs` | NGINX Instance Manager log files. | -| `nim-certs` | TLS certificates for the ingress proxy. | -| `proxy-certs` | Custom CA certificates for outbound proxy connections. | -| `clickhouse-data` | ClickHouse metrics and events database. | -| `nim-nap-compiler` | F5 WAF for NGINX compiler artifacts, mounted at `/opt/nms-nap-compiler`. | -{{
}} +When the NGINX Instance Manager container starts, `startNIM.sh` reads the environment variables that Docker Compose passes in. It writes their values into the NGINX Instance Manager configuration files using `yq`, a YAML processor. The two configuration files are: -To use NFS-backed volumes, add `driver_opts` to the volumes section in `docker-compose-rootless.yaml`: +- `/etc/nms/nms.conf` +- `/etc/nms/nms-sm-conf.yaml` -```yaml -volumes: - nim-data: - driver: local - driver_opts: - type: "nfs" - o: "addr=,rw" - device: ":/mnt/nfs_share/data" - clickhouse-data: - driver: local - driver_opts: - type: "nfs" - o: "addr=,rw" - device: ":/mnt/nfs_share/clickhouse" -``` - ---- +This means NGINX Instance Manager applies fresh configuration on every container start. You change a setting by updating the variable in `.env` and restarting the stack. You don't need to rebuild the image. -## Troubleshooting +The script exposes two helper functions: -### Container exits immediately +- `set_nms_conf` — writes a value to a key path in `nms.conf`. +- `set_nms_sm` — writes a value to a key path in `nms-sm-conf.yaml`. -Get the logs and check the last line before exit: +--- -```shell -docker compose -f docker-compose-rootless.yaml logs nim -docker compose -f docker-compose-rootless.yaml ps -a -``` +## Add or change NGINX Instance Manager configuration -{{}} -| Symptom | Fix | -|---|---| -| `admin_password.txt: no such file or directory` | Create the file: `echo "" > admin_password.txt` | -| `Error: Clickhouse TTL value must be an integer` | Set `NIM_METRICS_TTL`, `NIM_EVENTS_TTL`, or `NIM_SECURITY_TTL` to a plain integer, for example `"7"`. | -| `Error: NIM_WATCHDOG_TIMEOUT value must be an integer` | Set it to a plain integer in seconds, for example `"60"`. | -| `Error: ENABLE_METRICS value must be either true or false` | Correct the value in your compose file. | -| `Process nms- has stopped. Stopping container.` | See [NMS service crashes](#nms-service-crashes). | -{{
}} +To inject a new or changed configuration value, complete these steps: -### Permission errors +1. **Add the variable to `.env`** -The image sets ownership on all NGINX Instance Manager paths to `nms:nms` at build time. A host volume owned by root overrides this. + ```shell + MY_NEW_SETTING=myvalue + ``` -Check ownership: +2. **Pass the variable into the container in `docker-compose.yaml`** -```shell -docker compose -f docker-compose-rootless.yaml exec nim ls -la /data -``` + ```yaml + environment: + - MY_NEW_SETTING=${MY_NEW_SETTING} + ``` -Every entry must be owned by `nms`. If root owns the entries, someone pre-populated the volume as root before first boot. +3. **Map the variable to a config key in `startNIM.sh`** -- Named volumes (recommended): Don't pre-create the directory as root. Docker assigns ownership to the first writer (`nms`). -- Bind mounts: Run `sudo chown -R 101:101 /path/to/nim-data`. UID 101 is the `nms` user. + ```shell + # For nms.conf: + set_nms_conf '.path.to.config.key' MY_NEW_SETTING -### ClickHouse not reachable + # For nms-sm-conf.yaml: + set_nms_sm '.path.to.config.key' MY_NEW_SETTING + ``` -If startup loops on `Waiting for ClickHouse...`: +Then restart the stack to apply the change: ```shell -docker compose -f docker-compose-rootless.yaml ps clickhouse -docker compose -f docker-compose-rootless.yaml logs clickhouse -docker compose -f docker-compose-rootless.yaml exec nim nc -zv clickhouse 9000 +docker compose -f docker-compose.yaml up -d ``` -Both services must share the same Docker network. - -### Port binding failure - -Symptom: `bind() to 0.0.0.0:443 failed (13: Permission denied)`. - -Check that the NGINX binary has the required capability: - -```shell -docker compose -f docker-compose-rootless.yaml exec nim getcap $(which nginx) -``` +You don't need to rebuild the image. -The expected output is `/usr/sbin/nginx cap_net_bind_service=ep`. If it's missing, contact F5 Support. You can't fix this at runtime, and you can't rebuild this image yourself. +--- -### Certificate issues +## License modes {#license-modes} -Symptom: a certificate error in your browser, or NGINX fails with TLS errors, on first access. +NGINX Instance Manager supports two license operating modes. The correct choice depends on whether your host has outbound internet access to the NGINX licensing service. -Verify the certificates exist: +### Connected mode -```shell -docker compose -f docker-compose-rootless.yaml exec nim ls -la /data/certs/ -``` +NGINX Instance Manager contacts the NGINX licensing service directly over the internet. Use this mode when the host has reliable outbound HTTPS access. -You should see `manager-server.pem`, `manager-server.key`, and `ca.pem`. Then verify the symlink: +Set in `.env`: ```shell -docker compose -f docker-compose-rootless.yaml exec nim ls -la /etc/nms/certs +NIM_LICENSE_MODE_OF_OPERATION=connected ``` -The expected output shows `/etc/nms/certs -> /data/certs`. If the symlink is missing, gather the container logs and [contact F5 Support](https://www.f5.com/support). - -### NMS service crashes - -Symptom: `Process nms- has stopped. Stopping container.` +### Disconnected mode -The watchdog monitors `nms-dpm`, `nms-core`, `nms-integrations`, and `nms-ingestion` every 5 seconds. `nms-sm` (Security Monitor) isn't part of the watchdog. It can crash, and the container keeps running. +NGINX Instance Manager operates without outbound internet access and validates the license locally. Use this mode for air-gapped or restricted environments. -Identify the crashing service: +Set in `.env`: ```shell -docker compose -f docker-compose-rootless.yaml logs nim --tail=200 | grep -E "nms-(core|dpm|integrations|ingestion|sm)" +NIM_LICENSE_MODE_OF_OPERATION=disconnected ``` -- If `nms-ingestion` crashes, ClickHouse is likely unavailable. See [ClickHouse not reachable](#clickhouse-not-reachable). -- If `nms-core`, `nms-dpm`, or `nms-integrations` restarts repeatedly, restore from a recent backup. See [Backup and restore](#backup-and-restore). - -### License activation failures +### Switch modes at runtime -Symptom: the license isn't active, even though you set `NIM_LICENSE`. +To change the license mode without rebuilding the image: -Verify the license is valid base64: +1. Update `NIM_LICENSE_MODE_OF_OPERATION` in `docker-compose/.env`. +2. Confirm the variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. +3. Confirm the mapping exists in `startNIM.sh`: -```shell -echo "$NIM_LICENSE" | base64 -d | head -5 -``` - -Check for errors in the logs: + ```shell + set_nms_conf '.integrations.license.mode_of_operation' NIM_LICENSE_MODE_OF_OPERATION + ``` -```shell -docker compose -f docker-compose-rootless.yaml logs nim | grep -i license -``` +4. Restart the stack: -If activation fails, activate the license manually from the UI. For connected mode, confirm NGINX Console is reachable. See [Proxy misconfiguration](#proxy-misconfiguration). + ```shell + docker compose -f docker-compose.yaml up -d + ``` -### Proxy misconfiguration +--- -Symptom: outbound traffic (telemetry, license) fails when `PROXY_ENABLE` is set to `true`. +## Stop or remove services -Confirm that the container applied the proxy settings: +To stop the running stack: ```shell -docker compose -f docker-compose-rootless.yaml exec nim cat /etc/nms/nms.conf | grep -A 6 proxy_config +docker compose -f docker-compose.yaml stop ``` -Test proxy reachability from inside the container. A `200` or `400` response means the proxy is reachable. A `000` response means it isn't. +To stop and remove containers and networks: ```shell -docker compose -f docker-compose-rootless.yaml exec nim curl -x http://: -sS -o /dev/null -w "%{http_code}" https://product.connect.nginx.com/api/nginx-usage/batch +docker compose -f docker-compose.yaml down ``` -If your proxy uses a corporate CA, mount the PEM certificates into `/usr/local/share/ca-certificates` with the `proxy-certs` volume. For testing only, set `PROXY_SSL_VERIFY=false`. +--- -### Maintenance mode +## Troubleshooting -Use maintenance mode to back up, restore, or debug a container that won't start. In maintenance mode, the container initializes storage but doesn't start NGINX Instance Manager services or NGINX. +### Permission errors on startup -To turn it on, set `NIM_MAINTENANCE: "true"` in `docker-compose-rootless.yaml`, then restart: +All processes run as the `nms` non-root user. If you see permission errors, check that any host-mounted volumes are readable and writable by the `nms` user. Avoid using recursive `chown` or `chmod` commands, because these can interfere with rootless operation. -```shell -docker compose -f docker-compose-rootless.yaml up -d -``` +### Configuration changes not taking effect -Get shell access: +If an updated variable has no effect after a restart, verify all three steps were completed: -```shell -docker compose -f docker-compose-rootless.yaml exec nim bash -``` +- The variable is defined in `.env` with the correct value. +- The variable is listed under `environment:` in the `nim` service in `docker-compose.yaml`. +- A `set_nms_conf` or `set_nms_sm` call for that variable exists in `startNIM.sh`. +- The stack was fully restarted (`docker compose up -d` re-creates containers on config change). + +### View container logs -To turn it off, remove `NIM_MAINTENANCE` or set it to `false`, then restart: +To inspect startup output and verify configuration injection ran successfully: ```shell -docker compose -f docker-compose-rootless.yaml restart nim +docker compose -f docker-compose.yaml logs nim +docker compose -f docker-compose.yaml logs clickhouse ``` -### Gather support data +### Check running container state ```shell -docker compose -f docker-compose-rootless.yaml logs --since 24h > nim-logs-$(date +%Y-%m-%d).txt -docker exec nim-nim-1 nim-backup +docker compose -f docker-compose.yaml ps ``` --- ## See also -- [Build a custom rootless Docker image]({{< ref "nim/deploy/docker/build-nim-rootless-docker-image.md" >}}): Build your own rootless image from source, for air-gapped or custom-image environments. -- [Deploy using Docker Compose]({{< ref "nim/deploy/docker/deploy-nginx-instance-manager-docker-compose.md" >}}): Standard, non-rootless Docker Compose deployment. \ No newline at end of file +- [Deploy using Docker Compose]({{< ref "nim/deploy/docker/deploy-nginx-instance-manager-docker-compose.md" >}}) — Standard (non-rootless) Docker Compose deployment. +- [NGINX Instance Manager Documentation](https://docs.nginx.com/nginx-instance-manager/) +- [yq YAML Processor](https://mikefarah.gitbook.io/yq/) +- [Docker Compose Documentation](https://docs.docker.com/compose/) From ba0393cd7eafc405ce4a01b230041fca0458ce54 Mon Sep 17 00:00:00 2001 From: Travis Martin <33876974+travisamartin@users.noreply.github.com> Date: Wed, 2 Sep 2026 11:51:00 -0700 Subject: [PATCH 17/19] docs(DOCS-805): update NIM supported distros for 2.23 (#320) - Add Ubuntu 26.04 LTS support (NIM 2.23.0+, F5 WAF supported) - Split RHEL and Rocky Linux into separate table rows - Add Rocky Linux 10 native package support (2.23.0+) - Clarify Rocky Linux 8.x and 9.x use RHEL compatibility packages Files touched: - content/includes/nim/tech-specs/supported-distros.md --- content/includes/nim/tech-specs/supported-distros.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/includes/nim/tech-specs/supported-distros.md b/content/includes/nim/tech-specs/supported-distros.md index b75c0b016..d86fcac41 100644 --- a/content/includes/nim/tech-specs/supported-distros.md +++ b/content/includes/nim/tech-specs/supported-distros.md @@ -14,10 +14,10 @@ The following table lists the Linux distributions supported by NGINX Instance Ma |-----------------|----------------------------------------|------------------|-----------------------------------------------------|----------------------------------------------------| | Debian | 11
12
13 | x86_64
x86_64
x86_64 | Supported
Supported
Supported | Supported
Supported
Supported | | Oracle Linux | 8.0 and later in the 8.x family | x86_64 | Supported | Supported | -| RHEL and Rocky | 8.0 and later in the 8.x family
9.0 and later in the 9.x family
10.0 and later in the 10.x family | x86_64
x86_64
x86_64 | Supported
Supported
Supported | Supported
Supported
Supported only on RHEL 10 | -| Ubuntu | 22.04
24.04 | x86_64
x86_64 | Supported
Supported on 2.18.0+ | Supported
Supported | +| RHEL | 8.0 and later in the 8.x family
9.0 and later in the 9.x family
10.0 and later in the 10.x family | x86_64
x86_64
x86_64 | Supported
Supported
Supported | Supported
Supported
Supported | +| Rocky Linux | 8.0 and later in the 8.x family
9.0 and later in the 9.x family
10.0 and later in the 10.x family | x86_64
x86_64
x86_64 | Supported (via RHEL compatibility packages)
Supported (via RHEL compatibility packages)
Supported (native packages on 2.23.0+) | Supported
Supported
Supported | +| Ubuntu | 22.04
24.04
26.04 LTS | x86_64
x86_64
x86_64 | Supported
Supported on 2.18.0+
Supported on 2.23.0+ | Supported
Supported
Supported | {{}} - From 5db82f0c29cdc761130c045990c04ba7d1f62323 Mon Sep 17 00:00:00 2001 From: Travis Martin <33876974+travisamartin@users.noreply.github.com> Date: Thu, 3 Sep 2026 10:32:32 -0700 Subject: [PATCH 18/19] added 2.23 rns (#321) * added 2.23 rns * edits to rns and kis --- content/nim/releases/2.23.0-release-notes.md | 52 ++++++++++++++++ content/nim/releases/known-issues.md | 63 ++++++++++++++++++-- 2 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 content/nim/releases/2.23.0-release-notes.md diff --git a/content/nim/releases/2.23.0-release-notes.md b/content/nim/releases/2.23.0-release-notes.md new file mode 100644 index 000000000..7316bbb94 --- /dev/null +++ b/content/nim/releases/2.23.0-release-notes.md @@ -0,0 +1,52 @@ +--- +title: 2.23.0 release notes +weight: 956 +toc: true +f5content-type: reference +f5product: F5 NGINX Instance Manager +description: "Release notes for F5 NGINX Instance Manager, including new features, improvements, and bug fixes in each release." +f5-summary: > + Stay up to date with the latest features, improvements, and bug fixes in F5 NGINX Instance Manager. This document provides details about new features, known issues, and resolved problems for each version. +--- + +September 02, 2026 + +### Upgrade Paths {#2-23-0-upgrade-paths} + +NGINX Instance Manager 2.23.0 supports upgrades from these previous versions: + +- 2.20.0 - 2.22.2 + +If your NGINX Instance Manager version is older, you may need to upgrade to an intermediate version before upgrading to the target version. + +### What's new {#2-23-0-whats-new} + +This release includes the following updates: + +- {{% icon-feature %}} **Security monitoring for NGINX Gateway Fabric in NGINX Instance Manager** + + F5 NGINX Instance Manager now shows F5 WAF security events from NGINX Gateway Fabric deployments in the Security Dashboard, alongside F5 NGINX Ingress Controller events. NGINX Gateway Fabric's NGINX Agent v3 exports these events directly to NGINX Instance Manager, without requiring changes to Gateway API resources. This integration provides visibility only. NGINX Instance Manager can't manage NGINX Gateway Fabric instances, instance groups, or F5 WAF policy deployments. + + See [View NGINX Gateway Fabric security events]({{< ref "/nim/security-monitoring/ngf-security-events.md" >}}) to get started. + +- {{% icon-feature %}} **Support for Ubuntu 26.04 added** + + NGINX Instance Manager now supports Ubuntu 26.04 LTS (Resolute Racoon). + +- {{% icon-feature %}} **Rocky Linux 10 Support** + + F5 NGINX Instance Manager now includes native installation packages for Rocky Linux 10. Starting with version 2.21, Rocky Linux 10 used Red Hat Enterprise Linux 10 compatibility packages. This release adds native Rocky Linux 10 packages that F5 builds, packages, and validates. + +- {{% icon-feature %}} **New Usage Overview page for auditing raw NGINX usage data** + + NGINX Instance Manager 2.23.0 adds the **Usage Overview** page. This page gives you direct access to the raw, unaggregated usage records that NGINX Plus, NGINX Ingress Controller, and NGINX Gateway Fabric instances send, separately from the usage reports NGINX Instance Manager sends to F5. Filter, browse, and export records as a CSV file for offline audits and compliance reviews. You can configure retention from 120 days up to 1 year, and records never include hostnames, IP addresses, or other personally identifiable information. This page works in both connected and disconnected deployments. For details, see [View recent NGINX usage]({{< ref "/nim/licensing-and-reporting/view-recent-usage.md" >}}). + +### Resolved issues {#2-23-0-resolved-issues} + +This release fixes the following issues. Use your browser's search function to find the issue ID in the page. + +- {{% icon-resolved %}} Auto-downloaded WAF compiler v5.690.0 and later fails to compile policies (47651) + +### Known issues {#2-23-0-known-issues} + +You can find information about known issues in the [Known Issues]({{< ref "/nim/releases/known-issues.md" >}}) topic. diff --git a/content/nim/releases/known-issues.md b/content/nim/releases/known-issues.md index c0b29f9cc..b10a46d8b 100644 --- a/content/nim/releases/known-issues.md +++ b/content/nim/releases/known-issues.md @@ -136,6 +136,59 @@ How to re-enable mTLS for NGINX Agent and internal service connections: --- +### {{% icon-resolved %}} Auto-downloaded WAF compiler v5.690.0 and later fails to compile policies {#47651} + +| Issue ID | Status | +|----------------|--------| +| 47651 | Fixed in Instance Manager 2.23.0 | + +#### Description + +WAF compiler v5.690.0 and later can fail to compile policies on hosts where NGINX Instance Manager auto-downloaded it before you upgraded to NGINX Instance Manager 2.23.0. This release fixes the auto-download process, so new downloads no longer have this problem. + +You'll see an error like this in the NGINX Instance Manager web interface: + +```text +: failed building config payload: policy compilation failed for deployment due to integrations service error: compiler controller error: exit status 1 +``` + +The `nms.log` file also shows one of the following errors, depending on your operating system. + +**Debian or Ubuntu:** + +```text +/usr/bin/perl: symbol lookup error: /opt/nms-nap-compiler/app_protect-5.690.0/bin/../lib/perl/auto/F5/PatternMatching/PatternMatching.so: undefined symbol: _ZN3re23RE2C1ESt17basic_string_viewIcSt11char_traitsIcEERKNS0_7OptionsE +``` + +**RHEL:** + +```text +Can't load '/opt/nms-nap-compiler/app_protect-5.690.0/bin/../lib/perl/auto/F5/PatternMatching/PatternMatching.so' for module F5::PatternMatching: libre2.so.11: cannot open shared object file: No such file or directory at /usr/lib64/perl5/DynaLoader.pm +``` + +#### Workaround + +If NGINX Instance Manager auto-downloaded WAF compiler v5.690.0 or later on a host (not through `apt` or `yum`) before you upgraded to NGINX Instance Manager 2.23.0, do the following. + +1. Check the library filenames in your compiler's `lib` directory. The filenames in step 2 apply to compiler v5.690.0; later versions may bundle different library versions. + + ```shell + ls /opt/nms-nap-compiler/app_protect-/lib/ | grep -E 'libre2|libprotobuf' + ``` + +2. Replace `` with your installed compiler version and run the following command. If step 1 showed different filenames, edit the command to match before running it. + + ```shell + sudo bash -c ' + cd /opt/nms-nap-compiler/app_protect-/lib && \ + ln -sfn libre2.so.11.0.0 libre2.so.11 && \ + ln -sfn libprotobuf.so.3.21.12.0 libprotobuf.so.32 && \ + ln -sfn libprotobuf.so.32 libprotobuf.so + ' + ``` + +--- + ## 2.22.0 April 28, 2026 @@ -144,7 +197,7 @@ April 28, 2026 | Issue ID | Status | |----------------|--------| -| 47286 | Open | +| 47286 | Won't be resolved | #### Description @@ -156,7 +209,7 @@ Custom users can't perform any actions on the **Security Log Profiles** tab. | Issue ID | Status | |----------------|--------| -| 47287 | Open | +| 47287 | Won't be resolved | #### Description @@ -293,7 +346,7 @@ July 10, 2024 | Issue ID | Status | |----------------|--------| -| 45113 | Open | +| 45113 | Won't be resolved | #### Description @@ -309,7 +362,7 @@ Edit the "/etc/nginx-agent/nginx-agent.conf" file and configure "precompiled_pub | Issue ID | Status | |----------------|--------| -| 45131 | Open | +| 45131 | Won't be resolved | #### Description @@ -426,7 +479,7 @@ August 28, 2023 | Issue ID | Status | |----------------|--------| -| 43950 | Open | +| 43950 | Won't be resolved | #### Description From aeda5559b6cce6e1c1d8cba2a5b9b3f94680e348 Mon Sep 17 00:00:00 2001 From: Travis Martin Date: Thu, 3 Sep 2026 11:09:57 -0700 Subject: [PATCH 19/19] reverted regressions in policy-sources.md --- content/ngf/waf-integration/policy-sources.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/content/ngf/waf-integration/policy-sources.md b/content/ngf/waf-integration/policy-sources.md index d792b76e5..72d30b377 100644 --- a/content/ngf/waf-integration/policy-sources.md +++ b/content/ngf/waf-integration/policy-sources.md @@ -4,10 +4,10 @@ weight: 300 toc: true f5-content-type: how-to f5-product: NGINX Gateway Fabric -description: Configure WAFPolicy to fetch compiled bundles from F5 NGINX Instance Manager, F5 NGINX One Console, or an HTTP server. +description: Configure WAFPolicy to fetch compiled bundles from F5 NGINX Instance Manager, F5 NGINX One Console, an HTTP server, or Policy Lifecycle Management. --- -F5 NGINX Gateway Fabric supports three policy source types for fetching compiled F5 WAF bundles: F5 NGINX Instance Manager, F5 NGINX One Console, and direct HTTP/HTTPS URLs. For a quick start walkthrough using the HTTP source, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started-http.md" >}}). +NGINX Gateway Fabric supports four policy source types for fetching compiled WAF bundles: F5 NGINX Instance Manager, F5 NGINX One Console, direct HTTP/HTTPS URLs, and Policy Lifecycle Management (PLM). For a quick start walkthrough using the HTTP source, see [Get started with F5 WAF for NGINX]({{< ref "/ngf/waf-integration/get-started-http.md" >}}). For a walkthrough using PLM, see [Get started with F5 WAF for NGINX using PLM]({{< ref "/ngf/waf-integration/get-started-plm.md" >}}). Before you configure a policy source, make sure F5 WAF is turned on for the NginxProxy — either per Gateway or globally through Helm values. For version requirements, see [Technical specifications]({{< ref "/ngf/overview/technical-specifications.md" >}}).