A collection of command-line utilities for streamlined Jekyll GitHub Pages deployment on GitHub Enterprise Server (GHES) and GitHub.com. These tools simplify the process of setting up and deploying Jekyll sites to GitHub Pages using the gh-pages
branch with a /docs
folder structure.
These tools solve common GitHub Pages deployment challenges:
- Automated branch setup with proper folder structure
- API-driven configuration to avoid manual settings
- Force rebuild capability to fix 503 errors and deployment issues
- Local Jekyll building with remote deployment
- Multiple authentication methods for different environments
curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash
# Install to user directory (~/.local/bin)
curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash -s -- --user
# Install to custom directory
curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash -s -- --dir /opt/bin
# Force reinstall/update
curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash -s -- --force
One-time repository setup utility that creates the initial gh-pages
branch with proper structure.
Build and deployment automation with force rebuild capability for ongoing deployments.
- Git repository with remote configured
- Jekyll installed (
gem install jekyll bundler
) - Ruby with Bundler support (Ruby 3.3+ recommended)
- Curl (for installation script)
For automatic GitHub Pages rebuild functionality and API configuration:
# Authenticate with your GitHub instance
gh auth login --hostname your-ghes-instance.com
# For GitHub.com
gh auth login
Create a Personal Access Token with these permissions:
Required Scopes:
repo
(Full control of private repositories)pages
(Read and write GitHub Pages settings)
For fine-grained tokens, grant these repository permissions:
- Pages: Read and write
- Contents: Read and write
- Metadata: Read
- Pull requests: Read (if using PR-based workflows)
Set environment variable:
# Add to your ~/.bashrc, ~/.zshrc, or ~/.profile
export GITHUB_TOKEN="your_personal_access_token_here"
# Or use GH_TOKEN
export GH_TOKEN="your_personal_access_token_here"
Purpose: Creates the initial gh-pages
branch with proper structure for GitHub Pages deployment.
What it does:
- Checks if
gh-pages
branch exists on remote - Creates orphan
gh-pages
branch (clean history) - Sets up
/docs
folder structure with starter content - Automatically configures GitHub Pages via API to use
/docs
folder - Pushes branch to remote repository
- Returns you to your original working branch
Usage:
cd /path/to/your/jekyll-repository
jekyll-ghpages-setup
Options:
--help
- Show usage information- Prompts before overwriting existing
gh-pages
branch
Purpose: Builds your Jekyll site locally and deploys it to the gh-pages/docs/
folder with optional force rebuild.
What it does:
- Validates prerequisites (Jekyll, Bundler, project structure)
- Installs dependencies with
bundle install
- Builds Jekyll site from
src/
to_site/
- Uses Git worktree to deploy to
gh-pages
branch - Copies built files to
/docs
folder - Commits with descriptive message including timestamp
- Pushes to remote automatically
- Forces GitHub Pages rebuild via API to fix 503 errors
- Cleans up temporary files
Usage:
cd /path/to/your/jekyll-repository
jekyll-ghpages-deploy
Options:
--force
/-f
- Skip uncommitted changes warning--skip-checks
- Skip prerequisite validation (faster for repeated use)--rebuild
- Force GitHub Pages rebuild after deployment--help
/-h
- Show usage information
Build Process:
- Source:
src/
directory (Jekyll files) - Build:
_site/
directory (temporary) - Deploy:
gh-pages/docs/
directory (GitHub Pages source)
# 1. Setup repository structure
jekyll-ghpages-setup
# 2. GitHub Pages is automatically configured via API
# 3. Deploy your site
jekyll-ghpages-deploy
# Make changes to files in src/
# Test locally: cd src && bundle exec jekyll serve
# Deploy changes
jekyll-ghpages-deploy
# Skip checks for faster deployment
jekyll-ghpages-deploy --skip-checks
# Deploy and force Pages rebuild (fixes 503 errors)
jekyll-ghpages-deploy --rebuild
# Force deployment with uncommitted changes and rebuild
jekyll-ghpages-deploy --force --rebuild
your-jekyll-repo/
βββ src/ # Jekyll source files
β βββ _config.yml # Jekyll configuration
β βββ Gemfile # Ruby dependencies
β βββ index.md # Homepage
β βββ _layouts/ # Page templates
β βββ _includes/ # Reusable components
β βββ _posts/ # Blog posts
β βββ _sass/ # Sass stylesheets
β βββ assets/ # Images, CSS, JS
βββ README.md # Project documentation
βββ .gitignore # Git ignore rules
main branch: # Source code and development
βββ src/ # Jekyll source
βββ README.md
βββ .gitignore
gh-pages branch: # Deployment branch
βββ docs/ # Built site (GitHub Pages source)
β βββ index.html
β βββ assets/
β βββ (generated files)
βββ README.md # Branch documentation
βββ .gitignore
- GitHub CLI support - Uses
gh
command if available and authenticated - Token-based authentication - Falls back to
GITHUB_TOKEN
orGH_TOKEN
environment variables - Smart URL parsing - Works with both GitHub.com and GHES instances
- Graceful fallbacks - Shows manual instructions if API config fails
The deploy script can force GitHub Pages to rebuild, which fixes common issues:
- 503 Service Unavailable errors
- Stale deployments that won't update
- Caching issues after configuration changes
Rebuild Methods (in order of preference):
- GitHub CLI API -
gh api repos/owner/repo/pages/builds --method POST
- curl with token - Direct API call with authentication
- Empty commit - Fallback method that always works
Rebuild Confirmation: After triggering a rebuild, the script now:
- Checks the latest build status via API
- Reports build status (queued, building, built, errored)
- Displays your Pages URL
- Provides instructions to verify rebuild completion
# Deploy with automatic rebuild
jekyll-ghpages-deploy --rebuild
# The script will try multiple methods:
# 1. GitHub CLI API (preferred)
# 2. curl + Personal Access Token
# 3. Empty commit (fallback)
# Manually trigger a Pages rebuild without deploying
# For GitHub.com:
gh api repos/{owner}/{repo}/pages/builds --method POST
# For GHES:
gh api repos/{owner}/{repo}/pages/builds --method POST --hostname your-ghes-instance.com
Deployment commits include detailed information:
Deploy: 2025-07-16 14:30:22 (from main@a1b2c3d)
- Graceful cleanup on interruption
- Detailed error messages with suggestions
- Prerequisite validation before operations
- Working directory safety checks
- Automatic retry mechanisms for API calls
The tools can automatically configure GitHub Pages settings via API:
Supported settings:
- Source branch:
gh-pages
- Source folder:
/docs
- Custom domains (via API)
Authentication methods:
- GitHub CLI:
gh auth login --hostname your-ghes-instance.com
- Environment token:
export GITHUB_TOKEN="token_here"
- Manual fallback: Instructions provided if API fails
# Site settings
title: Your Site Title
description: Site description
baseurl: "/your-repo-name" # Important for GitHub Pages
url: "https://your-ghes-instance.com" # Your GHES URL
# Build settings
markdown: kramdown
kramdown:
footnote_nr: 1
footnote_backlink: "↩"
input: GFM
syntax_highlighter: rouge
# Plugins
plugins:
- jekyll-feed
- jekyll-sitemap
# Exclude from build
exclude:
- README.md
- Gemfile
- Gemfile.lock
- .ruby-version
# Recommended Ruby version (matches GitHub Pages)
echo "3.3.3" > src/.ruby-version
# With rbenv
rbenv install 3.3.3
rbenv local 3.3.3
# With asdf
asdf install ruby 3.3.3
asdf local ruby 3.3.3
Classic tokens need these scopes:
- β
repo
(Full control of private repositories) - β
pages
(GitHub Pages settings)
Fine-grained tokens need these repository permissions:
- β Pages: Read and write
- β Contents: Read and write
- β Metadata: Read
- β Actions: Read (if using GitHub Actions)
To create a token:
- Go to Settings β Developer settings β Personal access tokens
- Generate new token (classic or fine-grained)
- Select required scopes/permissions above
- Set expiration and create token
- Add to environment:
export GITHUB_TOKEN="your_token"
"Jekyll is not installed"
gem install jekyll bundler
"Source directory 'src' not found"
- Ensure Jekyll files are in
src/
directory - Check
_config.yml
exists insrc/
"Branch 'gh-pages' does not exist on remote"
jekyll-ghpages-setup # Run setup first
"No changes detected"
- Site is already up to date
- Check if you made changes to source files
"503 Service Unavailable" on Pages site
# Force rebuild to fix caching issues
jekyll-ghpages-deploy --rebuild
If rebuild doesn't fix the 503:
- Check Settings β Pages to see if there are build errors
- Verify the
/docs
folder contains anindex.html
file - Check if the
gh-pages
branch exists and has content - Try visiting a specific file like
/docs/index.html
directly - Check the build status:
gh api repos/{owner}/{repo}/pages/builds?per_page=5
- Look for Jekyll build errors in the Pages build logs
- Ensure no
.nojekyll
file exists if using Jekyll - Check for CNAME conflicts or custom domain issues
"API rebuild failed"
- Check GitHub CLI authentication:
gh auth status
- For GHES, ensure you're authenticated to the correct host:
gh auth status --hostname your-ghes-instance.com
- Verify token permissions (needs
repo
andpages
scopes) - Token may be expired or invalid
- The script will show the actual error message to help diagnose issues
"Failed to create worktree"
- Check if
gh-pages
branch exists:git branch -r | grep gh-pages
- Run setup script first:
jekyll-ghpages-setup
Permission denied on installation
# Try user installation
curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash -s -- --user
# Or use sudo
sudo curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash
# Force reinstall over existing scripts
curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash -s -- --force
jekyll-ghpages-setup --help
jekyll-ghpages-deploy --help
These tools work with both GitHub.com and GitHub Enterprise Server instances. For GHES:
- Ensure GitHub Pages is enabled on your GHES instance
- Use the same workflow - tools auto-detect the environment
- Pages URL will be:
https://your-ghes-instance.com/pages/user/repo
GHES-Specific Features:
- Automatic detection of GHES host from git remote URL
- GitHub CLI commands use
--hostname
flag automatically - API endpoints correctly use
/api/v3
path - Rebuild confirmation works with GHES instances
If your GHES instance is behind a web proxy, Pages builds may timeout trying to fetch dependencies.
Essential domains to whitelist:
# Ruby and gem dependencies
rubygems.org
*.rubygems.org
rubygems.global.ssl.fastly.net
# GitHub resources
github.com
raw.githubusercontent.com
codeload.github.com
api.github.com
# Optional (if used in your Jekyll site)
cdn.jsdelivr.net
cdnjs.cloudflare.com
fonts.googleapis.com
Diagnosing proxy issues:
- Build timeouts lasting exactly 11 minutes (660 seconds)
- Multiple consecutive build failures with "Page build timed out"
- No specific error messages about missing files
Solution: Contact your GHES administrator to whitelist the required domains or configure the HTTP proxy settings for the Pages build environment.
While these tools are designed for local development, you can integrate them with CI/CD systems:
pipeline {
agent any
stages {
stage('Deploy') {
steps {
sh 'jekyll-ghpages-deploy --skip-checks'
}
}
}
}
For repositories with GitHub Actions enabled, consider the official actions/deploy-pages
action instead.
To update the tools:
# Re-run the installer with force flag
curl -sSL https://gist.githubusercontent.com/SolomonHD/dcd3cf9587cef4751a96a80967b5d598/raw/jekyll-ghpages-installer.sh | bash -s -- --force
These tools are provided as-is for community use. Feel free to fork, modify, and share!
Created by: SolomonHD
Gist Collection: Jekyll GitHub Pages Tools
Last Updated: July 2025