github-sync-test / docs /github-hf-custom-domain-guide.md
billyaungmyint's picture
Sync from GitHub via hub-sync
1ec8f50 verified

A newer version of the Gradio SDK is available: 6.14.0

Upgrade

GitHub β†’ Hugging Face Space with Custom Domain β€” Setup Guide

A complete, repeatable playbook. Follow in order. Sections marked ⚠️ are the common pitfall spots.


Table of Contents

  1. Prerequisites
  2. Create the Hugging Face Space
  3. Configure the GitHub Repository
  4. Set Up the Sync Workflow
  5. README Front Matter (Critical)
  6. Custom Domain Setup
  7. Gradio root_path Rule
  8. Verify End-to-End
  9. Troubleshooting Reference

1. Prerequisites

What Where to get it
Hugging Face account https://huggingface.co
HF write token (fine-grained or classic) HF β†’ Settings β†’ Access Tokens β†’ New token β†’ Role: Write
GitHub repo (public or private) github.com
Domain registrar access (for custom domain) Your registrar (Cloudflare, Namecheap, etc.)

2. Create the Hugging Face Space

  1. Go to https://huggingface.co/new-space
  2. Fill in:
    • Owner: your HF username or org
    • Space name: e.g. github-sync-test
    • SDK: Gradio (or Streamlit)
    • Visibility: Public or Private
  3. Click Create Space β€” the Space is created with a default README.md.

You do not need to push any code manually; the GitHub Action will do it.


3. Configure the GitHub Repository

3.1 Add the HF token as a GitHub Secret

  1. GitHub repo β†’ Settings β†’ Secrets and variables β†’ Actions
  2. Click New repository secret
    • Name: HF_TOKEN
    • Value: your HF write token from step 1
  3. Save.

3.2 Minimum required files

your-repo/
β”œβ”€β”€ README.md          ← MUST have HF front matter (see Β§5)
β”œβ”€β”€ main.py            ← your Gradio app entry point
β”œβ”€β”€ requirements.txt   ← at minimum: gradio>=5.0
└── .github/
    └── workflows/
        └── sync.yml

4. Set Up the Sync Workflow

Create .github/workflows/sync.yml:

name: Sync to Hugging Face

on:
  push:
    branches: [master]        # or "main" β€” match your default branch
  workflow_dispatch:           # allows manual trigger from GitHub UI

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0       # full history required by hub-sync
          lfs: true

      - name: Write VERSION file
        run: echo "${{ github.sha }}" > VERSION

      - uses: huggingface/hub-sync@main
        with:
          github_repo_id: YOUR_GH_USERNAME/YOUR_GH_REPO
          huggingface_repo_id: YOUR_HF_USERNAME/YOUR_SPACE_NAME
          repo_type: space     # MUST be "space" for HF Spaces
          hf_token: ${{ secrets.HF_TOKEN }}

Replace YOUR_GH_USERNAME/YOUR_GH_REPO and YOUR_HF_USERNAME/YOUR_SPACE_NAME with your actual values.


5. README Front Matter (Critical)

⚠️ The single most common cause of sync failures.

The README.md at the repo root must start with this YAML front matter block. Without it, HF rejects the push with "Missing configuration in README".

---
title: your-space-name
emoji: "πŸ€—"
colorFrom: blue
colorTo: indigo
sdk: gradio
app_file: main.py
pinned: false
---

# Your Space Title
...rest of your README...
Field Notes
title Must match (or at least not conflict with) your HF Space name
sdk gradio or streamlit
app_file The Python file that launches your app (e.g. main.py)
emoji, colorFrom, colorTo Cosmetic β€” any valid values work
pinned true pins the Space on your profile

6. Custom Domain Setup

6.1 Add the domain in HF Space settings

  1. HF Space β†’ Settings β†’ Custom domains
  2. Enter your domain: e.g. demo.example.com
  3. HF shows you a CNAME target (looks like billyaungmyint-github-sync-test.hf.space)
  4. Copy that CNAME target value.

6.2 Add the DNS record at your registrar

Type Host Value TTL
CNAME demo (subdomain part only) billyaungmyint-github-sync-test.hf.space 300 or Auto

If you want an apex/root domain (example.com), use a CNAME Flattening or ALIAS record β€” check your registrar's docs. Most registrars support this via Cloudflare's "CNAME at root" feature.

6.3 Wait for DNS propagation

  • Typical: 1–5 minutes on Cloudflare, up to 48 hours on others.
  • Verify with: nslookup demo.example.com β€” should resolve to HF's servers.
  • HF will automatically provision a TLS certificate once the CNAME resolves.

6.4 ⚠️ No GRADIO_ROOT_PATH needed

When using a custom domain at the root path (e.g. https://demo.example.com):

  • Do not set GRADIO_ROOT_PATH in HF Space variables.
  • Leave it unset (or set to "").
  • Setting it to the old .hf.space URL after a domain change causes "Could not get API info. fetch failed".

Only set GRADIO_ROOT_PATH if your app is served at a subpath, e.g. https://example.com/myapp β†’ set GRADIO_ROOT_PATH=/myapp.


7. Gradio root_path Rule

Use this pattern in your main.py β€” it is safe for all scenarios:

import os

if __name__ == "__main__":
    # Strip trailing slash to avoid double-slash issues.
    # Leave GRADIO_ROOT_PATH unset (or "") for custom domains at root.
    _root_path = os.getenv("GRADIO_ROOT_PATH", "").rstrip("/")
    demo.launch(server_name="0.0.0.0", root_path=_root_path)
Deployment scenario GRADIO_ROOT_PATH env var value
Default .hf.space URL (unset) or ""
Custom domain at root (myapp.com) (unset) or ""
Custom domain at subpath (myapp.com/demo) /demo
Local dev (unset) β€” runs fine

8. Verify End-to-End

Run through this checklist after initial setup or after any DNS/domain change:

  • nslookup your-domain.com resolves (no NXDOMAIN)
  • https://your-domain.com loads the Space (no TLS error)
  • Browser DevTools β†’ Network: no failed /info or queue/join requests
  • Push a trivial commit to GitHub β†’ Action runs green β†’ Space rebuilds β†’ change appears
  • HF Space settings β†’ Custom domains β†’ Status shows βœ… (not "Pending")

9. Troubleshooting Reference

Error Cause Fix
Missing configuration in README README has no HF YAML front matter Add the front matter block (see Β§5)
Could not get API info. fetch failed GRADIO_ROOT_PATH set to wrong URL, or DNS not yet propagated Clear GRADIO_ROOT_PATH in Space variables (see Β§6.4 & Β§7)
HF_TOKEN secret not found / 401 Secret missing or token lacks write scope Re-add secret with a Write token (see Β§3.1)
Action fails: repo_type: space error Wrong repo_type in workflow Set repo_type: space in sync.yml (see Β§4)
Space stuck on "Building" Dependency error in requirements.txt Check Space build logs; pin a working version
TLS certificate "Pending" for >30 min CNAME not propagated yet or wrong target Verify CNAME value matches exactly what HF shows
Custom domain works but assets 404 root_path set to a subpath that doesn't exist Set GRADIO_ROOT_PATH="" or the correct subpath
Space rebuilds but shows old code fetch-depth: 0 missing in workflow Add fetch-depth: 0 to actions/checkout@v4 (see Β§4)
API Error / ValueError: API key is missing Secrets added to GitHub but missing in HF Space Add API keys directly in HF Space β†’ Settings β†’ Variables and secrets

10. Using this Template for AI Projects

This repository is designed as a ready-to-use template for future projects, coming with a pre-built Multi-Provider AI Chat Application in main.py.

Built-in Features

  • Multi-Provider Backend: Supports Hugging Face (z.ai), Google Gemini, GitHub Models, OpenRouter, and Fireworks.
  • Dynamic UI Selection: Gradio UI dropdowns to select providers and dynamically updated models natively without code edits.
  • Cost-Optimization Presets: Select quick presets like Ultra Cheap, Budget Dev, Balanced, and Quality Check to auto-configure cost-effective development environments.
  • Automatic Fallback: Specify auto as the backend to automatically cycle through fallback providers if one fails (configured via AI_FALLBACK_ORDER).

Environment Variables

⚠️ Important Pitfall: GitHub Action secrets do not automatically sync to Hugging Face Space secrets. While HF_TOKEN must be a GitHub Secret for CI/CD, runtime API keys must be added directly to Hugging Face.

1. GitHub Action Secrets (For Sync Only)

  • HF_TOKEN: Hugging Face write token (Required for hub-sync to work)

2. Hugging Face Space Secrets (For Runtime) Configure these in your HF Space via Settings β†’ Variables and secrets:

  • HF_TOKEN: Hugging Face token (if you want the space itself to make authenticated HF API calls)
  • GOOGLE_API_KEY: API key for Gemini models
  • GITHUB_TOKEN: API key for GitHub Models
  • OPENROUTER_API_KEY: API key for OpenRouter
  • FIREWORKS_API_KEY: API key for Fireworks

(Note: For local development, you can place these in a .env file or export them in your terminal).

You can further customize defaults and available choices by setting:

  • AI_BACKEND: Default provider (e.g., hf, google, github, auto)
  • <PROVIDER>_MODEL: Default model for the provider (e.g., GOOGLE_MODEL=gemini-2.0-flash-lite)
  • <PROVIDER>_MODELS: Comma-separated list for model dropdown choices (e.g., GOOGLE_MODELS=gemini-2.0-flash-lite,gemini-1.5-flash)