[{"data":1,"prerenderedAt":1425},["ShallowReactive",2],{"/blog/gitlab-as-your-aws-control-plane":3,"navigation-en-us":653,"banner-en-us":1082,"footer-en-us":1092,"blog-post-authors-en-us-Javier Urones Monteserín, Clober|Péter Bozsó":1352,"blog-related-posts-en-us-gitlab-as-your-aws-control-plane":1380,"blog-share-wrapper-en-us":1405,"next-steps-en-us":1415},{"id":4,"title":5,"authors":6,"body":9,"category":633,"date":634,"description":635,"extension":636,"externalUrl":637,"faq":637,"featured":638,"heroImage":639,"meta":640,"navigation":641,"path":642,"seo":643,"slug":645,"stem":646,"tags":647,"template":651,"updatedDate":637,"__hash__":652},"blogPosts/en-us/blog/gitlab-as-your-aws-control-plane.md","From OpenTofu to Argo CD: GitLab as your AWS control plane",[7,8],"Javier Urones Monteserín, Clober","Péter Bozsó",{"type":10,"value":11,"toc":622},"minimark",[12,16,32,37,40,43,66,69,95,98,140,143,146,163,166,192,206,209,212,215,222,260,278,281,292,299,302,314,317,323,326,329,332,335,341,344,347,350,391,394,397,400,403,409,412,415,447,456,459,462,473,476,479,482,485,491,494,518,521,524,544,547,553,556,560,563,578,597,601],[13,14,15],"p",{},"Configuring cloud-based environments is complex, as it requires considering networking, subscriptions, services, and all the components that make up the underlying infrastructure. Manual setup is error-prone, inconsistent, and difficult to reproduce.",[13,17,18,19,25,26,31],{},"This tutorial shows how to set up a fully automated cloud environment using GitLab as the main operations brain. All the cloud infrastructure is defined as code (hosted on GitLab) and deployed on AWS with ",[20,21,24],"a",{"href":22,"rel":23},"https://opentofu.org/",[],"OpenTofu"," through GitLab CI/CD pipelines. On top of this, these pipelines also handle the build and deployment of a real web application, using GitOps practices with ",[20,27,30],{"href":28,"rel":29},"https://argoproj.github.io/cd/",[],"Argo CD",".",[33,34,36],"h2",{"id":35},"why-infrastructure-as-code-and-gitops","Why infrastructure as code and GitOps?",[13,38,39],{},"First, it is important to understand why infrastructure as code (IaC) and GitOps matter, and how GitLab brings these practices together in a single platform.",[13,41,42],{},"IaC ensures environments are:",[44,45,46,54,60],"ul",{},[47,48,49,53],"li",{},[50,51,52],"strong",{},"Reproducible",": The same configuration can be deployed anywhere.",[47,55,56,59],{},[50,57,58],{},"Versioned",": Every change is tracked in a Version Control System (VCS), with Git as the primary choice.",[47,61,62,65],{},[50,63,64],{},"Automated",": No human interaction needed.",[13,67,68],{},"GitOps extends these principles into the application lifecycle. Instead of manually applying changes to Kubernetes clusters (or other infrastructure), the desired state of applications lives in Git. A GitOps operator like Argo CD continuously ensures the cluster reflects what is in the repository. This brings:",[44,70,71,77,83,89],{},[47,72,73,76],{},[50,74,75],{},"Consistency"," between environments",[47,78,79,82],{},[50,80,81],{},"Faster recovery"," with rollbacks that are as simple as reverting a commit",[47,84,85,88],{},[50,86,87],{},"Better collaboration"," because teams can review and approve changes via merge requests",[47,90,91,94],{},[50,92,93],{},"Increased security"," through deployments that are performed without requiring direct access to the cluster by the developers",[13,96,97],{},"GitLab combines all the capabilities required for this approach:",[44,99,100,110,120,130],{},[47,101,102,109],{},[50,103,104],{},[20,105,108],{"href":106,"rel":107},"https://docs.gitlab.com/user/get_started/get_started_managing_code/",[],"Source code management",": Track infrastructure and application code in one place.",[47,111,112,119],{},[50,113,114],{},[20,115,118],{"href":116,"rel":117},"https://docs.gitlab.com/ci/",[],"CI/CD pipelines",": Automate provisioning with OpenTofu and deployments with Kubernetes manifests.",[47,121,122,129],{},[50,123,124],{},[20,125,128],{"href":126,"rel":127},"https://docs.gitlab.com/user/infrastructure/iac/terraform_state/",[],"Terraform states",": Store and manage infrastructure state files securely.",[47,131,132,139],{},[50,133,134],{},[20,135,138],{"href":136,"rel":137},"https://docs.gitlab.com/user/packages/container_registry/",[],"Container Registry",": Build, store, and manage container images next to the code and pipelines.",[13,141,142],{},"With GitLab, everything from provisioning cloud infrastructure to application delivery happens through one platform.",[13,144,145],{},"To follow this tutorial, you will need:",[44,147,148,151,154,157,160],{},[47,149,150],{},"Basic knowledge of GitLab CI/CD pipelines and Git",[47,152,153],{},"Familiarity with iac (Terraform or OpenTofu) and GitOps",[47,155,156],{},"An AWS account",[47,158,159],{},"A Kubernetes cluster (EKS is provisioned in the tutorial)",[47,161,162],{},"Dockerfile for the sample web application",[13,164,165],{},"This tutorial includes instructions to:",[44,167,168,174,180,186],{},[47,169,170],{},[20,171,173],{"href":172},"#provision-a-complete-aws-environment-networking-eks-using-opentofu","Provision a complete AWS environment (networking, EKS) using OpenTofu",[47,175,176],{},[20,177,179],{"href":178},"#configure-kubernetes-tools-argo-cd-certmanager-automatically","Configure Kubernetes tools (Argo CD, CertManager) automatically",[47,181,182],{},[20,183,185],{"href":184},"#deploy-a-sample-web-application-using-gitops-principles-with-argo-cd","Deploy a sample web application using GitOps principles with Argo CD",[47,187,188],{},[20,189,191],{"href":190},"#build-and-package-a-sample-web-application-with-gitlab-cicd","Build and package a sample web application with GitLab CI/CD",[13,193,194,195,200,201,31],{},"Read on to learn how to reproduce this example in your own GitLab environment. You can find the source code of this ",[20,196,199],{"href":197,"rel":198},"https://gitlab.com/gitlab-partners-public/satec/aws-summit-2025-demo",[],"example"," in the ",[20,202,205],{"href":203,"rel":204},"https://gitlab.com/gitlab-partners-public/satec",[],"SATEC Public Demo Group",[33,207,173],{"id":208},"provision-a-complete-aws-environment-networking-eks-using-opentofu",[13,210,211],{},"The first step is to provision the cloud infrastructure with OpenTofu (the open-source Terraform fork). We can declaratively define networking components and create an Amazon EKS cluster.",[13,213,214],{},"To make this process reproducible and secure, we rely on GitLab CI/CD variables instead of hardcoding values. These variables allow us to configure the AWS environment dynamically across pipelines.",[13,216,217,218,221],{},"The following environment variables are required and need to be declared under ",[50,219,220],{},"Settings > CI/CD > Variables"," in the parent group (to be inherited by all projects):",[44,223,224,230,236,242,248,254],{},[47,225,226,229],{},[50,227,228],{},"TF_VAR_region",": AWS region where the infrastructure will be created (e.g., eu-west-1)",[47,231,232,235],{},[50,233,234],{},"TF_VAR_instance_type",": EC2 instance type for worker nodes (e.g., t3.medium)",[47,237,238,241],{},[50,239,240],{},"TF_VAR_instance_count",": Number of worker nodes in the cluster",[47,243,244,247],{},[50,245,246],{},"TF_VAR_cluster_name",": Name of the EKS cluster to provision",[47,249,250,253],{},[50,251,252],{},"AWS_ACCESS_KEY_ID",": AWS access key for authentication",[47,255,256,259],{},[50,257,258],{},"AWS_SECRET_ACCESS_KEY",": AWS secret key for authentication",[13,261,262,263,267,268,271,272,277],{},"All variables are defined as ",[264,265,266],"em",{},"protected"," in GitLab, and sensitive ones such as the AWS secret access key are also ",[264,269,270],{},"masked",", ensuring they are only exposed in secure CI/CD contexts. Security can be further enhanced by following ",[20,273,276],{"href":274,"rel":275},"https://docs.gitlab.com/ci/variables/#cicd-variable-security",[],"this CI/CD variables tutorial",". Separating code from configuration makes the pipeline both flexible and independent of environments.",[13,279,280],{},"Once configured, the OpenTofu pipeline can be executed automatically to:",[44,282,283,286,289],{},[47,284,285],{},"Provision networking resources (VPC, subnets, gateways, routing tables)",[47,287,288],{},"Provision EKS control plane and worker node groups",[47,290,291],{},"Trigger the pipeline to deploy Argo CD and CertManager into the new cluster",[13,293,294],{},[295,296],"img",{"alt":297,"src":298},"How the infrastructure provisioning process works","https://res.cloudinary.com/about-gitlab-com/image/upload/v1786721848/raobe2rbwouolxuakbdl.png",[13,300,301],{},"The diagram above illustrates how the infrastructure provisioning process works.",[303,304,305,308,311],"ol",{},[47,306,307],{},"A GitLab pipeline is triggered from the infrastructure repository, which contains the Terraform/OpenTofu configuration files.",[47,309,310],{},"GitLab CI/CD executes the OpenTofu commands, using the integrated Terraform state backend to securely manage the state file in GitLab.",[47,312,313],{},"OpenTofu connects to AWS through configured providers to create all required resources: the VPC, subnets, gateways, load balancers, and the Amazon EKS cluster distributed across multiple availability zones.",[13,315,316],{},"At the end of this stage, the AWS environment and Kubernetes cluster are fully provisioned and ready to operate.",[13,318,319],{},[295,320],{"alt":321,"src":322},"AWS environment and Kubernetes cluster fully provisioned","https://res.cloudinary.com/about-gitlab-com/image/upload/v1786721902/z6fbu78rw9xprgkrju9p.png",[13,324,325],{},"The final step of this process (post-deploy) is to trigger a secondary GitLab pipeline (located in a dedicated repository), which is responsible for deploying Argo CD and CertManager automatically into the new EKS cluster using the Helm Provider.",[33,327,179],{"id":328},"configure-kubernetes-tools-argo-cd-certmanager-automatically",[13,330,331],{},"Once the AWS infrastructure and the EKS cluster have been successfully provisioned, the next step is to configure the Kubernetes tools required to operate the environment, which are Argo CD, CertManager, and Ingress NGINX Controller.",[13,333,334],{},"This process is fully automated through a secondary GitLab pipeline hosted in a separate repository.",[13,336,337],{},[295,338],{"alt":339,"src":340},"Secondary GitLab pipeline hosted in a separate repo","https://res.cloudinary.com/about-gitlab-com/image/upload/v1786721969/tgupmzi9q557f0nivgb7.png",[13,342,343],{},"The execution of this second pipeline is triggered automatically from the infrastructure pipeline, using a trigger job once the OpenTofu provisioning stage has completed successfully.",[13,345,346],{},"In practice, this means that the deployment of these core components happens seamlessly as part of the same end-to-end workflow, there are no manual steps required. The deployment itself is handled by OpenTofu using the Helm provider, which allows managing Helm charts declaratively as code through GitLab.",[13,348,349],{},"A simplified workflow looks like this:",[303,351,352,358,381,384],{},[47,353,354,357],{},[50,355,356],{},"The first pipeline"," provides the EKS cluster and triggers the second one via a GitLab trigger job.",[47,359,360,363,364],{},[50,361,362],{},"The second pipeline"," uses OpenTofu with the Helm provider to:",[44,365,366,369,372,375],{},[47,367,368],{},"Download Kubeconfig from the EKS cluster.",[47,370,371],{},"Install Argo CD (for GitOps management).",[47,373,374],{},"Install CertManager (for automated TLS certificate management).",[47,376,377,378],{},"Install Ingress NGINX Controller (for ingress traffic routing). ",[264,379,380],{},"(Note: Ingress NGINX Controller is being deprecated in the Kubernetes ecosystem; for new deployments, it is recommended to consider alternatives such as Traefik or an API gateway-based approach.)",[47,382,383],{},"Each Helm release is defined in the OpenTofu configuration, allowing upgrades or rollbacks through standard infrastructure code changes.",[47,385,386,387,390],{},"Finally, ",[50,388,389],{},"a third pipeline"," is triggered to deploy the sample web application. This pipeline applies to the Argo CD application manifests that define the web app and its associated resources.",[33,392,185],{"id":393},"deploy-a-sample-web-application-using-gitops-principles-with-argo-cd",[13,395,396],{},"Once all the core Kubernetes components (Argo CD, CertManager, and Ingress NGINX Controller) are installed, the final stage of the automation pipeline begins. This step is executed automatically right after the Helm chart installation process is completed.",[13,398,399],{},"A third GitLab pipeline is triggered, responsible for deploying a sample web application into the newly created EKS cluster through Argo CD.",[13,401,402],{},"The diagram below shows the overall process:",[13,404,405],{},[295,406],{"alt":407,"src":408},"GitLab uses the kubeconfig generated by OpenTofu to connect to the cluster and apply the Argo CD application manifests that define the desired state of the web application","https://res.cloudinary.com/about-gitlab-com/image/upload/v1786722029/aw36utqgxlj6ipmw6rgj.png",[13,410,411],{},"In this stage, GitLab uses the kubeconfig generated by OpenTofu to connect to the cluster and apply the Argo CD application manifests that define the desired state of the web application.",[13,413,414],{},"The pipeline:",[44,416,417,423,429,435,441],{},[47,418,419,422],{},[50,420,421],{},"Downloads and updates the kubeconfig"," file to connect to the EKS Cluster.",[47,424,425,428],{},[50,426,427],{},"Updates credentials and repository information"," dynamically using CI/CD variables.",[47,430,431,434],{},[50,432,433],{},"Creates the Kubernetes namespace"," for the application (aws-summit-app).",[47,436,437,440],{},[50,438,439],{},"Applies the Argo CD manifests"," (repository.yaml, application.yaml, cluster-issuer.yaml).",[47,442,443,446],{},[50,444,445],{},"Creates a Container Registry secret"," to allow the application to pull images securely from GitLab using an access token.",[13,448,449,450,455],{},"All these actions are performed automatically through ",[20,451,454],{"href":452,"rel":453},"https://about.gitlab.com/blog/ultimate-guide-to-ci-cd-fundamentals-to-advanced-implementation/",[],"GitLab CI/CD",", with no manual intervention.",[13,457,458],{},"Once the manifests are applied, the Argo CD controller detects them and synchronizes the application state with the repository, deploying the sample web page into the EKS cluster.",[13,460,461],{},"The result is a fully operational Kubernetes environment, where:",[44,463,464,467,470],{},[47,465,466],{},"Infrastructure is provisioned with OpenTofu.",[47,468,469],{},"Cluster tools are installed declaratively with Helm.",[47,471,472],{},"Applications are deployed and managed via GitOps using Argo CD.",[13,474,475],{},"This approach ensures end-to-end automation, traceability, and reproducibility, all managed by GitLab.",[33,477,191],{"id":478},"build-and-package-a-sample-web-application-with-gitlab-cicd",[13,480,481],{},"Before the application is deployed through Argo CD, it must first be built, containerized, and published to the GitLab Container Registry.",[13,483,484],{},"This process is managed through a dedicated CI/CD pipeline and follows a GitOps repository structure, where the source code and Kubernetes manifests are stored in separate repositories.",[13,486,487],{},[295,488],{"alt":489,"src":490},"A dedicated CI/CD pipeline that follows a GitOps repository structure","https://res.cloudinary.com/about-gitlab-com/image/upload/v1786722075/nqscss5qee8sdydrej0d.png",[13,492,493],{},"In this setup, the GitLab group is organized into two main sections:",[44,495,496,507],{},[47,497,498,501,502],{},[50,499,500],{},"Apps/"," contains the source code repositories for the applications.",[44,503,504],{},[47,505,506],{},"Example: aws-summit-app/web holds the source code of the sample web page.",[47,508,509,512,513],{},[50,510,511],{},"Deployments/","  contains the repositories with Kubernetes manifests for each application.",[44,514,515],{},[47,516,517],{},"Example: aws-summit-app/web within Deployments defines the Kubernetes manifests to deploy the web page (deployment.yaml, ingress.yaml, service.yaml, etc.).",[13,519,520],{},"This separation enables a clean GitOps workflow because application code and deployment configurations are independent but remain synchronized through automation.",[13,522,523],{},"The CI/CD pipeline defined in the application repository automates the following tasks:",[44,525,526,532,538],{},[47,527,528,531],{},[50,529,530],{},"Build and package:"," The pipeline compiles the source code and builds the Docker image using the provided Dockerfile.",[47,533,534,537],{},[50,535,536],{},"Publish to the GitLab Container Registry:"," The image is automatically tagged and pushed to the integrated GitLab Container Registry.",[47,539,540,543],{},[50,541,542],{},"Update deployment manifests:"," Once the image has been published, the pipeline executes a job that updates the image reference inside the corresponding deployment repository (under Deployments/aws-summit-app/web).",[13,545,546],{},"These are performed automatically by committing the new image tag or creating a merge request.",[13,548,549],{},[295,550],{"alt":551,"src":552},"Committing the new image tag or creating a merge request","https://res.cloudinary.com/about-gitlab-com/image/upload/v1786722113/zdh3bk63swvxibhaw5m9.png",[13,554,555],{},"Once the commit or merge request is created, Argo CD automatically detects the change in the deployment repository and synchronizes the updated manifests with the Kubernetes cluster, ensuring that the new application version is deployed without any manual intervention.",[33,557,559],{"id":558},"summary","Summary",[13,561,562],{},"This tutorial demonstrated how to build a fully automated cloud environment with GitLab as the central hub, achieving the goals we set out at the beginning: infrastructure that is reproducible, versioned, and automated. By combining OpenTofu for infrastructure provisioning, GitLab CI/CD for pipeline orchestration, and Argo CD for GitOps-based application delivery, teams can manage the entire lifecycle — from cloud resources to running applications — through a single platform.",[13,564,565,566,571,572,577],{},"As a GitLab partner with deep expertise in cloud infrastructure and DevSecOps practices, ",[20,567,570],{"href":568,"rel":569},"https://www.clober.tech/",[],"Clober"," (",[20,573,576],{"href":574,"rel":575},"https://www.satec.es/en",[],"SATEC"," group) can help organizations implement similar automated environments tailored to their specific needs.",[13,579,580],{},[264,581,582,583,588,589,592,593,596],{},"Note: This blog post is based on a live demo originally presented at ",[20,584,587],{"href":585,"rel":586},"https://aws.amazon.com/es/events/summits/madrid/",[],"AWS Summit Madrid"," 2025 by the ",[20,590,570],{"href":568,"rel":591},[]," DevSecOps team (",[20,594,576],{"href":574,"rel":595},[]," group).",[33,598,600],{"id":599},"resources","Resources",[44,602,603,610,616],{},[47,604,605],{},[20,606,609],{"href":607,"rel":608},"https://docs.gitlab.com/ci/components/",[],"GitLab CI/CD components",[47,611,612],{},[20,613,615],{"href":136,"rel":614},[],"GitLab Container Registry",[47,617,618],{},[20,619,621],{"href":126,"rel":620},[],"GitLab-managed Terraform state management",{"title":623,"searchDepth":624,"depth":624,"links":625},"",2,[626,627,628,629,630,631,632],{"id":35,"depth":624,"text":36},{"id":208,"depth":624,"text":173},{"id":328,"depth":624,"text":179},{"id":393,"depth":624,"text":185},{"id":478,"depth":624,"text":191},{"id":558,"depth":624,"text":559},{"id":599,"depth":624,"text":600},"engineering","2026-08-18","Automate AWS infrastructure and app delivery end to end: OpenTofu provisions EKS, GitLab CI/CD builds and packages, Argo CD deploys via GitOps.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773865762/yti4ngyppos6amxsv0dj.png",{},true,"/en-us/blog/gitlab-as-your-aws-control-plane",{"config":644,"title":5,"description":635},{"noIndex":638},"gitlab-as-your-aws-control-plane","en-us/blog/gitlab-as-your-aws-control-plane",[648,649,650],"AWS","GitOps","partners","BlogPost","N5XmhW0jsQPCkBwdkuarZ_WVFme16tiz9qrerkZuRKE",{"logo":654,"freeTrial":659,"sales":664,"login":669,"items":674,"search":1002,"minimal":1033,"duo":1052,"switchNav":1061,"pricingDeployment":1072},{"config":655},{"href":656,"dataGaName":657,"dataGaLocation":658},"/","gitlab logo","header",{"text":660,"config":661},"Get free trial",{"href":662,"dataGaName":663,"dataGaLocation":658},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":665,"config":666},"Request a demo",{"href":667,"dataGaName":668,"dataGaLocation":658},"/request-a-demo/","sales",{"text":670,"config":671},"Sign in",{"href":672,"dataGaName":673,"dataGaLocation":658},"https://gitlab.com/users/sign_in/","sign in",[675,761,849,854,926,980],{"text":676,"left":641,"config":677,"menu":679},"Platform",{"dataNavLevelOne":678},"platform",{"type":680,"link":681,"columns":685,"feature":750},"lists",{"text":682,"config":683},"Explore the Platform",{"href":684,"dataGaName":678,"dataGaLocation":658},"/platform/",[686,709,732],{"title":687,"items":688},"Execution & Workflows",[689,694,699,704],{"text":690,"config":691},"CI/CD",{"href":692,"dataGaLocation":658,"dataGaName":693},"/solutions/continuous-integration/","ci/cd",{"text":695,"config":696},"Source Code Management",{"href":697,"dataGaLocation":658,"dataGaName":698},"/solutions/source-code-management/","source code management",{"text":700,"config":701},"Agile Delivery",{"href":702,"dataGaLocation":658,"dataGaName":703},"/solutions/agile-delivery/","agile delivery",{"text":705,"config":706},"Artifact Management",{"href":707,"dataGaLocation":658,"dataGaName":708},"/artifact-central/","artifact management",{"title":710,"items":711},"Security & Governance",[712,717,722,727],{"text":713,"config":714},"Application Security Testing",{"href":715,"dataGaLocation":658,"dataGaName":716},"/solutions/application-security-testing/","application security testing",{"text":718,"config":719},"Governance & Compliance",{"href":720,"dataGaLocation":658,"dataGaName":721},"/solutions/software-compliance/","governance and compliance",{"text":723,"config":724},"Secrets Management",{"href":725,"dataGaLocation":658,"dataGaName":726},"/gitlab-secrets-manager/","secrets management",{"text":728,"config":729},"Supply Chain Security",{"href":730,"dataGaLocation":658,"dataGaName":731},"/solutions/supply-chain/","supply chain security",{"title":733,"items":734},"Context & AI",[735,740,745],{"text":736,"config":737},"Agentic Orchestration",{"href":738,"dataGaLocation":658,"dataGaName":739},"/gitlab-duo-agent-platform/","agentic orchestration",{"text":741,"config":742},"Context Graph",{"href":743,"dataGaLocation":658,"dataGaName":744},"/gitlab-orbit/","context graph",{"text":746,"config":747},"Visibility & Measurement",{"href":748,"dataGaLocation":658,"dataGaName":749},"/solutions/visibility-measurement/","visibility and measurement",{"config":751,"title":754,"text":755,"link":756},{"background":752,"textColor":753},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1790185102/o7dn32anqcb6z8dgd3as.jpg')","#000","Why GitLab","One platform for speed with control across your software lifecycle.",{"text":757,"config":758},"Learn more",{"href":759,"dataGaName":760,"dataGaLocation":658},"/why-gitlab/","why gitlab",{"text":762,"left":641,"config":763,"menu":765},"Solutions",{"dataNavLevelOne":764},"solutions",{"type":680,"link":766,"columns":770,"feature":840},{"text":767,"config":768},"View all Solutions",{"href":769,"dataGaName":764,"dataGaLocation":658},"/solutions/",[771,789,807],{"title":772,"items":773},"Outcomes",[774,779,784],{"text":775,"config":776},"DevOps Modernization",{"href":777,"dataGaLocation":658,"dataGaName":778},"/assessments/devops-modernization-assessment/","devops modernization",{"text":780,"config":781},"Security Modernization",{"href":782,"dataGaLocation":658,"dataGaName":783},"/assessments/security-modernization-assessment/","security modernization",{"text":785,"config":786},"AI Modernization",{"href":787,"dataGaLocation":658,"dataGaName":788},"/assessments/ai-modernization-assessment/","ai modernization",{"title":790,"items":791},"By size",[792,797,802],{"text":793,"config":794},"Enterprise",{"href":795,"dataGaLocation":658,"dataGaName":796},"/enterprise/","enterprise",{"text":798,"config":799},"Small Business",{"href":800,"dataGaLocation":658,"dataGaName":801},"/small-business/","small business",{"text":803,"config":804},"Startups",{"href":805,"dataGaLocation":658,"dataGaName":806},"/solutions/startups/","startups",{"title":808,"items":809},"Industries",[810,815,820,825,830,835],{"text":811,"config":812},"Financial Services",{"href":813,"dataGaLocation":658,"dataGaName":814},"/solutions/finance/","financial services",{"text":816,"config":817},"Public Sector",{"href":818,"dataGaLocation":658,"dataGaName":819},"/solutions/public-sector/","public sector",{"text":821,"config":822},"Telecommunications",{"href":823,"dataGaLocation":658,"dataGaName":824},"/solutions/telecommunications/","telecommunications",{"text":826,"config":827},"Automotive",{"href":828,"dataGaLocation":658,"dataGaName":829},"/solutions/automotive/","automotive",{"text":831,"config":832},"Education",{"href":833,"dataGaLocation":658,"dataGaName":834},"/solutions/education/","education",{"text":836,"config":837},"Aerospace",{"href":838,"dataGaLocation":658,"dataGaName":839},"/solutions/aerospace/","aerospace",{"config":841,"title":842,"text":843,"link":844},{"background":752,"textColor":753},"GitLab Security Standard","Learn how to harden your software factory and let AI agents earn autonomy, without trading away security.",{"text":845,"config":846},"Explore the standard",{"href":847,"dataGaName":848,"dataGaLocation":658},"/gitlab-security-standard/","gitlab security standard",{"text":850,"config":851},"Pricing",{"href":852,"dataGaName":853,"dataGaLocation":658,"dataNavLevelOne":853},"/pricing/","pricing",{"text":600,"config":855,"menu":856},{"dataNavLevelOne":599},{"type":680,"link":857,"columns":861,"feature":917},{"text":858,"config":859},"View all resources",{"href":860,"dataGaName":599,"dataGaLocation":658},"/resources/",[862,890],{"title":863,"items":864},"Discover",[865,870,875,880,885],{"text":866,"config":867},"Docs",{"href":868,"dataGaName":869,"dataGaLocation":658},"https://docs.gitlab.com/","docs",{"text":871,"config":872},"University",{"href":873,"dataGaName":874,"dataGaLocation":658},"https://university.gitlab.com/","university",{"text":876,"config":877},"Demo Series",{"href":878,"dataGaName":879,"dataGaLocation":658},"/gitlab-technical-demo-series/","demo series",{"text":881,"config":882},"Demo Hub",{"href":883,"dataGaName":884,"dataGaLocation":658},"/demo-hub/","demo hub",{"text":886,"config":887},"Services",{"href":888,"dataGaName":889,"dataGaLocation":658},"/services/","services",{"title":891,"items":892},"Connect",[893,898,903,908,912],{"text":894,"config":895},"Blog",{"href":896,"dataGaName":897,"dataGaLocation":658},"/blog/","blog",{"text":899,"config":900},"Community",{"href":901,"dataGaName":902,"dataGaLocation":658},"/community/","community",{"text":904,"config":905},"Customers",{"href":906,"dataGaName":907,"dataGaLocation":658},"/customers/","customers",{"text":909,"config":910},"Partners",{"href":911,"dataGaName":650,"dataGaLocation":658},"/partners/",{"text":913,"config":914},"Events",{"href":915,"dataGaName":916,"dataGaLocation":658},"/events/","events",{"config":918,"title":919,"text":920,"link":921},{"background":752,"textColor":753},"What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":922,"config":923},"Read the latest",{"href":924,"dataGaName":925,"dataGaLocation":658},"/whats-new/","whats new",{"text":927,"config":928,"menu":930},"Company",{"dataNavLevelOne":929},"company",{"type":680,"columns":931},[932],{"items":933},[934,939,945,950,955,960,965,970,975],{"text":935,"config":936},"About",{"href":937,"dataGaName":938,"dataGaLocation":658},"/company/","about",{"text":940,"config":941,"footerGa":944},"Jobs",{"href":942,"dataGaName":943,"dataGaLocation":658},"/jobs/","jobs",{"dataGaName":943},{"text":946,"config":947},"Press",{"href":948,"dataGaName":949,"dataGaLocation":658},"/press/","press",{"text":951,"config":952},"Handbook",{"href":953,"dataGaName":954,"dataGaLocation":658},"https://handbook.gitlab.com/","handbook",{"text":956,"config":957},"Leadership",{"href":958,"dataGaName":959,"dataGaLocation":658},"/company/team/e-group/","leadership",{"text":961,"config":962},"Investor relations",{"href":963,"dataGaName":964,"dataGaLocation":658},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":966,"config":967},"Trust Center",{"href":968,"dataGaName":969,"dataGaLocation":658},"/security/","trust center",{"text":971,"config":972},"AI Transparency Center",{"href":973,"dataGaName":974,"dataGaLocation":658},"/ai-transparency-center/","ai transparency center",{"text":976,"config":977},"Newsletter",{"href":978,"dataGaName":979,"dataGaLocation":658},"/company/contact/#contact-forms","newsletter",{"text":981,"config":982,"menu":983},"Contact us",{"dataNavLevelOne":929},{"type":680,"columns":984},[985],{"items":986},[987,992,997],{"text":988,"config":989},"Talk to sales",{"href":990,"dataGaName":991,"dataGaLocation":658},"/sales/","talk to sales",{"text":993,"config":994},"Support portal",{"href":995,"dataGaName":996,"dataGaLocation":658},"https://support.gitlab.com/hc/en-us","support portal",{"text":998,"config":999},"Customer portal",{"href":1000,"dataGaName":1001,"dataGaLocation":658},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1003,"login":1004,"suggestions":1011},"Close",{"text":1005,"link":1006},"To search repositories and projects, login to",{"text":1007,"config":1008},"gitlab.com",{"href":672,"dataGaName":1009,"dataGaLocation":1010},"search login","search",{"text":1012,"default":1013},"Suggestions",[1014,1017,1020,1022,1026,1030],{"text":1015,"config":1016},"GitLab Duo Agent Platform",{"href":738,"dataGaName":1015,"dataGaLocation":1010},{"text":1018,"config":1019},"Code Suggestions (AI)",{"href":738,"dataGaName":1018,"dataGaLocation":1010},{"text":690,"config":1021},{"href":692,"dataGaName":690,"dataGaLocation":1010},{"text":1023,"config":1024},"GitLab on AWS",{"href":1025,"dataGaName":1023,"dataGaLocation":1010},"/partners/technology-partners/aws/",{"text":1027,"config":1028},"GitLab on Google Cloud",{"href":1029,"dataGaName":1027,"dataGaLocation":1010},"/partners/technology-partners/google-cloud-platform/",{"text":1031,"config":1032},"Why GitLab?",{"href":759,"dataGaName":1031,"dataGaLocation":1010},{"freeTrial":1034,"mobileIcon":1039,"desktopIcon":1044,"secondaryButton":1047},{"text":1035,"config":1036},"Start free trial",{"href":1037,"dataGaName":663,"dataGaLocation":1038},"https://gitlab.com/-/trials/new/","nav",{"altText":1040,"config":1041},"Gitlab Icon",{"src":1042,"dataGaName":1043,"dataGaLocation":1038},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1040,"config":1045},{"src":1046,"dataGaName":1043,"dataGaLocation":1038},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1048,"config":1049},"Get Started",{"href":1050,"dataGaName":1051,"dataGaLocation":1038},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1053,"mobileIcon":1057,"desktopIcon":1059},{"text":1054,"config":1055},"Learn more about GitLab Duo",{"href":738,"dataGaName":1056,"dataGaLocation":1038},"gitlab duo",{"altText":1040,"config":1058},{"src":1042,"dataGaName":1043,"dataGaLocation":1038},{"altText":1040,"config":1060},{"src":1046,"dataGaName":1043,"dataGaLocation":1038},{"button":1062,"mobileIcon":1067,"desktopIcon":1069},{"text":1063,"config":1064},"/switch",{"href":1065,"dataGaName":1066,"dataGaLocation":1038},"#contact","switch",{"altText":1040,"config":1068},{"src":1042,"dataGaName":1043,"dataGaLocation":1038},{"altText":1040,"config":1070},{"src":1071,"dataGaName":1043,"dataGaLocation":1038},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1073,"mobileIcon":1078,"desktopIcon":1080},{"text":1074,"config":1075},"Back to pricing",{"href":852,"dataGaName":1076,"dataGaLocation":1038,"icon":1077},"back to pricing","GoBack",{"altText":1040,"config":1079},{"src":1042,"dataGaName":1043,"dataGaLocation":1038},{"altText":1040,"config":1081},{"src":1046,"dataGaName":1043,"dataGaLocation":1038},{"title":1083,"button":1084,"config":1090},"Ship at agent speed. Prove every step. Transcend is here.",{"text":1085,"config":1086},"Watch now",{"href":1087,"dataGaName":1088,"dataGaLocation":1089},"/events/transcend/virtual/#watch-gitlab-transcend","transcend-october-2026-banner","global-banner",{"layout":1091,"disabled":638},"release",{"data":1093},{"text":1094,"source":1095,"edit":1101,"contribute":1106,"config":1111,"items":1116,"minimal":1341},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1096,"config":1097},"View page source",{"href":1098,"dataGaName":1099,"dataGaLocation":1100},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1102,"config":1103},"Edit this page",{"href":1104,"dataGaName":1105,"dataGaLocation":1100},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1107,"config":1108},"Please contribute",{"href":1109,"dataGaName":1110,"dataGaLocation":1100},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1112,"facebook":1113,"youtube":1114,"linkedin":1115},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1117,1164,1221,1268,1309],{"title":850,"links":1118,"subMenu":1133},[1119,1123,1128],{"text":1120,"config":1121},"View plans",{"href":852,"dataGaName":1122,"dataGaLocation":1100},"view plans",{"text":1124,"config":1125},"Why Premium?",{"href":1126,"dataGaName":1127,"dataGaLocation":1100},"/pricing/premium/","why premium",{"text":1129,"config":1130},"Why Ultimate?",{"href":1131,"dataGaName":1132,"dataGaLocation":1100},"/pricing/ultimate/","why ultimate",[1134],{"title":1135,"links":1136},"Contact Us",[1137,1140,1142,1144,1149,1154,1159],{"text":1138,"config":1139},"Contact sales",{"href":990,"dataGaName":668,"dataGaLocation":1100},{"text":993,"config":1141},{"href":995,"dataGaName":996,"dataGaLocation":1100},{"text":998,"config":1143},{"href":1000,"dataGaName":1001,"dataGaLocation":1100},{"text":1145,"config":1146},"Status",{"href":1147,"dataGaName":1148,"dataGaLocation":1100},"https://status.gitlab.com/","status",{"text":1150,"config":1151},"Terms of use",{"href":1152,"dataGaName":1153,"dataGaLocation":1100},"/terms/","terms of use",{"text":1155,"config":1156},"Privacy statement",{"href":1157,"dataGaName":1158,"dataGaLocation":1100},"/privacy/","privacy statement",{"text":1160,"config":1161},"Cookie preferences",{"dataGaName":1162,"dataGaLocation":1100,"id":1163,"isOneTrustButton":641},"cookie preferences","ot-sdk-btn",{"title":676,"links":1165,"subMenu":1179},[1166,1169,1171,1173,1175,1177],{"text":1167,"config":1168},"Explore the platform",{"href":684,"dataGaName":678,"dataGaLocation":1100},{"text":736,"config":1170},{"href":738,"dataGaName":739,"dataGaLocation":1100},{"text":690,"config":1172},{"href":692,"dataGaName":693,"dataGaLocation":1100},{"text":741,"config":1174},{"href":743,"dataGaName":744,"dataGaLocation":1100},{"text":723,"config":1176},{"href":725,"dataGaName":726,"dataGaLocation":1100},{"text":754,"config":1178},{"href":759,"dataGaName":760,"dataGaLocation":1100},[1180],{"title":1181,"links":1182},"Topics",[1183,1187,1191,1196,1201,1206,1211,1216],{"text":690,"config":1184},{"href":1185,"dataGaName":1186,"dataGaLocation":1100},"/topics/ci-cd/","cicd",{"text":649,"config":1188},{"href":1189,"dataGaName":1190,"dataGaLocation":1100},"/topics/gitops/","gitops",{"text":1192,"config":1193},"DevOps",{"href":1194,"dataGaName":1195,"dataGaLocation":1100},"/topics/devops/","devops",{"text":1197,"config":1198},"Version Control",{"href":1199,"dataGaName":1200,"dataGaLocation":1100},"/topics/version-control/","version control",{"text":1202,"config":1203},"DevSecOps",{"href":1204,"dataGaName":1205,"dataGaLocation":1100},"/topics/devsecops/","devsecops",{"text":1207,"config":1208},"Cloud Native",{"href":1209,"dataGaName":1210,"dataGaLocation":1100},"/topics/cloud-native/","cloud native",{"text":1212,"config":1213},"AI for Coding",{"href":1214,"dataGaName":1215,"dataGaLocation":1100},"/topics/devops/ai-for-coding/","ai for coding",{"text":1217,"config":1218},"Agentic AI",{"href":1219,"dataGaName":1220,"dataGaLocation":1100},"/topics/agentic-ai/","agentic ai",{"title":762,"links":1222},[1223,1226,1229,1232,1235,1238,1240,1242,1244,1246,1248,1251,1253,1256,1260,1264],{"text":1224,"config":1225},"DevOps modernization",{"href":777,"dataGaName":778,"dataGaLocation":1100},{"text":1227,"config":1228},"Security modernization",{"href":782,"dataGaName":783,"dataGaLocation":1100},{"text":1230,"config":1231},"AI modernization",{"href":787,"dataGaName":788,"dataGaLocation":1100},{"text":1233,"config":1234},"Financial services",{"href":813,"dataGaName":814,"dataGaLocation":1100},{"text":1236,"config":1237},"Public sector",{"href":818,"dataGaName":819,"dataGaLocation":1100},{"text":821,"config":1239},{"href":823,"dataGaName":824,"dataGaLocation":1100},{"text":826,"config":1241},{"href":828,"dataGaName":829,"dataGaLocation":1100},{"text":831,"config":1243},{"href":833,"dataGaName":834,"dataGaLocation":1100},{"text":836,"config":1245},{"href":838,"dataGaName":839,"dataGaLocation":1100},{"text":793,"config":1247},{"href":795,"dataGaName":796,"dataGaLocation":1100},{"text":1249,"config":1250},"Small business",{"href":800,"dataGaName":801,"dataGaLocation":1100},{"text":803,"config":1252},{"href":805,"dataGaName":806,"dataGaLocation":1100},{"text":649,"config":1254},{"href":1255,"dataGaName":1190,"dataGaLocation":1100},"/solutions/gitops/",{"text":1257,"config":1258},"Software composition analysis",{"href":730,"dataGaName":1259,"dataGaLocation":1100},"software composition analysis",{"text":1261,"config":1262},"Value stream management",{"href":748,"dataGaName":1263,"dataGaLocation":1100},"value stream management",{"text":1265,"config":1266},"All solutions",{"href":769,"dataGaName":1267,"dataGaLocation":1100},"all solutions",{"title":600,"links":1269},[1270,1275,1280,1282,1284,1286,1288,1290,1292,1294,1296,1298,1300,1302,1305],{"text":1271,"config":1272},"Install",{"href":1273,"dataGaName":1274,"dataGaLocation":1100},"/install/","install",{"text":1276,"config":1277},"Quick start guides",{"href":1278,"dataGaName":1279,"dataGaLocation":1100},"/get-started/","quick setup checklists",{"text":866,"config":1281},{"href":868,"dataGaName":869,"dataGaLocation":1100},{"text":871,"config":1283},{"href":873,"dataGaName":874,"dataGaLocation":1100},{"text":876,"config":1285},{"href":878,"dataGaName":879,"dataGaLocation":1100},{"text":881,"config":1287},{"href":883,"dataGaName":884,"dataGaLocation":1100},{"text":886,"config":1289},{"href":888,"dataGaName":889,"dataGaLocation":1100},{"text":894,"config":1291},{"href":896,"dataGaName":897,"dataGaLocation":1100},{"text":899,"config":1293},{"href":901,"dataGaName":902,"dataGaLocation":1100},{"text":904,"config":1295},{"href":906,"dataGaName":907,"dataGaLocation":1100},{"text":909,"config":1297},{"href":911,"dataGaName":650,"dataGaLocation":1100},{"text":913,"config":1299},{"href":915,"dataGaName":916,"dataGaLocation":1100},{"text":976,"config":1301},{"href":978,"dataGaName":979,"dataGaLocation":1100},{"text":1303,"config":1304},"What's new",{"href":924,"dataGaName":925,"dataGaLocation":1100},{"text":1306,"config":1307},"All resources",{"href":860,"dataGaName":1308,"dataGaLocation":1100},"all resources",{"title":927,"links":1310},[1311,1313,1315,1317,1319,1321,1323,1325,1327,1331,1336],{"text":935,"config":1312},{"href":937,"dataGaName":929,"dataGaLocation":1100},{"text":940,"config":1314},{"href":942,"dataGaName":943,"dataGaLocation":1100},{"text":946,"config":1316},{"href":948,"dataGaName":949,"dataGaLocation":1100},{"text":951,"config":1318},{"href":953,"dataGaName":954,"dataGaLocation":1100},{"text":956,"config":1320},{"href":958,"dataGaName":959,"dataGaLocation":1100},{"text":961,"config":1322},{"href":963,"dataGaName":964,"dataGaLocation":1100},{"text":966,"config":1324},{"href":968,"dataGaName":969,"dataGaLocation":1100},{"text":971,"config":1326},{"href":973,"dataGaName":974,"dataGaLocation":1100},{"text":1328,"config":1329},"Sustainability",{"href":1330,"dataGaName":1328,"dataGaLocation":1100},"/sustainability/",{"text":1332,"config":1333},"Diversity, inclusion and belonging (DIB)",{"href":1334,"dataGaName":1335,"dataGaLocation":1100},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1337,"config":1338},"Modern Slavery Transparency Statement",{"href":1339,"dataGaName":1340,"dataGaLocation":1100},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1342},[1343,1346,1349],{"text":1344,"config":1345},"Terms",{"href":1152,"dataGaName":1153,"dataGaLocation":1100},{"text":1347,"config":1348},"Cookies",{"dataGaName":1162,"dataGaLocation":1100,"id":1163,"isOneTrustButton":641},{"text":1350,"config":1351},"Privacy",{"href":1157,"dataGaName":1158,"dataGaLocation":1100},[1353,1367],{"id":1354,"title":1355,"body":637,"config":1356,"content":1358,"description":637,"extension":1361,"meta":1362,"navigation":641,"path":1363,"seo":1364,"stem":1365,"__hash__":1366},"blogAuthors/en-us/blog/authors/javier-urones-montesern-clober.yml","Javier Urones Montesern Clober",{"template":1357},"BlogAuthor",{"name":7,"config":1359},{"headshot":1360},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1786716301/m4ef0w9sgufwnsnjmip7.jpg","yml",{},"/en-us/blog/authors/javier-urones-montesern-clober",{},"en-us/blog/authors/javier-urones-montesern-clober","nOElEDg3yb2BENyQahBvRi_wTQHyakdSMJfSxFLyLPQ",{"id":1368,"title":1369,"body":637,"config":1370,"content":1371,"description":637,"extension":1361,"meta":1375,"navigation":641,"path":1376,"seo":1377,"stem":1378,"__hash__":1379},"blogAuthors/en-us/blog/authors/pter-bozs.yml","Pter Bozs",{"template":1357},{"name":8,"config":1372},{"headshot":1373,"ctfId":1374},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749666384/Blog/Author%20Headshots/pbozso_headshot.png","4i1NVYip0RqxRnbpZ9deKp",{},"/en-us/blog/authors/pter-bozs",{},"en-us/blog/authors/pter-bozs","M3DsNH5-3AKaaKicmGt_Gqj-Vp7wbz2QaGO8u57CB04",[1381,1389,1397],{"title":1382,"description":1383,"heroImage":1384,"category":633,"date":1385,"authors":1386,"slug":1388,"externalUrl":637},"Two front doors: Module-level access in a Django GRC app","A technical deep-dive on restructuring a Django internal tool to support two distinct GitLab teams: Security Compliance and Internal Audit.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750097663/Blog/Hero%20Images/Blog/Hero%20Images/Workflow%201800x945_2gQoQIbY9NvjLFpXtsxtXy_1750097663612.png","2026-10-05",[1387],"Donovan Felton","module-level-access-in-a-django-grc-app",{"title":1390,"description":1391,"heroImage":1392,"category":633,"date":1393,"authors":1394,"slug":1396,"externalUrl":637},"How GitLab reduced code-per-agentic-flow ratio by 45%","Learn how Flow Registry, a component-based framework that compiles YAML configurations into fully functional LangGraph flows, helped improve scalability and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1774465167/n5hlvrsrheadeccyr1oz.png","2026-09-22",[1395],"Mikolaj Wawrzyniak","how-gitlab-reduced-code-per-agentic-flow-ratio",{"title":1398,"description":1399,"heroImage":1400,"category":633,"date":1401,"authors":1402,"slug":1404,"externalUrl":637},"Co-Create: Building GitLab with our users","How GitLab users collaborated with us to build practical product improvements in the first half of 2026.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099203/Blog/Hero%20Images/Blog/Hero%20Images/blog-image-template-1800x945%20%2820%29_2bJGC5ZP3WheoqzlLT05C5_1750099203484.png","2026-09-10",[1403],"Isa Huerga","co-create-h1-2026",{"header":1406,"text":1407,"button":1411,"disclaimer":1414},"Start your free\n\n30-day GitLab trial\n",[1408,1409,1410],"GitLab Duo Agent Platform access","Try our most advanced features","Automate complex tasks with AI",{"text":660,"config":1412},{"href":1413,"dataGaName":663,"dataGaLocation":897},"https://gitlab.com/-/trials/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/blog/","No credit card required.",{"header":1416,"blurb":1417,"button":1418,"secondaryButton":1423},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1419,"config":1420},"Get your free trial",{"href":1421,"dataGaName":663,"dataGaLocation":1422},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1138,"config":1424},{"href":990,"dataGaName":668,"dataGaLocation":1422},1791944926568]