first commit
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# Deploy (build/lokal): SiCABE Control Panel
|
||||
|
||||
> Untuk deploy PRODUKSI dari image registry (menyatu dengan gateway: docker-proxy +
|
||||
> config-agent + nginx, dengan profile), pakai **`deploy/stack/`**. Compose di sini
|
||||
> untuk **build lokal** dan menjalankan panel sendirian.
|
||||
|
||||
Panel (Next.js) dijalankan sebagai container. Image produksi memakai
|
||||
**Next.js standalone** + user non-root (`nextjs`, uid 1001).
|
||||
|
||||
> Gateway **per host** (`deploy/host-gateway/`) adalah stack terpisah — sudah punya
|
||||
> compose sendiri. Panel hanya perlu menunjuk ke gateway itu lewat `SICABE_HOSTS`.
|
||||
|
||||
## 1. Build image
|
||||
|
||||
```bash
|
||||
./scripts/build-image.sh # tag default: sicabe/control-panel:<git-sha> + :latest
|
||||
./scripts/build-image.sh --tag sicabe/control-panel:1.0.0
|
||||
./scripts/build-image.sh --push --registry registry.example.com/sicabe
|
||||
./scripts/build-image.sh --no-cache --platform linux/amd64
|
||||
```
|
||||
|
||||
Script memverifikasi Dockerfile/`public/`, menandai `:latest` + `<sha>`, dan
|
||||
mencetak ukuran image.
|
||||
|
||||
## 2. Siapkan env
|
||||
|
||||
```bash
|
||||
cd deploy/panel
|
||||
cp env.example .env # lalu isi NEXTAUTH_SECRET, api key gateway, dll.
|
||||
# NEXTAUTH_SECRET: openssl rand -base64 32
|
||||
```
|
||||
|
||||
**Penting:** panel di container **tidak bisa membaca filesystem platform** → tiap
|
||||
host di `SICABE_HOSTS` **wajib** punya `configUrl` (config-agent). Karena itu
|
||||
**tidak perlu** mount folder platform: katalog Trino, project dbt, dokumen OPA,
|
||||
`.env` platform, dan CA Trino semuanya dibaca lewat agent (HTTP). Env
|
||||
`TRINO_CATALOG_DIR` / `DBT_PROJECT_DIR` / `OPA_DATA_FILE` / `SICABE_ENV_FILE` /
|
||||
`TRINO_CA_FILE` hanya dipakai `LocalConfigStore` (dev/single-host tanpa agent) —
|
||||
jangan diandalkan di container.
|
||||
|
||||
## 3. Jalankan
|
||||
|
||||
```bash
|
||||
cd deploy/panel
|
||||
docker compose up -d # pakai image hasil build
|
||||
# docker compose up -d --build # sekaligus build dari source
|
||||
docker compose logs -f panel
|
||||
```
|
||||
|
||||
Buka `http://localhost:3000` (atau `PANEL_PORT`).
|
||||
|
||||
## Yang persisten
|
||||
|
||||
| Data | Lokasi |
|
||||
| --- | --- |
|
||||
| Config panel (hosts/modules/services/service types) | volume `panel-data` → `/app/data/config.json` |
|
||||
| Monitored state | volume `panel-data` → `/app/data/state.json` |
|
||||
|
||||
Backup/pindah config lewat **Settings → Backup** (Export/Import) — tanpa
|
||||
menyentuh volume. Untuk migrasi dari deployment host lama: Export di yang lama →
|
||||
Import di yang baru.
|
||||
|
||||
## Catatan jaringan & TLS
|
||||
|
||||
- **Default compose = `network_mode: host`.** Gateway host
|
||||
(`deploy/host-gateway`) hanya membuka `127.0.0.1:22375` (aman), sehingga panel
|
||||
di **bridge network tidak bisa** menjangkaunya lewat `host.docker.internal`.
|
||||
Terverifikasi: dari bridge, Keycloak (`0.0.0.0:12080`) **bisa**, gateway
|
||||
(`127.0.0.1:22375`) **gagal**; dari host network keduanya **bisa**. Host network
|
||||
juga membuat `127.0.0.1` & SAN sertifikat Trino (`localhost`) cocok.
|
||||
Port ditentukan `PORT` (default 3000), bukan `ports:`.
|
||||
- **Varian bridge** (bila gateway dibuka ke alamat non-loopback): lihat komentar
|
||||
di `docker-compose.yml` — hapus `network_mode: host`, tambah `ports:` +
|
||||
`extra_hosts: host.docker.internal`.
|
||||
- **TLS Trino**: sertifikat self-signed Trino hanya mencakup SAN
|
||||
`localhost / trino / sicabe-trino / trino-coordinator / 127.0.0.1`.
|
||||
`host.docker.internal` **tidak** termasuk → verifikasi TLS gagal di bridge.
|
||||
- CA Trino **tidak perlu** file lokal bila host punya `configUrl` (agent `/ca`).
|
||||
|
||||
## Login di produksi = SSO (Keycloak)
|
||||
|
||||
Container berjalan `NODE_ENV=production`, dan **login kredensial dev dinonaktifkan
|
||||
di produksi** (hanya provider `keycloak` yang aktif — cek
|
||||
`GET /api/auth/providers`). Artinya:
|
||||
|
||||
- Login lewat tombol **Sign in with Keycloak** di browser (bukan form dev).
|
||||
- **`NEXTAUTH_URL` harus sama dengan URL publik panel**, dan panel Keycloak
|
||||
(`scripts/create-keycloak-client.sh`, `APP_URL`) harus punya redirect URI
|
||||
`${NEXTAUTH_URL}/api/auth/callback/keycloak`. Kalau panel disajikan di port
|
||||
selain 3000, jalankan ulang script dengan `APP_URL=http://<host>:<port>`.
|
||||
- Image **gagal-cepat** bila `NEXTAUTH_SECRET` atau `KEYCLOAK_CLIENT_SECRET`
|
||||
kosong (memang disengaja) — panel menolak start dengan pesan jelas.
|
||||
|
||||
## Update
|
||||
|
||||
```bash
|
||||
./scripts/build-image.sh --tag sicabe/control-panel:1.1.0
|
||||
PANEL_TAG=1.1.0 docker compose up -d # dari deploy/panel
|
||||
```
|
||||
|
||||
## Healthcheck
|
||||
|
||||
Image menyertakan `HEALTHCHECK` (`GET /api/auth/session` → 200 walau belum login),
|
||||
jadi `docker compose ps` menampilkan status `healthy`.
|
||||
@@ -0,0 +1,61 @@
|
||||
# =============================================================================
|
||||
# sicabe-control-panel — deploy panel (Next.js) via Docker Compose.
|
||||
#
|
||||
# Build image dulu: ../../scripts/build-image.sh
|
||||
# Lalu jalankan : docker compose up -d
|
||||
#
|
||||
# Persisten: volume bernama `panel-data` → `data/config.json` (hosts/modules/
|
||||
# services/service types) + `data/state.json`. Backup/restore dari UI
|
||||
# (Settings → Backup) tanpa menyentuh volume.
|
||||
#
|
||||
# PENTING: panel di container TIDAK bisa membaca filesystem platform → setiap
|
||||
# host di SICABE_HOSTS WAJIB punya `configUrl` (config-agent).
|
||||
#
|
||||
# NETWORK: default `network_mode: host` karena gateway host
|
||||
# (deploy/host-gateway) membuka `127.0.0.1:22375` — container di bridge TIDAK
|
||||
# bisa menjangkaunya via host.docker.internal. Dengan host network, `127.0.0.1`
|
||||
# berfungsi seperti di host (dan SAN sertifikat Trino `localhost` cocok).
|
||||
# Lihat README.md untuk varian bridge.
|
||||
# =============================================================================
|
||||
|
||||
name: sicabe-control-panel
|
||||
|
||||
services:
|
||||
panel:
|
||||
image: sicabe/control-panel:${PANEL_TAG:-latest}
|
||||
# Biarkan `build` aktif bila ingin `docker compose up --build`.
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: Dockerfile
|
||||
container_name: sicabe-control-panel
|
||||
network_mode: host
|
||||
# `.env` dibuat dari env.example (cp env.example .env). `required: false`
|
||||
# agar `docker compose config` tetap valid sebelum file dibuat.
|
||||
env_file:
|
||||
- path: .env
|
||||
required: false
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
HOSTNAME: "0.0.0.0"
|
||||
# Host network: port binding ditentukan PORT (bukan `ports:`).
|
||||
PORT: "${PANEL_PORT:-3000}"
|
||||
volumes:
|
||||
- panel-data:/app/data
|
||||
restart: unless-stopped
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
# ── Varian BRIDGE (bila gateway dibuka ke alamat non-loopback) ────────────
|
||||
# Hapus `network_mode: host` di atas, lalu tambahkan:
|
||||
# ports:
|
||||
# - "${PANEL_PORT:-3000}:3000"
|
||||
# extra_hosts:
|
||||
# - "host.docker.internal:host-gateway"
|
||||
# dan set SICABE_HOSTS/URL memakai host.docker.internal (perhatikan SAN TLS
|
||||
# Trino — host.docker.internal TIDAK ada di SAN).
|
||||
|
||||
volumes:
|
||||
panel-data:
|
||||
@@ -0,0 +1,70 @@
|
||||
# =============================================================================
|
||||
# Env untuk panel yang berjalan sebagai CONTAINER.
|
||||
# Salin ke .env LALU ISI NILAINYA (jangan commit .env):
|
||||
# cp deploy/panel/env.example deploy/panel/.env
|
||||
#
|
||||
# Beda penting dari .env dev (panel di host):
|
||||
# - Panel di container TIDAK bisa membaca filesystem platform → WAJIB pakai
|
||||
# config-agent (`configUrl`) di SICABE_HOSTS.
|
||||
# - Alamat ke service di HOST memakai `host.docker.internal` (atau
|
||||
# `network_mode: host`, lihat docker-compose.yml).
|
||||
# =============================================================================
|
||||
|
||||
# ── Wajib ────────────────────────────────────────────────────────────────────
|
||||
# URL publik panel — HARUS sama dengan yang diakses browser.
|
||||
NEXTAUTH_URL=http://localhost:3000
|
||||
# Rahasia NextAuth (WAJIB di produksi). Buat: openssl rand -base64 32
|
||||
NEXTAUTH_SECRET=
|
||||
|
||||
# ── Login lokal (hybrid dengan SSO) — OPSIONAL ───────────────────────────────
|
||||
#PANEL_LOCAL_USER=admin
|
||||
#PANEL_LOCAL_PASSWORD_HASH=$2b$10$...
|
||||
#PANEL_LOCAL_PASSWORD_HASH_B64=
|
||||
#PANEL_LOCAL_ROLE=data-admin
|
||||
#TRINO_SERVICE_ACCOUNT=svc_dbt
|
||||
|
||||
# ── Keycloak (SSO & login dev ROPC) ──────────────────────────────────────────
|
||||
# Dari container, Keycloak di host diakses via host.docker.internal.
|
||||
KEYCLOAK_URL=http://host.docker.internal:12080
|
||||
KEYCLOAK_CLIENT_ID=sicabe-control-panel
|
||||
KEYCLOAK_CLIENT_SECRET=dev-keycloak-secret
|
||||
# URL yang dilihat browser (tautan Keycloak).
|
||||
KEYCLOAK_WEB_URL=http://localhost:12080
|
||||
#KEYCLOAK_REALM=sicabe
|
||||
|
||||
# ── Host/agent yang dikelola (WAJIB configUrl) ───────────────────────────────
|
||||
# Gateway per host (nginx: docker-proxy + config-agent) jalan di HOST:22375.
|
||||
# Dari container → host.docker.internal:22375. `publicHost` = alamat yang
|
||||
# dilihat BROWSER (untuk tautan UI), mis. IP LAN host.
|
||||
SICABE_HOSTS='[{"name":"local-gw","proxyUrl":"http://host.docker.internal:22375","apiKey":"<gateway-key>","configUrl":"http://host.docker.internal:22375","configApiKey":"<gateway-key>","publicHost":"localhost","enabled":true}]'
|
||||
|
||||
# ── Service (fallback; registry hasil scan diutamakan) ───────────────────────
|
||||
# CATATAN TLS Trino: sertifikat Trino (self-signed) punya SAN
|
||||
# `localhost / trino / sicabe-trino / trino-coordinator / 127.0.0.1`. Dari
|
||||
# container, `host.docker.internal` TIDAK ada di SAN → verifikasi TLS gagal.
|
||||
# Pilihan:
|
||||
# (a) pakai `network_mode: host` (lihat docker-compose.yml) → 127.0.0.1 cocok;
|
||||
# (b) tambah alias di extra_hosts yang ADA di SAN (mis. `sicabe-trino`), lalu
|
||||
# set TRINO_URL=https://sicabe-trino:12443
|
||||
TRINO_URL=https://host.docker.internal:12443
|
||||
TRINO_WEB_URL=http://localhost:12443
|
||||
# CA diambil otomatis via config-agent (`/ca`) → tak perlu file lokal.
|
||||
|
||||
NESSIE_URL=http://host.docker.internal:12120
|
||||
|
||||
AIRFLOW_URL=http://host.docker.internal:12082
|
||||
STARROCKS_HOST=host.docker.internal
|
||||
STARROCKS_PORT=12930
|
||||
STARROCKS_WEB_URL=http://localhost:12030
|
||||
|
||||
OPENMETADATA_URL=http://host.docker.internal:12085
|
||||
GRAFANA_URL=http://host.docker.internal:12300
|
||||
MINIO_CONSOLE_URL=http://localhost:12901
|
||||
|
||||
# Dremio (bila ada)
|
||||
#DREMIO_URL=http://host.docker.internal:12947
|
||||
|
||||
# ── Runtime state (di dalam volume panel-data) ───────────────────────────────
|
||||
SICABE_CONFIG_FILE=data/config.json
|
||||
SICABE_STATE_FILE=data/state.json
|
||||
SICABE_COMPOSE_PROJECTS=sicabe
|
||||
Reference in New Issue
Block a user