GitLab Pages is a service that lets you publish static websites directly from your GitLab repository, no external hosting needed.
Let’s say you have a project with a static site, like a documentation site generated by Hugo or a simple HTML/CSS/JS app. You want to deploy it so anyone can visit it via a your-group.gitlab.io/your-project URL.
Here’s a typical .gitlab-ci.yml file that accomplishes this:
pages:
stage: deploy
script:
- mv public public/ # This command is a trick to create an empty directory if public is empty
- cp -r . public/ # Copy all files from the root directory to public/
artifacts:
paths:
- public
only:
- main
When you push changes to your main branch, GitLab CI/CD kicks in. The pages job runs. The script section is where the magic happens.
The first command, mv public public/, is a bit of a hack. If your build process doesn’t create a public directory (or if it’s empty), GitLab Pages won’t know what to serve. This command ensures there’s always a public directory, even if it’s empty.
The second command, cp -r . public/, is the core of this basic setup. It copies everything from the root of your repository into a directory named public. GitLab Pages expects your site’s files to be in a folder called public at the root of your artifact. This command effectively makes your entire repository the content of your static site.
The artifacts: paths: - public section tells GitLab CI/CD to collect the public directory after the script finishes and make it available for the Pages deployment.
Finally, only: - main ensures this deployment job only runs when you push to the main branch. You could change this to master, production, or any other branch.
Once the pipeline completes successfully, your site will be available at https://your-group.gitlab.io/your-project.
Now, let’s look at what happens under the hood when GitLab CI/CD runs this job. GitLab spins up a runner, which is essentially a container or VM. This runner executes your script commands. It copies your project files into the public directory. Then, GitLab takes that public directory artifact and uploads it to its GitLab Pages infrastructure. This infrastructure then serves your files over HTTP/S.
The crucial part here is that GitLab Pages only serves static files. It doesn’t run any server-side code. Your build process (like Hugo, Jekyll, or just manual HTML) must generate all the HTML, CSS, and JavaScript files before they are copied into the public directory.
Consider a slightly more complex scenario where you do have a build step. Let’s say you’re using Hugo. Your .gitlab-ci.yml might look like this:
image: registry.gitlab.com/pages/hugo/hugo_extended:latest
pages:
stage: deploy
script:
- hugo --minify
artifacts:
paths:
- public
only:
- main
Here, the image specifies a Docker image that has Hugo pre-installed. The script now simply runs hugo --minify. Hugo’s default behavior is to build the site into a public directory in the project’s root. The artifacts then picks up this generated public directory. This is a much cleaner approach when your site requires a build process.
The most surprising thing about GitLab Pages is that it’s not just for hosting static sites, but for deploying them directly from your Git repository’s history. Every commit to your designated branch can trigger a new version of your site, making rollbacks and version control of your website content incredibly straightforward.
The exact levers you control are primarily within your .gitlab-ci.yml: the script section defines how your site is built and prepared, and the artifacts: paths section defines what gets deployed. You can also configure custom domains, HTTPS, and redirects through GitLab’s project settings, but the core deployment mechanism is driven by this CI/CD configuration.
One common misconception is that GitLab Pages is slow to update. In reality, once the pipeline succeeds, the site is typically live within a minute or two. The perceived slowness often comes from browser caching or a misunderstanding of when the pipeline actually finishes.
The next concept you’ll likely explore is setting up custom domains and enabling HTTPS for your GitLab Pages site.