12 KiB
12 KiB
GitLab Pages Reference
Overview
GitLab Pages allows you to host static websites directly from your GitLab repository. Perfect for documentation, portfolios, blogs, and landing pages.
Pages URL Format
GitLab.com:
https://username.gitlab.io/project-name
Custom domain:
https://www.example.com
Group pages:
https://groupname.gitlab.io
Creating a Pages Site
Basic Setup
.gitlab-ci.yml:
pages:
stage: deploy
script:
- mkdir .public
- cp -r * .public
- mv .public public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Requirements:
- Job must be named
pages - Must create
public/directory - Must have artifact with
public/path - Runs on default branch (usually main)
Static HTML
index.html:
<!DOCTYPE html>
<html>
<head>
<title>My GitLab Page</title>
</head>
<body>
<h1>Welcome!</h1>
<p>This is hosted on GitLab Pages</p>
</body>
</html>
.gitlab-ci.yml:
pages:
stage: deploy
script:
- mkdir public
- cp index.html public/
artifacts:
paths:
- public
only:
- main
Static Site Generators
Hugo
image: registry.gitlab.com/pages/hugo:latest
variables:
GIT_SUBMODULE_STRATEGY: recursive
pages:
script:
- hugo
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Jekyll
image: ruby:2.7
before_script:
- bundle install
pages:
script:
- bundle exec jekyll build -d public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Gatsby
image: node:18
cache:
paths:
- node_modules/
- .cache/
pages:
script:
- npm install
- npm run build
- mv public public-gatsby
- mv public-gatsby public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Next.js
image: node:18
cache:
paths:
- node_modules/
- .next/cache/
pages:
script:
- npm install
- npm run build
- npm run export
- mv out public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
VuePress
image: node:18
pages:
script:
- npm install
- npm run docs:build
- mv docs/.vuepress/dist public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
MkDocs
image: python:3.11
pages:
script:
- pip install mkdocs mkdocs-material
- mkdocs build
- mv site public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Docusaurus
image: node:18
pages:
script:
- npm install
- npm run build
- mv build public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Hexo
image: node:18
pages:
script:
- npm install hexo-cli -g
- npm install
- hexo generate
- mv public public-hexo
- mv public-hexo public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
Custom Domain Setup
Add Custom Domain
Via UI:
- Settings > Pages
- New Domain
- Enter domain name
- Save
Via API:
curl --request POST --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages/domains" \
--data "domain=www.example.com"
DNS Configuration
For root domain (example.com):
Type: A
Name: @
Value: 35.185.44.232
For subdomain (www.example.com):
Type: CNAME
Name: www
Value: username.gitlab.io
Verify DNS:
dig www.example.com
nslookup www.example.com
SSL/TLS Certificate
Automatic Let's Encrypt:
- Add custom domain
- Configure DNS
- Enable "Automatic certificate management using Let's Encrypt"
Manual certificate:
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages/domains/www.example.com" \
--form "certificate=@/path/to/cert.pem" \
--form "key=@/path/to/key.pem"
Access Control
Private Pages
Require authentication to access pages (Premium/Ultimate):
Enable private pages:
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id" \
--data "pages_access_level=private"
Access levels:
public- Anyone can accessprivate- Only project membersenabled- Controlled by project visibilitydisabled- Pages disabled
Authentication
When pages are private:
- Users must log in to GitLab
- Project members can access
- Access controlled by member permissions
Preview Environments
Create preview for merge requests:
pages:
stage: deploy
script:
- npm run build
- mv dist public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
pages:preview:
stage: deploy
script:
- npm run build
- mv dist public
artifacts:
paths:
- public
environment:
name: review/$CI_COMMIT_REF_NAME
url: https://$CI_PROJECT_ROOT_NAMESPACE.gitlab.io/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public/index.html
rules:
- if: $CI_MERGE_REQUEST_ID
Advanced Configuration
Custom 404 Page
Create public/404.html:
<!DOCTYPE html>
<html>
<head>
<title>Page Not Found</title>
</head>
<body>
<h1>404 - Page Not Found</h1>
<p>The page you're looking for doesn't exist.</p>
<a href="/">Go Home</a>
</body>
</html>
Redirects
Create public/_redirects:
# Redirect /old-page to /new-page
/old-page /new-page 301
# Redirect with wildcards
/blog/* /news/:splat 301
# Conditional redirects
/api/* https://api.example.com/:splat 200
# Country-based redirects
/ /us 302 Country=us
/ /uk 302 Country=uk
Headers
Create public/_headers:
# Security headers
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Referrer-Policy: no-referrer-when-downgrade
# Cache control
/static/*
Cache-Control: public, max-age=31536000, immutable
# CORS
/api/*
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Base URL Configuration
For subdirectory deployment:
Hugo:
# config.toml
baseURL = "https://username.gitlab.io/project-name/"
Jekyll:
# _config.yml
baseurl: "/project-name"
url: "https://username.gitlab.io"
VuePress:
// .vuepress/config.js
module.exports = {
base: '/project-name/',
}
Optimization
Image Optimization
pages:
before_script:
- npm install -g sharp-cli
script:
- |
find public -name '*.jpg' -o -name '*.png' | while read img; do
sharp -i "$img" -o "$img" resize 1920
done
Minification
pages:
script:
- npm run build
- npm install -g html-minifier clean-css-cli uglify-js
- |
find public -name '*.html' -exec html-minifier --collapse-whitespace --remove-comments --minify-css --minify-js {} -o {} \;
find public -name '*.css' -exec cleancss -o {} {} \;
find public -name '*.js' -exec uglifyjs {} -c -m -o {} \;
Compression
pages:
script:
- npm run build
- mv dist public
- find public -type f -regex '.*\.\(htm\|html\|txt\|text\|js\|css\|svg\|json\)$' -exec gzip -f -k {} \;
- find public -type f -regex '.*\.\(htm\|html\|txt\|text\|js\|css\|svg\|json\)$' -exec brotli -f -k {} \;
CI/CD Examples
Multi-Branch Deployment
pages:
stage: deploy
script:
- npm run build
- mv dist public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == "main"
pages:staging:
stage: deploy
script:
- npm run build
- mv dist public
artifacts:
paths:
- public
environment:
name: staging
url: https://staging.example.com
rules:
- if: $CI_COMMIT_BRANCH == "staging"
Conditional Deployment
pages:
stage: deploy
script:
- |
if [ "$CI_COMMIT_BRANCH" == "main" ]; then
export NODE_ENV=production
else
export NODE_ENV=development
fi
- npm run build
- mv dist public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH
Scheduled Rebuild
pages:
script:
- npm run build
- mv dist public
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_PIPELINE_SOURCE == "schedule"
Monitoring
Analytics
Add Google Analytics:
<script async src="https://www.googletagmanager.com/gtag/js?id=GA_MEASUREMENT_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'GA_MEASUREMENT_ID');
</script>
Status Checks
test:pages:
stage: test
script:
- npm run build
- npm run test
- |
# Check for broken links
npm install -g broken-link-checker
blc http://localhost:8000 -ro
Troubleshooting
Pages Not Updating
- Check pipeline succeeded
- Verify
pagesjob ran - Check artifacts were created
- Clear browser cache
- Wait for CDN propagation (up to 30 minutes)
404 Errors
- Verify file exists in
public/directory - Check file paths (case-sensitive)
- Verify artifact includes files
- Check baseURL configuration
Custom Domain Issues
- Verify DNS configuration:
dig www.example.com - Check SSL certificate status
- Ensure domain verified in GitLab
- Check domain registrar settings
- Wait for DNS propagation (up to 48 hours)
Build Failures
pages:
script:
- set -e # Exit on error
- npm install
- npm run build || (echo "Build failed" && exit 1)
- mv dist public
artifacts:
paths:
- public
when: on_success
Best Practices
1. Performance
- Optimize images
- Minify CSS/JS
- Enable compression
- Use CDN
- Implement caching
2. Security
- Use HTTPS (automatic with Let's Encrypt)
- Set security headers
- Validate user input (if using forms)
- Keep dependencies updated
3. SEO
<meta name="description" content="Site description">
<meta name="keywords" content="keywords, here">
<meta property="og:title" content="Page Title">
<meta property="og:description" content="Description">
<meta property="og:image" content="https://example.com/image.jpg">
<meta name="twitter:card" content="summary_large_image">
<!-- Robots -->
<meta name="robots" content="index, follow">
<!-- Canonical URL -->
<link rel="canonical" href="https://example.com/page">
4. Accessibility
- Use semantic HTML
- Add alt text to images
- Ensure keyboard navigation
- Maintain color contrast
- Test with screen readers
5. Version Control
pages:
script:
- echo "Build $CI_COMMIT_SHA on $(date)" > public/version.txt
- npm run build
API Reference
Get Pages
curl --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages"
Delete Pages
curl --request DELETE --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages"
List Domains
curl --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages/domains"
Add Domain
curl --request POST --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages/domains" \
--data "domain=www.example.com" \
--data "auto_ssl_enabled=true"
Update Domain
curl --request PUT --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages/domains/www.example.com" \
--data "auto_ssl_enabled=true"
Delete Domain
curl --request DELETE --header "PRIVATE-TOKEN: <token>" \
"https://gitlab.com/api/v4/projects/:id/pages/domains/www.example.com"
Examples Repository
GitLab provides example pages projects:
- https://gitlab.com/pages
- Hugo: https://gitlab.com/pages/hugo
- Jekyll: https://gitlab.com/pages/jekyll
- Gatsby: https://gitlab.com/pages/gatsby
- Next.js: https://gitlab.com/pages/nextjs
Additional Resources
- Pages Documentation: https://docs.gitlab.com/ee/user/project/pages/
- Pages Examples: https://gitlab.com/pages
- Custom Domains: https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/
- Let's Encrypt: https://letsencrypt.org/