[{"data":1,"prerenderedAt":1325},["ShallowReactive",2],{"/blog/how-to-automate-creation-of-runners":3,"navigation-en-us":537,"banner-en-us":965,"footer-en-us":975,"blog-post-authors-en-us-Darren Eastman":1220,"blog-related-posts-en-us-how-to-automate-creation-of-runners":1235,"blog-promotions-en-us":1261,"next-steps-en-us":1315},{"id":4,"title":5,"authors":6,"body":8,"category":516,"date":517,"description":518,"extension":519,"externalUrl":520,"faq":520,"featured":521,"heroImage":522,"meta":523,"navigation":319,"path":524,"seo":525,"slug":529,"stem":530,"tags":531,"template":535,"updatedDate":520,"__hash__":536},"blogPosts/en-us/blog/how-to-automate-creation-of-runners.md","How to automate the creation of GitLab Runners",[7],"Darren Eastman",{"type":9,"value":10,"toc":505},"minimark",[11,15,22,27,38,48,51,57,62,70,76,79,83,86,90,100,115,123,128,132,135,191,197,215,226,229,237,241,256,289,294,480,484,487,498,501],[12,13,14],"p",{},"Automating the creation of GitLab Runners is an essential tactic in optimizing the operations and management of a runner fleet. Since announcing the deprecation and planned removal of the legacy runner registration token last year, there have been various questions by customers and the user community regarding the impact of the new workflow on any automation they rely on for creating and registering runners. This is a step-by-step guide for automating runner setup using the new runner creation workflows as depicted in the sequence diagram.",[12,16,17],{},[18,19],"img",{"alt":20,"src":21},"GitLab Runner create - sequence diagram","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397791/blog/Content%20Images/2023-06-19-how-to-automate-creating-runners/runner_create_sequence_diagram.png",[23,24,26],"h2",{"id":25},"new-terminology-and-concepts","New terminology and concepts",[12,28,29,30,34,35,37],{},"Before we dive into the automation steps, let’s first review a few new concepts with the runner creation process and how that differs from the registration token-based method. With the ",[31,32,33],"code",{},"registration token"," method, a ",[31,36,33],{}," is available for the instance, for each group, and for each project. Therefore, in a large GitLab installation, with many groups, sub-groups, and projects, you can have tens of hundreds of registration tokens that any authorized user can use to connect a runner. There are two steps to authorizing a runner (the application that you install on a target computing platform) to a GitLab instance:",[39,40,41,45],"ol",{},[42,43,44],"li",{},"Retrieve a registration token.",[42,46,47],{},"Run the register command in the runner application using the previously retrieved registration token.",[12,49,50],{},"The workflow images below depict the runner setup steps using the registration token compared with the new runner creation process.",[12,52,53],{},[18,54],{"alt":55,"src":56},"GitLab Runner registration workflows","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397791/blog/Content%20Images/2023-06-19-how-to-automate-creating-runners/runner_registration_workflows.png",[58,59,61],"h3",{"id":60},"reusable-runner-configurations","Reusable runner configurations",[12,63,64,65,69],{},"Now, in the registration token method, if you authenticated multiple runners using the same registration token (a valid use case), each runner entity would be visible in the UI in a separate row in the list view. The new creation method introduces the concept of a reusable runner configuration. For example, if you have to deploy multiple runners at the instance level, each with the same configuration (executor type, tags, etc.), you simply create a runner and configuration ",[66,67,68],"strong",{},"once",", then register each individual runner with the same authentication token that you retrieved from the first runner creation. Each of these runners is now displayed in the UI in a nested hierarchy.",[12,71,72],{},[18,73],{"alt":74,"src":75},"Runner detailed view with shared configurations","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397791/blog/Content%20Images/2023-06-19-how-to-automate-creating-runners/runner_detail_shared_configs.png",[12,77,78],{},"We heard from many of you that your Runners view was cluttered because each runner created received its own row in the table, even if they were the exact same configuration as 100 others. With this change, our intent is to ensure that you have the flexibility you need to configure a runner fleet at scale while ensuring that you can still easily understand and manage the fleet in the GitLab Runners view. We understand that this is a paradigm shift that may take some getting used to.",[23,80,82],{"id":81},"automation-steps-for-creating-a-runner","Automation steps for creating a runner",[12,84,85],{},"Here are the automation steps to create a runner.",[58,87,89],{"id":88},"step-1-create-an-access-token","Step 1: Create an access token",[12,91,92,93,99],{},"You will first need to create an access token. A ",[94,95,98],"a",{"href":96,"rel":97},"https://docs.gitlab.com/user/profile/personal_access_tokens/",[],"personal access token"," for an administrator account will allow you to create runners at the instance, group, and project levels.",[12,101,102,103,106,107,110,111,114],{},"If you only need to create a group or project runner, then it is best to use a group access token or project access token, respectively. For a group or project, navigate to ",[31,104,105],{},"Settings / Access Tokens"," and create a token. You must specify a name, the token expiration date, role, and scope. For the role, select ",[31,108,109],{},"Owner","; for the scopes, select ",[31,112,113],{},"create_runner",".",[12,116,117,118,114],{},"Note: The access token is only visible once in the UI. You will need to store this token in a secure location - for example, a secrets management solution such as Hashicorp Vault or the ",[94,119,122],{"href":120,"rel":121},"https://docs.keeper.io/secrets-manager/secrets-manager/integrations/terraform",[],"Keeper Secrets Manager Terraform plugin",[12,124,125],{},[18,126],{"alt":55,"src":127},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1782397791/blog/Content%20Images/2023-06-19-how-to-automate-creating-runners/project_access_token.png",[58,129,131],{"id":130},"step-2-use-the-access-token-to-create-a-runner-in-the-gitlab-instance","Step 2: Use the access token to create a runner in the GitLab instance",[12,133,134],{},"Now that you have an access token scoped to the instance, group, or project, the next step is to use that token to create a runner automatically. In this example, we will simply invoke a POST REST endpoint in a terminal using CURL.",[136,137,142],"pre",{"className":138,"code":139,"language":140,"meta":141,"style":141},"language-shell shiki shiki-themes github-light","curl -sX POST https://gitlab.example.com/api/v4/user/runners --data runner_type=group_type --data \"group_id=\u003Ctarget_group_or_project_id>\" --data \"description=software-eng-docker-builds-runner\" --data \"tag_list=\u003Cyour comma-separated tags>\" --header \"PRIVATE-TOKEN: \u003Cyour_access_token>\"\n","shell","",[31,143,144],{"__ignoreMap":141},[145,146,149,153,157,161,164,167,170,172,175,177,180,182,185,188],"span",{"class":147,"line":148},"line",1,[145,150,152],{"class":151},"s7eDp","curl",[145,154,156],{"class":155},"sYu0t"," -sX",[145,158,160],{"class":159},"sYBdl"," POST",[145,162,163],{"class":159}," https://gitlab.example.com/api/v4/user/runners",[145,165,166],{"class":155}," --data",[145,168,169],{"class":159}," runner_type=group_type",[145,171,166],{"class":155},[145,173,174],{"class":159}," \"group_id=\u003Ctarget_group_or_project_id>\"",[145,176,166],{"class":155},[145,178,179],{"class":159}," \"description=software-eng-docker-builds-runner\"",[145,181,166],{"class":155},[145,183,184],{"class":159}," \"tag_list=\u003Cyour comma-separated tags>\"",[145,186,187],{"class":155}," --header",[145,189,190],{"class":159}," \"PRIVATE-TOKEN: \u003Cyour_access_token>\"\n",[12,192,193,194,114],{},"Once this step is complete, the newly created runner configuration is visible in the GitLab UI. As the actual runner has not yet been configured, the status displayed is ",[31,195,196],{},"Never contacted",[12,198,199,200,203,204,207,208,211,212,214],{},"The API will return a message with the following fields: ",[31,201,202],{},"id",", ",[31,205,206],{},"token",", and ",[31,209,210],{},"token_expires_at",". You must save the value for the ",[31,213,206],{}," as it will only be displayed once.",[12,216,217,218,222,223,114],{},"As mentioned above, a critical point to note in the new runner creation is that you can reuse the runner token value to register multiple runners. If you choose to do that, runners created with the same token will be grouped in the Runners list. Whichever runner contacted GitLab most recently will be the one whose unique data (IP address, version, last contact time and status) displays in the list. You can still view all the runners in that group ",[219,220,221],"em",{},"and"," compare all of their unique data by going to the details page for that runner. Each runner in the group is uniquely identified by their ",[31,224,225],{},"system_id",[12,227,228],{},"At this point, you might ask yourself, what’s the difference between this new workflow and the workflow that relies on the registration token? The benefits are:",[39,230,231,234],{},[42,232,233],{},"You can now quickly identify the user that created a runner configuration. Not only does this add a layer of security compared to the old method, but it also simplifies troubleshooting runner performance issues, especially when your fleet expands.",[42,235,236],{},"Only the creator of the runner or administrator(s) can edit crucial configuration details like tags, the ability to run untagged jobs, the setting to lock to only run jobs in the current projects it is shared with, and more.",[23,238,240],{"id":239},"automation-of-runner-install-and-registration","Automation of runner install and registration",[12,242,243,244,249,250,255],{},"With the runner configuration creation steps completed, you now have a runner or runners configured in your GitLab instance and valid runner tokens that you can use to register a runner. You can manually install the runner application to a target compute host or automate the runner application installation. If you plan to host the runner on a public cloud virtual machine instance – for example, ",[94,245,248],{"href":246,"rel":247},"https://cloud.google.com/compute/docs/instances",[],"Google Cloud Compute Engine"," – then a good ",[94,251,254],{"href":252,"rel":253},"https://gitlab.com/gitlab-org/gitlab-runner/-/issues/1932#note_1172713979",[],"example pattern"," provided by one of our customers for automating the runner install and registration process is as follows:",[39,257,258,267,280],{},[42,259,260,261,266],{},"Use ",[94,262,265],{"href":263,"rel":264},"https://docs.gitlab.com/user/infrastructure/iac/",[],"Terraform infrastructure as code"," to install the runner application to a virtual machine hosted on GCP.",[42,268,269,270,275,276,279],{},"Use the ",[94,271,274],{"href":272,"rel":273},"https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/compute_instance",[],"GCP Terraform provider"," and specifically the ",[31,277,278],{},"metadata"," key to automatically add the runner authentication token to the runner configuration file on the newly created GCP virtual machine.",[42,281,282,283,288],{},"Register the newly installed runner with the target GitLab instance using a ",[94,284,287],{"href":285,"rel":286},"https://cloudinit.readthedocs.io/en/latest/index.html#",[],"cloud-init"," script populated from the GCP terraform provider.",[12,290,291],{},[66,292,293],{},"Example cloud-init script",[136,295,297],{"className":138,"code":296,"language":140,"meta":141,"style":141},"#!/bin/bash\napt update\n\ncurl -L \"https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh\" | bash\nGL_NAME=$(curl 169.254.169.254/computeMetadata/v1/instance/name -H \"Metadata-Flavor:Google\")\nGL_EXECUTOR=$(curl 169.254.169.254/computeMetadata/v1/instance/attributes/gl_executor -H \"Metadata-Flavor:Google\")\napt update\napt install -y gitlab-runner\ngitlab-runner register --non-interactive --name=\"$GL_NAME\" --url=\"https://gitlab.com\" --token=\"$RUNNER_TOKEN\" --request-concurrency=\"12\" --executor=\"$GL_EXECUTOR\" --docker-image=\"alpine:latest\"\nsystemctl restart gitlab-runner\n",[31,298,299,305,314,321,339,366,387,394,408,469],{"__ignoreMap":141},[145,300,301],{"class":147,"line":148},[145,302,304],{"class":303},"sAwPA","#!/bin/bash\n",[145,306,308,311],{"class":147,"line":307},2,[145,309,310],{"class":151},"apt",[145,312,313],{"class":159}," update\n",[145,315,317],{"class":147,"line":316},3,[145,318,320],{"emptyLinePlaceholder":319},true,"\n",[145,322,324,326,329,332,336],{"class":147,"line":323},4,[145,325,152],{"class":151},[145,327,328],{"class":155}," -L",[145,330,331],{"class":159}," \"https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh\"",[145,333,335],{"class":334},"sD7c4"," |",[145,337,338],{"class":151}," bash\n",[145,340,342,346,349,352,354,357,360,363],{"class":147,"line":341},5,[145,343,345],{"class":344},"sgsFI","GL_NAME",[145,347,348],{"class":334},"=",[145,350,351],{"class":344},"$(",[145,353,152],{"class":151},[145,355,356],{"class":159}," 169.254.169.254/computeMetadata/v1/instance/name",[145,358,359],{"class":155}," -H",[145,361,362],{"class":159}," \"Metadata-Flavor:Google\"",[145,364,365],{"class":344},")\n",[145,367,369,372,374,376,378,381,383,385],{"class":147,"line":368},6,[145,370,371],{"class":344},"GL_EXECUTOR",[145,373,348],{"class":334},[145,375,351],{"class":344},[145,377,152],{"class":151},[145,379,380],{"class":159}," 169.254.169.254/computeMetadata/v1/instance/attributes/gl_executor",[145,382,359],{"class":155},[145,384,362],{"class":159},[145,386,365],{"class":344},[145,388,390,392],{"class":147,"line":389},7,[145,391,310],{"class":151},[145,393,313],{"class":159},[145,395,397,399,402,405],{"class":147,"line":396},8,[145,398,310],{"class":151},[145,400,401],{"class":159}," install",[145,403,404],{"class":155}," -y",[145,406,407],{"class":159}," gitlab-runner\n",[145,409,411,414,417,420,423,426,429,431,434,437,440,442,445,447,450,453,456,458,461,463,466],{"class":147,"line":410},9,[145,412,413],{"class":151},"gitlab-runner",[145,415,416],{"class":159}," register",[145,418,419],{"class":155}," --non-interactive",[145,421,422],{"class":155}," --name=",[145,424,425],{"class":159},"\"",[145,427,428],{"class":344},"$GL_NAME",[145,430,425],{"class":159},[145,432,433],{"class":155}," --url=",[145,435,436],{"class":159},"\"https://gitlab.com\"",[145,438,439],{"class":155}," --token=",[145,441,425],{"class":159},[145,443,444],{"class":344},"$RUNNER_TOKEN",[145,446,425],{"class":159},[145,448,449],{"class":155}," --request-concurrency=",[145,451,452],{"class":159},"\"12\"",[145,454,455],{"class":155}," --executor=",[145,457,425],{"class":159},[145,459,460],{"class":344},"$GL_EXECUTOR",[145,462,425],{"class":159},[145,464,465],{"class":155}," --docker-image=",[145,467,468],{"class":159},"\"alpine:latest\"\n",[145,470,472,475,478],{"class":147,"line":471},10,[145,473,474],{"class":151},"systemctl",[145,476,477],{"class":159}," restart",[145,479,407],{"class":159},[23,481,483],{"id":482},"whats-next","What's next?",[12,485,486],{},"So there you have it, an overview of how to automate runner creation, installation, and registration. To summarize in three simple steps:",[39,488,489,492,495],{},[42,490,491],{},"Use the API to create a runner token and configuration.",[42,493,494],{},"Store the retrieved authentication token in a secrets management solution.",[42,496,497],{},"Use infrastructure as code to install the runner application on a target compute host.",[12,499,500],{},"Our long-term vision is to directly incorporate this automation lifecycle into the product to simplify your day-to-day runner fleet management operations.",[502,503,504],"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 .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 .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}",{"title":141,"searchDepth":307,"depth":307,"links":506},[507,510,514,515],{"id":25,"depth":307,"text":26,"children":508},[509],{"id":60,"depth":316,"text":61},{"id":81,"depth":307,"text":82,"children":511},[512,513],{"id":88,"depth":316,"text":89},{"id":130,"depth":316,"text":131},{"id":239,"depth":307,"text":240},{"id":482,"depth":307,"text":483},"engineering","2023-07-06","Follow this step-by-step guide for automating runner setup using new runner creation workflows.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664087/Blog/Hero%20Images/tanukicover.jpg",{},"/en-us/blog/how-to-automate-creation-of-runners",{"title":5,"description":518,"ogTitle":5,"ogDescription":518,"noIndex":521,"ogImage":522,"ogUrl":526,"ogSiteName":527,"ogType":528,"canonicalUrls":526},"https://about.gitlab.com/blog/how-to-automate-creation-of-runners","https://about.gitlab.com","article","how-to-automate-creation-of-runners","en-us/blog/how-to-automate-creation-of-runners",[532,533,534],"tutorial","workflow","performance","BlogPost","RGyclZOW2vspvFvioeibIFhIYIT40Y8RY8d_QPvjmSc",{"logo":538,"freeTrial":543,"sales":548,"login":553,"items":558,"search":885,"minimal":916,"duo":935,"switchNav":944,"pricingDeployment":955},{"config":539},{"href":540,"dataGaName":541,"dataGaLocation":542},"/","gitlab logo","header",{"text":544,"config":545},"Get free trial",{"href":546,"dataGaName":547,"dataGaLocation":542},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":549,"config":550},"Request a demo",{"href":551,"dataGaName":552,"dataGaLocation":542},"/sales/?contact-topic=request-demo","sales",{"text":554,"config":555},"Sign in",{"href":556,"dataGaName":557,"dataGaLocation":542},"https://gitlab.com/users/sign_in/","sign in",[559,588,688,693,807,863],{"text":560,"config":561,"menu":563},"Platform",{"dataNavLevelOne":562},"platform",{"type":564,"columns":565},"cards",[566,572,580],{"title":560,"description":567,"link":568},"The intelligent orchestration platform for DevSecOps",{"text":569,"config":570},"Explore our Platform",{"href":571,"dataGaName":562,"dataGaLocation":542},"/platform/",{"title":573,"description":574,"link":575},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":576,"config":577},"Meet GitLab Duo",{"href":578,"dataGaName":579,"dataGaLocation":542},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":581,"description":582,"link":583},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":584,"config":585},"Learn more",{"href":586,"dataGaName":587,"dataGaLocation":542},"/why-gitlab/","why gitlab",{"text":589,"left":319,"config":590,"menu":592},"Product",{"dataNavLevelOne":591},"solutions",{"type":593,"link":594,"columns":598,"feature":667},"lists",{"text":595,"config":596},"View all Solutions",{"href":597,"dataGaName":591,"dataGaLocation":542},"/solutions/",[599,623,646],{"title":600,"description":601,"link":602,"items":607},"Automation","CI/CD and automation to accelerate deployment",{"config":603},{"icon":604,"href":605,"dataGaName":606,"dataGaLocation":542},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[608,612,615,619],{"text":609,"config":610},"CI/CD",{"href":611,"dataGaLocation":542,"dataGaName":609},"/solutions/continuous-integration/",{"text":573,"config":613},{"href":578,"dataGaLocation":542,"dataGaName":614},"gitlab duo agent platform - product menu",{"text":616,"config":617},"Source Code Management",{"href":618,"dataGaLocation":542,"dataGaName":616},"/solutions/source-code-management/",{"text":620,"config":621},"Automated Software Delivery",{"href":605,"dataGaLocation":542,"dataGaName":622},"Automated software delivery",{"title":624,"description":625,"link":626,"items":631},"Security","Deliver code faster without compromising security",{"config":627},{"href":628,"dataGaName":629,"dataGaLocation":542,"icon":630},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[632,636,641],{"text":633,"config":634},"Application Security Testing",{"href":628,"dataGaName":635,"dataGaLocation":542},"Application security testing",{"text":637,"config":638},"Software Supply Chain Security",{"href":639,"dataGaLocation":542,"dataGaName":640},"/solutions/supply-chain/","Software supply chain security",{"text":642,"config":643},"Software Compliance",{"href":644,"dataGaName":645,"dataGaLocation":542},"/solutions/software-compliance/","software compliance",{"title":647,"link":648,"items":653},"Measurement",{"config":649},{"icon":650,"href":651,"dataGaName":652,"dataGaLocation":542},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[654,658,662],{"text":655,"config":656},"Visibility & Measurement",{"href":651,"dataGaLocation":542,"dataGaName":657},"Visibility and Measurement",{"text":659,"config":660},"Value Stream Management",{"href":661,"dataGaLocation":542,"dataGaName":659},"/solutions/value-stream-management/",{"text":663,"config":664},"Analytics & Insights",{"href":665,"dataGaLocation":542,"dataGaName":666},"/solutions/analytics-and-insights/","Analytics and insights",{"title":668,"type":593,"items":669},"GitLab for",[670,676,682],{"text":671,"config":672},"Enterprise",{"icon":673,"href":674,"dataGaLocation":542,"dataGaName":675},"Building","/enterprise/","enterprise",{"text":677,"config":678},"Small Business",{"icon":679,"href":680,"dataGaLocation":542,"dataGaName":681},"Work","/small-business/","small business",{"text":683,"config":684},"Public Sector",{"icon":685,"href":686,"dataGaLocation":542,"dataGaName":687},"Organization","/solutions/public-sector/","public sector",{"text":689,"config":690},"Pricing",{"href":691,"dataGaName":692,"dataGaLocation":542,"dataNavLevelOne":692},"/pricing/","pricing",{"text":694,"config":695,"menu":697},"Resources",{"dataNavLevelOne":696},"resources",{"type":593,"link":698,"columns":702,"feature":796},{"text":699,"config":700},"View all resources",{"href":701,"dataGaName":696,"dataGaLocation":542},"/resources/",[703,736,763],{"title":704,"items":705},"Getting started",[706,711,716,721,726,731],{"text":707,"config":708},"Install",{"href":709,"dataGaName":710,"dataGaLocation":542},"/install/","install",{"text":712,"config":713},"Quick start guides",{"href":714,"dataGaName":715,"dataGaLocation":542},"/get-started/","quick setup checklists",{"text":717,"config":718},"Learn",{"href":719,"dataGaLocation":542,"dataGaName":720},"https://university.gitlab.com/","learn",{"text":722,"config":723},"Product documentation",{"href":724,"dataGaName":725,"dataGaLocation":542},"https://docs.gitlab.com/","product documentation",{"text":727,"config":728},"Best practice videos",{"href":729,"dataGaName":730,"dataGaLocation":542},"/getting-started-videos/","best practice videos",{"text":732,"config":733},"Integrations",{"href":734,"dataGaName":735,"dataGaLocation":542},"/integrations/","integrations",{"title":737,"items":738},"Discover",[739,744,749,754,758],{"text":740,"config":741},"Customer success stories",{"href":742,"dataGaName":743,"dataGaLocation":542},"/customers/","customer success stories",{"text":745,"config":746},"Blog",{"href":747,"dataGaName":748,"dataGaLocation":542},"/blog/","blog",{"text":750,"config":751},"Demo Hub",{"href":752,"dataGaName":753,"dataGaLocation":542},"/demo-hub/","demo hub",{"text":755,"config":756},"The Source",{"href":757,"dataGaName":748,"dataGaLocation":542},"/the-source/",{"text":759,"config":760},"Remote",{"href":761,"dataGaName":762,"dataGaLocation":542},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":764,"items":765},"Connect",[766,771,776,781,786,791],{"text":767,"config":768},"GitLab Services",{"href":769,"dataGaName":770,"dataGaLocation":542},"/services/","services",{"text":772,"config":773},"Contribute",{"href":774,"dataGaName":775,"dataGaLocation":542},"https://contributors.gitlab.com","contribute",{"text":777,"config":778},"Community",{"href":779,"dataGaName":780,"dataGaLocation":542},"/community/","community",{"text":782,"config":783},"Forum",{"href":784,"dataGaName":785,"dataGaLocation":542},"https://forum.gitlab.com/","forum",{"text":787,"config":788},"Events",{"href":789,"dataGaName":790,"dataGaLocation":542},"/events/","events",{"text":792,"config":793},"Partners",{"href":794,"dataGaName":795,"dataGaLocation":542},"/partners/","partners",{"config":797,"title":800,"text":801,"link":802},{"background":798,"textColor":799},"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":803,"config":804},"Read the latest",{"href":805,"dataGaName":806,"dataGaLocation":542},"/whats-new/","whats new",{"text":808,"config":809,"menu":811},"Company",{"dataNavLevelOne":810},"company",{"type":593,"columns":812},[813],{"items":814},[815,820,826,828,833,838,843,848,853,858],{"text":816,"config":817},"About",{"href":818,"dataGaName":819,"dataGaLocation":542},"/company/","about",{"text":821,"config":822,"footerGa":825},"Jobs",{"href":823,"dataGaName":824,"dataGaLocation":542},"/jobs/","jobs",{"dataGaName":824},{"text":787,"config":827},{"href":789,"dataGaName":790,"dataGaLocation":542},{"text":829,"config":830},"Leadership",{"href":831,"dataGaName":832,"dataGaLocation":542},"/company/team/e-group/","leadership",{"text":834,"config":835},"Handbook",{"href":836,"dataGaName":837,"dataGaLocation":542},"https://handbook.gitlab.com/","handbook",{"text":839,"config":840},"Investor relations",{"href":841,"dataGaName":842,"dataGaLocation":542},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":844,"config":845},"Trust Center",{"href":846,"dataGaName":847,"dataGaLocation":542},"/security/","trust center",{"text":849,"config":850},"AI Transparency Center",{"href":851,"dataGaName":852,"dataGaLocation":542},"/ai-transparency-center/","ai transparency center",{"text":854,"config":855},"Newsletter",{"href":856,"dataGaName":857,"dataGaLocation":542},"/company/contact/#contact-forms","newsletter",{"text":859,"config":860},"Press",{"href":861,"dataGaName":862,"dataGaLocation":542},"/press/","press",{"text":864,"config":865,"menu":866},"Contact us",{"dataNavLevelOne":810},{"type":593,"columns":867},[868],{"items":869},[870,875,880],{"text":871,"config":872},"Talk to sales",{"href":873,"dataGaName":874,"dataGaLocation":542},"/sales/","talk to sales",{"text":876,"config":877},"Support portal",{"href":878,"dataGaName":879,"dataGaLocation":542},"https://support.gitlab.com/hc/en-us","support portal",{"text":881,"config":882},"Customer portal",{"href":883,"dataGaName":884,"dataGaLocation":542},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":886,"login":887,"suggestions":894},"Close",{"text":888,"link":889},"To search repositories and projects, login to",{"text":890,"config":891},"gitlab.com",{"href":556,"dataGaName":892,"dataGaLocation":893},"search login","search",{"text":895,"default":896},"Suggestions",[897,899,903,905,909,913],{"text":573,"config":898},{"href":578,"dataGaName":573,"dataGaLocation":893},{"text":900,"config":901},"Code Suggestions (AI)",{"href":902,"dataGaName":900,"dataGaLocation":893},"/solutions/code-suggestions/",{"text":609,"config":904},{"href":611,"dataGaName":609,"dataGaLocation":893},{"text":906,"config":907},"GitLab on AWS",{"href":908,"dataGaName":906,"dataGaLocation":893},"/partners/technology-partners/aws/",{"text":910,"config":911},"GitLab on Google Cloud",{"href":912,"dataGaName":910,"dataGaLocation":893},"/partners/technology-partners/google-cloud-platform/",{"text":914,"config":915},"Why GitLab?",{"href":586,"dataGaName":914,"dataGaLocation":893},{"freeTrial":917,"mobileIcon":922,"desktopIcon":927,"secondaryButton":930},{"text":918,"config":919},"Start free trial",{"href":920,"dataGaName":547,"dataGaLocation":921},"https://gitlab.com/-/trials/new/","nav",{"altText":923,"config":924},"Gitlab Icon",{"src":925,"dataGaName":926,"dataGaLocation":921},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":923,"config":928},{"src":929,"dataGaName":926,"dataGaLocation":921},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":931,"config":932},"Get Started",{"href":933,"dataGaName":934,"dataGaLocation":921},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":936,"mobileIcon":940,"desktopIcon":942},{"text":937,"config":938},"Learn more about GitLab Duo",{"href":578,"dataGaName":939,"dataGaLocation":921},"gitlab duo",{"altText":923,"config":941},{"src":925,"dataGaName":926,"dataGaLocation":921},{"altText":923,"config":943},{"src":929,"dataGaName":926,"dataGaLocation":921},{"button":945,"mobileIcon":950,"desktopIcon":952},{"text":946,"config":947},"/switch",{"href":948,"dataGaName":949,"dataGaLocation":921},"#contact","switch",{"altText":923,"config":951},{"src":925,"dataGaName":926,"dataGaLocation":921},{"altText":923,"config":953},{"src":954,"dataGaName":926,"dataGaLocation":921},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":956,"mobileIcon":961,"desktopIcon":963},{"text":957,"config":958},"Back to pricing",{"href":691,"dataGaName":959,"dataGaLocation":921,"icon":960},"back to pricing","GoBack",{"altText":923,"config":962},{"src":925,"dataGaName":926,"dataGaLocation":921},{"altText":923,"config":964},{"src":929,"dataGaName":926,"dataGaLocation":921},{"title":966,"titleMobile":967,"button":968,"config":973},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":584,"config":969},{"href":970,"dataGaName":971,"dataGaLocation":972},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":974,"disabled":521},"release",{"data":976},{"text":977,"source":978,"edit":984,"contribute":989,"config":994,"items":999,"minimal":1209},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":979,"config":980},"View page source",{"href":981,"dataGaName":982,"dataGaLocation":983},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":985,"config":986},"Edit this page",{"href":987,"dataGaName":988,"dataGaLocation":983},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":990,"config":991},"Please contribute",{"href":992,"dataGaName":993,"dataGaLocation":983},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":995,"facebook":996,"youtube":997,"linkedin":998},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1000,1047,1101,1145,1177],{"title":689,"links":1001,"subMenu":1016},[1002,1006,1011],{"text":1003,"config":1004},"View plans",{"href":691,"dataGaName":1005,"dataGaLocation":983},"view plans",{"text":1007,"config":1008},"Why Premium?",{"href":1009,"dataGaName":1010,"dataGaLocation":983},"/pricing/premium/","why premium",{"text":1012,"config":1013},"Why Ultimate?",{"href":1014,"dataGaName":1015,"dataGaLocation":983},"/pricing/ultimate/","why ultimate",[1017],{"title":1018,"links":1019},"Contact Us",[1020,1023,1025,1027,1032,1037,1042],{"text":1021,"config":1022},"Contact sales",{"href":873,"dataGaName":552,"dataGaLocation":983},{"text":876,"config":1024},{"href":878,"dataGaName":879,"dataGaLocation":983},{"text":881,"config":1026},{"href":883,"dataGaName":884,"dataGaLocation":983},{"text":1028,"config":1029},"Status",{"href":1030,"dataGaName":1031,"dataGaLocation":983},"https://status.gitlab.com/","status",{"text":1033,"config":1034},"Terms of use",{"href":1035,"dataGaName":1036,"dataGaLocation":983},"/terms/","terms of use",{"text":1038,"config":1039},"Privacy statement",{"href":1040,"dataGaName":1041,"dataGaLocation":983},"/privacy/","privacy statement",{"text":1043,"config":1044},"Cookie preferences",{"dataGaName":1045,"dataGaLocation":983,"id":1046,"isOneTrustButton":319},"cookie preferences","ot-sdk-btn",{"title":589,"links":1048,"subMenu":1057},[1049,1053],{"text":1050,"config":1051},"DevSecOps platform",{"href":571,"dataGaName":1052,"dataGaLocation":983},"devsecops platform",{"text":1054,"config":1055},"AI-Assisted Development",{"href":578,"dataGaName":1056,"dataGaLocation":983},"ai-assisted development",[1058],{"title":1059,"links":1060},"Topics",[1061,1066,1071,1076,1081,1086,1091,1096],{"text":1062,"config":1063},"CICD",{"href":1064,"dataGaName":1065,"dataGaLocation":983},"/topics/ci-cd/","cicd",{"text":1067,"config":1068},"GitOps",{"href":1069,"dataGaName":1070,"dataGaLocation":983},"/topics/gitops/","gitops",{"text":1072,"config":1073},"DevOps",{"href":1074,"dataGaName":1075,"dataGaLocation":983},"/topics/devops/","devops",{"text":1077,"config":1078},"Version Control",{"href":1079,"dataGaName":1080,"dataGaLocation":983},"/topics/version-control/","version control",{"text":1082,"config":1083},"DevSecOps",{"href":1084,"dataGaName":1085,"dataGaLocation":983},"/topics/devsecops/","devsecops",{"text":1087,"config":1088},"Cloud Native",{"href":1089,"dataGaName":1090,"dataGaLocation":983},"/topics/cloud-native/","cloud native",{"text":1092,"config":1093},"AI for Coding",{"href":1094,"dataGaName":1095,"dataGaLocation":983},"/topics/devops/ai-for-coding/","ai for coding",{"text":1097,"config":1098},"Agentic AI",{"href":1099,"dataGaName":1100,"dataGaLocation":983},"/topics/agentic-ai/","agentic ai",{"title":1102,"links":1103},"Solutions",[1104,1106,1108,1113,1117,1120,1124,1127,1129,1132,1135,1140],{"text":633,"config":1105},{"href":628,"dataGaName":633,"dataGaLocation":983},{"text":622,"config":1107},{"href":605,"dataGaName":606,"dataGaLocation":983},{"text":1109,"config":1110},"Agile development",{"href":1111,"dataGaName":1112,"dataGaLocation":983},"/solutions/agile-delivery/","agile delivery",{"text":1114,"config":1115},"SCM",{"href":618,"dataGaName":1116,"dataGaLocation":983},"source code management",{"text":1062,"config":1118},{"href":611,"dataGaName":1119,"dataGaLocation":983},"continuous integration & delivery",{"text":1121,"config":1122},"Value stream management",{"href":661,"dataGaName":1123,"dataGaLocation":983},"value stream management",{"text":1067,"config":1125},{"href":1126,"dataGaName":1070,"dataGaLocation":983},"/solutions/gitops/",{"text":671,"config":1128},{"href":674,"dataGaName":675,"dataGaLocation":983},{"text":1130,"config":1131},"Small business",{"href":680,"dataGaName":681,"dataGaLocation":983},{"text":1133,"config":1134},"Public sector",{"href":686,"dataGaName":687,"dataGaLocation":983},{"text":1136,"config":1137},"Education",{"href":1138,"dataGaName":1139,"dataGaLocation":983},"/solutions/education/","education",{"text":1141,"config":1142},"Financial services",{"href":1143,"dataGaName":1144,"dataGaLocation":983},"/solutions/finance/","financial services",{"title":694,"links":1146},[1147,1149,1151,1153,1156,1158,1161,1163,1165,1167,1169,1171,1173,1175],{"text":707,"config":1148},{"href":709,"dataGaName":710,"dataGaLocation":983},{"text":712,"config":1150},{"href":714,"dataGaName":715,"dataGaLocation":983},{"text":717,"config":1152},{"href":719,"dataGaName":720,"dataGaLocation":983},{"text":722,"config":1154},{"href":724,"dataGaName":1155,"dataGaLocation":983},"docs",{"text":745,"config":1157},{"href":747,"dataGaName":748,"dataGaLocation":983},{"text":1159,"config":1160},"What's new",{"href":805,"dataGaName":806,"dataGaLocation":983},{"text":740,"config":1162},{"href":742,"dataGaName":743,"dataGaLocation":983},{"text":759,"config":1164},{"href":761,"dataGaName":762,"dataGaLocation":983},{"text":767,"config":1166},{"href":769,"dataGaName":770,"dataGaLocation":983},{"text":772,"config":1168},{"href":774,"dataGaName":775,"dataGaLocation":983},{"text":777,"config":1170},{"href":779,"dataGaName":780,"dataGaLocation":983},{"text":782,"config":1172},{"href":784,"dataGaName":785,"dataGaLocation":983},{"text":787,"config":1174},{"href":789,"dataGaName":790,"dataGaLocation":983},{"text":792,"config":1176},{"href":794,"dataGaName":795,"dataGaLocation":983},{"title":808,"links":1178},[1179,1181,1183,1185,1187,1189,1193,1198,1200,1202,1204],{"text":816,"config":1180},{"href":818,"dataGaName":810,"dataGaLocation":983},{"text":821,"config":1182},{"href":823,"dataGaName":824,"dataGaLocation":983},{"text":829,"config":1184},{"href":831,"dataGaName":832,"dataGaLocation":983},{"text":834,"config":1186},{"href":836,"dataGaName":837,"dataGaLocation":983},{"text":839,"config":1188},{"href":841,"dataGaName":842,"dataGaLocation":983},{"text":1190,"config":1191},"Sustainability",{"href":1192,"dataGaName":1190,"dataGaLocation":983},"/sustainability/",{"text":1194,"config":1195},"Diversity, inclusion and belonging (DIB)",{"href":1196,"dataGaName":1197,"dataGaLocation":983},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":844,"config":1199},{"href":846,"dataGaName":847,"dataGaLocation":983},{"text":854,"config":1201},{"href":856,"dataGaName":857,"dataGaLocation":983},{"text":859,"config":1203},{"href":861,"dataGaName":862,"dataGaLocation":983},{"text":1205,"config":1206},"Modern Slavery Transparency Statement",{"href":1207,"dataGaName":1208,"dataGaLocation":983},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1210},[1211,1214,1217],{"text":1212,"config":1213},"Terms",{"href":1035,"dataGaName":1036,"dataGaLocation":983},{"text":1215,"config":1216},"Cookies",{"dataGaName":1045,"dataGaLocation":983,"id":1046,"isOneTrustButton":319},{"text":1218,"config":1219},"Privacy",{"href":1040,"dataGaName":1041,"dataGaLocation":983},[1221],{"id":1222,"title":7,"body":520,"config":1223,"content":1225,"description":520,"extension":1229,"meta":1230,"navigation":319,"path":1231,"seo":1232,"stem":1233,"__hash__":1234},"blogAuthors/en-us/blog/authors/darren-eastman.yml",{"template":1224},"BlogAuthor",{"name":7,"config":1226},{"headshot":1227,"ctfId":1228},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749665148/Blog/Author%20Headshots/darren_eastman.png","DarrenEastman","yml",{},"/en-us/blog/authors/darren-eastman",{},"en-us/blog/authors/darren-eastman","iXnMUFNVF56JYxVUygLV2-q6FjfdZM8UekM1NED6tu0",[1236,1245,1253],{"title":1237,"description":1238,"heroImage":1239,"category":516,"date":1240,"authors":1241,"slug":1244,"externalUrl":520},"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",[1242,1243],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1246,"description":1247,"heroImage":1248,"category":516,"date":1249,"authors":1250,"slug":1252,"externalUrl":520},"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",[1251],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1254,"description":1255,"heroImage":1256,"category":516,"date":1257,"authors":1258,"slug":1260,"externalUrl":520},"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",[1259],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1262},[1263,1277,1289,1301],{"id":1264,"categories":1265,"header":1267,"text":1268,"button":1269,"image":1274},"ai-modernization",[1266],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1270,"config":1271},"Get your AI maturity score",{"href":1272,"dataGaName":1273,"dataGaLocation":748},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1275},{"src":1276},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1278,"categories":1279,"header":1281,"text":1268,"button":1282,"image":1286},"devops-modernization",[1280,1085],"product","Are you just managing tools or shipping innovation?",{"text":1283,"config":1284},"Get your DevOps maturity score",{"href":1285,"dataGaName":1273,"dataGaLocation":748},"/assessments/devops-modernization-assessment/",{"config":1287},{"src":1288},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1290,"categories":1291,"header":1293,"text":1268,"button":1294,"image":1298},"security-modernization",[1292],"security","Are you trading speed for security?",{"text":1295,"config":1296},"Get your security maturity score",{"href":1297,"dataGaName":1273,"dataGaLocation":748},"/assessments/security-modernization-assessment/",{"config":1299},{"src":1300},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1302,"paths":1303,"header":1306,"text":1307,"button":1308,"image":1313},"github-azure-migration",[1304,1305],"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":1309,"config":1310},"See how GitLab compares to GitHub",{"href":1311,"dataGaName":1312,"dataGaLocation":748},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1314},{"src":1288},{"header":1316,"blurb":1317,"button":1318,"secondaryButton":1323},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1319,"config":1320},"Get your free trial",{"href":1321,"dataGaName":547,"dataGaLocation":1322},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1021,"config":1324},{"href":873,"dataGaName":552,"dataGaLocation":1322},1786803751642]