[{"data":1,"prerenderedAt":1457},["ShallowReactive",2],{"/blog/how-gitlab-pages-uses-the-gitlab-api":3,"navigation-en-us":668,"banner-en-us":1096,"footer-en-us":1106,"blog-post-authors-en-us-Jaime Martínez":1351,"blog-related-posts-en-us-how-gitlab-pages-uses-the-gitlab-api":1367,"blog-promotions-en-us":1393,"next-steps-en-us":1447},{"id":4,"title":5,"authors":6,"body":8,"category":647,"date":648,"description":649,"extension":650,"externalUrl":651,"faq":651,"featured":652,"heroImage":653,"meta":654,"navigation":655,"path":656,"seo":657,"slug":661,"stem":662,"tags":663,"template":666,"updatedDate":651,"__hash__":667},"blogPosts/en-us/blog/how-gitlab-pages-uses-the-gitlab-api.md","How GitLab Pages uses the GitLab API to serve content",[7],"Jaime Martínez",{"type":9,"value":10,"toc":641},"minimark",[11,15,30,43,48,56,72,90,120,137,159,310,333,337,346,357,363,504,516,530,543,547,554,563,573,577,596,614,623,637],[12,13,14],"p",{},"This blog post was originally published on the GitLab Unfiltered blog. It was reviewed and republished on 2020-11-13.",[12,16,17,23,24,29],{},[18,19,22],"a",{"href":20,"rel":21},"https://docs.gitlab.com/user/project/pages/",[],"GitLab Pages"," allows you to create and host GitLab project websites from a user account or group for free on ",[18,25,28],{"href":26,"rel":27},"https://about.gitlab.com/",[],"GitLab.com"," or on your self-managed GitLab instance.",[12,31,32,33,38,39,42],{},"In this post, I will explain how the ",[18,34,37],{"href":35,"rel":36},"https://gitlab.com/gitlab-org/gitlab-pages",[],"GitLab Pages daemon"," obtains a domain's configuration using the\nGitLab API, specifically on ",[18,40,28],{"href":26,"rel":41},[],".",[44,45,47],"h2",{"id":46},"how-does-gitlab-pages-know-where-to-find-your-website-files","How does GitLab Pages know where to find your website files?",[12,49,50,51,42],{},"GitLab Pages will use object storage to store the contents of your web site. You can follow the development of this new feature ",[18,52,55],{"href":53,"rel":54},"https://gitlab.com/groups/gitlab-org/-/epics/3901",[],"here",[12,57,58,59,67,68,71],{},"Currently, GitLab Pages uses an NFS shared mount drive to store the contents of your website.\nYou can define the value of this path by defining the ",[18,60,63],{"href":61,"rel":62},"https://docs.gitlab.com/administration/pages/#change-storage-path",[],[64,65,66],"code",{},"pages_path"," in your ",[64,69,70],{},"/etc/gitlab/gitlab.rb"," file.",[12,73,74,75,78,79,82,83,86,87,89],{},"When you deploy a website using the ",[64,76,77],{},"pages:"," keyword in your ",[64,80,81],{},".gitlab-ci.yml"," file, a ",[64,84,85],{},"public"," path artifact must be defined, containing the files available for your website. This ",[64,88,85],{}," artifact eventually makes its way into the NFS shared mount.",[12,91,92,93,98,99,102,103,106,107,110,111,116,117,42],{},"When you deploy a website to GitLab Pages a domain will be created based on the ",[18,94,97],{"href":95,"rel":96},"https://docs.gitlab.com/administration/pages/#configuration",[],"custom Pages domain you have configured",". For ",[18,100,28],{"href":26,"rel":101},[],", the pages domain is ",[64,104,105],{},"*.gitlab.io",", if you create a project named ",[64,108,109],{},"myproject.gitlab.io"," and enable HTTPS, a wildcard SSL certificate will be used.\nYou can also ",[18,112,115],{"href":113,"rel":114},"https://docs.gitlab.com/user/project/pages/custom_domains_ssl_tls_certification/",[],"setup a custom domain"," for your project, for example ",[64,118,119],{},"myawesomedomain.com",[12,121,122,123,125,126,129,130,133,134,136],{},"For every project (aka domain) that is served by the Pages daemon, there must be a directory in the NFS shared mount that matches your domain name and holds its contents. For example, if we had a project named ",[64,124,109],{},", the Pages daemon would look for your ",[64,127,128],{},".html"," files under ",[64,131,132],{},"/path/to/shared/pages/myproject/myproject.gitlab.io/public"," directory.\nThis is how GitLab Pages serves the content published by the ",[64,135,77],{}," keyword in your CI configuration.",[12,138,139,140,145,146,149,150,153,154,158],{},"Before ",[18,141,144],{"href":142,"rel":143},"https://docs.gitlab.com/releases/",[],"GitLab 12.10"," was released, the Pages daemon would rely on a file named ",[64,147,148],{},"config.json"," located in your project's directory in the NFS shared mount, that is ",[64,151,152],{},"/path/to/shared/pages/myproject/myproject.gitlab.io/config.json",".\nThis file contains metadata related to your project and ",[18,155,157],{"href":20,"rel":156},[],"custom domain names"," you may have setup.",[160,161,166],"pre",{"className":162,"code":163,"language":164,"meta":165,"style":165},"language-json shiki shiki-themes github-light","{\n  \"domains\":[\n    {\n      \"Domain\":\"myproject.gitlab.io\"\n    },\n    {\n      \"Domain\": \"mycustomdomain.com\",\n      \"Certificate\": \"--certificate contents--\",\n      \"Key\": \"--key contents--\"\n    }\n  ],\n  \"id\":123,\n  \"access_control\":true,\n  \"https_only\":true\n}\n","json","",[64,167,168,177,187,193,206,212,217,231,244,255,261,267,280,293,304],{"__ignoreMap":165},[169,170,173],"span",{"class":171,"line":172},"line",1,[169,174,176],{"class":175},"sgsFI","{\n",[169,178,180,184],{"class":171,"line":179},2,[169,181,183],{"class":182},"sYu0t","  \"domains\"",[169,185,186],{"class":175},":[\n",[169,188,190],{"class":171,"line":189},3,[169,191,192],{"class":175},"    {\n",[169,194,196,199,202],{"class":171,"line":195},4,[169,197,198],{"class":182},"      \"Domain\"",[169,200,201],{"class":175},":",[169,203,205],{"class":204},"sYBdl","\"myproject.gitlab.io\"\n",[169,207,209],{"class":171,"line":208},5,[169,210,211],{"class":175},"    },\n",[169,213,215],{"class":171,"line":214},6,[169,216,192],{"class":175},[169,218,220,222,225,228],{"class":171,"line":219},7,[169,221,198],{"class":182},[169,223,224],{"class":175},": ",[169,226,227],{"class":204},"\"mycustomdomain.com\"",[169,229,230],{"class":175},",\n",[169,232,234,237,239,242],{"class":171,"line":233},8,[169,235,236],{"class":182},"      \"Certificate\"",[169,238,224],{"class":175},[169,240,241],{"class":204},"\"--certificate contents--\"",[169,243,230],{"class":175},[169,245,247,250,252],{"class":171,"line":246},9,[169,248,249],{"class":182},"      \"Key\"",[169,251,224],{"class":175},[169,253,254],{"class":204},"\"--key contents--\"\n",[169,256,258],{"class":171,"line":257},10,[169,259,260],{"class":175},"    }\n",[169,262,264],{"class":171,"line":263},11,[169,265,266],{"class":175},"  ],\n",[169,268,270,273,275,278],{"class":171,"line":269},12,[169,271,272],{"class":182},"  \"id\"",[169,274,201],{"class":175},[169,276,277],{"class":182},"123",[169,279,230],{"class":175},[169,281,283,286,288,291],{"class":171,"line":282},13,[169,284,285],{"class":182},"  \"access_control\"",[169,287,201],{"class":175},[169,289,290],{"class":182},"true",[169,292,230],{"class":175},[169,294,296,299,301],{"class":171,"line":295},14,[169,297,298],{"class":182},"  \"https_only\"",[169,300,201],{"class":175},[169,302,303],{"class":182},"true\n",[169,305,307],{"class":171,"line":306},15,[169,308,309],{"class":175},"}\n",[12,311,312,313,318,319,324,325,332],{},"GitLab Pages has been a very popular addition to GitLab, and the number of hosted websites on GitLab.com has increased over time. We are currently hosting over 251,000 websites!\nOn start-up, the Pages daemon would ",[18,314,317],{"href":315,"rel":316},"https://gitlab.com/gitlab-org/gitlab-pages/-/blob/v1.21.0/app.go#L448",[],"traverse all directories"," in the NFS shared mount and load the configuration of all the deployed Pages projects into memory.\nBefore 09-19-2019, the Pages daemon would take ",[18,320,323],{"href":321,"rel":322},"https://gitlab.com/gitlab-org/gitlab-pages/-/issues/252",[],"approximately 25 minutes to be ready to serve requests"," per instance on GitLab.com.\nAfter upgrading GitLab Pages to version ",[18,326,329],{"href":327,"rel":328},"https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/185",[],[64,330,331],{},"v1.9.0",", there were some improvements in some dependencies that reduced booting time to approximately five minutes. This was great but not ideal.",[44,334,336],{"id":335},"gitlab-api-based-configuration","GitLab API-based configuration",[12,338,339,340,345],{},"API-based configuration was ",[18,341,344],{"href":342,"rel":343},"https://gitlab.com/gitlab-org/gitlab-pages/-/issues/282",[],"introduced"," in GitLab 12.10.\nWith API-based configuration, the daemon will start serving content in just a few seconds after booting.\nFor example, for a particular Pages node on GitLab.com, it usually is ready to serve content within one minute after starting.",[12,347,348,349,352,353,356],{},"On ",[18,350,28],{"href":26,"rel":351},[],", the Pages daemon now sources the domain configuration via an internal API endpoint\n",[64,354,355],{},"/api/v4/internal/pages?domain=myproject.gitlab.io",".\nThis is done on demand per domain and the configuration is cached in memory for a certain period of time to speed up serving content from that Pages node.",[12,358,359,360,362],{},"The response from the API is very similar to the contents of the ",[64,361,148],{}," file:",[160,364,366],{"className":162,"code":365,"language":164,"meta":165,"style":165},"{\n    \"certificate\": \"--cert-contents--\",\n    \"key\": \"--key-contents--\",\n    \"lookup_paths\": [\n        {\n            \"access_control\": true,\n            \"https_only\": true,\n            \"prefix\": \"/\",\n            \"project_id\": 123,\n            \"source\": {\n                \"path\": \"myproject/myproject.gitlab.io/public/\",\n                \"type\": \"file\"\n            }\n        }\n    ]\n}\n",[64,367,368,372,384,396,404,409,420,431,443,454,462,474,484,489,494,499],{"__ignoreMap":165},[169,369,370],{"class":171,"line":172},[169,371,176],{"class":175},[169,373,374,377,379,382],{"class":171,"line":179},[169,375,376],{"class":182},"    \"certificate\"",[169,378,224],{"class":175},[169,380,381],{"class":204},"\"--cert-contents--\"",[169,383,230],{"class":175},[169,385,386,389,391,394],{"class":171,"line":189},[169,387,388],{"class":182},"    \"key\"",[169,390,224],{"class":175},[169,392,393],{"class":204},"\"--key-contents--\"",[169,395,230],{"class":175},[169,397,398,401],{"class":171,"line":195},[169,399,400],{"class":182},"    \"lookup_paths\"",[169,402,403],{"class":175},": [\n",[169,405,406],{"class":171,"line":208},[169,407,408],{"class":175},"        {\n",[169,410,411,414,416,418],{"class":171,"line":214},[169,412,413],{"class":182},"            \"access_control\"",[169,415,224],{"class":175},[169,417,290],{"class":182},[169,419,230],{"class":175},[169,421,422,425,427,429],{"class":171,"line":219},[169,423,424],{"class":182},"            \"https_only\"",[169,426,224],{"class":175},[169,428,290],{"class":182},[169,430,230],{"class":175},[169,432,433,436,438,441],{"class":171,"line":233},[169,434,435],{"class":182},"            \"prefix\"",[169,437,224],{"class":175},[169,439,440],{"class":204},"\"/\"",[169,442,230],{"class":175},[169,444,445,448,450,452],{"class":171,"line":246},[169,446,447],{"class":182},"            \"project_id\"",[169,449,224],{"class":175},[169,451,277],{"class":182},[169,453,230],{"class":175},[169,455,456,459],{"class":171,"line":257},[169,457,458],{"class":182},"            \"source\"",[169,460,461],{"class":175},": {\n",[169,463,464,467,469,472],{"class":171,"line":263},[169,465,466],{"class":182},"                \"path\"",[169,468,224],{"class":175},[169,470,471],{"class":204},"\"myproject/myproject.gitlab.io/public/\"",[169,473,230],{"class":175},[169,475,476,479,481],{"class":171,"line":269},[169,477,478],{"class":182},"                \"type\"",[169,480,224],{"class":175},[169,482,483],{"class":204},"\"file\"\n",[169,485,486],{"class":171,"line":282},[169,487,488],{"class":175},"            }\n",[169,490,491],{"class":171,"line":295},[169,492,493],{"class":175},"        }\n",[169,495,496],{"class":171,"line":306},[169,497,498],{"class":175},"    ]\n",[169,500,502],{"class":171,"line":501},16,[169,503,309],{"class":175},[12,505,506,507,510,511,42],{},"You can see that the source type is ",[64,508,509],{},"file",". This means that the Pages daemon will still serve the contents from the NFS shared mount. We are actively working on removing the NFS dependency from GitLab Pages by ",[18,512,515],{"href":513,"rel":514},"https://gitlab.com/groups/gitlab-org/-/epics/1316",[],"updating the GitLab Pages architecture",[12,517,518,519,523,524,529],{},"We are planning to ",[18,520,522],{"href":53,"rel":521},[],"transition GitLab pages to object storage instead of NFS",". This will essentially ",[18,525,528],{"href":526,"rel":527},"https://gitlab.com/gitlab-org/gitlab/-/issues/39586",[],"enable GitLab Pages to run on Kubernetes"," in the future.",[12,531,532,536,537,542],{},[533,534,535],"strong",{},"Update",":\nWe have now ",[18,538,541],{"href":539,"rel":540},"https://gitlab.com/gitlab-com/gl-infra/production/-/issues/2808",[],"rolled out zip source type on GitLab.com",". This is behavior is behind feature flag and it's not the final implementation.\nAs of 10-22-2020 we serve about 75% of Pages projects from zip and object storage and we're getting closer to removing the NFS dependency!",[44,544,546],{"id":545},"self-managed-gitlab-instances","Self-managed GitLab instances",[12,548,549,550,42],{},"The changes to the GitLab Pages architecture were piloted on GitLab.com, which is possibly the largest GitLab Pages implementation.\nOnce all the changes supporting the move to an API-based configuration are completed, they will be rolled out to self-managed customers.\nYou can find more details and the issues we faced while rolling out API-based configuration in this ",[18,551,553],{"href":342,"rel":552},[],"issue",[12,555,556,557,562],{},"If you can't wait to speed up your Pages nodes startup, we have a potential guide in this ",[18,558,561],{"href":559,"rel":560},"https://gitlab.com/gitlab-org/gitlab/-/issues/28298#potential-workaround",[],"issue description"," which explains how we enabled the API on GitLab.com. However, this method will be removed in the near future.",[12,564,565,567,568,42],{},[533,566,535],{},":\nYou can now enable API-based configuration by following ",[18,569,572],{"href":570,"rel":571},"https://docs.gitlab.com/administration/pages/#gitlab-api-based-configuration",[],"this guide",[44,574,576],{"id":575},"domain-source-configuration-and-api-status","Domain source configuration and API status",[12,578,579,580,585,586,67,589,591,592,595],{},"In the meantime, we are working toward adding ",[18,581,584],{"href":582,"rel":583},"https://gitlab.com/gitlab-org/gitlab/-/issues/217912",[],"a new configuration flag for GitLab Pages"," which will allow you to choose the domain configuration source by specifying ",[64,587,588],{},"domain_config_source",[64,590,70],{}," file.\nBy default, GitLab Pages will use the ",[64,593,594],{},"disk"," source configuration the same way is used today.",[12,597,598,599,604,605,608,609,42],{},"In the background, the Pages daemon will start ",[18,600,603],{"href":601,"rel":602},"https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/304",[],"checking the API status"," by calling the ",[64,606,607],{},"/api/v4/internal/pages/status"," endpoint. This will help you check if the Pages daemon is ready to talk to the GitLab API, especially when you are ",[18,610,613],{"href":611,"rel":612},"https://docs.gitlab.com/administration/pages/#running-gitlab-pages-on-a-separate-server",[],"running Pages on a separate server",[12,615,616,617,622],{},"Please check the ",[18,618,621],{"href":619,"rel":620},"https://docs.gitlab.com/administration/pages/#troubleshooting",[],"GitLab Pages adminstration guide"," for further troubleshooting.",[12,624,625,626,631,632],{},"Cover image by ",[18,627,630],{"href":628,"rel":629},"https://unsplash.com/@retrosupply",[],"@RetroSupply"," on ",[18,633,636],{"href":634,"rel":635},"https://unsplash.com/photos/jLwVAUtLOAQ",[],"Unsplash",[638,639,640],"style",{},"html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}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);}",{"title":165,"searchDepth":179,"depth":179,"links":642},[643,644,645,646],{"id":46,"depth":179,"text":47},{"id":335,"depth":179,"text":336},{"id":545,"depth":179,"text":546},{"id":575,"depth":179,"text":576},"engineering","2020-08-03","GitLab Pages is changing the way it reads a project's configuration to speed up booting times and slowly remove its dependency to NFS.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679634/Blog/Hero%20Images/retrosupply-jLwVAUtLOAQ-unsplash.jpg",{},true,"/en-us/blog/how-gitlab-pages-uses-the-gitlab-api",{"title":5,"description":649,"ogTitle":5,"ogDescription":649,"noIndex":652,"ogImage":653,"ogUrl":658,"ogSiteName":659,"ogType":660,"canonicalUrls":658},"https://about.gitlab.com/blog/how-gitlab-pages-uses-the-gitlab-api-to-serve-content","https://about.gitlab.com","article","how-gitlab-pages-uses-the-gitlab-api","en-us/blog/how-gitlab-pages-uses-the-gitlab-api",[664,665],"inside GitLab","kubernetes","BlogPost","euONk91Ti4ECTLiErbEOOMnJL2fpCxJZNBSj_Y23p_M",{"logo":669,"freeTrial":674,"sales":679,"login":684,"items":689,"search":1016,"minimal":1047,"duo":1066,"switchNav":1075,"pricingDeployment":1086},{"config":670},{"href":671,"dataGaName":672,"dataGaLocation":673},"/","gitlab logo","header",{"text":675,"config":676},"Get free trial",{"href":677,"dataGaName":678,"dataGaLocation":673},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":680,"config":681},"Request a demo",{"href":682,"dataGaName":683,"dataGaLocation":673},"/sales/?contact-topic=request-demo","sales",{"text":685,"config":686},"Sign in",{"href":687,"dataGaName":688,"dataGaLocation":673},"https://gitlab.com/users/sign_in/","sign in",[690,719,819,824,938,994],{"text":691,"config":692,"menu":694},"Platform",{"dataNavLevelOne":693},"platform",{"type":695,"columns":696},"cards",[697,703,711],{"title":691,"description":698,"link":699},"The intelligent orchestration platform for DevSecOps",{"text":700,"config":701},"Explore our Platform",{"href":702,"dataGaName":693,"dataGaLocation":673},"/platform/",{"title":704,"description":705,"link":706},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":707,"config":708},"Meet GitLab Duo",{"href":709,"dataGaName":710,"dataGaLocation":673},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":712,"description":713,"link":714},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":715,"config":716},"Learn more",{"href":717,"dataGaName":718,"dataGaLocation":673},"/why-gitlab/","why gitlab",{"text":720,"left":655,"config":721,"menu":723},"Product",{"dataNavLevelOne":722},"solutions",{"type":724,"link":725,"columns":729,"feature":798},"lists",{"text":726,"config":727},"View all Solutions",{"href":728,"dataGaName":722,"dataGaLocation":673},"/solutions/",[730,754,777],{"title":731,"description":732,"link":733,"items":738},"Automation","CI/CD and automation to accelerate deployment",{"config":734},{"icon":735,"href":736,"dataGaName":737,"dataGaLocation":673},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[739,743,746,750],{"text":740,"config":741},"CI/CD",{"href":742,"dataGaLocation":673,"dataGaName":740},"/solutions/continuous-integration/",{"text":704,"config":744},{"href":709,"dataGaLocation":673,"dataGaName":745},"gitlab duo agent platform - product menu",{"text":747,"config":748},"Source Code Management",{"href":749,"dataGaLocation":673,"dataGaName":747},"/solutions/source-code-management/",{"text":751,"config":752},"Automated Software Delivery",{"href":736,"dataGaLocation":673,"dataGaName":753},"Automated software delivery",{"title":755,"description":756,"link":757,"items":762},"Security","Deliver code faster without compromising security",{"config":758},{"href":759,"dataGaName":760,"dataGaLocation":673,"icon":761},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[763,767,772],{"text":764,"config":765},"Application Security Testing",{"href":759,"dataGaName":766,"dataGaLocation":673},"Application security testing",{"text":768,"config":769},"Software Supply Chain Security",{"href":770,"dataGaLocation":673,"dataGaName":771},"/solutions/supply-chain/","Software supply chain security",{"text":773,"config":774},"Software Compliance",{"href":775,"dataGaName":776,"dataGaLocation":673},"/solutions/software-compliance/","software compliance",{"title":778,"link":779,"items":784},"Measurement",{"config":780},{"icon":781,"href":782,"dataGaName":783,"dataGaLocation":673},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[785,789,793],{"text":786,"config":787},"Visibility & Measurement",{"href":782,"dataGaLocation":673,"dataGaName":788},"Visibility and Measurement",{"text":790,"config":791},"Value Stream Management",{"href":792,"dataGaLocation":673,"dataGaName":790},"/solutions/value-stream-management/",{"text":794,"config":795},"Analytics & Insights",{"href":796,"dataGaLocation":673,"dataGaName":797},"/solutions/analytics-and-insights/","Analytics and insights",{"title":799,"type":724,"items":800},"GitLab for",[801,807,813],{"text":802,"config":803},"Enterprise",{"icon":804,"href":805,"dataGaLocation":673,"dataGaName":806},"Building","/enterprise/","enterprise",{"text":808,"config":809},"Small Business",{"icon":810,"href":811,"dataGaLocation":673,"dataGaName":812},"Work","/small-business/","small business",{"text":814,"config":815},"Public Sector",{"icon":816,"href":817,"dataGaLocation":673,"dataGaName":818},"Organization","/solutions/public-sector/","public sector",{"text":820,"config":821},"Pricing",{"href":822,"dataGaName":823,"dataGaLocation":673,"dataNavLevelOne":823},"/pricing/","pricing",{"text":825,"config":826,"menu":828},"Resources",{"dataNavLevelOne":827},"resources",{"type":724,"link":829,"columns":833,"feature":927},{"text":830,"config":831},"View all resources",{"href":832,"dataGaName":827,"dataGaLocation":673},"/resources/",[834,867,894],{"title":835,"items":836},"Getting started",[837,842,847,852,857,862],{"text":838,"config":839},"Install",{"href":840,"dataGaName":841,"dataGaLocation":673},"/install/","install",{"text":843,"config":844},"Quick start guides",{"href":845,"dataGaName":846,"dataGaLocation":673},"/get-started/","quick setup checklists",{"text":848,"config":849},"Learn",{"href":850,"dataGaLocation":673,"dataGaName":851},"https://university.gitlab.com/","learn",{"text":853,"config":854},"Product documentation",{"href":855,"dataGaName":856,"dataGaLocation":673},"https://docs.gitlab.com/","product documentation",{"text":858,"config":859},"Best practice videos",{"href":860,"dataGaName":861,"dataGaLocation":673},"/getting-started-videos/","best practice videos",{"text":863,"config":864},"Integrations",{"href":865,"dataGaName":866,"dataGaLocation":673},"/integrations/","integrations",{"title":868,"items":869},"Discover",[870,875,880,885,889],{"text":871,"config":872},"Customer success stories",{"href":873,"dataGaName":874,"dataGaLocation":673},"/customers/","customer success stories",{"text":876,"config":877},"Blog",{"href":878,"dataGaName":879,"dataGaLocation":673},"/blog/","blog",{"text":881,"config":882},"Demo Hub",{"href":883,"dataGaName":884,"dataGaLocation":673},"/demo-hub/","demo hub",{"text":886,"config":887},"The Source",{"href":888,"dataGaName":879,"dataGaLocation":673},"/the-source/",{"text":890,"config":891},"Remote",{"href":892,"dataGaName":893,"dataGaLocation":673},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":895,"items":896},"Connect",[897,902,907,912,917,922],{"text":898,"config":899},"GitLab Services",{"href":900,"dataGaName":901,"dataGaLocation":673},"/services/","services",{"text":903,"config":904},"Contribute",{"href":905,"dataGaName":906,"dataGaLocation":673},"https://contributors.gitlab.com","contribute",{"text":908,"config":909},"Community",{"href":910,"dataGaName":911,"dataGaLocation":673},"/community/","community",{"text":913,"config":914},"Forum",{"href":915,"dataGaName":916,"dataGaLocation":673},"https://forum.gitlab.com/","forum",{"text":918,"config":919},"Events",{"href":920,"dataGaName":921,"dataGaLocation":673},"/events/","events",{"text":923,"config":924},"Partners",{"href":925,"dataGaName":926,"dataGaLocation":673},"/partners/","partners",{"config":928,"title":931,"text":932,"link":933},{"background":929,"textColor":930},"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":934,"config":935},"Read the latest",{"href":936,"dataGaName":937,"dataGaLocation":673},"/whats-new/","whats new",{"text":939,"config":940,"menu":942},"Company",{"dataNavLevelOne":941},"company",{"type":724,"columns":943},[944],{"items":945},[946,951,957,959,964,969,974,979,984,989],{"text":947,"config":948},"About",{"href":949,"dataGaName":950,"dataGaLocation":673},"/company/","about",{"text":952,"config":953,"footerGa":956},"Jobs",{"href":954,"dataGaName":955,"dataGaLocation":673},"/jobs/","jobs",{"dataGaName":955},{"text":918,"config":958},{"href":920,"dataGaName":921,"dataGaLocation":673},{"text":960,"config":961},"Leadership",{"href":962,"dataGaName":963,"dataGaLocation":673},"/company/team/e-group/","leadership",{"text":965,"config":966},"Handbook",{"href":967,"dataGaName":968,"dataGaLocation":673},"https://handbook.gitlab.com/","handbook",{"text":970,"config":971},"Investor relations",{"href":972,"dataGaName":973,"dataGaLocation":673},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":975,"config":976},"Trust Center",{"href":977,"dataGaName":978,"dataGaLocation":673},"/security/","trust center",{"text":980,"config":981},"AI Transparency Center",{"href":982,"dataGaName":983,"dataGaLocation":673},"/ai-transparency-center/","ai transparency center",{"text":985,"config":986},"Newsletter",{"href":987,"dataGaName":988,"dataGaLocation":673},"/company/contact/#contact-forms","newsletter",{"text":990,"config":991},"Press",{"href":992,"dataGaName":993,"dataGaLocation":673},"/press/","press",{"text":995,"config":996,"menu":997},"Contact us",{"dataNavLevelOne":941},{"type":724,"columns":998},[999],{"items":1000},[1001,1006,1011],{"text":1002,"config":1003},"Talk to sales",{"href":1004,"dataGaName":1005,"dataGaLocation":673},"/sales/","talk to sales",{"text":1007,"config":1008},"Support portal",{"href":1009,"dataGaName":1010,"dataGaLocation":673},"https://support.gitlab.com/hc/en-us","support portal",{"text":1012,"config":1013},"Customer portal",{"href":1014,"dataGaName":1015,"dataGaLocation":673},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1017,"login":1018,"suggestions":1025},"Close",{"text":1019,"link":1020},"To search repositories and projects, login to",{"text":1021,"config":1022},"gitlab.com",{"href":687,"dataGaName":1023,"dataGaLocation":1024},"search login","search",{"text":1026,"default":1027},"Suggestions",[1028,1030,1034,1036,1040,1044],{"text":704,"config":1029},{"href":709,"dataGaName":704,"dataGaLocation":1024},{"text":1031,"config":1032},"Code Suggestions (AI)",{"href":1033,"dataGaName":1031,"dataGaLocation":1024},"/solutions/code-suggestions/",{"text":740,"config":1035},{"href":742,"dataGaName":740,"dataGaLocation":1024},{"text":1037,"config":1038},"GitLab on AWS",{"href":1039,"dataGaName":1037,"dataGaLocation":1024},"/partners/technology-partners/aws/",{"text":1041,"config":1042},"GitLab on Google Cloud",{"href":1043,"dataGaName":1041,"dataGaLocation":1024},"/partners/technology-partners/google-cloud-platform/",{"text":1045,"config":1046},"Why GitLab?",{"href":717,"dataGaName":1045,"dataGaLocation":1024},{"freeTrial":1048,"mobileIcon":1053,"desktopIcon":1058,"secondaryButton":1061},{"text":1049,"config":1050},"Start free trial",{"href":1051,"dataGaName":678,"dataGaLocation":1052},"https://gitlab.com/-/trials/new/","nav",{"altText":1054,"config":1055},"Gitlab Icon",{"src":1056,"dataGaName":1057,"dataGaLocation":1052},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1054,"config":1059},{"src":1060,"dataGaName":1057,"dataGaLocation":1052},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1062,"config":1063},"Get Started",{"href":1064,"dataGaName":1065,"dataGaLocation":1052},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1067,"mobileIcon":1071,"desktopIcon":1073},{"text":1068,"config":1069},"Learn more about GitLab Duo",{"href":709,"dataGaName":1070,"dataGaLocation":1052},"gitlab duo",{"altText":1054,"config":1072},{"src":1056,"dataGaName":1057,"dataGaLocation":1052},{"altText":1054,"config":1074},{"src":1060,"dataGaName":1057,"dataGaLocation":1052},{"button":1076,"mobileIcon":1081,"desktopIcon":1083},{"text":1077,"config":1078},"/switch",{"href":1079,"dataGaName":1080,"dataGaLocation":1052},"#contact","switch",{"altText":1054,"config":1082},{"src":1056,"dataGaName":1057,"dataGaLocation":1052},{"altText":1054,"config":1084},{"src":1085,"dataGaName":1057,"dataGaLocation":1052},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1087,"mobileIcon":1092,"desktopIcon":1094},{"text":1088,"config":1089},"Back to pricing",{"href":822,"dataGaName":1090,"dataGaLocation":1052,"icon":1091},"back to pricing","GoBack",{"altText":1054,"config":1093},{"src":1056,"dataGaName":1057,"dataGaLocation":1052},{"altText":1054,"config":1095},{"src":1060,"dataGaName":1057,"dataGaLocation":1052},{"title":1097,"titleMobile":1098,"button":1099,"config":1104},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":715,"config":1100},{"href":1101,"dataGaName":1102,"dataGaLocation":1103},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1105,"disabled":652},"release",{"data":1107},{"text":1108,"source":1109,"edit":1115,"contribute":1120,"config":1125,"items":1130,"minimal":1340},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1110,"config":1111},"View page source",{"href":1112,"dataGaName":1113,"dataGaLocation":1114},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1116,"config":1117},"Edit this page",{"href":1118,"dataGaName":1119,"dataGaLocation":1114},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1121,"config":1122},"Please contribute",{"href":1123,"dataGaName":1124,"dataGaLocation":1114},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1126,"facebook":1127,"youtube":1128,"linkedin":1129},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1131,1178,1232,1276,1308],{"title":820,"links":1132,"subMenu":1147},[1133,1137,1142],{"text":1134,"config":1135},"View plans",{"href":822,"dataGaName":1136,"dataGaLocation":1114},"view plans",{"text":1138,"config":1139},"Why Premium?",{"href":1140,"dataGaName":1141,"dataGaLocation":1114},"/pricing/premium/","why premium",{"text":1143,"config":1144},"Why Ultimate?",{"href":1145,"dataGaName":1146,"dataGaLocation":1114},"/pricing/ultimate/","why ultimate",[1148],{"title":1149,"links":1150},"Contact Us",[1151,1154,1156,1158,1163,1168,1173],{"text":1152,"config":1153},"Contact sales",{"href":1004,"dataGaName":683,"dataGaLocation":1114},{"text":1007,"config":1155},{"href":1009,"dataGaName":1010,"dataGaLocation":1114},{"text":1012,"config":1157},{"href":1014,"dataGaName":1015,"dataGaLocation":1114},{"text":1159,"config":1160},"Status",{"href":1161,"dataGaName":1162,"dataGaLocation":1114},"https://status.gitlab.com/","status",{"text":1164,"config":1165},"Terms of use",{"href":1166,"dataGaName":1167,"dataGaLocation":1114},"/terms/","terms of use",{"text":1169,"config":1170},"Privacy statement",{"href":1171,"dataGaName":1172,"dataGaLocation":1114},"/privacy/","privacy statement",{"text":1174,"config":1175},"Cookie preferences",{"dataGaName":1176,"dataGaLocation":1114,"id":1177,"isOneTrustButton":655},"cookie preferences","ot-sdk-btn",{"title":720,"links":1179,"subMenu":1188},[1180,1184],{"text":1181,"config":1182},"DevSecOps platform",{"href":702,"dataGaName":1183,"dataGaLocation":1114},"devsecops platform",{"text":1185,"config":1186},"AI-Assisted Development",{"href":709,"dataGaName":1187,"dataGaLocation":1114},"ai-assisted development",[1189],{"title":1190,"links":1191},"Topics",[1192,1197,1202,1207,1212,1217,1222,1227],{"text":1193,"config":1194},"CICD",{"href":1195,"dataGaName":1196,"dataGaLocation":1114},"/topics/ci-cd/","cicd",{"text":1198,"config":1199},"GitOps",{"href":1200,"dataGaName":1201,"dataGaLocation":1114},"/topics/gitops/","gitops",{"text":1203,"config":1204},"DevOps",{"href":1205,"dataGaName":1206,"dataGaLocation":1114},"/topics/devops/","devops",{"text":1208,"config":1209},"Version Control",{"href":1210,"dataGaName":1211,"dataGaLocation":1114},"/topics/version-control/","version control",{"text":1213,"config":1214},"DevSecOps",{"href":1215,"dataGaName":1216,"dataGaLocation":1114},"/topics/devsecops/","devsecops",{"text":1218,"config":1219},"Cloud Native",{"href":1220,"dataGaName":1221,"dataGaLocation":1114},"/topics/cloud-native/","cloud native",{"text":1223,"config":1224},"AI for Coding",{"href":1225,"dataGaName":1226,"dataGaLocation":1114},"/topics/devops/ai-for-coding/","ai for coding",{"text":1228,"config":1229},"Agentic AI",{"href":1230,"dataGaName":1231,"dataGaLocation":1114},"/topics/agentic-ai/","agentic ai",{"title":1233,"links":1234},"Solutions",[1235,1237,1239,1244,1248,1251,1255,1258,1260,1263,1266,1271],{"text":764,"config":1236},{"href":759,"dataGaName":764,"dataGaLocation":1114},{"text":753,"config":1238},{"href":736,"dataGaName":737,"dataGaLocation":1114},{"text":1240,"config":1241},"Agile development",{"href":1242,"dataGaName":1243,"dataGaLocation":1114},"/solutions/agile-delivery/","agile delivery",{"text":1245,"config":1246},"SCM",{"href":749,"dataGaName":1247,"dataGaLocation":1114},"source code management",{"text":1193,"config":1249},{"href":742,"dataGaName":1250,"dataGaLocation":1114},"continuous integration & delivery",{"text":1252,"config":1253},"Value stream management",{"href":792,"dataGaName":1254,"dataGaLocation":1114},"value stream management",{"text":1198,"config":1256},{"href":1257,"dataGaName":1201,"dataGaLocation":1114},"/solutions/gitops/",{"text":802,"config":1259},{"href":805,"dataGaName":806,"dataGaLocation":1114},{"text":1261,"config":1262},"Small business",{"href":811,"dataGaName":812,"dataGaLocation":1114},{"text":1264,"config":1265},"Public sector",{"href":817,"dataGaName":818,"dataGaLocation":1114},{"text":1267,"config":1268},"Education",{"href":1269,"dataGaName":1270,"dataGaLocation":1114},"/solutions/education/","education",{"text":1272,"config":1273},"Financial services",{"href":1274,"dataGaName":1275,"dataGaLocation":1114},"/solutions/finance/","financial services",{"title":825,"links":1277},[1278,1280,1282,1284,1287,1289,1292,1294,1296,1298,1300,1302,1304,1306],{"text":838,"config":1279},{"href":840,"dataGaName":841,"dataGaLocation":1114},{"text":843,"config":1281},{"href":845,"dataGaName":846,"dataGaLocation":1114},{"text":848,"config":1283},{"href":850,"dataGaName":851,"dataGaLocation":1114},{"text":853,"config":1285},{"href":855,"dataGaName":1286,"dataGaLocation":1114},"docs",{"text":876,"config":1288},{"href":878,"dataGaName":879,"dataGaLocation":1114},{"text":1290,"config":1291},"What's new",{"href":936,"dataGaName":937,"dataGaLocation":1114},{"text":871,"config":1293},{"href":873,"dataGaName":874,"dataGaLocation":1114},{"text":890,"config":1295},{"href":892,"dataGaName":893,"dataGaLocation":1114},{"text":898,"config":1297},{"href":900,"dataGaName":901,"dataGaLocation":1114},{"text":903,"config":1299},{"href":905,"dataGaName":906,"dataGaLocation":1114},{"text":908,"config":1301},{"href":910,"dataGaName":911,"dataGaLocation":1114},{"text":913,"config":1303},{"href":915,"dataGaName":916,"dataGaLocation":1114},{"text":918,"config":1305},{"href":920,"dataGaName":921,"dataGaLocation":1114},{"text":923,"config":1307},{"href":925,"dataGaName":926,"dataGaLocation":1114},{"title":939,"links":1309},[1310,1312,1314,1316,1318,1320,1324,1329,1331,1333,1335],{"text":947,"config":1311},{"href":949,"dataGaName":941,"dataGaLocation":1114},{"text":952,"config":1313},{"href":954,"dataGaName":955,"dataGaLocation":1114},{"text":960,"config":1315},{"href":962,"dataGaName":963,"dataGaLocation":1114},{"text":965,"config":1317},{"href":967,"dataGaName":968,"dataGaLocation":1114},{"text":970,"config":1319},{"href":972,"dataGaName":973,"dataGaLocation":1114},{"text":1321,"config":1322},"Sustainability",{"href":1323,"dataGaName":1321,"dataGaLocation":1114},"/sustainability/",{"text":1325,"config":1326},"Diversity, inclusion and belonging (DIB)",{"href":1327,"dataGaName":1328,"dataGaLocation":1114},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":975,"config":1330},{"href":977,"dataGaName":978,"dataGaLocation":1114},{"text":985,"config":1332},{"href":987,"dataGaName":988,"dataGaLocation":1114},{"text":990,"config":1334},{"href":992,"dataGaName":993,"dataGaLocation":1114},{"text":1336,"config":1337},"Modern Slavery Transparency Statement",{"href":1338,"dataGaName":1339,"dataGaLocation":1114},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1341},[1342,1345,1348],{"text":1343,"config":1344},"Terms",{"href":1166,"dataGaName":1167,"dataGaLocation":1114},{"text":1346,"config":1347},"Cookies",{"dataGaName":1176,"dataGaLocation":1114,"id":1177,"isOneTrustButton":655},{"text":1349,"config":1350},"Privacy",{"href":1171,"dataGaName":1172,"dataGaLocation":1114},[1352],{"id":1353,"title":1354,"body":651,"config":1355,"content":1357,"description":651,"extension":1361,"meta":1362,"navigation":655,"path":1363,"seo":1364,"stem":1365,"__hash__":1366},"blogAuthors/en-us/blog/authors/jaime-martnez.yml","Jaime Martnez",{"template":1356},"BlogAuthor",{"name":7,"config":1358},{"headshot":1359,"ctfId":1360},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679630/Blog/Author%20Headshots/jaime-headshot.jpg","jaime","yml",{},"/en-us/blog/authors/jaime-martnez",{},"en-us/blog/authors/jaime-martnez","Q6_uw2ZXThqBhUCeiLhEOl57bbHSEmxDLket-oi9uXY",[1368,1377,1385],{"title":1369,"description":1370,"heroImage":1371,"category":647,"date":1372,"authors":1373,"slug":1376,"externalUrl":651},"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",[1374,1375],"Mathias Ewald","Martin Paloncy, Edgeless Systems","confidential-ai-for-gitlab-self-hosted",{"title":1378,"description":1379,"heroImage":1380,"category":647,"date":1381,"authors":1382,"slug":1384,"externalUrl":651},"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",[1383],"Lysanne Pinto","green-devops-carbon-measurement-cicd-pipeline",{"title":1386,"description":1387,"heroImage":1388,"category":647,"date":1389,"authors":1390,"slug":1392,"externalUrl":651},"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",[1391],"Paul Meresanu","how-to-build-ci-cd-observability-at-scale",{"promotions":1394},[1395,1409,1421,1433],{"id":1396,"categories":1397,"header":1399,"text":1400,"button":1401,"image":1406},"ai-modernization",[1398],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1402,"config":1403},"Get your AI maturity score",{"href":1404,"dataGaName":1405,"dataGaLocation":879},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1407},{"src":1408},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1410,"categories":1411,"header":1413,"text":1400,"button":1414,"image":1418},"devops-modernization",[1412,1216],"product","Are you just managing tools or shipping innovation?",{"text":1415,"config":1416},"Get your DevOps maturity score",{"href":1417,"dataGaName":1405,"dataGaLocation":879},"/assessments/devops-modernization-assessment/",{"config":1419},{"src":1420},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1422,"categories":1423,"header":1425,"text":1400,"button":1426,"image":1430},"security-modernization",[1424],"security","Are you trading speed for security?",{"text":1427,"config":1428},"Get your security maturity score",{"href":1429,"dataGaName":1405,"dataGaLocation":879},"/assessments/security-modernization-assessment/",{"config":1431},{"src":1432},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1434,"paths":1435,"header":1438,"text":1439,"button":1440,"image":1445},"github-azure-migration",[1436,1437],"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":1441,"config":1442},"See how GitLab compares to GitHub",{"href":1443,"dataGaName":1444,"dataGaLocation":879},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1446},{"src":1420},{"header":1448,"blurb":1449,"button":1450,"secondaryButton":1455},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1451,"config":1452},"Get your free trial",{"href":1453,"dataGaName":678,"dataGaLocation":1454},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1152,"config":1456},{"href":1004,"dataGaName":683,"dataGaLocation":1454},1786803749459]