[{"data":1,"prerenderedAt":1729},["ShallowReactive",2],{"/blog/gitops-with-gitlab-secrets-management":3,"navigation-en-us":943,"banner-en-us":1371,"footer-en-us":1381,"blog-post-authors-en-us-Viktor Nagy":1624,"blog-related-posts-en-us-gitops-with-gitlab-secrets-management":1639,"blog-promotions-en-us":1665,"next-steps-en-us":1719},{"id":4,"title":5,"authors":6,"body":8,"category":922,"date":923,"description":924,"extension":925,"externalUrl":926,"faq":926,"featured":927,"heroImage":928,"meta":929,"navigation":715,"path":930,"seo":931,"slug":935,"stem":936,"tags":937,"template":941,"updatedDate":926,"__hash__":942},"blogPosts/en-us/blog/gitops-with-gitlab-secrets-management.md","GitOps with GitLab: How to tackle secrets management",[7],"Viktor Nagy",{"type":9,"value":10,"toc":905},"minimark",[11,24,27,32,35,39,47,50,53,69,73,76,87,92,109,120,124,130,133,137,152,184,188,215,226,232,236,242,271,275,282,330,334,337,415,425,434,532,535,668,681,685,691,700,872,879,883,886,890,893,901],[12,13,14],"p",{},[15,16,17,18,23],"em",{},"It is possible to use GitLab as a best-in-class GitOps tool, and this blog post series is going to show you how. These easy-to-follow tutorials will focus on different user problems, including provisioning, managing a base infrastructure, and deploying various third-party or custom applications on top of them. You can also view our entire ",[19,20,22],"a",{"href":21},"/blog/the-ultimate-guide-to-gitops-with-gitlab/","\"Ultimate guide to GitOps with GitLab\""," tutorial series.",[12,25,26],{},"In this article we will use our cluster connection to manage secrets within our cluster.",[28,29,31],"h2",{"id":30},"prerequisites","Prerequisites",[12,33,34],{},"This article assumes that you have a Kubernetes cluster connected to GitLab using the GitLab Agent for Kubernetes. If you don't have such a cluster, I recommend looking at the linked articles above so you have a similar setup from where we will start today.",[28,36,38],{"id":37},"a-few-words-about-secrets-management","A few words about secrets management",[12,40,41,42,46],{},"The Kubernetes ",[43,44,45],"code",{},"Secret"," resource is a rather tricky one! By design, secrets should have limited access and should be encrypted at rest and in transit. Still, by default, Kubernetes does not encrypt secrets at rest and accessing them might not be restricted in your cluster. We will not go into detail about how to secure your cluster with respect to secrets in this article. Instead, we want to focus on getting some secrets configured in your cluster with a GitOps approach.",[12,48,49],{},"Managing secrets with GitOps means you store those secrets within your Git repository. Of course, you should never store unencrypted secrets in a repo, and some security people are even reluctant to store encrypted secrets in Git. We will not be that worried, but you should consider if this is an acceptable risk for you. There is an alternative we'll talk about, below, if you prefer to not manage your secrets in Git.",[12,51,52],{},"There are a few benefits of Git-based secrets management:",[54,55,56,60,63,66],"ul",{},[57,58,59],"li",{},"you get versioning by default",[57,61,62],{},"collaboration is supported using merge requests",[57,64,65],{},"as secrets are in code, you push responsibilities towards the development team",[57,67,68],{},"the tools used are well-known to developers",[28,70,72],{"id":71},"secrets-management-with-gitlab","Secrets management with GitLab",[12,74,75],{},"When it comes to secrets, Kubernetes, and GitLab, there are at least 3 options to choose from:",[54,77,78,81,84],{},[57,79,80],{},"create secrets automatically from environment variables in GitLab CI",[57,82,83],{},"manage secrets through HashiCorp Vault and GitLab CI",[57,85,86],{},"manage secrets in git with a GitOps approach",[88,89,91],"h3",{"id":90},"create-secrets-automatically-from-environment-variables-in-gitlab-ci","Create secrets automatically from environment variables in GitLab CI",[12,93,94,95,103,104,108],{},"The Auto Deploy template applies every ",[19,96,99,102],{"href":97,"rel":98},"https://docs.gitlab.com/topics/autodevops/customize/#application-secret-variables",[],[43,100,101],{},"K8S_SECRET_"," prefixed environment variable"," into your cluster as a Kubernetes Secret. Later, your applications can reference these secrets. This approach is the simplest to use, especially if you would like to use ",[19,105,107],{"href":106},"/topics/devops/","Auto DevOps",". We will look into it in a future article.",[12,110,111,112,115,116,119],{},"While simple to use, with this approach your secrets are stored in the GitLab database, instead of ",[43,113,114],{},"Git",". That means you lose versioning of the secrets, you need ",[43,117,118],{},"Maintainer"," rights to modify these secrets, and you lose the ability to approve a change of secret in a merge request.",[88,121,123],{"id":122},"manage-secrets-through-hashicorp-vault-and-gitlab-ci","Manage secrets through HashiCorp Vault and GitLab CI",[12,125,126,127,129],{},"GitLab CI/CD integrates with HashiCorp Vault to support advanced secrets management use cases. You can combine the ",[43,128,101],{}," prefixed use case even with Vault-based secrets, and have the secrets applied automatically.",[12,131,132],{},"With this approach, you get the all the benefits of HashiCorp Vault, but there is a question: why do you move secrets from Vault to GitLab just to move them to your cluster instead of retrieving the secrets directly from within your cluster? We recommend leaving GitLab out of this flow if you don't have a really good reason to provide secret access to GitLab too! Vault has really great Kubernetes support, thus retrieving secrets directly should be feasible.",[88,134,136],{"id":135},"manage-secrets-in-git-with-a-gitops-approach","Manage secrets in Git with a GitOps approach",[12,138,139,140,145,146,151],{},"To manage secrets in Git, we will need some kind of tooling to take care of the encryption/decryption of the secrets. In this article, I will show you how to set up and use ",[19,141,144],{"href":142,"rel":143},"https://github.com/bitnami-labs/sealed-secrets",[],"Bitnami's Sealed Secrets",", but you can try other tools, like ",[19,147,150],{"href":148,"rel":149},"https://github.com/mozilla/sops",[],"SOPS"," too. We will look into Bitnami's approach as it targets Kubernetes exclusively, unlike SOPS that supports other use cases too, and might need a bit more setup for Kubernetes.",[12,153,154,155,158,159,161,162,164,165,167,168,171,172,174,175,177,178,180,181,183],{},"Bitnami's Sealed Secrets is composed of an in-cluster controller and a CLI tool. The cluster component defines a ",[43,156,157],{},"SealedSecret"," custom resource that stores the encrypted secret and related metadata. Once a ",[43,160,157],{}," is deployed into the cluster, the controller decrypts it and creates a native Kubernetes ",[43,163,45],{}," resource from it. To create a ",[43,166,157],{}," resource, the ",[43,169,170],{},"kubeseal"," utility can be used. ",[43,173,170],{}," can take a public key and transform and encrypt a native Kubernetes ",[43,176,45],{}," into a ",[43,179,157],{},", and ",[43,182,170],{}," can help with retrieving the public key from the cluster-side controller too.",[28,185,187],{"id":186},"setting-up-bitnamis-sealed-secrets","Setting up Bitnami's Sealed Secrets",[12,189,190,191,196,197,200,201,206,207,210,211,214],{},"As the GitLab Agent supports pure Kubernetes manifests to do GitOps, we will need the manifests for Sealed Secrets. Open the ",[19,192,195],{"href":193,"rel":194},"https://github.com/bitnami-labs/sealed-secrets/releases/",[],"Sealed Secrets releases page"," and find the most recent release (Don't be fooled by the ",[43,198,199],{},"helm"," releases!). At the time of writing this article, the most recent ",[19,202,205],{"href":203,"rel":204},"https://github.com/bitnami-labs/sealed-secrets/releases/tag/v0.16.0",[],"release is v0.16.0",". From there you can download the release ",[43,208,209],{},"yaml",", if your cluster supports RBAC, I recommend the basic ",[43,212,213],{},"controller.yaml"," file.",[54,216,217],{},[57,218,219,220,222,223],{},"Save and commit the ",[43,221,213],{}," under ",[43,224,225],{},"kubernetes/sealed-secrets.yaml",[12,227,228,229],{},"Push the changes and wait a few seconds for them to get applied. Check that they got applied successfully using: ",[43,230,231],{},"kubectl get pods -n kube-system -l name=sealed-secrets-controller",[28,233,235],{"id":234},"retrieving-the-public-key","Retrieving the public key",[12,237,238,239,241],{},"While the user can encrypt a secret directly with ",[43,240,170],{},", this approach requires them to have access to the Kube API. Instead of providing access, we can fetch the public key from the Sealed Secrets controller and store it in the Git repo. The public key can be used to encrypt secrets, but is useless for decrypting them.",[243,244,249],"pre",{"className":245,"code":246,"language":247,"meta":248,"style":248},"language-bash shiki shiki-themes github-light","kubeseal --fetch-cert > sealed-secrets.pub.pem\n","bash","",[43,250,251],{"__ignoreMap":248},[252,253,256,259,263,267],"span",{"class":254,"line":255},"line",1,[252,257,170],{"class":258},"s7eDp",[252,260,262],{"class":261},"sYu0t"," --fetch-cert",[252,264,266],{"class":265},"sD7c4"," >",[252,268,270],{"class":269},"sYBdl"," sealed-secrets.pub.pem\n",[88,272,274],{"id":273},"how-to-avoid-storing-unencrypted-secrets","How to avoid storing unencrypted secrets",[12,276,277,278,281],{},"I prefer to have an ",[43,279,280],{},"ignored"," directory within my Git repo. The content of this directory is never committed to Git, and I put every sensitive data under this directory.",[243,283,285],{"className":245,"code":284,"language":247,"meta":248,"style":248},"mkdir ignored\ncat \u003C\u003CEOF > ignored/.gitignore\n*\n!.gitignore\nEOF\n",[43,286,287,295,312,318,324],{"__ignoreMap":248},[252,288,289,292],{"class":254,"line":255},[252,290,291],{"class":258},"mkdir",[252,293,294],{"class":269}," ignored\n",[252,296,298,301,304,307,309],{"class":254,"line":297},2,[252,299,300],{"class":258},"cat",[252,302,303],{"class":265}," \u003C\u003C",[252,305,306],{"class":269},"EOF",[252,308,266],{"class":265},[252,310,311],{"class":269}," ignored/.gitignore\n",[252,313,315],{"class":254,"line":314},3,[252,316,317],{"class":269},"*\n",[252,319,321],{"class":254,"line":320},4,[252,322,323],{"class":269},"!.gitignore\n",[252,325,327],{"class":254,"line":326},5,[252,328,329],{"class":269},"EOF\n",[28,331,333],{"id":332},"continue-with-setup-not-needed-if-we-use-a-box","Continue with setup - not needed if we use a box",[12,335,336],{},"Now, you can create sealed secrets with the following two commands:",[243,338,340],{"className":245,"code":339,"language":247,"meta":248,"style":248},"echo \"Very secret\" | kubectl create secret generic my-secret -n gitlab-agent --dry-run=client --type=Opaque --from-file=token=/dev/stdin -o yaml > ignored/my-secret.yaml\nkubeseal --format=yaml --cert=sealed-secrets.pub.pem \u003C ignored/my-secret.yaml > kubernetes/\n",[43,341,342,394],{"__ignoreMap":248},[252,343,344,347,350,353,356,359,362,365,368,371,374,377,380,383,386,389,391],{"class":254,"line":255},[252,345,346],{"class":261},"echo",[252,348,349],{"class":269}," \"Very secret\"",[252,351,352],{"class":265}," |",[252,354,355],{"class":258}," kubectl",[252,357,358],{"class":269}," create",[252,360,361],{"class":269}," secret",[252,363,364],{"class":269}," generic",[252,366,367],{"class":269}," my-secret",[252,369,370],{"class":261}," -n",[252,372,373],{"class":269}," gitlab-agent",[252,375,376],{"class":261}," --dry-run=client",[252,378,379],{"class":261}," --type=Opaque",[252,381,382],{"class":261}," --from-file=token=/dev/stdin",[252,384,385],{"class":261}," -o",[252,387,388],{"class":269}," yaml",[252,390,266],{"class":265},[252,392,393],{"class":269}," ignored/my-secret.yaml\n",[252,395,396,398,401,404,407,410,412],{"class":254,"line":297},[252,397,170],{"class":258},[252,399,400],{"class":261}," --format=yaml",[252,402,403],{"class":261}," --cert=sealed-secrets.pub.pem",[252,405,406],{"class":265}," \u003C",[252,408,409],{"class":269}," ignored/my-secret.yaml",[252,411,266],{"class":265},[252,413,414],{"class":269}," kubernetes/\n",[12,416,417,418,420,421,424],{},"The first command creates a regular Kubernetes ",[43,419,45],{}," resource in the ",[43,422,423],{},"gitlab-agent"," namespace. Setting the namespace is important if you use Sealed Secrets and every SealedSecret is scoped for a specific namespace. You can read more about this in the Sealed Secrets documentation.",[12,426,427,428,430,431,433],{},"The second command takes a ",[43,429,45],{}," resource object and turns it into an encrypted ",[43,432,157],{}," resource. In my case, the secret file:",[243,435,438],{"className":436,"code":437,"language":209,"meta":248,"style":248},"language-yaml shiki shiki-themes github-light","apiVersion: v1\ndata:\n  token: VmVyeSBzZWNyZXQK\nkind: Secret\nmetadata:\n  creationTimestamp: null\n  name: my-secret\n  namespace: gitlab-agent\ntype: Opaque\n",[43,439,440,453,461,471,481,488,499,510,521],{"__ignoreMap":248},[252,441,442,446,450],{"class":254,"line":255},[252,443,445],{"class":444},"shJU0","apiVersion",[252,447,449],{"class":448},"sgsFI",": ",[252,451,452],{"class":269},"v1\n",[252,454,455,458],{"class":254,"line":297},[252,456,457],{"class":444},"data",[252,459,460],{"class":448},":\n",[252,462,463,466,468],{"class":254,"line":314},[252,464,465],{"class":444},"  token",[252,467,449],{"class":448},[252,469,470],{"class":269},"VmVyeSBzZWNyZXQK\n",[252,472,473,476,478],{"class":254,"line":320},[252,474,475],{"class":444},"kind",[252,477,449],{"class":448},[252,479,480],{"class":269},"Secret\n",[252,482,483,486],{"class":254,"line":326},[252,484,485],{"class":444},"metadata",[252,487,460],{"class":448},[252,489,491,494,496],{"class":254,"line":490},6,[252,492,493],{"class":444},"  creationTimestamp",[252,495,449],{"class":448},[252,497,498],{"class":261},"null\n",[252,500,502,505,507],{"class":254,"line":501},7,[252,503,504],{"class":444},"  name",[252,506,449],{"class":448},[252,508,509],{"class":269},"my-secret\n",[252,511,513,516,518],{"class":254,"line":512},8,[252,514,515],{"class":444},"  namespace",[252,517,449],{"class":448},[252,519,520],{"class":269},"gitlab-agent\n",[252,522,524,527,529],{"class":254,"line":523},9,[252,525,526],{"class":444},"type",[252,528,449],{"class":448},[252,530,531],{"class":269},"Opaque\n",[12,533,534],{},"got turned into:",[243,536,538],{"className":436,"code":537,"language":209,"meta":248,"style":248},"apiVersion: bitnami.com/v1alpha1\nkind: SealedSecret\nmetadata:\n  creationTimestamp: null\n  name: my-secret\n  namespace: gitlab-agent\nspec:\n  encryptedData:\n    token: AgC1m/D1UwliKD3C2QSv/g+zBi1qGz1YTLZfqnl5JJ4NydCatKzsp8LZr2stIlkwcS3f2YAo/ZIq1OUhOgSgkuNMwVdqsBx1zq7Z3xpGLMIMe7B3XhQ+ExWwqgrm1dTiTDHaH9eXsZWaNsruKQU0F8oGxgLfO/axEZeGWd4WngZRaed9B43dy2k05B6fZnxmwtUVSpr86MO52fX06/QdbvB8MZTrYb7qFuL14U0IDvdFl4l8sPl2rrXsriKg0fJHIV6XtlCwPpQGozTZTUX8nbvU0yXothBzPbaIUfXseFqaW8i/i0Ai+aKhWQAjPGooVAXGwKsuve16DxZ6GJPp1ymR1cEsBkEPlYKbVCKtH5VuptCYZuTXMM6OEPzjFabaIMIUVkkciHlUMcpKFfPnpf7XbBNqZCAKjt//9L99gc48dJRyO4pCrcpFnv6287d65UGnWjmcUJNQNBhEuh9k4esfEZuBNiYIz3Ouz7Wg5HQoT6v3i3J1X5LluWEcTK1G10T7UN+QrnklH4yUtx35yLp83B5/TGICo0Yq1QnARNbKhL5EXuwAO427XO65zzJ3Lh2ymUfrBY3bHO8NW4ykO7ZNDRdj/fsge1J8k4yaxeimQapDKs4XMhoNnKqUNPQYaiQzNPRoj9JwMvtvOH+WLJqEXHIc8RooWGkdo/SB7zp3q7OuHk6HRJM+AQVP3t0r3A1bVhHonUGlv1ApduM=\n  template:\n    metadata:\n      creationTimestamp: null\n      name: my-secret\n      namespace: gitlab-agent\n    type: Opaque\n\n",[43,539,540,549,558,564,572,580,588,595,602,612,620,628,638,648,658],{"__ignoreMap":248},[252,541,542,544,546],{"class":254,"line":255},[252,543,445],{"class":444},[252,545,449],{"class":448},[252,547,548],{"class":269},"bitnami.com/v1alpha1\n",[252,550,551,553,555],{"class":254,"line":297},[252,552,475],{"class":444},[252,554,449],{"class":448},[252,556,557],{"class":269},"SealedSecret\n",[252,559,560,562],{"class":254,"line":314},[252,561,485],{"class":444},[252,563,460],{"class":448},[252,565,566,568,570],{"class":254,"line":320},[252,567,493],{"class":444},[252,569,449],{"class":448},[252,571,498],{"class":261},[252,573,574,576,578],{"class":254,"line":326},[252,575,504],{"class":444},[252,577,449],{"class":448},[252,579,509],{"class":269},[252,581,582,584,586],{"class":254,"line":490},[252,583,515],{"class":444},[252,585,449],{"class":448},[252,587,520],{"class":269},[252,589,590,593],{"class":254,"line":501},[252,591,592],{"class":444},"spec",[252,594,460],{"class":448},[252,596,597,600],{"class":254,"line":512},[252,598,599],{"class":444},"  encryptedData",[252,601,460],{"class":448},[252,603,604,607,609],{"class":254,"line":523},[252,605,606],{"class":444},"    token",[252,608,449],{"class":448},[252,610,611],{"class":269},"AgC1m/D1UwliKD3C2QSv/g+zBi1qGz1YTLZfqnl5JJ4NydCatKzsp8LZr2stIlkwcS3f2YAo/ZIq1OUhOgSgkuNMwVdqsBx1zq7Z3xpGLMIMe7B3XhQ+ExWwqgrm1dTiTDHaH9eXsZWaNsruKQU0F8oGxgLfO/axEZeGWd4WngZRaed9B43dy2k05B6fZnxmwtUVSpr86MO52fX06/QdbvB8MZTrYb7qFuL14U0IDvdFl4l8sPl2rrXsriKg0fJHIV6XtlCwPpQGozTZTUX8nbvU0yXothBzPbaIUfXseFqaW8i/i0Ai+aKhWQAjPGooVAXGwKsuve16DxZ6GJPp1ymR1cEsBkEPlYKbVCKtH5VuptCYZuTXMM6OEPzjFabaIMIUVkkciHlUMcpKFfPnpf7XbBNqZCAKjt//9L99gc48dJRyO4pCrcpFnv6287d65UGnWjmcUJNQNBhEuh9k4esfEZuBNiYIz3Ouz7Wg5HQoT6v3i3J1X5LluWEcTK1G10T7UN+QrnklH4yUtx35yLp83B5/TGICo0Yq1QnARNbKhL5EXuwAO427XO65zzJ3Lh2ymUfrBY3bHO8NW4ykO7ZNDRdj/fsge1J8k4yaxeimQapDKs4XMhoNnKqUNPQYaiQzNPRoj9JwMvtvOH+WLJqEXHIc8RooWGkdo/SB7zp3q7OuHk6HRJM+AQVP3t0r3A1bVhHonUGlv1ApduM=\n",[252,613,615,618],{"class":254,"line":614},10,[252,616,617],{"class":444},"  template",[252,619,460],{"class":448},[252,621,623,626],{"class":254,"line":622},11,[252,624,625],{"class":444},"    metadata",[252,627,460],{"class":448},[252,629,631,634,636],{"class":254,"line":630},12,[252,632,633],{"class":444},"      creationTimestamp",[252,635,449],{"class":448},[252,637,498],{"class":261},[252,639,641,644,646],{"class":254,"line":640},13,[252,642,643],{"class":444},"      name",[252,645,449],{"class":448},[252,647,509],{"class":269},[252,649,651,654,656],{"class":254,"line":650},14,[252,652,653],{"class":444},"      namespace",[252,655,449],{"class":448},[252,657,520],{"class":269},[252,659,661,664,666],{"class":254,"line":660},15,[252,662,663],{"class":444},"    type",[252,665,449],{"class":448},[252,667,531],{"class":269},[12,669,670,671,673,674,677,678,680],{},"Just commit the ",[43,672,157],{}," and quickly start to watch for the event stream using ",[43,675,676],{},"kubectl get events --all-namespaces --watch"," to see when the sealed secret is unsealed and applied as a regular ",[43,679,45],{},".",[28,682,684],{"id":683},"utility-scripts","Utility scripts",[12,686,687,688,690],{},"If you found the ",[43,689,170],{}," command above to be quite complex, you can wrap it in a script.",[54,692,693],{},[57,694,695,696,699],{},"Create ",[43,697,698],{},"bin/seal-secret.sh"," with the following content:",[243,701,703],{"className":245,"code":702,"language":247,"meta":248,"style":248},"#!/bin/sh\n\nif [ $# -ne 2 ]\n  then\n    echo \"Usage: $0 ignored/my-secret.yaml output-dir/\"\n    echo \"This script requires two arguments\"\n    echo \"The first argument should be the unsealed secret\"\n    echo \"The second argument should be the directory to output the sealed secret\"\n  exit 1\nfi\n\n\nSECRET_FILE=$(basename $1)\n\nkubeseal --format=yaml --cert=sealed-secrets.pub.pem \u003C $1 > \"$2/SealedSecret.${SECRET_FILE}\"\n\necho \"Created file $2/SealedSecret.${SECRET_FILE}\"\n",[43,704,705,711,717,737,742,756,763,770,777,785,790,794,798,819,823,851,856],{"__ignoreMap":248},[252,706,707],{"class":254,"line":255},[252,708,710],{"class":709},"sAwPA","#!/bin/sh\n",[252,712,713],{"class":254,"line":297},[252,714,716],{"emptyLinePlaceholder":715},true,"\n",[252,718,719,722,725,728,731,734],{"class":254,"line":314},[252,720,721],{"class":265},"if",[252,723,724],{"class":448}," [ ",[252,726,727],{"class":261},"$#",[252,729,730],{"class":265}," -ne",[252,732,733],{"class":261}," 2",[252,735,736],{"class":448}," ]\n",[252,738,739],{"class":254,"line":320},[252,740,741],{"class":265},"  then\n",[252,743,744,747,750,753],{"class":254,"line":326},[252,745,746],{"class":261},"    echo",[252,748,749],{"class":269}," \"Usage: ",[252,751,752],{"class":261},"$0",[252,754,755],{"class":269}," ignored/my-secret.yaml output-dir/\"\n",[252,757,758,760],{"class":254,"line":490},[252,759,746],{"class":261},[252,761,762],{"class":269}," \"This script requires two arguments\"\n",[252,764,765,767],{"class":254,"line":501},[252,766,746],{"class":261},[252,768,769],{"class":269}," \"The first argument should be the unsealed secret\"\n",[252,771,772,774],{"class":254,"line":512},[252,773,746],{"class":261},[252,775,776],{"class":269}," \"The second argument should be the directory to output the sealed secret\"\n",[252,778,779,782],{"class":254,"line":523},[252,780,781],{"class":261},"  exit",[252,783,784],{"class":261}," 1\n",[252,786,787],{"class":254,"line":614},[252,788,789],{"class":265},"fi\n",[252,791,792],{"class":254,"line":622},[252,793,716],{"emptyLinePlaceholder":715},[252,795,796],{"class":254,"line":630},[252,797,716],{"emptyLinePlaceholder":715},[252,799,800,803,806,809,812,816],{"class":254,"line":640},[252,801,802],{"class":448},"SECRET_FILE",[252,804,805],{"class":265},"=",[252,807,808],{"class":448},"$(",[252,810,811],{"class":258},"basename",[252,813,815],{"class":814},"sqxcx"," $1",[252,817,818],{"class":448},")\n",[252,820,821],{"class":254,"line":650},[252,822,716],{"emptyLinePlaceholder":715},[252,824,825,827,829,831,833,835,837,840,843,846,848],{"class":254,"line":660},[252,826,170],{"class":258},[252,828,400],{"class":261},[252,830,403],{"class":261},[252,832,406],{"class":265},[252,834,815],{"class":814},[252,836,266],{"class":265},[252,838,839],{"class":269}," \"",[252,841,842],{"class":261},"$2",[252,844,845],{"class":269},"/SealedSecret.${",[252,847,802],{"class":448},[252,849,850],{"class":269},"}\"\n",[252,852,854],{"class":254,"line":853},16,[252,855,716],{"emptyLinePlaceholder":715},[252,857,859,861,864,866,868,870],{"class":254,"line":858},17,[252,860,346],{"class":261},[252,862,863],{"class":269}," \"Created file ",[252,865,842],{"class":261},[252,867,845],{"class":269},[252,869,802],{"class":448},[252,871,850],{"class":269},[12,873,874,875,177,877,680],{},"This script takes a path to a vanilla Kubernetes secret and an output directory, and tranforms your ",[43,876,45],{},[43,878,157],{},[28,880,882],{"id":881},"winding-it-up","Winding it up",[12,884,885],{},"In this article, we have seen how you can install Bitnami's Sealed Secret into your cluster and set it up for static secrets management. Please note the installation method provided here works for all the other 3rd party, off-the-shelf applications that can be deployed using Kubernetes manifests only.",[28,887,889],{"id":888},"what-is-next","What is next?",[12,891,892],{},"In the next article, we will see how you can access a Kubernetes cluster using GitLab CI/CD and why you might want to do it even if you aim for GitOps.",[12,894,895],{},[15,896,897,900],{},[19,898,899],{"href":21},"Click here"," for the next tutorial.",[902,903,904],"style",{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}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 .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}",{"title":248,"searchDepth":297,"depth":297,"links":906},[907,908,909,914,915,918,919,920,921],{"id":30,"depth":297,"text":31},{"id":37,"depth":297,"text":38},{"id":71,"depth":297,"text":72,"children":910},[911,912,913],{"id":90,"depth":314,"text":91},{"id":122,"depth":314,"text":123},{"id":135,"depth":314,"text":136},{"id":186,"depth":297,"text":187},{"id":234,"depth":297,"text":235,"children":916},[917],{"id":273,"depth":314,"text":274},{"id":332,"depth":297,"text":333},{"id":683,"depth":297,"text":684},{"id":881,"depth":297,"text":882},{"id":888,"depth":297,"text":889},"engineering","2021-12-02","In part four of our GitOps series, we learn how to manage secrets with the GitLab Agent for Kubernetes.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663397/Blog/Hero%20Images/logoforblogpost.jpg",{},"/en-us/blog/gitops-with-gitlab-secrets-management",{"title":5,"description":924,"ogTitle":5,"ogDescription":924,"noIndex":927,"ogImage":928,"ogUrl":932,"ogSiteName":933,"ogType":934,"canonicalUrls":932},"https://about.gitlab.com/blog/gitops-with-gitlab-secrets-management","https://about.gitlab.com","article","gitops-with-gitlab-secrets-management","en-us/blog/gitops-with-gitlab-secrets-management",[938,939,940],"GitOps","kubernetes","inside GitLab","BlogPost","OFPyabTJawWZyBypZFRjJrgR465IdQmjUrqbR-L5dYU",{"logo":944,"freeTrial":949,"sales":954,"login":959,"items":964,"search":1291,"minimal":1322,"duo":1341,"switchNav":1350,"pricingDeployment":1361},{"config":945},{"href":946,"dataGaName":947,"dataGaLocation":948},"/","gitlab logo","header",{"text":950,"config":951},"Get free trial",{"href":952,"dataGaName":953,"dataGaLocation":948},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":955,"config":956},"Request a demo",{"href":957,"dataGaName":958,"dataGaLocation":948},"/sales/?contact-topic=request-demo","sales",{"text":960,"config":961},"Sign in",{"href":962,"dataGaName":963,"dataGaLocation":948},"https://gitlab.com/users/sign_in/","sign in",[965,994,1094,1099,1213,1269],{"text":966,"config":967,"menu":969},"Platform",{"dataNavLevelOne":968},"platform",{"type":970,"columns":971},"cards",[972,978,986],{"title":966,"description":973,"link":974},"The intelligent orchestration platform for DevSecOps",{"text":975,"config":976},"Explore our Platform",{"href":977,"dataGaName":968,"dataGaLocation":948},"/platform/",{"title":979,"description":980,"link":981},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":982,"config":983},"Meet GitLab Duo",{"href":984,"dataGaName":985,"dataGaLocation":948},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":987,"description":988,"link":989},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":990,"config":991},"Learn more",{"href":992,"dataGaName":993,"dataGaLocation":948},"/why-gitlab/","why gitlab",{"text":995,"left":715,"config":996,"menu":998},"Product",{"dataNavLevelOne":997},"solutions",{"type":999,"link":1000,"columns":1004,"feature":1073},"lists",{"text":1001,"config":1002},"View all Solutions",{"href":1003,"dataGaName":997,"dataGaLocation":948},"/solutions/",[1005,1029,1052],{"title":1006,"description":1007,"link":1008,"items":1013},"Automation","CI/CD and automation to accelerate deployment",{"config":1009},{"icon":1010,"href":1011,"dataGaName":1012,"dataGaLocation":948},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1014,1018,1021,1025],{"text":1015,"config":1016},"CI/CD",{"href":1017,"dataGaLocation":948,"dataGaName":1015},"/solutions/continuous-integration/",{"text":979,"config":1019},{"href":984,"dataGaLocation":948,"dataGaName":1020},"gitlab duo agent platform - product menu",{"text":1022,"config":1023},"Source Code Management",{"href":1024,"dataGaLocation":948,"dataGaName":1022},"/solutions/source-code-management/",{"text":1026,"config":1027},"Automated Software Delivery",{"href":1011,"dataGaLocation":948,"dataGaName":1028},"Automated software delivery",{"title":1030,"description":1031,"link":1032,"items":1037},"Security","Deliver code faster without compromising security",{"config":1033},{"href":1034,"dataGaName":1035,"dataGaLocation":948,"icon":1036},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1038,1042,1047],{"text":1039,"config":1040},"Application Security Testing",{"href":1034,"dataGaName":1041,"dataGaLocation":948},"Application security testing",{"text":1043,"config":1044},"Software Supply Chain Security",{"href":1045,"dataGaLocation":948,"dataGaName":1046},"/solutions/supply-chain/","Software supply chain security",{"text":1048,"config":1049},"Software Compliance",{"href":1050,"dataGaName":1051,"dataGaLocation":948},"/solutions/software-compliance/","software compliance",{"title":1053,"link":1054,"items":1059},"Measurement",{"config":1055},{"icon":1056,"href":1057,"dataGaName":1058,"dataGaLocation":948},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1060,1064,1068],{"text":1061,"config":1062},"Visibility & Measurement",{"href":1057,"dataGaLocation":948,"dataGaName":1063},"Visibility and Measurement",{"text":1065,"config":1066},"Value Stream Management",{"href":1067,"dataGaLocation":948,"dataGaName":1065},"/solutions/value-stream-management/",{"text":1069,"config":1070},"Analytics & Insights",{"href":1071,"dataGaLocation":948,"dataGaName":1072},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1074,"type":999,"items":1075},"GitLab for",[1076,1082,1088],{"text":1077,"config":1078},"Enterprise",{"icon":1079,"href":1080,"dataGaLocation":948,"dataGaName":1081},"Building","/enterprise/","enterprise",{"text":1083,"config":1084},"Small Business",{"icon":1085,"href":1086,"dataGaLocation":948,"dataGaName":1087},"Work","/small-business/","small business",{"text":1089,"config":1090},"Public Sector",{"icon":1091,"href":1092,"dataGaLocation":948,"dataGaName":1093},"Organization","/solutions/public-sector/","public sector",{"text":1095,"config":1096},"Pricing",{"href":1097,"dataGaName":1098,"dataGaLocation":948,"dataNavLevelOne":1098},"/pricing/","pricing",{"text":1100,"config":1101,"menu":1103},"Resources",{"dataNavLevelOne":1102},"resources",{"type":999,"link":1104,"columns":1108,"feature":1202},{"text":1105,"config":1106},"View all resources",{"href":1107,"dataGaName":1102,"dataGaLocation":948},"/resources/",[1109,1142,1169],{"title":1110,"items":1111},"Getting started",[1112,1117,1122,1127,1132,1137],{"text":1113,"config":1114},"Install",{"href":1115,"dataGaName":1116,"dataGaLocation":948},"/install/","install",{"text":1118,"config":1119},"Quick start guides",{"href":1120,"dataGaName":1121,"dataGaLocation":948},"/get-started/","quick setup checklists",{"text":1123,"config":1124},"Learn",{"href":1125,"dataGaLocation":948,"dataGaName":1126},"https://university.gitlab.com/","learn",{"text":1128,"config":1129},"Product documentation",{"href":1130,"dataGaName":1131,"dataGaLocation":948},"https://docs.gitlab.com/","product documentation",{"text":1133,"config":1134},"Best practice videos",{"href":1135,"dataGaName":1136,"dataGaLocation":948},"/getting-started-videos/","best practice videos",{"text":1138,"config":1139},"Integrations",{"href":1140,"dataGaName":1141,"dataGaLocation":948},"/integrations/","integrations",{"title":1143,"items":1144},"Discover",[1145,1150,1155,1160,1164],{"text":1146,"config":1147},"Customer success stories",{"href":1148,"dataGaName":1149,"dataGaLocation":948},"/customers/","customer success stories",{"text":1151,"config":1152},"Blog",{"href":1153,"dataGaName":1154,"dataGaLocation":948},"/blog/","blog",{"text":1156,"config":1157},"Demo Hub",{"href":1158,"dataGaName":1159,"dataGaLocation":948},"/demo-hub/","demo hub",{"text":1161,"config":1162},"The Source",{"href":1163,"dataGaName":1154,"dataGaLocation":948},"/the-source/",{"text":1165,"config":1166},"Remote",{"href":1167,"dataGaName":1168,"dataGaLocation":948},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1170,"items":1171},"Connect",[1172,1177,1182,1187,1192,1197],{"text":1173,"config":1174},"GitLab Services",{"href":1175,"dataGaName":1176,"dataGaLocation":948},"/services/","services",{"text":1178,"config":1179},"Contribute",{"href":1180,"dataGaName":1181,"dataGaLocation":948},"https://contributors.gitlab.com","contribute",{"text":1183,"config":1184},"Community",{"href":1185,"dataGaName":1186,"dataGaLocation":948},"/community/","community",{"text":1188,"config":1189},"Forum",{"href":1190,"dataGaName":1191,"dataGaLocation":948},"https://forum.gitlab.com/","forum",{"text":1193,"config":1194},"Events",{"href":1195,"dataGaName":1196,"dataGaLocation":948},"/events/","events",{"text":1198,"config":1199},"Partners",{"href":1200,"dataGaName":1201,"dataGaLocation":948},"/partners/","partners",{"config":1203,"title":1206,"text":1207,"link":1208},{"background":1204,"textColor":1205},"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":1209,"config":1210},"Read the latest",{"href":1211,"dataGaName":1212,"dataGaLocation":948},"/whats-new/","whats new",{"text":1214,"config":1215,"menu":1217},"Company",{"dataNavLevelOne":1216},"company",{"type":999,"columns":1218},[1219],{"items":1220},[1221,1226,1232,1234,1239,1244,1249,1254,1259,1264],{"text":1222,"config":1223},"About",{"href":1224,"dataGaName":1225,"dataGaLocation":948},"/company/","about",{"text":1227,"config":1228,"footerGa":1231},"Jobs",{"href":1229,"dataGaName":1230,"dataGaLocation":948},"/jobs/","jobs",{"dataGaName":1230},{"text":1193,"config":1233},{"href":1195,"dataGaName":1196,"dataGaLocation":948},{"text":1235,"config":1236},"Leadership",{"href":1237,"dataGaName":1238,"dataGaLocation":948},"/company/team/e-group/","leadership",{"text":1240,"config":1241},"Handbook",{"href":1242,"dataGaName":1243,"dataGaLocation":948},"https://handbook.gitlab.com/","handbook",{"text":1245,"config":1246},"Investor relations",{"href":1247,"dataGaName":1248,"dataGaLocation":948},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1250,"config":1251},"Trust Center",{"href":1252,"dataGaName":1253,"dataGaLocation":948},"/security/","trust center",{"text":1255,"config":1256},"AI Transparency Center",{"href":1257,"dataGaName":1258,"dataGaLocation":948},"/ai-transparency-center/","ai transparency center",{"text":1260,"config":1261},"Newsletter",{"href":1262,"dataGaName":1263,"dataGaLocation":948},"/company/contact/#contact-forms","newsletter",{"text":1265,"config":1266},"Press",{"href":1267,"dataGaName":1268,"dataGaLocation":948},"/press/","press",{"text":1270,"config":1271,"menu":1272},"Contact us",{"dataNavLevelOne":1216},{"type":999,"columns":1273},[1274],{"items":1275},[1276,1281,1286],{"text":1277,"config":1278},"Talk to sales",{"href":1279,"dataGaName":1280,"dataGaLocation":948},"/sales/","talk to sales",{"text":1282,"config":1283},"Support portal",{"href":1284,"dataGaName":1285,"dataGaLocation":948},"https://support.gitlab.com/hc/en-us","support portal",{"text":1287,"config":1288},"Customer portal",{"href":1289,"dataGaName":1290,"dataGaLocation":948},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1292,"login":1293,"suggestions":1300},"Close",{"text":1294,"link":1295},"To search repositories and projects, login to",{"text":1296,"config":1297},"gitlab.com",{"href":962,"dataGaName":1298,"dataGaLocation":1299},"search login","search",{"text":1301,"default":1302},"Suggestions",[1303,1305,1309,1311,1315,1319],{"text":979,"config":1304},{"href":984,"dataGaName":979,"dataGaLocation":1299},{"text":1306,"config":1307},"Code Suggestions (AI)",{"href":1308,"dataGaName":1306,"dataGaLocation":1299},"/solutions/code-suggestions/",{"text":1015,"config":1310},{"href":1017,"dataGaName":1015,"dataGaLocation":1299},{"text":1312,"config":1313},"GitLab on AWS",{"href":1314,"dataGaName":1312,"dataGaLocation":1299},"/partners/technology-partners/aws/",{"text":1316,"config":1317},"GitLab on Google Cloud",{"href":1318,"dataGaName":1316,"dataGaLocation":1299},"/partners/technology-partners/google-cloud-platform/",{"text":1320,"config":1321},"Why GitLab?",{"href":992,"dataGaName":1320,"dataGaLocation":1299},{"freeTrial":1323,"mobileIcon":1328,"desktopIcon":1333,"secondaryButton":1336},{"text":1324,"config":1325},"Start free trial",{"href":1326,"dataGaName":953,"dataGaLocation":1327},"https://gitlab.com/-/trials/new/","nav",{"altText":1329,"config":1330},"Gitlab Icon",{"src":1331,"dataGaName":1332,"dataGaLocation":1327},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1329,"config":1334},{"src":1335,"dataGaName":1332,"dataGaLocation":1327},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1337,"config":1338},"Get Started",{"href":1339,"dataGaName":1340,"dataGaLocation":1327},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1342,"mobileIcon":1346,"desktopIcon":1348},{"text":1343,"config":1344},"Learn more about GitLab Duo",{"href":984,"dataGaName":1345,"dataGaLocation":1327},"gitlab duo",{"altText":1329,"config":1347},{"src":1331,"dataGaName":1332,"dataGaLocation":1327},{"altText":1329,"config":1349},{"src":1335,"dataGaName":1332,"dataGaLocation":1327},{"button":1351,"mobileIcon":1356,"desktopIcon":1358},{"text":1352,"config":1353},"/switch",{"href":1354,"dataGaName":1355,"dataGaLocation":1327},"#contact","switch",{"altText":1329,"config":1357},{"src":1331,"dataGaName":1332,"dataGaLocation":1327},{"altText":1329,"config":1359},{"src":1360,"dataGaName":1332,"dataGaLocation":1327},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1362,"mobileIcon":1367,"desktopIcon":1369},{"text":1363,"config":1364},"Back to pricing",{"href":1097,"dataGaName":1365,"dataGaLocation":1327,"icon":1366},"back to pricing","GoBack",{"altText":1329,"config":1368},{"src":1331,"dataGaName":1332,"dataGaLocation":1327},{"altText":1329,"config":1370},{"src":1335,"dataGaName":1332,"dataGaLocation":1327},{"title":1372,"titleMobile":1373,"button":1374,"config":1379},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":990,"config":1375},{"href":1376,"dataGaName":1377,"dataGaLocation":1378},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1380,"disabled":927},"release",{"data":1382},{"text":1383,"source":1384,"edit":1390,"contribute":1395,"config":1400,"items":1405,"minimal":1613},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1385,"config":1386},"View page source",{"href":1387,"dataGaName":1388,"dataGaLocation":1389},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1391,"config":1392},"Edit this page",{"href":1393,"dataGaName":1394,"dataGaLocation":1389},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1396,"config":1397},"Please contribute",{"href":1398,"dataGaName":1399,"dataGaLocation":1389},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1401,"facebook":1402,"youtube":1403,"linkedin":1404},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1406,1453,1505,1549,1581],{"title":1095,"links":1407,"subMenu":1422},[1408,1412,1417],{"text":1409,"config":1410},"View plans",{"href":1097,"dataGaName":1411,"dataGaLocation":1389},"view plans",{"text":1413,"config":1414},"Why Premium?",{"href":1415,"dataGaName":1416,"dataGaLocation":1389},"/pricing/premium/","why premium",{"text":1418,"config":1419},"Why Ultimate?",{"href":1420,"dataGaName":1421,"dataGaLocation":1389},"/pricing/ultimate/","why ultimate",[1423],{"title":1424,"links":1425},"Contact Us",[1426,1429,1431,1433,1438,1443,1448],{"text":1427,"config":1428},"Contact sales",{"href":1279,"dataGaName":958,"dataGaLocation":1389},{"text":1282,"config":1430},{"href":1284,"dataGaName":1285,"dataGaLocation":1389},{"text":1287,"config":1432},{"href":1289,"dataGaName":1290,"dataGaLocation":1389},{"text":1434,"config":1435},"Status",{"href":1436,"dataGaName":1437,"dataGaLocation":1389},"https://status.gitlab.com/","status",{"text":1439,"config":1440},"Terms of use",{"href":1441,"dataGaName":1442,"dataGaLocation":1389},"/terms/","terms of use",{"text":1444,"config":1445},"Privacy statement",{"href":1446,"dataGaName":1447,"dataGaLocation":1389},"/privacy/","privacy statement",{"text":1449,"config":1450},"Cookie preferences",{"dataGaName":1451,"dataGaLocation":1389,"id":1452,"isOneTrustButton":715},"cookie preferences","ot-sdk-btn",{"title":995,"links":1454,"subMenu":1463},[1455,1459],{"text":1456,"config":1457},"DevSecOps platform",{"href":977,"dataGaName":1458,"dataGaLocation":1389},"devsecops platform",{"text":1460,"config":1461},"AI-Assisted Development",{"href":984,"dataGaName":1462,"dataGaLocation":1389},"ai-assisted development",[1464],{"title":1465,"links":1466},"Topics",[1467,1472,1476,1480,1485,1490,1495,1500],{"text":1468,"config":1469},"CICD",{"href":1470,"dataGaName":1471,"dataGaLocation":1389},"/topics/ci-cd/","cicd",{"text":938,"config":1473},{"href":1474,"dataGaName":1475,"dataGaLocation":1389},"/topics/gitops/","gitops",{"text":1477,"config":1478},"DevOps",{"href":106,"dataGaName":1479,"dataGaLocation":1389},"devops",{"text":1481,"config":1482},"Version Control",{"href":1483,"dataGaName":1484,"dataGaLocation":1389},"/topics/version-control/","version control",{"text":1486,"config":1487},"DevSecOps",{"href":1488,"dataGaName":1489,"dataGaLocation":1389},"/topics/devsecops/","devsecops",{"text":1491,"config":1492},"Cloud Native",{"href":1493,"dataGaName":1494,"dataGaLocation":1389},"/topics/cloud-native/","cloud native",{"text":1496,"config":1497},"AI for Coding",{"href":1498,"dataGaName":1499,"dataGaLocation":1389},"/topics/devops/ai-for-coding/","ai for coding",{"text":1501,"config":1502},"Agentic AI",{"href":1503,"dataGaName":1504,"dataGaLocation":1389},"/topics/agentic-ai/","agentic ai",{"title":1506,"links":1507},"Solutions",[1508,1510,1512,1517,1521,1524,1528,1531,1533,1536,1539,1544],{"text":1039,"config":1509},{"href":1034,"dataGaName":1039,"dataGaLocation":1389},{"text":1028,"config":1511},{"href":1011,"dataGaName":1012,"dataGaLocation":1389},{"text":1513,"config":1514},"Agile development",{"href":1515,"dataGaName":1516,"dataGaLocation":1389},"/solutions/agile-delivery/","agile delivery",{"text":1518,"config":1519},"SCM",{"href":1024,"dataGaName":1520,"dataGaLocation":1389},"source code management",{"text":1468,"config":1522},{"href":1017,"dataGaName":1523,"dataGaLocation":1389},"continuous integration & delivery",{"text":1525,"config":1526},"Value stream management",{"href":1067,"dataGaName":1527,"dataGaLocation":1389},"value stream management",{"text":938,"config":1529},{"href":1530,"dataGaName":1475,"dataGaLocation":1389},"/solutions/gitops/",{"text":1077,"config":1532},{"href":1080,"dataGaName":1081,"dataGaLocation":1389},{"text":1534,"config":1535},"Small business",{"href":1086,"dataGaName":1087,"dataGaLocation":1389},{"text":1537,"config":1538},"Public sector",{"href":1092,"dataGaName":1093,"dataGaLocation":1389},{"text":1540,"config":1541},"Education",{"href":1542,"dataGaName":1543,"dataGaLocation":1389},"/solutions/education/","education",{"text":1545,"config":1546},"Financial services",{"href":1547,"dataGaName":1548,"dataGaLocation":1389},"/solutions/finance/","financial services",{"title":1100,"links":1550},[1551,1553,1555,1557,1560,1562,1565,1567,1569,1571,1573,1575,1577,1579],{"text":1113,"config":1552},{"href":1115,"dataGaName":1116,"dataGaLocation":1389},{"text":1118,"config":1554},{"href":1120,"dataGaName":1121,"dataGaLocation":1389},{"text":1123,"config":1556},{"href":1125,"dataGaName":1126,"dataGaLocation":1389},{"text":1128,"config":1558},{"href":1130,"dataGaName":1559,"dataGaLocation":1389},"docs",{"text":1151,"config":1561},{"href":1153,"dataGaName":1154,"dataGaLocation":1389},{"text":1563,"config":1564},"What's new",{"href":1211,"dataGaName":1212,"dataGaLocation":1389},{"text":1146,"config":1566},{"href":1148,"dataGaName":1149,"dataGaLocation":1389},{"text":1165,"config":1568},{"href":1167,"dataGaName":1168,"dataGaLocation":1389},{"text":1173,"config":1570},{"href":1175,"dataGaName":1176,"dataGaLocation":1389},{"text":1178,"config":1572},{"href":1180,"dataGaName":1181,"dataGaLocation":1389},{"text":1183,"config":1574},{"href":1185,"dataGaName":1186,"dataGaLocation":1389},{"text":1188,"config":1576},{"href":1190,"dataGaName":1191,"dataGaLocation":1389},{"text":1193,"config":1578},{"href":1195,"dataGaName":1196,"dataGaLocation":1389},{"text":1198,"config":1580},{"href":1200,"dataGaName":1201,"dataGaLocation":1389},{"title":1214,"links":1582},[1583,1585,1587,1589,1591,1593,1597,1602,1604,1606,1608],{"text":1222,"config":1584},{"href":1224,"dataGaName":1216,"dataGaLocation":1389},{"text":1227,"config":1586},{"href":1229,"dataGaName":1230,"dataGaLocation":1389},{"text":1235,"config":1588},{"href":1237,"dataGaName":1238,"dataGaLocation":1389},{"text":1240,"config":1590},{"href":1242,"dataGaName":1243,"dataGaLocation":1389},{"text":1245,"config":1592},{"href":1247,"dataGaName":1248,"dataGaLocation":1389},{"text":1594,"config":1595},"Sustainability",{"href":1596,"dataGaName":1594,"dataGaLocation":1389},"/sustainability/",{"text":1598,"config":1599},"Diversity, inclusion and belonging (DIB)",{"href":1600,"dataGaName":1601,"dataGaLocation":1389},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1250,"config":1603},{"href":1252,"dataGaName":1253,"dataGaLocation":1389},{"text":1260,"config":1605},{"href":1262,"dataGaName":1263,"dataGaLocation":1389},{"text":1265,"config":1607},{"href":1267,"dataGaName":1268,"dataGaLocation":1389},{"text":1609,"config":1610},"Modern Slavery Transparency Statement",{"href":1611,"dataGaName":1612,"dataGaLocation":1389},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1614},[1615,1618,1621],{"text":1616,"config":1617},"Terms",{"href":1441,"dataGaName":1442,"dataGaLocation":1389},{"text":1619,"config":1620},"Cookies",{"dataGaName":1451,"dataGaLocation":1389,"id":1452,"isOneTrustButton":715},{"text":1622,"config":1623},"Privacy",{"href":1446,"dataGaName":1447,"dataGaLocation":1389},[1625],{"id":1626,"title":7,"body":926,"config":1627,"content":1629,"description":926,"extension":1633,"meta":1634,"navigation":715,"path":1635,"seo":1636,"stem":1637,"__hash__":1638},"blogAuthors/en-us/blog/authors/viktor-nagy.yml",{"template":1628},"BlogAuthor",{"name":7,"config":1630},{"headshot":1631,"ctfId":1632},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662918/Blog/Author%20Headshots/nagy-headshot.jpg","nagyvgitlab","yml",{},"/en-us/blog/authors/viktor-nagy",{},"en-us/blog/authors/viktor-nagy","rM3QZ5iaPa1fk9rDH9Dq-owlsuuFm699I03jWP1dUY4",[1640,1649,1657],{"title":1641,"description":1642,"heroImage":1643,"category":922,"date":1644,"authors":1645,"slug":1648,"externalUrl":926},"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",[1646,1647],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1650,"description":1651,"heroImage":1652,"category":922,"date":1653,"authors":1654,"slug":1656,"externalUrl":926},"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",[1655],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1658,"description":1659,"heroImage":1660,"category":922,"date":1661,"authors":1662,"slug":1664,"externalUrl":926},"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",[1663],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1666},[1667,1681,1693,1705],{"id":1668,"categories":1669,"header":1671,"text":1672,"button":1673,"image":1678},"ai-modernization",[1670],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1674,"config":1675},"Get your AI maturity score",{"href":1676,"dataGaName":1677,"dataGaLocation":1154},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1679},{"src":1680},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1682,"categories":1683,"header":1685,"text":1672,"button":1686,"image":1690},"devops-modernization",[1684,1489],"product","Are you just managing tools or shipping innovation?",{"text":1687,"config":1688},"Get your DevOps maturity score",{"href":1689,"dataGaName":1677,"dataGaLocation":1154},"/assessments/devops-modernization-assessment/",{"config":1691},{"src":1692},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1694,"categories":1695,"header":1697,"text":1672,"button":1698,"image":1702},"security-modernization",[1696],"security","Are you trading speed for security?",{"text":1699,"config":1700},"Get your security maturity score",{"href":1701,"dataGaName":1677,"dataGaLocation":1154},"/assessments/security-modernization-assessment/",{"config":1703},{"src":1704},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1706,"paths":1707,"header":1710,"text":1711,"button":1712,"image":1717},"github-azure-migration",[1708,1709],"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":1713,"config":1714},"See how GitLab compares to GitHub",{"href":1715,"dataGaName":1716,"dataGaLocation":1154},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1718},{"src":1692},{"header":1720,"blurb":1721,"button":1722,"secondaryButton":1727},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1723,"config":1724},"Get your free trial",{"href":1725,"dataGaName":953,"dataGaLocation":1726},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1427,"config":1728},{"href":1279,"dataGaName":958,"dataGaLocation":1726},1786803751068]