El portal AI-LAB utiliza dos canales de publicacion independientes que comparten el mismo codigo fuente.

┌─────────────────┐
│ GitHub Repo │
│ albertgracia/ │
│ ai-lab │
└────────┬────────┘
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌────────────┐ ┌──────────────┐
│ Cloudflare Pages│ │ Cloudflare │ │ Servidor │
│ (Build automatico│ │ Tunnel │ │ 192.168.1.30 │
│ desde GitHub) │ │ │ │ │
└────────┬────────┘ └─────┬──────┘ └──────┬───────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌────────────┐ ┌──────────────┐
│ Blog Publico │ │ Traefik │ │ Astro Preview│
│ ai-lab.labrazah │ │ Reverse │ │ :4322 │
│ ome.com │ │ Proxy │ │ │
└─────────────────┘ └────────────┘ └──────────────┘
┌─────────────────┐
│ Blog Privado │
│ blog-ai-lab.labr│
│ azahome.com │
└─────────────────┘
  • Repo: github.com/albertgracia/ai-lab
  • Rama: main
  • Contenido: Codigo fuente Astro en apps/ialab-docs/
  • Trigger: Cada push a main activa Cloudflare Pages
  • URL: https://ai-lab.labrazahome.com
  • Build: Automatico desde GitHub (push a main)
  • Comando: npm run build en apps/ialab-docs/
  • Directorio publicacion: apps/ialab-docs/dist/
  • SSL: Automatico (Cloudflare)
  • Cache: Purga manual via Cloudflare Dashboard

3. Cloudflare Tunnel + Traefik (Blog Privado)

Section titled “3. Cloudflare Tunnel + Traefik (Blog Privado)”
  • URL: https://blog-ai-lab.labrazahome.com
  • Tunnel: Cloudflare Tunnel (docker en 192.168.1.40)
  • Proxy: Traefik (docker en 192.168.1.30)
  • Backend: Astro preview en :4322
  • Servicio: ailab-docs.service (systemd)
  • API: /api/* disponible via Traefik → :8084
  • Servicio: ailab-docs.service (systemd, autoarranque)
  • Comando: astro preview --host 0.0.0.0 --port 4322
  • Build: Manual via npm run build
  • Contenido: Mismo dist/ que Cloudflare Pages
apps/ialab-docs/src/content/
# 1. Crear o modificar documento en:
# 2. Construir localmente
cd /opt/ai-lab/apps/ialab-docs && npm run build
# 3. Commit y push a GitHub
cd /opt/ai-lab
git add apps/ialab-docs/
git commit -m "docs: descripcion del cambio"
git push origin main
SitioEfectoTiempo
Blog PublicoCloudflare Pages rebuild automatico~1-2 min
Blog PrivadoGitHub Actions runner rebuild + restart automatico~20-30 s

Para forzar el blog privado manualmente, si hace falta:

Section titled “Para forzar el blog privado manualmente, si hace falta:”
Terminal window
cd /opt/ai-lab/apps/ialab-docs && npm run build
sudo systemctl restart ailab-docs.service
Build command: npm run build
Build directory: apps/ialab-docs
Output directory: dist
Root directory: apps/ialab-docs
Node version: 22 (por defecto)
/opt/ai-lab/data/traefik/dynamic/ai-lab-docs.yml
http:
routers:
ai-lab-docs:
rule: "Host(`blog-ai-lab.labrazahome.com`)"
service: ai-lab-docs
ai-lab-docs-api:
rule: "Host(`blog-ai-lab.labrazahome.com`) && PathPrefix(`/api/`)"
service: ai-lab-docs-api
priority: 10
services:
ai-lab-docs:
loadBalancer:
servers:
- url: "http://host.docker.internal:4322"
ai-lab-docs-api:
loadBalancer:
servers:
- url: "http://host.docker.internal:8084"
ai-lab.labrazahome.com → Cloudflare Pages (CNAME)
blog-ai-lab.labrazahome.com → Cloudflare Tunnel (CNAME)
AspectoPublicoPrivado
URLai-lab.labrazahome.comblog-ai-lab.labrazahome.com
AutenticacionNoCloudflare Access (opcional)
BuildAutomatico (Cloudflare)Manual (local)
APINo disponibleDisponible (/api/*)
ActualizacionPush a GitHubRebuild + restart servicio
Latencia~2 min desde push0s (local)
Terminal window
# Verificar build local
cd /opt/ai-lab/apps/ialab-docs && npm run build 2>&1 | tail -5
# Debe mostrar: "64 page(s) built" sin errores
# Verificar servicio
sudo systemctl is-active ailab-docs.service
# Verificar sitio privado
curl -s http://localhost:4322/ | head -1
# Verificar sitio publico (externa)
curl -s https://ai-lab.labrazahome.com/ | head -1