feat(velxio): modular standalone orchestration & dynamic tailscale config
- Tambah podman-compose.velxio.yml untuk deployment Velxio standalone - Tambah command elemes.sh (velxio-run, velxio-runbuild, velxio-stop, velxio-status) - Template lms-tail.json.template dengan auto-generation via elemes.sh berdasarkan VELXIO_MODE - Dukungan VELXIO_COMPILER_URL dinamis pada compose utama
This commit is contained in:
parent
186161ac96
commit
77028e58ff
12
.env.example
12
.env.example
|
|
@ -21,6 +21,18 @@ COMPILER_WORKER_URL=http://compiler-worker:8080/execute
|
||||||
ELEMES_HOST=sinau-c-hostname-kamu
|
ELEMES_HOST=sinau-c-hostname-kamu
|
||||||
TS_AUTHKEY=tskey-auth-xxxx
|
TS_AUTHKEY=tskey-auth-xxxx
|
||||||
|
|
||||||
|
# ── Velxio Modular Deployment (opsional) ───────
|
||||||
|
# Mode operasi Velxio: 'local' (bundled dalam compose) atau 'remote' (terpisah)
|
||||||
|
VELXIO_MODE=local
|
||||||
|
# URL compiler Velxio (hanya perlu di-set saat VELXIO_MODE=remote)
|
||||||
|
# Default local: http://127.0.0.1:80/api/compile/
|
||||||
|
# Contoh remote via MagicDNS: http://velxio-dev:80/api/compile/
|
||||||
|
#VELXIO_COMPILER_URL=
|
||||||
|
# Hostname Tailscale untuk standalone Velxio node (dipakai di mesin Velxio & Elemes)
|
||||||
|
VELXIO_HOST=velxio-dev
|
||||||
|
# Auth key Tailscale terpisah untuk standalone Velxio node (di mesin Velxio)
|
||||||
|
VELXIO_TS_AUTHKEY=
|
||||||
|
|
||||||
# ── Flask (opsional: untuk dev mode lokal) ─────
|
# ── Flask (opsional: untuk dev mode lokal) ─────
|
||||||
FLASK_DEBUG=false
|
FLASK_DEBUG=false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,4 @@ velxio-deployer-firmware/build
|
||||||
velxio-deployer-firmware/managed_components/
|
velxio-deployer-firmware/managed_components/
|
||||||
lms-c-precompiled.tar
|
lms-c-precompiled.tar
|
||||||
.browser-test/
|
.browser-test/
|
||||||
|
config/lms-tail.json
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
"Proxy": "http://127.0.0.1:5000/velxio-compile"
|
"Proxy": "http://127.0.0.1:5000/velxio-compile"
|
||||||
},
|
},
|
||||||
"/velxio/": {
|
"/velxio/": {
|
||||||
"Proxy": "http://127.0.0.1:80/"
|
"Proxy": "__VELXIO_PROXY_TARGET__"
|
||||||
},
|
},
|
||||||
"/flowchart/": {
|
"/flowchart/": {
|
||||||
"Proxy": "http://127.0.0.1:8081/"
|
"Proxy": "http://127.0.0.1:8081/"
|
||||||
173
elemes.sh
173
elemes.sh
|
|
@ -62,6 +62,70 @@ compose_restart() {
|
||||||
run_compose_out restart "$@"
|
run_compose_out restart "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Helper untuk membaca nilai konfigurasi dari .env tanpa source
|
||||||
|
env_val() {
|
||||||
|
grep -m1 "^${1}=" "$PARENT_DIR/.env" 2>/dev/null | cut -d= -f2-
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Velxio standalone compose helpers ────────────────────────
|
||||||
|
VELXIO_PROJECT="${PROJECT_NAME}-velxio"
|
||||||
|
|
||||||
|
run_velxio_compose() {
|
||||||
|
cd "$SCRIPT_DIR" || exit
|
||||||
|
if [ "$VERBOSE" -eq 1 ]; then
|
||||||
|
podman-compose -p "$VELXIO_PROJECT" -f podman-compose.velxio.yml \
|
||||||
|
--env-file "$PARENT_DIR/.env" "$@"
|
||||||
|
else
|
||||||
|
podman-compose -p "$VELXIO_PROJECT" -f podman-compose.velxio.yml \
|
||||||
|
--env-file "$PARENT_DIR/.env" "$@" \
|
||||||
|
2> >(grep -v -E "$NOISE_RE" >&2)
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_velxio_compose_quiet() {
|
||||||
|
if [ "$VERBOSE" -eq 1 ]; then
|
||||||
|
run_velxio_compose "$@"
|
||||||
|
else
|
||||||
|
run_velxio_compose "$@" >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Daftar services elemes berdasarkan VELXIO_MODE.
|
||||||
|
# Return kosong = start all (local mode).
|
||||||
|
# Return daftar service = start hanya yang terdaftar (remote mode).
|
||||||
|
elemes_services() {
|
||||||
|
local mode
|
||||||
|
mode="$(env_val VELXIO_MODE)"
|
||||||
|
mode="${mode:-local}"
|
||||||
|
if [ "$mode" = "remote" ]; then
|
||||||
|
echo "elemes-ts postgres elemes compiler-worker elemes-frontend flowchart"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generate lms-tail.json dari template berdasarkan VELXIO_MODE.
|
||||||
|
# Dipanggil sebelum container start agar Tailscale Serve config up-to-date.
|
||||||
|
generate_ts_config() {
|
||||||
|
local template="$SCRIPT_DIR/config/lms-tail.json.template"
|
||||||
|
local output="$SCRIPT_DIR/config/lms-tail.json"
|
||||||
|
|
||||||
|
if [ ! -f "$template" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local mode
|
||||||
|
mode="$(env_val VELXIO_MODE)"
|
||||||
|
mode="${mode:-local}"
|
||||||
|
|
||||||
|
if [ "$mode" = "remote" ]; then
|
||||||
|
local velxio_host
|
||||||
|
velxio_host="$(env_val VELXIO_HOST)"
|
||||||
|
velxio_host="${velxio_host:-velxio-dev}"
|
||||||
|
sed "s|__VELXIO_PROXY_TARGET__|http://${velxio_host}:80/|g" "$template" > "$output"
|
||||||
|
else
|
||||||
|
sed 's|__VELXIO_PROXY_TARGET__|http://127.0.0.1:80/|g' "$template" > "$output"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# First-run/health DB: tunggu PostgreSQL, migrasi schema (idempotent), lalu
|
# First-run/health DB: tunggu PostgreSQL, migrasi schema (idempotent), lalu
|
||||||
# bootstrap akun guru otomatis bila TEACHER_TOKEN di .env tidak kosong.
|
# bootstrap akun guru otomatis bila TEACHER_TOKEN di .env tidak kosong.
|
||||||
db_init() {
|
db_init() {
|
||||||
|
|
@ -153,6 +217,16 @@ init)
|
||||||
echo "🔐 [Buat] Folder state/ (untuk Tailscale credentials & state)"
|
echo "🔐 [Buat] Folder state/ (untuk Tailscale credentials & state)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# state/velxio/ (untuk Tailscale credentials & state Velxio standalone)
|
||||||
|
if [ -d "$PARENT_DIR/state/velxio" ]; then
|
||||||
|
echo "✅ [Skip] Folder state/velxio/ sudah ada"
|
||||||
|
else
|
||||||
|
mkdir -p "$PARENT_DIR/state/velxio"
|
||||||
|
echo "🔐 [Buat] Folder state/velxio/ (untuk Tailscale Velxio standalone)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
generate_ts_config
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "🎯 Selesai! Langkah selanjutnya yang direkomendasikan:"
|
echo "🎯 Selesai! Langkah selanjutnya yang direkomendasikan:"
|
||||||
echo " 👉 1. Edit file ../.env sesuai dengan kebutuhan environment-mu"
|
echo " 👉 1. Edit file ../.env sesuai dengan kebutuhan environment-mu"
|
||||||
|
|
@ -181,7 +255,14 @@ runbuild)
|
||||||
;;&
|
;;&
|
||||||
runbuild | runclearbuild)
|
runbuild | runclearbuild)
|
||||||
echo "🚀 Menjalankan container di background..."
|
echo "🚀 Menjalankan container di background..."
|
||||||
run_compose up --force-recreate -d
|
generate_ts_config
|
||||||
|
SERVICES=$(elemes_services)
|
||||||
|
if [ -n "$SERVICES" ]; then
|
||||||
|
echo " ℹ️ VELXIO_MODE=remote → Velxio tidak dijalankan secara lokal"
|
||||||
|
run_compose up --force-recreate -d $SERVICES
|
||||||
|
else
|
||||||
|
run_compose up --force-recreate -d
|
||||||
|
fi
|
||||||
echo "✅ Elemes berhasil dijalankan!"
|
echo "✅ Elemes berhasil dijalankan!"
|
||||||
db_init
|
db_init
|
||||||
;;&
|
;;&
|
||||||
|
|
@ -206,7 +287,14 @@ runbuild | runclearbuild)
|
||||||
;;
|
;;
|
||||||
run)
|
run)
|
||||||
echo "🚀 Menjalankan container..."
|
echo "🚀 Menjalankan container..."
|
||||||
run_compose up -d
|
generate_ts_config
|
||||||
|
SERVICES=$(elemes_services)
|
||||||
|
if [ -n "$SERVICES" ]; then
|
||||||
|
echo " ℹ️ VELXIO_MODE=remote → Velxio tidak dijalankan secara lokal"
|
||||||
|
run_compose up -d $SERVICES
|
||||||
|
else
|
||||||
|
run_compose up -d
|
||||||
|
fi
|
||||||
echo "✅ Elemes berhasil dijalankan!"
|
echo "✅ Elemes berhasil dijalankan!"
|
||||||
db_init
|
db_init
|
||||||
;;
|
;;
|
||||||
|
|
@ -470,6 +558,81 @@ docs-validate)
|
||||||
compose_exec -w /app -e PYTHONPATH=services \
|
compose_exec -w /app -e PYTHONPATH=services \
|
||||||
elemes python scripts/validate_docs.py
|
elemes python scripts/validate_docs.py
|
||||||
;;
|
;;
|
||||||
|
velxio-stop | velxio-run | velxio-runbuild)
|
||||||
|
echo "🛑 Menghentikan Velxio standalone..."
|
||||||
|
run_velxio_compose_quiet down
|
||||||
|
;;&
|
||||||
|
velxio-stop)
|
||||||
|
echo "✅ Velxio standalone dihentikan."
|
||||||
|
;;
|
||||||
|
velxio-runbuild)
|
||||||
|
echo "🏗️ Membangun Velxio standalone image..."
|
||||||
|
run_velxio_compose build
|
||||||
|
;;&
|
||||||
|
velxio-run)
|
||||||
|
if ! podman image exists lms-velxio-standalone:latest 2>/dev/null; then
|
||||||
|
echo "⚠️ Image 'lms-velxio-standalone:latest' belum dibangun."
|
||||||
|
echo " Jalankan: ./elemes.sh velxio-runbuild"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
;;&
|
||||||
|
velxio-runbuild | velxio-run)
|
||||||
|
echo "🚀 Menjalankan Velxio standalone di background..."
|
||||||
|
run_velxio_compose up -d
|
||||||
|
echo "✅ Velxio standalone berhasil dijalankan!"
|
||||||
|
echo ""
|
||||||
|
VH="$(env_val VELXIO_HOST)"
|
||||||
|
VH="${VH:-velxio-dev}"
|
||||||
|
echo "📡 Velxio standalone info:"
|
||||||
|
echo " Tailscale hostname : $VH"
|
||||||
|
echo " Port internal : 80 (Nginx → FastAPI :8001)"
|
||||||
|
echo ""
|
||||||
|
echo "💡 Untuk menghubungkan Elemes ke Velxio ini, set di .env mesin Elemes:"
|
||||||
|
echo " VELXIO_MODE=remote"
|
||||||
|
echo " VELXIO_HOST=$VH"
|
||||||
|
echo " VELXIO_COMPILER_URL=http://$VH:80/api/compile/"
|
||||||
|
;;
|
||||||
|
velxio-status)
|
||||||
|
echo "📊 === Status Velxio ==="
|
||||||
|
MODE="$(env_val VELXIO_MODE)"
|
||||||
|
MODE="${MODE:-local}"
|
||||||
|
echo " Mode: $MODE"
|
||||||
|
|
||||||
|
if [ "$MODE" = "local" ]; then
|
||||||
|
echo " Velxio berjalan dalam compose utama (bundled)"
|
||||||
|
if podman ps --filter "label=io.podman.compose.project=$PROJECT_NAME" \
|
||||||
|
--filter "label=com.docker.compose.service=velxio" \
|
||||||
|
--format '{{.Names}} — {{.Status}}' 2>/dev/null | grep -q .; then
|
||||||
|
echo " ✅ Container:"
|
||||||
|
podman ps --filter "label=io.podman.compose.project=$PROJECT_NAME" \
|
||||||
|
--filter "label=com.docker.compose.service=velxio" \
|
||||||
|
--format ' {{.Names}} — {{.Status}}'
|
||||||
|
else
|
||||||
|
echo " ⚠️ Container: not running"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " Velxio berjalan terpisah (remote)"
|
||||||
|
VURL="$(env_val VELXIO_COMPILER_URL)"
|
||||||
|
echo " VELXIO_COMPILER_URL: ${VURL:-<belum diset>}"
|
||||||
|
if podman ps --filter "label=io.podman.compose.project=$VELXIO_PROJECT" \
|
||||||
|
--format '{{.Names}}' 2>/dev/null | grep -q .; then
|
||||||
|
echo " ✅ Standalone container (lokal):"
|
||||||
|
podman ps --filter "label=io.podman.compose.project=$VELXIO_PROJECT" \
|
||||||
|
--format ' {{.Names}} — {{.Status}}'
|
||||||
|
else
|
||||||
|
echo " ℹ️ Tidak ada standalone container lokal (Velxio berjalan di mesin remote)"
|
||||||
|
fi
|
||||||
|
if [ -n "$VURL" ]; then
|
||||||
|
HEALTH_URL=$(echo "$VURL" | sed 's|/api/compile.*|/health|')
|
||||||
|
echo -n " 🔍 Health check ($HEALTH_URL)... "
|
||||||
|
if curl -sf --max-time 5 "$HEALTH_URL" >/dev/null 2>&1; then
|
||||||
|
echo "✅ reachable"
|
||||||
|
else
|
||||||
|
echo "❌ unreachable"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
echo "💡 Cara Penggunaan elemes.sh:"
|
echo "💡 Cara Penggunaan elemes.sh:"
|
||||||
echo " ./elemes.sh init # Inisialisasi konfigurasi, folder, & template .env"
|
echo " ./elemes.sh init # Inisialisasi konfigurasi, folder, & template .env"
|
||||||
|
|
@ -493,6 +656,12 @@ docs-validate)
|
||||||
echo " ./elemes.sh test-worker # Compiler worker test suite"
|
echo " ./elemes.sh test-worker # Compiler worker test suite"
|
||||||
echo " ./elemes.sh docs-validate # Validasi frontmatter & broken link di docs/*.md"
|
echo " ./elemes.sh docs-validate # Validasi frontmatter & broken link di docs/*.md"
|
||||||
echo " ./elemes.sh loadtest # Menjalankan utilitas simulasi Load Test (Locust)"
|
echo " ./elemes.sh loadtest # Menjalankan utilitas simulasi Load Test (Locust)"
|
||||||
|
echo ""
|
||||||
|
echo "📡 Velxio Modular:"
|
||||||
|
echo " ./elemes.sh velxio-run # Jalankan Velxio standalone (reuse image)"
|
||||||
|
echo " ./elemes.sh velxio-runbuild # Build lalu jalankan Velxio standalone"
|
||||||
|
echo " ./elemes.sh velxio-stop # Hentikan Velxio standalone"
|
||||||
|
echo " ./elemes.sh velxio-status # Cek status & health Velxio (local/remote)"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
velxio-ts:
|
||||||
|
image: docker.io/tailscale/tailscale:latest
|
||||||
|
hostname: ${VELXIO_HOST:-velxio-dev}
|
||||||
|
environment:
|
||||||
|
- TS_AUTHKEY=${VELXIO_TS_AUTHKEY}
|
||||||
|
- TS_STATE_DIR=/var/lib/tailscale
|
||||||
|
- TS_USERSPACE=true
|
||||||
|
volumes:
|
||||||
|
- ../state/velxio:/var/lib/tailscale
|
||||||
|
- /dev/net/tun:/dev/net/tun
|
||||||
|
cap_add:
|
||||||
|
- net_admin
|
||||||
|
- sys_module
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
velxio:
|
||||||
|
image: lms-velxio-standalone:latest
|
||||||
|
build:
|
||||||
|
context: ./velxio
|
||||||
|
dockerfile: Dockerfile.standalone
|
||||||
|
network_mode: service:velxio-ts
|
||||||
|
environment:
|
||||||
|
- SECRET_KEY=${VELXIO_SECRET_KEY:-embed-only-no-auth-needed}
|
||||||
|
- DATABASE_URL=sqlite+aiosqlite:////app/data/velxio.db
|
||||||
|
- DATA_DIR=/app/data
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- velxio-ts
|
||||||
|
volumes:
|
||||||
|
- velxio-standalone-data:/app/data
|
||||||
|
- velxio-standalone-arduino-libs:/root/.arduino15
|
||||||
|
- velxio-standalone-ccache:/var/cache/ccache
|
||||||
|
- velxio-standalone-build:/var/lib/velxio-build
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
velxio-standalone-data:
|
||||||
|
velxio-standalone-arduino-libs:
|
||||||
|
velxio-standalone-ccache:
|
||||||
|
velxio-standalone-build:
|
||||||
|
|
@ -51,7 +51,7 @@ services:
|
||||||
environment:
|
environment:
|
||||||
- COMPILER_WORKER_URL=http://127.0.0.1:8080/execute
|
- COMPILER_WORKER_URL=http://127.0.0.1:8080/execute
|
||||||
- COMPILER_WORKER_BASE_URL=http://127.0.0.1:8080
|
- COMPILER_WORKER_BASE_URL=http://127.0.0.1:8080
|
||||||
- VELXIO_COMPILER_URL=http://127.0.0.1:80/api/compile/
|
- VELXIO_COMPILER_URL=${VELXIO_COMPILER_URL:-http://127.0.0.1:80/api/compile/}
|
||||||
- DATABASE_URL=${DATABASE_URL}
|
- DATABASE_URL=${DATABASE_URL}
|
||||||
- TOKEN_PEPPER=${TOKEN_PEPPER}
|
- TOKEN_PEPPER=${TOKEN_PEPPER}
|
||||||
- STORAGE_BACKEND=${STORAGE_BACKEND:-postgresql}
|
- STORAGE_BACKEND=${STORAGE_BACKEND:-postgresql}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue