NGINX Plus

43 Topics
"}},"componentScriptGroups({\"componentId\":\"custom.widget.Beta_MetaNav\"})":{"__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.Beta_Footer\"})":{"__typename":"Component","render({\"context\":{\"component\":{\"entities\":[],\"props\":{}},\"page\":{\"entities\":[],\"name\":\"TagPage\",\"props\":{},\"url\":\"https://community.f5.com/tag/NGINX%20Plus\"}}})":{"__typename":"ComponentRenderResult","html":"
 
 
 
 
 

\"F5 ©2024 F5, Inc. All rights reserved.
Trademarks Policies Privacy California Privacy Do Not Sell My Personal Information
"}},"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\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/community/NavbarDropdownToggle\"]})":[{"__ref":"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/OverflowNav\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageView/MessageViewInline\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/common/Pager/PagerLoadMore\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/common/Pager/PagerLoadMore-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/customComponent/CustomComponent\"]})":[{"__ref":"CachedAsset:text:en_US-components/customComponent/CustomComponent-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/users/UserLink\"]})":[{"__ref":"CachedAsset:text:en_US-components/users/UserLink-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageSubject\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageSubject-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageTime\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageTime-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/nodes/NodeIcon\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/nodes/NodeIcon-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageUnreadCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageUnreadCount-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageViewCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageViewCount-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/kudos/KudosCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/kudos/KudosCount-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageRepliesCount\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageRepliesCount-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"components/messages/MessageBody\"]})":[{"__ref":"CachedAsset:text:en_US-components/messages/MessageBody-1743097588266"}],"cachedText({\"lastModified\":\"1743097588266\",\"locale\":\"en-US\",\"namespaces\":[\"shared/client/components/users/UserAvatar\"]})":[{"__ref":"CachedAsset:text:en_US-shared/client/components/users/UserAvatar-1743097588266"}]},"CachedAsset:pages-1742462581816":{"__typename":"CachedAsset","id":"pages-1742462581816","value":[{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.MvpProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/mvp-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.AdvocacyProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/advocacy-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetHelp.NonCustomer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/non-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Customer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetInvolved","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"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":1742462581816,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetHelp.Community","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/community","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.ContributeCode","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/contribute-code","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.Learn.AboutIrules","type":"COMMUNITY","urlPath":"/c/how-do-i/learn/about-irules","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Support","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-support","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetHelp","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"HowDoI.GetHelp.SecurityIncident","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/security-incident","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1742462581816,"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}"},"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},"User:user:-1":{"__typename":"User","id":"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"]}},"deleted":false},"Theme:customTheme1":{"__typename":"Theme","id":"customTheme1"},"CachedAsset:theme:customTheme1-1742462581110":{"__typename":"CachedAsset","id":"theme:customTheme1-1742462581110","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":"JimmyPackets-512-1702592938213.png","imageLastModified":"1702592945815","__typename":"ThemeAsset"},"customerLogo":{"imageAssetName":"f5_logo_fix-1704824537976.svg","imageLastModified":"1704824540697","__typename":"ThemeAsset"},"maximumWidthOfPageContent":"1600px","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":"400","textTransform":"NONE","disabledOpacity":0.5,"primaryTextColor":"var(--lia-bs-white)","primaryTextHoverColor":"var(--lia-bs-white)","primaryTextActiveColor":"var(--lia-bs-white)","primaryBgColor":"var(--lia-bs-primary)","primaryBgHoverColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.85))","primaryBgActiveColor":"hsl(var(--lia-bs-primary-h), var(--lia-bs-primary-s), calc(var(--lia-bs-primary-l) * 0.7))","primaryBorder":"1px solid transparent","primaryBorderHover":"1px solid transparent","primaryBorderActive":"1px solid transparent","primaryBorderFocus":"1px solid var(--lia-bs-white)","primaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","secondaryTextColor":"var(--lia-bs-gray-900)","secondaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","secondaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","secondaryBgColor":"var(--lia-bs-gray-400)","secondaryBgHoverColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.96))","secondaryBgActiveColor":"hsl(var(--lia-bs-gray-400-h), var(--lia-bs-gray-400-s), calc(var(--lia-bs-gray-400-l) * 0.92))","secondaryBorder":"1px solid transparent","secondaryBorderHover":"1px solid transparent","secondaryBorderActive":"1px solid transparent","secondaryBorderFocus":"1px solid transparent","secondaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 0.2)","tertiaryTextColor":"var(--lia-bs-gray-900)","tertiaryTextHoverColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.95))","tertiaryTextActiveColor":"hsl(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), calc(var(--lia-bs-gray-900-l) * 0.9))","tertiaryBgColor":"transparent","tertiaryBgHoverColor":"transparent","tertiaryBgActiveColor":"hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.04)","tertiaryBorder":"1px solid transparent","tertiaryBorderHover":"1px solid hsla(var(--lia-bs-black-h), var(--lia-bs-black-s), var(--lia-bs-black-l), 0.08)","tertiaryBorderActive":"1px solid transparent","tertiaryBorderFocus":"1px solid transparent","tertiaryBoxShadowFocus":"0 0 0 1px var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 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 var(--lia-bs-primary), 0 0 0 4px hsla(var(--lia-bs-primary-h), var(--lia-bs-primary-s), var(--lia-bs-primary-l), 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":"NONE","sideContent":"NONE","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.08)","sm":"0 2px 4px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.06)","md":"0 5px 15px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","lg":"0 10px 30px hsla(var(--lia-bs-gray-900-h), var(--lia-bs-gray-900-s), var(--lia-bs-gray-900-l), 0.15)","__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":"400","defaultMessageFontStyle":"NORMAL","defaultMessageFontWeight":"400","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":"#0C5C8D","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"],"__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":"Inter","fontStyle":"NORMAL","fontWeight":"600","h1FontSize":"30px","h2FontSize":"25px","h3FontSize":"20px","h4FontSize":"18px","h5FontSize":"16px","h6FontSize":"16px","lineHeight":"1.2","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","__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":"Atkinson Hyperlegible","fontStyleBase":"NORMAL","fontWeightBase":"400","fontWeightLight":"300","fontWeightNormal":"400","fontWeightMd":"500","fontWeightBold":"700","letterSpacingSm":"normal","letterSpacingXs":"normal","lineHeightBase":"1.3","fontSizeBase":"15px","fontSizeXxs":"11px","fontSizeXs":"12px","fontSizeSm":"13px","fontSizeLg":"20px","fontSizeXl":"24px","smallFontSize":"14px","customFonts":[],"__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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Loading/LoadingDot-1743097588266","value":{"title":"Loading..."},"localOverride":false},"CachedAsset:text:en_US-components/common/EmailVerification-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/common/EmailVerification-1743097588266","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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-pages/tags/TagPage-1743097588266","value":{"tagPageTitle":"Tag:\"{tagName}\" | {communityTitle}","tagPageForNodeTitle":"Tag:\"{tagName}\" in \"{title}\" | {communityTitle}","name":"Tags Page","tag":"Tag: {tagName}"},"localOverride":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bi0zNC0xM2k0MzE3N0Q2NjFBRDg5NDAy\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bi0zNC0xM2k0MzE3N0Q2NjFBRDg5NDAy","mimeType":"image/png"},"Category:category:Articles":{"__typename":"Category","id":"category:Articles","entityType":"CATEGORY","displayId":"Articles","nodeType":"category","depth":1,"title":"Articles","shortTitle":"Articles","parent":{"__ref":"Category:category:top"},"categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Category:category:top":{"__typename":"Category","id":"category:top","displayId":"top","nodeType":"category","depth":0,"title":"Top"},"Tkb:board:TechnicalArticles":{"__typename":"Tkb","id":"board:TechnicalArticles","entityType":"TKB","displayId":"TechnicalArticles","nodeType":"board","depth":2,"conversationStyle":"TKB","title":"Technical Articles","description":"F5 SMEs share good practice.","avatar":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bi0zNC0xM2k0MzE3N0Q2NjFBRDg5NDAy\"}"},"profileSettings":{"__typename":"ProfileSettings","language":null},"parent":{"__ref":"Category:category:Articles"},"ancestors":{"__typename":"CoreNodeConnection","edges":[{"__typename":"CoreNodeEdge","node":{"__ref":"Community:community:zihoc95639"}},{"__typename":"CoreNodeEdge","node":{"__ref":"Category:category:Articles"}}]},"userContext":{"__typename":"NodeUserContext","canAddAttachments":false,"canUpdateNode":false,"canPostMessages":false,"isSubscribed":false},"boardPolicies":{"__typename":"BoardPolicies","canPublishArticleOnCreate":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","key":"error.lithium.policies.forums.policy_can_publish_on_create_workflow_action.accessDenied","args":[]}},"canReadNode":{"__typename":"PolicyResult","failureReason":null}},"tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"shortTitle":"Technical Articles","tagPolicies":{"__typename":"TagPolicies","canSubscribeTagOnNode":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.labels.action.corenode.subscribe_labels.allow.accessDenied","key":"error.lithium.policies.labels.action.corenode.subscribe_labels.allow.accessDenied","args":[]}},"canManageTagDashboard":{"__typename":"PolicyResult","failureReason":{"__typename":"FailureReason","message":"error.lithium.policies.labels.action.corenode.admin_labels.allow.accessDenied","key":"error.lithium.policies.labels.action.corenode.admin_labels.allow.accessDenied","args":[]}}}},"CachedAsset:quilt:f5.prod:pages/tags/TagPage:board:TechnicalArticles-1743097590074":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/tags/TagPage:board:TechnicalArticles-1743097590074","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:quiltWrapper:f5.prod:Common:1742462479161":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1742462479161","value":{"id":"Common","header":{"backgroundImageProps":{"assetName":"header.jpg","backgroundSize":"COVER","backgroundRepeat":"NO_REPEAT","backgroundPosition":"LEFT_CENTER","lastModified":"1702932449000","__typename":"BackgroundImageProps"},"backgroundColor":"transparent","items":[{"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,"style":{"boxShadow":"var(--lia-bs-box-shadow-sm)","linkFontWeight":"700","controllerHighlightColor":"hsla(30, 100%, 50%)","dropdownDividerMarginBottom":"10px","hamburgerBorderHover":"none","linkFontSize":"15px","linkBoxShadowHover":"none","backgroundOpacity":0.4,"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":"0","hamburgerBorder":"none","dropdownPaddingX":"10px","brandMarginRightSm":"10px","linkBoxShadow":"none","linkJustifyContent":"center","linkColor":"var(--lia-bs-primary)","collapseMenuDividerBg":"var(--lia-nav-link-color)","dropdownPaddingTop":"10px","controllerHighlightTextColor":"var(--lia-yiq-dark)","background":{"imageAssetName":"","color":"var(--lia-bs-white)","size":"COVER","repeat":"NO_REPEAT","position":"CENTER_CENTER","imageLastModified":""},"linkBorderRadius":"var(--lia-bs-border-radius-sm)","linkHoverColor":"var(--lia-bs-primary)","position":"FIXED","linkBorder":"none","linkTextBorderBottomHover":"2px solid #0C5C8D","brandMarginRight":"30px","hamburgerHoverColor":"var(--lia-nav-controller-icon-color)","linkBorderHover":"none","collapseMenuMarginLeft":"20px","linkFontStyle":"NORMAL","linkPaddingX":"10px","paddingTop":"10px","linkPaddingY":"5px","linkTextTransform":"NONE","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)","linkDropdownPaddingX":"var(--lia-nav-link-px)","linkBgColor":"transparent","linkDropdownPaddingY":"9px","controllerIconColor":"#0C5C8D","dropdownDividerMarginTop":"10px","linkGap":"10px","controllerIconHoverColor":"#0C5C8D"},"links":{"sideLinks":[],"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},"__typename":"QuiltComponent"},{"id":"community.widget.bannerWidget","props":{"backgroundColor":"transparent","visualEffects":{"showBottomBorder":false},"backgroundImageProps":{"backgroundSize":"COVER","backgroundPosition":"CENTER_CENTER","backgroundRepeat":"NO_REPEAT"},"fontColor":"#222222"},"__typename":"QuiltComponent"},{"id":"community.widget.breadcrumbWidget","props":{"backgroundColor":"var(--lia-bs-primary)","linkHighlightColor":"#FFFFFF","visualEffects":{"showBottomBorder":false},"backgroundOpacity":60,"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:text:en_US-components/common/ActionFeedback-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/common/ActionFeedback-1743097588266","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:component:custom.widget.Beta_MetaNav-en-1742462597562":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-1742462597562","value":{"component":{"id":"custom.widget.Beta_MetaNav","template":{"id":"Beta_MetaNav","markupLanguage":"HANDLEBARS","style":null,"texts":null,"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-1742462597562":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-1742462597562","value":{"component":{"id":"custom.widget.Beta_Footer","template":{"id":"Beta_Footer","markupLanguage":"HANDLEBARS","style":null,"texts":null,"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-1742462597562":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-1742462597562","value":{"component":{"id":"custom.widget.Tag_Manager_Helper","template":{"id":"Tag_Manager_Helper","markupLanguage":"HANDLEBARS","style":null,"texts":null,"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-1742462597562":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-1742462597562","value":{"component":{"id":"custom.widget.Consent_Blackbar","template":{"id":"Consent_Blackbar","markupLanguage":"HTML","style":null,"texts":null,"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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/community/Breadcrumb-1743097588266","value":{"navLabel":"Breadcrumbs","dropdown":"Additional parent page navigation"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagsHeaderWidget-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagsHeaderWidget-1743097588266","value":{"tag":"{tagName}","topicsCount":"{count} {count, plural, one {Topic} other {Topics}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListForNodeByRecentActivityWidget-1743097588266","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}}},"Forum:board:TechnicalForum":{"__typename":"Forum","id":"board:TechnicalForum","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Forum:board:WaterCooler":{"__typename":"Forum","id":"board:WaterCooler","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"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: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","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":397},"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":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTElCdUtx?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtNzFkcUtQ?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTUg5QUJ3?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtdUVHbGVh?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWFg0SFlz?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtc2Vhc2Zk?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDc","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWWY2NWFF?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDg","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtR1hhcE9X?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDk","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQ2lEa0xk?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0VZcW9C?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEx","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtWUtzZmVD?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEy","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTFRrUUJN?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEz","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtRWdvcWxa?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE0","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQjl3THk4?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE1","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtMm9YYU9R?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE2","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtOElSaUNi?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE3","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU2JGZ0Va?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE4","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtU0NqZDJ5?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE5","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtM0lZbGtk?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDIw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtTHRTMmVv?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDIx","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtQk91QVlK?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDIy","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtN0psanFj?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDIz","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtV3RYWDVS?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI0","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtZnZJV1gy?revision=34\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI1","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzgzMjAtVEFwVU5t?revision=34\"}"}}],"totalCount":30,"pageInfo":{"__typename":"PageInfo","hasNextPage":true,"endCursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI1","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","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":208},"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},"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/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","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":1447},"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":"MjUuMnwyLjF8b3wyNXxfTlZffDE","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}}},"Conversation:conversation:336851":{"__typename":"Conversation","id":"conversation:336851","topic":{"__typename":"TkbTopicMessage","uid":336851},"lastPostingActivityTime":"2025-01-08T12:58:25.159-08: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","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":424},"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":2,"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:336922":{"__typename":"Conversation","id":"conversation:336922","topic":{"__typename":"TkbTopicMessage","uid":336922},"lastPostingActivityTime":"2024-12-17T05:00:00.043-08: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:336922":{"__typename":"TkbTopicMessage","subject":"Introducing the New Docker Compose Installation Option for F5 NGINX Instance Manager","conversation":{"__ref":"Conversation:conversation:336922"},"id":"message:336922","revisionNum":4,"uid":336922,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:422019"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"Deploy Instance Manager in under 3 steps","metrics":{"__typename":"MessageMetrics","views":84},"postTime":"2024-12-17T05:00:00.043-08:00","lastPublishTime":"2024-12-17T05:00:00.043-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" F5 NGINX Instance Manager (NIM) is a centralised management solution designed to simplify the administration and monitoring of F5 NGINX instances across various environments, including on-premises, cloud, and hybrid infrastructures. It provides a single interface to efficiently oversee multiple NGINX instances, making it particularly useful for organizations using NGINX at scale. \n We’re excited to introduce a new Docker Compose installation option for NGINX Instance Manager, designed to help you get up and running faster than ever before, in just a couple of steps. \n Key Features: \n \n Quick and Easy Installation: With just a couple of steps, you can pull and deploy NGINX Instance Manager on any Docker host, without having to manually configure multiple components. The image is available in our container registry, so once you have a valid license to access it, getting up and running is as simple as pulling the container. \n Fault-Tolerant and Resilient: This installation option is designed with fault tolerance in mind. Persistent storage ensures your data is safe even in the event of container restarts or crashes. Additionally, with a separate database container, your product’s data is isolated, adding an extra layer of resilience and making it easier to manage backups and restores. \n Seamless Upgrades: Upgrades are a breeze. You can update to the latest version of NGINX Instance Manager by simply updating the image tag in your Docker Compose file. This makes it easy to stay up-to-date with the latest features and improvements without worrying about downtime or complex upgrade processes. \n Backup and Restore Options: To ensure your data is protected, this installation option comes with built-in backup and restore capabilities. Easily back up your data to a safe location and restore it in case of any issues. \n Environment Configuration Flexibility: The Docker Compose setup allows you to define custom environment variables, giving you full control over configuration settings such as log levels, timeout values, and more. \n Production-Ready: Designed for scalability and reliability, this installation method is ready for production environments. With proper resource allocation and tuning, you can deploy NGINX Instance Manager to handle heavy workloads while maintaining performance. \n \n   \n The following steps walk you through how to deploy and manage NGINX Instance Manager using Docker Compose. \n What you need \n \n A working version of Docker \n Your NGINX subscription’s JSON Web Token from MyF5 \n This pre-configured docker-compose.yaml file: \n \n  Download docker-compose.yaml file . \n \n \n   \n Step 1 - Set up Docker for NGINX container registry \n Log in to the Docker registry using the contents of the JSON Web Token file you downloaded from MyF5 : \n docker login private-registry.nginx.com --username=<JWT_CONTENTS> --password=none \n   \n Step 2 -  Run “docker login” and then “docker compose up” in the directory where you downloaded docker-compose.yaml \n Note: You can optionally set the Administrator password for NGINX Instance Manager prior to running Docker Compose. \n   \n ~$ docker login private-registry.nginx.com --username=<JWT_CONTENTS> --password=none ~$ echo \"admin\" > admin_password.txt ~$ docker compose up -d [+] Running 6/6  ✔ Network nim_clickhouse        Created                                                                                           0.1s  ✔ Network nim_external_network  Created                                                                                           0.2s  ✔ Network nim_default           Created                                                                                           0.2s  ✔ Container nim-precheck-1      Started                                                                                           0.8s  ✔ Container nim-clickhouse-1    Healthy                                                                                           6.7s  ✔ Container nim-nim-1           Started                                                                                           7.4s. \n   \n Step 3 – Access NGINX Instance Manager \n Go to the NGINX Instance Manager UI on https://<<DOCKER_HOST>>:443 and license the product using the same JSON Web Token you downloaded from MyF5 earlier. \n   \n Conclusion \n With this new setup, you can install and run NGINX Instance Manager  on any Docker host in just 3 steps, dramatically reducing setup time and simplifying deployment. Whether you are working in a development environment or deploying to production, the Docker Compose-based solution ensures a seamless and reliable experience. \n   \n For more information on using the docker compose option with NGINX Instance manager such as running a backup and restore, using secrets, and many more, please see the instructions here. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"7881","kudosSumWeight":1,"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:330138":{"__typename":"Conversation","id":"conversation:330138","topic":{"__typename":"TkbTopicMessage","uid":330138},"lastPostingActivityTime":"2024-12-09T11:56:04.412-08:00","solved":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZGt5Yk0x?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZGt5Yk0x?revision=18","title":"Screenshot 2024-05-29 at 8.32.49 PM.png","associationType":"BODY","width":1084,"height":690,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtc2ZWOEpx?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtc2ZWOEpx?revision=18","title":"genapi.png","associationType":"BODY","width":3558,"height":1720,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZ0ZqSHdP?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZ0ZqSHdP?revision=18","title":"genapi2.png","associationType":"BODY","width":3062,"height":1464,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtczd5OVBv?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtczd5OVBv?revision=18","title":"Screenshot 2024-05-29 at 8.47.04 PM.png","associationType":"BODY","width":1434,"height":560,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtYnZyVFNJ?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtYnZyVFNJ?revision=18","title":"Screenshot 2024-05-29 at 8.53.46 PM.png","associationType":"BODY","width":3056,"height":1248,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtb09wODAx?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtb09wODAx?revision=18","title":"Screenshot 2024-05-29 at 8.50.49 PM.png","associationType":"BODY","width":1342,"height":840,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtOXZ3NTJj?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtOXZ3NTJj?revision=18","title":"Screenshot 2024-05-29 at 9.46.40 PM.png","associationType":"BODY","width":946,"height":162,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtMUh0ejJu?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtMUh0ejJu?revision=18","title":"Screenshot 2024-05-29 at 10.05.35 PM.png","associationType":"BODY","width":1224,"height":282,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtWXRZUGk1?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtWXRZUGk1?revision=18","title":"Screenshot 2024-05-29 at 9.58.11 PM.png","associationType":"BODY","width":1912,"height":918,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtVjBGNTlX?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtVjBGNTlX?revision=18","title":"Screenshot 2024-05-29 at 9.05.54 PM.png","associationType":"BODY","width":2002,"height":822,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtRFRUdXd6?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtRFRUdXd6?revision=18","title":"Screenshot 2024-05-29 at 9.08.10 PM.png","associationType":"BODY","width":2450,"height":1266,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtUEZZdDha?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtUEZZdDha?revision=18","title":"Screenshot 2024-05-29 at 9.04.15 PM.png","associationType":"BODY","width":1070,"height":446,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtemFuVFZQ?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtemFuVFZQ?revision=18","title":"Screenshot 2024-05-29 at 10.28.32 PM.png","associationType":"BODY","width":1914,"height":940,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtaGRHMk9l?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtaGRHMk9l?revision=18","title":"Screenshot 2024-05-29 at 10.30.41 PM.png","associationType":"BODY","width":1048,"height":424,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZkwxcE5P?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZkwxcE5P?revision=18","title":"Screenshot 2024-05-29 at 11.11.44 PM.png","associationType":"BODY","width":1076,"height":408,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtenJBdVpT?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtenJBdVpT?revision=18","title":"Screenshot 2024-05-29 at 11.13.23 PM.png","associationType":"BODY","width":814,"height":342,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtVVMydWR2?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtVVMydWR2?revision=18","title":"Screenshot 2024-05-29 at 10.50.10 PM.png","associationType":"BODY","width":1246,"height":356,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtWmsyZmxT?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtWmsyZmxT?revision=18","title":"Screenshot 2024-05-29 at 10.51.07 PM.png","associationType":"BODY","width":1294,"height":342,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtODdQdVpD?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtODdQdVpD?revision=18","title":"Screenshot 2024-05-29 at 11.04.04 PM.png","associationType":"BODY","width":850,"height":458,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtdFFwSDFo?revision=18\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtdFFwSDFo?revision=18","title":"Screenshot 2024-05-29 at 11.08.41 PM.png","associationType":"BODY","width":1218,"height":486,"altText":""},"TkbTopicMessage:message:330138":{"__typename":"TkbTopicMessage","subject":"How I did it - \"Securing NVIDIA’s Morpheus AI Framework with NGINX Plus Ingress Controller”","conversation":{"__ref":"Conversation:conversation:330138"},"id":"message:330138","revisionNum":18,"uid":330138,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:189442"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" In this installment of \"How I Did It,\" we continue our journey into AI security. I have documented how I deployed an NVIDIA Morpheus AI infrastructure along with F5's NGINX Plus Ingress Controller to provide secure and scalable external access. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":324},"postTime":"2024-11-26T05:00:00.038-08:00","lastPublishTime":"2024-11-26T05:00:00.038-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hello! In this installment of \"How I Did It,\" we continue our journey into AI security. Below I have documented how I deployed an NVIDIA Morpheus AI infrastructure along with F5's NGINX Plus Ingress Controller to provide secure and scalable external access. \n The NVIDIA Morpheus AI Framework is a cybersecurity framework designed to detect and mitigate threats in real time by leveraging AI and machine learning. It provides tools for deep packet inspection, anomaly detection, and automated response, enabling organizations to protect their data and infrastructure from advanced cyber threats. The framework is optimized for use with NVIDIA GPUs, ensuring high performance and scalability.  Morpheus can run on Kubernetes allowing for scalable, flexible, and efficient management of AI workloads across distributed environments.  In addition to Morpheus, NVIDIA offers several NIM microservices that utilize the same AI engine (Triton Inference server). \n NVIDIA NIM (NVIDIA Infrastructure Manager) Microservices is a suite of tools designed to simplify and automate the deployment, management, and scaling of AI and deep learning infrastructure on Kubernetes clusters. It enables seamless integration with NVIDIA GPUs, facilitating efficient resource allocation and optimization for AI workloads.   \n NGINX Plus Ingress Controller is architected to provide and manage external connectivity to applications running on Kubernetes. It enhances the standard Kubernetes Ingress capabilities by providing advanced features such as SSL/TLS termination, traffic throttling, and advanced routing based on request attributes. NGINX Plus can also integrate with external authentication services and provide enhanced security features like NGINX App Protect.  The controller is designed to improve the performance, reliability, and security of applications deployed on Kubernetes, making it a popular choice for managing ingress traffic in production environments. \n Okay, with the major players identified, let's see How I did it.... \n Prerequisites \n \n GPU-enabled Kubernetes cluster - I utilized a Standard_NC6s_v3 with a V100 GPU running on an Azure AKS cluster.  To enable the cluster to utilize the GPU, I deployed the NVIDIA GPU Operator \n NVIDIA NGC Account - You will need to have an NGC login as well generate an API token to pull the NVIDIA images.  Additional NIMs, container, models, etc. listed may require a NVIDIA Enterprise subscription.  You can request a 90-day evaluation as well. \n NGINX Plus License - Log into or create an account on the MyF5 Portal, navigate to your subscription details, and download the relevant .JWT files.  With respect to licensing, if needed, F5 provides a fully functional 30-day trial license.   \n Service TLS Certificate(s) - The embedded Triton Inference server exposes three (3) endpoints for HTTP, GRPC, and metrics.  You will need to create Kubernetes TLS secret(s) referencing the cert/key pair.  In below walkthrough, I combined my three self-signed certificates and keys (PEM format) and generated a single TLS secret. \n Helm - Each of the pods, (Morpheus AI Engine, Morpheus SDK CLI, Morpheus MLflow, and NGINX Plus Ingress Controller) are deployed using Helm charts. \n \n Let's Get Started 😀 \n Download the Helm Charts \n Prior to deploying any resources, I used VSCode to first create a folder 'nvidia' and fetched/pulled down Helm charts into individual subfolders for the following:  \n \n Morpheus AI Engine \n Morpheus SDK CLI \n Morpheus MLflow \n NGINX Plus Ingress Controller \n \n \n Create and export NGC API Key \n From the NVIDIA NGC portal, I navigated to 'Setup' and 'Generate API Key' \n \n From the upper right corner I selected '+ Generate API Key' and confirm to create the key.  I copied the key from the screen and store for the next step. \n \n From the command line I created an environment variable, API_KEY specifying the copied API key.  This environment variable will be referenced in the NVIDIA helm installs. \n export API_KEY=<ngc apikey> \n Create Kubernetes Secrets \n From the MyF5 Portal, navigate to your subscription details, and download 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 \n I also needed to create a Kubernetes TLS secret to store my NGINX hosted endpoints.  For ease, I combined my three cert/key combos into two files.  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 Deploy NGINX Plus Ingress Controller \n Before I deployed the NGINX Helm chart, I first needed to modify a few settings in the 'values.yaml' file.  Since I wanted to deploy NGINX Plus Ingress Controller with (NAP)  I specified a repo image, set the 'nginxplus' to true and enabled NGINX App Protect. \n \n I used the below command to deploy the Helm chart. \n helm install nginx-ingress ./nginx-ingress \n I made note of the ingress controller's EXTERNAL IP and updated my domain's (f5demo.net) DNS records (triton-http.f5demo.net, triton-grpc.f5demo.net, triton-http-metrics.f5demo.net) to reflect the public address. \n \n I used the below command to port-forward the ingress controller container to my local machine and accessed the dashboard - localhost:8080/dashboard.html. \n kubectl port-forward nginx-ingress-controller-6489bd6546 8080:8080 \n Deploy Morpheus AI Engine \n Update the values.yaml file \n I updated the 'values.yaml' file to include FQDN tags for the published services. \n \n In addition, I created three separate NGINX virtual server resource objects corresponding to the three Triton server endpoints.  The virtual server resources map the Morpheus AI Engine endpoints, (8000, 8001, 8002) to the already deployed NGINX Ingress Controller.  The contents of each file is included below. \n apiVersion: k8s.nginx.org/v1 kind: VirtualServer metadata: name: {{ .Values.tags.http_fqdn }} spec: host: {{ .Values.tags.http_fqdn }} tls: secret: tls-secret gunzip: on upstreams: - name: triton-http service: ai-engine port: 8000 routes: - path: / action: pass: triton-http apiVersion: k8s.nginx.org/v1 kind: VirtualServer metadata: name: {{ .Values.tags.grpc_fqdn }} spec: host: {{ .Values.tags.grpc_fqdn }} tls: secret: tls-secret upstreams: - name: triton-grpc service: ai-engine port: 8001 type: grpc routes: - path: / action: pass: triton-grpc apiVersion: k8s.nginx.org/v1 kind: VirtualServer metadata: name: {{ .Values.tags.metrics_fqdn }} spec: host: {{ .Values.tags.metrics_fqdn }} tls: secret: tls-secret gunzip: on upstreams: - name: triton-metrics service: ai-engine port: 8002 routes: - path: / action: pass: triton-metrics \n With the above files created, I deployed the Helm chart using the following command. \n helm install --set ngc.apiKey=\"$API_KEY\" morpheus-ai ./morpheus-ai-engine \n I returned to my NGINX dashboard to verify connectivity with the ingress controller and the upstream Morpheus service.  \n \n Deploy Morpheus SDK Client \n The SDK Client hosts shared models and data libraries. More importantly, the client provides a platform to deploy Morpheus pipelines.  I deployed the Helm chart using the following command. \n helm install --set ngc.apiKey=\"$API_KEY\" morpheus-sdk ./morpheus-sdk-client \n Once the sdk-cli-helper pod reaches a running state, use the below commands to connect to the pod and move models/data to the shared volume.  The shared volume will be accessed by the Morpheus MLflow pod to publish and deploy models to the AI engine. \n kubectl exec sdk-cli-helper -- cp -RL /workspace/models /common kubectl exec sdk-cli-helper -- cp -R /workspace/examples/data /common \n   \n Deploy Morpheus MLFlow \n The Morpheus MLFlow service is used to publish and deploy models to the Morpheus AI engine, (triton inference server).  Once the deployed, I will exec into the pod and publish/deploy models. \n helm install --set ngc.apiKey=\"$API_KEY\" morpheus-mflow ./morpheus-mlflow \n The Morpheus AI engine Helm chart deploys an instance of Kafka and Zookeeper to facilitate Morpheus pipelines.  To enable pipelines, I created two (2) Kafka topics with the below commands. \n kubectl exec deploy/broker -c broker -- kafka-topics.sh --create --bootstrap-server broker:9092 --replication-factor 1 --partitions 3 --topic mytopic kubectl exec deploy/broker -c broker -- kafka-topics.sh --create --bootstrap-server broker:9092 --replication-factor 1 --partitions 3 --topic mytopic-out \n Deploy Models \n The final step in the deployment was to connect to the MLFlow pod and publish/deploy a couple models to the Triton Inference server. \n kubectl exec -it deploy/mlflow -- bash \n Now connected to the pods command line, I took a quick look at the available models in the shared volume. \n ls -lrt /common/models \n I used the below commands to publish and deploy two models (sid-minibert-onnx, phishing-bert-onnx) from the shared volume. \n python publish_model_to_mlflow.py --model_name sid-minibert-onnx --model_directory /common/models/triton-model-repo/sid-minibert-onnx --flavor triton mlflow deployments create -t triton --flavor triton --name sid-minibert-onnx -m models:/sid-minibert-onnx/1 -C \"version=1\" python publish_model_to_mlflow.py --model_name phishing-bert-onnx --model_directory /common/models/triton-model-repo/phishing-bert-onnx --flavor triton mlflow deployments create -t triton --flavor triton --name phishing-bert-onnx -m models:/phishing-bert-onnx/1 -C \"version=1\" \n Validate Remote Access to Models \n With my Morpheus infrastructure deployed and sitting securely behind my NGINX Ingress Controller, there's nothing left to do but test with a couple of curl commands.  I'll first use curl to reach the inference server's status page. \n curl -v -k https://triton-http.f5demo.net/v2/health/ready \n Finally, i'll use curl to validate that I can reach one of the hosted models. \n curl -k https://triton-http.f5demo.net/v2/models/sid-minibert-onnx/config | jq \n Check it Out \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 Additional Links \n NVIDIA Morpheus AI Framework \n NVIDIA NGC Catalog \n NGINX Plus Ingress Controller \n NGINX App Protect \n How I did it - \"Securing Nvidia Triton Inference Server with NGINX Plus Ingress Controller” ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"10890","kudosSumWeight":2,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZGt5Yk0x?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtc2ZWOEpx?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZ0ZqSHdP?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtczd5OVBv?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtYnZyVFNJ?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtb09wODAx?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDc","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtOXZ3NTJj?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDg","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtMUh0ejJu?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDk","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtWXRZUGk1?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtVjBGNTlX?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEx","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtRFRUdXd6?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEy","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtUEZZdDha?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDEz","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtemFuVFZQ?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE0","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtaGRHMk9l?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE1","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtZkwxcE5P?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE2","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtenJBdVpT?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE3","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtVVMydWR2?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE4","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtWmsyZmxT?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE5","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtODdQdVpD?revision=18\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDIw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxMzgtdFFwSDFo?revision=18\"}"}}],"totalCount":20,"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:282166":{"__typename":"Conversation","id":"conversation:282166","topic":{"__typename":"TkbTopicMessage","uid":282166},"lastPostingActivityTime":"2024-11-25T07:07:06.778-08:00","solved":false},"User:user:171064":{"__typename":"User","uid":171064,"login":"Foo-Bang_Chan","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xNzEwNjQtSzhEcmtx?image-coordinates=62%2C0%2C1665%2C1603"},"id":"user:171064"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMjE5MWlDM0QzQjcyMjc2MjQzMTQ2?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMjE5MWlDM0QzQjcyMjc2MjQzMTQ2?revision=2","title":"0151T000003q7NLQAY.jpg","associationType":"BODY","width":2648,"height":1518,"altText":"null"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMTI3MzdpNEVCOEYzMDE5OTg3QTQwRA?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMTI3MzdpNEVCOEYzMDE5OTg3QTQwRA?revision=2","title":"0151T000003q84yQAA.jpg","associationType":"BODY","width":2230,"height":1110,"altText":"null"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMTQ2MzRpM0IzOUY3NjY3QkZGQTRDRQ?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMTQ2MzRpM0IzOUY3NjY3QkZGQTRDRQ?revision=2","title":"0151T000003q6JSQAY.jpg","associationType":"BODY","width":1744,"height":1336,"altText":"null"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtNjIwNWk5OTk3Mjk2NjM4NTU1QzU4?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtNjIwNWk5OTk3Mjk2NjM4NTU1QzU4?revision=2","title":"0151T000003q7GQQAY.jpg","associationType":"BODY","width":2664,"height":1642,"altText":"null"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtNTU5OGlFQzlFMzQ5QTg2NTMzRTkw?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtNTU5OGlFQzlFMzQ5QTg2NTMzRTkw?revision=2","title":"0151T000003q7GRQAY.jpg","associationType":"BODY","width":2650,"height":1128,"altText":"null"},"TkbTopicMessage:message:282166":{"__typename":"TkbTopicMessage","subject":"GitOps: Declarative Infrastructure and Application Delivery with NGINX App Protect","conversation":{"__ref":"Conversation:conversation:282166"},"id":"message:282166","revisionNum":2,"uid":282166,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:171064"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":2089},"postTime":"2021-01-27T09:24:34.000-08:00","lastPublishTime":"2024-11-25T07:07:06.778-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" First thing first. What is GitOps? \n In a nutshell, GitOps is a practice (Git Operation) that allows you to use GIT and code repository as your configuration source of truth (Declarative Infrastructure as Code and Application Delivery as Code) couple with various supporting tools. The state of your git repository syncs with your infrastructure and application states. As operation team runs daily operations (CRUD - \"Create, Read, Update and Delete\") leveraging the goodness and philosophy of DevOps, they no longer required to store configuration manifest onto various configuration systems. THe Git repo will be the source of truth. Typically, the target systems or infrastructures runs on Kubernetes base platform. For further details and better explanation of GitOps, please refer to below or Google search. \n https://codefresh.io/learn/gitops/ \n https://www.atlassian.com/git/tutorials/gitops \n   \n Why practice GitOps? \n I have been managing my lab environment for many years. I use my lab for research of technologies, customer demos/Proof-of-Concepts, applications testing, and code development. Due to the nature of constant changes to my environment (agile and dynamic nature), especially with my multiple versions of Kubernetes platform, I have been spending too much time updating, changing, building, deploying and testing various cloud native apps. Commands like docker build, kubectl, istioctl and git have been constantly and repetitively used to operate environments. Hence, I practice GitOps for my Kubernetes infrastructure. Of course, task/operation can be automated and orchestrated with tools such as Ansible, Terraform, Chef and Puppet. You may not necessarily need GitOps to achieve similar outcome. I managed with GitOps practice partly to learn the new \"language\" and to experience first-hand the full benefit of GitOps. Here are some of my learnings and operations experience that I have been using to manage F5's NGINX App Protect and many demo apps protected by it, which may benefit you and give you some insight on how you can run your own GitOps. You may leverage your own GitOps workflow from here. For details and description on F5's NGINX App Protect, please refer to https://www.nginx.com/products/nginx-app-protect/ \n   \n Key architecture decision of my GitOps Workflow. \n \n Modular architecture - allows me to swap in/out technologies without rework. \"Lego block\" \n Must reduce my operational works - saves time, no repetitive task, write once and deploy many. \n Centralize all my configuration manifest - single source of truth. Currently, my configuration exists everywhere - jump hosts, local laptop, cloud storage and etc. I had lost track of which configuration was the latest. \n Must be simple, modern, easy to understand and as native as possible. \n \n   \n Use Case and desirable outcome \n \n Build and keep up to date NGINX Plus Ingress Controller with NGINX App Protect in my Kubernetes environment. \n Build and keep up to date NGINX App Protect's attack signature and Threat Champaign signature. \n Zero downtime/impact to apps protected by NGINX App Protect with frequent releases, update and patch cycle for NGINX App Protect. \n \n   \n My Problem Statement \n I need to ensure that my infrastructure (Kubernetes Ingress controller) and web application firewall (NGINX App Protect) is kept up to date with ease. For example, when there are new NGINX-ingress and NGINX App Protect updates (e.g., new version, attack signature and threat campaign signature), I would like to seamlessly push changes out to NGINX-ingress and NGINX App Protect (as it protects my backend apps) without impacting applications protected by NGINX App Protect. \n   \n GitOps Workflow \n Start small, start with clear workflow. Below is a depiction of the overall GitOps workflow. \n NGINX App Protect is the target application. Hence, before description of the full GitOps Workflow, let us understand deployment options for NGINX App Protect.   \n NGINX App Protect Deployment model \n There are four deployment models for NGINX App Protect. A common deployment models are: \n \n Edge - external load balancer and proxies (Global enforcement) \n Dynamic module inside Ingress Controller (per service/URI/ingress resource enforcement) \n Per-Service Proxy model - Kubernetes service tier (per service enforcement) \n Per-pod Proxy model - proxy embedded in pod (per endpoint enforcement) \n \n Pipeline demonstrated in this article will work with either NGINX App Protect deployed as Ingress Controller (2) or per-service proxy model (3). For the purposes of this article, NGINX App Protect is deployed at the Ingress controller at the entry point to Kubernetes (Kubernetes Edge Proxy). \n   \n For those who prefer video, \n Video Demonstration \n Part 1 /3 – GitOps with NGINX Plus Ingress and NGINX App Protect - Overview \n Part 2 /3 – GitOps with NGINX Plus Ingress and NGINX App Protect – Demo in Action \n Part 3/3 - GitOps with NGINX Plus Ingress and NGINX App Protect - WAF Security Policy Management. \n   \n Description of GitOps workflow \n \n Operation (myself) updates nginx-ingress + NAP image repo (e.g. .gitlab-ci.yml in nginx-plus-ingress) via VSCODE and perform code merge and commit changes to repo stored in Gitlab. \n Gitlab CI/CD pipeline triggered. Build, test and deploy job started. \n Git clone kubernetes-ingress repo from https://github.com/nginxinc/kubernetes-ingress/. Checkout latest kubernetes-ingress version and build new image with DockerfilewithAppProtectForPlus dockerfile. [ Ensure you have appropriate nginx app protect license in place ] \n As part of the build process, it triggers trivy container security scanning for vulnerabilities (Open Source version of AquaSec). Upon completion of static binary scanning, pipeline upload scanned report back to repo for continuous security improvement. \n Pipeline pushes image to private repository. Private image repo has been configured to perform nightly container security scan (Clair Scanner). Leverage multiple scanning tools - check and balance. \n Pipeline clone nginx-ingress deployment repo (my-kubernetes-apps) and update nginx-ingress deployment manifest with the latest build image tag (refer excerpt of the manifest below). \n Gitlab triggers a webhook to ArgoCD to refresh/sync the desire application state on ArgoCD with deployment state in Kubernetes. By default, ArgoCD will sync with Kubernetes every 3 mins. Webhook will trigger instance sync. \n ArgoCD (deployed on independent K3S cluster) fetches new code from the repo and detects code changes. \n ArgoCD automates the deployment of the desired application states in the specified target environment. It tracks updates to git branches, tags or pinned to a specific version of manifest at a git commit. \n Kubernetes triggers an image pull from private repo, performs a rolling updates, and ensures zero interruption to existing traffic. New pods (nginx-ingress) will spin up and traffic will move to new pods before terminating the old pod. \n Depending on environment and organisation maturity, a successful build, test and deployment onto DEV environment can be pushed to production environment. \n \n Note: \n \n DAST Scanning (ZAP Scanner) is not shown in this demo. Currently, running offline non-automated scanning. \n ArgoCD and Gitlab are integrated with Slack notifications. Events are reported into Slack channel via webhook. \n NGINX App Protect events are send to ELK stack for visibility and analytics. \n \n   \n Snippet on where Gitlab CI update nginx-plus-ingress deployment manifest (Flow#6). \n Each new image build will be tagged with <branch>-hash-<version> \n ... \nspec:\n  imagePullSecrets:\n    - name: regcred\n  serviceAccountName: nginx-ingress\n  containers:\n    - image: reg.foobz.com.au/apps/nginx-plus-ingress:master-f660306d-1.9.1\n      imagePullPolicy: IfNotPresent\n      name: nginx-plus-ingress\n...\n\n \n   \n Gitlab CI/CD Pipeline \n Successful run of CI/CD pipeline to build, test, scan and push container image to private repository and execute code commit onto nginx-plus-ingress repo. \n   \n Note: \n Trivy scanning report will be uploaded or committed back to the same repo. To prevent Gitlab CI triggering another build process (\"pipeline loop\"), the code commit is tagged with [skip ci]. \n   \n ArgoCD continuous deployment \n ArgoCD constantly (default every 3 mins) syncs desired application state with my Kubernetes cluster. Its ensures configuration manifest stored in Git repository is always synchronised with the target environment. \n   \n Mytrain-dev apps are protected by nginx-ingress + NGINX App Protect. Specific (per service/URI enforcement). NGINX App Protect policy is applied onto this service. \n   \n nginx-ingress + NGINX App Protect is deployed as an Ingress Controller in Kubernetes. pod-template-hash=xxxx is labeled and tracked by ArgoCD. \n $ kubectl -n nginx-ingress get pod --show-labels\nNAME                             READY   STATUS    RESTARTS   AGE   LABELS\nnginx-ingress-776b64dc89-pdtv7   1/1     Running   0          8h    app=nginx-ingress,pod-template-hash=776b64dc89\nnginx-ingress-776b64dc89-rwk8w   1/1     Running   0          8h    app=nginx-ingress,pod-template-hash=776b64dc89\n \n   \n Please refer to the attached video links above for full demo in actions. \n   \n References \n Tools involved \n \n NGINX Plus Ingress Controller - https://www.nginx.com/products/nginx-ingress-controller/ \n NGINX App Protect - https://www.nginx.com/products/nginx-app-protect/ \n Gitlab - https://gitlab.com \n Trivy Scanner - https://github.com/aquasecurity/trivy \n ArgoCD - https://argoproj.github.io/argo-cd/ \n Harbor Private Repository - https://goharbor.io/ \n Clair Scanner - https://github.com/quay/clair \n Slack - https://slack.com \n DAST Scanner - https://www.zaproxy.org/ \n Elasticsearch, Logstash and Kibana (ELK) - https://www.elastic.co/what-is/elk-stack, https://github.com/464d41/f5-waf-elk-dashboards \n K3S - https://k3s.io/ \n \n   \n Source repo used for this demonstration \n Repo for building nginx-ingress + NGINX App Protect image repo \n https://github.com/fbchan/nginx-plus-ingress.git \n   \n Repo use for deployment manifest of nginx-ingress controller with the NGINX App Protect policy. \n https://github.com/fbchan/my-kubernetes-apps.git \n   \n Summary \n GitOps perhaps is a new buzzword. It may or may not make sense in your environment. It definitely makes sense for me. It integrated well with NGINX App Protect and allows me to constantly update and push new code changes into my environment with ease. A few months down the road, when I need to update nginx-ingress and NGINX App Protect, I just need to trigger a CI job, and then everything works like magic. Your mileage may vary. Experience leads me to think along the line of - start small, start simple by \"GitOps-ing\" on one of your apps that may require frequency changes. Learn, revise and continuously improve from there. The outcome that GitOps provides will ease your operational burden with \"do more with less\". Ease of integration of nginx-ingress and NGINX App Protect into your declarative infrastructure and application delivery with GitOps and F5's industry leading Web Application firewall protection will definitely alleviate your organisation's risk exposure to external and internal applications threat. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"11771","kudosSumWeight":1,"repliesCount":3,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMjE5MWlDM0QzQjcyMjc2MjQzMTQ2?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMTI3MzdpNEVCOEYzMDE5OTg3QTQwRA?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtMTQ2MzRpM0IzOUY3NjY3QkZGQTRDRQ?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtNjIwNWk5OTk3Mjk2NjM4NTU1QzU4?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODIxNjYtNTU5OGlFQzlFMzQ5QTg2NTMzRTkw?revision=2\"}"}}],"totalCount":5,"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:335053":{"__typename":"Conversation","id":"conversation:335053","topic":{"__typename":"TkbTopicMessage","uid":335053},"lastPostingActivityTime":"2024-10-15T09:54:50.267-07:00","solved":false},"TkbTopicMessage:message:335053":{"__typename":"TkbTopicMessage","subject":"Upcoming Action Required: F5 NGINX Plus R33 Release and Licensing Update","conversation":{"__ref":"Conversation:conversation:335053"},"id":"message:335053","revisionNum":6,"uid":335053,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:419288"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":1169},"postTime":"2024-10-15T09:00:00.037-07:00","lastPublishTime":"2024-10-15T09:54:50.267-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hello community!   \n The upcoming release of NGINX Plus R33 is scheduled for this quarter. This release brings changes to our licensing process, aligning it with industry best practices and the rest of the F5 licensing programs. These updates are designed to better serve our commercial customers by providing improved visibility into usage, streamlined license tracking, and enhanced customer service.  \n Key Changes in NGINX Plus R33  \n \n Release: Q4, 2024  \n New Requirement: All commercial NGINX Plus instances will now require the placement of a JSON Web Token (JWT). This JWT file can be downloaded from your MyF5 account.  \n License Validation: NGINX Plus instances will regularly validate their license status with the F5 licensing endpoint for connected customers. Offline environments can manage this through the NGINX Instance Manager.  \n Usage Reporting: NGINX Plus R33 introduces a new requirement for commercial product usage reporting.   \n \n NGINX's adoption of F5's standardized approach ensures easier and more precise license and usage tracking. Once our customers are utilizing R33 together with NGINX’s management options, tasks such as usage reporting and renewals will be much more streamlined and straightforward. Additionally, NGINX instance visibility and management will be much easier.  \n Action Required  \n To ensure a smooth transition and uninterrupted service, please take the following steps:  \n \n Install the JWT: Make sure to install the JWT on all your commercial NGINX Plus instances. This is crucial to avoid any interruptions. \n Additional Steps: Refer to our detailed guide for any other necessary steps. See here for additional required next steps.   \n \n IMPORTANT: Failure to follow these steps will result in NGINX Plus R33 and subsequent release instances not functioning.  \n Critical Notes  \n \n JWT Requirement: JWT files are essential for the startup of NGINX Plus R33. \n NGINX Ingress Controller: Users of NGINX Ingress Controller should not upgrade to NGINX Plus R33 until the next version of the Ingress Controller is released. \n No Changes for Earlier Versions: If you are using a version of NGINX Plus prior to R33, no action is required.  \n \n Resources  \n We are preparing a range of resources to help you through this transition:  \n \n Support Documentation: Comprehensive support documentation will be available upon the release of NGINX Plus R33. \n Demonstration Videos: We will also provide demonstration videos to guide you through the new processes upon the release of NGINX Plus R33. \n NGINX Documentation: For more detailed information, visit our NGINX documentation.  \n \n Need Assistance?  \n If you have any questions or concerns, please do not hesitate to reach out:  \n \n F5 Representative: Contact your dedicated representative for personalized support. \n MyF5 Account: Support is readily available through your MyF5 account.  \n \n Stay tuned for more updates. \n Thank you for your continued partnership.  ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"3094","kudosSumWeight":2,"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:333813":{"__typename":"Conversation","id":"conversation:333813","topic":{"__typename":"TkbTopicMessage","uid":333813},"lastPostingActivityTime":"2024-09-12T05:00:00.057-07:00","solved":false},"User:user:275883":{"__typename":"User","uid":275883,"login":"Tony_Marfil","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0yNzU4ODMtQ2o3aUZ6?image-coordinates=0%2C0%2C3022%2C3022"},"id":"user:275883"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtc1JNb0RL?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtc1JNb0RL?revision=2","title":"1_aws_prep.png","associationType":"BODY","width":439,"height":622,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtSFBBaG4x?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtSFBBaG4x?revision=2","title":"3_docker_build.png","associationType":"BODY","width":1791,"height":1501,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtcEZQeHU5?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtcEZQeHU5?revision=2","title":"2_ecs_service.png","associationType":"BODY","width":2372,"height":1341,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtd3Bia3Rt?revision=2\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtd3Bia3Rt?revision=2","title":"4_qs_html.png","associationType":"BODY","width":1920,"height":1200,"altText":""},"TkbTopicMessage:message:333813":{"__typename":"TkbTopicMessage","subject":"Deploying F5 NGINX Plus Graviton-powered Containers as AWS ECS Fargate Tasks","conversation":{"__ref":"Conversation:conversation:333813"},"id":"message:333813","revisionNum":2,"uid":333813,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:275883"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" This tutorial guides users through deploying F5 NGINX Plus on AWS ECS Fargate using Graviton-powered containers, covering environment setup, custom image creation, and service deployment. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":185},"postTime":"2024-09-12T05:00:00.057-07:00","lastPublishTime":"2024-09-12T05:00:00.057-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Amazon's new cloud computing chip, Graviton4, is now generally available (July 2024). The price-performance ratio is impressive. Understandably, cloud architects are looking for solutions that: \n \n Are compatible with ARM64 and run well on Graviton \n Can run in containers and integrate into the AWS ecosystem \n \n NGINX Plus fits the bill! \n Introduction \n NGINX Plus, the commercial version of the popular open-source NGINX reverse proxy / Kubernetes Ingress Controller / load-balancer / application server, offers advanced features crucial for modern cloud architectures. NGINX Plus can effectively replace Amazon's native load-balancers and serve as a more feature-rich alternative to Elastic Kubernetes Service Ingress. Its versatility supports all cloud-native design patterns and seamlessly integrates with the AWS ecosystem. \n This tutorial leverages several AWS technologies: \n \n Graviton ARM64 instances: These offer a significant price-performance advantage over x86 instance types in AWS. \n ECS (Elastic Container Service): A fully managed container orchestration service. \n ECS Fargate: A serverless compute engine for containers, eliminating the need to provision and manage servers. \n ECR (Elastic Container Registry): A fully managed container registry for storing, managing, and deploying container images. \n AWS Secrets Manager: Securely stores and manages sensitive information like TLS certificates and private keys. \n \n What is the difference between ECS and ECS Fargate? \n The key difference between AWS ECS and AWS ECS Fargate lies in the level of infrastructure management: \n \n \n AWS ECS: \n \n You manage the underlying EC2 instances that host your containers \n You're responsible for patching, scaling, and maintaining these instances \n \n \n \n AWS ECS Fargate: \n \n Serverless compute engine for containers \n AWS manages the underlying infrastructure \n You only need to specify CPU and memory requirements for your containers \n \n \n \n In essence, Fargate abstracts away the server management aspect, allowing you to focus solely on your containerized applications, while standard ECS gives you more control but requires more hands-on management of the underlying infrastructure. \n While this tutorial doesn't cover it, NGINX Plus can send logs to CloudWatch. \n By the end of this guide, you'll have a solid understanding of how to configure, deploy, and quickly scale NGINX Plus on AWS ECS Graviton. \n Part 1: Prepare AWS Environment \n AWS Command Line version tested: \n aws --version \n aws-cli/2.17.0 Python/3.11.8 Linux/5.15.146.1-microsoft-standard-WSL2 exe/x86_64.ubuntu.20 \n 1. Set Up VPC Infrastructure \n If you already have a VPC with two public subnets, you can skip this part. \n 1.1 Create a VPC \n VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --query 'Vpc.VpcId' --output text)\necho \"VPC ID: $VPC_ID\" \n 1.2 Create an Internet Gateway \n IGW_ID=$(aws ec2 create-internet-gateway --query 'InternetGateway.InternetGatewayId' --output text)\necho \"Internet Gateway ID: $IGW_ID\"\n\naws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID \n 1.3 Create Subnets \n # Get available Availability Zones\nAZS=($(aws ec2 describe-availability-zones --query 'AvailabilityZones[].ZoneName' --output text))\n\n# Create subnet in the first AZ\nSUBNET1_ID=$(aws ec2 create-subnet \\\n --vpc-id $VPC_ID \\\n --cidr-block 10.0.1.0/24 \\\n --availability-zone ${AZS[0]} \\\n --query 'Subnet.SubnetId' \\\n --output text)\n\n# Create subnet in the second AZ\nSUBNET2_ID=$(aws ec2 create-subnet \\\n --vpc-id $VPC_ID \\\n --cidr-block 10.0.2.0/24 \\\n --availability-zone ${AZS[1]} \\\n --query 'Subnet.SubnetId' \\\n --output text)\n\necho \"Subnet 1 ID: $SUBNET1_ID (AZ: ${AZS[0]})\"\necho \"Subnet 2 ID: $SUBNET2_ID (AZ: ${AZS[1]})\" \n 1.4 Set Up Routing \n ROUTE_TABLE_ID=$(aws ec2 create-route-table --vpc-id $VPC_ID --query 'RouteTable.RouteTableId' --output text)\necho \"Route Table ID: $ROUTE_TABLE_ID\"\n\naws ec2 create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID\n\naws ec2 associate-route-table --subnet-id $SUBNET1_ID --route-table-id $ROUTE_TABLE_ID\naws ec2 associate-route-table --subnet-id $SUBNET2_ID --route-table-id $ROUTE_TABLE_ID \n 1.5 Configure Subnets for Public IP Assignment \n aws ec2 modify-subnet-attribute --subnet-id $SUBNET1_ID --map-public-ip-on-launch\naws ec2 modify-subnet-attribute --subnet-id $SUBNET2_ID --map-public-ip-on-launch \n 1.6. Create Security Group \n SG_ID=$(aws ec2 create-security-group --vpc-id $VPC_ID --group-name docker-client-sg --description \"Security group for Graviton Docker instance\" --query 'GroupId' --output text)\necho \"Security Group ID: $SG_ID\"\n\n# Allow SSH access from your IP\naws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 22 --cidr $YOUR_IP_ADDRESS/32\n\n# Allow HTTP and HTTPS access from anywhere\naws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 80 --cidr 0.0.0.0/0\naws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol tcp --port 443 --cidr 0.0.0.0/0\n\n# Allow ICMP from anywhere (for ping)\naws ec2 authorize-security-group-ingress --group-id $SG_ID --protocol icmp --port -1 --cidr 0.0.0.0/0 \n 1.7 Create an Elastic Container Registry (ECR) \n aws ecr create-repository --repository-name my-nginx-repo --region $AWS_REGION \n   \n 2. Launch an EC2 Graviton Instance \n 2.1 Find the latest Amazon Linux 2023 ARM64 AMI \n AMI_ID=$(aws ssm get-parameter --name \"/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64\" --query \"Parameter.Value\" --output text)\necho \"AMI ID: $AMI_ID\" \n 2.2 Launch an Amazon Linux 2023 Graviton instance \n INSTANCE_ID=$(aws ec2 run-instances \\\n --image-id $AMI_ID \\\n --instance-type t4g.micro \\\n --key-name $YOUR_KEY_NAME \\\n --security-group-ids $SG_ID \\\n --subnet-id $SUBNET1_ID \\\n --user-data '#!/bin/bash\ndnf update -y\ndnf install -y git jq docker\nsystemctl enable docker\nsystemctl start docker\nusermod -a -G docker ec2-user' \\\n --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=Graviton-Docker-Instance},{Key=Owner,Value=your.email@example.com}]' \\\n --query 'Instances[0].InstanceId' \\\n --output text)\necho \"Instance ID: $INSTANCE_ID\" \n Watch for progress in the AWS console. EC2 => Instances => \"Name = Graviton-Docker-Instance\". Once Status check passes (green font) you can proceed. \n 2.3 Get the public IP address of the instance \n PUBLIC_IP=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)\necho \"Public IP: $PUBLIC_IP\" \n 2.4. Connect to the Amazon Linux 2023 instance and test Docker installation \n SSH into your Amazon Linux 2023 instance: \n ssh -i /path/to/your/key.pem ec2-user@$PUBLIC_IP # Check Docker version\ndocker --version\n\n# Run a test NGINX container\ndocker run --name mynginx -d -p 80:80 nginx\n\n# Inspect the container\ndocker inspect mynginx\n\n# Test the NGINX server\ncurl localhost\n\n# Clean up\ndocker stop $(docker ps -aq) && docker rm $(docker ps -aq) \n Part 2: Building the Custom NGINX Plus ARM64 Container \n 1. IAM Roles and Permissions \n 1.1 Create a trust policy and IAM role \n The Graviton Docker build instance will need an IAM role to access the Elastic Container Registry (ECR). \n Run these commands from your local machine or an AWS CLI enabled environment: \n # Create trust policy file\ncat > trust-policy.json << EOL\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Service\": \"ec2.amazonaws.com\"\n },\n \"Action\": \"sts:AssumeRole\"\n }\n ]\n}\nEOL\n\n# Create the IAM role\naws iam create-role --role-name MyEC2Role --assume-role-policy-document file://trust-policy.json\n\n# Attach the AmazonEC2ContainerRegistryFullAccess policy to the role\naws iam attach-role-policy --role-name MyEC2Role --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess\n\n# Create the instance profile\naws iam create-instance-profile --instance-profile-name MyEC2_InstanceProfile\n\n# Add the role to the instance profile\naws iam add-role-to-instance-profile --instance-profile-name MyEC2_InstanceProfile --role-name MyEC2Role\n\n# Associate the instance profile with your EC2 instance\naws ec2 associate-iam-instance-profile --instance-id $INSTANCE_ID --iam-instance-profile Name=MyEC2_InstanceProfile \n 2 Base NGINX Plus ARM64 Container Image \n 2.1. Sign up for NGINX Plus trial \n Sign up for an NGINX Plus trial at https://www.f5.com/trials. After signing up, you'll receive a JSON Web Token (JWT) to authenticate to private-registry.nginx.com. \n If you are an existing F5 customer, you can request a trial from the https://my.f5.com portal. \n 2.2. Connect to the Amazon Linux 2023 instance \n SSH into your Amazon Linux 2023 instance: \n ssh -i /path/to/your/key.pem ec2-user@$PUBLIC_IP \n 2.3. Set up Docker for NGINX Plus container registry \n Set up Docker to communicate with the NGINX container registry located at private-registry.nginx.com. \n Open the JSON Web Token file previously downloaded from MyF5 customer portal (for example, nginx-repo-12345abc.jwt) and copy its contents. \n Log in to the docker registry using the contents of the JSON Web Token file: \n docker login private-registry.nginx.com --username=<output_of_jwt_token> --password=none \n Next, pull the image you need from private-registry.nginx.com. \n docker pull private-registry.nginx.com/nginx-plus/base:r32 \n 2.4. Tag and Push the Base NGINX Plus image to ECR \n # Get ECR repository URI\nECR_URI=$(aws ecr describe-repositories --repository-names my-nginx-repo --query 'repositories[0].repositoryUri' --output text)\necho \"ECR Repository URI: $ECR_URI\"\n\n# Tag the base image\ndocker tag private-registry.nginx.com/nginx-plus/base:r32 $ECR_URI:r32\n\n# Authenticate Docker to ECR (if not already done)\naws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_URI\n\n# Push the base image to ECR\ndocker push $ECR_URI:r32 \n 2.5 Verify the pushed image \n aws ecr list-images --repository-name my-nginx-repo \n 3. Custom NGINX Plus ARM64 Container Image \n 3.1 Create and store ECDSA certificate and key as AWS secret \n Before we create the ECS Service, we need to generate an ECDSA certificate and key, and store them in AWS Secrets Manager. This secret will be used by the fetch_and_setup_tls.sh script in our container. \n # Generate the private key:\nopenssl ecparam -name prime256v1 -genkey -noout -out ecdsa_private_key.pem\n\n# Generate a self-signed certificate:\nopenssl req -new -x509 -key ecdsa_private_key.pem -out ecdsa_certificate.pem -days 365 -subj \"/CN=example.com\"\n\n# Create JSON formatted file that contains both the cert and key\njq -n --arg cert \"$(cat ecdsa_certificate.pem)\" --arg key \"$(cat ecdsa_private_key.pem)\" \\\n'{\"certificate\": $cert, \"private_key\": $key}' > secret.json\n\n# Store the secret in AWS Secrets Manager\naws secretsmanager create-secret --name \"MyTlsCertAndKey1\" --secret-string file://secret.json \n 3.2 Dockerfile \n docker images \n Look for the base image: \n <your-account-id>.dkr.ecr.$AWS_REGION.amazonaws.com/my-nginx-repo:r32 \n Create a Dockerfile . Replace the base image in the Dockerfile with yours. \n # Use the existing nginx image as the base\nFROM <your-account-id>.dkr.ecr.$AWS_REGION.amazonaws.com/my-nginx-repo:r32\n\n# Install necessary packages in a single layer\nRUN apt-get update && \\\n apt-get install -y awscli jq less wget vim && \\\n apt-get clean\n\n# Ensure the permissions are correct for the HTML file\nCOPY qs.html /usr/share/nginx/html/index.html\nRUN chmod 644 /usr/share/nginx/html/index.html\n\n# Copy a custom nginx configuration file\nCOPY nginx.conf /etc/nginx/nginx.conf\n\n# Script to fetch TLS cert and key from AWS Secrets Manager\nCOPY fetch_and_setup_tls.sh /usr/local/bin/fetch_and_setup_tls.sh\nRUN chmod +x /usr/local/bin/fetch_and_setup_tls.sh\n\n# Expose HTTP and HTTPS ports\nEXPOSE 80 443\n\n# Start NGINX\nCMD /usr/local/bin/fetch_and_setup_tls.sh && nginx -g 'daemon off;' \n 3.3 fetch_and_setup_tls.sh \n Create a script that will run during the task container execution process and inject a TLS certificate and key from an AWS secret: fetch_and_setup_tls.sh . \n #!/bin/bash\n\n# Set secret ID\nAWS_SECRET_ID='MyTlsCertAndKey1'\n\n# TLS_CERT_AND_KEY environment variable found?\nif [ -n \"$TLS_CERT_AND_KEY\" ]; then\n echo \"$TLS_CERT_AND_KEY\" > /tmp/secret.json\nelse\n echo \"TLS_CERT_AND_KEY not found\" > /tmp/log.txt\nfi\n\n# Extract the certificate and key files from AWS_SECRET_ID\naws secretsmanager get-secret-value --secret-id \"$AWS_SECRET_ID\" \\\n | jq -r '.SecretString | fromjson | .certificate' > /etc/nginx/ecdsa_certificate.pem\n\naws secretsmanager get-secret-value --secret-id \"$AWS_SECRET_ID\" \\\n | jq -r '.SecretString | fromjson | .private_key' > /etc/nginx/ecdsa_private_key.pem\n\n# Set permissions on the certificate and key files\nchmod 600 /etc/nginx/ecdsa_certificate.pem /etc/nginx/ecdsa_private_key.pem \n 3.4 nginx.conf \n Create your nginx.conf . \n worker_processes 1;\n\nevents {\n worker_connections 1024;\n}\n\nhttp {\n include mime.types;\n default_type application/octet-stream;\n\n sendfile on;\n keepalive_timeout 65;\n\n server {\n listen 443 ssl;\n http2 on;\n server_name _;\n\n ssl_certificate /etc/nginx/ecdsa_certificate.pem;\n ssl_certificate_key /etc/nginx/ecdsa_private_key.pem;\n\n root /usr/share/nginx/html;\n index index.html;\n\n location / {\n try_files $uri $uri/ =404;\n }\n\n # Security improvements (optional but recommended)\n ssl_protocols TLSv1.2 TLSv1.3;\n ssl_prefer_server_ciphers on;\n ssl_ciphers \"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256\";\n ssl_session_timeout 1d;\n ssl_session_cache shared:MozSSL:10m;\n ssl_session_tickets off;\n ssl_stapling on;\n ssl_stapling_verify on;\n resolver 8.8.8.8 8.8.4.4 valid=300s;\n resolver_timeout 5s;\n add_header X-Content-Type-Options nosniff;\n add_header X-Frame-Options DENY;\n add_header X-XSS-Protection \"1; mode=block\";\n add_header Strict-Transport-Security \"max-age=31536000; includeSubDomains\" always;\n }\n\n server {\n listen 80;\n server_name _;\n\n location / {\n return 301 https://$host$request_uri;\n }\n }\n} \n 3.5 qs.html \n Create the qs.html demo html page. \n <!DOCTYPE html>\n<html lang=\"en\"><head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>QuantumSynergy AI CloudSec Solutions</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n background-color: #f4f4f4;\n margin: 0;\n padding: 0;\n }\n .header {\n background-color: #282c34;\n color: white;\n padding: 20px;\n text-align: center;\n }\n .container {\n padding: 20px;\n }\n .jumbotron {\n background-color: #61dafb;\n padding: 40px;\n text-align: center;\n border-radius: 5px;\n }\n .features {\n display: flex;\n justify-content: space-around;\n margin-top: 20px;\n }\n .feature {\n background-color: white;\n padding: 20px;\n border-radius: 5px;\n box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);\n width: 30%;\n text-align: center;\n }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>QuantumSynergy AI CloudSec Solutions</h1>\n <p>Revolutionizing Synergistic Paradigms in the Cloud</p>\n </div>\n <div class=\"container\">\n <div class=\"jumbotron\">\n <h2>Welcome to QuantumSynergy!</h2>\n <p>Leveraging Blockchain-Enhanced AI to Disrupt the Synergistic Cloud Security Landscape</p>\n </div>\n <div class=\"features\">\n <div class=\"feature\">\n <h3>AI-Powered Blockchain</h3>\n <p>Our AI integrates with blockchain technology to \nensure decentralized and autonomous synergy. Experience unparalleled \nsecurity with quantum encryption.</p>\n </div>\n <div class=\"feature\">\n <h3>Quantum Cloud Integration</h3>\n <p>By harnessing the power of quantum computing, we \noffer cloud solutions that are faster, smarter, and more secure than \never. Your data will be in a constant state of quantum flux.</p>\n </div>\n <div class=\"feature\">\n <h3>Synergistic Paradigms</h3>\n <p>Our holistic approach to cloud security brings \ntogether AI, blockchain, and quantum computing to create a synergistic \nparadigm that’s greater than the sum of its parts.</p>\n </div>\n </div>\n </div>\n</body></html> \n 3.6 Build the custom Image \n In the directory containing the Dockerfile , fetch_and_setup_tls.sh , nginx.conf , and qs.html files, run: \n docker build -t nginx-plus:r32-custom . \n 3.7 Confirm the image was built \n docker images \n 3.8 Tag and push the custom image to ECR \n # Get ECR repository URI\nECR_URI=$(aws ecr describe-repositories --repository-names my-nginx-repo --query 'repositories[0].repositoryUri' --output text)\necho \"ECR Repository URI: $ECR_URI\"\n\n# Tag the custom image\ndocker tag nginx-plus:r32-custom $ECR_URI:r32-custom\n\n# Authenticate Docker to ECR (if not already done)\naws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $ECR_URI\n\n# Push the custom image to ECR\ndocker push $ECR_URI:r32-custom \n 3.9 Verify the pushed image \n aws ecr list-images --repository-name my-nginx-repo \n   \n   \n Part 3: Deploying NGINX Plus on ECS Fargate \n 1. Create IAM Roles and Polices \n 1.1 Create secret-access-policy.json \n Create a file named secret-access-policy.json with the following content: \n {\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"secretsmanager:GetSecretValue\"\n ],\n \"Resource\": \"arn:aws:secretsmanager:*:*:secret:MyTlsCertAndKey1-*\"\n }\n ]\n} \n 1.2 Create MySecretAccessPolicy \n aws iam create-policy --policy-name MySecretAccessPolicy --policy-document file://secret-access-policy.json\n\n# Get the ARN of MySecretAccessPolicy\nPOLICY_ARN=$(aws iam list-policies --query 'Policies[?PolicyName==`MySecretAccessPolicy`].Arn' --output text)\necho MySecretAccessPolicy ARN: $POLICY_ARN \n 1.3 Create MyECSTaskExecutionRole \n aws iam create-role --role-name MyECSTaskExecutionRole --assume-role-policy-document '{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Service\": \"ecs-tasks.amazonaws.com\"\n },\n \"Action\": \"sts:AssumeRole\"\n }\n ]\n}'\n\n# Attach MySecretAccessPolicy to MyECSTaskExecutionRole\naws iam attach-role-policy \\\n --role-name MyECSTaskExecutionRole \\\n --policy-arn $POLICY_ARN\n\n# Attach AmazonECSTaskExecutionRolePolicy to MyECSTaskExecutionRole\naws iam attach-role-policy \\\n --role-name MyECSTaskExecutionRole \\\n --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy \n 1.4 Create MyECSTaskRole \n aws iam create-role --role-name MyECSTaskRole --assume-role-policy-document '{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"\",\n \"Effect\": \"Allow\",\n \"Principal\": {\n \"Service\": \"ecs-tasks.amazonaws.com\"\n },\n \"Action\": \"sts:AssumeRole\"\n }\n ]\n}'\n\n# Attach MySecretAccessPolicy to MyECSTaskRole\naws iam attach-role-policy --role-name MyECSTaskRole --policy-arn $POLICY_ARN \n \n Note Understanding the difference between MyECSTaskExecutionRole and MyECSTaskRole is crucial for proper security configuration in ECS. \n \n \n \n MyECSTaskExecutionRole: \n \n Used by the ECS agent to launch and manage the container. \n Grants permissions to:\n \n Pull container images from ECR \n Send container logs to CloudWatch \n Retrieve sensitive data from AWS Secrets Manager or Systems Manager Parameter Store \n \n \n In our setup, it has:\n \n AmazonECSTaskExecutionRolePolicy (AWS managed policy) \n Custom policy to access our specific secret in Secrets Manager \n \n \n \n \n \n MyECSTaskRole: \n \n Used by the application running inside the container. \n Grants permissions for the application to interact with other AWS services. \n In our setup, it has:\n \n Custom policy to access our specific secret in Secrets Manager \n \n \n \n \n \n The separation of these roles adheres to the principle of least privilege. The MyECSTaskExecutionRole should have the minimum permissions needed to start and run the container, while the MyECSTaskRole needs only the permissions required by the application itself. This separation enhances security by limiting the potential impact of a compromised container. \n ECSTaskExecutionRole can be locked down further in your environment to restrict access to specific resources such as your ECR Registry and CloudWatch Log Group. \n 2. Create and Launch the ECS Service \n 2.1 Create an ECS Cluster \n aws ecs create-cluster --cluster-name my-ecs-cluster \n 2.2 Create a CloudWatch Log Group \n aws logs create-log-group --log-group-name /ecs/my-fargate-task \n 2.3. Prepare the Task Definition \n Create a file named my-fargate-task.json with the following content: \n {\n \"family\": \"my-fargate-task\",\n \"networkMode\": \"awsvpc\",\n \"containerDefinitions\": [\n {\n \"name\": \"nginx\",\n \"image\": \"<your-account-id>.dkr.ecr.$AWS_REGION.amazonaws.com/my-nginx-repo:r32-custom\",\n \"essential\": true,\n \"portMappings\": [\n {\n \"containerPort\": 80,\n \"hostPort\": 80,\n \"protocol\": \"tcp\"\n },\n {\n \"containerPort\": 443,\n \"hostPort\": 443,\n \"protocol\": \"tcp\"\n }\n ],\n \"secrets\": [\n {\n \"name\": \"TLS_CERT_AND_KEY\",\n \"valueFrom\": \"arn:aws:secretsmanager:$AWS_REGION:<your-account-id>:secret:MyTlsCertAndKey1-xxxxxx\"\n }\n ],\n \"logConfiguration\": {\n \"logDriver\": \"awslogs\",\n \"options\": {\n \"awslogs-group\": \"/ecs/my-fargate-task\",\n \"awslogs-region\": \"$AWS_REGION\",\n \"awslogs-stream-prefix\": \"ecs\"\n }\n },\n \"memory\": 512,\n \"cpu\": 256\n }\n ],\n \"requiresCompatibilities\": [\n \"FARGATE\"\n ],\n \"cpu\": \"256\",\n \"memory\": \"512\",\n \"runtimePlatform\": {\n \"operatingSystemFamily\": \"LINUX\",\n \"cpuArchitecture\": \"ARM64\"\n },\n \"executionRoleArn\": \"arn:aws:iam::<your-account-id>:role/MyECSTaskExecutionRole\",\n \"taskRoleArn\": \"arn:aws:iam::<your-account-id>:role/MyECSTaskRole\"\n} \n Replace <your-account-id> with your AWS account ID. \n 2.4. Register the Task Definition \n Register the task definition with ECS: \n aws ecs register-task-definition --cli-input-json file://my-fargate-task.json \n 2.5. Create an ECS Service \n Now, create an ECS Service to run and maintain your desired number of tasks: \n aws ecs create-service \\\n --cluster my-ecs-cluster \\\n --service-name my-fargate-service \\\n --task-definition my-fargate-task \\\n --desired-count 1 \\\n --launch-type FARGATE \\\n --network-configuration \"awsvpcConfiguration={subnets=[$SUBNET1_ID,$SUBNET2_ID],securityGroups=[$SG_ID],assignPublicIp=ENABLED}\" \\\n --enable-execute-command \n Replace $SUBNET1_ID , $SUBNET2_ID , and $SECURITY_GROUP_ID with your actual subnet and security group IDs. \n After creating the service, you can verify that the container is running in the AWS Management Console: \n \n Log in to the AWS Management Console \n Navigate to the Amazon ECS Service \n In the left sidebar, click on \"Clusters\" \n Click on the \"my-ecs-cluster\" that you created \n In the \"Services\" tab, you should see your \"my-fargate-task\" service \n Click on the service name to view details \n In the \"Tasks\" tab, you should see your running task \n \n \n   \n 2.6. Scaling ECS Services across multiple tasks \n To manually scale your service from one container to two, use the following command: \n aws ecs update-service --cluster my-ecs-cluster --service my-fargate-service --desired-count 2 \n When you create or scale an ECS Service with multiple subnets specified in the network configuration, ECS uses a round-robin strategy to distribute tasks across the available subnets. In our example, the subnets were spread across different Availability Zones. This distribution helps to improve the availability and fault tolerance of your application. \n To view the current distribution of your tasks: \n aws ecs list-tasks --cluster my-ecs-cluster --service-name my-fargate-service \n Then, for each task ID, you can describe the task to see which subnet it's running in: \n aws ecs describe-tasks --cluster my-ecs-cluster --tasks <task-id> \n 2.7. Test the demo application \n After scaling your ECS Service to two containers, let's verify that both are accessible via HTTPS. To access the web pages in a browser, simply enter the HTTPS URL with the public IP \n https://<PUBLIC_IP> \n Note: Your browser will likely show a security warning because we're using a self-signed certificate. In a production environment, you would use a certificate from a trusted Certificate Authority. \n \n   \n This completes our tutorial on building and deploying NGINX Plus ARM64 containers on AWS ECS Fargate. You've successfully set up the AWS environment, built a custom NGINX Plus image, deployed it to ECS Fargate, and verified HTTPS connectivity to multiple container instances. \n Remember to clean up your AWS resources when you're done to avoid unnecessary charges. \n \n Note > NGINX App Protect, the NGINX Web Application Firewall, is not compatible with Graviton (ARM64) as of August 2024. \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"26518","kudosSumWeight":1,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtc1JNb0RL?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtSFBBaG4x?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtcEZQeHU5?revision=2\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzM4MTMtd3Bia3Rt?revision=2\"}"}}],"totalCount":4,"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:330193":{"__typename":"Conversation","id":"conversation:330193","topic":{"__typename":"TkbTopicMessage","uid":330193},"lastPostingActivityTime":"2024-08-28T10:07:18.146-07:00","solved":false},"User:user:73390":{"__typename":"User","uid":73390,"login":"Doug_Gallarda","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS03MzM5MC16eVAxM0E?image-coordinates=48%2C0%2C1204%2C1156"},"id":"user:73390"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxOTMtWFVKdUlP?revision=4\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxOTMtWFVKdUlP?revision=4","title":"Screenshot 2024-05-30 at 9.13.53 PM.png","associationType":"BODY","width":1220,"height":988,"altText":""},"TkbTopicMessage:message:330193":{"__typename":"TkbTopicMessage","subject":"NGINX Virtual Machine Building with cloud-init","conversation":{"__ref":"Conversation:conversation:330193"},"id":"message:330193","revisionNum":4,"uid":330193,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:73390"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" Traditionally, building new servers was a manual process. A system administrator had a run book with all the steps required and would perform each task one by one. If the admin had multiple servers to build the same steps were repeated over and over. \n All public cloud compute platforms provide an automation tool called cloud-init that makes it easy to automate configuration tasks while a new VM instance is being launched. \n In this article, you will learn how to automate the process of building out a new NGINX Plus server using cloud-init. ","introduction":"Quickly create fresh NGINX VMs on any cloud provider","metrics":{"__typename":"MessageMetrics","views":691},"postTime":"2024-06-07T05:00:00.037-07:00","lastPublishTime":"2024-08-28T10:07:18.146-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" The joy and burden of building new servers \n The initial build of a new application server requires multiple steps. First, the operating system must be installed. Then additional software packages need to be added as required by the application. Lastly, both the operating system and software package configurations need to be customized to the needs of the runtime environment. \n Traditionally, building new servers was a manual process. A system administrator had a run book with all the steps required and would perform each task one by one. If the admin had multiple servers to build, the same steps were repeated over and over. \n Looking at Installing NGINX Plus on Debian or Ubuntu as an example, an administrator needs to complete around 14 tasks. If these tasks must be performed manually every time a new VM is launched, much time can be wasted. \n One way to reduce this burden is to build out one server, snapshot it, and then clone that snapshot for every additional server that needs to be deployed. All hypervisor platforms have this capability. The problem with snapshots, however, is that it captures the state of a server at a specific moment in time. If new versions of the operating system or software packages are released, your golden image becomes obsolete. \n Rather than taking a picture of a server after it's been configured, another approach is to automate the execution of the configuration tasks themselves. Every time a new server is launched, the configuration is built from scratch, including the latest versions of the operating system and software packages. Now every new server arrives fresh instead of a clone of a configuration created months ago. \n Introducing cloud-init \n In this article, you will learn how to automate the process of building out a new NGINX Plus server using cloud-init. \n The beauty of cloud-init is that all public cloud providers already include it as a built-in feature. You can even build local VMs on your own hardware or laptop. Just put your configuration tasks into a simple text file and it can be used to build new VMs anywhere cloud-init is available. \n Automating NGINX Plus Installation \n Let's take a look at how cloud-init can automate the process of installing NGINX Plus on a Ubuntu server. Below is the \"simple text file\" (formatted as YAML) that describes what tasks need to be performed. Notice that we are not just replicating each command-line operation into a shell script. This is much better than that. The contents are more declarative in nature, where we describe our desired final state rather than providing the imperative steps to get there. Now let's walk through each section of this file to see how it works. \n #cloud-config\n\nwrite_files:\n - content: |\n -----BEGIN CERTIFICATE-----\n MIIETDCCAzSgAwIBAgIRAN0W2fO6kAXvYOhjggkZ608wDQYJKoZIhvcNAQELBQAw\n Zj7Kh4dgUD+jOI5rJgn5DGm7inpiJf5eksH+scrOVTP+WuJHs8VzhH0UUqAwM3Tx\n <REDACTED>\n iIyDaR6Z9XvtFWiVyjfWv/R9hutbc7QLpbbcC/JIAmrUnskTlFu1Mz00p7Jis8f4\n 7X4xxTENEFzwPfrXIF/bxpg+X75IRb1aYOXpadxuUrckd7Rb46P4FPPxVzEH7TA7\n -----END CERTIFICATE-----\n path: /etc/ssl/nginx/nginx-repo.crt\n - content: |\n -----BEGIN PRIVATE KEY-----\n MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCtKV0irhiXnx4U\n uz1v2neP9ew857iFpZ9FyrsvYqrwaRLdxsBkrU8CgYBRYEknMdfl8OhTcvyYFSMV\n <REDACTED>\n PjQ5U2Kaf3gMia5v4nGkhyKPuvasyvEeupwkIGDvRDmc+/AVtQQbJSJa7O0X1fwE\n aIDBc9S5hiWeqIOK8489IA==\n -----END PRIVATE KEY-----\n path: /etc/ssl/nginx/nginx-repo.key\n\napt:\n conf: |\n Acquire::https::pkgs.nginx.com::Verify-Peer \"true\";\n Acquire::https::pkgs.nginx.com::Verify-Host \"true\";\n Acquire::https::pkgs.nginx.com::SslCert \"/etc/ssl/nginx/nginx-repo.crt\";\n Acquire::https::pkgs.nginx.com::SslKey \"/etc/ssl/nginx/nginx-repo.key\";\n \n sources:\n nginx:\n source: \"deb http://nginx.org/packages/mainline/ubuntu $RELEASE nginx\"\n keyid: 2FD21310B49F6B46\n nginx-plus:\n source: \"deb https://pkgs.nginx.com/plus/ubuntu $RELEASE nginx-plus\"\n keyid: 2FD21310B49F6B46\n app-protect:\n source: \"deb https://pkgs.nginx.com/app-protect/ubuntu $RELEASE nginx-plus\"\n keyid: 2FD21310B49F6B46\n app-protect-dos:\n source: \"deb https://pkgs.nginx.com/app-protect-dos/ubuntu $RELEASE nginx-plus\"\n keyid: 2FD21310B49F6B46\n security-updates:\n source: \"deb https://pkgs.nginx.com/app-protect-security-updates/ubuntu $RELEASE nginx-plus\"\n keyid: A5F6473795E778F4\n keyserver: https://cs.nginx.com/static/keys/app-protect-security-updates.key\n\npackages:\n# - nginx\n - nginx-plus\n# - nginx-plus-module-njs\n# - nginx-ha-keepalived\n# - app-protect\n\nruncmd:\n - systemctl enable --now nginx\n\nfinal_message: \"The system is finally up, after $UPTIME seconds\"\n \n The write_files section (Lines 3-21) \n The NGINX software repository requires mTLS client authentication. Two files are provided to customers to authenticate: nginx-repo.crt and nginx-repo.key. These two files need to be copied to the new server for software installation. The write_files section creates these files with the content included inline in the YAML file.  Notice that each line of content needs to be indented to produce valid YAML.  I use awk to indent each line like so: \n awk '{$1=\"        \"$1}1' nginx-repo.crt \n Being able to create these files using cloud-init is nice because everything is in one YAML file. Of course, you will need to replace the content subsections with the content of your own nginx-repo.crt and nginx-repo.key files. \n The apt section (Lines 23-46) \n With Ubuntu Linux, the apt command is used to install software. To install NGINX Plus we configure apt with two things: \n \n The conf subsection -- Tells apt where the mTLS digital certificate files are that we created in the previous section. \n The sources subsection -- Adds the NGINX software repositories to apt. Each repository has a keyid that refers to a verification key in Ubuntu's keyserver. Notice that the \"security-updates\" keyid is not in Ubuntu's keyserver so a custom keyserver is provided. \n \n The packages section (Lines 48-53) \n Here is where we specify which software packages should be installed. In this case I only need NGINX Plus so I've commented out the others. In this section you can install any package available to Ubuntu that you need. \n The runcmd section (Lines 55-56) \n After install, we just need to run one command to start up NGINX and make sure it automatically starts when the server boots in the future. \n The final_message section (Line 58) \n The final_message is a string that is written to the /var/log/cloud-init-output.log file after the automated install. In this case, I use the $UPTIME variable to record how long it took for the installation process to complete. \n Using a cloud-init file when creating a new VM \n Now that we have a cloud-init file ready to go, let's go ahead and use it to configure a brand new VM. Here are some examples of providing your YAML file when launching a new VM instance: \n On AWS EC2 using the Web UI \n When using the Web UI to launch a new instance, click on Advanced Details at the bottom of the page. Scroll down until you see a section labeled, \"User data - optional.\"  You can either paste your YAML into the box provided or click the \"Choose file\" to upload the file from your computer. \n \n On Google Cloud Platform (GCP) using the gcloud CLI \n In addition to a Web UI, cloud platforms also provide a command line interface for launching new VM instances. Here is an example using GCP's CLI: \n ​gcloud compute instances create mynginx --zone=us-central1-a --image-project=ubuntu-os-cloud --image-family=ubuntu-2204-lts --metadata-from-file user-data=plus.yaml \n Here the metadata-from-file parameter is used to pass our YAML file named \"plus.yaml\" \n On your laptop using multipass \n Canonical, the makers of Ubuntu, provide a tool named Canonical Multipass for running VMs on your Windows, Mac, or Linux laptop or desktop system. When launching a new instance with multipass, you can pass our YAML file like so: \n multipass launch -n mynginx --cloud-init plus.yaml \n Viewing the cloud-init-output log file \n While the cloud-init automated installation is in progress, output for each task is written to /var/log/cloud-init-output.log \n You can view this file after the new instance is booted to verify that each step has completed successfully. Here is a snippet of the end of this log file: \n Cloud-init v. 24.1.3-0ubuntu3 running 'modules:final' at Fri, 31 May 2024 02:24:41 +0000. Up 35.57 seconds.\nReading package lists...\nBuilding dependency tree...\nReading state information...\nThe following NEW packages will be installed:\n nginx-plus\n0 upgraded, 1 newly installed, 0 to remove and 51 not upgraded.\nNeed to get 3700 kB of archives.\nAfter this operation, 7378 kB of additional disk space will be used.\nGet:1 https://pkgs.nginx.com/plus/ubuntu noble/nginx-plus amd64 nginx-plus amd64 32-1~noble [3700 kB]\nFetched 3700 kB in 1s (2513 kB/s)\nSelecting previously unselected package nginx-plus.\n(Reading database ... 71839 files and directories currently installed.)\nPreparing to unpack .../nginx-plus_32-1~noble_amd64.deb ...\n----------------------------------------------------------------------\n\nThank you for using NGINX!\n\nPlease find the documentation for NGINX Plus here:\n/usr/share/nginx/html/nginx-modules-reference.pdf\n\nNGINX Plus is proprietary software. EULA and License information:\n/usr/share/doc/nginx-plus/\n\nFor support information, please see:\nhttps://www.nginx.com/support/\n\n----------------------------------------------------------------------\nUnpacking nginx-plus (32-1~noble) ...\nSetting up nginx-plus (32-1~noble) ...\nCreated symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.\nProcessing triggers for man-db (2.12.0-4build2) ...\n\nRunning kernel seems to be up-to-date.\n\nNo services need to be restarted.\n\nNo containers need to be restarted.\n\nNo user sessions are running outdated binaries.\n\nNo VM guests are running outdated hypervisor (qemu) binaries on this host.\nSynchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.\nExecuting: /usr/lib/systemd/systemd-sysv-install enable nginx\nThe system is finally up, after 44.67 seconds \n By the final_message the automated install competed in 44.67 seconds. Much faster than if the administrator had to perform the same tasks manually! \n Conclusion \n There are other automation tools out there, like Ansible from Red Hat and Terraform from Hashicorp. These platforms come with a learning curve and require setup and configuration before they can be used. \n Using cloud-init to automate the build-out of new NGINX Plus servers offers the following advantages: \n \n Included with all public cloud compute offerings. Launching new VMs with cloud-init support comes by default. \n A declarative interface simplifies describing the configuration tasks that need to be automated. \n All instructions go into a single YAML text file that is easy to share across all your compute platforms. \n Instead of using a stale VM golden image, cloud-init does a fresh install and config every time you spin up a new VM. \n \n Hopefully this introduction to using cloud-init to build new NGINX Plus VM instances has been useful. Please feel free to leave any questions or feedback you may have in the comments below. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"11609","kudosSumWeight":3,"repliesCount":4,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuMnwyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMzAxOTMtWFVKdUlP?revision=4\"}"}}],"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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/community/Navbar-1743097588266","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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarHamburgerDropdown-1743097588266","value":{"hamburgerLabel":"Side Menu"},"localOverride":false},"CachedAsset:text:en_US-components/community/BrandLogo-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/community/BrandLogo-1743097588266","value":{"logoAlt":"Khoros","themeLogoAlt":"Brand Logo"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarTextLinks-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarTextLinks-1743097588266","value":{"more":"More"},"localOverride":false},"CachedAsset:text:en_US-components/authentication/AuthenticationLink-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/authentication/AuthenticationLink-1743097588266","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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/nodes/NodeLink-1743097588266","value":{"place":"Place {name}"},"localOverride":false},"CachedAsset:text:en_US-components/tags/TagSubscriptionAction-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/tags/TagSubscriptionAction-1743097588266","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-components/messages/MessageListTabs-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageListTabs-1743097588266","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-shared/client/components/common/QueryHandler-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/QueryHandler-1743097588266","value":{"title":"Query Handler"},"localOverride":false},"CachedAsset:text:en_US-components/community/NavbarDropdownToggle-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/community/NavbarDropdownToggle-1743097588266","value":{"ariaLabelClosed":"Press the down arrow to open the menu"},"localOverride":false},"CachedAsset:text:en_US-shared/client/components/common/OverflowNav-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/OverflowNav-1743097588266","value":{"toggleText":"More"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageView/MessageViewInline-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageView/MessageViewInline-1743097588266","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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/common/Pager/PagerLoadMore-1743097588266","value":{"loadMore":"Show More"},"localOverride":false},"CachedAsset:text:en_US-components/customComponent/CustomComponent-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/customComponent/CustomComponent-1743097588266","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-components/users/UserLink-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/users/UserLink-1743097588266","value":{"authorName":"View Profile: {author}","anonymous":"Anonymous"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageSubject-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageSubject-1743097588266","value":{"noSubject":"(no subject)"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageTime-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageTime-1743097588266","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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/nodes/NodeIcon-1743097588266","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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageUnreadCount-1743097588266","value":{"unread":"{count} unread","comments":"{count, plural, one { unread comment} other{ unread comments}}"},"localOverride":false},"CachedAsset:text:en_US-components/messages/MessageViewCount-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageViewCount-1743097588266","value":{"textTitle":"{count, plural,one {View} other{Views}}","views":"{count, plural, one{View} other{Views}}"},"localOverride":false},"CachedAsset:text:en_US-components/kudos/KudosCount-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/kudos/KudosCount-1743097588266","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-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageRepliesCount-1743097588266","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-components/messages/MessageBody-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-components/messages/MessageBody-1743097588266","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-shared/client/components/users/UserAvatar-1743097588266":{"__typename":"CachedAsset","id":"text:en_US-shared/client/components/users/UserAvatar-1743097588266","value":{"altText":"{login}'s avatar","altTextGeneric":"User's avatar"},"localOverride":false}}}},"page":"/tags/TagPage/TagPage","query":{"nodeId":"board:TechnicalArticles","tagName":"NGINX Plus"},"buildId":"q_bLpq2mflH0BeZigxpj6","runtimeConfig":{"buildInformationVisible":false,"logLevelApp":"info","logLevelMetrics":"info","openTelemetryClientEnabled":false,"openTelemetryConfigName":"f5","openTelemetryServiceVersion":"25.2.0","openTelemetryUniverse":"prod","openTelemetryCollector":"http://localhost:4318","openTelemetryRouteChangeAllowedTime":"5000","apolloDevToolsEnabled":false,"inboxMuteWipFeatureEnabled":false},"isFallback":false,"isExperimentalCompile":false,"dynamicIds":["./components/customComponent/CustomComponent/CustomComponent.tsx","./components/community/Navbar/NavbarWidget.tsx","./components/community/Breadcrumb/BreadcrumbWidget.tsx","./components/tags/TagsHeaderWidget/TagsHeaderWidget.tsx","./components/messages/MessageListForNodeByRecentActivityWidget/MessageListForNodeByRecentActivityWidget.tsx","./components/tags/TagSubscriptionAction/TagSubscriptionAction.tsx","./components/customComponent/CustomComponentContent/TemplateContent.tsx","../shared/client/components/common/List/ListGroup/ListGroup.tsx","./components/messages/MessageView/MessageView.tsx","./components/messages/MessageView/MessageViewInline/MessageViewInline.tsx","../shared/client/components/common/Pager/PagerLoadMore/PagerLoadMore.tsx","./components/customComponent/CustomComponentContent/HtmlContent.tsx","./components/customComponent/CustomComponentContent/CustomComponentScripts.tsx"],"appGip":true,"scriptLoader":[]}