docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration - #2197

Open
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm
Open

docs: Add PLM policy source tutorial and copy edits for NGF WAF integration#2197
travisamartin wants to merge 50 commits into
mainfrom
techdocs-5345-deploy-plm

Conversation

@travisamartin

@travisamartintravisamartin commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What this PR does

Adds documentation for using Policy Lifecycle Management (PLM) as a WAF policy source in NGINX Gateway Fabric, and applies style guide copy edits across the NGF WAF integration docs.


New files

content/includes/waf/plm-deploy-infrastructure.md

A shared include covering PLM backend deployment. Consumable by both the NGINX Gateway Fabric and NGINX Ingress Controller tutorials without modification. Covers:

  • PLM architecture: Policy Controller → gRPC → NAP compiler service → SeaweedFS/S3
  • Installing the four required CRDs (appolicies, aplogconfs, apusersigs, apsignatures)
  • Creating the registry pull secret
  • Helm install with plm-values.yaml (uses the version-waf-policy-controller shortcode for the chart version)
  • Verification: SeaweedFS backend readiness, Policy Controller pod, expected 8-pod output, CRD confirmation

content/includes/waf/plm-define-policy-bundle-method.md

A shared include covering the precompiled-bundle policy definition method. Product-neutral and consumable by both tutorials. Covers:

  • Referencing a .tgz bundle from an artifact registry
  • bundle.state values (pending, processing, ready, invalid)
  • isCompiled: false behavior
  • Correct update trigger: re-apply the APPolicy resource (the Policy Controller does not poll)

content/ngf/waf-integration/get-started-plm.md

New end-to-end tutorial for protecting traffic with F5 WAF for NGINX using PLM in NGINX Gateway Fabric. Covers:

  • Deploying the PLM infrastructure (pulls in the shared include above)
  • Connecting NGINX Gateway Fabric to in-cluster PLM storage
  • Defining WAF policies using three methods: inline, Git-reference, and precompiled bundle
  • Deploying a Gateway and attaching a WAFPolicy
  • Configuring HTTPRoutes
  • Validating policy compilation and application
  • Testing WAF enforcement with a sample application
  • Applying a route-level data guard override

Updated files

content/ngf/waf-integration/overview.md

content/ngf/waf-integration/policy-sources.md

content/ngf/reference/cli-help.md (PLM storage flags)

Copy edits applying the F5 style guide:

  • Replaced em dashes with commas, periods, colons, or parentheses
  • Replaced Latin abbreviations (viathrough/using)
  • Replaced since (causal) with because
  • Replaced ensure with make sure
  • Preferred contractions per Modern Voice guidelines
  • Recasted product name possessives (PLM's, NGINX Agent's)
  • Fixed placeholder casing (<namespace>/<NAMESPACE>/)
  • Replaced non-RFC-5737 IP address (10.96.20.187192.0.2.1) across six files
  • Updated f5-description in policy-sources.md to include PLM
  • Removed redundant heading in policy-sources.md

Open questions for SME review

  • Registry credentials: the install covers JWT, certificate, and key. Confirm whether a separate registry token is also required and where it is passed.
  • Private CA for bundle server: confirm the Helm value or config mechanism for trusting a private CA when using the precompiled-bundle method.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation product/ngf Issues related to NGINX Gateway Fabric product/waf Issues related to F5 WAF for NGINX labels Aug 10, 2026
@github-actions

Copy link
Copy Markdown

Deploy Preview will be available once build job completes!

NameLink
😎 Deploy Previewhttps://frontdoor-test-docs.nginx.com/previews/docs/2197/

@travisamartin
travisamartin changed the base branch from main to ngf-waf-plmAugust 10, 2026 18:22
@github-actionsgithub-actionsBot added product/nim Issues related to NGINX Instance Manager product/nginx-plus Issues related to NGINX Plus (and NGINX Open Source in docs.nginx.com) product/nginxaas-azure Issues related to NGINX as a Service for Azure tooling Back end, repository, Hugo, and all things not related to content product/dos Issues related to F5 DoS for NGINX product/nic Issues related to NGINX Ingress Controller product/nginx-one-console Issues related to NGINX One Console labels Aug 10, 2026
Comment threadcontent/ngf/waf-integration/get-started-plm.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md Outdated
@sjberman
sjberman requested a review from a teamAugust 10, 2026 19:52
@sjberman

Copy link
Copy Markdown
Contributor

We probably need some consistency brought into this doc. In NGF, we avoid placeholder values as much as possible (except for sensitive info) so that a user can just copy/paste commands. The PLM docs don't follow this right now.

@travisamartin
travisamartin marked this pull request as ready for review August 10, 2026 21:05
@travisamartin
travisamartin requested review from a team as code ownersAugust 10, 2026 21:05
@travisamartin
travisamartin deleted the branch mainAugust 10, 2026 21:06
@travisamartin
travisamartin changed the base branch from ngf-waf-plm to nginx-august-releasesAugust 10, 2026 21:10
@travisamartintravisamartin changed the title docs: Add PLM infrastructure and WAF policy sections for NGF tutorialdocs: NGF WAF + PLM tutorial and copy edits (August release)Aug 10, 2026
@travisamartintravisamartin changed the title docs: NGF WAF + PLM tutorial and copy edits (August release)docs: Add PLM policy source tutorial and copy edits for NGF WAF integrationAug 10, 2026
Comment threadcontent/includes/waf/plm-define-policy-bundle-method.md Outdated
Comment threadcontent/includes/waf/plm-deploy-infrastructure.md
travisamartinand others added 24 commits September 1, 2026 13:28
Helm installs CRDs on first install automatically, so the manual
kubectl apply step is only required when upgrading. Relocate it from
the top of the install flow (where it misled new users) to a new
"Update the CRDs" section after "Verify the deployment". Add a note
clarifying that the step can be skipped on a fresh install. Remove
the redundant CRD verification block from the upgrade section, as
the verify section already confirms CRD presence.
Also pins the GitHub raw URL to the versioned tag using the
version-waf-policy-controller shortcode, replacing the previous
reference to main.
- Rewrite registry pull secret steps to store the JWT in a
Kubernetes Secret before use, avoiding inline JWT exposure
- Add JWT download steps to get-started-plm.md prerequisites,
reorder prereqs so JWT comes before the registry Secret
- Copy edit download-jwt.md include: active voice in call-out,
bold UI labels separated, update f5-files consumer list
- Add content/includes/waf/plm-prerequisites.md with PLM-specific
prerequisites (StorageClass, Helm, JWT) and SeaweedFS storage
defaults (embedded S3 store, default pod topology, credential
Secret, HTTP-by-default note)
- Restructure get-started-plm.md Before you begin: add PLM
prerequisites subsection, add Example values H3
- Copy edit get-started-plm.md: fix causal 'since' → 'because',
remove hedge ('should show'), split two-action step, rewrite
passive results, tighten team-ownership callouts, fix directional
reference, fix 'this guide' → 'this tutorial'
- Copy edit plm-define-policy-bundle-method.md: use contraction
('doesn't poll')
The PLM chart does not generate TLS certificates. If certificates.enabled
is set to true in the seaweedfsOperatorConfig, all five Secrets (CA, master,
volume, filer, client) must be pre-created before running helm upgrade
--install. Missing Secrets cause SeaweedFS pods to fail on mount.
Add an optional TLS subsection to the 'Install the Policy Controller'
section that:
- States TLS is off by default
- Shows the certificates block with the five secretName keys
- Warns explicitly that the chart does not generate certificates
- Provides kubectl create secret commands for each required Secret
- Explains the PKI prerequisite
Resolves feedback from code review.
The SeaweedFS operator deployment becomes Available before it reconciles
the SeaweedFS CR and creates the SeaweedFS pods. This means kubectl wait
--selector app.kubernetes.io/name=seaweedfs can exit immediately with no
matches (and therefore an error) during the window between the operator
being ready and the pods being created.
Replace the two-step wait with a polling loop that retries kubectl wait
every 5 seconds until either all SeaweedFS pods are Ready or a 300s
timeout is exceeded.
- Add '#### Install the chart' heading before the helm repo add / helm
upgrade commands to visually separate them from the optional TLS
subsection. Without this heading, the install commands appeared to be
continuation content of the TLS section rather than a step for all
readers.
- Replace inline skip note on '### Update the CRDs' with a note
call-out so the upgrade-only scope is the first thing readers see
before the imperative content.
Move the sample app deployment, security logging configuration, and
APPolicy inline/Git-reference definitions from get-started-plm.md into
product-agnostic shared includes so NIC can reuse them:
- plm-sample-app.md: customers and orders Deployment/Service manifests
- plm-configure-logging.md: security namespace and APLogConf definition
- plm-define-policy-inline-git.md: APPolicy inline and Git-reference methods
The ReferenceGrant block stays inline in the NGF tutorial — NIC does not
use ReferenceGrant. The precompiled-bundle method remains in the existing
plm-define-policy-bundle-method.md include.
Addresses review comment by @ciarams87 (r3756532202).
NIC tutorials have not been created yet. Remove the placeholder
content/nic/waf-integration/get-started-plm.md f5-files entry from all
five PLM includes. These will be restored when the NIC tutorial is
written as part of the NIC work.
Add five deploy-time failure scenarios from SME review by @ohad-perets
(r3769976191) to plm-deploy-infrastructure.md:
- ImagePullBackOff: bad/expired JWT or line break in token
- Policy Controller Init:0/1: SeaweedFS not ready, PVCs pending
- SeaweedFS pods Pending: no default StorageClass
- APPolicy invalid after enabling TLS: orphaned objects in storage
- Helm ClusterRole conflict: duplicate PLM installation
Also adds the Policy Controller log command as the primary diagnostic
path, with a note that containers are distroless (kubectl exec unavailable).
The APPolicy certificate error (x509: unknown authority) is placed in
plm-define-policy-bundle-method.md as it only applies to the
precompiled-bundle method, not general deployment.
Addresses review comment by @ciarams87 and @ohad-perets (r3769976191).
Apply F5 style guide to troubleshooting content added in the previous
commit:
- Convert bold symptom labels to #### subheadings (bold.md)
- Rename heading from gerund to imperative (headings.md)
- Rewrite fragment topic sentences (paragraph-structure.md)
- Reorder conditional sentences: condition before instruction (conditional-sentences.md)
- Tighten passive constructions to active imperative (active-voice.md)
- Split sentences exceeding the 25-word conceptual limit (sentence-length.md)
- Replace contractions withheld by ASD-STE100 (contractions.md)
- Drop hedge phrase 'Note that' (modern-voice.md)
- Tighten Note in plm-define-policy-bundle-method.md: split long
sentence, remove 'must be able to'
Merge plm-define-policy-inline-git.md and plm-define-policy-bundle-method.md
into a single plm-define-policy-methods.md include that wraps all three
policy definition methods (Inline, Git reference, Precompiled bundle) in
a tabs shortcode.
Hugo tab shortcodes cannot span include boundaries, so separate includes
cannot be tabbed from a parent template. Consolidating into one include
lets the tabbed UI render correctly while keeping the content reusable
for the NIC tutorial.
The ReferenceGrant block remains inline in get-started-plm.md after the
include, as it is NGF-specific and does not belong in a shared include.
Convert the five symptom-based troubleshooting items in the PLM
infrastructure include from subheadings to {{< details >}} expandos.
Readers can scan symptom labels and expand only the relevant one.
The 'Check the Policy Controller logs' subsection stays open as a
universal diagnostic step that applies to all scenarios.
The two kubectl apply heredocs in the Git-reference tab contained
$ref: fields. Using unquoted <<EOF caused the shell to expand $ref
as an empty variable, corrupting the YAML. Changed both to <<'EOF'
to pass content literally.
All other heredocs in the PLM includes and tutorial contain no $
fields that require expansion, so their unquoted <<EOF is correct.
Apply style guide placeholder rules (all-caps, angle brackets,
PATH/TO/ for paths):
- plm-prerequisites.md: <release> -> <RELEASE>
- plm-deploy-infrastructure.md: <PATH_TO_*> -> <PATH/TO/*> for all
five TLS certificate/key placeholders and the prose reference
- get-started-plm.md: <nginx-pod-name> -> <NGINX_POD_NAME>
- Moved the skip-logging note above the include so readers see it
before deciding whether to continue with the section
- Replaced vague 'in the next steps' with a direct link to the
specific WAFPolicy section where securityLogs is configured
- configuration.md: document logRef.apLogConfRef as the PLM equivalent
of logSource
- troubleshooting.md: add RefNotPermitted condition and note PLM
APPolicy/APLogConf refs in ResolvedRefs/InvalidRef
- get-started-plm.md: add inline PLM-side compile-failure diagnosis
(bundle.state table + Policy Controller logs), link CLI flags and
storage rollout check, switch security logging to stderr for
verifiability, and note per-Gateway WAF, GRPCRoute inheritance, and
WAFPolicy conflict rules
…nal logging
The security namespace was created inside the optional 'Configure
security logging' section. Readers who skipped that section got
'namespaces "security" not found' when applying the APPolicy in
the next required step.
Fix: extract namespace creation into a new shared include
(plm-create-security-namespace.md) and pull it into the tutorial as
a required '## Create the security namespace' step that runs before
the optional logging section. The ordering is now:
1. Create the security namespace (required)
2. Configure security logging (optional)
3. Define the WAF policy (required, uses namespace: security)
Readers who skip logging still have the namespace available for
APPolicy, APLogConf, and ReferenceGrant resources.
Addresses review comment by @ohad-perets (r3823360430).
…hooting
Edit pass on text added in commit 3ab3d15:
get-started-plm.md:
- CLI flags sentence: remove 'instead of Helm', tighten phrasing
- bundle.state table: add missing 'ready' row; add sentence-ending
periods per lists.md; reword 'was stored' -> 'is stored' (present tense)
- Policy Controller logs: add -c policy-controller flag (pod has
multiple containers; omitting the flag returns an error)
- NginxProxy note: 'attach a per-Gateway NginxProxy through' ->
'create ... and reference it from' (active, imperative)
- WAFPolicy conflict note: rewrite passive 'is rejected' with clear
subject; tighten sentence length
troubleshooting.md:
- ResolvedRefs table: remove (or, for PLM, ...) and (PLM) parentheticals;
rewrite meanings as plain statements covering all source types
plm-define-policy-methods.md precompiled-bundle tab:
- namespace: plm-system -> security. APPolicy resources belong in the
security namespace (per the tutorial example values table), not the
PLM backend namespace.
- Fix update trigger wording: annotating or re-applying an unchanged
APPolicy doesn't trigger a fetch. To pick up a new bundle, update
the $ref URL and reapply. To re-fetch the same URL, delete and
recreate the APPolicy. (Per SME correction by @ohad-perets,
r3823399725.)
Also applies the same update-trigger correction to the Git-reference
tab's 'Update a Git-referenced policy' section.
plm-deploy-infrastructure.md (Ohad's comment, r3822699625):
- Fix CA Secret creation: add --from-file=tls.crt alongside ca.crt.
PLM chart components mount the CA via tls.crt; the data plane S3
client reads ca.crt. Both keys are required.
- Switch to chart-default Secret names (plm-f5-waf-seaweedfs-*) and
remove the five explicit *SecretName overrides from Helm values.
Names now match what helm show values documents.
- Add prose explaining why both CA keys are needed.
- Add forward reference from TLS caution to the troubleshooting entry
for 'APPolicy invalid with unexpected EOF after enabling TLS'.
- Fix broken anchor: replace direct expando link with link to the
Troubleshoot the deployment section heading.
Call-out audit across guide and all PLM includes:
- Promote note -> important for skip-logging, ReferenceGrant
ownership, and WAFPolicy conflict rule (reader must act)
- Promote note -> caution for enabling TLS on existing install and
Git-reference branch pin risk
- Promote note -> tip for DNS record shortcut
- Promote note -> important for private CA registry configuration
- Add informative titles to all call-outs in place of 'Note'/'Warning'
- Rewrite passive ownership sentence to active voice
- Remove hedging ('typically') from security team ownership sentence
- Split em-dash compound into two sentences (em-dash rule)
- Replace ambiguous 'it' pronouns with specific nouns throughout
- Split run-on task sentences that exceeded 20-word limit
- Convert 'Re-applying' gerund to standard verb form 'Reapplying'
- Replace em dashes with parentheses in git-ref update prose
- Replace 'enabled' with 'turned on' (enable-disable rule)
- Replace 'as-is' idiom with 'without recompilation' (global-audience)
- Rewrite passive table entries to active voice (active-voice rule)
- Replace 'decouple' with 'separate' (global-audience, simpler word)
- Remove SSL_CERT_FILE em dash; clarify ambiguous 'it' referent
@travisamartin
travisamartinforce-pushed the techdocs-5345-deploy-plm branch from b70b3a4 to c2c451aCompareSeptember 1, 2026 20:28
@travisamartin
travisamartin requested review from a team and a lite review from CopilotSeptember 1, 2026 20:32

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new end-to-end tutorial for using Policy Lifecycle Management (PLM) as a WAF policy source with NGINX Gateway Fabric, along with shared PLM include content and broad copy edits across existing NGF security/WAF docs (including new PLM storage CLI flags and RFC 5737 example IP updates).

Changes:

  • Add PLM “get started” tutorial for NGF WAF integration plus several new PLM include fragments (deploy PLM backend, policy definition methods, sample app, etc.).
  • Extend NGF WAF integration docs to document PLM as a WAFPolicy.spec.type, including ReferenceGrant behavior and PLM field differences.
  • Apply style/consistency edits and update example IPs to 192.0.2.1, plus add new PLM storage flags to CLI reference docs.

Reviewed changes

Copilot reviewed 18 out of 24 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
layouts/shortcodes/version-waf.htmlWAF version shortcode update (no functional doc flow change).
layouts/shortcodes/version-waf-policy-controller.htmlPolicy Controller version shortcode update.
layouts/shortcodes/version-waf-ip-intelligence.htmlIP Intelligence version shortcode update.
layouts/shortcodes/version-waf-enforcer.htmlEnforcer version shortcode update.
layouts/shortcodes/version-waf-config-mgr.htmlConfig Manager version shortcode update.
layouts/shortcodes/version-waf-compiler.htmlCompiler version shortcode update.
content/ngf/waf-integration/troubleshooting.mdExpand ResolvedRefs troubleshooting to cover PLM refs and ReferenceGrant restrictions.
content/ngf/waf-integration/policy-sources.mdAdd PLM as a policy source type and update navigation to the new HTTP/PLM tutorials.
content/ngf/waf-integration/overview.mdDocument PLM as a first-class source type and add an overview comparison section.
content/ngf/waf-integration/get-started-plm.mdNew PLM tutorial: install PLM backend, connect NGF to storage, define policies, and validate enforcement.
content/ngf/waf-integration/get-started-http.mdRename HTTP tutorial and add an alias to preserve the old URL.
content/ngf/waf-integration/configuration.mdAdd PLM-specific guidance for log configuration (logRef.apLogConfRef).
content/ngf/traffic-security/oidc-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/jwt-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/cors.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/traffic-security/basic-authentication.mdUpdate example Gateway IP to RFC 5737 address.
content/ngf/reference/cli-help.mdDocument new PLM storage CLI flags.
content/includes/waf/plm-sample-app.mdNew shared include: sample apps for PLM tutorial testing.
content/includes/waf/plm-prerequisites.mdNew shared include: PLM prerequisites and defaults.
content/includes/waf/plm-deploy-infrastructure.mdNew shared include: deploy PLM backend via Helm with verification/troubleshooting.
content/includes/waf/plm-define-policy-methods.mdNew shared include: define APPolicy via inline/Git/precompiled bundle methods.
content/includes/waf/plm-create-security-namespace.mdNew shared include: create the security namespace.
content/includes/waf/plm-configure-logging.mdNew shared include: define an APLogConf log profile.
content/includes/ngf/installation/nginx-plus/download-jwt.mdExpand include usage to additional install paths and update wording/call-out formatting.
Suppressed comments (1)

content/ngf/waf-integration/get-started-plm.md:112

  • This section says the PLM installation creates the credentials Secret automatically, but the example Secret manifest uses a different name/namespace (plm-storage-credentials in nginx-gateway) than the values.yaml examples above (plm-system/plm-f5-waf-seaweedfs-auth). As written, readers won’t know which Secret they should actually reference for credentialsSecretName.
kind: Secret
metadata:
name: plm-storage-credentials
namespace: nginx-gateway
type: Opaque

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Comment threadcontent/ngf/waf-integration/get-started-plm.md
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationproduct/dosIssues related to F5 DoS for NGINXproduct/ngfIssues related to NGINX Gateway Fabricproduct/nginx-one-consoleIssues related to NGINX One Consoleproduct/nginx-plusIssues related to NGINX Plus (and NGINX Open Source in docs.nginx.com)product/nginxaas-azureIssues related to NGINX as a Service for Azureproduct/nicIssues related to NGINX Ingress Controllerproduct/nimIssues related to NGINX Instance Managerproduct/wafIssues related to F5 WAF for NGINXtoolingBack end, repository, Hugo, and all things not related to content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants

@travisamartin@sjberman@ciarams87@vepatel@JTorreG@shaun-nx@ohad-perets@ViktorFefilovF5