Admin app onboarding — dev guide¶
Jak v praxi zaregistrovat novou vendor aplikaci do AVAX platformy. Pro super_adminy a vývojáře platformy. User-facing průvodce je v user-guide/admin/aplikace-gateway.md.
Spec: docs/spec/admin-app-onboarding.md.
Architektura toho, co se děje¶
Vendor app onboarding se skládá ze čtyř kroků:
1. create_app endpoint → DB row + Gitea repo + S3 bucket + secrets + port
2. Vendor pushne kód → Gitea Actions CI postaví image + spustí kontejner
3. Gateway toggle → flip apps.gateway_enabled=true + pubsub trigger
4. Background probe → poll /<slug>/health 30s → apps.health_status
Kroky 1, 3 a 4 jsou plně automatizované přes admin UI v launcheru (Vendoři tab → "+ Nová aplikace" + Aplikace tab → checkbox "Gateway routing"). Krok 2 dělá vendor sám (push do Gitea).
Standardní flow (UI cesta)¶
- Login do launcheru jako super_admin (
michal@avaxis.cznebo jinýsystem_role=super_admin). - Tab "Vendoři" → "+ Nová aplikace" — vyplnit slug, jméno, popis, zaškrtnout "Má backend (per-app kontejner)" pokud aplikace má serverovou část.
- Klik "Vytvořit" — backend volá
POST /admin/app-management/create. Po ~10 s response s linkem na Gitea repo a S3 bucket info. - Vendor naklonuje repo (např.
paincelebratorMichal pro AVAXIS apps), pushe vlastní kód. Gitea Actions automaticky spustí.gitea/workflows/backend.ymlco postaví image a spustí kontejneravax-app-<slug>na127.0.0.1:<port>(port byl alokován v kroku 1). - Tab "Aplikace" → najít novou app → otevřít detail → sekce
"🌐 Distribuce" → zaškrtnout "Gateway routing". Backend volá
PUT /admin/app-management/<slug>/gateway {enabled:true}: - flip
gateway_enabled=true+is_public=truev DB - Redis pubsub
apps.changed→ apps-gateway refresh cache <1s - FastAPI BackgroundTasks →
health_probe.probe_app_health()30s - Sledovat badge "⏳ gateway" v Aplikace seznamu — během ~30 s
se přebarví na
✅ gateway(healthy) nebo❌ gateway(probe selhala).
Po tomto je https://api.avaxis.cz/apps/<slug>/... (nebo
http://192.168.1.55/apps/<slug>/... z dev LAN) plně funkční.
Ruční řešení (fallback když UI nefunguje)¶
Pokud admin UI / launcher není dostupný, nebo jeden z automatických kroků selže, postup přes SSH + curl:
Diagnostika: kde to padá?¶
# 1. Apps-gateway běží?
curl -sS http://127.0.0.1:8100/health
# → {"status":"ok","version":"0.1.0"}
# 2. App row v DB?
sudo docker exec avax-postgres psql -U avaxis -d avaxis_dev \
-c "SELECT slug, gateway_enabled, is_public, container_port, health_status \
FROM apps WHERE slug='<slug>';"
# 3. Backend kontejner běží?
sudo docker ps --filter "name=avax-app-<slug>" \
--format '{{.Names}}\t{{.Status}}\t{{.Ports}}'
# 4. Routing přes nginx (s Host headerem)
curl -H 'Host: api.avaxis.cz' http://127.0.0.1/apps/<slug>/health
# Bez Host headeru z LAN nefunguje — viz reference_avaxdev_infra_gotchas
# v session memory (nginx default_server priorita).
Ruční flip gateway_enabled (když UI checkbox nefunguje)¶
sudo docker exec avax-postgres psql -U avaxis -d avaxis_dev -c \
"UPDATE apps SET gateway_enabled=true, is_public=true, \
health_status='unknown', last_health_error=NULL \
WHERE slug='<slug>';"
# Trigger apps-gateway cache refresh (pubsub fallback)
curl -X POST http://127.0.0.1:8100/admin/refresh
Ruční vypnutí gateway_enabled¶
sudo docker exec avax-postgres psql -U avaxis -d avaxis_dev -c \
"UPDATE apps SET gateway_enabled=false WHERE slug='<slug>';"
curl -X POST http://127.0.0.1:8100/admin/refresh
Ruční probe (když background task nefungoval)¶
Backend by měl probe spustit automaticky po gateway flip, ale pokud
worker padl uprostřed nebo restart:
# Z avaxdev — přímo přes apps-gateway loopback
curl -sS http://127.0.0.1:8100/<slug>/health
# DB ručně sladit (status="ok" pokud výše vrátilo 200)
sudo docker exec avax-postgres psql -U avaxis -d avaxis_dev -c \
"UPDATE apps SET health_status='ok', last_health_check_at=now(), \
last_health_error=NULL \
WHERE slug='<slug>';"
Ruční vytvoření app row (když create_app endpoint selhal)¶
Krajní případ — backend nezvládl vytvořit, ale Gitea repo a S3 bucket už existují. Insert do DB ručně:
sudo docker exec avax-postgres psql -U avaxis -d avaxis_dev <<'SQL'
INSERT INTO apps (
id, slug, name, description, category, publisher_id, vendor_company_id,
visibility, is_active, is_public, distribution_bucket,
backend_mount, gitea_repo_url, container_port, gateway_enabled,
container_host, health_path, health_status, docs_slug,
created_at, updated_at
) VALUES (
gen_random_uuid(), '<slug>', '<Display name>', '<Description>', NULL,
'<publisher company UUID>', '<vendor company UUID>',
'public', true, false, 'app-<slug>',
true, 'https://git.avaxis.cz/avax-apps/<slug>-app',
8104, -- první volný port v range 8101-8199
false, 'localhost', '/health', 'unknown', '<slug>',
now(), now()
);
SQL
Port volný najít:
SELECT container_port FROM apps WHERE container_port IS NOT NULL ORDER BY container_port;
-- Vybrat první volný v range 8101-8199 nepoužitý.
Ruční Gitea repo + secrets (když backend selhal)¶
Backend create_app má best-effort try/except — pokud Gitea API timeoutuje,
repo se nevytvoří ale DB row ano. Manuálně:
# 1. Vytvořit repo přes Gitea API (token: admin paincelebrator)
curl -X POST https://git.avaxis.cz/api/v1/orgs/avax-apps/repos \
-H "Authorization: token $GITEA_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"<slug>-app","description":"<desc>","private":true,
"auto_init":false,"default_branch":"main"}'
# 2. Inject APPDIST_S3_* secrets do repa
for secret in APPDIST_S3_ENDPOINT APPDIST_S3_ACCESS_KEY APPDIST_S3_SECRET_KEY APPDIST_S3_REGION; do
VAL=$(sudo grep "^$secret=" /etc/avax/.env | cut -d= -f2-)
curl -X PUT "https://git.avaxis.cz/api/v1/repos/avax-apps/<slug>-app/actions/secrets/$secret" \
-H "Authorization: token $GITEA_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"data\":\"$VAL\"}"
done
# 3. Push template skeleton — viz tools/avax-app-template/
Ruční S3 bucket (když Ceph create_bucket selhal)¶
# Na avaxdev:
set -a && source <(sudo cat /etc/avax/.env) && set +a
aws --endpoint-url "$APPDIST_S3_ENDPOINT" s3 mb "s3://app-<slug>"
# Public-read policy pro channels/* + version-manifest + files
cat > /tmp/bucket-policy.json <<'EOF'
{"Version":"2012-10-17","Statement":[{
"Sid":"PublicReadDistribution","Effect":"Allow","Principal":"*",
"Action":"s3:GetObject",
"Resource":["arn:aws:s3:::app-<slug>/channels/*",
"arn:aws:s3:::app-<slug>/versions/*/version-manifest.json",
"arn:aws:s3:::app-<slug>/versions/*/files/*"]
}]}
EOF
aws --endpoint-url "$APPDIST_S3_ENDPOINT" s3api put-bucket-policy \
--bucket "app-<slug>" --policy file:///tmp/bucket-policy.json
Související¶
- Spec:
spec/admin-app-onboarding.md - Spec apps-gateway:
spec/apps-gateway.md - Spec per-app kontejner:
spec/per-app-container.md - Spec vendor onboarding:
spec/vendor-onboarding.md - Reference: avaxdev gotchas (nginx default_server, dual-PG, APPDIST creds
v
/etc/avax/.envroot-only) — v session memory