Back to Blog

Deploy Jekyll to GitHub Pages in 2026: GitHub Actions, Custom Domain & Cloudflare

AI Transformation Lead
  • DevOps
  • GitHub Pages
  • Jekyll
  • GitHub Actions
  • Cloudflare
  • CI/CD
  • HTTPS
Jekyll deployed to GitHub Pages with GitHub Actions CI/CD and Cloudflare CDN

GitHub Pages remains the best free static site host for developers in 2026. The catch: the built-in Jekyll builder is limited to a small set of allowed gems. The solution is a GitHub Actions workflow that builds Jekyll with full plugin support and deploys the output to GitHub Pages. This guide walks through the complete setup, from a blank repo to a custom domain served over HTTPS via Cloudflare.

Prerequisites

  • A GitHub account with a repository for your Jekyll site
  • A custom domain (optional but recommended)
  • A Cloudflare account (free tier is sufficient)
  • Ruby ≥ 3.1 and Jekyll ≥ 4.3 installed locally for testing

Step 1: Configure Jekyll for Production

Ensure _config.yml sets the correct URL:

yaml
# _config.yml url: "https://yourdomain.com" baseurl: "" plugins: - jekyll-feed - jekyll-sitemap - jekyll-seo-tag

Add a Gemfile:

ruby
source "https://rubygems.org" gem "jekyll", "~> 4.3" group :jekyll_plugins do gem "jekyll-feed" gem "jekyll-sitemap" gem "jekyll-seo-tag" end

Step 2: Create the GitHub Actions Workflow

Create .github/workflows/deploy.yml:

yaml
name: Deploy Jekyll to GitHub Pages on: push: branches: [main] workflow_dispatch: permissions: contents: read pages: write id-token: write concurrency: group: "pages" cancel-in-progress: false jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: '3.3' bundler-cache: true # Caches gems for faster builds - name: Configure GitHub Pages uses: actions/configure-pages@v5 - name: Build with Jekyll run: bundle exec jekyll build --destination ./_site env: JEKYLL_ENV: production - name: Upload artifact uses: actions/upload-pages-artifact@v3 deploy: needs: build runs-on: ubuntu-latest environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4

This workflow uses the official upload-pages-artifact + deploy-pages pattern, the recommended approach since 2024 that avoids pushing to a gh-pages branch.

Step 3: Enable GitHub Pages in Repository Settings

  1. Go to Settings > Pages
  2. Under Source, select GitHub Actions (not a branch)
  3. Save

Push to main, the workflow runs automatically and your site deploys within ~2 minutes.

Step 4: Configure a Custom Domain

4a. Create the CNAME File

Add a CNAME file to the root of your repo (no extension, plain text):

yourdomain.com

Commit and push it. GitHub Pages reads this file to know which custom domain to serve.

4b. Set the Domain in GitHub Pages Settings

In Settings > Pages > Custom domain, enter yourdomain.com and save.

Step 5: Configure DNS (Cloudflare)

In the Cloudflare dashboard for your domain, add these records:

TypeNameContentProxy
A@185.199.108.153✔ On
A@185.199.109.153✔ On
A@185.199.110.153✔ On
A@185.199.111.153✔ On
CNAMEwwwyourusername.github.io✔ On

These are GitHub's current (2026) IP addresses. The old addresses from 2016 (192.30.252.x) are deprecated.

Step 6: Enable HTTPS

Once DNS propagates (usually minutes with Cloudflare):

  1. In Settings > Pages, check Enforce HTTPS
  2. In Cloudflare SSL/TLS, set mode to Full (not Full Strict)
  3. Add a Cloudflare Redirect Rule: www.yourdomain.comhttps://yourdomain.com (301)

Step 7: Cloudflare Performance Optimizations (Free Tier)

In the Cloudflare dashboard, enable:

  • Speed > Optimization > Auto Minify: HTML, CSS, JS
  • Caching > Configuration > Browser Cache TTL: 4 hours
  • Speed > Optimization > Brotli: on

Verify Everything Works

bash
# Check DNS resolves to GitHub Pages IPs dig yourdomain.com A +short # Verify HTTPS and response headers curl -I https://yourdomain.com # Look for: strict-transport-security, cf-ray (Cloudflare edge hit)

The Result

FeatureStatus
Unlimited plugins & custom gems✔ via GitHub Actions
Custom domain✔ CNAME file + DNS
HTTPS / TLS✔ Let's Encrypt via GitHub
Global CDN✔ Cloudflare
DDoS protection✔ Cloudflare
Deploy on push✔ Auto via Actions
Cost$0

Your Jekyll site is now fully production-grade: CI/CD deploys on every push, TLS is enforced, and Cloudflare caches assets at 300+ edge nodes worldwide.

X / Twitter
LinkedIn
Facebook
WhatsApp
Telegram
AI Engineering for B2B

Stuck between an AI pilot and a system your team can run?

I join your engineering team and build the agent layer alongside you, covering architecture, MCP integration, evals, and production deployment. When the engagement ends, your team owns the system and keeps shipping.

12+ years shipping production systems

Senior engineer turned AI specialist. React, Next.js, AWS, agent orchestration.

Dubai-based, working with B2B teams worldwide

Direct collaboration across UAE, Europe, and US time zones.

AI agent teams that ship, not demos that stall

Discovery, role design, MCP integration, evals, and production deployment.

Questions about this piece

Follow-ups readers ask most often about the argument above.

  • GitHub's built-in builder only supports a fixed set of plugins and runs an older Jekyll version. GitHub Actions lets you use any gem, any Jekyll version, custom plugins, and advanced build steps. The workflow deploys to gh-pages branch which GitHub Pages then serves.

  • Create a CNAME file containing your bare domain (yourdomain.com) in the repo root. In your DNS provider, add an A record pointing @ to GitHub's four IPs (185.199.108.153, 185.199.109.153, 185.199.110.153, 185.199.111.153) and a CNAME record pointing www to <username>.github.io. Then set the custom domain in the repo's Pages settings.

  • Yes. Once DNS propagates, enable 'Enforce HTTPS' in Settings > Pages. GitHub uses Let's Encrypt to issue and auto-renew a TLS certificate for your domain. This typically activates within 24 hours of correct DNS configuration.

  • Keep it ON (proxied) for CDN caching, DDoS mitigation, and Cloudflare analytics. Set Cloudflare SSL/TLS to 'Full' (not Full Strict) to avoid certificate errors. Also set a page rule or Redirect Rule to redirect www to your apex domain for a single canonical URL.

  • With Cloudflare managing your DNS, propagation is typically near-instant globally. Without Cloudflare, allow up to 48 hours. You can verify resolution with: dig yourdomain.com A +short

Get practical AI and engineering playbooks

Weekly field notes on private AI, automation, and high-performance Next.js builds. Each edition is concise, implementation-ready, and tested in production work.

Open full subscription page

Get the latest insights on AI and full-stack development.