Tmavý režim
Nasazení
Tahle stránka popisuje, jak se projekt staví a nasazuje — lokálně, na test a na produkci.
Přehled architektury
Systém se skládá ze čtyř kontejnerů + jednoho samostatného static buildu:
| Komponenta | Co to je | Kde se buildí |
|---|---|---|
| atrea-user-api | API (/api) + Swagger (/api/docs) + docs (/docs). Panel NENÍ uvnitř. | deploy.sh na DEV → push do hub.atrea.name |
| atrea-user-panel | Admin panel (Vue SPA), servírovaný staticky | build.sh přímo na serveru |
| atrea-zitadel-login | Zitadel Login v2 UI (Next.js) | image z hub.atrea.name |
| atrea-zitadel | Zitadel server (OIDC/SAML IdP) | oficiální image ghcr.io/zitadel/zitadel |
| atrea-postgres | Jeden PostgreSQL se dvěma databázemi: atrea-user-db + zitadel | postgres:16-alpine |
Klíčové principy:
- Image je env-agnostický. Tentýž
atrea-user-apiimage běží na prod i testu — prostředí vybíráNODE_ENV(→config/production.yaml/config/test.yaml). - Panel se vydává samostatně (často, nezávisle na API), buduje se na serveru z repa
atrea-user-panel. - Panel ↔ API jsou cross-origin (každý na své doméně). CORS je v API otevřený, takže to funguje bez whitelistu.
- TLS terminuje Caddy na proxy serveru; kontejnery jedou v HTTP.
Domény
Produkce (amotion.cloud)
| Doména | Cíl |
|---|---|
zitadel.auth.amotion.cloud | Zitadel server (issuer / mgmt API / konzole) |
auth.amotion.cloud | Login v2 UI |
api.auth.amotion.cloud | API /api + Swagger /api/docs + docs /docs |
admin.auth.amotion.cloud | Admin panel (static) |
test.admin.auth.amotion.cloud | Admin panel — test-production build (test FE proti ostrému prod backendu) |
Test (kagb.cloud)
| Doména | Cíl |
|---|---|
admin.kagb.cloud | Zitadel server |
login.kagb.cloud | Login v2 UI |
api.user.kagb.cloud | API + Swagger + docs |
panel.kagb.cloud | Admin panel (static) |
1) Lokální vývoj
docker-compose.yml postaví celý stack lokálně z buildů (ne z hubu) — vlastní postgres (app/app, auto-init z sql/), API, panel i login s build kontexty.
bash
./build.sh # git pull 3 repa + docker compose up --build- API:
localhost:3001, Postgres:localhost:5434, Zitadel:localhost:3000/8080 NODE_ENV=development→ padá naconfig/default.yaml- Panel pro lokální vývoj:
npm run devv repuatrea-user-panel(Vite na:5173, proxy/api→localhost:3001)
2) API image — build & push (DEV stroj)
API image se staví a pushuje skriptem deploy.sh na vývojářském stroji:
bash
# 1) bump verze (vytvoří git tag vX.Y.Z)
npm version patch # nebo minor / major
# 2) build + push do hub.atrea.name
./deploy.shCo deploy.sh dělá:
- vyžaduje čistý git tree;
docker buildxcross-build prolinux/amd64(servery jsou x86_64 — na Macu by jinak vznikl arm64 a spadl by „exec format error");- build + push v jednom kroku, tagy
:vX.Y.Z(z git tagu) a:latest(namain); - panel nebuildí (od oddělení panelu) — image obsahuje jen API + docs.
Přebít platformu jde přes PLATFORMS=… ./deploy.sh.
3) Panel — build na serveru
Panel se buduje přímo na serveru z repa atrea-user-panel skriptem build.sh. Je to per-env build (build:production / build:test / build:test-production) — build-time hodnoty se berou z příslušného .env.<mode> (hlavně VITE_API_BASE_URL + Zitadel clientId/orgs).
bash
cd /opt/apps/atrea-user-panel
./build.sh # nabídne: 1) production 2) test 3) test-production
./build.sh -q # production bez dotazuTři módy a jejich výstup (verzovaný adresář + symlink latest):
| Mód | Env soubor | Výstup | Doména | Backend |
|---|---|---|---|---|
| production | .env.production | release/latest | admin.auth.amotion.cloud | prod API + prod Zitadel |
| test | .env.test | release-test/latest | panel.kagb.cloud | test API + test Zitadel (kagb) |
| test-production | .env.test-production | release-test-production/latest | test.admin.auth.amotion.cloud | prod API + prod Zitadel |
test-production
Slouží k testování změn pouze ve frontendu proti ostrému produkčnímu backendu. Je shodný s production, liší se jen redirect/logout URI (míří na test.admin.auth.amotion.cloud) — ta URI musí být povolená v produkční Zitadel aplikaci (Redirect URIs), jinak login selže.
Caddy pak servíruje statiku z latest symlinku:
caddyfile
admin.auth.amotion.cloud {
root * /opt/apps/atrea-user-panel/release/latest
try_files {path} /index.html # SPA fallback
file_server
}
panel.kagb.cloud {
root * /opt/apps/atrea-user-panel/release-test/latest
try_files {path} /index.html
file_server
}
test.admin.auth.amotion.cloud {
root * /opt/apps/atrea-user-panel/release-test-production/latest
try_files {path} /index.html
file_server
}Produkční client ID
Protože panel nemá runtime config, Zitadel clientId a org IDs se zapékají při buildu z panelového .env.production (VITE_ZITADEL_CLIENT_ID, VITE_ZITADEL_ORG_*). Pro produkční (amotion) Zitadel instanci je doplň před produkčním buildem panelu, jinak se nepřihlásí. Na testu (kagb) jsou hodnoty známé.
4) Stack na serveru — pull & up
Images (atrea-user-api, atrea-zitadel-login) se na server jen tahají z hubu, nebuildí se tam.
Produkce
Nasazuje se přes ansible (volá docker compose), nebo ručně:
bash
docker compose -f docker-compose.production.yml --env-file .env.production pull
docker compose -f docker-compose.production.yml --env-file .env.production up -dTest
bash
docker compose -f docker-compose.test.yml --env-file .env.test pull
docker compose -f docker-compose.test.yml --env-file .env.test up -dNODE_ENV (production / test) je v compose souboru a vybere config/*.yaml. Hesla a secrety jdou z .env.production / .env.test (gitignored).
Databáze
Jeden postgres (atrea-postgres) drží dvě databáze:
atrea-user-db— user-api (vlastníkapp).zitadel— Zitadel si ji vytvoří sám při prvním startu (appje instance admin, vyrobí DB + runtime userazitadel).
Schéma a seed user-api se aplikují ručně po prvním startu (server nemá repo se sql/):
bash
docker exec -i atrea-postgres psql -U app -d atrea-user-db < sql/init.sql
docker exec -i atrea-postgres psql -U app -d atrea-user-db < sql/data.sql
# Pak doženi pending migrace, které ještě nejsou v init.sql:
docker exec -i atrea-postgres psql -U app -d atrea-user-db < sql/migrations/<soubor>.sqlinit.sql vs migrace
sql/init.sql nemusí být plně synchronní s nejnovějšími migracemi v sql/migrations/. Po init.sql + data.sql vždy dožeň migrace, které vznikly později, jinak schéma nebude sedět s kódem.
Spuštění migrace na běžícím prostředí:
bash
docker exec -i atrea-postgres psql -U app -d atrea-user-db < sql/migrations/<soubor>.sqlKonfigurace prostředí
Hierarchie configu (node-config):
config/default.yaml— společné defaulty (+ dev).config/test.yaml(NODE_ENV=test) /config/production.yaml(NODE_ENV=production).config/custom-environment-variables.yaml— mapuje secrety na env proměnné.
Secrety se nikdy necommitují — jdou přes .env.production / .env.test:
| Proměnná | Význam |
|---|---|
POSTGRES_PASSWORD | heslo DB app (user-api + Zitadel admin) |
ZITADEL_DB_PASSWORD | heslo Zitadel runtime usera |
ZITADEL_MASTERKEY | klíč, kterým Zitadel šifruje secrety v DB (32 znaků) |
ZITADEL_ADMIN_USER / _PASSWORD | první admin Zitadelu (bootstrap) |
ZITADEL_SERVICE_ACCOUNT_TOKEN | PAT service účtu, kterým API volá Zitadel |
ZITADEL_WEBHOOK_SECRET | ověření příchozích Zitadel Action callů |
INTERNAL_API_KEY | sdílený klíč pro interní service-to-service endpointy |
BRAND_SMTP_KEY | AES klíč pro šifrování per-brand SMTP hesel v DB |
EMAIL_SMTP_* | globální SMTP fallback (když brand nemá vlastní) |
Health check
bash
curl https://api.auth.amotion.cloud/api/health # { status, version, uptime }
curl https://api.auth.amotion.cloud/api/version # { version, gitSha, buildMode }Kontejner app má i Docker healthcheck na /api/health.
Checklist před nasazením
API image (DEV):
- [ ]
npm versionbump (git tagvX.Y.Z) - [ ] čistý git tree
- [ ]
./deploy.sh→ image v hubu (:vX.Y.Z+:latest)
Panel (server):
- [ ]
.env.production/.env.testmá správnýVITE_API_BASE_URL - [ ] produkční
VITE_ZITADEL_CLIENT_ID+VITE_ZITADEL_ORG_*doplněné - [ ]
./build.sh→release(-test)/latest - [ ] Caddy servíruje z
latestsymlinku
Stack (server):
- [ ]
.env.production/.env.testse secrety (žádné defaultychange-me-*) - [ ]
ZITADEL_MASTERKEYnastaven (a při migraci DB sedí se starým) - [ ]
docker compose … pull && up -d - [ ] DB inicializována (
init.sql+data.sql+ pending migrace) - [ ] Caddy: 4 domény (zitadel / login / api / panel)
- [ ] SSL certifikáty platné
- [ ] Zálohování DB nastaveno