chore: sync ports to 4000s infra (4006/4011/4012) and DB pool 6432

This commit is contained in:
asepharyana
2026-08-02 16:14:12 +07:00
parent 2eb4e47585
commit 46d98a3544
15 changed files with 57 additions and 57 deletions
+2 -2
View File
@@ -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.
+1 -1
View File
@@ -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
View File
@@ -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 autodiscovery 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
+1 -1
View File
@@ -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
View File
@@ -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"]
+1 -1
View File
@@ -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',
},
});
+1 -1
View File
@@ -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',
+2 -2
View File
@@ -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"]
+9 -9
View File
@@ -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
View File
@@ -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;
+15 -15
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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"
+4 -4
View File
@@ -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
View File
@@ -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)