Deploying Chirpy Jekyll Blog to GitHub Pages from Kali Linux
Overview
This guide documents my actual deployment of a Chirpy Jekyll blog to GitHub Pages from Kali Linux VM running on a MacBook Pro M3. These are the exact commands I ran - no theory, just real steps that worked.
Platform Note: This guide is tested on Kali Linux. The process should be similar on macOS, but key differences may exist (especially with Git configuration). If you’re on macOS, some commands may need adjustments.
Why GitHub Pages?
- Free hosting for static sites
- Automatic builds on git push
- Custom domain support
- HTTPS included
- Git-based workflow you’re already using
Prerequisites
- GitHub account
- Local Chirpy blog working (tested with
bundle exec jekyll serve) - Git installed and configured
- Your blog posts ready in
_posts/directory
Step 1: Create GitHub Repository
Go to github.com/new
- Repository name options:
username.github.io→ Site athttps://username.github.io/blogorranger-blog→ Site athttps://username.github.io/blog/
- Settings:
- Public (required for free GitHub Pages)
- Don’t initialize with README (we have local files)
- Click Create repository
Step 2: Prepare Local Repository
Check Current Git Remote
If you cloned chirpy-starter, it points to their repo:
1
2
3
4
cd /home/kali/Documents/web/ranger-chirpy
git remote -v
# Shows: origin https://github.com/cotes2020/chirpy-starter.git
Change Remote to YOUR Repository
Don’t delete .git! Just change where it points:
1
2
3
4
5
6
7
8
9
# Remove old remote (chirpy-starter)
git remote remove origin
# Add YOUR new repository
git remote add origin https://github.com/yourusername/yourusername.github.io.git
# Verify it's correct
git remote -v
# Should show: origin https://github.com/yourusername/yourusername.github.io.git
My actual command:
1
git remote add origin https://github.com/davidtkeane/davidtkeane.github.io.git
Update Configuration
Edit _config.yml with your actual GitHub Pages URL:
1
2
3
4
5
6
# For username.github.io repository:
url: "https://yourusername.github.io"
baseurl: ""
github:
username: yourusername
My actual config:
1
2
3
4
url: "https://davidtkeane.github.io"
github:
username: davidtkeane
Important: The
urlmust match your GitHub Pages URL exactly, without trailing slash.
Step 3: GitHub Actions Workflow
Chirpy uses GitHub Actions to build the site. The workflow file should already exist:
1
2
ls .github/workflows/
# Should see: pages-deploy.yml or jekyll.yml
If missing, create .github/workflows/pages-deploy.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
name: "Build and Deploy"
on:
push:
branches:
- main
paths-ignore:
- .gitignore
- README.md
- LICENSE
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.2
bundler-cache: true
- name: Build site
run: bundle exec jekyll b -d "_site"
env:
JEKYLL_ENV: "production"
- name: Upload site artifact
uses: actions/upload-pages-artifact@v3
with:
path: "_site"
deploy:
environment:
name: github-pages
url: $
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
Step 4: Commit and Push to GitHub
1
2
3
4
5
6
7
8
9
10
11
# Add all your files (posts, config, assets)
git add .
# Check what will be committed
git status
# Commit with descriptive message
git commit -m "Initial deployment: Chirpy blog with posts"
# Push to GitHub (first time requires -u flag)
git push -u origin main
My actual sequence:
1
2
3
git add .
git commit -m "Deploy Chirpy blog to GitHub Pages"
git push -u origin main
Note: If you get authentication errors, make sure you have a Personal Access Token (PAT) set up, or use SSH keys. See Git Authentication Common Mistakes.
Step 5: Configure GitHub Pages
Go to your repository on GitHub
Click Settings → Pages (left sidebar)
- Under Build and deployment:
- Source: GitHub Actions
- (Not “Deploy from a branch”)
- Wait for the first workflow to complete:
- Go to Actions tab
- Watch the build progress
- Green checkmark = success
- Your site URL appears in Settings → Pages
Step 6: Verify Deployment
Visit your site:
https://username.github.io/(if using username.github.io repo)https://username.github.io/blog/(if using project repo with baseurl)
Check that:
- Homepage loads with posts
- Profile picture appears
- Categories/tags work
- Post links are correct
Updating Your Blog
After initial setup, publishing is simple:
1
2
3
4
5
6
7
8
9
10
11
# Create new post
# Edit _posts/YYYY-MM-DD-title.md
# Commit and push
git add .
git commit -m "Add new post: Title"
git push
# GitHub Actions automatically builds and deploys
# Check Actions tab for build status
# Site updates in ~2-3 minutes
Troubleshooting
Build Fails - Check Actions Log
- Go to Actions tab
- Click failed workflow
- Expand the failed step
- Common issues:
- Missing gems in Gemfile
- Syntax errors in YAML front matter
- Invalid liquid template
404 Errors on Assets
Problem: CSS/JS not loading, broken images
Solution: Check baseurl in _config.yml:
1
2
3
4
5
# Wrong - trailing slash causes issues
baseurl: "/blog/"
# Correct
baseurl: "/blog"
Posts Not Appearing
- Future date issue - Use past timestamp in front matter
- Wrong file location - Must be in
_posts/directory - Invalid filename - Must be
YYYY-MM-DD-title.md
Local Works, Production Broken
Test with production settings locally:
1
JEKYLL_ENV=production bundle exec jekyll serve --baseurl '/blog'
Network Access (Before Deployment)
While developing locally, you can access your Chirpy blog from other devices on your network.
Enable Network Access
Add --host 0.0.0.0 to bind to all network interfaces:
1
bundle exec jekyll serve --livereload --host 0.0.0.0 --port 4000
Output shows:
1
2
LiveReload address: http://0.0.0.0:35729
Server address: http://0.0.0.0:4000/
Find Your Local IP
1
2
3
4
5
6
# Linux/Kali
hostname -I | awk '{print $1}'
# Example: 192.168.1.29
# Or check your prompt/network settings
ip addr show | grep "inet " | grep -v 127.0.0.1
Access from MacBook/Windows
Once Jekyll is running with --host 0.0.0.0:
From MacBook:
1
http://192.168.1.29:4000/
From Windows:
1
http://192.168.1.29:4000/
From iPhone/Android:
1
http://192.168.1.29:4000/
Replace 192.168.1.29 with your actual Kali VM IP.
Automated Function Example
Create a shell function that shows both URLs:
1
2
3
4
5
6
7
8
# In ~/.zshrc or ~/.bashrc
function jchirpy {
cd ~/Documents/web/ranger-chirpy
local_ip=$(hostname -I | awk '{print $1}')
echo "Local: http://127.0.0.1:4000/"
echo "Network: http://${local_ip}:4000/"
bundle exec jekyll serve --livereload --host 0.0.0.0 --port 4000
}
Troubleshooting Network Access
Can’t connect from other device:
- Check firewall:
1 2 3
sudo ufw status # If active, allow port 4000: sudo ufw allow 4000
- Verify Jekyll is listening on 0.0.0.0:
1 2
netstat -tlnp | grep 4000 # Should show: 0.0.0.0:4000 (not 127.0.0.1:4000)
Ensure devices are on same network (same WiFi/subnet)
- Check VM network settings (if using VirtualBox/VMware):
- Use “Bridged Adapter” not “NAT”
- VM gets its own IP on your network
Public Internet Access
For sharing outside your local network, consider:
- GitHub Pages - Deploy permanently (this guide)
- Cloudflare Tunnel - Temporary public URL without port forwarding
- Port Forwarding - Opens your home IP (security risk)
See: Cloudflare Tunnel: Expose Local Services Securely
Security Considerations
Don’t Commit Secrets
Add to .gitignore:
1
2
3
4
5
6
# Sensitive files
.env
*credentials*
*secret*
*.pem
*.key
Review Before Pushing
1
2
3
4
5
6
# Check what will be committed
git status
git diff --cached
# Review history
git log --oneline
Sensitive Content Warning
Remember: GitHub Pages repos are public. Don’t include:
- API keys
- Passwords (even in screenshots)
- Private IP addresses
- Client information
- Unpublished vulnerabilities
Workflow Automation
Pre-commit Checks
Create scripts/pre-commit.sh:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
# Check for common issues before committing
# No future-dated posts
for file in _posts/*.md; do
date=$(grep "^date:" "$file" | head -1)
echo "Checking: $file"
done
# No secrets in posts
if grep -r "password\|secret\|api_key" _posts/; then
echo "WARNING: Potential secret in post!"
exit 1
fi
echo "Pre-commit checks passed!"
Git Hooks
1
2
3
4
5
# Make executable
chmod +x scripts/pre-commit.sh
# Link to git hooks
ln -s ../../scripts/pre-commit.sh .git/hooks/pre-commit
Cost Comparison
| Platform | Monthly Cost | Custom Domain | SSL | Build Minutes |
|---|---|---|---|---|
| GitHub Pages | Free | Yes (free) | Yes | 2000/month |
| Netlify (free) | Free | Yes | Yes | 300/month |
| Vercel (free) | Free | Yes | Yes | 6000/month |
| DigitalOcean | $4-6 | Manual | Manual | N/A |
| InMotion Shared | $3-8 | Included | Included | N/A |
GitHub Pages is perfect for personal blogs and HTB writeups.
SUCCESS! It’s Live! 🎉
After following all these steps, my blog is now live at:
https://davidtkeane.github.io/
The GitHub Actions workflow built the site automatically, and within 2-3 minutes everything was online. All 20+ posts, images, and configuration - all working perfectly!
Daily Workflow: Editing & Publishing
Now that your blog is deployed, here’s how to manage it day-to-day.
Editing an Existing Post
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 1. Navigate to your blog directory
cd /home/kali/Documents/web/ranger-chirpy
# 2. Edit the post
vim _posts/2025-11-17-your-post.md
# Or use any editor: nano, code, etc.
# 3. Test locally (optional but recommended)
bundle exec jekyll serve
# Visit http://127.0.0.1:4000/ to preview
# 4. Stage the changes
git add _posts/2025-11-17-your-post.md
# 5. Commit with descriptive message
git commit -m "Update: fix typo in deployment post"
# 6. Push to GitHub
git push
# 7. Wait 2-3 minutes for GitHub Actions to rebuild
# Check: https://github.com/yourusername/yourusername.github.io/actions
Creating a New Blog Post
1
2
3
4
5
6
7
8
9
# 1. Navigate to blog directory
cd /home/kali/Documents/web/ranger-chirpy
# 2. Create new post with correct naming
# Format: YYYY-MM-DD-title-with-dashes.md
touch _posts/2025-11-18-my-new-awesome-post.md
# 3. Edit the post
vim _posts/2025-11-18-my-new-awesome-post.md
Add front matter:
1
2
3
4
5
6
7
8
9
10
11
12
13
---
title: "My New Awesome Post"
date: 2025-11-18 01:00:00 +0000 # Use 01:00:00 - safe default!
categories: [GitHub, Guides]
tags: [tutorial, beginner, example]
pin: false
math: false
mermaid: false
---
## Introduction
Your content here...
Then publish:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 4. Test locally
bundle exec jekyll serve
# Check http://127.0.0.1:4000/
# 5. Stage new post
git add _posts/2025-11-18-my-new-awesome-post.md
# 6. Commit
git commit -m "Add new post: My New Awesome Post"
# 7. Push to live site
git push
# 8. Verify deployment
# Check GitHub Actions tab for build status
# Your post appears at: https://yourusername.github.io/posts/my-new-awesome-post/
Adding Images to Posts
1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. Copy image to assets folder
cp ~/Downloads/screenshot.png assets/img/screenshot.png
# 2. Reference in your post

# 3. Stage both post and image
git add _posts/2025-11-18-post-with-image.md
git add assets/img/screenshot.png
# 4. Commit and push
git commit -m "Add post with screenshot"
git push
Multiple Changes at Once
1
2
3
4
5
6
7
8
9
10
11
# Stage everything
git add .
# Or stage specific files
git add _posts/2025-11-18-post1.md _posts/2025-11-18-post2.md
# Commit all together
git commit -m "Add two new posts about security tools"
# Single push updates everything
git push
Quick Reference Card
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# === DAILY COMMANDS ===
# Start local server
cd ~/Documents/web/ranger-chirpy
bundle exec jekyll serve
# Create new post
touch _posts/$(date +%Y-%m-%d)-post-title.md
# Edit post
vim _posts/YYYY-MM-DD-title.md
# Deploy changes
git add .
git commit -m "Your message here"
git push
# Check build status
# https://github.com/username/username.github.io/actions
# View live site
# https://username.github.io/
What’s Next
In Part 3, I’ll cover:
- Adding a custom domain (yourdomain.com)
- DNS configuration
- SSL certificate verification
- SEO optimization
- Analytics setup (privacy-respecting options)
Resources
Deployed from Kali Linux VM on MacBook Pro M3
Blog live at: https://davidtkeane.github.io/