How to Deploy a Jekyll Site to Cloudflare Pages (Step-by-Step Guide)
Deploy your Jekyll site to Cloudflare Pages — the fastest global CDN for static sites. A complete guide covering setup, build config, custom domains, and redirects.
Cloudflare Pages is one of the best places to host a Jekyll site in 2026. It is free for unlimited sites, has 300+ CDN locations worldwide, deploys automatically from GitHub or GitLab, and includes built-in DDoS protection from Cloudflare’s network — at no cost. Here is exactly how to set it up.
Why Cloudflare Pages for Jekyll
- Free tier is genuinely unlimited — no bandwidth limits, unlimited sites, unlimited requests
- 300+ CDN edge locations — faster global delivery than GitHub Pages or most competitors
- Automatic HTTPS — SSL certificate provisioned automatically on every domain
- Preview deployments — every pull request gets a unique preview URL
- Built-in redirects and headers — via a
_redirectsfile, no server config needed - Free custom domains — connect any domain you own at no charge
Prerequisites
- A Jekyll site in a GitHub or GitLab repository
- A Cloudflare account (free at cloudflare.com)
- Your repository must have a
Gemfilelisting your gems
Step 1: Prepare your Jekyll project
Cloudflare Pages builds your site using bundle exec jekyll build. Make sure your repository has:
A Gemfile:
source "https://rubygems.org"
gem "jekyll", "~> 4.3"
gem "jekyll-feed"
gem "jekyll-seo-tag"
gem "jekyll-sitemap"
# add any other plugins you use
A Gemfile.lock committed to the repository. Run bundle install locally to generate it:
bundle install
git add Gemfile.lock
git commit -m "Add Gemfile.lock"
git push
Cloudflare Pages requires Gemfile.lock to reproduce your build environment.
Step 2: Connect your repository to Cloudflare Pages
- Log in to dash.cloudflare.com
- Select Workers & Pages from the left sidebar
- Click Create application → Pages → Connect to Git
- Authorise Cloudflare to access your GitHub or GitLab account
- Select your Jekyll repository and click Begin setup
Step 3: Configure the build settings
On the build configuration screen, set:
| Setting | Value |
|---|---|
| Framework preset | Jekyll |
| Build command | jekyll build |
| Build output directory | _site |
Cloudflare automatically detects Jekyll and pre-fills these values. Verify they are correct before continuing.
Setting environment variables
Click Environment variables (advanced) and add:
| Variable | Value |
|---|---|
JEKYLL_ENV |
production |
RUBY_VERSION |
3.2.2 |
The JEKYLL_ENV=production variable enables production-only features in your site (analytics, optimisations). The RUBY_VERSION variable pins the Ruby version Cloudflare uses for the build.
To check which Ruby versions Cloudflare supports, refer to their build image documentation.
Step 4: Deploy
Click Save and Deploy. Cloudflare clones your repository, runs bundle exec jekyll build, and publishes the _site folder to its CDN. The first build typically takes 60–90 seconds.
You will see a live deployment URL in the format your-project.pages.dev — your site is immediately live on Cloudflare’s network.
Step 5: Add a custom domain
- In your Pages project, go to Custom domains → Set up a custom domain
- Enter your domain (e.g.
jekyllhub.com) - Cloudflare adds a DNS record automatically if your domain’s nameservers point to Cloudflare
- If your domain is registered elsewhere, you will need to add a CNAME record manually:
- Name:
@(orwww) - Target:
your-project.pages.dev
- Name:
SSL is provisioned automatically within a few minutes. Both www and root domain work.
Configuring redirects
Create a _redirects file in your Jekyll source root (not _site — Jekyll copies it automatically):
# Redirect www to non-www
https://www.jekyllhub.com/* https://jekyllhub.com/:splat 301
# Redirect old URLs
/old-post/ /new-post/ 301
/blog/category/themes/ /themes/ 301
# Custom 404
/* /404.html 404
Jekyll needs to copy this file to the build output. Add it to your _config.yml to ensure it is included:
include:
- _redirects
Configuring custom headers
Create a _headers file in your source root for HTTP headers:
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
/assets/*
Cache-Control: public, max-age=31536000, immutable
Add _headers to include in _config.yml the same way as _redirects.
Preview deployments
Every pull request to your repository automatically triggers a preview build at a unique URL (https://abc123.your-project.pages.dev). This lets you review changes before merging to main.
To disable preview deployments for a branch, go to your Pages project → Deployments → Branch control and add branches to the exclusion list.
Using a GitHub Actions workflow (optional)
By default, Cloudflare Pages manages the build. If you need more control — custom Ruby gems, pre-build scripts, fetching from an API — you can trigger deployments from GitHub Actions using the Cloudflare Wrangler action:
# .github/workflows/deploy.yml
name: Deploy to Cloudflare Pages
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.2"
bundler-cache: true
- name: Build Jekyll site
run: JEKYLL_ENV=production bundle exec jekyll build
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
apiToken: $
accountId: $
command: pages deploy _site --project-name=your-project-name
Store CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID as secrets in your GitHub repository settings.
Troubleshooting common errors
Build fails with Could not find gem
Your Gemfile.lock is missing or not committed. Run bundle install locally, commit Gemfile.lock, and push.
Build fails with ruby: command not found
Set the RUBY_VERSION environment variable in your Pages project settings.
Custom domain shows a security warning The SSL certificate is still provisioning. Wait 5–10 minutes and refresh.
_redirects not working
Ensure the file is in your Jekyll source root and listed under include: in _config.yml. Verify it was copied to _site/ in your build output.
Jekyll build succeeds but site looks broken
Check your baseurl in _config.yml. If it is set to a subdirectory (e.g. /my-repo), remove or blank it for a root-domain deployment.
Cloudflare Pages is fast to set up, genuinely free at scale, and gives your Jekyll site the best global CDN coverage available. For most Jekyll projects, it is the best hosting choice in 2026.