Skip to content

Hosting Plan: wiki.graffold.com

Goal

Three domains on one Hetzner VPS:

Domain Purpose
wiki.graffold.com Unified docs for graffold-api + graffold-ingest
api.graffold.com Live API with interactive Swagger/ReDoc
graphrag.graffold.com Temporary replica of Olink graphrag_api wiki (legacy reference)

Architecture

wiki.graffold.com                    ← mkdocs Material (graffold-api + ingest)
├── /                                ← Landing / home
├── /getting-started/                ← Quick start guides
├── /architecture/                   ← System design
├── /ingestion/                      ← Pipeline + graffold-ingest docs
├── /querying/                       ← Query agents, modes
├── /operations/                     ← Redis, Grafana, hosting
└── /development/                    ← Testing, CLI, SDK API reference

api.graffold.com                     ← FastAPI (live, auto-generated)
├── /docs                            ← Swagger UI (interactive)
├── /redoc                           ← ReDoc (clean reference layout)
└── /openapi.json                    ← Machine-readable spec

graphrag.graffold.com                ← mkdocs Material (legacy Olink wiki replica)
├── /                                ← GraphRAG API docs (temporary)
├── /ingestion/                      ← Pipeline guides
├── /architecture/                   ← System design
├── /benchmarks/                     ← Gold standard evals
└── /operations/                     ← Maintenance & validation

Deployment

Static Wikis → Cloudflare Pages

Both wiki sites are deployed as static mkdocs builds to Cloudflare Pages. This gives:

  • Zero infra to manage (no Caddy/nginx for static content)
  • Global CDN with edge caching
  • Automatic preview deployments on PRs
  • Instant rollbacks via CF dashboard
  • Free custom domains with auto-TLS
wiki.graffold.com      → CF Pages project "graffold-wiki"
graphrag.graffold.com  → CF Pages project "graphrag-wiki"

Live API → Hetzner VPS

api.graffold.com       → Hetzner VPS (Caddy → FastAPI container)

The API needs a server (database connections, LLM calls, state). The wikis don't.

Setup: Cloudflare Pages

  1. Create two Pages projects in CF dashboard:
  2. graffold-wiki → custom domain wiki.graffold.com
  3. graphrag-wiki → custom domain graphrag.graffold.com

  4. Add GitHub secrets to the repo:

  5. CLOUDFLARE_API_TOKEN — API token with Pages edit permission
  6. CLOUDFLARE_ACCOUNT_ID — your CF account ID

  7. Push to main — the workflow builds mkdocs and deploys via wrangler pages deploy

Setup: API (Hetzner)

The API continues to run on Hetzner with a simpler Caddyfile (only one domain now):

api.graffold.com {
    reverse_proxy localhost:8000
    header {
        X-Content-Type-Options "nosniff"
        Referrer-Policy "strict-origin-when-cross-origin"
    }
}

Wiki Build Pipeline

# Build wiki (runs in CI or on deploy)
pip install mkdocs-material
mkdocs build --site-dir wiki-build/

# Deploy to Hetzner
rsync -avz wiki-build/ hetzner:/srv/wiki/

FastAPI Docs Customization

To match the clean layout of the Olink API reference, customize the Swagger UI:

# In api/app.py
app = FastAPI(
    title="Graffold API",
    version="0.2.0",
    description="Scientific Knowledge Graph Platform API",
    docs_url="/docs",
    redoc_url="/redoc",
    openapi_url="/openapi.json",
    openapi_tags=[
        {"name": "sdk", "description": "SDK endpoints for external integrations"},
        {"name": "query", "description": "Knowledge graph query and session management"},
        {"name": "ingestion", "description": "Document ingestion and KG construction"},
        {"name": "enrichment", "description": "External database enrichment"},
        {"name": "platform", "description": "Health, metrics, and configuration"},
    ],
)

CI/CD

# .github/workflows/docs.yml
name: Deploy Docs
on:
  push:
    branches: [main]
    paths: ['docs/**', 'mkdocs.yml']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
      - run: pip install mkdocs-material
      - run: mkdocs build --site-dir wiki-build
      - name: Deploy to Hetzner
        run: rsync -avz -e "ssh -o StrictHostKeyChecking=no" wiki-build/ deploy@${{ secrets.HETZNER_IP }}:/srv/wiki/

DNS Records

wiki.graffold.com      CNAME → graffold-wiki.pages.dev      (CF Pages)
graphrag.graffold.com  CNAME → graphrag-wiki.pages.dev      (CF Pages)
api.graffold.com       A     → 89.167.10.208                (Hetzner VPS)

Wiki domains use Cloudflare Pages custom domains (CNAME to *.pages.dev).
The API domain points to Hetzner where the FastAPI container runs.

All get TLS automatically — CF Pages via their edge, Hetzner via Caddy + Let's Encrypt.