[{"data":1,"prerenderedAt":717},["ShallowReactive",2],{"/en-us/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/":3,"navigation-en-us":32,"banner-en-us":461,"footer-en-us":478,"Guest author André Miranda":688,"next-steps-en-us":702},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":22,"_id":25,"_type":26,"title":27,"_source":28,"_file":29,"_stem":30,"_extension":31},"/en-us/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Tutorial: Securing your GitLab Pages with TLS and Let's Encrypt","In this post we will talk about HTTPS and how to add it to your GitLab Pages site with Let's Encrypt","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672214/Blog/Hero%20Images/altssh.jpg","https://about.gitlab.com/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Securing your GitLab Pages with TLS and Let's Encrypt\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Guest author André Miranda\"}],\n        \"datePublished\": \"2016-04-11\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21},[18],"Guest author André Miranda","2016-04-11","In this post we will talk about HTTPS and how to add it to your GitLab Pages\nsite\n\nwith [Let's Encrypt][letsencrypt].\n\n\n\u003C!-- more -->\n\n\n## Why TLS/SSL?\n\n\nWhen discussing HTTPS, it's common to hear people saying that a static\n\nwebsite doesn't need HTTPS, since it doesn't receive any POST requests, or\nisn't\n\nhandling credit card transactions or any other secure request.\n\nBut that's not the whole story.\n\n\nTLS ([formerly SSL][TLSwiki]) is a security protocol that can be added to\nHTTP\n\nto increase the security of your website by:\n\n\n1. properly authenticating yourself: the client can trust that you are\nreally\n\n**you**. The TLS handshake that is made at the beginning of the connection\n\nensures the client that no one is trying to impersonate you;\n\n2. data integrity: this ensures that no one has tampered with the data in a\n\nrequest/response cycle;\n\n3. encryption: this is the main selling point of TLS, but the\n\nother two are just as important. This protects the privacy of the\ncommunication\n\nbetween client and server.\n\n\nThe TLS layer can be added to other protocols too, such as FTP (making it\n\n[FTPS](https://en.wikipedia.org/wiki/FTPS)) or WebSockets\n\n(making `ws://`\n[`wss://`](https://devcenter.heroku.com/articles/websocket-security#wss)).\n\n\n## HTTPS Everywhere\n\n\nNowadays, there is a strong push for using TLS on every website.\n\nThe ultimate goal is to make the web safer, by adding those three components\n\ncited above to every website.\n\n\nThe first big player was the [HTTPS\nEverywhere](https://www.eff.org/https-everywhere)\n\nbrowser extension. Google has also been using HTTPS compliance to better\n\nrank websites since\n[2014](https://webmasters.googleblog.com/2014/08/https-as-ranking-signal.html).\n\n\n## How to get TLS certificates\n\n\nIn order to add TLS to HTTP, one would need to get a certificate, and until\n2015,\n\none would need to either pay for it or figure out how to do it with one of\nthe\n\navailable [Certificate Authorities][certificateauthority].\n\n\nEnter [Let's Encrypt][letsencrypt], a free, automated, and open Certificate\nAuthority.\n\nSince [December 2015][publicbeta] anyone can get a free certificate from\nthis\n\nnew Certificate Authority from the comfort of their terminal.\n\n\n\n## Implementation\n\n\nSo, let's suppose we're going to create a static blog with [Jekyll\n3][Jekyll].\n\nIf you are not creating a blog or are not using Jekyll just follow along, it\n\nshould be straightforward enough to translate the steps for different\npurposes.\n\nYou can also find many example projects using different static site\ngenerators\n\n(like Middleman or Hugo) in [GitLab's example projects][examplepages].\n\n\nA simple example blog can be created with:\n\n\n```shell\n\n$ jekyll new cool-blog\n\nNew jekyll site installed in ~/cool-blog.\n\n$ cd cool-blog/\n\n```\n\n\nNow you have to create a GitLab project. Here we are going to create a \"user\n\npage\", which means that it is a project created within a user account (not a\n\ngroup account), and that the name of the project looks like\n`YOURUSERNAME.gitlab.io`.\n\nRefer to the [\"Getting started\" section of the GitLab Pages\nmanual][pagesdocs]\n\nfor more information on that.\n\n\nFrom now on, remember to replace `YOURDOMAIN.org` with your custom domain\nand\n\n`YOURUSERNAME` with, well, your username. ;)\n\n\n[Create a project] named `YOURUSERNAME.gitlab.io` so that GitLab will\n\nidentify the project correctly. After that, upload your code to GitLab:\n\n\n```\n\n$ git remote add origin\ngit@gitlab.com:YOURUSERNAME/YOURUSERNAME.gitlab.io.git\n\n$ git push -u origin master\n\n```\n\n\nOK, so far we have a project uploaded to GitLab, but we haven't configured\nGitLab Pages yet.\n\nTo configure it, just create a `.gitlab-ci.yml` file in the root directory\nof your repository\n\nwith the following contents:\n\n\n```yaml\n\npages:\n  stage: deploy\n  image: ruby:2.3\n  script:\n    - gem install jekyll\n    - jekyll build -d public/\n  artifacts:\n    paths:\n      - public\n  only:\n    - master\n```\n\n\nThis file instructs GitLab Runner to `deploy` by installing Jekyll and\n\nbuilding your website under the `public/` folder\n\n(`jekyll build -d public/`).\n\n\nWhile you Wait for the build process to complete, you can track the progress\nin the\n\nBuilds page of your project. Once it starts, it probably won't take longer\n\nthan a few minutes. Once the build is finished, your website will be\navailable at\n\n`https://YOURUSERNAME.gitlab.io`. Note that GitLab already provides TLS\n\ncertificates to all subdomains of `gitlab.io` (but it has some limitations,\nso\n\nplease [refer to the documentation for more][limitation]). So if you don't\nwant to add a\n\ncustom domain, you're done.\n\n\n## How to configure the TLS certificate of your custom domain.\n\n\nOnce you buy a domain name and point that domain to your GitLab Pages\nwebsite,\n\nyou need to configure 2 things:\n\n\n1. add the domain to GitLab Pages configuration ([see\ndocumentation][customdomain]);\n\n2. add your custom certificate to your website.\n\n\nOnce you add your domain, your website will be available under both\n\n`http://YOURDOMAIN.org` and `https://YOURUSERNAME.gitlab.io`.\n\n\nBut if you try to access your custom domain with `HTTPS`\n\n(`https://YOURDOMAIN.org` in this case), your browser will show that\n\nhorrible page, saying that things are going wrong and someone is trying to\n\nsteal your information. *Why is that?*\n\n\nSince GitLab offers TLS certificates to all `gitlab.io` pages\n\nand your custom domain is just a `CNAME` over that same domain, GitLab\nserves\n\nthe `gitlab.io` certificate, and your browser receives mixed messages: on\none\n\nside, the browser is trying to access `YOURDOMAIN.org`, but on the other\nside\n\nit is getting a TLS certificate for `*.gitlab.io`,\n\nsignaling that something is wrong.\n\n\nIn order to fix it, you need to obtain a certificate for `YOURDOMAIN.org`\nand\n\nadd it to GitLab Pages. For that we are going to use\n\n[Let's Encrypt](https://letsencrypt.org/).\n\n\nLet's Encrypt is a new certificate authority that offers both *free* and\n\n*automated* certificates. That's perfect for us: we don't have to pay for\n\nhaving HTTPS and you can do everything within the comfort of your terminal.\n\n\nWe begin with downloading the `letsencrypt-auto` utility.\n\nOpen a new terminal window and type:\n\n\n```shell\n\n$ git clone https://github.com/letsencrypt/letsencrypt\n\n$ cd letsencrypt\n\n```\n\n\n`letsencrypt-auto` offers a lot of functionality. For example, if you have\n\na web server running Apache, you could add `letsencrypt-auto --apache`\ninside your\n\nwebserver and have everything done for you. `letsencrypt` targets primarily\nUnix-like\n\nwebservers, so the `letsencrypt-auto` tool won't work for Windows users.\nCheck [this\n\ntutorial][letsencryptwindows] to see how to get Let's Encrypt certificates\nwhile running\n\nWindows.\n\n\nSince we are running on GitLab's servers instead, we have to do a bit of\nmanual\n\nwork:\n\n\n```shell\n\n$ ./letsencrypt-auto certonly -a manual -d YOURDOMAIN.org\n\n#\n\n# If you want to support another domain, www.YOURDOMAIN.org, for example,\nyou\n\n# can add it to the domain list after -d like:\n\n# ./letsencrypt-auto certonly -a manual -d YOURDOMAIN.org www.YOURDOMAIN.org\n\n#\n\n```\n\n\nAfter you accept that your IP will be publicly logged, a message like the\n\nfollowing will appear:\n\n\n```shell\n\nMake sure your web server displays the following content at\n\nhttp://YOURDOMAIN.org/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM\n\nbefore continuing:\n\n\n5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.ewlbSYgvIxVOqiP1lD2zeDKWBGEZMRfO_4kJyLRP_4U\n\n\n#\n\n# output omitted\n\n#\n\n\nPress ENTER to continue\n\n```\n\n\nNow it is waiting for the server to be correctly configured so it can go on.\n\nLeave this terminal window open for now.\n\n\nSo, the goal is to the make our already-published static website return\n\nsaid token when said URL is requested. That's easy: create a custom\n\npage! Just create a file in your blog folder that looks like this:\n\n\n```markdown\n\n---\n\nlayout: null\n\npermalink:\n/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.html\n\n---\n\n\n5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.ewlbSYgvIxVOqiP1lD2zeDKWBGEZMRfO_4kJyLRP_4U\n\n```\n\n\nThis tells Jekyll to create a static page, which you can see at\n\n`cool-blog/_site/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.html`,\n\nwith no extra HTML, just the token in plain text. As we are using the\n`permalink` attribute in the\n\nfront matter, you can name this file anyway you want and put it anywhere,\ntoo.\n Note that the behaviour of the `permalink` attribute has\n[changed][jekyllversion] from Jekyll 2 to Jekyll 3, so make sure you have\nJekyll 3.x installed.\n\nIf you're not using version 3 of Jekyll or if you're using a different tool,\n\njust create the same file in the exact path, like\n\n`cool-blog/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.html`\n\nor an equivalent path in your static site generator of choice.\n\nHere we'll call it `letsencrypt-setup.html` and place it in the root folder\n\nof the blog. In order to check that everything is working as expected, start\na local server with `jekyll serve` in a separate terminal window and try to\naccess the URL:\n\n\n```shell\n\n$ curl\nhttp://localhost:4000/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM\n\n# response:\n\n5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM.ewlbSYgvIxVOqiP1lD2zeDKWBGEZMRfO_4kJyLRP_4U\n\n```\n\n\nNote that I just replaced the `http://YOURDOMAIN.org` (from the\n\n`letsencrypt-auto` instructions) with `http://localhost:4000`.\n\nEverything is working fine, so we just need to upload the new file to\nGitLab:\n\n\n```\n\n$ git add letsencrypt-setup.html\n\n$ git commit -m \"add letsencypt-setup.html file\"\n\n$ git push\n\n```\n\n\nOnce the build finishes, test again if everything is working well:\n\n\n```shell\n\n# Note that we're using the actual domain, not localhost anymore\n\n$ curl\nhttp://YOURDOMAIN.org/.well-known/acme-challenge/5TBu788fW0tQ5EOwZMdu1Gv3e9C33gxjV58hVtWTbDM\n\n```\n\n\nIf you get a `404 page not found`, check if you missed any step, or get in\ntouch\n\nin the comments below.\n\n\nNow that everything is working as expected, go back to the terminal window\n\nthat's waiting for you and hit `ENTER`. This instructs the Let's Encrypt's\n\nservers to go to the URL we just created. If they get the response they were\nwaiting for,\n\nwe've proven that we actually own the domain and now they'll send you the\n\nTLS certificates. After a while it responds:\n\n\n```\n\nIMPORTANT NOTES:\n - Congratulations! Your certificate and chain have been saved at\n   /etc/letsencrypt/live/YOURDOMAIN.org/fullchain.pem. Your cert will\n   expire on 2016-07-04. To obtain a new version of the certificate in\n   the future, simply run Let's Encrypt again.\n - If you like Let's Encrypt, please consider supporting our work by:\n\n   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate\n   Donating to EFF:                    https://eff.org/donate-le\n```\n\n\nSuccess! We have correctly acquired a free TLS certificate for our domain!\n\n\nNote, however, that like any other TLS certificate, it has an expiration\ndate,\n\nand in the case of certificates issued by Let's Encrypt, the certificate\nwill\n\nremain valid for 90 days. When you finish setting up, just put in your\ncalendar to\n\nremember to renew the certificate in time, otherwise it will become invalid,\n\nand the browser will reject it.\n\n\nNow we just need to upload the certificate and the key to GitLab.\n\nGo to **Settings** -> **Pages** inside your project, remove the old `CNAME`\nand\n\nadd a new one with the same domain, but now you'll also upload the TLS\n\ncertificate. Paste the contents of\n`/etc/letsencrypt/live/YOURDOMAIN.org/fullchain.pem`\n\n(you'll need `sudo` to read the file) to the \"Certificate (PEM)\"\n field and `/etc/letsencrypt/live/YOURDOMAIN.org/privkey.pem` (also needs `sudo`) to the\n\"Key (PEM)\" field.\n\n\n![Uploading the certificate to GitLab\nPages](https://about.gitlab.com/images/blogimages/gitlab-pages-cert-upload-screenshot.png)\n\n\nAnd you're done! You now have a fully working HTTPS website:\n\n\n```shell\n\n$ curl -vX HEAD https://YOURDOMAIN.org/\n\n#\n\n# starting connection\n\n#\n\n* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n\n* Server certificate: YOURDOMAIN.org\n\n* Server certificate: Lets Encrypt Authority X3\n\n* Server certificate: DST Root CA X3\n\n```\n\n\n## How to redirect all traffic to the HTTPS version\n\n\nEverything is working fine, but now we have an extra concern: we have two\n\nworking versions of our website, both HTTP **and** HTTPS. We need a way to\n\nredirect all of our traffic to the HTTPS version, and tell search engines to\n\ndo the same.\n\n\n### How to tell search engines which is the correct version\n\n\nInstructing the search engines is really easy: just tell them that the HTTPS\n\nversion is the \"canonical\" version, and they send all the users to it.\n\nAnd how do you do that? By adding a `link` tag to the header of the HTML:\n\n\n```html\n\n\u003Clink rel=\"canonical\" href=\"https://YOURDOMAIN.org/specific/page\" />\n\n```\n\n\nAdding this to every header on a blog tells the search engine that the\ncorrect\n\nversion is the HTTPS one, and they'll comply.\n\n\n### Internal links\n\n\nRemember to use HTTPS for your CSS or JavaScript file URLs, because when the\n\nbrowser accesses a secure website that relies on an insecure resource, it\nmay\n\nblock that resource.\n\n\nIt is [considered a good practice][relativeprotocol] to use the\nprotocol-agnostic path:\n\n\n```\n\n\u003Clink rel=\"stylesheet\" href=\"//YOURDOMAIN.org/styles.css\" />\n\n\u003Cscript src=\"//YOURDOMAIN.org/script.js\">\u003C/script>\n\n```\n\n\n### When to use JavaScript-based redirect\n\n\nThere is, however, a case where the user specifically types in the URL\n\n**without** using HTTPS, and they'll access the HTTP version of your\nwebsite.\n\n\nThe correct way of handling that would be to respond with a 301 \"Moved\n\npermanently\" HTTP code, and the browser would remember it for the next\nrequest.\n\nHowever, that's not a possibility we have here, since we're running on\nGitLab's servers.\n\n\nA small hack you can do is to redirect your users with a bit of JavaScript\ncode:\n\n\n```javascript\n\nvar host = \"YOURDOMAIN.org\";\n\nif ((host == window.location.host) && (window.location.protocol !=\n'https:')) {\n  window.location = window.location.toString().replace(/^http:/, \"https:\");\n}\n\n```\n\n\nThis redirects the user to the HTTPS version, but there are a few problems\nwith it:\n\n\n1. a user could have JavaScript disabled, and would not be affected by that;\n\n2. an attacker could simply remove that code and behave as a [Man in the\nMiddle][middleattack];\n\n3. the browser won't remember the redirect instruction, so every time the\nuser types\n\nthat same URL, the website will have to redirect him/her again.\n\n\n## Wrap up\n\n\n![a working certificate\nscreenshot](https://about.gitlab.com/images/blogimages/working-certificate-screenshot.png)\n\n\nThat's how easy it is to have a free HTTPS-enabled website.\n\nWith these tools, I see no reason not to do it.\n\n\nIf you want to improve GitLab's support for Let's Encrypt, you can\n\ndiscuss and contribute in issues [#474][issue474], [#467][issue467] and\n\n[#472][issue472] from GitLab EE. They are open to merge requests!\n\n\nThere's an [excellent talk][talk] by [Pierre Far][pierretwitter] and\n\n[Ilya Grigorik][ilyatwitter] on HTTPS where you can learn more\n\nabout it.\n\n\nIf you want to check the status of your HTTPS enabled website,\n\n[SSL Labs offers a free online service][ssltest] that\n\n\"performs a deep analysis of the configuration of any SSL web server on the\n\npublic Internet\".\n\n\nThis article is based on [Paul Wakeford's post][wakeford].\n\n\nI hope it helps you :)\n\n\n[Create a project]:\nhttps://docs.gitlab.com/ee/user/project/working_with_projects.html#create-a-project\n\n[Jekyll]: https://jekyllrb.com/\n\n[examplepages]: https://gitlab.com/groups/pages\n\n[pagesdocs]:\nhttp://doc.gitlab.com/ee/pages/README.html#getting-started-with-gitlab-pages\n\n[TLSwiki]: https://en.wikipedia.org/wiki/Transport_Layer_Security#TLS_1.0\n\n[letsencrypt]: https://letsencrypt.org/\n\n[wakeford]: https://www.paulwakeford.info/2015/11/24/letsencrypt/\n\n[publicbeta]: https://letsencrypt.org/2015/12/03/entering-public-beta.html\n\n[ssltest]: https://www.ssllabs.com/ssltest/\n\n[middleattack]: https://en.wikipedia.org/wiki/Man-in-the-middle_attack\n\n[talk]: https://www.youtube.com/watch?v=cBhZ6S0PFCY\n\n[relativeprotocol]: http://www.paulirish.com/2010/the-protocol-relative-url/\n\n[jekyllversion]:\nhttps://jekyllrb.com/docs/upgrading/2-to-3/#permalinks-no-longer-automatically-add-a-trailing-slash\n\n[letsencryptwindows]: https://cultiv.nl/blog/lets-encrypt-on-windows/\n\n[customdomain]:\nhttp://doc.gitlab.com/ee/pages/README.html#add-a-custom-domain-to-your-pages-website\n\n[certificateauthority]: https://en.wikipedia.org/wiki/Certificate_authority\n\n[limitation]: http://doc.gitlab.com/ee/pages/README.html#limitations\n\n[issue474]: https://gitlab.com/gitlab-org/gitlab-ee/issues/474\n\n[issue472]: https://gitlab.com/gitlab-org/gitlab-ee/issues/472\n\n[issue467]: https://gitlab.com/gitlab-org/gitlab-ee/issues/467\n\n[pierretwitter]: https://twitter.com/pierrefar\n\n[ilyatwitter]: https://twitter.com/igrigorik\n","engineering",{"slug":23,"featured":6,"template":24},"tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt","BlogPost","content:en-us:blog:tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt.yml","yaml","Tutorial Securing Your Gitlab Pages With Tls And Letsencrypt","content","en-us/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt.yml","en-us/blog/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt","yml",{"_path":33,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":35,"_id":457,"_type":26,"title":458,"_source":28,"_file":459,"_stem":460,"_extension":31},"/shared/en-us/main-navigation","en-us",{"logo":36,"freeTrial":41,"sales":46,"login":51,"items":56,"search":388,"minimal":419,"duo":438,"pricingDeployment":447},{"config":37},{"href":38,"dataGaName":39,"dataGaLocation":40},"/","gitlab logo","header",{"text":42,"config":43},"Get free trial",{"href":44,"dataGaName":45,"dataGaLocation":40},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":47,"config":48},"Talk to sales",{"href":49,"dataGaName":50,"dataGaLocation":40},"/sales/","sales",{"text":52,"config":53},"Sign in",{"href":54,"dataGaName":55,"dataGaLocation":40},"https://gitlab.com/users/sign_in/","sign in",[57,101,199,204,309,369],{"text":58,"config":59,"cards":61,"footer":84},"Platform",{"dataNavLevelOne":60},"platform",[62,68,76],{"title":58,"description":63,"link":64},"The most comprehensive AI-powered DevSecOps Platform",{"text":65,"config":66},"Explore our Platform",{"href":67,"dataGaName":60,"dataGaLocation":40},"/platform/",{"title":69,"description":70,"link":71},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":72,"config":73},"Meet GitLab Duo",{"href":74,"dataGaName":75,"dataGaLocation":40},"/gitlab-duo/","gitlab duo ai",{"title":77,"description":78,"link":79},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":80,"config":81},"Learn more",{"href":82,"dataGaName":83,"dataGaLocation":40},"/why-gitlab/","why gitlab",{"title":85,"items":86},"Get started with",[87,92,97],{"text":88,"config":89},"Platform Engineering",{"href":90,"dataGaName":91,"dataGaLocation":40},"/solutions/platform-engineering/","platform engineering",{"text":93,"config":94},"Developer Experience",{"href":95,"dataGaName":96,"dataGaLocation":40},"/developer-experience/","Developer experience",{"text":98,"config":99},"MLOps",{"href":100,"dataGaName":98,"dataGaLocation":40},"/topics/devops/the-role-of-ai-in-devops/",{"text":102,"left":103,"config":104,"link":106,"lists":110,"footer":181},"Product",true,{"dataNavLevelOne":105},"solutions",{"text":107,"config":108},"View all Solutions",{"href":109,"dataGaName":105,"dataGaLocation":40},"/solutions/",[111,136,160],{"title":112,"description":113,"link":114,"items":119},"Automation","CI/CD and automation to accelerate deployment",{"config":115},{"icon":116,"href":117,"dataGaName":118,"dataGaLocation":40},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[120,124,128,132],{"text":121,"config":122},"CI/CD",{"href":123,"dataGaLocation":40,"dataGaName":121},"/solutions/continuous-integration/",{"text":125,"config":126},"AI-Assisted Development",{"href":74,"dataGaLocation":40,"dataGaName":127},"AI assisted development",{"text":129,"config":130},"Source Code Management",{"href":131,"dataGaLocation":40,"dataGaName":129},"/solutions/source-code-management/",{"text":133,"config":134},"Automated Software Delivery",{"href":117,"dataGaLocation":40,"dataGaName":135},"Automated software delivery",{"title":137,"description":138,"link":139,"items":144},"Security","Deliver code faster without compromising security",{"config":140},{"href":141,"dataGaName":142,"dataGaLocation":40,"icon":143},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[145,150,155],{"text":146,"config":147},"Application Security Testing",{"href":148,"dataGaName":149,"dataGaLocation":40},"/solutions/application-security-testing/","Application security testing",{"text":151,"config":152},"Software Supply Chain Security",{"href":153,"dataGaLocation":40,"dataGaName":154},"/solutions/supply-chain/","Software supply chain security",{"text":156,"config":157},"Software Compliance",{"href":158,"dataGaName":159,"dataGaLocation":40},"/solutions/software-compliance/","software compliance",{"title":161,"link":162,"items":167},"Measurement",{"config":163},{"icon":164,"href":165,"dataGaName":166,"dataGaLocation":40},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[168,172,176],{"text":169,"config":170},"Visibility & Measurement",{"href":165,"dataGaLocation":40,"dataGaName":171},"Visibility and Measurement",{"text":173,"config":174},"Value Stream Management",{"href":175,"dataGaLocation":40,"dataGaName":173},"/solutions/value-stream-management/",{"text":177,"config":178},"Analytics & Insights",{"href":179,"dataGaLocation":40,"dataGaName":180},"/solutions/analytics-and-insights/","Analytics and insights",{"title":182,"items":183},"GitLab for",[184,189,194],{"text":185,"config":186},"Enterprise",{"href":187,"dataGaLocation":40,"dataGaName":188},"/enterprise/","enterprise",{"text":190,"config":191},"Small Business",{"href":192,"dataGaLocation":40,"dataGaName":193},"/small-business/","small business",{"text":195,"config":196},"Public Sector",{"href":197,"dataGaLocation":40,"dataGaName":198},"/solutions/public-sector/","public sector",{"text":200,"config":201},"Pricing",{"href":202,"dataGaName":203,"dataGaLocation":40,"dataNavLevelOne":203},"/pricing/","pricing",{"text":205,"config":206,"link":208,"lists":212,"feature":296},"Resources",{"dataNavLevelOne":207},"resources",{"text":209,"config":210},"View all resources",{"href":211,"dataGaName":207,"dataGaLocation":40},"/resources/",[213,246,268],{"title":214,"items":215},"Getting started",[216,221,226,231,236,241],{"text":217,"config":218},"Install",{"href":219,"dataGaName":220,"dataGaLocation":40},"/install/","install",{"text":222,"config":223},"Quick start guides",{"href":224,"dataGaName":225,"dataGaLocation":40},"/get-started/","quick setup checklists",{"text":227,"config":228},"Learn",{"href":229,"dataGaLocation":40,"dataGaName":230},"https://university.gitlab.com/","learn",{"text":232,"config":233},"Product documentation",{"href":234,"dataGaName":235,"dataGaLocation":40},"https://docs.gitlab.com/","product documentation",{"text":237,"config":238},"Best practice videos",{"href":239,"dataGaName":240,"dataGaLocation":40},"/getting-started-videos/","best practice videos",{"text":242,"config":243},"Integrations",{"href":244,"dataGaName":245,"dataGaLocation":40},"/integrations/","integrations",{"title":247,"items":248},"Discover",[249,254,258,263],{"text":250,"config":251},"Customer success stories",{"href":252,"dataGaName":253,"dataGaLocation":40},"/customers/","customer success stories",{"text":255,"config":256},"Blog",{"href":257,"dataGaName":5,"dataGaLocation":40},"/blog/",{"text":259,"config":260},"Remote",{"href":261,"dataGaName":262,"dataGaLocation":40},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":264,"config":265},"TeamOps",{"href":266,"dataGaName":267,"dataGaLocation":40},"/teamops/","teamops",{"title":269,"items":270},"Connect",[271,276,281,286,291],{"text":272,"config":273},"GitLab Services",{"href":274,"dataGaName":275,"dataGaLocation":40},"/services/","services",{"text":277,"config":278},"Community",{"href":279,"dataGaName":280,"dataGaLocation":40},"/community/","community",{"text":282,"config":283},"Forum",{"href":284,"dataGaName":285,"dataGaLocation":40},"https://forum.gitlab.com/","forum",{"text":287,"config":288},"Events",{"href":289,"dataGaName":290,"dataGaLocation":40},"/events/","events",{"text":292,"config":293},"Partners",{"href":294,"dataGaName":295,"dataGaLocation":40},"/partners/","partners",{"backgroundColor":297,"textColor":298,"text":299,"image":300,"link":304},"#2f2a6b","#fff","Insights for the future of software development",{"altText":301,"config":302},"the source promo card",{"src":303},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":305,"config":306},"Read the latest",{"href":307,"dataGaName":308,"dataGaLocation":40},"/the-source/","the source",{"text":310,"config":311,"lists":313},"Company",{"dataNavLevelOne":312},"company",[314],{"items":315},[316,321,327,329,334,339,344,349,354,359,364],{"text":317,"config":318},"About",{"href":319,"dataGaName":320,"dataGaLocation":40},"/company/","about",{"text":322,"config":323,"footerGa":326},"Jobs",{"href":324,"dataGaName":325,"dataGaLocation":40},"/jobs/","jobs",{"dataGaName":325},{"text":287,"config":328},{"href":289,"dataGaName":290,"dataGaLocation":40},{"text":330,"config":331},"Leadership",{"href":332,"dataGaName":333,"dataGaLocation":40},"/company/team/e-group/","leadership",{"text":335,"config":336},"Team",{"href":337,"dataGaName":338,"dataGaLocation":40},"/company/team/","team",{"text":340,"config":341},"Handbook",{"href":342,"dataGaName":343,"dataGaLocation":40},"https://handbook.gitlab.com/","handbook",{"text":345,"config":346},"Investor relations",{"href":347,"dataGaName":348,"dataGaLocation":40},"https://ir.gitlab.com/","investor relations",{"text":350,"config":351},"Trust Center",{"href":352,"dataGaName":353,"dataGaLocation":40},"/security/","trust center",{"text":355,"config":356},"AI Transparency Center",{"href":357,"dataGaName":358,"dataGaLocation":40},"/ai-transparency-center/","ai transparency center",{"text":360,"config":361},"Newsletter",{"href":362,"dataGaName":363,"dataGaLocation":40},"/company/contact/","newsletter",{"text":365,"config":366},"Press",{"href":367,"dataGaName":368,"dataGaLocation":40},"/press/","press",{"text":370,"config":371,"lists":372},"Contact us",{"dataNavLevelOne":312},[373],{"items":374},[375,378,383],{"text":47,"config":376},{"href":49,"dataGaName":377,"dataGaLocation":40},"talk to sales",{"text":379,"config":380},"Get help",{"href":381,"dataGaName":382,"dataGaLocation":40},"/support/","get help",{"text":384,"config":385},"Customer portal",{"href":386,"dataGaName":387,"dataGaLocation":40},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":389,"login":390,"suggestions":397},"Close",{"text":391,"link":392},"To search repositories and projects, login to",{"text":393,"config":394},"gitlab.com",{"href":54,"dataGaName":395,"dataGaLocation":396},"search login","search",{"text":398,"default":399},"Suggestions",[400,402,406,408,412,416],{"text":69,"config":401},{"href":74,"dataGaName":69,"dataGaLocation":396},{"text":403,"config":404},"Code Suggestions (AI)",{"href":405,"dataGaName":403,"dataGaLocation":396},"/solutions/code-suggestions/",{"text":121,"config":407},{"href":123,"dataGaName":121,"dataGaLocation":396},{"text":409,"config":410},"GitLab on AWS",{"href":411,"dataGaName":409,"dataGaLocation":396},"/partners/technology-partners/aws/",{"text":413,"config":414},"GitLab on Google Cloud",{"href":415,"dataGaName":413,"dataGaLocation":396},"/partners/technology-partners/google-cloud-platform/",{"text":417,"config":418},"Why GitLab?",{"href":82,"dataGaName":417,"dataGaLocation":396},{"freeTrial":420,"mobileIcon":425,"desktopIcon":430,"secondaryButton":433},{"text":421,"config":422},"Start free trial",{"href":423,"dataGaName":45,"dataGaLocation":424},"https://gitlab.com/-/trials/new/","nav",{"altText":426,"config":427},"Gitlab Icon",{"src":428,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":426,"config":431},{"src":432,"dataGaName":429,"dataGaLocation":424},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":434,"config":435},"Get Started",{"href":436,"dataGaName":437,"dataGaLocation":424},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":439,"mobileIcon":443,"desktopIcon":445},{"text":440,"config":441},"Learn more about GitLab Duo",{"href":74,"dataGaName":442,"dataGaLocation":424},"gitlab duo",{"altText":426,"config":444},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":446},{"src":432,"dataGaName":429,"dataGaLocation":424},{"freeTrial":448,"mobileIcon":453,"desktopIcon":455},{"text":449,"config":450},"Back to pricing",{"href":202,"dataGaName":451,"dataGaLocation":424,"icon":452},"back to pricing","GoBack",{"altText":426,"config":454},{"src":428,"dataGaName":429,"dataGaLocation":424},{"altText":426,"config":456},{"src":432,"dataGaName":429,"dataGaLocation":424},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":462,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"title":463,"button":464,"image":469,"config":473,"_id":475,"_type":26,"_source":28,"_file":476,"_stem":477,"_extension":31},"/shared/en-us/banner","is now in public beta!",{"text":465,"config":466},"Try the Beta",{"href":467,"dataGaName":468,"dataGaLocation":40},"/gitlab-duo/agent-platform/","duo banner",{"altText":470,"config":471},"GitLab Duo Agent Platform",{"src":472},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":474},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":479,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"data":480,"_id":684,"_type":26,"title":685,"_source":28,"_file":686,"_stem":687,"_extension":31},"/shared/en-us/main-footer",{"text":481,"source":482,"edit":488,"contribute":493,"config":498,"items":503,"minimal":676},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":483,"config":484},"View page source",{"href":485,"dataGaName":486,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":489,"config":490},"Edit this page",{"href":491,"dataGaName":492,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":494,"config":495},"Please contribute",{"href":496,"dataGaName":497,"dataGaLocation":487},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":499,"facebook":500,"youtube":501,"linkedin":502},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[504,527,583,612,646],{"title":58,"links":505,"subMenu":510},[506],{"text":507,"config":508},"DevSecOps platform",{"href":67,"dataGaName":509,"dataGaLocation":487},"devsecops platform",[511],{"title":200,"links":512},[513,517,522],{"text":514,"config":515},"View plans",{"href":202,"dataGaName":516,"dataGaLocation":487},"view plans",{"text":518,"config":519},"Why Premium?",{"href":520,"dataGaName":521,"dataGaLocation":487},"/pricing/premium/","why premium",{"text":523,"config":524},"Why Ultimate?",{"href":525,"dataGaName":526,"dataGaLocation":487},"/pricing/ultimate/","why ultimate",{"title":528,"links":529},"Solutions",[530,535,537,539,544,549,553,556,560,565,567,570,573,578],{"text":531,"config":532},"Digital transformation",{"href":533,"dataGaName":534,"dataGaLocation":487},"/topics/digital-transformation/","digital transformation",{"text":146,"config":536},{"href":148,"dataGaName":146,"dataGaLocation":487},{"text":135,"config":538},{"href":117,"dataGaName":118,"dataGaLocation":487},{"text":540,"config":541},"Agile development",{"href":542,"dataGaName":543,"dataGaLocation":487},"/solutions/agile-delivery/","agile delivery",{"text":545,"config":546},"Cloud transformation",{"href":547,"dataGaName":548,"dataGaLocation":487},"/topics/cloud-native/","cloud transformation",{"text":550,"config":551},"SCM",{"href":131,"dataGaName":552,"dataGaLocation":487},"source code management",{"text":121,"config":554},{"href":123,"dataGaName":555,"dataGaLocation":487},"continuous integration & delivery",{"text":557,"config":558},"Value stream management",{"href":175,"dataGaName":559,"dataGaLocation":487},"value stream management",{"text":561,"config":562},"GitOps",{"href":563,"dataGaName":564,"dataGaLocation":487},"/solutions/gitops/","gitops",{"text":185,"config":566},{"href":187,"dataGaName":188,"dataGaLocation":487},{"text":568,"config":569},"Small business",{"href":192,"dataGaName":193,"dataGaLocation":487},{"text":571,"config":572},"Public sector",{"href":197,"dataGaName":198,"dataGaLocation":487},{"text":574,"config":575},"Education",{"href":576,"dataGaName":577,"dataGaLocation":487},"/solutions/education/","education",{"text":579,"config":580},"Financial services",{"href":581,"dataGaName":582,"dataGaLocation":487},"/solutions/finance/","financial services",{"title":205,"links":584},[585,587,589,591,594,596,598,600,602,604,606,608,610],{"text":217,"config":586},{"href":219,"dataGaName":220,"dataGaLocation":487},{"text":222,"config":588},{"href":224,"dataGaName":225,"dataGaLocation":487},{"text":227,"config":590},{"href":229,"dataGaName":230,"dataGaLocation":487},{"text":232,"config":592},{"href":234,"dataGaName":593,"dataGaLocation":487},"docs",{"text":255,"config":595},{"href":257,"dataGaName":5,"dataGaLocation":487},{"text":250,"config":597},{"href":252,"dataGaName":253,"dataGaLocation":487},{"text":259,"config":599},{"href":261,"dataGaName":262,"dataGaLocation":487},{"text":272,"config":601},{"href":274,"dataGaName":275,"dataGaLocation":487},{"text":264,"config":603},{"href":266,"dataGaName":267,"dataGaLocation":487},{"text":277,"config":605},{"href":279,"dataGaName":280,"dataGaLocation":487},{"text":282,"config":607},{"href":284,"dataGaName":285,"dataGaLocation":487},{"text":287,"config":609},{"href":289,"dataGaName":290,"dataGaLocation":487},{"text":292,"config":611},{"href":294,"dataGaName":295,"dataGaLocation":487},{"title":310,"links":613},[614,616,618,620,622,624,626,630,635,637,639,641],{"text":317,"config":615},{"href":319,"dataGaName":312,"dataGaLocation":487},{"text":322,"config":617},{"href":324,"dataGaName":325,"dataGaLocation":487},{"text":330,"config":619},{"href":332,"dataGaName":333,"dataGaLocation":487},{"text":335,"config":621},{"href":337,"dataGaName":338,"dataGaLocation":487},{"text":340,"config":623},{"href":342,"dataGaName":343,"dataGaLocation":487},{"text":345,"config":625},{"href":347,"dataGaName":348,"dataGaLocation":487},{"text":627,"config":628},"Sustainability",{"href":629,"dataGaName":627,"dataGaLocation":487},"/sustainability/",{"text":631,"config":632},"Diversity, inclusion and belonging (DIB)",{"href":633,"dataGaName":634,"dataGaLocation":487},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":350,"config":636},{"href":352,"dataGaName":353,"dataGaLocation":487},{"text":360,"config":638},{"href":362,"dataGaName":363,"dataGaLocation":487},{"text":365,"config":640},{"href":367,"dataGaName":368,"dataGaLocation":487},{"text":642,"config":643},"Modern Slavery Transparency Statement",{"href":644,"dataGaName":645,"dataGaLocation":487},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":647,"links":648},"Contact Us",[649,652,654,656,661,666,671],{"text":650,"config":651},"Contact an expert",{"href":49,"dataGaName":50,"dataGaLocation":487},{"text":379,"config":653},{"href":381,"dataGaName":382,"dataGaLocation":487},{"text":384,"config":655},{"href":386,"dataGaName":387,"dataGaLocation":487},{"text":657,"config":658},"Status",{"href":659,"dataGaName":660,"dataGaLocation":487},"https://status.gitlab.com/","status",{"text":662,"config":663},"Terms of use",{"href":664,"dataGaName":665,"dataGaLocation":487},"/terms/","terms of use",{"text":667,"config":668},"Privacy statement",{"href":669,"dataGaName":670,"dataGaLocation":487},"/privacy/","privacy statement",{"text":672,"config":673},"Cookie preferences",{"dataGaName":674,"dataGaLocation":487,"id":675,"isOneTrustButton":103},"cookie preferences","ot-sdk-btn",{"items":677},[678,680,682],{"text":662,"config":679},{"href":664,"dataGaName":665,"dataGaLocation":487},{"text":667,"config":681},{"href":669,"dataGaName":670,"dataGaLocation":487},{"text":672,"config":683},{"dataGaName":674,"dataGaLocation":487,"id":675,"isOneTrustButton":103},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[689],{"_path":690,"_dir":691,"_draft":6,"_partial":6,"_locale":7,"content":692,"config":696,"_id":698,"_type":26,"title":699,"_source":28,"_file":700,"_stem":701,"_extension":31},"/en-us/blog/authors/guest-author-andr-miranda","authors",{"name":18,"config":693},{"headshot":694,"ctfId":695},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","Guest-author-Andr-Miranda",{"template":697},"BlogAuthor","content:en-us:blog:authors:guest-author-andr-miranda.yml","Guest Author Andr Miranda","en-us/blog/authors/guest-author-andr-miranda.yml","en-us/blog/authors/guest-author-andr-miranda",{"_path":703,"_dir":34,"_draft":6,"_partial":6,"_locale":7,"header":704,"eyebrow":705,"blurb":706,"button":707,"secondaryButton":711,"_id":713,"_type":26,"title":714,"_source":28,"_file":715,"_stem":716,"_extension":31},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":42,"config":708},{"href":709,"dataGaName":45,"dataGaLocation":710},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":47,"config":712},{"href":49,"dataGaName":50,"dataGaLocation":710},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758662353084]