refactor(compose): adaptasi pola network tailscale ala firefly-iii

- Semua service share netns elemes-ts (network_mode: service:elemes-ts),
  hapus bridge network elemes_network
- lms-tail.json: proxy target 127.0.0.1 (bukan nama service DNS)
- flowchart pindah port 80 → 8081 (konflik port di netns bersama),
  tambah nginx.conf custom + EXPOSE 8081
- env internal (COMPILER_WORKER_URL, VELXIO_COMPILER_URL, API_BACKEND,
  hooks fallback, vite dev proxy) → 127.0.0.1
- fix format volume velxio-data/velxio-arduino-libs agar kompatibel
  podman-compose 1.0.6 (named volume standar)
This commit is contained in:
a2nr 2026-08-01 12:56:51 +00:00
parent 52771bc264
commit 0ee39f152e
7 changed files with 110 additions and 90 deletions

View File

@ -8,22 +8,22 @@
"${TS_CERT_DOMAIN}:443": {
"Handlers": {
"/": {
"Proxy": "http://elemes-frontend:3000"
"Proxy": "http://127.0.0.1:3000"
},
"/assets/": {
"Proxy": "http://elemes:5000/assets/"
"Proxy": "http://127.0.0.1:5000/assets/"
},
"/velxio/api/compile/": {
"Proxy": "http://elemes:5000/velxio-compile/"
"Proxy": "http://127.0.0.1:5000/velxio-compile/"
},
"/velxio/api/compile": {
"Proxy": "http://elemes:5000/velxio-compile"
"Proxy": "http://127.0.0.1:5000/velxio-compile"
},
"/velxio/": {
"Proxy": "http://velxio:80/"
"Proxy": "http://127.0.0.1:80/"
},
"/flowchart/": {
"Proxy": "http://flowchart:80/"
"Proxy": "http://127.0.0.1:8081/"
}
}
}
@ -31,4 +31,4 @@
"AllowFunnel": {
"${TS_CERT_DOMAIN}:443": true
}
}
}

View File

@ -14,5 +14,10 @@ FROM nginx:alpine
# Copy built static files to Nginx's default public directory
COPY --from=builder /app/dist/ /usr/share/nginx/html/
EXPOSE 80
# Listen on 8081 (not 80) — all services share elemes-ts network
# namespace, where port 80 is taken by velxio. Tailscale serve strips
# the /flowchart/ mount point before proxying here.
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 8081
CMD ["nginx", "-g", "daemon off;"]

13
flowchart/nginx.conf Normal file
View File

@ -0,0 +1,13 @@
server {
listen 8081;
server_name _;
root /usr/share/nginx/html;
index index.html;
# SPA fallback tailscale serve strips the /flowchart/ mount point,
# so nginx receives /assets/... and / (index.html)
location / {
try_files $uri $uri/ /index.html;
}
}

View File

@ -2,7 +2,8 @@
* SvelteKit server hook proxies /api/* requests to the Flask backend.
*
* Uses API_BACKEND env var (set in podman-compose.yml).
* Falls back to http://elemes:5000, then tries container IP resolution.
* Falls back to http://127.0.0.1:5000 — all services share the
* elemes-ts network namespace, so the backend lives on localhost.
*/
import type { Handle } from '@sveltejs/kit';
@ -10,7 +11,7 @@ import type { Handle } from '@sveltejs/kit';
function resolveBackend(): string {
const env = process.env.API_BACKEND;
if (env) return env;
return 'http://elemes:5000';
return 'http://127.0.0.1:5000';
}
const API_BACKEND = resolveBackend();

View File

@ -9,17 +9,17 @@ export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://elemes:5000',
target: 'http://127.0.0.1:5000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
},
'/velxio/api/compile': {
target: 'http://elemes:5000',
target: 'http://127.0.0.1:5000',
changeOrigin: true,
rewrite: (path) => '/velxio-compile'
},
'/assets': {
target: 'http://elemes:5000',
target: 'http://127.0.0.1:5000',
changeOrigin: true
}
}

View File

@ -1,74 +1,6 @@
version: '3.8'
services:
elemes:
build: .
image: lms-backend:latest
volumes:
- ../content:/app/content:ro
- ../tokens_siswa.csv:/app/tokens.csv:rw
- ../assets:/app/assets:ro
env_file:
- ../.env
environment:
- COMPILER_WORKER_URL=http://compiler-worker:8080/execute
networks:
- elemes_network
# production
command: gunicorn --config gunicorn.conf.py "app:create_app()"
# debug
# command: python app.py
compiler-worker:
build: ./compiler_worker
image: lms-compiler-worker:latest
runtime: runsc # Enable gVisor
networks:
- elemes_network
elemes-frontend:
build: ./frontend
image: lms-frontend:latest
# ports:
# - 3000:3000
environment:
- ORIGIN=http://localhost:3000
- API_BACKEND=http://elemes:5000
- PUBLIC_APP_BAR_TITLE=${APP_BAR_TITLE}
- PUBLIC_COPYRIGHT_TEXT=${COPYRIGHT_TEXT}
- PUBLIC_PAGE_TITLE_SUFFIX=${PAGE_TITLE_SUFFIX}
- PUBLIC_CURSOR_OFFSET_Y=${CURSOR_OFFSET_Y:-50}
networks:
- elemes_network
depends_on:
- elemes
velxio:
image: lms-velxio:latest
build:
context: ./velxio
dockerfile: Dockerfile.standalone
args:
VITE_BASE_PATH: /velxio/
VITE_API_BASE: /velxio/api
ENABLE_ESP32: ${ENABLE_ESP32:-0}
environment:
- SECRET_KEY=embed-only-no-auth-needed
- DATABASE_URL=sqlite+aiosqlite:////app/data/velxio.db
- DATA_DIR=/app/data
networks:
- elemes_network
volumes:
- velxio-data:/app/data
- velxio-arduino-libs:/root/.arduino15
flowchart:
build: ./flowchart
image: lms-flowchart:latest
networks:
- elemes_network
elemes-ts:
image: docker.io/tailscale/tailscale:latest
hostname: ${ELEMES_HOST}
@ -85,16 +17,85 @@ services:
- net_admin
- sys_module
restart: unless-stopped
depends_on:
- elemes-frontend
env_file:
- ../.env
elemes:
build: .
image: lms-backend:latest
network_mode: service:elemes-ts
volumes:
- ../content:/app/content:ro
- ../tokens_siswa.csv:/app/tokens.csv:rw
- ../assets:/app/assets:ro
env_file:
- ../.env
environment:
- COMPILER_WORKER_URL=http://127.0.0.1:8080/execute
- VELXIO_COMPILER_URL=http://127.0.0.1:80/api/compile/
restart: unless-stopped
depends_on:
- elemes-ts
# production
command: gunicorn --config gunicorn.conf.py "app:create_app()"
# debug
# command: python app.py
compiler-worker:
build: ./compiler_worker
image: lms-compiler-worker:latest
runtime: runsc # Enable gVisor
network_mode: service:elemes-ts
restart: unless-stopped
depends_on:
- elemes-ts
elemes-frontend:
build: ./frontend
image: lms-frontend:latest
# ports:
# - 3000:3000
network_mode: service:elemes-ts
environment:
- ORIGIN=http://localhost:3000
- API_BACKEND=http://127.0.0.1:5000
- PUBLIC_APP_BAR_TITLE=${APP_BAR_TITLE}
- PUBLIC_COPYRIGHT_TEXT=${COPYRIGHT_TEXT}
- PUBLIC_PAGE_TITLE_SUFFIX=${PAGE_TITLE_SUFFIX}
- PUBLIC_CURSOR_OFFSET_Y=${CURSOR_OFFSET_Y:-50}
restart: unless-stopped
depends_on:
- elemes-ts
- elemes
velxio:
image: lms-velxio:latest
build:
context: ./velxio
dockerfile: Dockerfile.standalone
args:
VITE_BASE_PATH: /velxio/
VITE_API_BASE: /velxio/api
network_mode: service:elemes-ts
environment:
- SECRET_KEY=embed-only-no-auth-needed
- DATABASE_URL=sqlite+aiosqlite:////app/data/velxio.db
- DATA_DIR=/app/data
restart: unless-stopped
depends_on:
- elemes-ts
volumes:
- velxio-data:/app/data
- velxio-arduino-libs:/root/.arduino15
flowchart:
build: ./flowchart
image: lms-flowchart:latest
network_mode: service:elemes-ts
restart: unless-stopped
depends_on:
- elemes-ts
volumes:
velxio-data:
velxio-arduino-libs:
networks:
elemes_network:
driver: bridge
network_mode: service:elemes-ts

View File

@ -14,8 +14,8 @@ from extensions import limiter
compile_bp = Blueprint('compile', __name__)
COMPILER_WORKER_URL = os.environ.get('COMPILER_WORKER_URL', 'http://compiler-worker:8080/execute')
VELXIO_COMPILER_URL = os.environ.get('VELXIO_COMPILER_URL', 'http://velxio:80/api/compile/')
COMPILER_WORKER_URL = os.environ.get('COMPILER_WORKER_URL', 'http://127.0.0.1:8080/execute')
VELXIO_COMPILER_URL = os.environ.get('VELXIO_COMPILER_URL', 'http://127.0.0.1:80/api/compile/')
ANON_QUEUE_DIR = "/tmp/elemes_anon_queue"
# Ensure queue directory exists