Přeskočit obsah

Deployment

Jak deployovat backend, worker, frontend, dokumentaci.

Backend + Worker (Sliplane)

Auto-deploy z GitHub main

Sliplane má GitHub integration enabled per service:

https://sliplane.io → service settings → Repository
  url: https://github.com/Algawebbusiness/nemoreport-ai-backend-v2
  branch: main
  autoDeploy: true

Kdykoliv někdo pushne na main: 1. Sliplane build agent (Hetzner-based) cloneuje repo 2. Build Docker image z Dockerfile 3. Push do registry-01.nbg1.ger.sliplane.io/... 4. Pull + restart container 5. Health check /health

Build čas typicky 60-90s (cached layers).

Dockerfile

FROM docker.io/library/python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
RUN apt-get update \
    && apt-get install -y --no-install-recommends libmagic1 \
    && rm -rf /var/lib/apt/lists/*
COPY pyproject.toml uv.lock* README.md ./
RUN uv sync --frozen --no-install-project --no-dev || uv sync --no-install-project --no-dev
COPY app ./app
COPY prompts ./prompts
COPY skills ./skills
COPY fixtures ./fixtures
RUN uv sync --frozen --no-dev || uv sync --no-dev

Stejný image pro backend i worker — liší se jen cmd:

Service CMD
nemoreport-ai-backend-v2 uv run uvicorn app.main:app --host 0.0.0.0 --port 8000
nemoreport-ai-worker-v2 uv run python -m app.worker_entry

Environment variables

ENV se nastavuje per service v Sliplane UI nebo via API. Strict-validated v app/config.py (fail-fast on missing).

Required pro backend + worker (oba mají stejný set):

ENV Příklad Secret?
SUPABASE_URL https://cubdrgjdkatyecrgckwp.supabase.co ne
SUPABASE_ANON_KEY sb_publishable_... ne
SUPABASE_SERVICE_ROLE_KEY eyJ... ano
GEMINI_API_KEY AIza... ano
MISTRAL_API_KEY ... ano
COHERE_API_KEY ... ano
ADMIN_HASH 3bddbafdec... (sha1 of secret) ano
NETTE_HMAC_SECRET ... ano (jen backend)
EMBEDDING_MODEL gemini-embedding-2 ne
EMBEDDING_MODEL_VERSION ga-2026-04 ne
COHERE_RERANK_MODEL rerank-v4.0-pro ne
COHERE_RERANK_ENABLED true ne
LLM_MODEL google-gla:gemini-3-flash-preview ne
ALLOWED_ORIGINS https://nemoreport-ai-frontend-v2.algaweb.workers.dev,http://localhost:3000 ne
RATE_LIMIT_STORAGE_URI redis://nemoreport-redis.internal:6379/0 ne
REDIS_URL redis://nemoreport-redis.internal:6379/1 ne
LOG_LEVEL INFO ne
APP_ENV production ne

Update env vars

Per Sliplane API quirk (app/CLAUDE.md note): - updateService PUT s value="" smaže ENV var - Pro secret keys vždy passnout konkrétní hodnotu, ne "" - secret=true v getService response zobrazí jako value="" (masking, ne reálná empty)

Aktualizace přes MCP: mcp__sliplane__updateService s celým env arrayí (full replace).

Manual restart

# Restart backend
sliplane services restart nemoreport-ai-backend-v2

# Or via UI: Services → Click service → Restart

Logs

# Tail logs
sliplane services logs nemoreport-ai-backend-v2 --follow

# Or via MCP:
# mcp__sliplane__getServiceLogs(projectId, serviceId, from=<unix_ts>)

Resource scaling

Sliplane pricing: per-service CPU + RAM. Aktuálně každý service 1 CPU × 1 GB RAM (default).

Pro scale-up:

sliplane services rescale nemoreport-ai-backend-v2 --cpu 2 --ram 2GB

Rollback

Sliplane drží předchozí Docker images v registry. Rollback: 1. Find předchozí commit hash v Sliplane events log 2. git revert na předchozí commit 3. git push origin main → auto-deploy

Redis (Sliplane)

service: nemoreport-redis
image: redis:7-alpine
internal_dns: nemoreport-redis.internal:6379
persistence: AOF (append-only file)

Žádné public exposure. Backend + worker komunikují přes internal Sliplane network.

Backup strategy: Redis AOF persistuje na disk volume. Pro DR je potřeba volume snapshot (Sliplane managed).

Frontend (Cloudflare Workers)

Manual deploy

CF Pages auto-deploy nepoužíváme. Frontend deploy je manual přes wrangler:

cd /home/jiri/Nextcloud/vibecode/Nemoreport_v2/nemoreport-ai-frontend-v2

# Build (Next.js + OpenNext adapter)
npm run build  # → .next/ + .open-next/

# Deploy na CF Workers
npm run deploy  # = wrangler deploy

# Output:
#   Total Upload: 6458.55 KiB / gzip: 1348.60 KiB
#   Worker Startup Time: 35 ms
#   Uploaded nemoreport-ai-frontend-v2 (22.44 sec)
#   Deployed: https://nemoreport-ai-frontend-v2.algaweb.workers.dev
#   Current Version ID: <uuid>

Konfigurace

wrangler.jsonc:

{
  "name": "nemoreport-ai-frontend-v2",
  "main": ".open-next/worker.js",
  "compatibility_date": "2025-09-23",
  "compatibility_flags": ["nodejs_compat"],
  "assets": {
    "directory": ".open-next/assets",
    "binding": "ASSETS"
  }
}

open-next.config.ts:

import { defineCloudflareConfig } from "@opennextjs/cloudflare";

export default defineCloudflareConfig({
  // Default config
});

Environment variables

Setup v wrangler.jsonc (vars, not secrets):

{
  "vars": {
    "NEXT_PUBLIC_SUPABASE_URL": "https://cubdrgjdkatyecrgckwp.supabase.co",
    "NEXT_PUBLIC_SUPABASE_ANON_KEY": "sb_publishable_...",
    "NEXT_PUBLIC_BACKEND_URL": "https://nemoreport-ai-backend-v2.sliplane.app"
  }
}

Žádné secrets na FE — SUPABASE_SERVICE_ROLE_KEY zůstává jen na BE.

Rollback

Cloudflare drží versions:

# List versions
wrangler versions list

# Rollback
wrangler versions rollback <version-id>

Nebo přes CF Workers Dashboard: Workers > nemoreport-ai-frontend-v2 > Deployments > Rollback.

Supabase

Migrace

# Local dev
cd /home/jiri/Nextcloud/vibecode/Nemoreport_v2/nemoreport-ai-backend-v2
supabase link --project-ref cubdrgjdkatyecrgckwp
supabase db push

# Or inline via MCP:
# mcp__claude_ai_Supabase__apply_migration(project_id, name, query)

Config (auth, redirect URLs, SMTP)

supabase/config.toml je source of truth. Push:

supabase config push --yes

Změní: - api.schemas (PostgREST exposed schemas) - auth.hooks (custom JWT hook function) - auth.email.template (custom magic link template) - SMTP config s RESEND_API_KEY env substituci - auth.redirect_urls (allowed redirect destinations)

Backups

Supabase Pro plán: - PITR (Point-in-time recovery) — 7 dní default - Daily backups — týden retention

Pro produkci doporučeno upgrade Free → Pro ($25/mo) — PITR essential pro disaster recovery.

Edge Functions (NEPOUŽÍVÁME zatím)

Phase B+ jsme se rozhodli use Sliplane worker místo Supabase Edge Functions kvůli: - Lepší debugging (full Python ekosystém) - Žádné cold starts - Lépe handle long-running OCR (15 min timeouty)

Dokumentace

Lokální dev

cd /home/jiri/Nextcloud/vibecode/Nemoreport_v2

# Install (jednorazově)
uv tool install mkdocs-material

# Dev server s live reload
mkdocs serve  # http://127.0.0.1:8000

# Static build
mkdocs build  # → site/

Hosting options

Option 1: Cloudflare Pages (recommended)

# Build
mkdocs build

# Deploy
wrangler pages deploy site/ --project-name=nemoreport-docs

Option 2: GitHub Pages

# Push docs to gh-pages branch
mkdocs gh-deploy --force

Option 3: Sliplane static

Add new service s nginx serving site/ directory.

Doporučeno: Cloudflare Pages, custom doména docs.nemoreport.algaweb.cz.

Lokální development

Backend

cd /home/jiri/Nextcloud/vibecode/Nemoreport_v2/nemoreport-ai-backend-v2

# Install deps
uv sync

# Setup .env.local s minimum:
cat > .env.local <<EOF
SUPABASE_URL=https://cubdrgjdkatyecrgckwp.supabase.co
SUPABASE_ANON_KEY=...
SUPABASE_SERVICE_ROLE_KEY=...
GEMINI_API_KEY=...
ADMIN_HASH=test_local
RATE_LIMIT_STORAGE_URI=memory://
APP_ENV=development
EOF

# Run dev server
uv run uvicorn app.main:app --reload --port 8000

# Run worker (separate terminal)
uv run python -m app.worker_entry
# Note: needs Redis. Use Sliplane internal nebo lokální docker run redis.

Frontend

cd /home/jiri/Nextcloud/vibecode/Nemoreport_v2/nemoreport-ai-frontend-v2

npm install
npm run dev  # http://localhost:3000

# Setup .env.local:
cat > .env.local <<EOF
NEXT_PUBLIC_SUPABASE_URL=https://cubdrgjdkatyecrgckwp.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=sb_publishable_...
NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
EOF

Deploy checklist (production go-live)

Před production:

  • Supabase upgrade Free → Pro ($25/mo) pro PITR
  • Resend domain verification (mimo sandbox owner-only)
  • Cohere production key (mimo trial 1000/mo limit)
  • Vertex AI tier místo google-gla Developer API (data privacy)
  • DNS cutover: nemoreport-ai-frontend-v2.algaweb.workers.dev → custom doména
  • HTTPS certs (CF managed automaticky)
  • Monitoring + alerts (Sentry / Datadog?)
  • Backup strategy (Supabase PITR + týdenní DB dump do CF R2)
  • Cost alerts (Stripe / billing thresholds)
  • Pen test (Phase A+B+C má pgTAP suite + smoke tests, ale dedicated security audit doporučen)
  • GDPR compliance review (data retention, right to erasure → nemoreport.handle_delete_user trigger)
  • Terms of Service + Privacy Policy hosted

Disaster recovery

Scenario 1: Sliplane outage

  • Backend + worker down → app nefunguje
  • Mitigation: deploy na backup provider (Render / Fly.io) — 2 dny prep
  • RTO: 4 hodiny (manual restore from Docker images)
  • RPO: 0 (Postgres je nezávislé na Sliplane)

Scenario 2: Supabase outage

  • DB + Auth down → app nefunguje
  • Mitigation: vendor's responsibility (status page); Pro plán má SLA
  • RTO: depends on Supabase
  • Recovery: PITR pokud DB corruption

Scenario 3: Cloudflare outage

  • Frontend down (FE Worker)
  • Mitigation: rare (Cloudflare tier-1 reliability)
  • RTO: depends on CF
  • Backup: Vercel deploy ready (@opennextjs works na Vercel)

Scenario 4: Vendor data loss

  • Supabase delete project / corruption
  • Mitigation: PITR (7d), týdenní DB dump do CF R2 (offsite)
  • Implementation: cron job na týdenní pg_dump → upload na R2

Scenario 5: Code repo loss

  • GitHub + GitLab oba lost (extremely unlikely)
  • Mitigation: dual-push remote (git push origin main → oba simultaneously)
  • Local clones na dev machines + Nextcloud sync (/home/jiri/Nextcloud/vibecode/)