[{"data":1,"prerenderedAt":1969},["ShallowReactive",2],{"/blog/set-up-flux-for-gitops-on-openshift":3,"navigation-en-us":1183,"banner-en-us":1610,"footer-en-us":1620,"blog-post-authors-en-us-Bart Zhang":1864,"blog-related-posts-en-us-set-up-flux-for-gitops-on-openshift":1879,"blog-promotions-en-us":1905,"next-steps-en-us":1959},{"id":4,"title":5,"authors":6,"body":8,"category":1163,"date":1164,"description":1165,"extension":1166,"externalUrl":1167,"faq":1167,"featured":1168,"heroImage":1169,"meta":1170,"navigation":623,"path":1171,"seo":1172,"slug":1176,"stem":1177,"tags":1178,"template":1181,"updatedDate":1167,"__hash__":1182},"blogPosts/en-us/blog/set-up-flux-for-gitops-on-openshift.md","Set up Flux for GitOps to deploy workloads on OpenShift",[7],"Bart Zhang",{"type":9,"value":10,"toc":1155},"minimark",[11,22,37,42,61,65,68,71,82,85,91,100,108,111,182,185,367,370,413,416,425,448,451,454,457,507,510,566,568,574,577,580,583,591,605,798,814,817,867,869,895,898,953,955,961,964,970,972,1087,1090,1093,1096,1099,1108,1113,1137,1146,1151],[12,13,14,15,21],"p",{},"In February, we announced that ",[16,17,20],"a",{"href":18,"rel":19},"https://about.gitlab.com/blog/why-did-we-choose-to-integrate-fluxcd-with-gitlab/",[],"Flux CD would be our recommended approach to do GitOps with GitLab",". This tutorial explains how to set up GitLab and Flux to deploy workloads on Red Hat OpenShift. You’ll set up a sample project, complete a bootstrap Flux installation, and authenticate your installation with a project deploy token. By the end of this tutorial, you should be able to deploy an example NGINX workload to OpenShift from a GitLab Repo via Flux.",[12,23,24,25,30,31,36],{},"You can find the fully configured tutorial project in ",[16,26,29],{"href":27,"rel":28},"https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux",[],"this GitLab repository",". It works in conjunction with ",[16,32,35],{"href":33,"rel":34},"https://gitlab.com/gitlab-partner-demos/red-hat-demos/web-app-manifests",[],"this repository",", which contains the example OpenShift manifest.",[38,39,41],"h3",{"id":40},"to-set-up-flux-for-gitops","To set up Flux for GitOps:",[43,44,45,49,52,55,58],"ol",{},[46,47,48],"li",{},"Create a personal access token",[46,50,51],{},"Create the Flux repository",[46,53,54],{},"Create the OpenShift manifest repository",[46,56,57],{},"Configure Flux to sync your manifests",[46,59,60],{},"Verify your configuration",[38,62,64],{"id":63},"prerequisites","Prerequisites:",[12,66,67],{},"You must have an OpenShift cluster running. Cluster-admin privileges are required to install Flux on OpenShift, which can either be installed via OperatorHub or the CLI.",[12,69,70],{},"When installing Flux with CLI, you need to set the nonroot SCC for all controllers in the flux-system namespace like this:",[72,73,79],"pre",{"className":74,"code":76,"language":77,"meta":78},[75],"language-text","NS=\"flux-system\"\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:kustomize-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:helm-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:source-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:notification-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:image-automation-controller\noc adm policy add-scc-to-user nonroot system:serviceaccount:${NS}:image-reflector-controller\n","text","",[80,81,76],"code",{"__ignoreMap":78},[12,83,84],{},"Expected output:",[72,86,89],{"className":87,"code":88,"language":77,"meta":78},[75],"clusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"kustomize-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"helm-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"source-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"notification-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"image-automation-controller\"\nclusterrole.rbac.authorization.k8s.io/system:openshift:scc:nonroot added: \"image-reflector-controller\"\n",[80,90,88],{"__ignoreMap":78},[12,92,93,94,99],{},"Also, you'll need to ",[16,95,98],{"href":96,"rel":97},"https://access.redhat.com/documentation/en-us/openshift_container_platform/4.8/html/security_and_compliance/seccomp-profiles",[],"patch your Kustomization"," to remove the SecComp Profile and enforce runUserAs to the same UID provided by the images to prevent OpenShift to alter the user expected by our controllers, prior to bootstrapping the cluster.",[12,101,102,103,107],{},"You’ll need to create a Git repository and clone it locally. I chose to create ",[16,104,106],{"href":33,"rel":105},[],"the web-app-manifests repository"," to store my manifest file once it is created through the following steps.",[12,109,110],{},"Create the file structure required by bootstrap using the following command:",[72,112,116],{"className":113,"code":114,"language":115,"meta":78,"style":78},"language-shell shiki shiki-themes github-light","git clone https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux/\ncd flux\nmkdir -p clusters/my-cluster/flux-system\ntouch clusters/my-cluster/flux-system/gotk-components.yaml \\\n    clusters/my-cluster/flux-system/gotk-sync.yaml \\\n    clusters/my-cluster/flux-system/kustomization.yaml\n\n","shell",[80,117,118,134,144,156,168,176],{"__ignoreMap":78},[119,120,123,127,131],"span",{"class":121,"line":122},"line",1,[119,124,126],{"class":125},"s7eDp","git",[119,128,130],{"class":129},"sYBdl"," clone",[119,132,133],{"class":129}," https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux/\n",[119,135,137,141],{"class":121,"line":136},2,[119,138,140],{"class":139},"sYu0t","cd",[119,142,143],{"class":129}," flux\n",[119,145,147,150,153],{"class":121,"line":146},3,[119,148,149],{"class":125},"mkdir",[119,151,152],{"class":139}," -p",[119,154,155],{"class":129}," clusters/my-cluster/flux-system\n",[119,157,159,162,165],{"class":121,"line":158},4,[119,160,161],{"class":125},"touch",[119,163,164],{"class":129}," clusters/my-cluster/flux-system/gotk-components.yaml",[119,166,167],{"class":139}," \\\n",[119,169,171,174],{"class":121,"line":170},5,[119,172,173],{"class":129},"    clusters/my-cluster/flux-system/gotk-sync.yaml",[119,175,167],{"class":139},[119,177,179],{"class":121,"line":178},6,[119,180,181],{"class":129},"    clusters/my-cluster/flux-system/kustomization.yaml\n",[12,183,184],{},"Add the following YAML snippet and its patches section to flux/clusters/my-cluster/flux-system/kustomization.yaml:",[72,186,190],{"className":187,"code":188,"language":189,"meta":78,"style":78},"language-yaml shiki shiki-themes github-light","apiVersion: kustomize.config.k8s.io/v1beta1\nkind: Kustomization\nresources:\n  - gotk-components.yaml\n  - gotk-sync.yaml\npatches:\n  - patch: |\n      apiVersion: apps/v1\n      kind: Deployment\n      metadata:\n        name: all\n      spec:\n        template:\n          spec:\n            containers:\n              - name: manager\n                securityContext:\n                  runAsUser: 65534\n                  seccompProfile:\n                    $patch: delete      \n    target:\n      kind: Deployment\n      labelSelector: app.kubernetes.io/part-of=flux\n\n","yaml",[80,191,192,205,215,223,231,238,245,259,265,271,277,283,289,295,301,307,313,319,325,331,337,345,356],{"__ignoreMap":78},[119,193,194,198,202],{"class":121,"line":122},[119,195,197],{"class":196},"shJU0","apiVersion",[119,199,201],{"class":200},"sgsFI",": ",[119,203,204],{"class":129},"kustomize.config.k8s.io/v1beta1\n",[119,206,207,210,212],{"class":121,"line":136},[119,208,209],{"class":196},"kind",[119,211,201],{"class":200},[119,213,214],{"class":129},"Kustomization\n",[119,216,217,220],{"class":121,"line":146},[119,218,219],{"class":196},"resources",[119,221,222],{"class":200},":\n",[119,224,225,228],{"class":121,"line":158},[119,226,227],{"class":200},"  - ",[119,229,230],{"class":129},"gotk-components.yaml\n",[119,232,233,235],{"class":121,"line":170},[119,234,227],{"class":200},[119,236,237],{"class":129},"gotk-sync.yaml\n",[119,239,240,243],{"class":121,"line":178},[119,241,242],{"class":196},"patches",[119,244,222],{"class":200},[119,246,248,250,253,255],{"class":121,"line":247},7,[119,249,227],{"class":200},[119,251,252],{"class":196},"patch",[119,254,201],{"class":200},[119,256,258],{"class":257},"sD7c4","|\n",[119,260,262],{"class":121,"line":261},8,[119,263,264],{"class":129},"      apiVersion: apps/v1\n",[119,266,268],{"class":121,"line":267},9,[119,269,270],{"class":129},"      kind: Deployment\n",[119,272,274],{"class":121,"line":273},10,[119,275,276],{"class":129},"      metadata:\n",[119,278,280],{"class":121,"line":279},11,[119,281,282],{"class":129},"        name: all\n",[119,284,286],{"class":121,"line":285},12,[119,287,288],{"class":129},"      spec:\n",[119,290,292],{"class":121,"line":291},13,[119,293,294],{"class":129},"        template:\n",[119,296,298],{"class":121,"line":297},14,[119,299,300],{"class":129},"          spec:\n",[119,302,304],{"class":121,"line":303},15,[119,305,306],{"class":129},"            containers:\n",[119,308,310],{"class":121,"line":309},16,[119,311,312],{"class":129},"              - name: manager\n",[119,314,316],{"class":121,"line":315},17,[119,317,318],{"class":129},"                securityContext:\n",[119,320,322],{"class":121,"line":321},18,[119,323,324],{"class":129},"                  runAsUser: 65534\n",[119,326,328],{"class":121,"line":327},19,[119,329,330],{"class":129},"                  seccompProfile:\n",[119,332,334],{"class":121,"line":333},20,[119,335,336],{"class":129},"                    $patch: delete      \n",[119,338,340,343],{"class":121,"line":339},21,[119,341,342],{"class":196},"    target",[119,344,222],{"class":200},[119,346,348,351,353],{"class":121,"line":347},22,[119,349,350],{"class":196},"      kind",[119,352,201],{"class":200},[119,354,355],{"class":129},"Deployment\n",[119,357,359,362,364],{"class":121,"line":358},23,[119,360,361],{"class":196},"      labelSelector",[119,363,201],{"class":200},[119,365,366],{"class":129},"app.kubernetes.io/part-of=flux\n",[12,368,369],{},"Commit and push the changes to main branch:",[72,371,373],{"className":113,"code":372,"language":115,"meta":78,"style":78},"cd ~/flux\ngit add -A && git commit -m \"init flux for openshift\" && git push\n",[80,374,375,382],{"__ignoreMap":78},[119,376,377,379],{"class":121,"line":122},[119,378,140],{"class":139},[119,380,381],{"class":129}," ~/flux\n",[119,383,384,386,389,392,395,397,400,403,406,408,410],{"class":121,"line":136},[119,385,126],{"class":125},[119,387,388],{"class":129}," add",[119,390,391],{"class":139}," -A",[119,393,394],{"class":200}," && ",[119,396,126],{"class":125},[119,398,399],{"class":129}," commit",[119,401,402],{"class":139}," -m",[119,404,405],{"class":129}," \"init flux for openshift\"",[119,407,394],{"class":200},[119,409,126],{"class":125},[119,411,412],{"class":129}," push\n",[38,414,48],{"id":415},"create-a-personal-access-token",[12,417,418,419,424],{},"To authenticate with the Flux CLI, you must create a GitLab personal access token (",[16,420,423],{"href":421,"rel":422},"https://docs.gitlab.com/user/profile/personal_access_tokens/",[],"PAT",") with the api scope:",[43,426,427,430,433,436,439,442,445],{},[46,428,429],{},"In the upper-right corner, select your avatar.",[46,431,432],{},"Select Edit profile.",[46,434,435],{},"On the left sidebar, select Access Tokens.",[46,437,438],{},"Enter a name and expiry date for the token.",[46,440,441],{},"Select the api scope.",[46,443,444],{},"Select Create personal access token.",[46,446,447],{},"Copy the new token to your clipboard.",[12,449,450],{},"Note: You can also use a project or group access token with the api scope.",[38,452,51],{"id":453},"create-the-flux-repository",[12,455,456],{},"Create a Git repository, install Flux, and authenticate Flux with your repo in RedHat OpenShift:",[43,458,459,466,486,498,504],{},[46,460,461,462,465],{},"Make sure you are logged in as an OpenShift user in your CLI to access your cluster. ",[80,463,464],{},"oc login"," command is useful here.",[46,467,468,473,474,477,478,481,482,485],{},[16,469,472],{"href":470,"rel":471},"https://fluxcd.io/flux/installation/#bootstrap",[],"Install the Flux CLI",". You must install Flux v2 or higher. ",[80,475,476],{},"brew install fluxcd/tap/flux"," on Mac OSX. Check your flux version with ",[80,479,480],{},"flux -v",". Mine is ",[80,483,484],{},"flux version 2.0.0-rc.1",".",[46,487,488,489,492,493],{},"In GitLab, create a new empty project called ",[80,490,491],{},"flux",". I chose to use ",[16,494,497],{"href":495,"rel":496},"https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux/",[],"the respository in this readme",[46,499,500,501,485],{},"From your shell, export a GITLAB_TOKEN environment variable with the value of your personal access token. For example, ",[80,502,503],{},"export GITLAB_TOKEN=\u003Cpersonal-access-token>",[46,505,506],{},"Run the bootstrap command. The exact command depends on whether you are creating the Flux repository under a GitLab user, group, or subgroup. For more information, see the Flux bootstrap documentation.",[12,508,509],{},"In this tutorial, you’re working with a public project in a subgroup. The bootstrap command looks like this:",[72,511,513],{"className":113,"code":512,"language":115,"meta":78,"style":78},"cd ~/flux\nflux bootstrap gitlab \\\n  --owner=gitlab-partner-demos/red-hat-demos \\\n  --repository=flux \\\n  --branch=master \\\n  --path=clusters/my-cluster \\\n  --token-auth\n\n",[80,514,515,521,533,540,547,554,561],{"__ignoreMap":78},[119,516,517,519],{"class":121,"line":122},[119,518,140],{"class":139},[119,520,381],{"class":129},[119,522,523,525,528,531],{"class":121,"line":136},[119,524,491],{"class":125},[119,526,527],{"class":129}," bootstrap",[119,529,530],{"class":129}," gitlab",[119,532,167],{"class":139},[119,534,535,538],{"class":121,"line":146},[119,536,537],{"class":139},"  --owner=gitlab-partner-demos/red-hat-demos",[119,539,167],{"class":139},[119,541,542,545],{"class":121,"line":158},[119,543,544],{"class":139},"  --repository=flux",[119,546,167],{"class":139},[119,548,549,552],{"class":121,"line":170},[119,550,551],{"class":139},"  --branch=master",[119,553,167],{"class":139},[119,555,556,559],{"class":121,"line":178},[119,557,558],{"class":139},"  --path=clusters/my-cluster",[119,560,167],{"class":139},[119,562,563],{"class":121,"line":247},[119,564,565],{"class":139},"  --token-auth\n",[12,567,84],{},[72,569,572],{"className":570,"code":571,"language":77,"meta":78},[75],"► connecting to https://gitlab.com\n► cloning branch \"master\" from Git repository \"https://gitlab.com/gitlab-partner-demos/red-hat-demos/flux.git\"\n✔ cloned repository\n► generating component manifests\n✔ generated component manifests\n✔ component manifests are up to date\n► installing components in \"flux-system\" namespace\n✔ installed components\n✔ reconciled components\n► determining if source secret \"flux-system/flux-system\" exists\n✔ source secret up to date\n► generating sync manifests\n✔ generated sync manifests\n✔ sync manifests are up to date\n► applying sync manifests\n✔ reconciled sync configuration\n◎ waiting for Kustomization \"flux-system/flux-system\" to be reconciled\n",[80,573,571],{"__ignoreMap":78},[12,575,576],{},"This command installs the Flux agent on the OpenShift cluster and configures it to manage itself from the repository flux-config. The command also automatically creates the project deploy token required to access the flux-config repository.",[12,578,579],{},"Great work! You now have a repository bootstrapped with a Flux configuration. Any updates to your repository are automatically synced to the cluster.",[38,581,54],{"id":582},"create-the-openshift-manifest-repository",[12,584,585,586,590],{},"Next, create a repository for your Flux manifest files. These are stateful files that track the current running configuration by\nthe Flux agent. I chose to use ",[16,587,589],{"href":33,"rel":588},[],"web-app-manifests"," project to track my manifest files.",[43,592,593,598],{},[46,594,595,596,485],{},"In GitLab, create a new repository called ",[80,597,589],{},[46,599,600,601,604],{},"Add a file to web-app-manifests named ",[80,602,603],{},"nginx-deployment.yaml"," with the following contents:",[72,606,608],{"className":187,"code":607,"language":189,"meta":78,"style":78},"apiVersion: apps/v1\n\nkind: Deployment\n\nmetadata:\n  name: nginx-deployment\n  labels:\n    app: nginx\nspec:\n  replicas: 3\n  selector:\n    matchLabels:\n      app: nginx\n  template:\n    metadata:\n      labels:\n        app: nginx\n    spec:\n      containers:\n      - name: nginx-unprivileged\n        image: nginxinc/nginx-unprivileged:latest\n        ports:\n        - containerPort: 80\n\n",[80,609,610,619,625,633,637,644,654,661,671,678,688,695,702,711,718,725,732,741,748,755,768,778,785],{"__ignoreMap":78},[119,611,612,614,616],{"class":121,"line":122},[119,613,197],{"class":196},[119,615,201],{"class":200},[119,617,618],{"class":129},"apps/v1\n",[119,620,621],{"class":121,"line":136},[119,622,624],{"emptyLinePlaceholder":623},true,"\n",[119,626,627,629,631],{"class":121,"line":146},[119,628,209],{"class":196},[119,630,201],{"class":200},[119,632,355],{"class":129},[119,634,635],{"class":121,"line":158},[119,636,624],{"emptyLinePlaceholder":623},[119,638,639,642],{"class":121,"line":170},[119,640,641],{"class":196},"metadata",[119,643,222],{"class":200},[119,645,646,649,651],{"class":121,"line":178},[119,647,648],{"class":196},"  name",[119,650,201],{"class":200},[119,652,653],{"class":129},"nginx-deployment\n",[119,655,656,659],{"class":121,"line":247},[119,657,658],{"class":196},"  labels",[119,660,222],{"class":200},[119,662,663,666,668],{"class":121,"line":261},[119,664,665],{"class":196},"    app",[119,667,201],{"class":200},[119,669,670],{"class":129},"nginx\n",[119,672,673,676],{"class":121,"line":267},[119,674,675],{"class":196},"spec",[119,677,222],{"class":200},[119,679,680,683,685],{"class":121,"line":273},[119,681,682],{"class":196},"  replicas",[119,684,201],{"class":200},[119,686,687],{"class":139},"3\n",[119,689,690,693],{"class":121,"line":279},[119,691,692],{"class":196},"  selector",[119,694,222],{"class":200},[119,696,697,700],{"class":121,"line":285},[119,698,699],{"class":196},"    matchLabels",[119,701,222],{"class":200},[119,703,704,707,709],{"class":121,"line":291},[119,705,706],{"class":196},"      app",[119,708,201],{"class":200},[119,710,670],{"class":129},[119,712,713,716],{"class":121,"line":297},[119,714,715],{"class":196},"  template",[119,717,222],{"class":200},[119,719,720,723],{"class":121,"line":303},[119,721,722],{"class":196},"    metadata",[119,724,222],{"class":200},[119,726,727,730],{"class":121,"line":309},[119,728,729],{"class":196},"      labels",[119,731,222],{"class":200},[119,733,734,737,739],{"class":121,"line":315},[119,735,736],{"class":196},"        app",[119,738,201],{"class":200},[119,740,670],{"class":129},[119,742,743,746],{"class":121,"line":321},[119,744,745],{"class":196},"    spec",[119,747,222],{"class":200},[119,749,750,753],{"class":121,"line":327},[119,751,752],{"class":196},"      containers",[119,754,222],{"class":200},[119,756,757,760,763,765],{"class":121,"line":333},[119,758,759],{"class":200},"      - ",[119,761,762],{"class":196},"name",[119,764,201],{"class":200},[119,766,767],{"class":129},"nginx-unprivileged\n",[119,769,770,773,775],{"class":121,"line":339},[119,771,772],{"class":196},"        image",[119,774,201],{"class":200},[119,776,777],{"class":129},"nginxinc/nginx-unprivileged:latest\n",[119,779,780,783],{"class":121,"line":347},[119,781,782],{"class":196},"        ports",[119,784,222],{"class":200},[119,786,787,790,793,795],{"class":121,"line":358},[119,788,789],{"class":200},"        - ",[119,791,792],{"class":196},"containerPort",[119,794,201],{"class":200},[119,796,797],{"class":139},"80\n",[12,799,800,801,803,804,809,810,813],{},"In the new ",[80,802,589],{}," repository, create a ",[16,805,808],{"href":806,"rel":807},"https://docs.gitlab.com/user/project/deploy_tokens/",[],"GitLab deploy token"," with only the ",[80,811,812],{},"read_repository"," scope.",[12,815,816],{},"Store your deploy token username and password somewhere safe. I used environmental variables to save mine:",[72,818,820],{"className":113,"code":819,"language":115,"meta":78,"style":78},"export GITLAB_DEPLOY_TOKEN_USER=\u003Cmy-gitlab-deployment-token-username>\nexport GITLAB_DEPLOY_TOKEN_PASS=\u003Cmy-gitlab-deployment-token-password>\nenv |grep GITLAB_DEPLOY_TOKEN\n",[80,821,822,839,853],{"__ignoreMap":78},[119,823,824,827,830,833,836],{"class":121,"line":122},[119,825,826],{"class":257},"export",[119,828,829],{"class":200}," GITLAB_DEPLOY_TOKEN_USER",[119,831,832],{"class":257},"=\u003C",[119,834,835],{"class":200},"my-gitlab-deployment-token-username",[119,837,838],{"class":257},">\n",[119,840,841,843,846,848,851],{"class":121,"line":136},[119,842,826],{"class":257},[119,844,845],{"class":200}," GITLAB_DEPLOY_TOKEN_PASS",[119,847,832],{"class":257},[119,849,850],{"class":200},"my-gitlab-deployment-token-password",[119,852,838],{"class":257},[119,854,855,858,861,864],{"class":121,"line":146},[119,856,857],{"class":125},"env",[119,859,860],{"class":257}," |",[119,862,863],{"class":125},"grep",[119,865,866],{"class":129}," GITLAB_DEPLOY_TOKEN\n",[12,868,84],{},[72,870,872],{"className":113,"code":871,"language":115,"meta":78,"style":78},"GITLAB_DEPLOY_TOKEN_USER=myGitLabUserName\nGITLAB_DEPLOY_TOKEN_PASS=MySecretToken\n",[80,873,874,885],{"__ignoreMap":78},[119,875,876,879,882],{"class":121,"line":122},[119,877,878],{"class":200},"GITLAB_DEPLOY_TOKEN_USER",[119,880,881],{"class":257},"=",[119,883,884],{"class":129},"myGitLabUserName\n",[119,886,887,890,892],{"class":121,"line":136},[119,888,889],{"class":200},"GITLAB_DEPLOY_TOKEN_PASS",[119,891,881],{"class":257},[119,893,894],{"class":129},"MySecretToken\n",[12,896,897],{},"In Flux CLI, create a secret with your deploy token and point the secret to the new repository. For example:",[72,899,901],{"className":113,"code":900,"language":115,"meta":78,"style":78},"flux create secret git flux-deploy-authentication \\\n         --url=https://gitlab.com/gitlab-partner-demos/red-hat-demos/web-app-manifests \\\n         --namespace=default \\\n         --username=$GITLAB_DEPLOY_TOKEN_USER \\\n         --password=$GITLAB_DEPLOY_TOKEN_PASS\n\n",[80,902,903,921,928,935,945],{"__ignoreMap":78},[119,904,905,907,910,913,916,919],{"class":121,"line":122},[119,906,491],{"class":125},[119,908,909],{"class":129}," create",[119,911,912],{"class":129}," secret",[119,914,915],{"class":129}," git",[119,917,918],{"class":129}," flux-deploy-authentication",[119,920,167],{"class":139},[119,922,923,926],{"class":121,"line":136},[119,924,925],{"class":139},"         --url=https://gitlab.com/gitlab-partner-demos/red-hat-demos/web-app-manifests",[119,927,167],{"class":139},[119,929,930,933],{"class":121,"line":146},[119,931,932],{"class":139},"         --namespace=default",[119,934,167],{"class":139},[119,936,937,940,943],{"class":121,"line":158},[119,938,939],{"class":139},"         --username=",[119,941,942],{"class":200},"$GITLAB_DEPLOY_TOKEN_USER",[119,944,167],{"class":139},[119,946,947,950],{"class":121,"line":170},[119,948,949],{"class":139},"         --password=",[119,951,952],{"class":200},"$GITLAB_DEPLOY_TOKEN_PASS\n",[12,954,84],{},[72,956,959],{"className":957,"code":958,"language":77,"meta":78},[75],"► git secret 'flux-deploy-authentication' created in 'default' namespace\n",[80,960,958],{"__ignoreMap":78},[12,962,963],{},"To check if your secret was generated successfully, run:",[72,965,968],{"className":966,"code":967,"language":77,"meta":78},[75],"oc -n default get secrets flux-deploy-authentication -o yaml\n",[80,969,967],{"__ignoreMap":78},[12,971,84],{},[72,973,975],{"className":187,"code":974,"language":189,"meta":78,"style":78},"apiVersion: v1\ndata:\n  password: Base64EncodedPassword=\n  username: Base64EncodedUsername\nkind: Secret\nmetadata:\n  creationTimestamp: \"2023-04-20T18:22:33Z\"\n  name: flux-deploy-authentication\n  namespace: default\n  resourceVersion: \"8168670\"\n  uid: 16292254-83cd-4df2-8a9c-bc4c718e4b4a\ntype: Opaque\n",[80,976,977,986,993,1003,1013,1022,1028,1038,1047,1057,1067,1077],{"__ignoreMap":78},[119,978,979,981,983],{"class":121,"line":122},[119,980,197],{"class":196},[119,982,201],{"class":200},[119,984,985],{"class":129},"v1\n",[119,987,988,991],{"class":121,"line":136},[119,989,990],{"class":196},"data",[119,992,222],{"class":200},[119,994,995,998,1000],{"class":121,"line":146},[119,996,997],{"class":196},"  password",[119,999,201],{"class":200},[119,1001,1002],{"class":129},"Base64EncodedPassword=\n",[119,1004,1005,1008,1010],{"class":121,"line":158},[119,1006,1007],{"class":196},"  username",[119,1009,201],{"class":200},[119,1011,1012],{"class":129},"Base64EncodedUsername\n",[119,1014,1015,1017,1019],{"class":121,"line":170},[119,1016,209],{"class":196},[119,1018,201],{"class":200},[119,1020,1021],{"class":129},"Secret\n",[119,1023,1024,1026],{"class":121,"line":178},[119,1025,641],{"class":196},[119,1027,222],{"class":200},[119,1029,1030,1033,1035],{"class":121,"line":247},[119,1031,1032],{"class":196},"  creationTimestamp",[119,1034,201],{"class":200},[119,1036,1037],{"class":129},"\"2023-04-20T18:22:33Z\"\n",[119,1039,1040,1042,1044],{"class":121,"line":261},[119,1041,648],{"class":196},[119,1043,201],{"class":200},[119,1045,1046],{"class":129},"flux-deploy-authentication\n",[119,1048,1049,1052,1054],{"class":121,"line":267},[119,1050,1051],{"class":196},"  namespace",[119,1053,201],{"class":200},[119,1055,1056],{"class":129},"default\n",[119,1058,1059,1062,1064],{"class":121,"line":273},[119,1060,1061],{"class":196},"  resourceVersion",[119,1063,201],{"class":200},[119,1065,1066],{"class":129},"\"8168670\"\n",[119,1068,1069,1072,1074],{"class":121,"line":279},[119,1070,1071],{"class":196},"  uid",[119,1073,201],{"class":200},[119,1075,1076],{"class":129},"16292254-83cd-4df2-8a9c-bc4c718e4b4a\n",[119,1078,1079,1082,1084],{"class":121,"line":285},[119,1080,1081],{"class":196},"type",[119,1083,201],{"class":200},[119,1085,1086],{"class":129},"Opaque\n",[12,1088,1089],{},"Under data, you should see base64-encoded values associated with your token username and password.",[12,1091,1092],{},"Congratulations! You now have a manifest repository, a deploy token, and a secret generated directly on your cluster.",[38,1094,57],{"id":1095},"configure-flux-to-sync-your-manifests",[12,1097,1098],{},"Next, tell flux-config to sync with the web-app-manifests repository.",[12,1100,1101,1102,1107],{},"To do so, create a ",[16,1103,1106],{"href":1104,"rel":1105},"https://docs.openshift.com/container-platform/3.11/dev_guide/application_lifecycle/new_app.html",[],"GitRepository resource"," in OpenShift:",[43,1109,1110],{},[46,1111,1112],{},"Clone the flux repo to your machine.",[72,1114,1116],{"className":113,"code":1115,"language":115,"meta":78,"style":78},"# Remember that we already have the flux repo cloned into our home dir.\ncd ~/flux\ngit pull\n",[80,1117,1118,1124,1130],{"__ignoreMap":78},[119,1119,1120],{"class":121,"line":122},[119,1121,1123],{"class":1122},"sAwPA","# Remember that we already have the flux repo cloned into our home dir.\n",[119,1125,1126,1128],{"class":121,"line":136},[119,1127,140],{"class":139},[119,1129,381],{"class":129},[119,1131,1132,1134],{"class":121,"line":146},[119,1133,126],{"class":125},[119,1135,1136],{"class":129}," pull\n",[43,1138,1139],{"start":136},[46,1140,1141,1142,1145],{},"In your local clone of flux, add the GitRepository file ",[80,1143,1144],{},"clusters/my-cluster/web-app-manifests-source.yaml",":",[72,1147,1149],{"className":1148,"code":78,"language":77,"meta":78},[75],[80,1150,78],{"__ignoreMap":78},[1152,1153,1154],"style",{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}",{"title":78,"searchDepth":136,"depth":136,"links":1156},[1157,1158,1159,1160,1161,1162],{"id":40,"depth":146,"text":41},{"id":63,"depth":146,"text":64},{"id":415,"depth":146,"text":48},{"id":453,"depth":146,"text":51},{"id":582,"depth":146,"text":54},{"id":1095,"depth":146,"text":57},"engineering","2023-07-05","Learn how to set up a sample project, complete a bootstrap Flux installation, and authenticate your installation with a project deploy token.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682825/Blog/Hero%20Images/genericworkflow.jpg",{},"/en-us/blog/set-up-flux-for-gitops-on-openshift",{"title":5,"description":1165,"ogTitle":5,"ogDescription":1165,"noIndex":1168,"ogImage":1169,"ogUrl":1173,"ogSiteName":1174,"ogType":1175,"canonicalUrls":1173},"https://about.gitlab.com/blog/set-up-flux-for-gitops-on-openshift","https://about.gitlab.com","article","set-up-flux-for-gitops-on-openshift","en-us/blog/set-up-flux-for-gitops-on-openshift",[1179,1180],"tutorial","GitOps","BlogPost","UbJUXIuPsNw5QmIVpcniwjQotsWYYgdrAhsb-UATCS4",{"logo":1184,"freeTrial":1189,"sales":1194,"login":1199,"items":1204,"search":1530,"minimal":1561,"duo":1580,"switchNav":1589,"pricingDeployment":1600},{"config":1185},{"href":1186,"dataGaName":1187,"dataGaLocation":1188},"/","gitlab logo","header",{"text":1190,"config":1191},"Get free trial",{"href":1192,"dataGaName":1193,"dataGaLocation":1188},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":1195,"config":1196},"Request a demo",{"href":1197,"dataGaName":1198,"dataGaLocation":1188},"/sales/?contact-topic=request-demo","sales",{"text":1200,"config":1201},"Sign in",{"href":1202,"dataGaName":1203,"dataGaLocation":1188},"https://gitlab.com/users/sign_in/","sign in",[1205,1234,1334,1339,1452,1508],{"text":1206,"config":1207,"menu":1209},"Platform",{"dataNavLevelOne":1208},"platform",{"type":1210,"columns":1211},"cards",[1212,1218,1226],{"title":1206,"description":1213,"link":1214},"The intelligent orchestration platform for DevSecOps",{"text":1215,"config":1216},"Explore our Platform",{"href":1217,"dataGaName":1208,"dataGaLocation":1188},"/platform/",{"title":1219,"description":1220,"link":1221},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1222,"config":1223},"Meet GitLab Duo",{"href":1224,"dataGaName":1225,"dataGaLocation":1188},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1227,"description":1228,"link":1229},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1230,"config":1231},"Learn more",{"href":1232,"dataGaName":1233,"dataGaLocation":1188},"/why-gitlab/","why gitlab",{"text":1235,"left":623,"config":1236,"menu":1238},"Product",{"dataNavLevelOne":1237},"solutions",{"type":1239,"link":1240,"columns":1244,"feature":1313},"lists",{"text":1241,"config":1242},"View all Solutions",{"href":1243,"dataGaName":1237,"dataGaLocation":1188},"/solutions/",[1245,1269,1292],{"title":1246,"description":1247,"link":1248,"items":1253},"Automation","CI/CD and automation to accelerate deployment",{"config":1249},{"icon":1250,"href":1251,"dataGaName":1252,"dataGaLocation":1188},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1254,1258,1261,1265],{"text":1255,"config":1256},"CI/CD",{"href":1257,"dataGaLocation":1188,"dataGaName":1255},"/solutions/continuous-integration/",{"text":1219,"config":1259},{"href":1224,"dataGaLocation":1188,"dataGaName":1260},"gitlab duo agent platform - product menu",{"text":1262,"config":1263},"Source Code Management",{"href":1264,"dataGaLocation":1188,"dataGaName":1262},"/solutions/source-code-management/",{"text":1266,"config":1267},"Automated Software Delivery",{"href":1251,"dataGaLocation":1188,"dataGaName":1268},"Automated software delivery",{"title":1270,"description":1271,"link":1272,"items":1277},"Security","Deliver code faster without compromising security",{"config":1273},{"href":1274,"dataGaName":1275,"dataGaLocation":1188,"icon":1276},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1278,1282,1287],{"text":1279,"config":1280},"Application Security Testing",{"href":1274,"dataGaName":1281,"dataGaLocation":1188},"Application security testing",{"text":1283,"config":1284},"Software Supply Chain Security",{"href":1285,"dataGaLocation":1188,"dataGaName":1286},"/solutions/supply-chain/","Software supply chain security",{"text":1288,"config":1289},"Software Compliance",{"href":1290,"dataGaName":1291,"dataGaLocation":1188},"/solutions/software-compliance/","software compliance",{"title":1293,"link":1294,"items":1299},"Measurement",{"config":1295},{"icon":1296,"href":1297,"dataGaName":1298,"dataGaLocation":1188},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1300,1304,1308],{"text":1301,"config":1302},"Visibility & Measurement",{"href":1297,"dataGaLocation":1188,"dataGaName":1303},"Visibility and Measurement",{"text":1305,"config":1306},"Value Stream Management",{"href":1307,"dataGaLocation":1188,"dataGaName":1305},"/solutions/value-stream-management/",{"text":1309,"config":1310},"Analytics & Insights",{"href":1311,"dataGaLocation":1188,"dataGaName":1312},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1314,"type":1239,"items":1315},"GitLab for",[1316,1322,1328],{"text":1317,"config":1318},"Enterprise",{"icon":1319,"href":1320,"dataGaLocation":1188,"dataGaName":1321},"Building","/enterprise/","enterprise",{"text":1323,"config":1324},"Small Business",{"icon":1325,"href":1326,"dataGaLocation":1188,"dataGaName":1327},"Work","/small-business/","small business",{"text":1329,"config":1330},"Public Sector",{"icon":1331,"href":1332,"dataGaLocation":1188,"dataGaName":1333},"Organization","/solutions/public-sector/","public sector",{"text":1335,"config":1336},"Pricing",{"href":1337,"dataGaName":1338,"dataGaLocation":1188,"dataNavLevelOne":1338},"/pricing/","pricing",{"text":1340,"config":1341,"menu":1342},"Resources",{"dataNavLevelOne":219},{"type":1239,"link":1343,"columns":1347,"feature":1441},{"text":1344,"config":1345},"View all resources",{"href":1346,"dataGaName":219,"dataGaLocation":1188},"/resources/",[1348,1381,1408],{"title":1349,"items":1350},"Getting started",[1351,1356,1361,1366,1371,1376],{"text":1352,"config":1353},"Install",{"href":1354,"dataGaName":1355,"dataGaLocation":1188},"/install/","install",{"text":1357,"config":1358},"Quick start guides",{"href":1359,"dataGaName":1360,"dataGaLocation":1188},"/get-started/","quick setup checklists",{"text":1362,"config":1363},"Learn",{"href":1364,"dataGaLocation":1188,"dataGaName":1365},"https://university.gitlab.com/","learn",{"text":1367,"config":1368},"Product documentation",{"href":1369,"dataGaName":1370,"dataGaLocation":1188},"https://docs.gitlab.com/","product documentation",{"text":1372,"config":1373},"Best practice videos",{"href":1374,"dataGaName":1375,"dataGaLocation":1188},"/getting-started-videos/","best practice videos",{"text":1377,"config":1378},"Integrations",{"href":1379,"dataGaName":1380,"dataGaLocation":1188},"/integrations/","integrations",{"title":1382,"items":1383},"Discover",[1384,1389,1394,1399,1403],{"text":1385,"config":1386},"Customer success stories",{"href":1387,"dataGaName":1388,"dataGaLocation":1188},"/customers/","customer success stories",{"text":1390,"config":1391},"Blog",{"href":1392,"dataGaName":1393,"dataGaLocation":1188},"/blog/","blog",{"text":1395,"config":1396},"Demo Hub",{"href":1397,"dataGaName":1398,"dataGaLocation":1188},"/demo-hub/","demo hub",{"text":1400,"config":1401},"The Source",{"href":1402,"dataGaName":1393,"dataGaLocation":1188},"/the-source/",{"text":1404,"config":1405},"Remote",{"href":1406,"dataGaName":1407,"dataGaLocation":1188},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1409,"items":1410},"Connect",[1411,1416,1421,1426,1431,1436],{"text":1412,"config":1413},"GitLab Services",{"href":1414,"dataGaName":1415,"dataGaLocation":1188},"/services/","services",{"text":1417,"config":1418},"Contribute",{"href":1419,"dataGaName":1420,"dataGaLocation":1188},"https://contributors.gitlab.com","contribute",{"text":1422,"config":1423},"Community",{"href":1424,"dataGaName":1425,"dataGaLocation":1188},"/community/","community",{"text":1427,"config":1428},"Forum",{"href":1429,"dataGaName":1430,"dataGaLocation":1188},"https://forum.gitlab.com/","forum",{"text":1432,"config":1433},"Events",{"href":1434,"dataGaName":1435,"dataGaLocation":1188},"/events/","events",{"text":1437,"config":1438},"Partners",{"href":1439,"dataGaName":1440,"dataGaLocation":1188},"/partners/","partners",{"config":1442,"title":1445,"text":1446,"link":1447},{"background":1443,"textColor":1444},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":1448,"config":1449},"Read the latest",{"href":1450,"dataGaName":1451,"dataGaLocation":1188},"/whats-new/","whats new",{"text":1453,"config":1454,"menu":1456},"Company",{"dataNavLevelOne":1455},"company",{"type":1239,"columns":1457},[1458],{"items":1459},[1460,1465,1471,1473,1478,1483,1488,1493,1498,1503],{"text":1461,"config":1462},"About",{"href":1463,"dataGaName":1464,"dataGaLocation":1188},"/company/","about",{"text":1466,"config":1467,"footerGa":1470},"Jobs",{"href":1468,"dataGaName":1469,"dataGaLocation":1188},"/jobs/","jobs",{"dataGaName":1469},{"text":1432,"config":1472},{"href":1434,"dataGaName":1435,"dataGaLocation":1188},{"text":1474,"config":1475},"Leadership",{"href":1476,"dataGaName":1477,"dataGaLocation":1188},"/company/team/e-group/","leadership",{"text":1479,"config":1480},"Handbook",{"href":1481,"dataGaName":1482,"dataGaLocation":1188},"https://handbook.gitlab.com/","handbook",{"text":1484,"config":1485},"Investor relations",{"href":1486,"dataGaName":1487,"dataGaLocation":1188},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1489,"config":1490},"Trust Center",{"href":1491,"dataGaName":1492,"dataGaLocation":1188},"/security/","trust center",{"text":1494,"config":1495},"AI Transparency Center",{"href":1496,"dataGaName":1497,"dataGaLocation":1188},"/ai-transparency-center/","ai transparency center",{"text":1499,"config":1500},"Newsletter",{"href":1501,"dataGaName":1502,"dataGaLocation":1188},"/company/contact/#contact-forms","newsletter",{"text":1504,"config":1505},"Press",{"href":1506,"dataGaName":1507,"dataGaLocation":1188},"/press/","press",{"text":1509,"config":1510,"menu":1511},"Contact us",{"dataNavLevelOne":1455},{"type":1239,"columns":1512},[1513],{"items":1514},[1515,1520,1525],{"text":1516,"config":1517},"Talk to sales",{"href":1518,"dataGaName":1519,"dataGaLocation":1188},"/sales/","talk to sales",{"text":1521,"config":1522},"Support portal",{"href":1523,"dataGaName":1524,"dataGaLocation":1188},"https://support.gitlab.com/hc/en-us","support portal",{"text":1526,"config":1527},"Customer portal",{"href":1528,"dataGaName":1529,"dataGaLocation":1188},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1531,"login":1532,"suggestions":1539},"Close",{"text":1533,"link":1534},"To search repositories and projects, login to",{"text":1535,"config":1536},"gitlab.com",{"href":1202,"dataGaName":1537,"dataGaLocation":1538},"search login","search",{"text":1540,"default":1541},"Suggestions",[1542,1544,1548,1550,1554,1558],{"text":1219,"config":1543},{"href":1224,"dataGaName":1219,"dataGaLocation":1538},{"text":1545,"config":1546},"Code Suggestions (AI)",{"href":1547,"dataGaName":1545,"dataGaLocation":1538},"/solutions/code-suggestions/",{"text":1255,"config":1549},{"href":1257,"dataGaName":1255,"dataGaLocation":1538},{"text":1551,"config":1552},"GitLab on AWS",{"href":1553,"dataGaName":1551,"dataGaLocation":1538},"/partners/technology-partners/aws/",{"text":1555,"config":1556},"GitLab on Google Cloud",{"href":1557,"dataGaName":1555,"dataGaLocation":1538},"/partners/technology-partners/google-cloud-platform/",{"text":1559,"config":1560},"Why GitLab?",{"href":1232,"dataGaName":1559,"dataGaLocation":1538},{"freeTrial":1562,"mobileIcon":1567,"desktopIcon":1572,"secondaryButton":1575},{"text":1563,"config":1564},"Start free trial",{"href":1565,"dataGaName":1193,"dataGaLocation":1566},"https://gitlab.com/-/trials/new/","nav",{"altText":1568,"config":1569},"Gitlab Icon",{"src":1570,"dataGaName":1571,"dataGaLocation":1566},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1568,"config":1573},{"src":1574,"dataGaName":1571,"dataGaLocation":1566},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1576,"config":1577},"Get Started",{"href":1578,"dataGaName":1579,"dataGaLocation":1566},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1581,"mobileIcon":1585,"desktopIcon":1587},{"text":1582,"config":1583},"Learn more about GitLab Duo",{"href":1224,"dataGaName":1584,"dataGaLocation":1566},"gitlab duo",{"altText":1568,"config":1586},{"src":1570,"dataGaName":1571,"dataGaLocation":1566},{"altText":1568,"config":1588},{"src":1574,"dataGaName":1571,"dataGaLocation":1566},{"button":1590,"mobileIcon":1595,"desktopIcon":1597},{"text":1591,"config":1592},"/switch",{"href":1593,"dataGaName":1594,"dataGaLocation":1566},"#contact","switch",{"altText":1568,"config":1596},{"src":1570,"dataGaName":1571,"dataGaLocation":1566},{"altText":1568,"config":1598},{"src":1599,"dataGaName":1571,"dataGaLocation":1566},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1601,"mobileIcon":1606,"desktopIcon":1608},{"text":1602,"config":1603},"Back to pricing",{"href":1337,"dataGaName":1604,"dataGaLocation":1566,"icon":1605},"back to pricing","GoBack",{"altText":1568,"config":1607},{"src":1570,"dataGaName":1571,"dataGaLocation":1566},{"altText":1568,"config":1609},{"src":1574,"dataGaName":1571,"dataGaLocation":1566},{"title":1611,"titleMobile":1612,"button":1613,"config":1618},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1230,"config":1614},{"href":1615,"dataGaName":1616,"dataGaLocation":1617},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1619,"disabled":1168},"release",{"data":1621},{"text":1622,"source":1623,"edit":1629,"contribute":1634,"config":1639,"items":1644,"minimal":1853},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1624,"config":1625},"View page source",{"href":1626,"dataGaName":1627,"dataGaLocation":1628},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1630,"config":1631},"Edit this page",{"href":1632,"dataGaName":1633,"dataGaLocation":1628},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1635,"config":1636},"Please contribute",{"href":1637,"dataGaName":1638,"dataGaLocation":1628},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1640,"facebook":1641,"youtube":1642,"linkedin":1643},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1645,1692,1745,1789,1821],{"title":1335,"links":1646,"subMenu":1661},[1647,1651,1656],{"text":1648,"config":1649},"View plans",{"href":1337,"dataGaName":1650,"dataGaLocation":1628},"view plans",{"text":1652,"config":1653},"Why Premium?",{"href":1654,"dataGaName":1655,"dataGaLocation":1628},"/pricing/premium/","why premium",{"text":1657,"config":1658},"Why Ultimate?",{"href":1659,"dataGaName":1660,"dataGaLocation":1628},"/pricing/ultimate/","why ultimate",[1662],{"title":1663,"links":1664},"Contact Us",[1665,1668,1670,1672,1677,1682,1687],{"text":1666,"config":1667},"Contact sales",{"href":1518,"dataGaName":1198,"dataGaLocation":1628},{"text":1521,"config":1669},{"href":1523,"dataGaName":1524,"dataGaLocation":1628},{"text":1526,"config":1671},{"href":1528,"dataGaName":1529,"dataGaLocation":1628},{"text":1673,"config":1674},"Status",{"href":1675,"dataGaName":1676,"dataGaLocation":1628},"https://status.gitlab.com/","status",{"text":1678,"config":1679},"Terms of use",{"href":1680,"dataGaName":1681,"dataGaLocation":1628},"/terms/","terms of use",{"text":1683,"config":1684},"Privacy statement",{"href":1685,"dataGaName":1686,"dataGaLocation":1628},"/privacy/","privacy statement",{"text":1688,"config":1689},"Cookie preferences",{"dataGaName":1690,"dataGaLocation":1628,"id":1691,"isOneTrustButton":623},"cookie preferences","ot-sdk-btn",{"title":1235,"links":1693,"subMenu":1702},[1694,1698],{"text":1695,"config":1696},"DevSecOps platform",{"href":1217,"dataGaName":1697,"dataGaLocation":1628},"devsecops platform",{"text":1699,"config":1700},"AI-Assisted Development",{"href":1224,"dataGaName":1701,"dataGaLocation":1628},"ai-assisted development",[1703],{"title":1704,"links":1705},"Topics",[1706,1711,1715,1720,1725,1730,1735,1740],{"text":1707,"config":1708},"CICD",{"href":1709,"dataGaName":1710,"dataGaLocation":1628},"/topics/ci-cd/","cicd",{"text":1180,"config":1712},{"href":1713,"dataGaName":1714,"dataGaLocation":1628},"/topics/gitops/","gitops",{"text":1716,"config":1717},"DevOps",{"href":1718,"dataGaName":1719,"dataGaLocation":1628},"/topics/devops/","devops",{"text":1721,"config":1722},"Version Control",{"href":1723,"dataGaName":1724,"dataGaLocation":1628},"/topics/version-control/","version control",{"text":1726,"config":1727},"DevSecOps",{"href":1728,"dataGaName":1729,"dataGaLocation":1628},"/topics/devsecops/","devsecops",{"text":1731,"config":1732},"Cloud Native",{"href":1733,"dataGaName":1734,"dataGaLocation":1628},"/topics/cloud-native/","cloud native",{"text":1736,"config":1737},"AI for Coding",{"href":1738,"dataGaName":1739,"dataGaLocation":1628},"/topics/devops/ai-for-coding/","ai for coding",{"text":1741,"config":1742},"Agentic AI",{"href":1743,"dataGaName":1744,"dataGaLocation":1628},"/topics/agentic-ai/","agentic ai",{"title":1746,"links":1747},"Solutions",[1748,1750,1752,1757,1761,1764,1768,1771,1773,1776,1779,1784],{"text":1279,"config":1749},{"href":1274,"dataGaName":1279,"dataGaLocation":1628},{"text":1268,"config":1751},{"href":1251,"dataGaName":1252,"dataGaLocation":1628},{"text":1753,"config":1754},"Agile development",{"href":1755,"dataGaName":1756,"dataGaLocation":1628},"/solutions/agile-delivery/","agile delivery",{"text":1758,"config":1759},"SCM",{"href":1264,"dataGaName":1760,"dataGaLocation":1628},"source code management",{"text":1707,"config":1762},{"href":1257,"dataGaName":1763,"dataGaLocation":1628},"continuous integration & delivery",{"text":1765,"config":1766},"Value stream management",{"href":1307,"dataGaName":1767,"dataGaLocation":1628},"value stream management",{"text":1180,"config":1769},{"href":1770,"dataGaName":1714,"dataGaLocation":1628},"/solutions/gitops/",{"text":1317,"config":1772},{"href":1320,"dataGaName":1321,"dataGaLocation":1628},{"text":1774,"config":1775},"Small business",{"href":1326,"dataGaName":1327,"dataGaLocation":1628},{"text":1777,"config":1778},"Public sector",{"href":1332,"dataGaName":1333,"dataGaLocation":1628},{"text":1780,"config":1781},"Education",{"href":1782,"dataGaName":1783,"dataGaLocation":1628},"/solutions/education/","education",{"text":1785,"config":1786},"Financial services",{"href":1787,"dataGaName":1788,"dataGaLocation":1628},"/solutions/finance/","financial services",{"title":1340,"links":1790},[1791,1793,1795,1797,1800,1802,1805,1807,1809,1811,1813,1815,1817,1819],{"text":1352,"config":1792},{"href":1354,"dataGaName":1355,"dataGaLocation":1628},{"text":1357,"config":1794},{"href":1359,"dataGaName":1360,"dataGaLocation":1628},{"text":1362,"config":1796},{"href":1364,"dataGaName":1365,"dataGaLocation":1628},{"text":1367,"config":1798},{"href":1369,"dataGaName":1799,"dataGaLocation":1628},"docs",{"text":1390,"config":1801},{"href":1392,"dataGaName":1393,"dataGaLocation":1628},{"text":1803,"config":1804},"What's new",{"href":1450,"dataGaName":1451,"dataGaLocation":1628},{"text":1385,"config":1806},{"href":1387,"dataGaName":1388,"dataGaLocation":1628},{"text":1404,"config":1808},{"href":1406,"dataGaName":1407,"dataGaLocation":1628},{"text":1412,"config":1810},{"href":1414,"dataGaName":1415,"dataGaLocation":1628},{"text":1417,"config":1812},{"href":1419,"dataGaName":1420,"dataGaLocation":1628},{"text":1422,"config":1814},{"href":1424,"dataGaName":1425,"dataGaLocation":1628},{"text":1427,"config":1816},{"href":1429,"dataGaName":1430,"dataGaLocation":1628},{"text":1432,"config":1818},{"href":1434,"dataGaName":1435,"dataGaLocation":1628},{"text":1437,"config":1820},{"href":1439,"dataGaName":1440,"dataGaLocation":1628},{"title":1453,"links":1822},[1823,1825,1827,1829,1831,1833,1837,1842,1844,1846,1848],{"text":1461,"config":1824},{"href":1463,"dataGaName":1455,"dataGaLocation":1628},{"text":1466,"config":1826},{"href":1468,"dataGaName":1469,"dataGaLocation":1628},{"text":1474,"config":1828},{"href":1476,"dataGaName":1477,"dataGaLocation":1628},{"text":1479,"config":1830},{"href":1481,"dataGaName":1482,"dataGaLocation":1628},{"text":1484,"config":1832},{"href":1486,"dataGaName":1487,"dataGaLocation":1628},{"text":1834,"config":1835},"Sustainability",{"href":1836,"dataGaName":1834,"dataGaLocation":1628},"/sustainability/",{"text":1838,"config":1839},"Diversity, inclusion and belonging (DIB)",{"href":1840,"dataGaName":1841,"dataGaLocation":1628},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1489,"config":1843},{"href":1491,"dataGaName":1492,"dataGaLocation":1628},{"text":1499,"config":1845},{"href":1501,"dataGaName":1502,"dataGaLocation":1628},{"text":1504,"config":1847},{"href":1506,"dataGaName":1507,"dataGaLocation":1628},{"text":1849,"config":1850},"Modern Slavery Transparency Statement",{"href":1851,"dataGaName":1852,"dataGaLocation":1628},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1854},[1855,1858,1861],{"text":1856,"config":1857},"Terms",{"href":1680,"dataGaName":1681,"dataGaLocation":1628},{"text":1859,"config":1860},"Cookies",{"dataGaName":1690,"dataGaLocation":1628,"id":1691,"isOneTrustButton":623},{"text":1862,"config":1863},"Privacy",{"href":1685,"dataGaName":1686,"dataGaLocation":1628},[1865],{"id":1866,"title":7,"body":1167,"config":1867,"content":1869,"description":1167,"extension":1873,"meta":1874,"navigation":623,"path":1875,"seo":1876,"stem":1877,"__hash__":1878},"blogAuthors/en-us/blog/authors/bart-zhang.yml",{"template":1868},"BlogAuthor",{"name":7,"config":1870},{"headshot":1871,"ctfId":1872},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664177/Blog/Author%20Headshots/bartzhang-headshot.jpg","bartzhang","yml",{},"/en-us/blog/authors/bart-zhang",{},"en-us/blog/authors/bart-zhang","b7CFRNFezC9yhgQ3GRiTZ4joQAY5dZB2u6FIo2bo1Xs",[1880,1889,1897],{"title":1881,"description":1882,"heroImage":1883,"category":1163,"date":1884,"authors":1885,"slug":1888,"externalUrl":1167},"Confidential AI for GitLab Self-Hosted","Give developers AI coding agents in GitLab Duo without source code leaving a hardware-encrypted boundary — no GPUs needed.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1773866173/vte9qh8rriznvyclhkes.png","2026-08-06",[1886,1887],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1890,"description":1891,"heroImage":1892,"category":1163,"date":1893,"authors":1894,"slug":1896,"externalUrl":1167},"Green DevOps: Why carbon measurement belongs in your CI/CD pipeline","CI/CD pipelines have a hidden carbon cost. Here's why measuring it matters, and how you can get started with Eco CI and Carmen in GitLab.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1765809212/noh0mdfn9o94ry9ykura.png","2026-07-09",[1895],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1898,"description":1899,"heroImage":1900,"category":1163,"date":1901,"authors":1902,"slug":1904,"externalUrl":1167},"How to build CI/CD observability at scale","This practical guide to GitLab pipeline analytics helps self-managed users gain operational insights using Prometheus and Grafana.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-04-28",[1903],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1906},[1907,1921,1933,1945],{"id":1908,"categories":1909,"header":1911,"text":1912,"button":1913,"image":1918},"ai-modernization",[1910],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1914,"config":1915},"Get your AI maturity score",{"href":1916,"dataGaName":1917,"dataGaLocation":1393},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1919},{"src":1920},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1922,"categories":1923,"header":1925,"text":1912,"button":1926,"image":1930},"devops-modernization",[1924,1729],"product","Are you just managing tools or shipping innovation?",{"text":1927,"config":1928},"Get your DevOps maturity score",{"href":1929,"dataGaName":1917,"dataGaLocation":1393},"/assessments/devops-modernization-assessment/",{"config":1931},{"src":1932},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1934,"categories":1935,"header":1937,"text":1912,"button":1938,"image":1942},"security-modernization",[1936],"security","Are you trading speed for security?",{"text":1939,"config":1940},"Get your security maturity score",{"href":1941,"dataGaName":1917,"dataGaLocation":1393},"/assessments/security-modernization-assessment/",{"config":1943},{"src":1944},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1946,"paths":1947,"header":1950,"text":1951,"button":1952,"image":1957},"github-azure-migration",[1948,1949],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":1953,"config":1954},"See how GitLab compares to GitHub",{"href":1955,"dataGaName":1956,"dataGaLocation":1393},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1958},{"src":1932},{"header":1960,"blurb":1961,"button":1962,"secondaryButton":1967},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1963,"config":1964},"Get your free trial",{"href":1965,"dataGaName":1193,"dataGaLocation":1966},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1666,"config":1968},{"href":1518,"dataGaName":1198,"dataGaLocation":1966},1786803754732]