"}},"componentScriptGroups({\"componentId\":\"custom.widget.Beta_Footer\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/nginx%20plus\"}}})":{"__typename":"ComponentRenderResult","html":" "}},"componentScriptGroups({\"componentId\":\"custom.widget.Tag_Manager_Helper\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"component({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/nginx%20plus\"}}})":{"__typename":"ComponentRenderResult","html":""}},"componentScriptGroups({\"componentId\":\"custom.widget.Consent_Blackbar\"})":{"__typename":"ComponentScriptGroups","scriptGroups":{"__typename":"ComponentScriptGroupsDefinition","afterInteractive":{"__typename":"PageScriptGroupDefinition","group":"AFTER_INTERACTIVE","scriptIds":[]},"lazyOnLoad":{"__typename":"PageScriptGroupDefinition","group":"LAZY_ON_LOAD","scriptIds":[]}},"componentScripts":[]},"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageListTabs\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageListTabs-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageView/MessageViewInline\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/Pager/PagerLoadMore\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/customComponent/CustomComponent\"]})":[{"__ref":"CachedAsset:text:en_US-components/customComponent/CustomComponent-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/OverflowNav\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTime\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTime-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageUnreadCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageViewCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageViewCount-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/kudos/KudosCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/kudos/KudosCount-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRepliesCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1751557989989"}],"cachedText({\"lastModified\":\"1751557989989\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1751557989989"}]},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"User:user:-1":{"__typename":"User","id":"user:-1","entityType":"USER","eventPath":"community:zihoc95639/user:-1","uid":-1,"login":"Former Member","email":"","avatar":null,"rank":null,"kudosWeight":1,"registrationData":{"__typename":"RegistrationData","status":"ANONYMOUS","registrationTime":null,"confirmEmailStatus":false,"registrationAccessLevel":"VIEW","ssoRegistrationFields":[]},"ssoId":null,"profileSettings":{"__typename":"ProfileSettings","dateDisplayStyle":{"__typename":"InheritableStringSettingWithPossibleValues","key":"layout.friendly_dates_enabled","value":"false","localValue":"true","possibleValues":["true","false"]},"dateDisplayFormat":{"__typename":"InheritableStringSetting","key":"layout.format_pattern_date","value":"dd-MMM-yyyy","localValue":"MM-dd-yyyy"},"language":{"__typename":"InheritableStringSettingWithPossibleValues","key":"profile.language","value":"en-US","localValue":null,"possibleValues":["en-US","en-GB","fr-FR","de-DE","ja-JP","pt-PT","pt-BR","es-ES"]},"repliesSortOrder":{"__typename":"InheritableStringSettingWithPossibleValues","key":"config.user_replies_sort_order","value":"DEFAULT","localValue":"DEFAULT","possibleValues":["DEFAULT","LIKES","PUBLISH_TIME","REVERSE_PUBLISH_TIME"]}},"deleted":false},"CachedAsset:pages-1751560861975":{"__typename":"CachedAsset","id":"pages-1751560861975","value":[{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.MvpProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/mvp-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.AdvocacyProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/advocacy-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetHelp.NonCustomer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/non-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Customer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"WorkstreamsPage","type":"COMMUNITY","urlPath":"/workstreams","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetInvolved","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.Learn","type":"COMMUNITY","urlPath":"/c/how-do-i/learn","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1739501996000,"localOverride":null,"page":{"id":"Test","type":"CUSTOM","urlPath":"/custom-test-2","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetHelp.Community","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/community","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.ContributeCode","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/contribute-code","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.Learn.AboutIrules","type":"COMMUNITY","urlPath":"/c/how-do-i/learn/about-irules","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Support","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-support","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetHelp","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI.GetHelp.SecurityIncident","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/security-incident","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1751560861975,"localOverride":null,"page":{"id":"HowDoI","type":"COMMUNITY","urlPath":"/c/how-do-i","__typename":"PageDescriptor"},"__typename":"PageResource"}],"localOverride":false},"CachedAsset:text:en_US-components/context/AppContext/AppContextProvider-0":{"__typename":"CachedAsset","id":"text:en_US-components/context/AppContext/AppContextProvider-0","value":{"noCommunity":"Cannot find community","noUser":"Cannot find current user","noNode":"Cannot find node with id {nodeId}","noMessage":"Cannot find message with id {messageId}","userBanned":"We're sorry, but you have been banned from using this site.","userBannedReason":"You have been banned for the following reason: {reason}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-0":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-0","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:theme:customTheme1-1751557990837":{"__typename":"CachedAsset","id":"theme:customTheme1-1751557990837","value":{"id":"customTheme1","animation":{"fast":"150ms","normal":"250ms","slow":"500ms","slowest":"750ms","function":"cubic-bezier(0.07, 0.91, 0.51, 1)","__typename":"AnimationThemeSettings"},"avatar":{"borderRadius":"50%","collections":["custom"],"__typename":"AvatarThemeSettings"},"basics":{"browserIcon":{"imageAssetName":"android-chrome-512x512-1748534255255.png","imageLastModified":"1748534256856","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"F5-devCentral-HR-color-reverse-1750868999153.png","imageLastModified":"1750869001512","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"fluid","oneColumnNarrowWidth":"800px","gridGutterWidthMd":"30px","gridGutterWidthXs":"10px","pageWidthStyle":"WIDTH_OF_PAGE_CONTENT","__typename":"BasicsThemeSettings"},"buttons":{"borderRadiusSm":"5px","borderRadius":"5px","borderRadiusLg":"5px","paddingY":"5px","paddingYLg":"7px","paddingYHero":"var(--lia-bs-btn-padding-y-lg)","paddingX":"12px","paddingXLg":"14px","paddingXHero":"42px","fontStyle":"NORMAL","fontWeight":"500","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"#0072B0","primaryBgHoverColor":"hsl(201.10000000000002, 100%, 29.3%)","primaryBgActiveColor":"hsl(201.10000000000002, 100%, 24.2%)","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px #0072B0, 0 0 0 4px rgba(0, 114, 176, 0.2)","secondaryTextColor":"var(--lia-bs-white)","secondaryTextHoverColor":"var(--lia-bs-white)","secondaryTextActiveColor":"var(--lia-bs-white)","secondaryBgColor":"#0072B0","secondaryBgHoverColor":"hsl(201.10000000000002, 100%, 29.3%)","secondaryBgActiveColor":"hsl(201.10000000000002, 100%, 24.2%)","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px #0072B0, 0 0 0 4px rgba(0, 114, 176, 0.2)","tertiaryTextColor":"#0072B0","tertiaryTextHoverColor":"hsl(201.10000000000002, 100%, 32.8%)","tertiaryTextActiveColor":"hsl(201.10000000000002, 100%, 31.1%)","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"rgba(0, 114, 176, 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid rgba(0, 114, 176, 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px #0072B0, 0 0 0 4px rgba(0, 114, 176, 0.2)","destructiveTextColor":"var(--lia-bs-danger)","destructiveTextHoverColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.95))","destructiveTextActiveColor":"hsl(var(--lia-bs-danger-h), var(--lia-bs-danger-s), calc(var(--lia-bs-danger-l) * 0.9))","destructiveBgColor":"var(--lia-bs-gray-300)","destructiveBgHoverColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.96))","destructiveBgActiveColor":"hsl(var(--lia-bs-gray-300-h), var(--lia-bs-gray-300-s), calc(var(--lia-bs-gray-300-l) * 0.92))","destructiveBorder":"1px solid transparent","destructiveBorderHover":"1px solid transparent","destructiveBorderActive":"1px solid transparent","destructiveBorderFocus":"1px solid transparent","destructiveBoxShadowFocus":"0 0 0 1px #0072B0, 0 0 0 4px rgba(0, 114, 176, 0.2)","__typename":"ButtonsThemeSettings"},"border":{"color":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","mainContent":"DARK","sideContent":"DARK","radiusSm":"3px","radius":"5px","radiusLg":"9px","radius50":"100vw","__typename":"BorderThemeSettings"},"boxShadow":{"xs":"0 0 0 1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.08), 0 3px 0 -1px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.16)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.12)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.3)","__typename":"BoxShadowThemeSettings"},"cards":{"bgColor":"var(--lia-panel-bg-color)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":"var(--lia-box-shadow-xs)","__typename":"CardsThemeSettings"},"chip":{"maxWidth":"300px","height":"30px","__typename":"ChipThemeSettings"},"coreTypes":{"defaultMessageLinkColor":"var(--lia-bs-primary)","defaultMessageLinkDecoration":"none","defaultMessageLinkFontStyle":"NORMAL","defaultMessageLinkFontWeight":"500","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","defaultMessageFontFamily":"var(--lia-bs-font-family-base)","forumColor":"#0C5C8D","forumFontFamily":"var(--lia-bs-font-family-base)","forumFontWeight":"var(--lia-default-message-font-weight)","forumLineHeight":"var(--lia-bs-line-height-base)","forumFontStyle":"var(--lia-default-message-font-style)","forumMessageLinkColor":"var(--lia-default-message-link-color)","forumMessageLinkDecoration":"var(--lia-default-message-link-decoration)","forumMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","forumMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","forumSolvedColor":"#62C026","blogColor":"#730015","blogFontFamily":"var(--lia-bs-font-family-base)","blogFontWeight":"var(--lia-default-message-font-weight)","blogLineHeight":"1.75","blogFontStyle":"var(--lia-default-message-font-style)","blogMessageLinkColor":"var(--lia-default-message-link-color)","blogMessageLinkDecoration":"var(--lia-default-message-link-decoration)","blogMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","blogMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","tkbColor":"#C20025","tkbFontFamily":"var(--lia-bs-font-family-base)","tkbFontWeight":"var(--lia-default-message-font-weight)","tkbLineHeight":"1.75","tkbFontStyle":"var(--lia-default-message-font-style)","tkbMessageLinkColor":"var(--lia-default-message-link-color)","tkbMessageLinkDecoration":"var(--lia-default-message-link-decoration)","tkbMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","tkbMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaColor":"#4099E2","qandaFontFamily":"var(--lia-bs-font-family-base)","qandaFontWeight":"var(--lia-default-message-font-weight)","qandaLineHeight":"var(--lia-bs-line-height-base)","qandaFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkColor":"var(--lia-default-message-link-color)","qandaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","qandaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","qandaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","qandaSolvedColor":"#3FA023","ideaColor":"#F3704B","ideaFontFamily":"var(--lia-bs-font-family-base)","ideaFontWeight":"var(--lia-default-message-font-weight)","ideaLineHeight":"var(--lia-bs-line-height-base)","ideaFontStyle":"var(--lia-default-message-font-style)","ideaMessageLinkColor":"var(--lia-default-message-link-color)","ideaMessageLinkDecoration":"var(--lia-default-message-link-decoration)","ideaMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","ideaMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","contestColor":"#FCC845","contestFontFamily":"var(--lia-bs-font-family-base)","contestFontWeight":"var(--lia-default-message-font-weight)","contestLineHeight":"var(--lia-bs-line-height-base)","contestFontStyle":"var(--lia-default-message-link-font-style)","contestMessageLinkColor":"var(--lia-default-message-link-color)","contestMessageLinkDecoration":"var(--lia-default-message-link-decoration)","contestMessageLinkFontStyle":"ITALIC","contestMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","occasionColor":"#EE4B5B","occasionFontFamily":"var(--lia-bs-font-family-base)","occasionFontWeight":"var(--lia-default-message-font-weight)","occasionLineHeight":"var(--lia-bs-line-height-base)","occasionFontStyle":"var(--lia-default-message-font-style)","occasionMessageLinkColor":"var(--lia-default-message-link-color)","occasionMessageLinkDecoration":"var(--lia-default-message-link-decoration)","occasionMessageLinkFontStyle":"var(--lia-default-message-link-font-style)","occasionMessageLinkFontWeight":"var(--lia-default-message-link-font-weight)","grouphubColor":"#491B62","categoryColor":"#949494","communityColor":"#FFFFFF","productColor":"#949494","__typename":"CoreTypesThemeSettings"},"colors":{"black":"#000000","white":"#FFFFFF","gray100":"#F7F7F7","gray200":"#F7F7F7","gray300":"#E8E8E8","gray400":"#D9D9D9","gray500":"#CCCCCC","gray600":"#949494","gray700":"#707070","gray800":"#545454","gray900":"#333333","dark":"#545454","light":"#F7F7F7","primary":"#0072B0","secondary":"#333333","bodyText":"#222222","bodyBg":"#F5F5F5","info":"#1D9CD3","success":"#62C026","warning":"#FFD651","danger":"#C20025","alertSystem":"#FF6600","textMuted":"#707070","highlight":"#FFFCAD","outline":"var(--lia-bs-primary)","custom":["#C20025","#081B85","#009639","#B3C6D7","#7CC0EB","#F29A36","#B2D7EB","#66AFD7","#007ABC","#343434","#0E6EB9","#0072B0"],"__typename":"ColorsThemeSettings"},"divider":{"size":"3px","marginLeft":"4px","marginRight":"4px","borderRadius":"50%","bgColor":"var(--lia-bs-gray-600)","bgColorActive":"var(--lia-bs-gray-600)","__typename":"DividerThemeSettings"},"dropdown":{"fontSize":"var(--lia-bs-font-size-sm)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius-sm)","dividerBg":"var(--lia-bs-gray-300)","itemPaddingY":"5px","itemPaddingX":"20px","headerColor":"var(--lia-bs-gray-700)","__typename":"DropdownThemeSettings"},"email":{"link":{"color":"#0069D4","hoverColor":"#0061c2","decoration":"none","hoverDecoration":"underline","__typename":"EmailLinkSettings"},"border":{"color":"#e4e4e4","__typename":"EmailBorderSettings"},"buttons":{"borderRadiusLg":"5px","paddingXLg":"16px","paddingYLg":"7px","fontWeight":"700","primaryTextColor":"#ffffff","primaryTextHoverColor":"#ffffff","primaryBgColor":"#0069D4","primaryBgHoverColor":"#005cb8","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","__typename":"EmailButtonsSettings"},"panel":{"borderRadius":"5px","borderColor":"#e4e4e4","__typename":"EmailPanelSettings"},"__typename":"EmailThemeSettings"},"emoji":{"skinToneDefault":"#ffcd43","skinToneLight":"#fae3c5","skinToneMediumLight":"#e2cfa5","skinToneMedium":"#daa478","skinToneMediumDark":"#a78058","skinToneDark":"#5e4d43","__typename":"EmojiThemeSettings"},"heading":{"color":"var(--lia-bs-body-color)","fontFamily":"Neusa Next Pro Wide Bold","fontStyle":"NORMAL","fontWeight":"700","h1FontSize":"30px","h2FontSize":"25px","h3FontSize":"20px","h4FontSize":"18px","h5FontSize":"16px","h6FontSize":"16px","lineHeight":"1.1","subHeaderFontSize":"11px","subHeaderFontWeight":"500","h1LetterSpacing":"normal","h2LetterSpacing":"normal","h3LetterSpacing":"normal","h4LetterSpacing":"normal","h5LetterSpacing":"normal","h6LetterSpacing":"normal","subHeaderLetterSpacing":"2px","h1FontWeight":"var(--lia-bs-headings-font-weight)","h2FontWeight":"var(--lia-bs-headings-font-weight)","h3FontWeight":"var(--lia-bs-headings-font-weight)","h4FontWeight":"var(--lia-bs-headings-font-weight)","h5FontWeight":"var(--lia-bs-headings-font-weight)","h6FontWeight":"var(--lia-bs-headings-font-weight)","__typename":"HeadingThemeSettings"},"icons":{"size10":"10px","size12":"12px","size14":"14px","size16":"16px","size20":"20px","size24":"24px","size30":"30px","size40":"40px","size50":"50px","size60":"60px","size80":"80px","size120":"120px","size160":"160px","__typename":"IconsThemeSettings"},"imagePreview":{"bgColor":"var(--lia-bs-gray-900)","titleColor":"var(--lia-bs-white)","controlColor":"var(--lia-bs-white)","controlBgColor":"var(--lia-bs-gray-800)","__typename":"ImagePreviewThemeSettings"},"input":{"borderColor":"var(--lia-bs-gray-600)","disabledColor":"var(--lia-bs-gray-600)","focusBorderColor":"var(--lia-bs-primary)","labelMarginBottom":"10px","btnFontSize":"var(--lia-bs-font-size-sm)","focusBoxShadow":"0 0 0 3px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","checkLabelMarginBottom":"2px","checkboxBorderRadius":"3px","borderRadiusSm":"var(--lia-bs-border-radius-sm)","borderRadius":"var(--lia-bs-border-radius)","borderRadiusLg":"var(--lia-bs-border-radius-lg)","formTextMarginTop":"4px","textAreaBorderRadius":"var(--lia-bs-border-radius)","activeFillColor":"var(--lia-bs-primary)","__typename":"InputThemeSettings"},"loading":{"dotDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.2)","dotLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.5)","barDarkColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.06)","barLightColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.4)","__typename":"LoadingThemeSettings"},"link":{"color":"var(--lia-bs-primary)","hoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) - 10%))","decoration":"none","hoverDecoration":"underline","__typename":"LinkThemeSettings"},"listGroup":{"itemPaddingY":"15px","itemPaddingX":"15px","borderColor":"var(--lia-bs-gray-300)","__typename":"ListGroupThemeSettings"},"modal":{"contentTextColor":"var(--lia-bs-body-color)","contentBg":"var(--lia-bs-white)","backgroundBg":"var(--lia-bs-black)","smSize":"440px","mdSize":"760px","lgSize":"1080px","backdropOpacity":0.3,"contentBoxShadowXs":"var(--lia-bs-box-shadow-sm)","contentBoxShadow":"var(--lia-bs-box-shadow)","headerFontWeight":"700","__typename":"ModalThemeSettings"},"navbar":{"position":"FIXED","background":{"attachment":null,"clip":null,"color":"var(--lia-bs-white)","imageAssetName":null,"imageLastModified":"0","origin":null,"position":"CENTER_CENTER","repeat":"NO_REPEAT","size":"COVER","__typename":"BackgroundProps"},"backgroundOpacity":0.8,"paddingTop":"15px","paddingBottom":"15px","borderBottom":"1px solid var(--lia-bs-border-color)","boxShadow":"var(--lia-bs-box-shadow-sm)","brandMarginRight":"30px","brandMarginRightSm":"10px","brandLogoHeight":"30px","linkGap":"10px","linkJustifyContent":"flex-start","linkPaddingY":"5px","linkPaddingX":"10px","linkDropdownPaddingY":"9px","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkColor":"var(--lia-bs-body-color)","linkHoverColor":"var(--lia-bs-primary)","linkFontSize":"var(--lia-bs-font-size-sm)","linkFontStyle":"NORMAL","linkFontWeight":"400","linkTextTransform":"NONE","linkLetterSpacing":"normal","linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkBgColor":"transparent","linkBgHoverColor":"transparent","linkBorder":"none","linkBorderHover":"none","linkBoxShadow":"none","linkBoxShadowHover":"none","linkTextBorderBottom":"none","linkTextBorderBottomHover":"none","dropdownPaddingTop":"10px","dropdownPaddingBottom":"15px","dropdownPaddingX":"10px","dropdownMenuOffset":"2px","dropdownDividerMarginTop":"10px","dropdownDividerMarginBottom":"10px","dropdownBorderColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.1)","controllerIconColor":"var(--lia-bs-body-color)","controllerIconHoverColor":"var(--lia-bs-body-color)","controllerTextColor":"var(--lia-nav-controller-icon-color)","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","controllerHighlightColor":"hsla(30, 100%, 50%)","controllerHighlightTextColor":"var(--lia-yiq-light)","controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerColor":"var(--lia-nav-controller-icon-color)","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","hamburgerBgColor":"transparent","hamburgerBgHoverColor":"transparent","hamburgerBorder":"none","hamburgerBorderHover":"none","collapseMenuMarginLeft":"20px","collapseMenuDividerBg":"var(--lia-nav-link-color)","collapseMenuDividerOpacity":0.16,"__typename":"NavbarThemeSettings"},"pager":{"textColor":"var(--lia-bs-link-color)","textFontWeight":"var(--lia-font-weight-md)","textFontSize":"var(--lia-bs-font-size-sm)","__typename":"PagerThemeSettings"},"panel":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-bs-border-radius)","borderColor":"var(--lia-bs-border-color)","boxShadow":"none","__typename":"PanelThemeSettings"},"popover":{"arrowHeight":"8px","arrowWidth":"16px","maxWidth":"300px","minWidth":"100px","headerBg":"var(--lia-bs-white)","borderColor":"var(--lia-bs-border-color)","borderRadius":"var(--lia-bs-border-radius)","boxShadow":"0 0.5rem 1rem hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.15)","__typename":"PopoverThemeSettings"},"prism":{"color":"#000000","bgColor":"#f5f2f0","fontFamily":"var(--font-family-monospace)","fontSize":"var(--lia-bs-font-size-base)","fontWeightBold":"var(--lia-bs-font-weight-bold)","fontStyleItalic":"italic","tabSize":2,"highlightColor":"#b3d4fc","commentColor":"#62707e","punctuationColor":"#6f6f6f","namespaceOpacity":"0.7","propColor":"#990055","selectorColor":"#517a00","operatorColor":"#906736","operatorBgColor":"hsla(0, 0%, 100%, 0.5)","keywordColor":"#0076a9","functionColor":"#d3284b","variableColor":"#c14700","__typename":"PrismThemeSettings"},"rte":{"bgColor":"var(--lia-bs-white)","borderRadius":"var(--lia-panel-border-radius)","boxShadow":" var(--lia-panel-box-shadow)","customColor1":"#bfedd2","customColor2":"#fbeeb8","customColor3":"#f8cac6","customColor4":"#eccafa","customColor5":"#c2e0f4","customColor6":"#2dc26b","customColor7":"#f1c40f","customColor8":"#e03e2d","customColor9":"#b96ad9","customColor10":"#3598db","customColor11":"#169179","customColor12":"#e67e23","customColor13":"#ba372a","customColor14":"#843fa1","customColor15":"#236fa1","customColor16":"#ecf0f1","customColor17":"#ced4d9","customColor18":"#95a5a6","customColor19":"#7e8c8d","customColor20":"#34495e","customColor21":"#000000","customColor22":"#ffffff","defaultMessageHeaderMarginTop":"14px","defaultMessageHeaderMarginBottom":"10px","defaultMessageItemMarginTop":"0","defaultMessageItemMarginBottom":"10px","diffAddedColor":"hsla(170, 53%, 51%, 0.4)","diffChangedColor":"hsla(43, 97%, 63%, 0.4)","diffNoneColor":"hsla(0, 0%, 80%, 0.4)","diffRemovedColor":"hsla(9, 74%, 47%, 0.4)","specialMessageHeaderMarginTop":"14px","specialMessageHeaderMarginBottom":"10px","specialMessageItemMarginTop":"0","specialMessageItemMarginBottom":"10px","tableBgColor":"transparent","tableBorderColor":"var(--lia-bs-gray-700)","tableBorderStyle":"solid","tableCellPaddingX":"5px","tableCellPaddingY":"5px","tableTextColor":"var(--lia-bs-body-color)","tableVerticalAlign":"middle","__typename":"RteThemeSettings"},"tags":{"bgColor":"var(--lia-bs-gray-200)","bgHoverColor":"var(--lia-bs-gray-400)","borderRadius":"var(--lia-bs-border-radius-sm)","color":"var(--lia-bs-body-color)","hoverColor":"var(--lia-bs-body-color)","fontWeight":"var(--lia-font-weight-md)","fontSize":"var(--lia-font-size-xxs)","textTransform":"UPPERCASE","letterSpacing":"0.5px","__typename":"TagsThemeSettings"},"toasts":{"borderRadius":"var(--lia-bs-border-radius)","paddingX":"12px","__typename":"ToastsThemeSettings"},"typography":{"fontFamilyBase":"Proxima Nova A Medium","fontStyleBase":"NORMAL","fontWeightBase":"500","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.2","fontSizeBase":"15px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"13px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[{"source":"SERVER","name":"Proxima Nova A Medium","styles":[{"style":"NORMAL","weight":"500","__typename":"FontStyleData"}],"assetNames":["ProximaNovaAMedium-normal-500.woff2"],"__typename":"CustomFont"},{"source":"SERVER","name":"Neusa Next Pro Wide Bold","styles":[{"style":"NORMAL","weight":"700","__typename":"FontStyleData"}],"assetNames":["NeusaNextProWideBold-normal-700.woff2"],"__typename":"CustomFont"}],"__typename":"TypographyThemeSettings"},"unstyledListItem":{"marginBottomSm":"5px","marginBottomMd":"10px","marginBottomLg":"15px","marginBottomXl":"20px","marginBottomXxl":"25px","__typename":"UnstyledListItemThemeSettings"},"yiq":{"light":"#ffffff","dark":"#000000","__typename":"YiqThemeSettings"},"colorLightness":{"primaryDark":0.36,"primaryLight":0.74,"primaryLighter":0.89,"primaryLightest":0.95,"infoDark":0.39,"infoLight":0.72,"infoLighter":0.85,"infoLightest":0.93,"successDark":0.24,"successLight":0.62,"successLighter":0.8,"successLightest":0.91,"warningDark":0.39,"warningLight":0.68,"warningLighter":0.84,"warningLightest":0.93,"dangerDark":0.41,"dangerLight":0.72,"dangerLighter":0.89,"dangerLightest":0.95,"__typename":"ColorLightnessThemeSettings"},"localOverride":false,"__typename":"Theme"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Loading/LoadingDot-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1751557989989","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1751557989989","value":{"email.verification.title":"Email Verification Required","email.verification.message.update.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. To change your email, visit My Settings.","email.verification.message.resend.email":"To participate in the community, you must first verify your email address. The verification email was sent to {email}. Resend email."},"localOverride":false},"CachedAsset:text:en_US-pages/tags/TagPage-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-pages/tags/TagPage-1751557989989","value":{"tagPageTitle":"Tag:\"{tagName}\" | {communityTitle}","tagPageForNodeTitle":"Tag:\"{tagName}\" in \"{title}\" | {communityTitle}","name":"Tags Page","tag":"Tag: {tagName}"},"localOverride":false},"CachedAsset:quilt:f5.prod:pages/tags/TagPage:community:zihoc95639-1751557989071":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/tags/TagPage:community:zihoc95639-1751557989071","value":{"id":"TagPage","container":{"id":"Common","headerProps":{"removeComponents":["community.widget.bannerWidget"],"__typename":"QuiltContainerSectionProps"},"items":[{"id":"tag-header-widget","layout":"ONE_COLUMN","bgColor":"var(--lia-bs-white)","showBorder":"BOTTOM","sectionEditLevel":"LOCKED","columnMap":{"main":[{"id":"tags.widget.TagsHeaderWidget","__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"},{"id":"messages-list-for-tag-widget","layout":"ONE_COLUMN","columnMap":{"main":[{"id":"messages.widget.messageListForNodeByRecentActivityWidget","props":{"viewVariant":{"type":"inline","props":{"useUnreadCount":true,"useViewCount":true,"useAuthorLogin":true,"clampBodyLines":3,"useAvatar":true,"useBoardIcon":false,"useKudosCount":true,"usePreviewMedia":true,"useTags":false,"useNode":true,"useNodeLink":true,"useTextBody":true,"truncateBodyLength":-1,"useBody":true,"useRepliesCount":true,"useSolvedBadge":true,"timeStampType":"conversation.lastPostingActivityTime","useMessageTimeLink":true,"clampSubjectLines":2}},"panelType":"divider","useTitle":false,"hideIfEmpty":false,"pagerVariant":{"type":"loadMore"},"style":"list","showTabs":true,"tabItemMap":{"default":{"mostRecent":true,"mostRecentUserContent":false,"newest":false},"additional":{"mostKudoed":true,"mostViewed":true,"mostReplies":false,"noReplies":false,"noSolutions":false,"solutions":false}}},"__typename":"QuiltComponent"}],"__typename":"OneSectionColumns"},"__typename":"OneColumnQuiltSection"}],"__typename":"QuiltContainer"},"__typename":"Quilt"},"localOverride":false},"CachedAsset:text:en_US-components/common/ActionFeedback-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1751557989989","value":{"joinedGroupHub.title":"Welcome","joinedGroupHub.message":"You are now a member of this group and are subscribed to updates.","groupHubInviteNotFound.title":"Invitation Not Found","groupHubInviteNotFound.message":"Sorry, we could not find your invitation to the group. The owner may have canceled the invite.","groupHubNotFound.title":"Group Not Found","groupHubNotFound.message":"The grouphub you tried to join does not exist. It may have been deleted.","existingGroupHubMember.title":"Already Joined","existingGroupHubMember.message":"You are already a member of this group.","accountLocked.title":"Account Locked","accountLocked.message":"Your account has been locked due to multiple failed attempts. Try again in {lockoutTime} minutes.","editedGroupHub.title":"Changes Saved","editedGroupHub.message":"Your group has been updated.","leftGroupHub.title":"Goodbye","leftGroupHub.message":"You are no longer a member of this group and will not receive future updates.","deletedGroupHub.title":"Deleted","deletedGroupHub.message":"The group has been deleted.","groupHubCreated.title":"Group Created","groupHubCreated.message":"{groupHubName} is ready to use","accountClosed.title":"Account Closed","accountClosed.message":"The account has been closed and you will now be redirected to the homepage","resetTokenExpired.title":"Reset Password Link has Expired","resetTokenExpired.message":"Try resetting your password again","invalidUrl.title":"Invalid URL","invalidUrl.message":"The URL you're using is not recognized. Verify your URL and try again.","accountClosedForUser.title":"Account Closed","accountClosedForUser.message":"{userName}'s account is closed","inviteTokenInvalid.title":"Invitation Invalid","inviteTokenInvalid.message":"Your invitation to the community has been canceled or expired.","inviteTokenError.title":"Invitation Verification Failed","inviteTokenError.message":"The url you are utilizing is not recognized. Verify your URL and try again","pageNotFound.title":"Access Denied","pageNotFound.message":"You do not have access to this area of the community or it doesn't exist","eventAttending.title":"Responded as Attending","eventAttending.message":"You'll be notified when there's new activity and reminded as the event approaches","eventInterested.title":"Responded as Interested","eventInterested.message":"You'll be notified when there's new activity and reminded as the event approaches","eventNotFound.title":"Event Not Found","eventNotFound.message":"The event you tried to respond to does not exist.","redirectToRelatedPage.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.title":"Showing Related Content","redirectToRelatedPageForBaseUsers.message":"The content you are trying to access is archived","redirectToRelatedPage.message":"The content you are trying to access is archived","relatedUrl.archivalLink.flyoutMessage":"The content you are trying to access is archived View Archived Content"},"localOverride":false},"CachedAsset:quiltWrapper:f5.prod:Common:1751557989536":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1751557989536","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"#343434","items":[{"id":"custom.widget.GainsightShared","props":{"widgetVisibility":"signedInOnly","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Beta_MetaNav","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"community.widget.navbarWidget","props":{"showUserName":false,"showRegisterLink":true,"useIconLanguagePicker":true,"useLabelLanguagePicker":true,"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","linkFontWeight":"700","controllerHighlightColor":"#F29A36","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkFontSize":"15px","linkBoxShadowHover":"none","backgroundOpacity":1,"controllerBorderRadius":"var(--lia-border-radius-50)","hamburgerBgColor":"transparent","linkTextBorderBottom":"none","hamburgerColor":"var(--lia-nav-controller-icon-color)","brandLogoHeight":"48px","linkLetterSpacing":"normal","linkBgHoverColor":"transparent","collapseMenuDividerOpacity":0.16,"paddingBottom":"10px","dropdownPaddingBottom":"15px","dropdownMenuOffset":"2px","hamburgerBgHoverColor":"transparent","borderBottom":"unset","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","linkJustifyContent":"center","linkColor":"var(--lia-bs-white)","collapseMenuDividerBg":"var(--lia-nav-link-color)","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","controllerTextColor":"var(--lia-nav-controller-icon-color)","background":{"imageAssetName":"","color":"var(--lia-bs-body-color)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-white)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid var(--lia-bs-white)","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","linkPaddingX":"10px","controllerTextHoverColor":"var(--lia-nav-controller-icon-hover-color)","paddingTop":"10px","linkPaddingY":"5px","linkTextTransform":"NONE","dropdownBorderColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.08)","controllerBgHoverColor":"hsla(var(--lia-bs-white-h), var(--lia-bs-white-s), var(--lia-bs-white-l), 0.1)","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkBgColor":"transparent","linkDropdownPaddingY":"9px","controllerIconColor":"var(--lia-bs-white)","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"var(--lia-bs-white)"},"links":{"sideLinks":[],"logoLinks":[],"mainLinks":[{"children":[{"linkType":"INTERNAL","id":"migrated-link-1","params":{"boardId":"TechnicalForum","categoryId":"Forums"},"routeName":"ForumBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-2","params":{"boardId":"WaterCooler","categoryId":"Forums"},"routeName":"ForumBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-0","params":{"categoryId":"Forums"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-4","params":{"boardId":"codeshare","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-5","params":{"boardId":"communityarticles","categoryId":"CrowdSRC"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-3","params":{"categoryId":"CrowdSRC"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-7","params":{"boardId":"TechnicalArticles","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"article-series","params":{"boardId":"article-series","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"security-insights","params":{"boardId":"security-insights","categoryId":"Articles"},"routeName":"TkbBoardPage"},{"linkType":"INTERNAL","id":"migrated-link-8","params":{"boardId":"DevCentralNews","categoryId":"Articles"},"routeName":"TkbBoardPage"}],"linkType":"INTERNAL","id":"migrated-link-6","params":{"categoryId":"Articles"},"routeName":"CategoryPage"},{"children":[{"linkType":"INTERNAL","id":"migrated-link-10","params":{"categoryId":"CommunityGroups"},"routeName":"CategoryPage"},{"linkType":"INTERNAL","id":"migrated-link-11","params":{"categoryId":"F5-Groups"},"routeName":"CategoryPage"}],"linkType":"INTERNAL","id":"migrated-link-9","params":{"categoryId":"GroupsCategory"},"routeName":"CategoryPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-12","params":{"boardId":"Events","categoryId":"top"},"routeName":"EventBoardPage"},{"children":[],"linkType":"INTERNAL","id":"migrated-link-13","params":{"boardId":"Suggestions","categoryId":"top"},"routeName":"IdeaBoardPage"},{"children":[],"linkType":"EXTERNAL","id":"Common-external-link","url":"https://community.f5.com/c/how-do-i","target":"SELF"}]},"className":"QuiltComponent_lia-component-edit-mode__lQ9Z6","showSearchIcon":false,"languagePickerStyle":"iconAndLabel"},"__typename":"QuiltComponent"},{"id":"community.widget.bannerWidget","props":{"backgroundColor":"#343434","visualEffects":{"showBottomBorder":false},"backgroundImageProps":{"backgroundSize":"COVER","backgroundPosition":"CENTER_CENTER","backgroundRepeat":"NO_REPEAT"},"fontColor":"var(--lia-bs-white)"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"#343434","linkHighlightColor":"#FFFFFF","visualEffects":{"showBottomBorder":true},"backgroundOpacity":100,"linkTextColor":"#FFFFFF"},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"footer":{"backgroundImageProps":{"assetName":null,"backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"CENTER_CENTER","lastModified":null,"__typename":"BackgroundImageProps"},"backgroundColor":"var(--lia-bs-body-color)","items":[{"id":"custom.widget.Beta_Footer","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Tag_Manager_Helper","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"},{"id":"custom.widget.Consent_Blackbar","props":{"widgetVisibility":"signedInOrAnonymous","useTitle":true,"useBackground":false,"title":"","lazyLoad":false},"__typename":"QuiltComponent"}],"__typename":"QuiltWrapperSection"},"__typename":"QuiltWrapper","localOverride":false},"localOverride":false},"CachedAsset:component:custom.widget.GainsightShared-en-us-1751558010090":{"__typename":"CachedAsset","id":"component:custom.widget.GainsightShared-en-us-1751558010090","value":{"component":{"id":"custom.widget.GainsightShared","template":{"id":"GainsightShared","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.GainsightShared","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Shared functions for Gainsight integration","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_MetaNav-en-us-1751558010090":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-us-1751558010090","value":{"component":{"id":"custom.widget.Beta_MetaNav","template":{"id":"Beta_MetaNav","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_MetaNav","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"MetaNav menu at the top of every page.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Beta_Footer-en-us-1751558010090":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-us-1751558010090","value":{"component":{"id":"custom.widget.Beta_Footer","template":{"id":"Beta_Footer","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Beta_Footer","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"DevCentral´s custom footer.","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Tag_Manager_Helper-en-us-1751558010090":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-us-1751558010090","value":{"component":{"id":"custom.widget.Tag_Manager_Helper","template":{"id":"Tag_Manager_Helper","markupLanguage":"HANDLEBARS","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Tag_Manager_Helper","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"CUSTOM","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"Helper widget to inject Tag Manager scripts into head element","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:component:custom.widget.Consent_Blackbar-en-us-1751558010090":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-us-1751558010090","value":{"component":{"id":"custom.widget.Consent_Blackbar","template":{"id":"Consent_Blackbar","markupLanguage":"HTML","style":null,"texts":{},"defaults":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"components":[{"id":"custom.widget.Consent_Blackbar","form":null,"config":null,"props":[],"__typename":"Component"}],"grouping":"TEXTHTML","__typename":"ComponentTemplate"},"properties":{"config":{"applicablePages":[],"description":"","fetchedContent":null,"__typename":"ComponentConfiguration"},"props":[],"__typename":"ComponentProperties"},"form":null,"__typename":"Component","localOverride":false},"globalCss":null,"form":null},"localOverride":false},"CachedAsset:text:en_US-components/community/Breadcrumb-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1751557989989","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagsHeaderWidget-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagsHeaderWidget-1751557989989","value":{"tag":"{tagName}","topicsCount":"{count} {count, plural, one {Topic} other {Topics}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1751557989989","value":{"title@userScope:other":"Recent Content","title@userScope:self":"Contributions","title@board:FORUM@userScope:other":"Recent Discussions","title@board:BLOG@userScope:other":"Recent Blogs","emptyDescription":"No content to show","MessageListForNodeByRecentActivityWidgetEditor.nodeScope.label":"Scope","title@instance:1706288370055":"Content Feed","title@instance:1743095186784":"Most Recent Updates","title@instance:1704317906837":"Content Feed","title@instance:1743095018194":"Most Recent Updates","title@instance:1702668293472":"Community Feed","title@instance:1743095117047":"Most Recent Updates","title@instance:1704319314827":"Blog Feed","title@instance:1743095235555":"Most Recent Updates","title@instance:1704320290851":"My Contributions","title@instance:1703720491809":"Forum Feed","title@instance:1743095311723":"Most Recent Updates","title@instance:1703028709746":"Group Content Feed","title@instance:VTsglH":"Content Feed"},"localOverride":false},"Category:category:Forums":{"__typename":"Category","id":"category:Forums","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"Forums"},"Forum:board:TechnicalForum":{"__typename":"Forum","id":"board:TechnicalForum","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"TechnicalForum","nodeType":"board","conversationStyle":"FORUM","title":"Technical Forum","shortTitle":"Technical Forum","parent":{"__ref":"Category:category:Forums"}},"Forum:board:WaterCooler":{"__typename":"Forum","id":"board:WaterCooler","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:Articles":{"__typename":"Category","id":"category:Articles","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"Articles"},"Tkb:board:TechnicalArticles":{"__typename":"Tkb","id":"board:TechnicalArticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"TechnicalArticles","nodeType":"board","conversationStyle":"TKB","title":"Technical Articles","shortTitle":"Technical Articles","parent":{"__ref":"Category:category:Articles"}},"Tkb:board:DevCentralNews":{"__typename":"Tkb","id":"board:DevCentralNews","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:GroupsCategory":{"__typename":"Category","id":"category:GroupsCategory","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:F5-Groups":{"__typename":"Category","id":"category:F5-Groups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:CommunityGroups":{"__typename":"Category","id":"category:CommunityGroups","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Occasion:board:Events":{"__typename":"Occasion","id":"board:Events","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"occasionPolicies":{"__typename":"OccasionPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Idea:board:Suggestions":{"__typename":"Idea","id":"board:Suggestions","boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"ideaPolicies":{"__typename":"IdeaPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:CrowdSRC":{"__typename":"Category","id":"category:CrowdSRC","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:codeshare":{"__typename":"Tkb","id":"board:codeshare","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:communityarticles":{"__typename":"Tkb","id":"board:communityarticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:security-insights":{"__typename":"Tkb","id":"board:security-insights","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:article-series":{"__typename":"Tkb","id":"board:article-series","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Conversation:conversation:341971":{"__typename":"Conversation","id":"conversation:341971","topic":{"__typename":"TkbTopicMessage","uid":341971},"lastPostingActivityTime":"2025-06-17T08:00:00.024-07:00","solved":false},"User:user:422019":{"__typename":"User","uid":422019,"login":"michealkingston","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS00MjIwMTkteVVlbW9T?image-coordinates=0%2C0%2C800%2C800"},"id":"user:422019"},"TkbTopicMessage:message:341971":{"__typename":"TkbTopicMessage","subject":"Announcing F5 NGINX Instance Manager 2.20","conversation":{"__ref":"Conversation:conversation:341971"},"id":"message:341971","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:341971","revisionNum":5,"uid":341971,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:422019"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":187},"postTime":"2025-06-17T08:00:00.024-07:00","lastPublishTime":"2025-06-17T08:00:00.024-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" We’re thrilled to announce the release of F5 NGINX Instance Manager 2.20, now available for download! This update focuses on improving accessibility, simplifying deployments, improving observability, and enriching the user experience based on valuable customer feedback. \n \n What’s New in This Release? \n \n Lightweight Mode for NGINX Instance Manager \n Reduce resource usage with the new \"Lightweight Mode\", which allows you to deploy F5 NGINX Instance Manager without requiring a ClickHouse database. While metrics and events will no longer be available without ClickHouse, all other instance management functionalities—such as certificate management, WAF, templates, and more—will work seamlessly across VM, Docker, and Kubernetes installations. \n With this change, ClickHouse becomes optional for deployments. Customers who require metrics and events should continue to include ClickHouse in their setup. For those focused on basic use cases, Lightweight Mode offers a streamlined deployment that reduces system complexity while maintaining core functionality for essential tasks. \n Lightweight Mode is perfect for customers who need simplified management capabilities for scenarios such as: \n \n \n Fleet Management \n WAF Configuration \n Usage Reporting as Part of Your Subscription (for NGINX Plus R33 or later) \n Certificate Management \n Managing Templates \n Scanning Instances \n Enabling API-based GitOps for Configuration Management \n \n \n In testing, NGINX Instance Manager worked well without ClickHouse. It only needed 1 CPU and 1 GB of RAM to manage up to 10 instances (without App Protect). However, please note that this represents the absolute minimum configuration and may result in performance issues depending on your use case. For optimal performance, we recommend allocating more appropriate system resources. \n See the updated technical specification in the documentation for more details. \n \n Support for Multiple Subscriptions \n Align and consolidate usage from multiple NGINX Plus subscriptions on a single NGINX Instance Manager instance. This feature is especially benficial for customers who use NGINX Instance Manager as a reporting endpoint, even in disconnected or air-gapped environments. This feature was added with NGINX Plus R33. \n \n Improved Licensing and Reporting for Disconnected Environments \n Managing NGINX Instance Manager in environments with no outbound internet connectivity is now simpler. Customers can configure NGINX Instance Manager to use a forward proxy for licensing and reporting. For truly air-gapped environments, we've improved offline licensing: upload your license JWT to activate all features, and enjoy a 90-day grace period to submit an initial report to F5. We've also revamped the usage reporting script to be more intuitive and backwards-compatible with older versions. \n \n Enhanced User Interface \n We’ve modernized the NGINX Instance Manager UI to streamline navigation and make it consistent with the F5 NGINX One Console. Features are now grouped into submenus for easier access. Additionally, breadcrumbs have been added to all pages for improved usability. \n \n Instance Export Enhancements \n We’ve added the ability to export instances and instance groups, simplifying the process of managing and sharing configuration details. This improvement makes it easier to keep track of large deployments and maintain consistency across environments. \n \n Performance and Stability Improvements \n With this release, we’ve made performance and stability improvements, a key part of every update to ensure NGINX Instance Manager runs smoothly in all environments. \n We’ve addressed multiple bug fixes in this release to improve stability and reliability. For more details on all the fixes included, please visit the release notes. \n \n Platform Improvements and Helm Chart Migration \n We’ve made significant enhancements to the Helm charts to simplify the installation process for NGINX Instance Manager in Kubernetes environments. Starting with this release, the Helm charts have moved to a new repository: nginx-stable/nim with chart version 2.0. \n Note: NGINX Instance Manager versions 2.19 or lower will remain in the old repository, nms-stable/nms-hybrid. Be sure to update your configurations accordingly when upgrading to version 2.20 or later. \n \n Looking Ahead: Security, Modernization, and Kubernetes Innovations \n As part of the F5 NGINX One product offering, NGINX Instance Manager continues to evolve to meet the demands of modern infrastructures. We're committed to improving security, scalability, usability, and observability to align with your needs. \n Although support for the latest F5 NGINX Agent v3 is not included in this release. We are actively exploring ways to enable it later this year to bring additional value for both NGINX Instance Manager and the NGINX One Console. \n Additionally, we’re exploring new ways to enhance support for data plane NGINX deployments, particularly in Kubernetes environments. Stay tuned for updates as we continue to innovate for cloud-native and containerized workloads. \n We’re eager to hear your feedback to help shape the roadmap for future releases. \n \n Get Started Now \n To explore the new lightweight mode, enhanced UI, and updated features, download NGINX Instance Manager 2.20. For more details on bug fixes and performance improvements, check out the full release notes. . \n \n The NGINX Impact in F5’s Application Delivery & Security Platform \n NGINX Instance Manager is part of F5’s Application Delivery & Security Platform. It helps organizations deliver, optimize, and secure modern applications and APIs. This platform is a unified solution designed to ensure reliable performance, robust security, and seamless scalability for applications deployed across cloud, hybrid, and edge architectures. \n NGINX Instance Manager is also a key component of NGINX One, the all-in-one, subscription-based package that unifies all of NGINX’s capabilities. NGINX One brings together the features of NGINX Plus, F5 NGINX App Protect, and NGINX Kubernetes and management solutions into a single, easy-to-consume package. A cornerstone of the NGINX One package, NGINX Instance Manager extends the capabilities of open-source NGINX with features designed specifically for enterprise-grade performance, scalability, and security. \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"6479","kudosSumWeight":0,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:336851":{"__typename":"Conversation","id":"conversation:336851","topic":{"__typename":"TkbTopicMessage","uid":336851},"lastPostingActivityTime":"2025-05-29T21:02:24.243-07:00","solved":false},"User:user:419867":{"__typename":"User","uid":419867,"login":"Akash_Ananthanarayan","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS00MTk4NjctQ1IwTHhL?image-coordinates=0%2C420%2C1080%2C1500"},"id":"user:419867"},"TkbTopicMessage:message:336851":{"__typename":"TkbTopicMessage","subject":"F5 NGINX Plus R33 Licensing and Usage Reporting","conversation":{"__ref":"Conversation:conversation:336851"},"id":"message:336851","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:336851","revisionNum":15,"uid":336851,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:419867"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":616},"postTime":"2024-11-20T08:45:00.035-08:00","lastPublishTime":"2024-11-20T08:45:00.035-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Beginning with F5 NGINX Plus version R33, all customers are required to deploy a JSON Web Token (JWT) license for each commercial instance of NGINX Plus. Each instance is responsible for validating its own license status. Furthermore, NGINX Plus will report usage either to the F5 NGINX licensing endpoint or to the F5 NGINX Instance Manager for customers who are connected. For those customers who are disconnected or operate in an air-gapped environment, usage can be reported directly to the F5 NGINX Instance Manager. \n To learn more about the latest features of NGINX R33, please check out the recent blog post. \n \n Install or Upgrade NGINX Plus R33 \n To successfully upgrade to NGINX Plus R33 or perform a fresh installation, begin by downloading the JWT license from your F5 account. Once you have the license, place it in the F5 NGINX directory before proceeding with the upgrade. For a fresh installation, after completing the installation, also place the JWT license in the NGINX directory. For further details, please refer to the provided instructions. \n This video provides a step-by-step guide on installing or upgrading to NGINX Plus R33. \n \n \n Report Usage to F5 in Connected Environment \n To effectively report usage data to F5 within a connected environment using NGINX Instance Manager, it's important to ensure that port 443 is open. The default configuration directs the usage endpoint to send reports directly to the F5 licensing endpoint at product.connect.nginx.com. By default, usage reporting is enabled, and it's crucial to successfully send at least one report on installation for NGINX to process traffic. \n However, you can postpone the initial reporting requirement by turning off the directive in your NGINX configuration. This allows NGINX Plus to handle traffic without immediate reporting during a designated grace period. To configure usage reporting to F5 using NGINX Instance Manager, update the usage endpoint to reflect the fully qualified domain name (FQDN) of the NGINX Instance Manager. \n For further details, please refer to the provided instructions. \n This video shows how to report usage in the connected environment using NGINX Instance Manager. \n \n \n Report Usage to F5 in Disconnected Environment using NGINX Instance Manager \n In a disconnected environment without an internet connection, you need to take certain steps before submitting usage data to F5. First, in NGINX Plus R33, update the `usage report` directive within the management block of your NGINX configuration to point to your NGINX Instance Manager host. Ensure that your NGINX R33 instances can access the NGINX Instance Manager by setting up the necessary DNS entries. \n Next, in the NMS configuration in NGINX Instance Manager, modify the ‘mode of operation’ to disconnected, save the file, and restart NGINX Instance Manager. \n There are multiple methods available for adding a license and submitting the initial usage report in this disconnected environment. You can use a Bash script, REST API, or the web interface. For detailed instructions on each method, please refer to the documentation. \n This video shows how to report usage in disconnected environments using NGINX Instance Manager. \n \n \n \n Conclusion \n The transition to NGINX Plus R33 introduces important enhancements in licensing and usage reporting that can greatly improve your management of NGINX instances. With the implementation of JSON Web Tokens (JWT), you can validate your subscription and report telemetry data more effectively. To ensure compliance and optimize performance, it’s crucial to understand the best practices for usage reporting, regardless of whether you are operating in a connected or disconnected environment. \n Get started today with a 30-day trial, and contact us if you have any questions. \n \n Resources \n \n NGINX support documentation \n Blog announcement providing a comprehensive summary of the new features in this release. \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"4026","kudosSumWeight":3,"repliesCount":3,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:340695":{"__typename":"Conversation","id":"conversation:340695","topic":{"__typename":"TkbTopicMessage","uid":340695},"lastPostingActivityTime":"2025-04-28T05:00:00.040-07:00","solved":false},"User:user:427467":{"__typename":"User","uid":427467,"login":"Anu_Soni","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-8.svg?time=0"},"id":"user:427467"},"TkbTopicMessage:message:340695":{"__typename":"TkbTopicMessage","subject":"F5 NGINX API Gateway: Simplify Response Manipulation","conversation":{"__ref":"Conversation:conversation:340695"},"id":"message:340695","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:340695","revisionNum":5,"uid":340695,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:427467"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Discover how NGINX API Gateway, powered by the NJS module, can dynamically manipulate API responses to enhance functionality without backend changes. This article walks through a basic hands-on example of incrementing response values, explores batching API requests with NGINX Plus for better performance, and shares best practices from F5. Learn how to optimize your APIs, reduce latency, and unlock new possibilities with NGINX and F5’s expert solutions. Read more to transform your API strategy today! ","introduction":"","metrics":{"__typename":"MessageMetrics","views":221},"postTime":"2025-04-28T05:00:00.040-07:00","lastPublishTime":"2025-04-28T05:00:00.040-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" In the fast-evolving world of digital applications, APIs are the unsung heroes driving seamless connectivity. But what if you could elevate your APIs to deliver more value—without overhauling your backend? With the F5 NGINX API Gateway, powered by the lightweight NGINX Javascript NJS) module, you can dynamically manipulate API responses, streamline operations, and delight your users. In this article, we'll walk you through a hands-on example of response manipulation using F5 NGINX API Gateway, highlight the power of batching API requests with F5 NGINX Plus, and share best practices to ensure success. Ready to transform your API strategy? Let's get started! \n \n A Hands-On Example: Boosting API Responses with F5 NGINX API Gateway \n Let's consider a practical scenario. You manage a simple API server that returns numeric values, but your business team wants to increment each response value by 10 for a promotional campaign. Instead of modifying the backend, you can use F5 NGINX API Gateway to handle this at the gateway layer, saving time and keeping your backend lean. \n Step 1: The Backend API \n Let’s start by creating a simple Node.js Express application (app.js) to serve as our backend API. For this example, we’ll assume Node.js is already installed on an Ubuntu 24.04 server. In my setup, the backend API runs on the IP address 10.1.1.5, which we’ll reference later in the nginx.conf file for proxying requests. Here’s how to get the backend up and running: \n // Import the Express framework to create a web server\nconst express = require('express');\n// Initialize an Express application instance\nconst app = express();\n\n// Add middleware to log incoming requests for debugging purposes\napp.use((req, res, next) => {\n // Log the request method, URL, and headers in a formatted string\n console.log(`Received request: ${req.method} ${req.url} Headers: ${JSON.stringify(req.headers)}`);\n // Call the next middleware or route handler in the chain\n next();\n});\n\n// Define a GET route for '/api/v1/1' that returns a JSON response with value 100\napp.get('/api/v1/1', (req, res) => res.json({ value: 100 }));\n// Define a GET route for '/api/v1/2' that returns a JSON response with value 200\napp.get('/api/v1/2', (req, res) => res.json({ value: 200 }));\n// Define a GET route for '/api/v1/3' that returns a JSON response with value 300\napp.get('/api/v1/3', (req, res) => res.json({ value: 300 }));\n// Define a GET route for '/api/v1' that returns a JSON response with value 10\napp.get('/api/v1', (req, res) => res.json({ value: 10 }));\n\n// Start the Express server on port 3050, listening on all network interfaces ('0.0.0.0')\napp.listen(3050, '0.0.0.0', () => console.log('API server running on port 3050')); \n This server returns JSON responses like {\"value\": 100}. Now, let's enhance these responses using NGINX. \n Step 2: NGINX Configuration \n Next, configure NGINX (nginx.conf) to proxy requests to the backend and manipulate the responses using the NJS module: \n # Load the njs module to enable dynamic scripting capabilities \nload_module /usr/lib/nginx/modules/ngx_http_js_module.so; \n\nuser nginx; \nworker_processes auto; \nerror_log /var/log/nginx/error.log debug; \npid /var/run/nginx.pid; \n\nevents { \n worker_connections 1024; \n} \n\n http { \n include /etc/nginx/mime.types; \n default_type application/octet-stream; \n\n # Import the njs script 'manipulate.js' and alias it as 'manipulate' \n js_import manipulate from /etc/nginx/njs/manipulate.js; \n\n server { \n listen 80; \n location /api/ { \n # Proxy requests to the backend server running on 10.1.1.5:3050 \n proxy_pass http://10.1.1.5:3050; \n proxy_set_header Host $host; \n proxy_set_header X-Real-IP $remote_addr; \n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; \n proxy_set_header X-Forwarded-Proto $scheme; \n proxy_buffer_size 128k; \n proxy_buffers 4 256k; \n proxy_busy_buffers_size 256k; \n proxy_connect_timeout 5s; \n proxy_read_timeout 10s; \n\n # Apply the njs body filter to manipulate the response before sending to the client \n js_body_filter manipulate.manipulateBodyFilter; \n } \n } \n} \n The js_body_filter directive is where the magic happens—it calls the NJS script to modify the response. \n Step 3: The NJS Script for Response Manipulation \n Here’s the NJS script (manipulate.js) that adds 10 to the value field in each response: \n // Define the body filter function to manipulate API responses \nfunction manipulateBodyFilter(r, data, flags) { \n try { \n // Check if there is no data in the response chunk \n if (!data) { \n // If no data, send an empty buffer to the client and exit \n r.sendBuffer(\"\", flags); \n return; \n } \n // Log the received data chunk for debugging purposes \n r.log(\"Received chunk: \" + data); \n // Store the data chunk in a variable (body filter processes data in chunks) \n let body = data; \n // Parse the data as JSON to work with the response object \n let parsedBody = JSON.parse(body); \n // Validate that the 'value' field exists and is a number \n if (parsedBody.value === undefined || typeof parsedBody.value !== 'number') { \n // Log an error if the response format is invalid \n r.error(\"Invalid response format: 'value' missing or not a number\"); \n // Send an error message to the client and exit \n r.sendBuffer(\"Invalid response format\", flags); \n return; \n } \n // Increment the 'value' field by 10 to modify the response \n parsedBody.value = parsedBody.value + 10; \n // Convert the modified object back to JSON and send it to the client \n r.sendBuffer(JSON.stringify(parsedBody), flags); \n } catch (e) { \n // Log any errors that occur during processing (e.g., JSON parsing failure) \n r.error(\"NJS Error in body filter: \" + e.message); \n // Send an error message to the client with the error details \n r.sendBuffer(\"Internal Server Error: \" + e.message, flags); \n } \n} \n// Export the manipulateBodyFilter function for use in NGINX configuration \nexport default { manipulateBodyFilter }; \n \n How It Works \n \n A client sends a request to /api/v1/1 via NGINX. \n NGINX proxies the request to the backend, which responds with {\"value\": 100}. \n The js_body_filter intercepts the response, adds 10 to the value, and sends {\"value\": 110} to the client. \n \n Test it with curl http://<nginx-ip>/api/v1/1 and see the modified response in action. It’s a seamless way to enhance your APIs without backend changes! \n Why This Matters \n Using NGINX API Gateway for response manipulation saves development time, reduces backend complexity, and allows dynamic adjustments. Whether adding fields, transforming data, or enforcing policies, NGINX gives you the flexibility to adapt quickly. \n Batching API Requests: Efficiency with F5 NGINX Plus \n For efficiency, you should take a quick look at the F5 blog post “Batching API Requests with NGINX Plus and the JavaScript Module”. This article showcases how F5 NGINX Plus can batch multiple API calls into a single HTTP request, reducing latency and server load. \n Using NJS, you can create a custom request handler to aggregate API calls server-side (Aggregation means combining multiple API requests into one on the server side). The article provides a practical example of implementing request batching with F5 NGINX Plus. This technique optimises resource usage and speeds up client response times. \n Why It’s a Game-Changer \n \n Lower Latency: Fewer round trips to the backend. \n Scalability: Offload processing to NGINX Plus. \n Customization: Tailor batching logic with JavaScript. \n \n Combine this with response manipulation, and you’ve got an API Gateway that’s both intelligent and efficient. \n Best Practices for NGINX API Gateway Success \n To ensure your NGINX API Gateway deployment shines, here are some best practices from F5’s “Deploying NGINX as an API Gateway” whitepaper \n \n Optimize Buffers: Configure proxy_buffer_size and proxy_buffers to handle larger responses smoothly. \n Set Timeouts: Use proxy_connect_timeout and proxy_read_timeout to prevent hanging requests. \n Handle Errors Gracefully: As shown in manipulate.js, always include error handling and logging. \n Prioritize Security: Implement authentication and rate limiting with NGINX Plus to safeguard your APIs. \n Start Small, Scale Up: Begin with simple logic, then expand as needed. \n \n Explore More with NJS Examples \n Looking for inspiration? The NGINX njs Examples on GitHub offers a treasure trove of use cases, from authentication to content rewriting. It’s the perfect resource to fuel your NGINX API Gateway journey. \n Why Choose NGINX with F5? \n NGINX, backed by F5’s world-class expertise, is more than a tool—it’s a strategic advantage. Whether using open-source NGINX or unlocking advanced features with F5 NGINX Plus, you get unmatched performance, flexibility, and support. Ready to make your APIs a competitive edge? Contact F5 today to see how NGINX can accelerate your business. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"9303","kudosSumWeight":0,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:340832":{"__typename":"Conversation","id":"conversation:340832","topic":{"__typename":"TkbTopicMessage","uid":340832},"lastPostingActivityTime":"2025-04-17T07:00:00.029-07:00","solved":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDA4MzItNUdLcUxF?revision=3\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDA4MzItNUdLcUxF?revision=3","title":"NGINXaaS (1).png","associationType":"BODY","width":3564,"height":1725,"altText":""},"TkbTopicMessage:message:340832":{"__typename":"TkbTopicMessage","subject":"Unlocking Insights: Enhancing Observability in F5 NGINXaaS for Azure for Optimal Operations","conversation":{"__ref":"Conversation:conversation:340832"},"id":"message:340832","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:340832","revisionNum":3,"uid":340832,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:419867"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":150},"postTime":"2025-04-17T07:00:00.029-07:00","lastPublishTime":"2025-04-17T07:00:00.029-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Introduction \n To understand application performance, you need more than just regular health checks. You need to look at the system’s behavior, how users use it, and find possible slowdowns before they become big problems. \n By using F5 NGINXaaS for Azure, organizations can gain enhanced visibility into their backend applications through extensive metrics, API (access) logs, and operational logs within Azure environments. This proactive approach helps prevent minor issues from developing into major challenges while optimizing resource efficiency. \n This technical guide highlights advanced observability techniques and demonstrates how organizations can leverage F5 NGINXaaS to create robust, high-performing application delivery solutions that ensure seamless and responsive user experiences. \n \n Benefits of F5 NGINX as a Service \n F5 NGINXaaS for Azure provides robust integration with ecosystem tools designed to monitor and analyze application health and performance. It uses rich telemetry from granular metrics across various protocols, including HTTP, TLS, TCP, and UDP. For technical experts overseeing deployments in Azure, this service delivers valuable insights that facilitate more effective troubleshooting and optimize workflows for streamlined operations. \n Key advantages of F5 NGINXaaS include access to over 200 detailed health and performance metrics that are critical for ensuring application stability, scalability, and efficiency. Please refer to the documentation for detailed information to learn more about the available metrics. \n There are two ways to monitor metrics in F5 NGINXaaS for Azure, providing flexibility in how you can track the health and performance of your applications: \n \n Azure Monitoring Integration for F5 NGINXaaS: An Azure-native solution delivering detailed analytical reports and customizable alerts. \n \n \n Grafana Dashboard Support: A visualization tool specifically designed to provide real-time, actionable insights into system health and performance. \n \n \n \n \n Dive Deep with Azure Monitoring for F5 NGINXaaS \n Azure Monitoring integration with F5 NGINXaaS provides a comprehensive observability solution tailored to dynamic cloud environments, equipping teams with the tools to enhance application performance and reliability. A crucial aspect of this solution is the integration of F5 NGINXaaS access and error logs, which offers insights essential for troubleshooting and resolving issues effectively. By combining these logs with deep insights into application and performance metrics such as request throughput, latency, error rates, and resource utilization, technical teams can make informed decisions to optimize their applications. \n Key Features Include: \n \n Advanced Analytics: Explore detailed traffic patterns and usage trends to better understand application load dynamics. This allows teams to fine-tune configurations and improve performance based on actual user activity. \n \n \n Customizable Alerts: Set specific thresholds for key performance indicators to receive immediate notifications about anomalies, such as unexpected spikes in 5xx error rates or latency challenges. This proactive approach empowers teams to resolve incidents swiftly and minimize their impact. \n \n \n Detailed Metrics: Utilize comprehensive metrics encompassing connection counts, active connections, and request processing times. These insights facilitate better resource allocation and more efficient traffic management. \n \n \n Logs Integration: Access and analyze F5 NGINXaaS logs alongside performance metrics, providing a holistic view of application behavior. This integration is vital for troubleshooting, enabling teams to correlate log data with observability insights for effective issue identification and resolution. \n \n \n Scalability Insights: Monitor real-time resource allocation and consumption. Predict growth challenges and optimize scaling decisions to ensure your F5 NGINXaaS service deployments can handle variable client load effectively. \n \n By integrating Azure Monitoring with F5 NGINXaaS, organizations can significantly enhance their resilience, swiftly tackle performance challenges, and ensure that their services consistently deliver outstanding user experiences. With actionable data at their fingertips, teams are well-positioned to achieve operational excellence and foster greater user satisfaction. \n \n Visualize Success with Native Azure Grafana Dashboard \n Enable the Grafana dashboard and import the F5 NGINXaaS metrics dashboard to take your monitoring capabilities to the next level. This dynamic integration provides a clear view of various performance metrics, allowing teams to make informed decisions backed by insightful data. \n Together, Azure Monitoring and the Grafana Dashboard form a strong alliance, creating a comprehensive observability solution that amplifies your application’s overall performance and reliability. \n The Grafana interface allows real-time querying of performance metrics, offering intuitive visual tools like graphs and charts that simplify complex data interpretation. With Azure Monitoring, Grafana builds a robust observability stack, ensuring proactive oversight and reactive diagnostics. \n \n Getting Started with NGINXaaS Azure Workshop \n We have curated self-paced workshops designed to help you effectively leverage the enhanced observability features of F5 NGINXaaS. These workshops provide valuable insights and hands-on experience, empowering you to develop robust observability in a self-directed learning environment. \n Azure monitoring lab workshop will enhance your skills in creating and analyzing access logs with NGINX. You’ll learn to develop a comprehensive log format, capturing essential details from backend servers. By the end, you'll be equipped to use Azure’s monitoring tools effectively, significantly contributing to your growth and success. \n In the Native Azure Grafana Dashboard workshop, you'll explore the integration of F5 NGINXaaS for Azure with Grafana for effective service monitoring. You'll create a dashboard to track essential metrics for your backend servers. This hands-on session will equip you with the skills to analyze real-time data and make informed decisions backed by valuable insights. \n Upon completing this lab exercise, you will have gained practical expertise in leveraging enhanced observability features of F5 NGINXaaS. You will be proficient in creating and analyzing access logs, ensuring you can effectively capture critical data from backend servers. Additionally, you will have developed the skills necessary to integrate F5 NGINXaaS with Grafana, allowing you to build a dynamic dashboard that tracks essential metrics in real-time. This hands-on experience will empower you to make informed decisions based on valuable insights, significantly enhancing your capabilities in monitoring and maintaining your applications. \n \n Conclusion \n By fully utilizing the observability features of F5 NGINXaaS, the organization can gain valuable insights that enhance performance and efficiency. With Azure Monitoring and Grafana working together, teams can manage proactively and make informed, data-driven decisions. This approach leads to smoother web experiences and improves operational performance. \n Interested in getting started with F5 NGINXaaS for Azure? You can find us on the Azure marketplace. \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"7646","kudosSumWeight":1,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDA4MzItNUdLcUxF?revision=3\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:340552":{"__typename":"Conversation","id":"conversation:340552","topic":{"__typename":"TkbTopicMessage","uid":340552},"lastPostingActivityTime":"2025-04-07T10:50:51.723-07:00","solved":false},"User:user:37113":{"__typename":"User","uid":37113,"login":"route443","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0zNzExMy1XdTJXRWo?image-coordinates=0%2C0%2C1100%2C1100"},"id":"user:37113"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDA1NTItd1JLMXVT?revision=7\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDA1NTItd1JLMXVT?revision=7","title":"OIDC.png","associationType":"TEASER","width":1113,"height":626,"altText":""},"TkbTopicMessage:message:340552":{"__typename":"TkbTopicMessage","subject":"Simplifying OIDC and SSO with the New NGINX Plus R34 OIDC Module","conversation":{"__ref":"Conversation:conversation:340552"},"id":"message:340552","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:340552","revisionNum":7,"uid":340552,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:37113"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" ","introduction":"","metrics":{"__typename":"MessageMetrics","views":466},"postTime":"2025-04-01T08:00:00.041-07:00","lastPublishTime":"2025-04-07T10:50:51.723-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Introduction: Why OIDC and SSO Matter \n As web infrastructures scale and modernize, strong and standardized methods of authentication become essential. OpenID Connect (OIDC) provides a flexible layer on top of OAuth 2.0, enabling both user authentication (login) and authorization (scopes, roles). By adopting OIDC for SSO, you can: \n \n Provide a frictionless login experience across multiple services. \n Consolidate user session management, removing custom auth code from each app. \n Lay a foundation for Zero Trust policies, by validating and enforcing identity at the network’s edge. \n \n While Zero Trust is a broader security model that extends beyond SSO alone, implementing OIDC at the proxy level is an important piece of the puzzle. It ensures that every request is associated with a verified identity, enabling fine-grained policies and tighter security boundaries across all your applications. \n NGINX, acting as a reverse proxy, is an ideal place to manage these OIDC flows. However, the journey to robust OIDC support in NGINX has evolved - from an njs-based approach with scripts and maps, to a far more user-friendly native module in NGINX Plus R34. \n The njs-based OIDC Solution \n Before the native OIDC module, many users turned to the njs-based reference implementation. This setup combines multiple pieces: \n \n njs script to handle OIDC flows (redirecting to the IdP, exchanging tokens, etc.). \n auth_jwt module for token validation. \n keyval module to store and pair a session cookie with the actual ID token. \n \n While it covers the essential OIDC steps (redirects, code exchanges, and forwarding claims), it has some drawbacks: \n \n Configuration complexity. Most of the logic hinges on creative usage of NGINX directives (like map), which can be cumbersome, especially if you used more than one authentication provider or your environment changes frequently. \n Limited Metadata Discovery. It doesn’t natively fetch the IdP’s `.well-known/openid-configuration`. Instead, a separate bash script queries the IdP and rewrites parts of the NGINX config. Any IdP changes require you to re-run that script and reload NGINX. \n Performance Overhead. The njs solution effectively revalidates ID tokens on every request. Why? Because NGINX on its own doesn’t maintain a traditional server-side session object. Instead, it simulates a “session” by tying a cookie to the user’s id_token in keyval. auth_jwt checks the token each time, retrieving it from keyval and verifying the signature, expiration, and extract claims. Under heavy load, this constant JWT validation can become expensive. \n \n For many, that extra overhead conflicts with how modern OIDC clients usually do short-lived session cookies, validating the token only once per session or relying on a more efficient approach. Hence the motivation for a native OIDC module. \n Meet the New Native OIDC Module in NGINX Plus R34 \n With the complexities of the njs-based approach in mind, NGINX introduced a fully integrated OIDC module in NGINX Plus R34. This module is designed to be a “proper” OIDC client, including: \n \n Automatic TLS-only communication with the IdP. \n Full metadata discovery (no external scripts needed). \n Authorization code flows. \n Token validation and caching. \n A real session model using secure cookies. \n Access token support (including automatic refresh). \n Straightforward mapping of user claims to NGINX variables. \n \n We also have a Deployment Guide that shows how to set up this module for popular IdPs like Okta, Keycloak, Entra ID, and others. That guide focuses on typical use cases (obtaining tokens, verifying them, and passing claims upstream). However, here we’ll go deeper into how the module works behind the scenes, using Keycloak as our IdP. \n Our Scenario: Keycloak + NGINX Plus R34 \n We’ll demonstrate a straightforward Keycloak realm called nginx and a client also named nginx with “client authentication” and the “standard flow” enabled. We have: \n \n Keycloak as the IdP, running at https://kc.route443.dev/realms/nginx. \n NGINX Plus R34 configured as a reverse proxy. \n A simple upstream service at http://127.0.0.1:8080. \n \n Minimal Configuration Example: \n http {\n resolver 1.1.1.1 ipv4=on valid=300s;\n\n oidc_provider keycloak {\n issuer https://kc.route443.dev/realms/nginx;\n client_id nginx;\n client_secret secret;\n }\n\n server {\n listen 443 ssl;\n server_name n1.route443.dev;\n\n ssl_certificate /etc/ssl/certs/fullchain.pem;\n ssl_certificate_key /etc/ssl/private/key.pem;\n\n location / {\n auth_oidc keycloak;\n\n proxy_set_header sub $oidc_claim_sub;\n proxy_set_header email $oidc_claim_email;\n proxy_set_header name $oidc_claim_name;\n proxy_pass http://127.0.0.1:8080;\n }\n }\n\n server {\n # Simple test backend\n listen 8080;\n\n location / {\n return 200 \"Hello, $http_name!\\nEmail: $http_email\\nKeycloak sub: $http_sub\\n\";\n default_type text/plain;\n }\n }\n} \n Configuration Breakdown \n \n oidc_provider keycloak {}. Points to our Keycloak issuer, plus client_id and client_secret. Automatically triggers .well-known/openid-configuration discovery. Quite an important note: all interaction with the IdP is secured exclusively over SSL/TLS, so NGINX must trust the certificate presented by Keycloak. By default, this trust is validated against your system’s CA bundle (the default CA store for your Linux or FreeBSD distribution). If the IdP’s certificate is not included in the system CA bundle, you can explicitly specify a trusted certificate or chain using the ssl_trusted_certificate directive so that NGINX can validate and trust your Keycloak certificate. \n auth_oidc keycloak. For any request to https://n1.route443.dev/, NGINX checks if the user has a valid session. If not, it starts the OIDC flow. \n Passing Claims Upstream. We add headers sub, email, and name based on $oidc_claim_sub, $oidc_claim_email, and $oidc_claim_name, the module’s built-in variables extracted from token. \n \n Step-by-Step: Under the Hood of the OIDC Flow \n Retrieving and Caching OIDC Metadata \n As soon as you send an HTTP GET request to https://n1.route443.dev, you’ll see that NGINX redirects you to Keycloak’s authentication page. However, before that redirect happens, several interesting steps occur behind the scenes. Let’s take a closer look at the very first thing NGINX does in this flow: \n NGINX checks if it has cached OIDC metadata for the IdP. If no valid cache exists, NGINX constructs a metadata URL by appending /.well-known/openid-configuration to the issuer you specified in the config. It then resolves the IdP’s hostname using the resolver directive. \n NGINX parses the JSON response from the IdP, extracting critical parameters such as issuer, authorization_endpoint and token_endpoint. It also inspects response_types_supported to confirm that this IdP supports the authorization code flow and ID tokens. These details are essential for the subsequent steps in the OIDC process. \n NGINX caches these details for one hour (or for however long the IdP’s Cache-Control headers specify), so it doesn’t need to re-fetch them on every request. This process happens in the background. However, you might notice a slight delay for the very first user if the cache is empty, since NGINX needs a fresh copy of the metadata. \n Below is an example of the metadata request and response: \n NGINX -> IdP:\nHTTP GET /realms/nginx/.well-known/openid-configuration\n\nIdP -> NGINX:\nHTTP 200 OK\nContent-Type: application/json\nCache-Control: no-cache // Means NGINX will store it for 1 hour by default\n\n{\n \"issuer\": \"<https://kc.route443.dev/realms/nginx>\",\n \"authorization_endpoint\": \"<https://kc.route443.dev/realms/nginx/protocol/openid-connect/auth>\",\n \"token_endpoint\": \"<https://kc.route443.dev/realms/nginx/protocol/openid-connect/token>\",\n \"jwks_uri\": \"<http://kc.route443.dev:8080/realms/nginx/protocol/openid-connect/certs>\",\n \"response_types_supported\": [\n \"code\",\"none\",\"id_token\",\"token\",\"id_token token\",\n \"code id_token\",\"code token\",\"code id_token token\"\n ]\n // ... other parameters\n} \n This metadata tells NGINX everything it needs to know about how to redirect users for authentication, where to request tokens afterward, and which JWT signing keys to trust. By caching these results, NGINX avoids unnecessary lookups on subsequent logins, making the process more efficient for every user who follows. \n Building the Authorization URL & Setting a Temporary Session Cookie \n Now that NGINX has discovered and cached the IdP’s metadata, it’s ready to redirect your browser to Keycloak for actual login. Here’s where the OpenID Connect Authorization Code Flow begins in earnest. NGINX adds a few crucial parameters, like response_type=code, client_id, redirect_uri, state, and nonce to the authorization_endpoint it learned from the metadata, then sends you the following HTTP 302 response: \n NGINX -> User Agent:\nHTTP 302 Moved Temporarily\nLocation: <https://kc.route443.dev/realms/nginx/protocol/openid-connect/auth?response_type=code&scope=openid&client_id=nginx&redirect_uri=http%3A%2F%2Fn1.route443.dev%2Foidc_callback&state=state&nonce=nonce>\nSet-Cookie: NGX_OIDC_SESSION=temp_cookie/; Path=/; Secure; HttpOnly \n At this point, you’re probably noticing the Set-Cookie: NGX_OIDC_SESSION=temp_cookie; line. This is a temporary session cookie, sometimes called a “pre-session” cookie. NGINX needs it to keep track of your “in-progress” authentication state - so once you come back from Keycloak with the authorization code, NGINX will know how to match that code to your browser session. However, since NGINX hasn’t actually validated any tokens yet, this cookie is only ephemeral. It remains a placeholder until Keycloak returns valid tokens and NGINX completes the final checks. Once that happens, you’ll get a permanent session cookie, which will then store your real session data across requests. \n User Returns to NGINX with an Authorization Code \n Once the user enters their credentials on Keycloak’s login page and clicks “Login”, Keycloak redirects the browser back to the URL specified in your redirect_uri parameter. In our example, that happens to be http://n1.route443.dev/oidc_callback. It’s worth noting that /oidc_callback is just the default location and if you ever need something different, you can tweak it via the redirect_uri directive in the OIDC module configuration. \n When Keycloak redirects the user, it includes several query parameters in the URL, most importantly, the code parameter (the authorization code) and state, which NGINX uses to ensure this request matches the earlier session-setup steps. Here’s a simplified example of what the callback request might look like: \n \n User Agent -> NGINX:\nHTTP GET /oidc_callback\n Query Parameter: state=state\n Query Parameter: session_state=keycloak_session_state\n Query Parameter: iss=<https://kc.route443.dev/realms/nginx>\n Query Parameter: code=code \n Essentially, Keycloak is handing NGINX a “proof” that this user successfully logged in, along with a cryptographic token (the code) that lets NGINX exchange it for real ID and access tokens. Since /oidc_callback is tied to NGINX’s native OIDC logic, NGINX automatically grabs these parameters, checks whether the state parameter matches what it originally sent to Keycloak, and then prepares to make a token request to the IdP’s token_endpoint. Note that the OIDC module does not use the iss parameter for identifying the provider, provider identity is verified through the state parameter and the pre-session cookie, which references a provider-specific key. \n Exchanging the Code for Tokens and Validating the ID Token \n Once NGINX receives the oidc_callback request and checks all parameters, it proceeds by sending a POST request to the Keycloak token_endpoint, supplying the authorization code, client credentials, and the redirect_uri: \n \n NGINX -> IdP:\nPOST /realms/nginx/protocol/openid-connect/token\nHost: kc.route443.dev\nAuthorization: Basic bmdpbng6c2VjcmV0\n\nForm data:\ngrant_type=authorization_code\ncode=5865798e-682e-4eb7-8e3e-2d2c0dc5132e.f2abd107-35c1-4c8c-949f-03953a5249b2.nginx\nredirect_uri=https://n1.route443.dev/oidc_callback \n Keycloak responds with a JSON object containing at least an id_token, access_token plus token_type=bearer. Depending on your IdP’s configuration and the scope you requested, the response might also include a refresh_token and an expires_in field. The expires_in value indicates how long the access token is valid (in seconds), and NGINX can use it to decide when to request a new token on the user’s behalf. At this point, the module also spends a moment validating the ID token’s claims - ensuring that fields like iss, aud, exp, and nonce align with what was sent initially. If any of these checks fail, the token is deemed invalid, and the request is rejected. \n Once everything checks out, NGINX stores the tokens and session details. Here, the OIDC module takes advantage of the keyval mechanism to keep track of user sessions. You might wonder, “Where is that keyval zone configured?” The short answer is that it’s automatic for simplicity, unless you want to override it with your own settings. By default, you get up to 8 MB of session storage, which is more than enough for most use cases. But if you need something else, you can specify a custom zone via the session_store directive. If you’re curious to see this store in action, you can even inspect it through the NGINX Plus API endpoint, for instance: \n GET /api/9/http/keyvals/oidc_default_store_keycloak \n (where oidc_default_store_ is the prefix and keycloak is your oidc_provider name). \n With the tokens now safely validated and stashed, NGINX is ready to finalize the session. The module issues a permanent session cookie back to the user and transitions them into the “logged-in” state, exactly what we’ll see in the next step. \n Finalizing the Session and Passing Claims Upstream \n Once NGINX verifies all tokens and securely stores the user’s session data, it sends a final HTTP 302 back to the client, this time setting a permanent session cookie: \n NGINX -> User Agent:\nHTTP 302 Moved Temporarily\nLocation: https://n1.route443.dev/\nSet-Cookie: NGX_OIDC_SESSION=permanent_cookie; Path=/; Secure; HttpOnly \n At this point, the user officially has a valid OIDC session in NGINX. Armed with that session cookie, they can continue sending requests to the protected resource (in our case, https://n1.route443.dev/). Each request now carries the NGX_OIDC_SESSION cookie, so NGINX recognizes the user as authenticated and automatically injects the relevant OIDC claims into request headers - such as sub, email, and name. This means your upstream application at http://127.0.0.1:8080 can rely on these headers to know who the user is and handle any additional logic accordingly. \n Working with OIDC Variables \n Now, let’s talk about how you can leverage the OIDC module for more than just simple authentication. One of its biggest strengths is its ability to extract token claims and forward them upstream in request headers. Any claim in the token can be used as an NGINX variable named $oidc_claim_name, where name is whichever claim you’d like to extract. In our example, we’ve already shown how to pass sub, email, and name, but you can use any claims that appear in the token. For a comprehensive list of possible claims, check the OIDC specification as well as your IdP’s documentation. \n Beyond individual claims, you can also access the entire ID and Access Tokens directly via $oidc_id_token and $oidc_access_token. These variables can come in handy if you need to pass an entire token in a request header, or if you’d like to inspect its contents for debugging purposes. \n As you can see, configuring NGINX as a reverse proxy with OIDC support doesn’t require you to be an authentication guru. All you really need to do is set up the module, specify the parameters you want, and decide which token claims you’d like to forward as headers. \n Handling Nested or Complex Claims (Using auth_jwt) \n Sometimes, the claim you need to extract is actually a nested object, or even an array. That’s not super common, but it can happen if your Identity Provider returns complex data structures in the token. Currently, the OIDC module can’t directly parse nested claims - this is a known limitation that should be addressed in future releases. \n In the meantime, your best workaround is to use the auth_jwt module. Yes, it’s a bit of a detour, but right now it’s the only way (whether you use an njs-based approach or the native OIDC module) to retrieve more intricate structures from a token. Let’s look at an example where the address claim is itself an object containing street, city, and zip, and we only want the city field forwarded as a header: \n http {\n auth_jwt_claim_set $city address city;\n\n server {\n ...\n location / {\n auth_oidc keycloak;\n auth_jwt off token=$oidc_id_token;\n\n proxy_set_header x-city $city;\n proxy_pass http://127.0.0.1:8080;\n }\n }\n} \n Notice how we’ve set auth_jwt off token=$oidc_id_token. We’re effectively telling auth_jwt to not revalidate the token (because it was already validated during the initial OIDC flow) but to focus on extracting additional claims from it. Meanwhile, the auth_jwt_claim_set directive specifies the variable $city and points it to the nested city field in the address claim. With this in place, you can forward that value in a custom header (x-city) to your application. \n And that’s it. By combining the OIDC module for authentication with the auth_jwt module for more nuanced claim extraction, you can handle even the trickiest token structures in NGINX. In most scenarios, though, you’ll find that the straightforward $oidc_claim_ variables do the job just fine and no extra modules needed. \n Role-Based Access Control (Using auth_jwt) \n As you’ve noticed, because we’re not revalidating the token signature on every request, the overhead introduced by the auth_jwt module is fairly minimal. That’s great news for performance. But auth_jwt also opens up additional possibilities, like the ability to leverage the auth_jwt_require directive. With this, you can tap into NGINX not just for authentication, but also for authorization, restricting access to certain parts of your site or API based on claims (or any other variables you might be tracking). \n For instance, maybe you only want to grant admin-level users access to a specific admin dashboard. If a user’s token doesn’t include the right claim (like role=admin), you want to deny entry. Let’s take a quick look at how this might work in practice: \n \n http {\n map $jwt_claim_role $role_admin {\n \"admin\" 1;\n }\n\n server {\n ...\n # Location for admin-only resources:\n location /admin {\n auth_jwt foo token=$oidc_id_token;\n\n # Check that $role_admin is not empty and not \"0\" -> otherwise return 403:\n auth_jwt_require $role_admin error=403;\n\n # If 403 happens, we show a custom page:\n error_page 403 /403_custom.html;\n\n proxy_pass http://127.0.0.1:8080;\n }\n\n # Location for the custom 403 page\n location = /403_custom.html {\n # Internal, so it can't be directly accessed from outside\n internal;\n # Return the 403 status and a custom message\n return 403 \"Access restricted to admins only!\";\n }\n }\n} \n How It Works: \n In our map block, we check the user’s $jwt_claim_role and set $role_admin to 1 if it matches \"admin\". Then, inside the /admin location, we have something like: \n auth_jwt foo token=$oidc_id_token;\nauth_jwt_require $role_admin error=403; \n Here, foo is simply the realm name (a generic string you can customize), and token=$oidc_id_token tells NGINX which token to parse. At first glance, this might look like a normal auth_jwt configuration - but notice that we haven’t specified a public key via auth_jwt_key_file or auth_jwt_key_request. That means NGINX isn’t re-verifying the token’s signature here. Instead, it’s only parsing the token so we can use its claims within auth_jwt_require. \n Thanks to the fact that the OIDC module has already validated the ID token earlier in the flow, this works perfectly fine in practice. We still get access to $jwt_claim_role and can enforce auth_jwt_require $role_admin error=403;, ensuring anyone without the “admin” role gets an immediate 403 Forbidden. Meanwhile, we display a friendlier message by specifying: \n error_page 403 /403_custom.html; \n So even though it might look like a normal JWT validation setup, it’s really a lesser-known trick to parse claims without re-checking signatures, leveraging the prior validation done by the OIDC module. This approach neatly ties together the native OIDC flow with role-based access control - without requiring us to juggle another set of keys. \n Logout in OIDC \n So far, we’ve covered how to log in with OIDC and handle advanced scenarios like nested claims or role-based control. But there’s another critical topic: how do users log out? The OpenID Connect standard lays out several mechanisms: \n \n RP-Initiated Logout: The relying party (NGINX in this case) calls the IdP’s logout endpoint, which can clear sessions both in NGINX and at the IdP level. \n Front-Channel Logout: The IdP provides a way to notify the RP via a front-channel mechanism (often iframes or redirects) that the user has ended their session. \n Back-Channel Logout: Uses server-to-server requests between the IdP and the RP to terminate sessions behind the scenes. \n \n Right now, the native OIDC module in its first release does not fully implement these logout flows. They’re on the roadmap, but as of today, you may need a workaround if you want to handle sign-outs more gracefully. Still, one of the great things about NGINX is that even if a feature isn’t officially implemented, you can often piece together a solution with a little extra configuration. \n A Simple Logout Workaround \n Imagine you have a proxied application that includes a “Logout” button or link. You want clicking that button to end the user’s NGINX session. Below is a conceptual snippet showing how you might achieve that: \n http {\n server {\n listen 443 ssl;\n server_name n1.route443.dev;\n\n # OIDC provider config omitted for brevity\n # ...\n\n location / {\n auth_oidc keycloak;\n proxy_pass http://127.0.0.1:8080;\n }\n\n # \"Logout\" location that invalidates the session\n location /logout {\n # Here, we forcibly remove the NGX_OIDC_SESSION cookie\n add_header Set-Cookie \"NGX_OIDC_SESSION=; Path=/; HttpOnly; Secure; Expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n \n # Optionally, we can redirect the user to a \"logged out\" page\n return 302 \"https://n1.route443.dev/logged_out\";\n }\n\n location = /logged_out {\n # A simple page or message confirming the user is logged out\n return 200 \"You've been logged out.\";\n }\n }\n} \n \n /logout location: When the user clicks the “logout” link in your app, it can redirect them here. \n Clearing the cookie: We set NGX_OIDC_SESSION to an expired value, ensuring NGINX no longer recognizes this OIDC session on subsequent requests. \n Redirect to a “logged out” page: We redirect the user to /logged_out, or wherever you want them to land next. \n \n Keep in mind, this approach only logs out at the NGINX layer. The user might still have an active session with the IdP (Keycloak, Entra ID, etc.) because it manages its own cookies. A fully synchronized logout - where both the RP and the IdP sessions end simultaneously, would require an actual OIDC logout flow, which the current module hasn’t fully implemented yet. \n Conclusion \n Whether you’re looking to protect a basic web app, parse claims, or enforce role-based policies, the native OIDC module in NGINX Plus R34 offers a way to integrate modern SSO at the proxy layer. Although certain scenarios (like nested claim parsing or fully-fledged OIDC logout) may still require workarounds and careful configuration, the out-of-the-box experience is already much more user-friendly than older njs-based solutions, and new features continue to land in every release. \n If you’re tackling more complex setups - like UserInfo endpoint support, advanced session management, or specialized logout requirements - stay tuned. The NGINX team is actively improving the module and extend its capabilities. With a little know-how (and possibly a sprinkle of auth_jwt magic), you can achieve an OIDC-based architecture that fits your exact needs, all while preserving the flexibility and performance NGINX is known for. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"25093","kudosSumWeight":2,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDA1NTItd1JLMXVT?revision=7\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:340300":{"__typename":"Conversation","id":"conversation:340300","topic":{"__typename":"TkbTopicMessage","uid":340300},"lastPostingActivityTime":"2025-04-07T10:45:46.760-07:00","solved":false},"User:user:419288":{"__typename":"User","uid":419288,"login":"Prabhat","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS00MTkyODgtNDBzTzIz?image-coordinates=0%2C43%2C654%2C697"},"id":"user:419288"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDAzMDAtaG41RmJP?revision=7\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDAzMDAtaG41RmJP?revision=7","title":"NginxPlusReleaseFeaturedImage.png","associationType":"TEASER","width":1113,"height":626,"altText":""},"TkbTopicMessage:message:340300":{"__typename":"TkbTopicMessage","subject":"F5 NGINX Plus R34 Release Now Available","conversation":{"__ref":"Conversation:conversation:340300"},"id":"message:340300","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:340300","revisionNum":7,"uid":340300,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:419288"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" ","introduction":"","metrics":{"__typename":"MessageMetrics","views":944},"postTime":"2025-04-01T08:00:00.038-07:00","lastPublishTime":"2025-04-07T10:45:46.760-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" We’re excited to announce the availability of F5 NGINX Plus Release 34 (R34). Based on NGINX Open Source, NGINX Plus is the only all-in-one software web server, load balancer, reverse proxy, content cache, and API gateway. \n New and enhanced features in NGINX Plus R34 include: \n Forward proxy support for NGINX usage reporting: With R34, NGINX Plus allows NGINX customers to send their license usage telemetry to F5 via an existing enterprise forward proxy in their environment. \n Native support for OpenID Connect configuration: With this release, we would like to announce the availability of native OpenID Connect (OIDC) module in NGINX Plus. The native module brings simplified configuration and better performance while addressing many of the complexities with the existing njs-based solution. \n SSL Dynamic Certificate Caching: NGINX Plus R34 builds upon the certificate caching improvements in R32 and introduces support for caching of dynamic certificates and preserving this cache across configuration reloads. \n \n Important Changes In Behavior \n Removal of OpenTracing Module: In NGINX Plus R32, we announced deprecation of the OpenTracing module in favor of OpenTelemetry module introduced in NGINX Plus R29. , and was marked to be removed with NGINX Plus R34. The OpenTracing is now being removed from NGINX Plus effective this release. \n \n Changes to Platform Support \n Added Platforms: \n \n Alpine Linux 3.21 \n \n Removed Platforms: \n \n Alpine Linux 3.17 \n SLES12 \n \n Deprecated Platforms: \n \n Alpine Linux 3.18 \n Ubuntu 20.04 \n \n \n New Features in Detail \n \n Forward proxy support for NGINX usage reporting \n \n In the previous NGINX Plus release (NGINX Plus R33), we introduced major changes to NGINX Plus licensing requiring all NGINX customers to report their commercial NGINX usage to F5. One of the prime feedback we received for this feature was the need to enable NGINX instances to send telemetry via existing outbound proxies, primarily for environments where NGINX instances cannot connect to the F5 licensing endpoint directly. \n We are pleased to note that NGINX Plus R34 introduces support for using existing forward proxy solutions in customers environment for sending licensing telemetry to F5. With this update, NGINX Plus can now be configured to use the HTTP CONNECT proxy to establish a tunnel to the F5 licensing endpoint to send the usage telemetry. \n Configuration \n The following snippet shows the basic NGINX configuration needed in the ngx_mgmt_module module for sending NGINX usage telemetry via a forward proxy solution. \n mgmt {\n proxy HOST:PORT;\n proxy_username USER; #optional\n proxy_password PASS; #optional\n} \n \n For complete details, refer the docs here. \n \n Native support for OpenID Connect configuration \n Currently, NGINX Plus relies on a njs-based solution for OpenID Connect (OIDC) implementation that involves intricate JavaScript files and advanced setup steps, which are error-prone. With NGINX Plus R34, we're thrilled to introduce native OIDC support in NGINX Plus. This native implementation eliminates many of the complexities of the njs-based approach, making it faster, highly efficient, and incredibly easy to configure, with no burdensome overheads of maintaining and upgrading the njs module. \n To this effect, a new module ngx_http_oidc_module is introduced in NGINX Plus R34 that implements authentication as a relying party in OIDC using the Authorization Code Flow. The native implementation allows the flexibility to enable OIDC authentication globally, or at a more granular, per-server or a per-location level. It also allows effortless auto-discovery and retrieval of the OpenID providers' configuration metadata without needing complex external scripts for each Identity Provider (IdP), greatly simplifying the configuration process. For a complete overview and examples of the features in the native implementation of OIDC in NGINX Plus and how it improves upon the njs based implementation, refer the blog. \n \n Configuration \n The configuration to setup OIDC natively in NGINX Plus is relatively straightforward requiring minimal directives when compared to the njs based implementation. \n http { \n resolver 10.0.0.1; \n \n oidc_provider my_idp { \n issuer \"https://provider.domain\"; \n client_id \"unique_id\"; \n client_secret \"unique_secret\"; \n } \n \n server { \n location / { \n auth_oidc my_idp; \n \n proxy_set_header username $oidc_claim_sub; \n proxy_pass http://backend; \n } \n } \n} \n \n The example assumes that the “https://<nginx-host>/oidc_callback” redirection URI is configured on the OpenID Provider's side. \n For instructions on how to configure the native OIDC module for various identity providers, refer the NGINX deployment guide. \n \n SSL Certificate Caching improvements \n In NGINX Plus R32, we introduced changes to cache various SSL objects and reuse the cached objects elsewhere in the configuration. This provided noticeable improvements in the initial configuration load time primarily where a small number of unique objects were being referenced multiple times. \n With R34, we are adding further enhancements to this functionality where cached SSL objects are reused across configuration reloads, making the reloads even faster. Also, SSL certificates with variables are now cached as well. Refer the blog for a detailed overview of this feature implementation. \n \n Other Enhancements and Bug Fixes \n \n Keepalive timeout improvements \n Prior to this release, idle keepalive connections could be closed any time the connection needed to be reused for another client or when the worker was gracefully shutting down. \n With NGINX Plus R34, a new directive keepalive_min_timeout is being introduced. This directive sets a timeout during which a keepalive connection will not be closed by NGINX for connection reuse or graceful worker shutdown. The change allows clients that send multiple requests over the same connection without delay or with a small delay between them, to avoid receiving a TCP RST in response to one of them, if not for network reasons or non-graceful worker shutdown. \n As a side-effect, it also addresses the TCP reset problem described in RFC 9112, Section 9.6, when the last sent HTTP response could be damaged by a followup TCP RST. It is important for non-idempotent requests, which cannot be retried by client. \n It is however recommended to not set keepalive_min_timeout to large values as this can introduce an additional delay during worker process shutdown and may restrict NGINX from effective connection reuse. \n \n Improved health check logging \n NGINX Plus R34 adds logging enhancements in the error log for better visibility while troubleshooting upstream health check failures. The server status code is now logged on health check failures. \n \n Increased session key size \n Prior to R34, NGINX accepted an SSL session with maximum 4k(4096) bytes. With NGINX Plus R34, the maximum session size has been increased to 8k(8192) bytes to accommodate use cases where the sessions could be larger than 4k bytes. For ex. in cases where a client certificate is saved in the session, with tickets (in TLS v1.2 or older versions), or with stateless tickets (in TLS v1.3) the sessions maybe of noticeably large size. Certain stateless session resumption implementations may store additional data as well. One such case is with JDK, which is known to include server certificates in the session ticket data which roughly doubles the decoded session size. \n The changes also include improved logging to capture cases when sessions are not saved in shared memory due to size. \n \n Changes in the Open Telemetry Module \n TLS support in OTEL traces: \n NGINX now allows enabling TLS for sending OTEL traces. It can be enabled by specifying \"https\" scheme in the endpoint as shown. \n otel_exporter { endpoint \"https://otel.labt.fp.f5net.com:4433\"; trusted_certificate “path/to/custom/ca/bundle“; # optional } \n \n By default, system CA bundle is used to verify endpoint's certificate which can be overridden with \"trusted_certificate\" directive if required. \n For a complete list of changes to the OTEL module, refer the NGINX OTEL change log. \n \n Changes Inherited from NGINX Open Source \n NGINX Plus R34 is based on NGINX mainline release and inherits all functional changes, features, and bug fixes made since NGINX Plus R33 was released (in NGINX Open source 1.27.3 and 1.27.4 mainline versions) \n Features: \n \n SSL Certificate Caching \n \"keepalive_min_timeout\" directive \n The \"server\" directive in the \"upstream\" block supports the \"resolve\" parameter. \n The \"resolver\" and \"resolver_timeout\" directives in the \"upstream\" block. \n SmarterMail specific mode support for IMAP LOGIN with untagged CAPABILITY response in the mail proxy module. \n \n Changes: \n \n Now TLSv1 and TLSv1.1 protocols are disabled by default. \n An IPv6 address in square brackets and no port can be specified in the \"proxy_bind\", \"fastcgi_bind\", \"grpc_bind\", \"memcached_bind\", \"scgi_bind\", and \"uwsgi_bind\" directives, and as client address in ngx_http_realip_module. \n \n Bug Fixes: \n \n gzip filter failed to use preallocated memory\" alerts appeared in logs when using zlib-ng. \n nginx could not build libatomic library using the library sources if the --with-libatomic=DIR option was used. \n QUIC connection might not be established when using 0-RTT; the bug had appeared in 1.27.1. \n NGINX now ignores QUIC version negotiation packets from clients. \n NGINX could not be built on Solaris 10 and earlier with the ngx_http_v3_module. \n Bugfixes in HTTP/3. \n Bugfixes in the ngx_http_mp4_module. \n The \"so_keepalive\" parameter of the \"listen\" directive might be handled incorrectly on DragonFly BSD. \n Bugfix in the proxy_store directive. \n \n Security: \n \n Insufficient check in virtual servers handling with TLSv1.3 SNI allowed to reuse SSL sessions in a different virtual server, to bypass client SSL certificates verification (CVE-2025-23419). \n \n \n For the full list of new changes, features, bug fixes, and workarounds inherited from recent releases, see the NGINX changes . \n \n Changes to the NGINX Javascript Module \n NGINX Plus R34 incorporates changes from the NGINX JavaScript (njs) module version 0.8.9. The following is a list of notable changes in njs since 0.8.7 (which was the version shipped with NGINX Plus R33). \n Features: \n \n Added fs module for QuickJS engine. \n Implemented process object for the QuickJS engine. \n Implemented the process.kill() method. \n \n Bug Fixes: \n \n Removed extra VM creation per server. Previously, when js_import was declared in http or stream blocks, an extra copy of the VM instance was created for each server block. This was not needed and consumed a lot of memory for configurations with many server blocks. This issue was introduced in 9b674412 (0.8.6) and was partially fixed for location blocks only in 685b64f0 (0.8.7). \n Fixed XML tests with libxml2 2.13 and later. \n Fixed promise resolving when Promise is inherited. \n Fixed absolute scope in cloned VMs. \n Fixed limit rated output. \n Optimized use of SSL contexts for the js_fetch_trusted_certificate directive. \n \n \n For a comprehensive list of all the features, changes, and bug fixes, see the njs Changelog. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"11610","kudosSumWeight":0,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zNDAzMDAtaG41RmJP?revision=7\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:340187":{"__typename":"Conversation","id":"conversation:340187","topic":{"__typename":"ForumTopicMessage","uid":340187},"lastPostingActivityTime":"2025-03-09T06:39:25.994-07:00","solved":false},"User:user:115530":{"__typename":"User","uid":115530,"login":"Ding_Hsu","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-6.svg?time=0"},"id":"user:115530"},"ForumTopicMessage:message:340187":{"__typename":"ForumTopicMessage","subject":"Question regarding nginx plus gpg key","conversation":{"__ref":"Conversation:conversation:340187"},"id":"message:340187","entityType":"FORUM_TOPIC","eventPath":"category:Forums/community:zihoc95639board:TechnicalForum/message:340187","revisionNum":1,"uid":340187,"depth":0,"board":{"__ref":"Forum:board:TechnicalForum"},"author":{"__ref":"User:user:115530"},"metrics":{"__typename":"MessageMetrics","views":53},"postTime":"2025-03-07T19:48:31.477-08:00","lastPublishTime":"2025-03-07T19:48:31.477-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hi Everyone, I'm trying to install the Nginx Plus on my ubuntu lab. I followed the nginx article to set up my lab environment, including setting up the gpg key, and get the valid nginx signed key from our F5 sale representative for lab tesing. https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-plus/#install_debian_ubuntu I got the error message after running apt update. It indicates that the repotitory is not signed. Reading package lists... Done E: Failed to fetch https://pkgs.nginx.com/plus/ubuntu/dists/jammy/InRelease 400 Bad Request [IP: 18.198.212.80 443] E: The repository 'https://pkgs.nginx.com/plus/ubuntu jammy InRelease' is not signed. N: Updating from such a repository can't be done securely, and is therefore disabled by default. N: See apt-secure(8) manpage for repository creation and user configuration details. Has anyone got this issue like this ? Does anyone know how I can fix this issue ? Best regards, Ding ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"1036","kudosSumWeight":0,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:338320":{"__typename":"Conversation","id":"conversation:338320","topic":{"__typename":"TkbTopicMessage","uid":338320},"lastPostingActivityTime":"2025-01-14T10:25:58.835-08:00","solved":false},"User:user:189442":{"__typename":"User","uid":189442,"login":"Greg_Coward","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xODk0NDItOHNzWXY0?image-coordinates=250%2C0%2C1960%2C1710"},"id":"user:189442"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTElCdUtx?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTElCdUtx?revision=34","title":"image1.png","associationType":"BODY","width":1917,"height":928,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtNzFkcUtQ?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtNzFkcUtQ?revision=34","title":"Screenshot 2024-12-10 at 4.09.46 PM.png","associationType":"BODY","width":1655,"height":246,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTUg5QUJ3?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTUg5QUJ3?revision=34","title":"Screenshot 2024-12-10 at 4.10.20 PM.png","associationType":"BODY","width":396,"height":225,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtdUVHbGVh?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtdUVHbGVh?revision=34","title":"Screenshot 2024-12-10 at 4.11.01 PM.png","associationType":"BODY","width":1410,"height":326,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWFg0SFlz?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWFg0SFlz?revision=34","title":"Screenshot 2024-12-10 at 4.18.40 PM.png","associationType":"BODY","width":818,"height":839,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtc2Vhc2Zk?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtc2Vhc2Zk?revision=34","title":"Screenshot 2024-12-10 at 4.20.05 PM.png","associationType":"BODY","width":845,"height":874,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWWY2NWFF?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWWY2NWFF?revision=34","title":"Screenshot 2024-12-10 at 4.22.36 PM.png","associationType":"BODY","width":864,"height":873,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtR1hhcE9X?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtR1hhcE9X?revision=34","title":"Screenshot 2024-12-10 at 4.25.32 PM.png","associationType":"BODY","width":977,"height":585,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQ2lEa0xk?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQ2lEa0xk?revision=34","title":"Screenshot 2024-12-10 at 4.26.46 PM.png","associationType":"BODY","width":1387,"height":169,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0VZcW9C?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0VZcW9C?revision=34","title":"Screenshot 2024-12-10 at 4.27.59 PM.png","associationType":"BODY","width":1396,"height":214,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWUtzZmVD?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWUtzZmVD?revision=34","title":"Screenshot 2024-12-11 at 4.50.44 PM.png","associationType":"BODY","width":1915,"height":846,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTFRrUUJN?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTFRrUUJN?revision=34","title":"Screenshot 2024-12-10 at 5.18.29 PM.png","associationType":"BODY","width":868,"height":232,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtRWdvcWxa?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtRWdvcWxa?revision=34","title":"Screenshot 2024-12-10 at 5.15.48 PM.png","associationType":"BODY","width":999,"height":804,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQjl3THk4?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQjl3THk4?revision=34","title":"Screenshot 2024-12-10 at 5.19.21 PM.png","associationType":"BODY","width":1988,"height":464,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtMm9YYU9R?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtMm9YYU9R?revision=34","title":"Screenshot 2024-12-10 at 5.23.53 PM.png","associationType":"BODY","width":1650,"height":222,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtOElSaUNi?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtOElSaUNi?revision=34","title":"Screenshot 2024-12-10 at 5.25.49 PM.png","associationType":"BODY","width":1672,"height":1548,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU2JGZ0Va?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU2JGZ0Va?revision=34","title":"Screenshot 2024-12-11 at 3.25.34 PM.png","associationType":"BODY","width":804,"height":313,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0NqZDJ5?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0NqZDJ5?revision=34","title":"Screenshot 2024-12-11 at 3.28.18 PM.png","associationType":"BODY","width":1903,"height":807,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtM0lZbGtk?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtM0lZbGtk?revision=34","title":"Screenshot 2024-12-11 at 5.26.15 PM.png","associationType":"BODY","width":1916,"height":794,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTHRTMmVv?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTHRTMmVv?revision=34","title":"Screenshot 2024-12-11 at 5.33.46 PM.png","associationType":"BODY","width":1256,"height":806,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQk91QVlK?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQk91QVlK?revision=34","title":"Screenshot 2024-12-11 at 5.35.38 PM.png","associationType":"BODY","width":1242,"height":835,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtN0psanFj?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtN0psanFj?revision=34","title":"Screenshot 2024-12-11 at 6.12.04 PM.png","associationType":"BODY","width":877,"height":345,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtV3RYWDVS?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtV3RYWDVS?revision=34","title":"Screenshot 2024-12-11 at 6.16.35 PM.png","associationType":"BODY","width":1151,"height":700,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtZnZJV1gy?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtZnZJV1gy?revision=34","title":"Screenshot 2024-12-11 at 6.17.46 PM.png","associationType":"BODY","width":1160,"height":602,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtVEFwVU5t?revision=34\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtVEFwVU5t?revision=34","title":"Screenshot 2025-01-14 at 9.54.18 AM.png","associationType":"BODY","width":1241,"height":762,"altText":""},"TkbTopicMessage:message:338320":{"__typename":"TkbTopicMessage","subject":"How I did it - “Delivering Kasm Workspaces three ways”","conversation":{"__ref":"Conversation:conversation:338320"},"id":"message:338320","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:338320","revisionNum":34,"uid":338320,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:189442"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Securing modern, containerized platforms like Kasm Workspaces requires a robust and multi-faceted approach to ensure performance, reliability, and data protection. In this edition of \"How I did it\" we'll see how F5 technologies can enhance the security and scalability of Kasm Workspaces deployments. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":617},"postTime":"2024-12-23T05:00:00.031-08:00","lastPublishTime":"2025-01-14T10:25:58.835-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Securing modern, containerized platforms like Kasm Workspaces requires a robust and multi-faceted approach to ensure performance, reliability, and data protection. In this edition of \"How I did it\" we'll see how F5 technologies can enhance the security and scalability of Kasm Workspaces deployments. We’ll start by detailing how F5 BIG-IP TMOS can fortify network and application traffic; then move to securing Kubernetes-based Kasm Workspaces with the NGINX Plus Ingress Controller. Finally, we’ll demonstrate how F5 Distributed Cloud Services can deliver a comprehensive solution for secure and efficient application delivery. \n \n Kasm Workspaces \n Kasm Workspaces is a containerized streaming platform designed for secure, web-based access to desktops, applications, and web browsing. It leverages container technology to deliver virtualized environments directly to users' browsers, enhancing security, scalability, and performance. Commonly used for remote work, cybersecurity, and DevOps workflows, Kasm Workspaces provides a flexible and customizable solution for organizations needing secure and efficient access to virtual resources. \n \n Let me count the ways.... \n As noted in the Kasm documentation, the Kasm Workspaces Web App Role servers should not be exposed directly to the public. To address this requirement, F5 provides a variety of solutions to secure and deliver Kasm web servers. For the remainder of this article, we'll take a look at three of these solutions. \n \n \n Kasm Workspaces with F5 BIG-IP and FAST Templates \n \n \n Kasm Workspaces running on K8s with NGINX Plus Ingress Controller \n \n \n Bringing it all together with F5 Distributed Cloud Services \n \n \n \n Kasm Workspaces with F5 BIG-IP and FAST Templates \n For the following walkthrough, I utilized the F5 BIG-IP, (ver. 17.1.1.4 Build 0.0.9) to deliver and secure my on-premises Kasm Workspaces installation. While I could configure the various BIG-IP resources (virtual server, pool members, profiles, etc.) manually, I elected to utilize the BIG-IP Automation Toolchain to greatly simplify my deployment. \n The F5 BIG-IP Automation Toolchain is a suite of tools designed to automate the deployment, configuration, and management of F5 BIG-IP devices. It enables efficient and consistent management through the use of declarative APIs, templates, and integrations with popular automation frameworks. Specifically, I'll used AS3 and FAST templates. Application services (FAST) templates are predefined configurations that streamline the deployment and management of applications by providing consistent and repeatable setups. \n \n \n \n \n \n F5 BIG-IP Application Services Templates (FAST) \n \n \n F5 BIG-IP Application Services 3 Extension (AS3) \n \n \n \n \n \n As a prerequisite, I downloaded and installed the above packages (delivered as RPMs) onto the BIG-IP, (see below). \n \n With the RPMs installed, I was ready to deploy my application. From the side menu bar of the BIG-IP UI I navigated to 'iApps' --> 'Application Services' --> 'Applications LX' and selected 'F5 Application Services Templates'. \n \n From the provided templates, I selected the 'HTTP Application Template', (see below). The rest was a simple matter of completing and deploying the template. \n \n I needed to provide a tenant, (partition) name, application name, VIP address and listening port. \n \n I selected a previously installed certificate/key combination and enable client-side TLS. Since I'm using SAML federation between my Kasm Workspaces and Microsoft Entra ID, I have elected to enable TLS for server-side connections as well. Additionally, I provided the backend Kasm server address and port (see below). \n \n I created a custom HTTPs health monitor and associate with the Kasm backend pool. The send string makes a GET request to the Kasm healthcheck API (see below). \n \n Send String = GET /api/__healthcheck\\r\\n \n Receive String = OK \n \n \n I enabled and associated a template-generated WAF policy, enabled BOT defense and configured logging options. \n \n With the highlighted fields completed, I navigated back to the top of the template and selected 'Deploy', \n \n With the template successfully deployed, my application is ready to test. \n \n Video Walkthrough \n Want to get a feel for it before trying yourself? The video below provides a step-by-step walkthrough of the above deployment. \n \n \n \n Kasm Workspaces running on K8s with NGINX Plus Ingress Controller \n Both Kasm and F5 provide Helm charts for simplified deployments of Kasm Workspaces and NGINX Ingress Controller on Kubernetes. \n Create Kubernetes Secrets \n From the MyF5 Portal, I navigated to your subscription details, and downloaded the relevant .JWT file. With the JWT token in hand, I created the docker registry secret. This will be used to pull NGINX Plus IC from the private registry. \n kubectl create secret docker-registry regcred --docker-server=private-registry.nginx.com --docker-username=<jwt token=\"\"> --docker-password=none </jwt> \n I needed to create a Kubernetes TLS secret to use with my NGINX-hosted endpoint (kasmn.f5demo.net). I used the command below to create the secret. \n kubectl create secret tls tls-secret --cert=/users/coward/certificates/combined-cert.pem --key=/users/coward/certificates/combined-key.pem \n Once created, I used the command 'kubectl get secret' to verify the secrets were successfully created. \n \n \n \n \n \n Update K8s Custom Resource Definitions \n I ran the following command to update the CRDs required to deploy and operate the NGINX Ingress Controller. \n kubectl apply -f https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/v3.7.2/deploy/crds.yaml \n Deploy NGINX Plus Ingress Controller \n Prior to deploying the NGINX Helm chart, I needed to navigate to the repo folder and modify a few settings in the 'values.yaml' file. To deploy NGINX Plus Ingress Controller with (NAP) I specified a repo image, set the 'nginxplus' flag to true and enabled NGINX App Protect. \n \n I used the below command to deploy the Helm chart. \n helm install nginx . \n Once deployed, I used the command, 'kubectl get svc' to view the NGINX service and capture the external IP assigned (see below). For this example, the DNS entry, 'kasmn.f5demo.net' was updated to reflect the assigned IP address. \n \n Deploy Kasm Workspaces \n For this example, I have deployed an Azure AKS cluster to host my Kasm Workspaces application. Prior to deploying the Kasm Helm chart, I created a file in the 'templates' directory defining a VirtualServer resource. The VirtualServer resource defines load balancing configuration for a domain name, such as f5demo.net and maps the backend K8s service with the NGINX Ingress Controller. \n I navigated to the 'templates' directory and created the file (virtualserver.yaml) using the contents below. \n apiVersion: k8s.nginx.org/v1 \nkind: VirtualServer \nmetadata: \n name: {{ .Values.kasmApp.name | default \"kasm\" }}-virtualserver\n namespace: {{ .Values.global.namespace | default .Release.Namespace }}\n labels:\n app.kubernetes.io/name: {{ .Values.kasmApp.name }}-virtualserver\n{{- include \"kasm.defaultLabels\" . | indent 4 }}\nspec: \n host: {{ .Values.global.hostname | quote }}\n tls: \n secret: tls-secret \n gunzip: on \n upstreams: \n - name: kasm-proxy\n service: kasm-proxy\n port: 8080\n routes: \n - path: /\n action: \n pass: kasm-proxy\n \n With the file created and saved, I was ready to deploy the Kasm Helm chart. \n \n I navigated to the parent repo folder and used the following command to deploy the chart. \n helm install kasm kasm-single-zone \n With the deployment complete, I am ready to test access to the Kasm Workspaces UI. \n \n Video Walkthrough \n The video below provides a step-by-step walkthrough of the above deployment. \n \n \n Bringing it all together with F5 Distributed Cloud Services \n F5 Distributed Cloud Services (F5 XC) facilitates the deployment of applications across on-premises, cloud, and colocation facilities by offering a unified platform that integrates networking, security, and application delivery services. This approach ensures consistent performance, security, and management regardless of the deployment environment, enabling seamless hybrid and multi-cloud operations. \n For this demonstration, I used F5 XC to secure and publish globally both my on-premises and Azure AKS-hosted Kasm workloads using a single HTTP load balancer. \n Customer Edge (CE) Sites \n To publish my Kasm Workspace application with F5 XC I first needed to establish secure connectivity between my on-premises and Azure AKS environments and the F5 Distributed Cloud. To accomplish this, I have deployed CE devices and created a Customer Edge site in each location. \n \n Origin Pool \n I created two origin pools with a custom health check that will be associated to the load balancer. The first origin pool references the Kasm Workspace Web App server located on-premises. As shown below, the server is located behind and reached via the Customer edge site connection. Additionally, like the BIG-IP deployment scenario, I configured the connection to the backend server to use TLS. \n \n I have created a second origin pool referencing the AKS-hosted workload, (see below). I've used K8s Service Discovery to expose the Kasm-proxy K8s service. \n \n Custom Health Check \n \n HTTP Load Balancer \n With my origin pools created, I configured the load balancer. Similar to a BIG-IP virtual server, I used the HTTP load balancer to create a public-facing endpoint, associate backend origin pool(s) and apply various security policies and profiles. \n As shown below, I provided a load balancer’s name and domain name. Additionally, I have enabled automatic certificate generation for the domain name specified. I’ve enabled HTTP to HTTPS redirection and specified the port of the backend server(s). \n \n I associated both origin pools. Incoming connections will be directed to both my on-premises and AKS-hosted Kasm Workspace servers based on the load balancing algorithm selected. As an option, I can modify the weight and priorities of my backend pools. \n For additional security, I've enabled WAF and specified and a policy. Additionally, I have enabled API discovery and DDOS protection. \n \n \n \n\n To establish workspace connectivity, I\"ll need to configure routing and enable WebSockets. Under 'Routes', I selected 'Edit Configuration'. I configured a simple route and associated the origin pool(s), (see below). \n \n I navigated down and selected 'Advanced Options'. From the 'Advanced Options' page, I scrolled down to \"Protocol Upgrades' and enabled WebSockets, (see below). \n \n I selected 'Apply' twice and verified the route settings, (see below) and selected 'Apply' again to return to the load balancer configuration page. \n \n With respect to VIP advertisement, I elected to publish my Kasm Workspaces deployment publicly. \n \n Once configured and saved (and allowing a few minutes to deploy) the application is ready for testing. \n \n Video Walkthrough \n The video below provides a step-by-step walkthrough of the above deployment. \n \n Additional Links \n \n Kasm Workspaces \n F5 BIG-IP Application Services 3 Extension Documentation (AS3) \n F5 BIG-IP Application Services Templates (FAST) \n Kasm K8s Helm Chart \n NGINX Plus Ingress Controller \n NGINX Plus Ingress Controller Helm Chart Deployment \n F5 Distributed Cloud Services \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"11810","kudosSumWeight":2,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTElCdUtx?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtNzFkcUtQ?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTUg5QUJ3?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtdUVHbGVh?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWFg0SFlz?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtc2Vhc2Zk?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDc","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWWY2NWFF?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDg","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtR1hhcE9X?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDk","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQ2lEa0xk?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDEw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0VZcW9C?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDEx","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWUtzZmVD?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDEy","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTFRrUUJN?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDEz","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtRWdvcWxa?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE0","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQjl3THk4?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE1","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtMm9YYU9R?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE2","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtOElSaUNi?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE3","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU2JGZ0Va?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE4","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0NqZDJ5?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE5","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtM0lZbGtk?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDIw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTHRTMmVv?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDIx","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQk91QVlK?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDIy","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtN0psanFj?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDIz","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtV3RYWDVS?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDI0","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtZnZJV1gy?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDI1","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtVEFwVU5t?revision=34\"}"}}],"totalCount":30,"pageInfo":{"__typename":"PageInfo","hasNextPage":true,"endCursor":"MjUuNHwyLjF8b3wyNXxfTlZffDI1","hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:338614":{"__typename":"Conversation","id":"conversation:338614","topic":{"__typename":"TkbTopicMessage","uid":338614},"lastPostingActivityTime":"2025-01-13T14:21:24.641-08:00","solved":false},"User:user:189438":{"__typename":"User","uid":189438,"login":"Gee_Chow","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xODk0MzgtMTcxOTdpQ0QzNUFDNjdDREVENTRGNg"},"id":"user:189438"},"TkbTopicMessage:message:338614":{"__typename":"TkbTopicMessage","subject":"Installing and Locking a Specific Version of F5 NGINX Plus","conversation":{"__ref":"Conversation:conversation:338614"},"id":"message:338614","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:338614","revisionNum":5,"uid":338614,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:189438"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":261},"postTime":"2025-01-06T05:00:00.041-08:00","lastPublishTime":"2025-01-13T14:21:24.641-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" A guide for installing and locking a specific version of NGINX Plus to ensure stability, meet internal policies, and prepare for controlled upgrades. \n Introduction \n The most common way to install F5 NGINX Plus is by using the package manager tool native to your Linux host (e.g., yum, apt-get, etc.). By default, the package manager installs the latest available version of NGINX Plus. However, there may be scenarios where you need to install an earlier version. To help you modify your automation scripts, we’ve provided example commands for selecting a specific version. \n Common Scenarios for Installing an Earlier Version of NGINX Plus \n \n Your internal policy requires sticking to internally tested versions before deploying the latest release. \n \n \n You prefer to maintain consistency by using the same version across your entire fleet for simplicity. \n \n \n You’d like to verify and meet additional requirements introduced in a newer release (e.g., NGINX Plus Release 33) before upgrading. \n \n Commands for Installing and Holding a Specific Version of NGINX Plus \n Use the following commands based on your Linux distribution to install and lock a prior version of NGINX Plus: \n Ubuntu 20.04, 22.04, 24.04 LTS \n sudo apt-get update \nsudo apt-get install -y nginx-plus=<VERSION> \nsudo apt-mark hold nginx-plus \n \n Debian 11, 12 \n sudo apt-get update \nsudo apt-get install -y nginx-plus=<VERSION> \nsudo apt-mark hold nginx-plus \n \n AlmaLinux 8, 9 / Rocky Linux 8, 9 / Oracle Linux 8.1+, 9 / RHEL 8.1+, 9 \n sudo yum install -y nginx-plus-<VERSION> \nsudo yum versionlock nginx-plus \n \n Amazon Linux 2 LTS, 2023 \n sudo yum install -y nginx-plus-<VERSION> \nsudo yum versionlock nginx-plus \n \n SUSE Linux Enterprise Server 12, 15 SP5+ \n sudo zypper install nginx-plus=<VERSION> \nsudo zypper addlock nginx-plus \n \n Alpine Linux 3.17, 3.18, 3.19, 3.20 \n apk add nginx-plus=<VERSION> \necho \"nginx-plus hold\" | sudo tee -a /etc/apk/world \n \n FreeBSD 13, 14 \n pkg install nginx-plus-<VERSION> \npkg lock nginx-plus \n \n Notes \n \n Replace <VERSION> with the desired version (e.g., 32-2*). \n \n \n After installation, verify the installed version with the command: nginx -v. \n \n \n Holding or locking the package ensures it won’t be inadvertently upgraded during routine updates. \n \n Conclusion \n Installing and locking a specific version of NGINX Plus ensures stability, compliance with internal policies, and proper validation of new features before deployment. By following the provided commands tailored to your Linux distribution, you can confidently maintain control over your infrastructure while minimizing the risk of unintended upgrades. Regularly verifying the installed version and holding updates will help ensure consistency and reliability across your environments. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"3034","kudosSumWeight":0,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"Conversation:conversation:336403":{"__typename":"Conversation","id":"conversation:336403","topic":{"__typename":"TkbTopicMessage","uid":336403},"lastPostingActivityTime":"2025-01-09T09:06:14.546-08:00","solved":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzY0MDMtTk5DNmsy?revision=9\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzY0MDMtTk5DNmsy?revision=9","title":"nginx-reverse-proxy-featured.jpeg","associationType":"TEASER","width":1024,"height":617,"altText":""},"TkbTopicMessage:message:336403":{"__typename":"TkbTopicMessage","subject":"F5 NGINX Plus R33 Release Now Available","conversation":{"__ref":"Conversation:conversation:336403"},"id":"message:336403","entityType":"TKB_ARTICLE","eventPath":"category:Articles/community:zihoc95639board:TechnicalArticles/message:336403","revisionNum":9,"uid":336403,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:419288"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" \n We’re excited to announce the availability of NGINX Plus Release 33 (R33). The release introduces major changes to NGINX licensing, support for post quantum cryptography, initial support for QuickJS runtime in NGINX JavaScript and a lot more. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":1995},"postTime":"2024-11-19T07:00:00.022-08:00","lastPublishTime":"2024-11-19T15:02:10.321-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" We’re excited to announce the availability of F5 NGINX Plus Release 33 (R33). Based on NGINX Open Source, NGINX Plus is the only all-in-one software web server, load balancer, reverse proxy, content cache, and API gateway. \n New and enhanced features in NGINX Plus R33 include: \n Licensing Changes in NGINX Plus: Starting with NGINX Plus R33, all customers are required to deploy a JSON Web Token (JWT) license on each commercial NGINX Plus instance. Each instance will also validate its license status, and report F5 NGINX usage to the F5 licensing endpoint for connected customers or to F5 NGINX Instance Manager for offline/air-gapped customers. \n Support for Post Quantum Cryptography NGINX Plus R33 announces support for post quantum cryptography in NGINX ensuring long-term data transmission security and allowing enterprises to be prepared for future changes in cryptography. \n QuickJS runtime support in NGINX JavaScript: QuickJS is a lightweight, embeddable JavaScript engine that supports the ES2023 specification, provides garbage collection out of the box and offers performance improvements over the existing JavaScript runtime engine. For ease of use, this runtime will co-exist and be delivered as a drop-in replacement to the existing JavaScript runtime in the NGINX JavaScript module. \n OCSP Stapling Support in Stream module: NGINX Plus R33 introduces support for Online Certificate Status Protocol (OCSP) stapling and client certificate verification in the stream module. \n Rounding out the release are new features and bug fixes inherited from NGINX Open source and updates to the NGINX JavaScript module. \n \n Important Changes in Behavior \n Note: If you are upgrading from a release other than NGINX Plus R32, make sure to review the Important Changes in Behavior section in previous NGINX Plus release announcement blogs for all releases between your current version and this one. \n \n Changes to NGINX Licensing \n Starting with the NGINX Plus R33 release, a valid JWT license is necessary for NGINX to operate. There is a single JWT license per subscription and it must be placed on each NGINX instance associated with that subscription. \n Additionally, all customers are required to report their commercial NGINX usage to F5. By default, your usage report is automatically sent to the F5 licensing endpoint. For network restricted environments, there are options to route the usage report through NGINX Instance Manager. \n See here for more details. \n \n Changes to Platform Support \n The following changes have been made to supported platforms in this release. \n Added Platforms: \n \n Alpine Linux 3.20 \n \n Removed Platforms: \n \n CentOS 7 / RHEL 7 / Oracle Linux 7 \n Alpine Linux 3.16 \n \n Deprecated Platforms: \n \n Alpine Linux 3.17 \n SLES 12 \n \n \n New Features in Detail \n \n Licensing Changes in NGINX Plus: \n With the NGINX Plus R33 release, we are introducing notable changes to how NGINX commercial products are licensed. As a pre-requisite, a JWT license is required to be deployed on all NGINX instances. There is a single license per subscription, and it must be installed on all the instances included in that subscription. The license can be obtained from your MyF5 account. Refer the instructions here on how to get your license and deploy it on your NGINX instances. \n With the NGINX Plus R33 release, all NGINX customers are also required to report their commercial NGINX usage to F5. \n By default, the usage is reported to the F5 licensing endpoint. Refer to the instructions here for connectivity requirements. \n For environments where NGINX instances have external network restrictions, the usage must be reported to NGINX Instance Manager which provides both connected and disconnected modes of sending NGINX usage to F5. Refer to the instructions here on how to configure your NGINX instances and send commercial usage telemetry to NGINX Instance Manager. \n Refer to NGINX licensing documentation for a complete overview of these changes. \n \n Support for Post Quantum Cryptography: \n With the advancement of quantum computing, traditional cryptographic algorithms such as RSA and ECC are becoming vulnerable to potential quantum computer attacks. This necessitates a transition to post-quantum cryptography (PQC), which is resistant to such attacks. \n We are pleased to announce initial support for Post Quantum Cryptography (PQC) in NGINX Plus R33. \n NGINX provides PQC support using the Open Quantum Safe provider library for OpenSSL 3.x (oqs-provider). This library is available from the Open Quantum Safe (OQS) project. The oqs-provider library adds support for all post-quantum algorithms supported by the OQS project into network protocols like TLS in OpenSSL-3 reliant applications. All ciphers/algorithms provided by oqs-provider are supported by NGINX. \n To configure NGINX with PQC support using oqs-provider, follow these steps: \n \n Install the necessary dependencies \n \n sudo apt update\nsudo apt install -y build-essential git cmake ninja-build libssl-dev pkg-config \n \n \n Download and install liboqs \n \n git clone --branch main https://github.com/open-quantum-safe/liboqs.git\ncd liboqs\nmkdir build && cd build\ncmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr/local -DOQS_DIST_BUILD=ON ..\nninja\nsudo ninja install \n \n \n Download and install oqs-provider \n \n git clone --branch main https://github.com/open-quantum-safe/oqs-provider.git\ncd oqs-provider\nmkdir build && cd build\ncmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DOPENSSL_ROOT_DIR=/usr/local/ssl ..\nmake -j$(nproc)\nsudo make install \n \n \n Download and install OpenSSL with oqs-provider support \n \n git clone https://github.com/openssl/openssl.git\ncd openssl\n./Configure --prefix=/usr/local/ssl --openssldir=/usr/local/ssl linux-x86_64\nmake -j$(nproc)\nsudo make install_sw \n \n \n Configure OpenSSL for oqs-provider \n \n /usr/local/ssl/openssl.cnf:\nopenssl_conf = openssl_init\n\n[openssl_init]\nproviders = provider_sect\n\n[provider_sect]\ndefault = default_sect\noqsprovider = oqsprovider_sect\n\n[default_sect]\nactivate = 1\n\n[oqsprovider_sect]\nactivate = 1 \n \n \n Generate post quantum certificates \n \n export OPENSSL_CONF=/usr/local/ssl/openssl.cnf\n\n# Generate CA key and certificate\n/usr/local/ssl/bin/openssl req -x509 -new -newkey dilithium3 -keyout ca.key -out ca.crt -nodes -subj \"/CN=Post-Quantum CA\" -days 365\n# Generate server key and certificate signing request (CSR)\n/usr/local/ssl/bin/openssl req -new -newkey dilithium3 -keyout server.key -out server.csr -nodes -subj \"/CN=your.domain.com\"\n# Sign the server certificate with the CA\n/usr/local/ssl/bin/openssl x509 -req -in server.csr -out server.crt -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 \n \n \n Download and install NGINX Plus \n \n \n \n Configure NGINX to use the post quantum certificates \n \n server {\n\n listen 0.0.0.0:443 ssl;\n ssl_certificate /path/to/server.crt;\n ssl_certificate_key /path/to/server.key;\n ssl_protocols TLSv1.3;\n ssl_ecdh_curve kyber768;\n\n location / {\n return 200 \"$ssl_curve $ssl_curves\";\n }\n } \n \n QuickJS runtime support in NGINX JavaScript module: \n NGINX JavaScript is a unique JavaScript implementation for NGINX and NGINX Plus, designed specifically for server-side use cases and per request processing. It extends NGINX configuration syntax with JavaScript code to implement sophisticated configuration solutions. \n Today, the JavaScript runtime engine used in the NGINX JavaScript module is developed and maintained entirely by the NGINX team. While it has its obvious advantages in terms of feature development and prioritization, the rapidly evolving JavaScript specification is a challenging task to keep up with. NGINX JavaScript currently follows ECMAScript 5.1 with elements of ECMAScript 6 and above. \n To address spec challenges, we are pleased to introduce preview support for QuickJS runtime in NGINX JavaScript module version 0.8.6. QuickJS is a lightweight, embeddable JavaScript engine that supports the ES2023 specification, provides garbage collection out of the box and improved performance. And to offer best of both worlds, QuickJS will co-exist with NGINX JavaScript runtime and will be available as drop-in replacement in your njs scripts. Full support of the existing functionality will be available in future releases. \n For details on how you can leverage QuickJS in your njs scripts and the functions supported today, please refer to our documentation. \n \n OCSP Client Verification and Stapling Support in Stream module: \n The Online Certificate Status Protocol (OCSP) is a protocol for checking if an SSL certificate has been revoked. It was created as an alternative to CRL to reduce the SSL negotiation time. With CRL (Certificate Revocation List) the browser downloads a list of revoked certificate serial numbers and verifies the current certificate, which increases the SSL negotiation time. In OCSP, as the client certificates are presented, the browser sends a request to a OCSP URL and receives a response containing the validity status of the certificate. \n Today, NGINX Plus supports OCSP client certificate verification and stapling in the http module. In R33, we are bringing the OCSP client certificate verification and stapling support to the stream module as well. \n To enable OCSP validation of SSL client certificates, include the new ssl_ocsp directive along with the ssl_verify_client directive (should be set to on or optional), which enables certificate verification. \n Syntax: \n ssl_ocsp on | off | leaf;\n(default is off, the leaf parameter enables validation of the client certificate only.) \n OCSP however has two issues - privacy and heavy load on CA’s servers. Since OCSP requires the browser to contact the CA to confirm certificate validity it compromises privacy. The CA knows what website is being accessed and who accessed it. Also, if a HTTPS website gets lots of visitors, the CA’s OCSP server must handle all the OCSP requests made by the visitors. \n This is where OCSP stapling comes into play. OCSP stapling is a TLS/SSL extension which aims to improve the performance of SSL negotiation while improving performance and maintaining visitor privacy. With OCSP stapling, the certificate holder (read web server) queries the OCSP server directly and caches the response. This response is “stapled” with the TLS/SSL Handshake via the Certificate Status Request extension response. As a result, the CA’s servers are not burdened with requests and browsers no longer need to disclose users’ browsing habits to any third party. \n To enable OCSP stapling, use the ssl_stapling directive. \n ssl_stapling on | off;\n(default is off) \n \n Refer to the NGINX documentation for details on how to use these and related directives for OCSP certificate verification and stapling in stream context. \n \n Other Enhancements and Bug Fixes in NGINX Plus R33 \n \n HTTP Response trailers support \n HTTP Response trailers allow senders to add additional fields at the end of a chunked message and can be used to pass additional dynamic content like processing status, digital signatures etc. along with the response body. Refer here for enabling trailers with HTTP/1.1 and use cases where HTTP trailers cannot be used. \n Today, trailers are only supported in gRPC proxying using the grpc_pass directive. This enhancement adds support for trailers in proxy_pass as well. A new directive proxy_pass_trailers is introduced which allows passing trailer fields from the proxied upstream to clients. \n Sample Configuration \n location / {\n proxy_http_version 1.1;\n proxy_set_header Connection \"te\";\n proxy_set_header TE \"trailers\";\n proxy_pass_trailers on;\n proxy_pass ...\n} \n \n SSL Key Logging \n This enhancement allows logging SSL keys created during client and upstream connections to a file. This is useful for troubleshooting cases where you want to decrypt SSL traffic and examine SSL keys. The file is in SSLKEYLOGFILE format and is passed as an argument to the directive. \n ssl_key_log, proxy_ssl_key_log, grpc_ssl_key_log and uwsgi_ssl_key_log directives are being introduced in the R33 release to support SSL key logging. \n Sample configuration for logging SSL keys to a file: \n ssl_key_log /tmp/sslkey.log;\nproxy_key_log /tmp/sslkey.log; \n \n Improvements to SSL Client certificate verification \n With the NGINX Plus R33 release, the \"ssl_client_certificate\" directive is no longer required for client SSL certificates verification when using ssl_verify_client directive. This change relaxes the prior requirement to have at least one trusted CA certificate in the ssl_client_certificate directive. All trusted CA certificates can be specified using the ssl_trusted_certificate directive as well, if required. \n \n Bug Fixes: \n \n SSL Certificate Caching: Fixed loading of trusted CA bundles containing entries with duplicate Distinguished Name (DN). \n \n \n Changes Inherited from NGINX Open Source \n NGINX Plus R33 is based on NGINX Open Source 1.27.2 and inherits functional changes, features, and bug fixes made since NGINX Plus R32 was released (in NGINX open source 1.27.0, 1.27.1 and 1.27.2). \n Features: \n \n SSL certificates, secret keys, and CRLs are now cached on start or during reconfiguration. \n Added support for client certificate validation with OCSP in the stream module. \n Added support for OCSP stapling in the stream module. \n Added support for proxy_pass_trailers directive in the ngx_http_proxy_module. \n The ssl_client_certificate directive now supports certificates with auxiliary information. \n Variables support in the \"proxy_limit_rate\", \"fastcgi_limit_rate\", \"scgi_limit_rate\", and \"uwsgi_limit_rate\" directives. \n \n Changes: \n \n The ssl_client_certificate directive is no more required for client SSL certificates verification. \n The stream module handler is no longer mandatory. \n \n Bug Fixes: \n \n New HTTP/2 connections might ignore graceful shutdown of old worker processes. \n Reduced memory consumption for long-lived requests when \"gzip\", \"gunzip\", \"ssi\", \"sub_filter\" or \"grpc_pass\" directives are used. \n \n Security: \n \n CVE-2024-7347 - Processing of a specially crafted mp4 file by the ngx_http_mp4_module might cause a worker process crash. \n \n For the full list of new changes, features, bug fixes, and workarounds inherited from recent releases, see the NGINX changes . \n \n Changes to the NGINX JavaScript Module \n NGINX Plus R33 incorporates changes from the NGINX JavaScript (njs) module version 0.8.7. The following is a list of notable changes in njs since 0.8.4 (which was the version shipped with NGINX Plus R32). \n Features \n \n Introduced initial support for QuickJS JavaScript engine. \n Added optional nocache flag for js_set directive. \n Exposed capture group variables in HTTP module. \n Added timeout argument for add(), set(), and incr() methods of a shared dictionary. \n \n Changes \n \n The bytes invalid in UTF-8 encoding are converted into the replacement character in:\n \n r.variables.var, r.requestText, r.responseText, s.variables.var \n the data argument of the s.on() callback with upload or download event types \n the data argument of the js_body_filter directive. \n \n \n \n Bug Fixes \n \n Fixed handling of empty labelled statement in a function. \n Fixed Function constructor handling when called without arguments. \n Fixed Buffer.prototype.writeInt8() and friends. \n Fixed Buffer.prototype.writeFloat() and friends. \n Fixed Buffer.prototype.lastIndexOf(). \n Fixed Buffer.prototype.write(). \n Fixed maybe-uninitialized warnings in error creation. \n Fixed 'ctx.codepoint' initialization in UTF-8 decoding. \n Fixed 'length' initialization in Array.prototype.pop(). \n Fixed handling of encode arg in fs.readdir() and fs.realpath(). \n Fixed checking for duplicate js_set variables. \n Fixed request Host header when the port is non-standard. \n Fixed handling of a zero-length request body in ngx.fetch() and r.subrequest(). \n Fixed heap-buffer-overflow in Headers.get(). \n Fixed r.subrequest() error handling. \n Fixed zlib.inflate(). \n Fixed String.prototype.replaceAll() with a zero-length argument. \n Fixed retval handling after an exception in Array.prototype.toSpliced(), Array.prototype.toReversed(), Array.prototype.toSorted(). \n Fixed RegExp.prototype[@@replace]() with replacements containing $', $` and strings with Unicode characters. \n Fixed a one-byte overread in decodeURI() and decodeURIComponent(). \n Fixed tracking of argument scope. \n Fixed integer overflow in Date.parse(). \n \n For a comprehensive list of all the features, changes, and bug fixes, see the njs Changelog. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"17018","kudosSumWeight":3,"repliesCount":3,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuNHwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzY0MDMtTk5DNmsy?revision=9\"}"}}],"totalCount":1,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}},"videos":{"__typename":"VideoConnection","edges":[],"totalCount":0,"pageInfo":{"__typename":"PageInfo","hasNextPage":false,"endCursor":null,"hasPreviousPage":false,"startCursor":null}}},"CachedAsset:text:en_US-components/community/Navbar-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1751557989989","value":{"community":"Community Home","inbox":"Inbox","manageContent":"Manage Content","tos":"Terms of Service","forgotPassword":"Forgot Password","themeEditor":"Theme Editor","edit":"Edit Navigation Bar","skipContent":"Skip to content","migrated-link-9":"Groups","migrated-link-7":"Technical Articles","migrated-link-8":"DevCentral News","migrated-link-1":"Technical Forum","migrated-link-10":"Community Groups","migrated-link-2":"Water Cooler","migrated-link-11":"F5 Groups","Common-external-link":"How Do I...?","migrated-link-0":"Forums","article-series":"Article Series","migrated-link-5":"Community Articles","migrated-link-6":"Articles","security-insights":"Security Insights","migrated-link-3":"CrowdSRC","migrated-link-4":"CodeShare","migrated-link-12":"Events","migrated-link-13":"Suggestions"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarHamburgerDropdown-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1751557989989","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1751557989989","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1751557989989","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1751557989989","value":{"title.login":"Sign In","title.registration":"Register","title.forgotPassword":"Forgot Password","title.multiAuthLogin":"Sign In"},"localOverride":false},"CachedAsset:text:en_US-components/nodes/NodeLink-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1751557989989","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagSubscriptionAction-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagSubscriptionAction-1751557989989","value":{"success.follow.title":"Following Tag","success.unfollow.title":"Unfollowed Tag","success.follow.message.followAcrossCommunity":"You will be notified when this tag is used anywhere across the community","success.unfollowtag.message":"You will no longer be notified when this tag is used anywhere in this place","success.unfollowtagAcrossCommunity.message":"You will no longer be notified when this tag is used anywhere across the community","unexpected.error.title":"Error - Action Failed","unexpected.error.message":"An unidentified problem occurred during the action you took. Please try again later.","buttonTitle":"{isSubscribed, select, true {Unfollow} false {Follow} other{}}","unfollow":"Unfollow"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/QueryHandler-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1751557989989","value":{"title":"Query Handler"},"localOverride":false},"Category:category:top":{"__typename":"Category","id":"category:top","nodeType":"category"},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1751557989989","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListTabs-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListTabs-1751557989989","value":{"mostKudoed":"{value, select, IDEA {Most Votes} other {Most Likes}}","mostReplies":"Most Replies","mostViewed":"Most Viewed","newest":"{value, select, IDEA {Newest Ideas} OCCASION {Newest Events} other {Newest Topics}}","newestOccasions":"Newest Events","mostRecent":"Most Recent","noReplies":"No Replies Yet","noSolutions":"No Solutions Yet","solutions":"Solutions","mostRecentUserContent":"Most Recent","trending":"Trending","draft":"Drafts","spam":"Spam","abuse":"Abuse","moderation":"Moderation","tags":"Tags","PAST":"Past","UPCOMING":"Upcoming","sortBymostRecent":"Sort By Most Recent","sortBymostRecentUserContent":"Sort By Most Recent","sortBymostKudoed":"Sort By Most Likes","sortBymostReplies":"Sort By Most Replies","sortBymostViewed":"Sort By Most Viewed","sortBynewest":"Sort By Newest Topics","sortBynewestOccasions":"Sort By Newest Events","otherTabs":" Messages list in the {tab} for {conversationStyle}","guides":"Guides","archives":"Archives"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewInline-1751557989989","value":{"bylineAuthor":"{bylineAuthor}","bylineBoard":"{bylineBoard}","anonymous":"Anonymous","place":"Place {bylineBoard}","gotoParent":"Go to parent {name}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Pager/PagerLoadMore-1751557989989","value":{"loadMore":"Show More"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1751557989989","value":{"errorMessage":"Error rendering component id: {customComponentId}","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/OverflowNav-1751557989989","value":{"toggleText":"More"},"localOverride":false},"CachedAsset:text:en_US-components/users/UserLink-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1751557989989","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1751557989989","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageBody-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1751557989989","value":{"showMessageBody":"Show More","mentionsErrorTitle":"{mentionsType, select, board {Board} user {User} message {Message} other {}} No Longer Available","mentionsErrorMessage":"The {mentionsType} you are trying to view has been removed from the community.","videoProcessing":"Video is being processed. Please try again in a few minutes.","bannerTitle":"Video provider requires cookies to play the video. Accept to continue or {url} it directly on the provider's site.","buttonTitle":"Accept","urlText":"watch"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1751557989989","value":{"postTime":"Published: {time}","lastPublishTime":"Last Update: {time}","conversation.lastPostingActivityTime":"Last posting activity time: {time}","conversation.lastPostTime":"Last post time: {time}","moderationData.rejectTime":"Rejected time: {time}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1751557989989","value":{"contentType":"Content Type {style, select, FORUM {Forum} BLOG {Blog} TKB {Knowledge Base} IDEA {Ideas} OCCASION {Events} other {}} icon"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageUnreadCount-1751557989989","value":{"unread":"{count} unread","comments":"{count, plural, one { unread comment} other{ unread comments}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageViewCount-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageViewCount-1751557989989","value":{"textTitle":"{count, plural,one {View} other{Views}}","views":"{count, plural, one{View} other{Views}}"},"localOverride":false},"CachedAsset:text:en_US-components/kudos/KudosCount-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/kudos/KudosCount-1751557989989","value":{"textTitle":"{count, plural,one {{messageType, select, IDEA{Vote} other{Like}}} other{{messageType, select, IDEA{Votes} other{Likes}}}}","likes":"{count, plural, one{like} other{likes}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRepliesCount-1751557989989","value":{"textTitle":"{count, plural,one {{conversationStyle, select, IDEA{Comment} OCCASION{Comment} other{Reply}}} other{{conversationStyle, select, IDEA{Comments} OCCASION{Comments} other{Replies}}}}","comments":"{count, plural, one{Comment} other{Comments}}"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1751557989989":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1751557989989","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false}}}},"page":"/tags/TagPage/TagPage","query":{"messages.widget.messagelistfornodebyrecentactivitywidget-tab-main-messages-list-for-tag-widget-0":"mostRecent","tagName":"nginx plus"},"buildId":"3XH0qYWYCnEYycuN5W4S8","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","surveysEnabled":true,"openTelemetry":{"clientEnabled":false,"configName":"f5","serviceVersion":"25.4.0","universe":"prod","collector":"http://localhost:4318","logLevel":"error","routeChangeAllowedTime":"5000","headers":"","enableDiagnostic":"false","maxAttributeValueLength":"4095"},"apolloDevToolsEnabled":false,"quiltLazyLoadThreshold":"3"},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["components_customComponent_CustomComponent","components_community_Navbar_NavbarWidget","components_community_Breadcrumb_BreadcrumbWidget","components_tags_TagsHeaderWidget","components_messages_MessageListForNodeByRecentActivityWidget","components_tags_TagSubscriptionAction","components_customComponent_CustomComponentContent_TemplateContent","shared_client_components_common_List_ListGroup","components_messages_MessageView","components_messages_MessageView_MessageViewInline","shared_client_components_common_Pager_PagerLoadMore","components_customComponent_CustomComponentContent_HtmlContent","components_customComponent_CustomComponentContent_CustomComponentScripts"],"appGip":true,"scriptLoader":[]}