Deploy a 24/7 AI ChatbotUsing GitHub Only & Connect Your Self-Hosted Local LLM to Your GitHub Chatbot

Deploy a 24/7 AI Chatbot Using GitHub — Beginner’s Guide
Complete Beginner’s Guide · GitHub Edition

Deploy a 24/7 AI Chatbot
Using GitHub Only

No servers. No coding knowledge. No monthly fees. Just a GitHub account and this guide.

⏱ 1–2 hours £0 cost Zero coding Always online
Phase 1 · GitHub Account
Phase 2 · Repository
Phase 3 · Chatbot Page
Phase 4 · AI Brain
Phase 5 · Lead Form
Phase 6 · Go Live
Phase 7 · Customize
Phase 8 · OpenAI (Advanced)
Begin
§ 1 · Foundation

Before We Start —
Key Concepts Explained

Read these short definitions before touching any buttons. They’ll make every step feel logical rather than mysterious.

📚 The Vocabulary You Need

🐙 GitHub

A free website where people store website files. Think of it like Google Drive, but for websites. It has a feature that turns your files into a live website — free, 24/7.

📁 Repository

A “repo” is just a folder on GitHub. It holds all your chatbot files. Every project lives in its own repository.

🌐 GitHub Pages

GitHub’s free hosting service. It takes the files in your repository and makes them a real, live website. Your address: yourusername.github.io/chatbot

📄 HTML File

The language that describes web pages. Think of it like a Word document for websites. You’ll create one file — mostly copy-and-paste.

🤖 Chatbot Widget

A ready-made chatbot you embed on your page with one line of code. The AI brain lives on the provider’s servers — you just add it to your page.

🔑 Commit

In GitHub, “committing” means saving a version of your file. Like pressing Save, but it also keeps a record of every change you’ve ever made.

💡
GitHub Pages runs your website continuously on Microsoft’s servers. There is no computer you need to leave on. Your chatbot will be available 24/7 as long as GitHub exists — which, owned by Microsoft, is extremely reliable.
§ 2 · Requirements

What You Need

The barrier to entry here is remarkably low. No special hardware, no paid software.

ItemDetails
ComputerAny Windows, Mac, or Chromebook
Internet connectionAny connection works — even mobile data
Email addressFor creating free accounts
Time1–2 hours for a complete beginner
Budget£0 / €0 / $0 — this guide uses only free tools
Technical skillNone required — every step is fully explained
Phase 1 · GitHub Account

Create Your GitHub Account

Your GitHub account is your home base. It takes about 5 minutes to set up.

1

Go to GitHub’s Website

Open any web browser and navigate to https://www.github.com. You’ll see a dark homepage with a headline about building software.

2

Click “Sign Up”

Look for “Sign up” in the top-right corner of the page and click it. GitHub takes you through a short sign-up flow.

3

Enter Your Email Address

Type your email address in the box and click “Continue”.

💡
Use an email you check regularly — GitHub will send a verification code there.
4

Create a Password

Type a strong password — a mix of letters, numbers, and symbols. Write it down somewhere safe. You’ll need it every time you log in. Click “Continue”.

5

Choose a Username

This is important — your username becomes part of your website address.

For example: if your username is mybusiness, your website will be at https://mybusiness.github.io/chatbot

  • Use only letters, numbers, and hyphens
  • A green checkmark appears when the username is available
  • Use something professional — your business name works well
⚠️
Choose carefully. Your username is part of your public website address and is difficult to change later.
6

Complete Verification and Confirm Your Email

  1. GitHub may show a puzzle to confirm you’re human — follow the instructions
  2. Click “Create account”
  3. Check your email inbox — GitHub sent a 6-digit verification code
  4. Type that code into the boxes on the GitHub page
You are now inside GitHub! You’ll see your dashboard — a simple home screen showing your account.
7

Skip or Answer Setup Questions

GitHub may ask about your experience level. You can answer or scroll to the bottom and click “Skip personalization”. Either way, you’ll arrive at your dashboard.

✅ Phase 1 Complete — GitHub account created and verified
Phase 2 · Repository

Create Your Website Repository

A repository is the folder that holds all your chatbot files. This is where your website lives on GitHub.

8

Create a New Repository

On your GitHub dashboard, look for a green “New” button on the left side — or click the “+” icon in the top-right corner and select “New repository”.

9

Fill In the Repository Details

A form appears. Fill it in exactly as follows:

FieldWhat to type / select
Repository namechatbot — use only lowercase letters
Description“My AI chatbot for support and leads” (optional)
Public / PrivateSelect Public — required for free GitHub Pages hosting
Add a README file✅ Check this box — it creates your first file automatically
Everything elseLeave at defaults
10

Click “Create Repository”

Scroll to the bottom and click the green “Create repository” button. GitHub creates your folder and takes you inside it — you’ll see one file (README.md) listed.

You now have your own project folder on GitHub. In the next phase you’ll add your chatbot files to it.
✅ Phase 2 Complete — Repository created at github.com/yourusername/chatbot
Phase 3 · Chatbot Page

Build Your Chatbot Page

You’ll create one HTML file — the page that becomes your chatbot website. It’s mostly copy-and-paste. No prior knowledge needed.

11

Create a New File in Your Repository

  1. Make sure you are inside your repository on GitHub
  2. Click the “Add file” button near the top of the file list
  3. In the dropdown that appears, click “Create new file”
  4. A text editor opens — this is where you’ll write your chatbot page
12

Name Your File

At the top of the editor, click in the field that says “Name your file…” and type exactly:

index.html
The filename is critical. It must be exactly index.html — all lowercase, with the .html extension. This is the file GitHub Pages automatically shows as your homepage.
13

Paste the Chatbot Code

Click inside the large white text area. Then copy the entire block below and paste it in. Don’t worry about understanding every line — we’ll explain the key parts afterwards.

<!-- COPY EVERYTHING FROM HERE -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Support & Chat — We're Here to Help</title>
  <!-- Styles and full chatbot code: see the .md file for the complete version -->
</head>
<body>
  <!-- Paste the full index.html from the Markdown guide here -->
</body>
</html>
📋
For the complete, ready-to-paste chatbot code: open the accompanying .md file (github-chatbot-guide.md), scroll to Step 13, and copy the full HTML block between the triple-backtick markers. It contains the complete chatbot with styling, logic, chat window, and lead form.
14

Commit (Save) Your File

  1. Scroll down below the text editor
  2. You’ll see a section called “Commit new file”
  3. In the first text box, you can leave the default message or type: Add chatbot homepage
  4. Leave everything else at default
  5. Click the green “Commit new file” button
Your file is saved. You’ll now see both README.md and index.html in your repository file list.
✅ Phase 3 Complete — Chatbot page created and saved to your repository
Phase 4 · AI Brain

Connect a Free AI Brain

Your page has a built-in basic response system. To upgrade to a genuine AI that answers anything intelligently, connect one of these free services.

OptionCostIntelligenceDifficulty
Built-in knowledge base (already done)FreeBasic — preset answers✅ Done
Tidio (recommended)Free tierVery good AIEasy
Crisp ChatFree tierGood AIEasy
OpenAI API (Phase 8)~£0.01–£1/monthExcellent — like ChatGPTMedium
Option A — Tidio (Recommended)
15

Create a Free Tidio Account

  1. Go to https://www.tidio.com
  2. Click “Get started free”
  3. Enter your email and create a password
  4. Fill in basic details about your website
💡
Tidio’s free plan includes AI-powered responses, live chat, and up to 50 conversations per month — more than enough to get started.
16

Get Your Tidio Embed Code

  1. Once inside Tidio, click Settings in the left sidebar
  2. Click “Developer” or “Channels” → “Live Chat”
  3. Find the “Installation” or “Embed code” section
  4. You’ll see a short line of code — it looks like this:
<script src="//code.tidio.co/XXXXXXXXXXXXXXXXXX.js" async></script>

Copy that entire line.

17

Add Tidio to Your GitHub Page

  1. Go back to your GitHub repository
  2. Click on index.html to open it
  3. Click the pencil/edit icon (top-right of the file)
  4. Scroll to the very bottom — find the line that says </body>
  5. Click just above that line and press Enter to create a new line
  6. Paste your Tidio script there:
  ... your page code ...

  <script src="//code.tidio.co/XXXXXXXXXXXXXXXXXX.js" async></script>
</body>
</html>
  1. Scroll down and click “Commit changes”
Tidio’s AI chatbot will now appear as a floating chat bubble on your live page!
Option B — Crisp Chat

Crisp is another excellent free alternative. Go to https://crisp.chat → Sign up → Settings → Website → Installation → copy the script → paste it before </body> following the same process as Step 17.

✅ Phase 4 Complete — AI chatbot brain connected and active
Phase 5 · Lead Capture

Capture Leads with a Form

Your chatbot page already includes a lead capture form. Now you need to connect it to Formspree — a free service that emails you every submission.

18

Create a Free Formspree Account

  1. Go to https://www.formspree.io
  2. Click “Get started” or “Sign up”
  3. Enter your email and create a password
  4. Confirm your email address
💡
Formspree’s free plan handles 50 form submissions per month — plenty for getting started. No credit card required.
19

Create a New Form in Formspree

  1. Once logged in, click “+ New form”
  2. Name it: Chatbot Lead Capture
  3. Click “Create Form”
  4. Formspree gives you a unique URL — it looks like:
https://formspree.io/f/abcdefgh

Copy this entire URL — you’ll need it in the next step.

20

Connect the Form to Your Page

  1. In your GitHub repository, open index.html for editing (pencil icon)
  2. Press Ctrl+F (Windows) or Command+F (Mac) to search
  3. Search for: YOUR_FORM_ID
  4. Replace it with your actual Formspree form ID (the characters after the last /)
<!-- BEFORE (placeholder) -->
action="https://formspree.io/f/YOUR_FORM_ID"

<!-- AFTER (your real ID) -->
action="https://formspree.io/f/abcdefgh"
  1. Click “Commit changes”
21

Set Up Email Notifications in Formspree

  1. In your Formspree dashboard, click on your form
  2. Go to “Notifications” or “Settings”
  3. Confirm your email address is set as the notification recipient
  4. Click Save
Every time someone fills in your form, you’ll receive an instant email with their details.
✅ Phase 5 Complete — Lead capture form connected and sending notifications
Phase 6 · Go Live

Go Live with GitHub Pages

This is the most exciting step — turning your repository files into a real, live website that anyone on the internet can visit.

22

Open Repository Settings

  1. Go to your repository on GitHub
  2. Look at the tab row along the top: Code, Issues, Pull requests, Actions, Settings
  3. Click “Settings”
23

Navigate to GitHub Pages

  1. On the Settings page, look at the left sidebar
  2. Scroll down until you see “Pages”
  3. Click “Pages”
  4. You are now on the GitHub Pages configuration screen
24

Configure the Source

  1. Under “Source”, click the dropdown (probably says “None”)
  2. Select “Deploy from a branch”
  3. A second dropdown appears — select “main”
  4. In the folder dropdown next to it, keep “/ (root)”
  5. Click “Save”
25

Wait for Your Site to Go Live

  1. GitHub needs 1–3 minutes to build and publish your site
  2. Refresh the Settings → Pages page after 2 minutes
  3. You’ll see a green banner saying something like:
🎉
“Your site is live at https://yourusername.github.io/chatbot”
Click that link — your chatbot is now on the internet, available 24/7, for free!
26

Test Your Live Website

Visit your new URL and test everything:

  • Type messages in the chat: “What are your prices?”, “I need help”, “What are your hours?”
  • Fill in the lead form with your own details
  • Check your email — did you get the Formspree notification?
  • Try on your phone (open the URL on mobile)
✅ Phase 6 Complete — Your chatbot is LIVE at yourusername.github.io/chatbot 🚀
Phase 7 · Customize

Customize Your Chatbot

Now that everything works, make it yours. Replace the placeholder text with your real business information.

27

Edit Your Page Text

In GitHub, open index.html → pencil icon to edit → use Ctrl+F to find and replace each item in this table:

Find this textReplace with
My Business AssistantYour actual business name
Support & Chat — We’re Here to HelpYour page title
How Can We Help You Today?Your headline
hello@yourbusiness.comYour real email address
+44 20 0000 0000Your real phone number
[YOUR CITY, COUNTRY]Your actual location

Click “Commit changes” when done.

28

Customize the Chatbot Answers

In index.html, find the section starting with const responses = {. Replace each answer with your real business information:

const responses = {
  pricing: "YOUR ACTUAL PRICING INFO HERE...",
  support: "YOUR ACTUAL SUPPORT PROCESS HERE...",
  hours: "YOUR ACTUAL OPENING HOURS HERE...",
  contact: "YOUR ACTUAL CONTACT DETAILS HERE...",
};
29

Update the Quick Reply Buttons

Find and customize the quick-reply buttons to match your services:

<!-- Example: for a restaurant -->
<button onclick="sendQuick('I want a reservation')">🍽️ Reservations</button>
<button onclick="sendQuick('What is on the menu?')">📋 Menu</button>
30

How to See Your Changes

After every edit and commit, wait 30–60 seconds then refresh your live website. GitHub Pages automatically redeploys every change you save. No extra steps needed.

💡
GitHub keeps a full history of every version of your file. If you ever break something, click “History” on the file and restore a previous version.
✅ Phase 7 Complete — Chatbot customized with your real business information
Phase 8 · Advanced · Optional

Advanced — Connect OpenAI
for Smarter Answers

Optional. Your chatbot works without this. Do this only if you want ChatGPT-level intelligence responding to anything — not just preset answers.

⚠️
This phase requires creating an OpenAI account and adding a payment method. Costs are very small (typically under £1/month for a small site) but are not zero. Set spending limits as described in Step 32.
31

Create an OpenAI Account

  1. Go to https://platform.openai.com
  2. Click “Sign up” and create an account
  3. Verify your email and phone number
  4. Add a payment method (required, but costs are tiny)
32

Set a Spending Limit (Important!)

  1. In OpenAI dashboard → Settings → Billing → Usage limits
  2. Set Monthly spending limit to £5
  3. Set a Soft limit alert at £3
💡
The gpt-4o-mini model used in this guide costs roughly £0.001 per conversation. Even 1,000 conversations a month would only cost about £1.
33

Get Your API Key

  1. Click your profile icon → “API Keys”
  2. Click “+ Create new secret key”
  3. Name it: GitHub Chatbot
  4. Click “Create secret key”
  5. Copy the key IMMEDIATELY — you can only see it once
sk-proj-...XXXXXXXXXXXXXXXXXXXXXXXX
Store your API key in a password manager or secure notes app. Never share it publicly. For small personal sites, using it in an HTML file is acceptable — but set a spending limit to stay safe.
34

Add OpenAI to Your Chatbot

In your index.html file, find the line const knowledge = { and add this above it:

// OpenAI configuration
const OPENAI_KEY = 'sk-proj-YOUR_KEY_HERE';
const OPENAI_SYSTEM_PROMPT = `You are a helpful support assistant
for [YOUR BUSINESS NAME]. Answer questions about our products
and services politely and concisely. If you cannot help,
suggest the visitor fills in the contact form. Keep answers
under 100 words. Be friendly and professional.`;

Then find the getResponse function and replace it with the async version that calls the OpenAI API. The complete replacement code is in the .md guide at Phase 8, Step 33.

✅ Phase 8 Complete — Your chatbot now uses ChatGPT-level AI for any question
§ 11 · Ongoing

Maintaining Your Chatbot

Once running, your chatbot needs very little attention. Here are the key maintenance tasks.

✏️ Update answers

Edit & Commit

Open index.html on GitHub, click the pencil icon, make your changes, click “Commit changes”. Live in ~60 seconds.

📥 Check leads

Formspree Dashboard

Log in to formspree.io to see all form submissions. You also get email notifications for each one automatically.

🔍 Check uptime

Visit Your URL

Occasionally visit your live URL to confirm the chatbot is working. For outages, check status.github.com.

🔄 Restore versions

GitHub History

If you break something, click “History” on index.html to see every past version and restore any of them.

§ 12 · Troubleshooting

Troubleshooting Guide

Common problems and their solutions. Don’t panic — almost every issue has a simple fix.

My site is not live — I see a 404 error
Check these in order: (1) GitHub Pages not enabled — go to Settings → Pages and set source to “main” branch. (2) File named wrong — must be exactly index.html — all lowercase. (3) Still loading — GitHub can take up to 10 minutes the first time. Wait, then refresh. (4) Wrong URL — your address is yourusername.github.io/chatbot — check both parts match your actual username and repository name.
The chat is not responding when I type
Make sure JavaScript is enabled in your browser. Try a different browser (Chrome, Firefox, Edge). Verify the file was committed correctly — open it on GitHub and confirm the code is there.
The lead form is not sending emails to me
(1) Confirm you replaced YOUR_FORM_ID with your real Formspree ID. (2) Check your Formspree account email is verified. (3) After submitting the form, wait 2–3 minutes. (4) Check your spam/junk folder — Formspree emails sometimes end up there. (5) Log into formspree.io to see if submissions are arriving even without the email.
My OpenAI chatbot shows an error message
(1) Check the API key is pasted correctly with no extra spaces. (2) Confirm your OpenAI account has a valid payment method added. (3) Check your usage limits — you may have hit the monthly cap. (4) Press F12 in your browser → click the Console tab → look for red error messages that will tell you exactly what went wrong.
I accidentally broke the page — it looks wrong
GitHub keeps every version. In your repository, click on index.html → click “History” (top-right of the file view) → find a working version → click the three-dot menu → “View file” → copy all the text → go back to editing and paste the old version back → commit.
GitHub Pages says “Your site is published” but I see a blank page
The HTML file might have a syntax error. Open the browser’s developer tools (press F12) → click the Console tab → look for red error messages. Most commonly: a missing closing tag or a quote that wasn’t closed. Compare your code against the original template in this guide.
§ 13 · Reference

Glossary

Every technical term used in this guide, explained in plain English.

API
A “door” that lets two software apps share data with each other automatically.
API Key
A secret password proving you have permission to use an API service.
Chatbot
A program that automatically has text conversations with website visitors.
Commit
Saving a version of your file in GitHub, with a record of every change made.
CSS
Controls how a web page looks — colours, fonts, layout, and spacing.
Deploy
Making your website or app go live and accessible on the internet.
Embed
Placing one service (like a chatbot) inside another webpage using a script.
Formspree
A free service that receives contact form submissions and emails them to you.
GitHub
A website for storing files and code, with a free feature to host live websites.
GitHub Pages
GitHub’s free hosting that turns your files into a live, 24/7 website.
HTML
The language that describes the structure and content of a web page.
index.html
The default homepage file that browsers load when visiting a website.
JavaScript
The programming language that makes web pages interactive and responsive.
Knowledge Base
Preset questions and answers used by the chatbot’s built-in response system.
Lead
A potential customer who has shared their contact details with you.
OpenAI
The company behind ChatGPT; provides an API to add AI to your own apps.
Repository
A folder on GitHub containing all the files for one project or website.
Script
A short piece of code you paste into a webpage to add a ready-made feature.
Widget
A ready-made mini-application (like a chatbot) that you embed in your site.

Deploy a 24/7 AI Chatbot Using GitHub Only  ·  Beginner’s Guide v1.0

No server required · No coding knowledge required · Always free on GitHub Pages

Connect Local LLM to GitHub Chatbot — All Platforms Guide
SYSTEM ONLINE SELF-HOSTED LLM → GITHUB CHATBOT

LOCAL LLM
TO GITHUB
CHATBOT BRIDGE

Complete setup guide for connecting your self-hosted
llama.cpp / Open WebUI containers to your GitHub Pages chatbot
via Cloudflare Tunnel — on any operating system.

visitor browser ────────────────────────────── internet
│ HTTPS request
github pages ──── your chatbot page, always live
│ fetch() to tunnel URL
cloudflare tunnel ── free, encrypted, no port-forwarding
│ forwards to localhost:8080
your machine ──── running cloudflared daemon
│ http://localhost:8080
llama-mistral ── docker container, /v1/chat/completions
│ AI response
reply ─────────── travels back same path to visitor
Your Setup · docker ps output

Your Running Containers

Based on your docker ps, here is what you have and which ports to use.

ContainerPortAPI EndpointUse
llama-mistral8080localhost:8080/v1/chat/completions✓ Recommended — best quality
llama-tiny8081localhost:8081/v1/chat/completionsFaster, lighter answers
my-ai-chatbot3030Open WebUI — web interfaceAdmin panel only
taskflow-pro3000Not an LLM APIUnrelated service
💡
Both llama-mistral (port 8080) and llama-tiny (port 8081) use the OpenAI-compatible API format — the same interface used by ChatGPT. The JavaScript code in Phase 5 works with both. Just change the port number to switch models.
Phase 1 · macOS

macOS Setup

Tested on macOS Ventura, Sonoma, and Sequoia. Works on both Intel and Apple Silicon (M1/M2/M3).

🍎 macOS — All versions
01

Verify Docker Containers Are Running

Open Terminal (Command + Space → type “Terminal” → Enter):

$ docker ps
# You should see llama-mistral with Status: Up

# If it is not running, start it:
$ docker start llama-mistral
02

Test the LLM API Locally

Confirm the API is responding before setting up the tunnel:

$ curl -s http://localhost:8080/v1/chat/completions \
  -H “Content-Type: application/json” \
  -d ‘{“messages”:[{“role”:”user”,”content”:”Say hello”}],”max_tokens”:20}’

# Expected: JSON with choices[0].message.content = “Hello! How can I help?”
💡
If you see an error, wait 30 seconds for the container to be fully ready, then try again. If the container keeps failing, run docker logs llama-mistral –tail 30 to see why.
03

Install Cloudflared

Option A — Homebrew (Recommended)
# Install Homebrew if you don’t have it:
$ /bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)”

# Then install cloudflared:
$ brew install cloudflared

# Verify:
$ cloudflared –version
Option B — Direct Download (Intel Mac)
$ curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-darwin-amd64.tar.gz -o cloudflared.tar.gz
$ tar -xzf cloudflared.tar.gz
$ sudo mv cloudflared /usr/local/bin/
$ sudo chmod +x /usr/local/bin/cloudflared
Option C — Apple Silicon (M1/M2/M3)
# Replace amd64 with arm64 for Apple Silicon:
$ curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-darwin-arm64.tar.gz -o cloudflared.tar.gz
$ tar -xzf cloudflared.tar.gz
$ sudo mv cloudflared /usr/local/bin/
$ sudo chmod +x /usr/local/bin/cloudflared
04

Start the Tunnel

$ cloudflared tunnel –url http://localhost:8080

# Wait 10-15 seconds. You will see:
# +——————————————————————+
# | Your quick Tunnel has been created! Visit it at: |
# | https://random-words-here.trycloudflare.com |
# +——————————————————————+
⚠️
Copy that URL immediately and save it. You will paste it into your GitHub chatbot code in Phase 5. Do NOT close this Terminal window — the tunnel stops if you close it.
05

Prevent Mac From Sleeping

Open a second Terminal tab (Command+T) and run:

# Prevent sleep indefinitely. Ctrl+C to stop.
$ caffeinate -i

For a permanent setting: System Settings → Battery → Options → Enable “Prevent automatic sleeping when the display is off”

06

Auto-start Tunnel at Login (launchd)

$ sudo nano /Library/LaunchDaemons/com.llm.tunnel.plist
<?xml version=”1.0″ encoding=”UTF-8″?> <!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”> <plist version=”1.0″> <dict> <key>Label</key> <string>com.llm.tunnel</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/cloudflared</string> <string>tunnel</string> <string>–url</string> <string>http://localhost:8080</string> </array> <key>RunAtLoad</key><true/> <key>KeepAlive</key><true/> <key>StandardOutPath</key> <string>/var/log/llm-tunnel.log</string> </dict></plist>
$ sudo launchctl load /Library/LaunchDaemons/com.llm.tunnel.plist
$ sudo launchctl start com.llm.tunnel

# Find your tunnel URL in the log:
$ cat /var/log/llm-tunnel.log | grep trycloudflare
Phase 1 complete — macOS tunnel running, URL copied
Phase 2 · Windows

Windows Setup

Tested on Windows 10 and Windows 11. Uses PowerShell and Task Scheduler for background running.

🪟 Windows 10 / 11
01

Open PowerShell as Administrator

Press Start → type “PowerShell” → right-click → “Run as administrator”. Click Yes on the UAC prompt.

# Verify Docker is running:
PS> docker ps

# Start llama-mistral if not running:
PS> docker start llama-mistral
02

Test the LLM API on Windows

# PowerShell method:
PS> Invoke-RestMethod `
  -Uri “http://localhost:8080/v1/chat/completions” `
  -Method POST `
  -ContentType “application/json” `
  -Body ‘{“messages”:[{“role”:”user”,”content”:”Hello”}],”max_tokens”:20}’

# Or use curl in Command Prompt:
C:\> curl -X POST http://localhost:8080/v1/chat/completions ^
  -H “Content-Type: application/json” ^
  -d “{\”messages\”:[{\”role\”:\”user\”,\”content\”:\”Hello\”}],\”max_tokens\”:20}”
03

Install Cloudflared on Windows

Option A — winget (Windows 10/11, Recommended)
PS> winget install –id Cloudflare.cloudflared
# Close and reopen PowerShell after installation
Option B — MSI Installer

Download and run this MSI file in your browser:

https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.msi
# Double-click the downloaded .msi file to install
# Then reopen PowerShell
Option C — Portable .exe (No Install)
PS> New-Item -ItemType Directory -Path C:\tools -Force
PS> Invoke-WebRequest `
  -Uri “https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe” `
  -OutFile “C:\tools\cloudflared.exe”
PS> $env:PATH += “;C:\tools”
04

Start the Tunnel

PS> cloudflared tunnel –url http://localhost:8080

# Wait for the URL to appear:
# Your quick Tunnel: https://random-words.trycloudflare.com
⚠️
Keep this PowerShell window open. Closing it kills the tunnel. Use Task Scheduler in the next step to run it automatically in the background.
05

Auto-start with Task Scheduler

# Run in PowerShell as Administrator:
PS> $action = New-ScheduledTaskAction `
  -Execute “cloudflared” `
  -Argument “tunnel –url http://localhost:8080”
PS> $trigger = New-ScheduledTaskTrigger -AtLogOn
PS> $settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit 0
PS> Register-ScheduledTask `
  -TaskName “LLM Cloudflare Tunnel” `
  -Action $action `
  -Trigger $trigger `
  -Settings $settings `
  -RunLevel Highest `
  -Force
06

Prevent Windows Sleep

# Disable sleep and monitor timeout (AC power):
PS> powercfg /change standby-timeout-ac 0
PS> powercfg /change monitor-timeout-ac 0

# To restore later:
PS> powercfg /change standby-timeout-ac 30
Phase 2 complete — Windows tunnel configured and auto-start set
Phase 3 · Ubuntu Linux

Ubuntu Linux Setup

Covers Ubuntu 20.04, 22.04, and 24.04 LTS. Uses systemd for permanent background service management.

🐧 Ubuntu 20.04 / 22.04 / 24.04 LTS
01

Check Containers and Docker

$ docker ps

# If permission denied, add yourself to docker group:
$ sudo usermod -aG docker $USER
$ newgrp docker

# Start container if not running:
$ docker start llama-mistral
02

Test the LLM API

$ curl -s http://localhost:8080/v1/chat/completions \
  -H “Content-Type: application/json” \
  -d ‘{“messages”:[{“role”:”user”,”content”:”Hello”}],”max_tokens”:20}’ \
  | python3 -m json.tool

# The | python3 -m json.tool part formats the output nicely
03

Install Cloudflared

Option A — Official Cloudflare Repository (Gets Auto-Updates)
# Add Cloudflare’s GPG key:
$ sudo mkdir -p –mode=0755 /usr/share/keyrings
$ curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg \
  | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null

# Add the repository:
$ echo “deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] \
  https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main” \
  | sudo tee /etc/apt/sources.list.d/cloudflared.list

# Install:
$ sudo apt update && sudo apt install cloudflared -y
Option B — Direct .deb Package
$ wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
$ sudo dpkg -i cloudflared-linux-amd64.deb
$ cloudflared –version
Option C — Binary Only
$ sudo wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
  -O /usr/local/bin/cloudflared
$ sudo chmod +x /usr/local/bin/cloudflared
$ cloudflared –version
04

Quick Test — Start Tunnel Manually

$ cloudflared tunnel –url http://localhost:8080

# Copy the URL that appears then Ctrl+C to stop
# We will run it properly as a service in the next step
05

Create systemd Service (Permanent Background Running)

$ sudo nano /etc/systemd/system/llm-tunnel.service
[Unit] Description=Cloudflare Tunnel for Local LLM After=docker.service network-online.target Wants=network-online.target [Service] Type=simple User=YOUR_USERNAME # ← replace with your actual username ExecStart=/usr/local/bin/cloudflared tunnel –url http://localhost:8080 Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target

Save: Ctrl+O → Enter → Ctrl+X

$ sudo systemctl daemon-reload
$ sudo systemctl enable llm-tunnel
$ sudo systemctl start llm-tunnel
$ sudo systemctl status llm-tunnel

# Should show: Active: active (running) in green

# Get your tunnel URL from the logs:
$ sudo journalctl -u llm-tunnel –no-pager | grep trycloudflare
06

Enable Docker Container Auto-restart

# Make Docker start on boot:
$ sudo systemctl enable docker

# Make containers restart automatically:
$ docker update –restart=always llama-mistral
$ docker update –restart=always llama-tiny
Phase 3 complete — Ubuntu tunnel running as systemd service, survives reboots
Phase 4 · CentOS / AlmaLinux / Rocky Linux

CentOS Setup

Covers CentOS 7, CentOS 8, CentOS Stream 8/9, AlmaLinux 8/9, and Rocky Linux 8/9. Includes SELinux and firewalld configuration.

🎩 CentOS 7/8 · Stream · AlmaLinux · Rocky Linux
01

Verify Docker and Containers

$ docker ps

# Start Docker service if not running:
$ sudo systemctl start docker
$ sudo systemctl status docker

# Start your LLM container:
$ docker start llama-mistral
02

Test API and Install curl if Needed

# CentOS 7 — install curl if missing:
$ sudo yum install curl -y

# CentOS 8 / Stream / AlmaLinux / Rocky:
$ sudo dnf install curl -y

# Test the API:
$ curl -s http://localhost:8080/v1/chat/completions \
  -H “Content-Type: application/json” \
  -d ‘{“messages”:[{“role”:”user”,”content”:”Hello”}],”max_tokens”:20}’
03

Install Cloudflared on CentOS

Option A — RPM Package (CentOS 7)
$ wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-x86_64.rpm
$ sudo yum localinstall cloudflared-linux-x86_64.rpm -y
$ cloudflared –version
Option B — RPM Package (CentOS 8+ / AlmaLinux / Rocky)
$ wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-x86_64.rpm
$ sudo dnf localinstall cloudflared-linux-x86_64.rpm -y
$ cloudflared –version
Option C — Binary (All CentOS versions)
$ sudo wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
  -O /usr/local/bin/cloudflared
$ sudo chmod +x /usr/local/bin/cloudflared
$ cloudflared –version
04

Configure SELinux (CentOS Specific)

CentOS uses SELinux which can block new programs from making network connections. Fix it:

# Check SELinux status:
$ getenforce

# If “Enforcing”, allow network connections:
$ sudo setsebool -P httpd_can_network_connect 1

# Fix the binary’s SELinux label:
$ sudo restorecon -v /usr/local/bin/cloudflared
$ sudo chcon -t bin_t /usr/local/bin/cloudflared

# Temporary permissive mode for testing only:
$ sudo setenforce 0
⚠️
setenforce 0 disables SELinux enforcement temporarily. Do not leave it in permissive mode in production. Always use the setsebool and restorecon approach for a proper permanent fix.
05

Configure Firewalld

Cloudflare Tunnel only makes outbound connections — no inbound ports are needed. But if Docker networking causes issues:

# Allow Docker bridge interface through firewall:
$ sudo firewall-cmd –permanent –zone=trusted –add-interface=docker0
$ sudo firewall-cmd –reload

# Verify:
$ sudo firewall-cmd –list-all
06

Create systemd Service on CentOS

$ sudo nano /etc/systemd/system/llm-tunnel.service
[Unit] Description=Cloudflare Tunnel for Local LLM After=docker.service network-online.target Wants=network-online.target [Service] Type=simple User=YOUR_USERNAME # ← replace with your username ExecStart=/usr/local/bin/cloudflared tunnel –url http://localhost:8080 Restart=always RestartSec=15 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable llm-tunnel
$ sudo systemctl start llm-tunnel
$ sudo systemctl status llm-tunnel

# Get tunnel URL:
$ sudo journalctl -u llm-tunnel –no-pager | grep trycloudflare
07

Enable Docker and Containers at Boot

$ sudo systemctl enable docker
$ docker update –restart=always llama-mistral
$ docker update –restart=always llama-tiny
Phase 4 complete — CentOS tunnel running as systemd service with SELinux configured
Phase 5 · GitHub Chatbot Code

Update Your GitHub Chatbot

Replace the getResponse function in your index.html with this version that calls your local LLM through the tunnel.

01

Open index.html on GitHub

  1. Go to github.com → your repository → click index.html
  2. Click the pencil icon to edit
  3. Press Ctrl+F and search for getResponse
  4. Select and delete the entire existing function
02

Paste the New LLM Function

// ============================================================ // LOCAL LLM CONFIGURATION // Replace the URL with YOUR Cloudflare Tunnel URL // ============================================================ const LLM_CONFIG = { url: ‘https://YOUR-TUNNEL.trycloudflare.com’, // ← REPLACE THIS model: ‘mistral’, // llama.cpp ignores this, but it must be present maxTokens: 200, // max reply length (increase for longer answers) temperature: 0.7, // 0=robotic, 1=creative systemPrompt: `You are a friendly support assistant. Answer questions concisely and helpfully. Keep replies under 80 words unless detail is needed. If unsure, suggest filling the contact form. Be warm, professional, and helpful.` }; // Stores conversation history for multi-turn chat const conversationHistory = []; async function getResponse(message) { // Add user message to history conversationHistory.push({ role: ‘user’, content: message }); try { const response = await fetch( `${LLM_CONFIG.url}/v1/chat/completions`, { method: ‘POST’, headers: { ‘Content-Type’: ‘application/json’ }, body: JSON.stringify({ model: LLM_CONFIG.model, messages: [ { role: ‘system’, content: LLM_CONFIG.systemPrompt }, …conversationHistory // includes full chat history ], max_tokens: LLM_CONFIG.maxTokens, temperature: LLM_CONFIG.temperature, stream: false }) } ); if (!response.ok) throw new Error(`HTTP ${response.status}`); const data = await response.json(); const reply = data.choices[0].message.content.trim(); // Add AI reply to history for context conversationHistory.push({ role: ‘assistant’, content: reply }); return reply; } catch (error) { console.error(‘LLM error:’, error); return “I’m having trouble connecting right now. “ + “Please try again or use the contact form below!”; } }
03

Set Your Tunnel URL

Find this line and replace the placeholder with your real tunnel URL:

// BEFORE: url: ‘https://YOUR-TUNNEL.trycloudflare.com’, // AFTER (use your actual URL): url: ‘https://silent-tree-morning-abc123.trycloudflare.com’,
04

Customize the System Prompt

Edit systemPrompt in LLM_CONFIG to match your business. Examples:

// E-commerce example: systemPrompt: `You are a support agent for [SHOP NAME]. We sell [PRODUCTS]. Orders ship within 2-3 business days. Returns accepted within 30 days. Free shipping over £50. For order tracking, ask for the order number. Be friendly and concise.` // SaaS / software example: systemPrompt: `You are a technical support agent for [APP NAME]. Help users troubleshoot issues, explain features, and guide them to docs at [DOCS URL]. For billing: billing@domain.com. For bugs: ask for OS, browser, and steps to reproduce. Be clear and patient.`
05

Commit and Test

  1. Scroll down → commit message: Connect local LLM via Cloudflare tunnel
  2. Click “Commit changes”
  3. Wait 60 seconds, then visit your GitHub Pages live URL
  4. Open browser DevTools (F12) → Console tab — look for errors
  5. Type a message — your local LLM should reply!
Phase 5 complete — GitHub chatbot now calls your self-hosted LLM
Diagnostics

Troubleshooting

Common errors and their fixes. Check the browser console (F12) first — it usually tells you exactly what went wrong.

“Failed to fetch” — chatbot shows connection error
Checklist: (1) Is cloudflared still running? Check with systemctl status llm-tunnel (Linux) or Task Manager (Windows). (2) Is the container up? docker ps — is llama-mistral listed as Up? (3) Did the quick-tunnel URL change? Restart cloudflared and update index.html with the new URL. (4) Try the permanent named tunnel (Phase 7 in the .md guide) to stop URLs changing.
CORS error in browser console
The browser is blocking cross-domain requests. Fix by restarting your llama.cpp container with the CORS flag:
$ docker stop llama-mistral
$ docker run -d –name llama-mistral -p 8080:8080 \
  ghcr.io/ggml-org/llama.cpp:server \
  –host 0.0.0.0 –port 8080 \
  –cors-allow-origins “*”
Responses are very slow (30+ seconds)
Switch to llama-tiny (port 8081) for faster replies. Also reduce maxTokens from 200 to 80. Check RAM: docker stats llama-mistral — Mistral needs 6GB+ available. In Docker Desktop → Settings → Resources → increase Memory allocation.
CentOS: “Permission denied” running cloudflared
$ sudo chmod 755 /usr/local/bin/cloudflared
$ sudo chown root:root /usr/local/bin/cloudflared
$ sudo restorecon -v /usr/local/bin/cloudflared
$ sudo setsebool -P httpd_can_network_connect 1
Windows: cloudflared not found after install
PS> Get-ChildItem -Path C:\ -Recurse -Filter “cloudflared.exe” 2>$null
# Find where it installed, then add to PATH:
PS> $env:PATH += “;C:\path\to\cloudflared”
Tunnel URL keeps changing on every restart
Quick tunnels get a new URL every time cloudflared restarts. Solution: set up a Named Tunnel (free) using the steps in the .md guide, Phase 7. Named tunnels give you a permanent URL that never changes — update your index.html once and forget about it.
Reference

Quick Reference

All essential commands in one place. Copy and run as needed.

🐳 Docker — all platforms
# List running containers
docker ps

# Start/stop containers
docker start llama-mistral
docker stop llama-mistral

# View logs
docker logs llama-mistral --tail 50

# Auto-restart on reboot
docker update --restart=always llama-mistral

# Resource usage
docker stats
🌐 Test LLM API — macOS / Linux
curl -s http://localhost:8080/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"messages":[{
    "role":"user",
    "content":"Hello"
  }],"max_tokens":50}'
🌐 Test LLM API — Windows PowerShell
Invoke-RestMethod `
  -Uri "http://localhost:8080/v1/chat/completions" `
  -Method POST `
  -ContentType "application/json" `
  -Body '{
    "messages":[{"role":"user","content":"Hello"}],
    "max_tokens":50
  }'
☁️ Cloudflared — tunnel commands
# Quick tunnel (URL changes on restart)
cloudflared tunnel --url http://localhost:8080

# Named tunnel (permanent URL)
cloudflared tunnel run llm-chatbot

# Version check
cloudflared --version
⚙️ systemd — Ubuntu / CentOS
sudo systemctl start   llm-tunnel
sudo systemctl stop    llm-tunnel
sudo systemctl restart llm-tunnel
sudo systemctl status  llm-tunnel
sudo systemctl enable  llm-tunnel

# Watch live logs:
sudo journalctl -u llm-tunnel -f

# Get tunnel URL from logs:
sudo journalctl -u llm-tunnel \
  --no-pager | grep trycloudflare
🪟 Windows — Task Scheduler
# Check status:
Get-ScheduledTask `
  -TaskName "LLM Cloudflare Tunnel"

# Start / Stop:
Start-ScheduledTask `
  -TaskName "LLM Cloudflare Tunnel"
Stop-ScheduledTask `
  -TaskName "LLM Cloudflare Tunnel"
ContainerPortSwitch to use it
llama-mistral8080Tunnel –url http://localhost:8080, set LLM_CONFIG.url to port 8080 tunnel
llama-tiny8081Tunnel –url http://localhost:8081, set LLM_CONFIG.url to port 8081 tunnel
LOCAL LLM → GITHUB CHATBOT BRIDGE  ·  v1.0  ·  macOS · Windows · Ubuntu · CentOS
llama.cpp · Cloudflare Tunnel · GitHub Pages