1---
2stage: Release
3group: Release
4info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
5---
6
7# Exploring GitLab Pages **(FREE)**
8
9This document is a user guide to explore the options and settings
10GitLab Pages offers.
11
12To familiarize yourself with GitLab Pages first:
13
14- Read an [introduction to GitLab Pages](index.md).
15- Learn [how to get started with Pages](index.md#getting-started).
16- Learn how to enable GitLab Pages
17  across your GitLab instance on the [administrator documentation](../../../administration/pages/index.md).
18
19## GitLab Pages requirements
20
21In brief, this is what you need to upload your website in GitLab Pages:
22
231. Domain of the instance: domain name that is used for GitLab Pages
24   (ask your administrator).
251. GitLab CI/CD: a `.gitlab-ci.yml` file with a specific job named [`pages`](../../../ci/yaml/index.md#pages) in the root directory of your repository.
261. A directory called `public` in your site's repository containing the content
27   to be published.
281. GitLab Runner enabled for the project.
29
30## GitLab Pages on GitLab.com
31
32If you are using [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlabcom) to host your website, then:
33
34- The domain name for GitLab Pages on GitLab.com is `gitlab.io`.
35- Custom domains and TLS support are enabled.
36- Shared runners are enabled by default, provided for free and can be used to
37  build your website. If you want you can still bring your own runner.
38
39## Example projects
40
41Visit the [GitLab Pages group](https://gitlab.com/groups/pages) for a complete list of example projects. Contributions are very welcome.
42
43## Custom error codes Pages
44
45You can provide your own 403 and 404 error pages by creating the `403.html` and
46`404.html` files respectively in the root directory of the `public/` directory
47that are included in the artifacts. Usually this is the root directory of
48your project, but that may differ depending on your static generator
49configuration.
50
51If the case of `404.html`, there are different scenarios. For example:
52
53- If you use project Pages (served under `/projectname/`) and try to access
54  `/projectname/non/existing_file`, GitLab Pages tries to serve first
55  `/projectname/404.html`, and then `/404.html`.
56- If you use user/group Pages (served under `/`) and try to access
57  `/non/existing_file` GitLab Pages tries to serve `/404.html`.
58- If you use a custom domain and try to access `/non/existing_file`, GitLab
59  Pages tries to serve only `/404.html`.
60
61## Redirects in GitLab Pages
62
63You can configure redirects for your site using a `_redirects` file. To learn more, read
64the [redirects documentation](redirects.md).
65
66## GitLab Pages Access Control **(FREE)**
67
68To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.md).
69
70## Unpublishing your Pages
71
72If you ever feel the need to purge your Pages content, you can do so by going
73to your project's settings through the gear icon in the top right, and then
74navigating to **Pages**. Click the **Remove pages** button to delete your Pages
75website.
76
77![Remove pages](img/remove_pages.png)
78
79## Limitations
80
81When using Pages under the general domain of a GitLab instance (`*.example.io`),
82you _cannot_ use HTTPS with sub-subdomains. That means that if your
83username or group name contains a dot, for example `foo.bar`, the domain
84`https://foo.bar.example.io` does _not_ work. This is a limitation of the
85[HTTP Over TLS protocol](https://tools.ietf.org/html/rfc2818#section-3.1).
86HTTP pages continue to work provided you don't redirect HTTP to HTTPS.
87
88GitLab Pages [does **not** support group websites for subgroups](../../group/subgroups/index.md#limitations).
89You can only create the highest-level group website.
90
91## Specific configuration options for Pages
92
93Learn how to set up GitLab CI/CD for specific use cases.
94
95### `.gitlab-ci.yml` for plain HTML websites
96
97Supposed your repository contained the following files:
98
99```plaintext
100├── index.html
101├── css
102│   └── main.css
103└── js
104    └── main.js
105```
106
107Then the `.gitlab-ci.yml` example below simply moves all files from the root
108directory of the project to the `public/` directory. The `.public` workaround
109is so `cp` doesn't also copy `public/` to itself in an infinite loop:
110
111```yaml
112pages:
113  script:
114    - mkdir .public
115    - cp -r * .public
116    - mv .public public
117  artifacts:
118    paths:
119      - public
120  only:
121    - main
122```
123
124### `.gitlab-ci.yml` for a static site generator
125
126See this document for a [step-by-step guide](getting_started/pages_from_scratch.md).
127
128### `.gitlab-ci.yml` for a repository where there's also actual code
129
130Remember that GitLab Pages are by default branch/tag agnostic and their
131deployment relies solely on what you specify in `.gitlab-ci.yml`. You can limit
132the `pages` job with the [`only` parameter](../../../ci/yaml/index.md#only--except),
133whenever a new commit is pushed to a branch used specifically for your
134pages.
135
136That way, you can have your project's code in the `main` branch and use an
137orphan branch (let's name it `pages`) to host your static generator site.
138
139You can create a new empty branch like this:
140
141```shell
142git checkout --orphan pages
143```
144
145The first commit made on this new branch has no parents and is the root of a
146new history totally disconnected from all the other branches and commits.
147Push the source files of your static generator in the `pages` branch.
148
149Below is a copy of `.gitlab-ci.yml` where the most significant line is the last
150one, specifying to execute everything in the `pages` branch:
151
152```yaml
153image: ruby:2.6
154
155pages:
156  script:
157    - gem install jekyll
158    - jekyll build -d public/
159  artifacts:
160    paths:
161      - public
162  only:
163    - pages
164```
165
166See an example that has different files in the [`main` branch](https://gitlab.com/pages/jekyll-branched/tree/main)
167and the source files for Jekyll are in a [`pages` branch](https://gitlab.com/pages/jekyll-branched/tree/pages) which
168also includes `.gitlab-ci.yml`.
169
170### Serving compressed assets
171
172Most modern browsers support downloading files in a compressed format. This
173speeds up downloads by reducing the size of files.
174
175Before serving an uncompressed file, Pages checks if the same file exists with
176a `.br` or `.gz` extension. If it does, and the browser supports receiving
177compressed files, it serves that version instead of the uncompressed one.
178
179To take advantage of this feature, the artifact you upload to the Pages should
180have this structure:
181
182```plaintext
183public/
184├─┬ index.html
185│ | index.html.br
186│ └ index.html.gz
187188├── css/
189│   └─┬ main.css
190│     | main.css.br
191│     └ main.css.gz
192193└── js/
194    └─┬ main.js
195      | main.js.br
196main.js.gz
197```
198
199This can be achieved by including a `script:` command like this in your
200`.gitlab-ci.yml` pages job:
201
202```yaml
203pages:
204  # Other directives
205  script:
206    # Build the public/ directory first
207    - find public -type f -regex '.*\.\(htm\|html\|txt\|text\|js\|css\)$' -exec gzip -f -k {} \;
208    - find public -type f -regex '.*\.\(htm\|html\|txt\|text\|js\|css\)$' -exec brotli -f -k {} \;
209```
210
211By pre-compressing the files and including both versions in the artifact, Pages
212can serve requests for both compressed and uncompressed content without
213needing to compress files on-demand.
214
215### Resolving ambiguous URLs
216
217> [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/95) in GitLab 11.8
218
219GitLab Pages makes assumptions about which files to serve when receiving a
220request for a URL that does not include an extension.
221
222Consider a Pages site deployed with the following files:
223
224```plaintext
225public/
226├── index.html
227├── data.html
228├── info.html
229├── data/
230│   └── index.html
231└── info/
232    └── details.html
233```
234
235Pages supports reaching each of these files through several different URLs. In
236particular, it always looks for an `index.html` file if the URL only
237specifies the directory. If the URL references a file that doesn't exist, but
238adding `.html` to the URL leads to a file that *does* exist, it's served
239instead. Here are some examples of what happens given the above Pages site:
240
241| URL path             | HTTP response |
242| -------------------- | ------------- |
243| `/`                  | `200 OK`: `public/index.html` |
244| `/index.html`        | `200 OK`: `public/index.html` |
245| `/index`             | `200 OK`: `public/index.html` |
246| `/data`              | `302 Found`: redirecting to `/data/` |
247| `/data/`             | `200 OK`: `public/data/index.html` |
248| `/data.html`         | `200 OK`: `public/data.html` |
249| `/info`              | `302 Found`: redirecting to `/info/` |
250| `/info/`             | `404 Not Found` Error Page |
251| `/info.html`         | `200 OK`: `public/info.html` |
252| `/info/details`      | `200 OK`: `public/info/details.html` |
253| `/info/details.html` | `200 OK`: `public/info/details.html` |
254
255Note that when `public/data/index.html` exists, it takes priority over the `public/data.html` file
256for both the `/data` and `/data/` URL paths.
257
258## Frequently Asked Questions
259
260### Can I download my generated pages?
261
262Sure. All you need to do is download the artifacts archive from the job page.
263
264### Can I use GitLab Pages if my project is private?
265
266Yes. GitLab Pages doesn't care whether you set your project's visibility level
267to private, internal or public.
268
269### Can I create a personal or a group website
270
271Yes. See the documentation about [GitLab Pages domain names, URLs, and base URLs](getting_started_part_one.md).
272
273### Do I need to create a user/group website before creating a project website?
274
275No, you don't. You can create your project first and access it under
276`http(s)://namespace.example.io/projectname`.
277
278## Known issues
279
280For a list of known issues, visit the GitLab [public issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues?label_name[]=Category%3APages).
281
282## Troubleshooting
283
284### 404 error when accessing a GitLab Pages site URL
285
286This problem most likely results from a missing `index.html` file in the public directory. If after deploying a Pages site
287a 404 is encountered, confirm that the public directory contains an `index.html` file. If the file contains a different name
288such as `test.html`, the Pages site can still be accessed, but the full path would be needed. For example: `https//group-name.pages.example.com/project-name/test.html`.
289
290The contents of the public directory can be confirmed by [browsing the artifacts](../../../ci/pipelines/job_artifacts.md#download-job-artifacts) from the latest pipeline.
291
292Files listed under the public directory can be accessed through the Pages URL for the project.
293
294A 404 can also be related to incorrect permissions. If [Pages Access Control](pages_access_control.md) is enabled, and a user
295navigates to the Pages URL and receives a 404 response, it is possible that the user does not have permission to view the site.
296To fix this, verify that the user is a member of the project.
297
298For Geo instances, 404 errors on Pages occur after promoting a secondary to a primary.
299Find more details in the [Pages administration documentation](../../../administration/pages/index.md#404-error-after-promoting-a-geo-secondary-to-a-primary-node)
300
301### Cannot play media content on Safari
302
303Safari requires the web server to support the [Range request header](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html#//apple_ref/doc/uid/TP40006514-SW6)
304in order to play your media content. For GitLab Pages to serve
305HTTP Range requests, you should use the following two variables in your `.gitlab-ci.yaml` file:
306
307```yaml
308pages:
309  stage: deploy
310  variables:
311    FF_USE_FASTZIP: "true"
312    ARTIFACT_COMPRESSION_LEVEL: "fastest"
313  script:
314    - echo "Deploying pages"
315  artifacts:
316    paths:
317      - public
318```
319
320The `FF_USE_FASTZIP` variable enables the [feature flag](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) which is needed for [`ARTIFACT_COMPRESSION_LEVEL`](../../../ci/runners/configure_runners.md#artifact-and-cache-settings).
321