chore: sync ports to 4000s infra (4006/4011/4012) and DB pool 6432
This commit is contained in:
+2
-2
@@ -1,6 +1,6 @@
|
||||
WEB_PORT=5173
|
||||
API_PORT=3000
|
||||
DATABASE_URL=postgres://postgres:postgres@localhost:5432/zeavis_edu
|
||||
API_PORT=4006
|
||||
DATABASE_URL=postgres://asephs:***@100.121.180.82:6432/zeavis_edu
|
||||
|
||||
# ── Telemetry / ClickHouse ──────────────────────────────────────────
|
||||
# These credentials are used by the telemetry Docker Compose stack.
|
||||
|
||||
@@ -162,7 +162,7 @@ Each ZeaVis Edu service exposes a `GET /metrics` endpoint:
|
||||
|
||||
All three share the `zeavis_` metric prefix and are scraped by Prometheus via `file_sd_configs` (see `telemetry/prometheus/targets/zeavis-edu.json`).
|
||||
|
||||
**IMPORTANT — Production architecture:** ZeaVis Edu apps and the Telemetry stack run on **separate VPS instances** connected via **Tailscale** (mesh VPN). Prometheus scrapes the API and ML service through their **Tailscale IPs** (e.g. `100.x.x.a:3000`), not via Docker hostnames. The target file has `__CHANGE_ME__` placeholders — replace with actual Tailscale IPs before deploying.
|
||||
**IMPORTANT — Production architecture:** ZeaVis Edu apps and the Telemetry stack run on **separate VPS instances** connected via **Tailscale** (mesh VPN). Prometheus scrapes the API and ML service through their **Tailscale IPs** (e.g. `100.x.x.a:4006`), not via Docker hostnames. The target file has `__CHANGE_ME__` placeholders — replace with actual Tailscale IPs before deploying.
|
||||
|
||||
The telemetry stack is managed from the project root via `make telemetry-*` targets (see `Makefile`). Docker Compose defines 5 services (Prometheus, Node Exporter, Query Proxy, Grafana, Telemetry UI).
|
||||
|
||||
|
||||
+6
-6
@@ -10,15 +10,15 @@ application stack and the payload each service provides.
|
||||
| Service | Host (prod) | Metrics Endpoint | Port (local) |
|
||||
|-----------------------|-----------------------------------|----------------------------|--------------|
|
||||
| Web (Vite dev) | `zeavisedu.asepharyana.my.id` | `GET /metrics` | 5173 |
|
||||
| API (Elysia) | `api-zeavisedu.asepharyana.my.id` | `GET /metrics` | 3000 |
|
||||
| ML Service (Axum) | `ml-zeavisedu.asepharyana.my.id` | `GET /metrics` | 8000 |
|
||||
| API (Elysia) | `api-zeavisedu.asepharyana.my.id` | `GET /metrics` | 4006 |
|
||||
| ML Service (Axum) | `ml-zeavisedu.asepharyana.my.id` | `GET /metrics` | 4012 |
|
||||
| Prometheus Collector | — | `GET /metrics` (self) | 9090 |
|
||||
|
||||
> In production all metrics are scraped by the Prometheus collector running in the
|
||||
> Telemetry stack on a **separate VPS** connected via **Tailscale**.
|
||||
> See [`telemetry/prometheus/targets/`](./telemetry/prometheus/targets/)
|
||||
> for the auto‑discovery configuration. Target files must use **Tailscale IPs**
|
||||
> (e.g. `100.x.x.a:3000`), not Docker hostnames, because the services are on
|
||||
> (e.g. `100.x.x.a:4006`), not Docker hostnames, because the services are on
|
||||
> different hosts.
|
||||
>
|
||||
> In production (nginx), the web app proxies `/metrics` to the API service:
|
||||
@@ -101,11 +101,11 @@ The Telemetry submodule includes a Prometheus instance that uses
|
||||
```json
|
||||
[
|
||||
{
|
||||
"targets": ["100.x.x.a:3000"],
|
||||
"targets": ["100.x.x.a:4006"],
|
||||
"labels": { "service": "zeavis-api", "component": "backend", "env": "production" }
|
||||
},
|
||||
{
|
||||
"targets": ["100.x.x.b:8000"],
|
||||
"targets": ["100.x.x.b:4012"],
|
||||
"labels": { "service": "zeavis-ml", "component": "inference", "env": "production" }
|
||||
}
|
||||
]
|
||||
@@ -113,7 +113,7 @@ The Telemetry submodule includes a Prometheus instance that uses
|
||||
|
||||
> ⚠️ **Cross-VPS:** Gunakan **IP Tailscale** (bukan Docker hostname) karena
|
||||
> Prometheus dan ZeaVis Edu berjalan di VPS berbeda. Pastikan port service
|
||||
> (`:3000`, `:8000`) terekspos di `0.0.0.0` atau diizinkan oleh aturan
|
||||
> (`:4006`, `:4012`) terekspos di `0.0.0.0` atau diizinkan oleh aturan
|
||||
> `iptables`/`ufw` untuk interface Tailscale (`tailscale0`/`100.x.x.x/10`).
|
||||
|
||||
The Prometheus config (in `telemetry/prometheus/prometheus.yml`) will
|
||||
|
||||
@@ -209,7 +209,7 @@ bun install
|
||||
bun run dev # Semua service (web + api)
|
||||
cd apps/web && bun run dev # Hanya frontend
|
||||
cd apps/api && bun run start # Hanya backend API
|
||||
cd apps/ml-service && cargo run # ML inference engine (port 8000)
|
||||
cd apps/ml-service && cargo run # ML inference engine (port 4012)
|
||||
cd apps/tauri && bun run tauri dev # Tauri desktop dev
|
||||
cd apps/tauri && bun run tauri android dev # Tauri Android dev
|
||||
```
|
||||
|
||||
+2
-2
@@ -11,7 +11,7 @@ RUN bun install --production
|
||||
FROM oven/bun:1.3.14 AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
ENV API_PORT=3000
|
||||
ENV API_PORT=4006
|
||||
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY --from=deps /app/apps/api/node_modules apps/api/node_modules
|
||||
@@ -20,5 +20,5 @@ COPY package.json bunfig.toml tsconfig.base.json ./
|
||||
COPY apps/api apps/api
|
||||
COPY packages/shared packages/shared
|
||||
|
||||
EXPOSE 3000
|
||||
EXPOSE 4006
|
||||
CMD ["bun", "apps/api/src/index.ts"]
|
||||
|
||||
@@ -5,6 +5,6 @@ export default defineConfig({
|
||||
out: './drizzle',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL ?? 'postgres://postgres:postgres@localhost:5432/zeavis_edu',
|
||||
url: process.env.DATABASE_URL ?? 'postgres://asephs:***@100.121.180.82:6432/zeavis_edu',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ const allowedOrigins = [
|
||||
const secureCookies = Bun.env.SECURE_COOKIES === 'true' || webAppUrl.startsWith('https://');
|
||||
|
||||
export const env = {
|
||||
port: Number(Bun.env.API_PORT ?? 3000),
|
||||
port: Number(Bun.env.API_PORT ?? 4006),
|
||||
databaseUrl: Bun.env.DATABASE_URL,
|
||||
sessionSecret: Bun.env.SESSION_SECRET,
|
||||
uploaderBaseUrl: Bun.env.UPLOADER_BASE_URL ?? 'https://upload.asepharyana.my.id',
|
||||
|
||||
@@ -11,7 +11,7 @@ WORKDIR /app
|
||||
ENV MODEL_PATH=/app/model/model.onnx
|
||||
ENV MODEL_INPUT_SIZE=224
|
||||
ENV ML_SERVICE_HOST=0.0.0.0
|
||||
ENV ML_SERVICE_PORT=8000
|
||||
ENV ML_SERVICE_PORT=4012
|
||||
ENV RUST_LOG=info
|
||||
|
||||
RUN pacman -Syu --noconfirm ca-certificates 2>/dev/null
|
||||
@@ -19,5 +19,5 @@ RUN pacman -Syu --noconfirm ca-certificates 2>/dev/null
|
||||
COPY --from=builder /app/target/release/zeavis-ml-service /usr/local/bin/zeavis-ml-service
|
||||
COPY Machine_Learning/model/model.onnx /app/model/model.onnx
|
||||
|
||||
EXPOSE 8000
|
||||
EXPOSE 4012
|
||||
CMD ["zeavis-ml-service"]
|
||||
|
||||
@@ -48,7 +48,7 @@ Output build lokal berada di `target/` dan direktori tersebut diabaikan oleh Git
|
||||
|
||||
Semua perintah di bawah dijalankan dari direktori `apps/ml-service`.
|
||||
|
||||
### Opsi 1: Default (Port 8000)
|
||||
### Opsi 1: Default (Port 4012)
|
||||
|
||||
```bash
|
||||
cargo run
|
||||
@@ -91,7 +91,7 @@ ML_SERVICE_PORT=9000 MODEL_PATH=/path/to/model.onnx cargo run
|
||||
### Health Check
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
curl http://localhost:4012/health
|
||||
```
|
||||
|
||||
```json
|
||||
@@ -104,7 +104,7 @@ curl http://localhost:8000/health
|
||||
### Metadata
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/metadata
|
||||
curl http://localhost:4012/metadata
|
||||
```
|
||||
|
||||
```json
|
||||
@@ -123,7 +123,7 @@ curl http://localhost:8000/metadata
|
||||
Upload gambar daun jagung untuk klasifikasi:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/predict \
|
||||
curl -X POST http://localhost:4012/predict \
|
||||
-F "file=@/path/to/corn-leaf.jpg"
|
||||
```
|
||||
|
||||
@@ -164,13 +164,13 @@ cargo test
|
||||
cargo run
|
||||
|
||||
# 2. Health check
|
||||
curl http://localhost:8000/health
|
||||
curl http://localhost:4012/health
|
||||
|
||||
# 3. Metadata
|
||||
curl http://localhost:8000/metadata
|
||||
curl http://localhost:4012/metadata
|
||||
|
||||
# 4. Prediksi
|
||||
curl -X POST http://localhost:8000/predict \
|
||||
curl -X POST http://localhost:4012/predict \
|
||||
-F "file=@../../Machine_Learning/dataset/Daun\ Sehat/sample.jpg"
|
||||
```
|
||||
|
||||
@@ -182,7 +182,7 @@ Service dapat di-deploy via Docker. Build dari root repository karena Dockerfile
|
||||
|
||||
```bash
|
||||
docker build -f apps/ml-service/Dockerfile -t zeavis-ml-service .
|
||||
docker run -p 8000:8000 zeavis-ml-service
|
||||
docker run -p 8000:4012 zeavis-ml-service
|
||||
```
|
||||
|
||||
Pastikan `Machine_Learning/model/model.onnx` sudah dibuat sebelum build image.
|
||||
@@ -210,7 +210,7 @@ MODEL_PATH=/absolute/path/to/model.onnx cargo run
|
||||
```bash
|
||||
ML_SERVICE_PORT=9000 cargo run
|
||||
# Cek port yang digunakan:
|
||||
lsof -i :8000
|
||||
lsof -i :4012
|
||||
```
|
||||
|
||||
### ONNX Runtime tidak kompatibel
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ server {
|
||||
index index.html;
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://zeavis-api:3000/api/;
|
||||
proxy_pass http://zeavis-api:4006/api/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
@@ -14,7 +14,7 @@ server {
|
||||
|
||||
# Expose API metrics through the web endpoint (Prometheus scrape target)
|
||||
location /metrics {
|
||||
proxy_pass http://zeavis-api:3000/metrics;
|
||||
proxy_pass http://zeavis-api:4006/metrics;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
@@ -225,25 +225,25 @@ export function TelemetryPage() {
|
||||
queryInstant(`rate(node_network_receive_bytes_total{instance="${INST}:9100",device="eth0"}[5m])`),
|
||||
queryInstant(`rate(node_network_transmit_bytes_total{instance="${INST}:9100",device="eth0"}[5m])`),
|
||||
// API
|
||||
queryInstant(`zeavis_api_http_requests_total{instance="${INST}:3000"}`),
|
||||
queryInstant(`zeavis_api_http_requests_active{instance="${INST}:3000"}`),
|
||||
queryInstant(`zeavis_api_http_request_duration_seconds_sum{instance="${INST}:3000"} / zeavis_api_http_request_duration_seconds_count{instance="${INST}:3000"}`),
|
||||
queryRange(`zeavis_api_http_requests_total{instance="${INST}:3000"}`, 60),
|
||||
queryRange(`zeavis_api_http_request_duration_seconds_sum{instance="${INST}:3000"} / zeavis_api_http_request_duration_seconds_count{instance="${INST}:3000"}`, 60),
|
||||
queryInstant(`zeavis_api_http_requests_total{instance="${INST}:4006"}`),
|
||||
queryInstant(`zeavis_api_http_requests_active{instance="${INST}:4006"}`),
|
||||
queryInstant(`zeavis_api_http_request_duration_seconds_sum{instance="${INST}:4006"} / zeavis_api_http_request_duration_seconds_count{instance="${INST}:4006"}`),
|
||||
queryRange(`zeavis_api_http_requests_total{instance="${INST}:4006"}`, 60),
|
||||
queryRange(`zeavis_api_http_request_duration_seconds_sum{instance="${INST}:4006"} / zeavis_api_http_request_duration_seconds_count{instance="${INST}:4006"}`, 60),
|
||||
// ML
|
||||
queryInstant(`zeavis_ml_zeavis_ml_model_load_status{instance="${INST}:8000"}`),
|
||||
// NodeJS
|
||||
queryInstant(`nodejs_heap_size_used_bytes{instance="${INST}:3000"}`),
|
||||
queryInstant(`nodejs_heap_size_total_bytes{instance="${INST}:3000"}`),
|
||||
queryInstant(`nodejs_eventloop_lag_seconds{instance="${INST}:3000"}`),
|
||||
queryInstant(`nodejs_active_handles_total{instance="${INST}:3000"}`),
|
||||
queryInstant(`nodejs_active_requests_total{instance="${INST}:3000"}`),
|
||||
queryRange(`nodejs_heap_size_used_bytes{instance="${INST}:3000"}`, 60),
|
||||
queryRange(`nodejs_eventloop_lag_seconds{instance="${INST}:3000"}`, 60),
|
||||
queryInstant(`nodejs_heap_size_used_bytes{instance="${INST}:4006"}`),
|
||||
queryInstant(`nodejs_heap_size_total_bytes{instance="${INST}:4006"}`),
|
||||
queryInstant(`nodejs_eventloop_lag_seconds{instance="${INST}:4006"}`),
|
||||
queryInstant(`nodejs_active_handles_total{instance="${INST}:4006"}`),
|
||||
queryInstant(`nodejs_active_requests_total{instance="${INST}:4006"}`),
|
||||
queryRange(`nodejs_heap_size_used_bytes{instance="${INST}:4006"}`, 60),
|
||||
queryRange(`nodejs_eventloop_lag_seconds{instance="${INST}:4006"}`, 60),
|
||||
// Process
|
||||
queryInstant(`rate(process_cpu_seconds_total{instance="${INST}:3000"}[5m])`),
|
||||
queryInstant(`process_resident_memory_bytes{instance="${INST}:3000"}`),
|
||||
queryInstant(`process_open_fds{instance="${INST}:3000"}`),
|
||||
queryInstant(`rate(process_cpu_seconds_total{instance="${INST}:4006"}[5m])`),
|
||||
queryInstant(`process_resident_memory_bytes{instance="${INST}:4006"}`),
|
||||
queryInstant(`process_open_fds{instance="${INST}:4006"}`),
|
||||
]);
|
||||
|
||||
setCpuData(cpuR); setMemData(memR); setDiskData(diskR);
|
||||
|
||||
@@ -6,7 +6,7 @@ import { metricsPlugin } from './vite-plugin-metrics';
|
||||
|
||||
export default defineConfig(({ mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), '');
|
||||
const apiProxyTarget = env.VITE_API_PROXY_TARGET || 'http://localhost:3000';
|
||||
const apiProxyTarget = env.VITE_API_PROXY_TARGET || 'http://localhost:4006';
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
|
||||
+6
-6
@@ -32,21 +32,21 @@ services:
|
||||
- app-shared-net
|
||||
- telemetry-net
|
||||
ports:
|
||||
- "${TS_IP:-0.0.0.0}:3000:3000"
|
||||
- "${TS_IP:-0.0.0.0}:4006:4006"
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
API_PORT: "3000"
|
||||
API_PORT: "4006"
|
||||
WEB_APP_URL: https://zeavisedu.asepharyana.my.id
|
||||
ML_SERVICE_URL: ${ML_SERVICE_URL:-http://zeavis-ml:8000}
|
||||
ML_SERVICE_URL: ${ML_SERVICE_URL:-http://zeavis-ml:4012}
|
||||
labels:
|
||||
traefik.enable: "true"
|
||||
traefik.http.routers.zeavis-api.rule: Host(`api-zeavisedu.asepharyana.my.id`)
|
||||
traefik.http.routers.zeavis-api.entrypoints: websecure
|
||||
traefik.http.routers.zeavis-api.tls: "true"
|
||||
traefik.http.routers.zeavis-api.tls.certresolver: cloudflare
|
||||
traefik.http.services.zeavis-api.loadbalancer.server.port: "3000"
|
||||
traefik.http.services.zeavis-api.loadbalancer.server.port: "4006"
|
||||
|
||||
# Node Exporter — expose system metrics (CPU, RAM, disk) for Prometheus scraping
|
||||
node_exporter:
|
||||
@@ -73,7 +73,7 @@ services:
|
||||
- app-shared-net
|
||||
- telemetry-net
|
||||
ports:
|
||||
- "${TS_IP:-0.0.0.0}:8000:8000"
|
||||
- "${TS_IP:-0.0.0.0}:4012:4012"
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
@@ -85,4 +85,4 @@ services:
|
||||
traefik.http.routers.zeavis-ml.entrypoints: websecure
|
||||
traefik.http.routers.zeavis-ml.tls: "true"
|
||||
traefik.http.routers.zeavis-ml.tls.certresolver: cloudflare
|
||||
traefik.http.services.zeavis-ml.loadbalancer.server.port: "8000"
|
||||
traefik.http.services.zeavis-ml.loadbalancer.server.port: "4012"
|
||||
|
||||
@@ -66,7 +66,7 @@ WRAPPER
|
||||
export MODEL_PATH="$out/share/zeavis-ml/model.onnx"
|
||||
export MODEL_INPUT_SIZE="224"
|
||||
export ML_SERVICE_HOST="0.0.0.0"
|
||||
export ML_SERVICE_PORT="8200"
|
||||
export ML_SERVICE_PORT="4012"
|
||||
export RUST_LOG="info"
|
||||
exec $out/bin/.zeavis-ml-service
|
||||
WRAPPER
|
||||
@@ -99,13 +99,13 @@ http {
|
||||
include ${pkgs.nginx}/conf/mime.types;
|
||||
access_log /var/lib/zeavis-web/nginx-access.log;
|
||||
server {
|
||||
listen 8088;
|
||||
listen 4011;
|
||||
server_name _;
|
||||
root $out/share/zeavis-web/html;
|
||||
index index.html;
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:3200/api/;
|
||||
proxy_pass http://127.0.0.1:4006/api/;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
@@ -113,7 +113,7 @@ http {
|
||||
}
|
||||
|
||||
location /metrics {
|
||||
proxy_pass http://127.0.0.1:3200/metrics;
|
||||
proxy_pass http://127.0.0.1:4006/metrics;
|
||||
proxy_set_header Host \$host;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
|
||||
+4
-4
@@ -29,7 +29,7 @@ ZeaVis Edu berjalan di **dua VPS terpisah** yang terhubung melalui **Tailscale**
|
||||
│ │ │ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ ┌──────────┐ ┌──────────────┐ │
|
||||
│ │ Web │ │ API │ │ ML │ │ │ │Prometheus│ │Metric │ │
|
||||
│ │:80 │ │:3000 │ │:8000 │ │ │ │:9090 │ │Ingester │ │
|
||||
│ │:80 │ │:4006 │ │:4012 │ │ │ │:9090 │ │Ingester │ │
|
||||
│ │/metrics │ │/metrics │ │/metrics │ │ │ │ │ │:9091 │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ │ │ └────┬─────┘ └──────┬───────┘ │
|
||||
│ ┌──────────────────────────────────────┐ │ │ │ │ │
|
||||
@@ -65,7 +65,7 @@ ZeaVis Edu berjalan di **dua VPS terpisah** yang terhubung melalui **Tailscale**
|
||||
|
||||
| VPS | Hostname | OS | Peran |
|
||||
|---|---|---|---|
|
||||
| **App VPS** | `imrnes` | Arch Linux | Web (:80), API (:3000), ML Service (:8000) |
|
||||
| **App VPS** | `imrnes` | Arch Linux | Web (:80), API (:4006), ML Service (:4012) |
|
||||
| **Telemetry VPS** | `orange` | Ubuntu | Prometheus, ClickHouse, Telemetry UI |
|
||||
|
||||
---
|
||||
@@ -128,8 +128,8 @@ bash clickhouse/init.sh
|
||||
| Port | Service | Akses |
|
||||
|---|---|---|
|
||||
| 80/443 | Web (via Traefik/Coolify) | Public |
|
||||
| 3000 | API metrics | Tailscale-only |
|
||||
| 8000 | ML service metrics | Tailscale-only |
|
||||
| 4006 | API metrics | Tailscale-only |
|
||||
| 4012 | ML service metrics | Tailscale-only |
|
||||
| 9100 | Node Exporter | Tailscale-only |
|
||||
|
||||
### Telemetry VPS (orange)
|
||||
|
||||
Reference in New Issue
Block a user