Skip to content

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:

KomponentaCo to jeKde se buildí
atrea-user-apiAPI (/api) + Swagger (/api/docs) + docs (/docs). Panel NENÍ uvnitř.deploy.sh na DEV → push do hub.atrea.name
atrea-user-panelAdmin panel (Vue SPA), servírovaný statickybuild.sh přímo na serveru
atrea-zitadel-loginZitadel Login v2 UI (Next.js)image z hub.atrea.name
atrea-zitadelZitadel server (OIDC/SAML IdP)oficiální image ghcr.io/zitadel/zitadel
atrea-postgresJeden PostgreSQL se dvěma databázemi: atrea-user-db + zitadelpostgres:16-alpine

Klíčové principy:

  • Image je env-agnostický. Tentýž atrea-user-api image 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énaCíl
zitadel.auth.amotion.cloudZitadel server (issuer / mgmt API / konzole)
auth.amotion.cloudLogin v2 UI
api.auth.amotion.cloudAPI /api + Swagger /api/docs + docs /docs
admin.auth.amotion.cloudAdmin panel (static)
test.admin.auth.amotion.cloudAdmin panel — test-production build (test FE proti ostrému prod backendu)

Test (kagb.cloud)

DoménaCíl
admin.kagb.cloudZitadel server
login.kagb.cloudLogin v2 UI
api.user.kagb.cloudAPI + Swagger + docs
panel.kagb.cloudAdmin 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á na config/default.yaml
  • Panel pro lokální vývoj: npm run dev v repu atrea-user-panel (Vite na :5173, proxy /apilocalhost: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.sh

Co deploy.sh dělá:

  • vyžaduje čistý git tree;
  • docker buildx cross-build pro linux/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 (na main);
  • 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 dotazu

Tři módy a jejich výstup (verzovaný adresář + symlink latest):

MódEnv souborVýstupDoménaBackend
production.env.productionrelease/latestadmin.auth.amotion.cloudprod API + prod Zitadel
test.env.testrelease-test/latestpanel.kagb.cloudtest API + test Zitadel (kagb)
test-production.env.test-productionrelease-test-production/latesttest.admin.auth.amotion.cloudprod 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 -d

Test

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 -d

NODE_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ík app).
  • zitadel — Zitadel si ji vytvoří sám při prvním startu (app je instance admin, vyrobí DB + runtime usera zitadel).

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>.sql

init.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>.sql

Konfigurace 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_PASSWORDheslo DB app (user-api + Zitadel admin)
ZITADEL_DB_PASSWORDheslo Zitadel runtime usera
ZITADEL_MASTERKEYklíč, kterým Zitadel šifruje secrety v DB (32 znaků)
ZITADEL_ADMIN_USER / _PASSWORDprvní admin Zitadelu (bootstrap)
ZITADEL_SERVICE_ACCOUNT_TOKENPAT service účtu, kterým API volá Zitadel
ZITADEL_WEBHOOK_SECRETověření příchozích Zitadel Action callů
INTERNAL_API_KEYsdílený klíč pro interní service-to-service endpointy
BRAND_SMTP_KEYAES 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 version bump (git tag vX.Y.Z)
  • [ ] čistý git tree
  • [ ] ./deploy.sh → image v hubu (:vX.Y.Z + :latest)

Panel (server):

  • [ ] .env.production / .env.test má správný VITE_API_BASE_URL
  • [ ] produkční VITE_ZITADEL_CLIENT_ID + VITE_ZITADEL_ORG_* doplněné
  • [ ] ./build.shrelease(-test)/latest
  • [ ] Caddy servíruje z latest symlinku

Stack (server):

  • [ ] .env.production / .env.test se secrety (žádné defaulty change-me-*)
  • [ ] ZITADEL_MASTERKEY nastaven (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

Atrea User API — interní dokumentace