chore: remove unused configuration files and submodules

This commit is contained in:
asepharyana
2026-07-21 12:54:57 +07:00
parent 44a56fa0a9
commit cdad9ae720
23 changed files with 11 additions and 486 deletions
-7
View File
@@ -1,7 +0,0 @@
{
"image": "mcr.microsoft.com/devcontainers/universal:2",
"features": {
"ghcr.io/devcontainers/features/rust:1": {},
"ghcr.io/devcontainers/features/node:2": {}
}
}
+1 -1
View File
@@ -89,7 +89,7 @@ jobs:
git fetch origin main --depth=1 || true
# Detect changed files before resetting
ALL_COMPOSE_FILES="infra/compose/traefik.yml infra/compose/shared.yml infra/compose/scraper.yml infra/compose/elysia.yml infra/compose/react.yml infra/compose/rust-auth.yml"
ALL_COMPOSE_FILES="infra/compose/traefik.yml infra/compose/shared.yml infra/compose/scraper.yml"
TRAEFIK_DYNAMIC_DIR="infra/traefik/dynamic"
if git rev-parse HEAD >/dev/null 2>&1; then
+3 -27
View File
@@ -5,7 +5,7 @@ on:
branches:
- main
paths:
- 'apps/**'
- 'apps/scraper/**'
- '.github/workflows/docker-build-push.yml'
- 'infra/**'
- '!infra/compose/**'
@@ -34,9 +34,6 @@ jobs:
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
scraper-api: ${{ steps.filter.outputs['scraper-api'] == 'true' || steps.dispatch.outputs['scraper-api'] == 'true' || github.event_name == 'workflow_dispatch' }}
elysia-api: ${{ steps.filter.outputs['elysia-api'] == 'true' || steps.dispatch.outputs['elysia-api'] == 'true' || github.event_name == 'workflow_dispatch' }}
react-web: ${{ steps.filter.outputs['react-web'] == 'true' || steps.dispatch.outputs['react-web'] == 'true' || github.event_name == 'workflow_dispatch' }}
rust-auth: ${{ steps.filter.outputs['rust-auth'] == 'true' || steps.dispatch.outputs['rust-auth'] == 'true' || github.event_name == 'workflow_dispatch' }}
steps:
- uses: actions/checkout@v6
with:
@@ -63,9 +60,6 @@ jobs:
}
echo "scraper-api=$(changed '^(apps/scraper(/|$)|\.github/workflows/docker-build-push\.yml$|infra/docker/scraper\.Dockerfile$)')" >> "$GITHUB_OUTPUT"
echo "elysia-api=$(changed '^(apps/elysia(/|$)|\.github/workflows/docker-build-push\.yml$|infra/docker/elysia\.Dockerfile$)')" >> "$GITHUB_OUTPUT"
echo "react-web=$(changed '^(apps/react(/|$)|\.github/workflows/docker-build-push\.yml$|infra/docker/react\.Dockerfile$)')" >> "$GITHUB_OUTPUT"
echo "rust-auth=$(changed '^(apps/rust-auth(/|$)|infra/docker/rust\.Dockerfile$|\.github/workflows/docker-build-push\.yml$|\.gitmodules$)')" >> "$GITHUB_OUTPUT"
- name: Parse repository_dispatch payload
id: dispatch
@@ -87,7 +81,7 @@ jobs:
fi
case "$SERVICE" in
scraper-api|elysia-api|react-web|rust-auth) ;;
scraper-api) ;;
*)
exit 1
;;
@@ -95,7 +89,7 @@ jobs:
if ! [[ "$SHA" =~ ^[0-9a-fA-F]{40}$ ]]; then echo "::error::Invalid sha '$SHA'. Expected 40 hex characters"; exit 1; fi
SERVICES=(scraper-api elysia-api react-web rust-auth)
SERVICES=(scraper-api)
for svc in "${SERVICES[@]}"; do
if [ "$SERVICE" = "$svc" ]; then
echo "${svc}=true" >> "$GITHUB_OUTPUT"
@@ -113,9 +107,6 @@ jobs:
}
if [ "${{ steps.filter.outputs['scraper-api'] == 'true' || steps.dispatch.outputs['scraper-api'] == 'true' || github.event_name == 'workflow_dispatch' }}" == "true" ]; then add_service "scraper-api" "docker-scraper" "apps/scraper"; fi
if [ "${{ steps.filter.outputs['elysia-api'] == 'true' || steps.dispatch.outputs['elysia-api'] == 'true' || github.event_name == 'workflow_dispatch' }}" == "true" ]; then add_service "elysia-api" "docker-elysia" "apps/elysia"; fi
if [ "${{ steps.filter.outputs['react-web'] == 'true' || steps.dispatch.outputs['react-web'] == 'true' || github.event_name == 'workflow_dispatch' }}" == "true" ]; then add_service "react-web" "docker-react" "apps/react"; fi
if [ "${{ steps.filter.outputs['rust-auth'] == 'true' || steps.dispatch.outputs['rust-auth'] == 'true' || github.event_name == 'workflow_dispatch' }}" == "true" ]; then add_service "rust-auth" "docker-rust-auth" "apps/rust-auth"; fi
JSON_ARRAY="[$(IFS=,; echo "${SERVICES[*]}")]"
echo "matrix=$JSON_ARRAY" >> $GITHUB_OUTPUT
@@ -135,9 +126,6 @@ jobs:
case "$SERVICE" in
"scraper-api") REPO="https://github.com/asepharyana/asepharyana-hub-scraper.git" ;;
"elysia-api") REPO="https://github.com/asepharyana/asepharyana-hub-elysia.git" ;;
"react-web") REPO="https://github.com/asepharyana/asepharyana-hub-react.git" ;;
"rust-auth") REPO="https://github.com/asepharyana/asepharyana-hub-rust-auth.git" ;;
*)
echo "::error::Unsupported service '$SERVICE'"
exit 1
@@ -219,9 +207,6 @@ jobs:
echo "cache-registry=${REGISTRY}/${IMAGE_NAME_PREFIX}/${SVC_NAME}:buildcache" >> $GITHUB_OUTPUT
case "$SVC_NAME" in
"scraper-api") echo "dockerfile=infra/docker/scraper.Dockerfile" >> $GITHUB_OUTPUT ;;
"elysia-api") echo "dockerfile=infra/docker/elysia.Dockerfile" >> $GITHUB_OUTPUT ;;
"react-web") echo "dockerfile=infra/docker/react.Dockerfile" >> $GITHUB_OUTPUT ;;
"rust-auth") echo "dockerfile=infra/docker/rust.Dockerfile" >> $GITHUB_OUTPUT ;;
esac
- name: Build and Push Docker image
@@ -266,15 +251,9 @@ jobs:
declare -A SERVICES
SERVICES["scraper-api"]="scraper.yml"
SERVICES["elysia-api"]="elysia.yml"
SERVICES["react-web"]="react.yml"
SERVICES["rust-auth"]="rust-auth.yml"
declare -A PATHS
PATHS["scraper-api"]="apps/scraper"
PATHS["elysia-api"]="apps/elysia"
PATHS["react-web"]="apps/react"
PATHS["rust-auth"]="apps/rust-auth"
# Use git config for possible commits
git config --local user.email "action@github.com"
@@ -283,9 +262,6 @@ jobs:
for id in "${!SERVICES[@]}"; do
SHOULD_HAVE_RUN=false
if [ "${{ needs.changes.outputs['scraper-api'] }}" == "true" ] && [ "$id" == "scraper-api" ]; then SHOULD_HAVE_RUN=true; fi
if [ "${{ needs.changes.outputs['elysia-api'] }}" == "true" ] && [ "$id" == "elysia-api" ]; then SHOULD_HAVE_RUN=true; fi
if [ "${{ needs.changes.outputs['react-web'] }}" == "true" ] && [ "$id" == "react-web" ]; then SHOULD_HAVE_RUN=true; fi
if [ "${{ needs.changes.outputs['rust-auth'] }}" == "true" ] && [ "$id" == "rust-auth" ]; then SHOULD_HAVE_RUN=true; fi
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then SHOULD_HAVE_RUN=true; fi
-36
View File
@@ -1,36 +0,0 @@
name: TypeCheck
on:
pull_request:
branches: [main]
paths:
- 'apps/react/src/**/*.ts'
- 'apps/react/src/**/*.tsx'
- 'apps/elysia/src/**/*.ts'
- 'apps/elysia/tsconfig.json'
- 'tsconfig.base.json'
jobs:
typecheck:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
with:
submodules: recursive
- uses: oven/setup-bun@v2
with:
bun-version: latest
- name: TypeCheck apps/react
working-directory: apps/react
run: |
bun install
npx tsc --noEmit
- name: TypeCheck apps/elysia
working-directory: apps/elysia
run: |
bun install
bun run typecheck
+1 -1
View File
@@ -36,7 +36,7 @@ jobs:
fi
case "$SERVICE" in
scraper-api|elysia-api|react-web|rust-auth) ;;
scraper-api) ;;
*)
echo "::error::Unsupported service '$SERVICE'"
exit 1
-9
View File
@@ -1,12 +1,3 @@
[submodule "apps/elysia"]
path = apps/elysia
url = https://github.com/asepharyana/asepharyana-hub-elysia.git
[submodule "apps/react"]
path = apps/react
url = https://github.com/asepharyana/asepharyana-hub-react.git
[submodule "apps/scraper"]
path = apps/scraper
url = https://github.com/asepharyana/asepharyana-hub-scraper.git
[submodule "apps/rust-auth"]
path = apps/rust-auth
url = https://github.com/asepharyana/asepharyana-hub-rust-auth.git
-8
View File
@@ -1,8 +0,0 @@
{
"mcpServers": {
"next-devtools": {
"command": "npx",
"args": ["-y", "next-devtools-mcp@latest"]
}
}
}
-81
View File
@@ -1,81 +0,0 @@
# Agent Protocol v10: Strategic Execution and Diagnostic Directives
1. **Mandatory Executability.**
- **Directive:** All generated outputs must be syntactically correct and directly executable by the target system's interpreter, compiler, or shell.
- **Constraint:** Placeholders and pseudo-code are forbidden. Every output must be a complete, functional artifact.
2. **Data and State Integrity.**
- **Directive:** All generated code must strictly adhere to declared data structures, schemas, and the target language's type system.
- **Constraint:** Any operation producing a type mismatch, schema violation, or logical inconsistency is an invalid operation and must be discarded.
3. **Atomic and Consistent State Modification.**
- **Directive:** Modification of a shared resource must be performed as an atomic operation or within an ACID-compliant transaction.
- **Constraint:** Operations that can lead to race conditions or inconsistent state are prohibited. Immutability is the required default.
4. **Zero-Trust Security (Inviolable Safety Constraint).**
- **Directive:** Secrets must not be stored as literal values in source code. They must be loaded at runtime from a secure external source.
- **Constraint:** Generated access policies must adhere to the Principle of Least Privilege.
5. **Supply Chain Security (Inviolable Safety Constraint).**
- **Directive:** All external dependencies must be sourced from trusted repositories and defined in a lockfile for deterministic resolution.
- **Constraint:** The dependency graph must be scanned for known CVEs. Dependencies with critical vulnerabilities are prohibited.
6. **Deterministic and Reproducible Builds.**
- **Directive:** From a given source commit, the build process must produce a byte-for-byte identical artifact in every execution.
- **Constraint:** All automated tests must be deterministic. A regression test codifying the fixed bug's failure condition must be included with the fix.
7. **Structured, Traceable Logging.**
- **Directive:** All processes must emit structured (JSON) logs for significant events. All log entries for a request must contain the same unique trace ID.
- **Constraint:** Error conditions must be explicitly logged with context and propagated. Errors must not be silently suppressed.
8. **Strict API Contract Enforcement.**
- **Directive:** All network communication must strictly conform to its published, versioned API contract.
- **Constraint:** Any network call violating the contract must be rejected. Breaking changes require a major version increment (SemVer).
9. **Distributed System Consensus.**
- **Directive:** Changes to shared state across a distributed system are committed only after a formal consensus algorithm confirms quorum.
- **Constraint:** Nodes in a minority partition must enter a read-only or unavailable state to prevent a split-brain scenario.
10. **Execution Planning and Pre-flight Validation (Think Before Acting).**
- **Directive:** For any multi-step task, a detailed execution plan (sequence of commands and file modifications) must be formulated before any state-modifying action is taken.
- **Constraint:** Before executing a command, the agent must first use a validation or dry-run flag (e.g., `--dry-run`, `--check`) if available. The operation may only proceed if the pre-flight check passes without error.
11. **Post-Failure Root Cause Analysis (Evaluate Mistakes from Logs).**
- **Directive:** Upon command execution failure (non-zero exit code), the current execution plan must be halted, and the agent must enter a diagnostic mode.
- **Constraint:** In diagnostic mode, the agent is required to: 1) Capture and parse the complete `stdout` and `stderr` logs. 2) Identify the specific error message or stack trace. 3) Correlate the error with the last command to form a root cause hypothesis. 4) Formulate a new, corrective execution plan based on the analysis.
12. **Context-Aware File System Operations.**
- **Directive:** Before modifying any file, its full content must be read to establish context. All edits must be based on an in-memory understanding of the file's current state.
- **Constraint:** Blind file operations, such as stream-based search-and-replace without structural validation, are strictly prohibited.
13. **Idempotent State Transitions.**
- **Directive:** Operations that modify state must be designed to be idempotent wherever the protocol allows.
- **Constraint:** Executing the same operation multiple times must result in the same final system state as executing it only once.
14. **Resource Lifecycle Management.**
- **Directive:** All finite system resources (e.g., file handles, network sockets) must be explicitly released after use.
- **Constraint:** The agent must generate code that prevents resource leaks, utilizing language-specific constructs like `try-with-resources` or `defer`.
15. **Configuration as Code (CaC).**
- **Directive:** All configuration must be defined and versioned in source-controlled files.
- **Constraint:** Manual, out-of-band configuration changes are prohibited. Versioned files are the single source of truth.
16. **Atomic and Semantic Version Control.**
- **Directive:** All code changes must be organized into logically atomic commits representing one complete unit of work.
- **Constraint:** Commit messages must adhere to a defined specification (e.g., Conventional Commits).
17. **User Authority and Command Primacy.**
- **Directive:** User-provided instructions and corrections are the definitive source of truth and have the highest operational priority.
- **Constraint:** The agent must immediately adapt its process to align with user directives. Rejected solutions must not be proposed again.
18. **Precedent-Based Improvement.**
- **Directive:** User-approved outputs and successful patterns must be recorded and prioritized as precedents for subsequent tasks.
- **Constraint:** Performance, security, and code quality must not degrade.
19. **Optimization by Explicit Consent.**
- **Directive:** The agent may identify and propose optimizations with a technical justification and supporting metrics.
- **Constraint:** The agent is prohibited from applying any self-initiated optimization without an explicit "approve" command from the user.
20. **System Hierarchy and Safety Overrides.**
- **Directive:** The operational control hierarchy is absolute: 1) **User Command**, 2) **Inviolable Safety Directives (#4, #5)**, 3) **Standard Operational Directives**.
- **Constraint:** If a command conflicts with an Inviolable Directive, the agent must halt, report the conflict and risk, and await a revised command.
-8
View File
@@ -1,8 +0,0 @@
{
"recommendations": [
"nrwl.angular-console",
"biomejs.biome",
"ms-playwright.playwright",
"firsttris.vscode-jest-runner"
]
}
-23
View File
@@ -1,23 +0,0 @@
{
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
},
"editor.codeActionsOnSave": {
"source.organizeImports.biome": "explicit"
}
}
+5 -16
View File
@@ -5,9 +5,6 @@
```
asepharyana-hub/
├── apps/ # Application services (Git submodules)
│ ├── elysia/ # Realtime API (Bun/Elysia/Drizzle/Redis)
│ ├── react/ # Frontend SPA (React/Vite/TanStack)
│ ├── rust-auth/ # IAM & auth service (Axum/SeaORM)
│ └── scraper/ # Web scraper service
├── docs/ # Documentation
│ ├── adr/ # Architecture Decision Records
@@ -31,19 +28,11 @@ asepharyana-hub/
## Technology Stack
### Backend Services
### Services
| Service | Language/Runtime | Framework | Database | Key Libraries |
| ------------- | ---------------- | ---------- | ------------------------ | ------------------------------------------------------------ |
| **rust-auth** | Rust | Axum 0.8 | PostgreSQL (sqlx) | sqlx, jsonwebtoken, argon2, redis, opentelemetry, prometheus |
| **elysia** | TypeScript/Bun | Elysia 1.4 | PostgreSQL (Drizzle ORM) | Drizzle ORM, Redis (ioredis), JWT (jose), OTel, Swagger |
| **scraper** | _(submodule)_ | — | — | — |
### Frontend
| Service | Framework | Build Tool | Key Libraries |
| --------- | --------- | ---------- | --------------------------------------------------------------------------------------------------- |
| **react** | React 19 | Vite 7 | TanStack Router + Query, Three.js/React Three Fiber, Tailwind CSS 4, Zustand, Recharts, tsParticles |
| Service | Language/Runtime | Framework | Database | Key Libraries |
| --------- | ---------------- | --------- | -------- | ------------- |
| **scraper** | _(submodule)_ | — | — | — |
### Infrastructure
@@ -90,7 +79,7 @@ Shared services:
Service compose files are combined during deployment:
```bash
docker compose -f traefik.yml -f shared.yml -f elysia.yml -f react.yml ... up -d
docker compose -f traefik.yml -f shared.yml -f scraper.yml up -d
```
### Tailscale Networking
Submodule apps/elysia deleted from b8f4b5806e
Submodule apps/react deleted from 124d2f88bd
Submodule apps/rust-auth deleted from 6e695f07e8
+1 -8
View File
@@ -9,10 +9,7 @@ infra/
├── compose/ # One compose file per stack/service
│ ├── traefik.yml # Public reverse proxy
│ ├── shared.yml # Shared Redis
── react.yml # React SPA
│ ├── scraper.yml # Scraper API
│ ├── elysia.yml # Elysia API
│ └── rust-auth.yml # Rust auth API
── scraper.yml # Scraper API
├── docker/ # Dockerfiles and image runtime helpers
├── traefik/ # Static and dynamic Traefik configuration
│ ├── dynamic/ # Routers, services, middlewares, TLS certs
@@ -41,10 +38,7 @@ docker compose -f infra/compose/shared.yml up -d
docker compose -f infra/compose/traefik.yml up -d
docker compose \
-f infra/compose/react.yml \
-f infra/compose/scraper.yml \
-f infra/compose/elysia.yml \
-f infra/compose/rust-auth.yml \
up -d
```
@@ -55,7 +49,6 @@ Common variables used by infra compose files:
```env
DATABASE_URL=
GITHUB_TOKEN=
JWT_SECRET=
SHARED_REDIS_EXPOSE=127.0.0.1:6379:6379
```
-24
View File
@@ -1,24 +0,0 @@
services:
elysia-api:
container_name: elysia-api
image: ghcr.io/asepharyana/asepharyana-hub/elysia-api:sha-fe998aa
restart: always
networks:
app-shared-net:
aliases:
- elysia-api
env_file:
- ../../.env
environment:
- REDIS_URL=redis://redis:6379
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET is required}
- DATABASE_URL=${DATABASE_URL}
- GITHUB_TOKEN=${GITHUB_TOKEN}
- PORT=4092
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otlp-metrics-backend:4317
- OTEL_SERVICE_NAME=elysia-api
networks:
app-shared-net:
name: app-shared-net
external: true
-13
View File
@@ -1,13 +0,0 @@
services:
react-web:
container_name: react-web
image: ghcr.io/asepharyana/asepharyana-hub/react-web:sha-124223c
restart: always
networks: [app-shared-net]
environment:
- VITE_API_URL=https://scraper.asepharyana.my.id/api
- VITE_ELYSIA_URL=https://elysia.asepharyana.my.id
networks:
app-shared-net:
name: app-shared-net
external: true
-20
View File
@@ -1,20 +0,0 @@
services:
rust-auth:
container_name: rust-auth-api
image: ghcr.io/asepharyana/asepharyana-hub/rust-auth:sha-b199f8c
restart: always
networks:
app-shared-net:
aliases:
- rust-auth
env_file:
- ../../.env
environment:
- PORT=3000
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otlp-metrics-backend:4317
- OTEL_SERVICE_NAME=rust-auth
networks:
app-shared-net:
name: app-shared-net
external: true
-26
View File
@@ -1,26 +0,0 @@
# build stage
FROM oven/bun:1-alpine AS builder
WORKDIR /app
# install dependencies with cache mounts
COPY apps/elysia/package.json apps/elysia/bun.lock ./
RUN --mount=type=cache,target=/root/.bun/install/cache \
bun install --frozen-lockfile
# build the application
COPY apps/elysia ./
RUN bun run build
# runtime stage
FROM oven/bun:1-distroless
WORKDIR /app
# copy build artifacts
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
# distroless uses nonroot user (UID 65532) by default, or we can use it
USER nonroot
EXPOSE 4092
CMD ["run", "dist/index.js"]
-77
View File
@@ -1,77 +0,0 @@
import { existsSync, readFileSync } from 'node:fs';
import { resolve, sep } from 'node:path';
const distDir = resolve('./dist');
const indexPath = resolve(distDir, 'index.html');
const contentTypes = {
html: 'text/html; charset=utf-8',
css: 'text/css; charset=utf-8',
js: 'application/javascript; charset=utf-8',
json: 'application/json; charset=utf-8',
svg: 'image/svg+xml',
png: 'image/png',
jpg: 'image/jpeg',
jpeg: 'image/jpeg',
gif: 'image/gif',
webp: 'image/webp',
ico: 'image/x-icon',
woff: 'font/woff',
woff2: 'font/woff2',
ttf: 'font/ttf',
};
function responseFromFile(filePath, headers) {
try {
return new Response(readFileSync(filePath), { headers });
} catch (error) {
if (error?.code === 'ENOENT') {
return new Response('Not Found', { status: 404 });
}
console.error('File read error:', error);
return new Response('Internal Server Error', { status: 500 });
}
}
function serveIndex() {
return responseFromFile(indexPath, {
'Content-Type': contentTypes.html,
'Cache-Control': 'no-cache',
});
}
function serveFile(filePath, pathname) {
const ext = filePath.split('.').pop() || '';
return responseFromFile(filePath, {
'Content-Type': contentTypes[ext] || 'application/octet-stream',
'Cache-Control': pathname.startsWith('/assets/')
? 'public, max-age=31536000, immutable'
: 'no-cache',
});
}
Bun.serve({
port: 80,
hostname: '0.0.0.0',
fetch(req) {
const url = new URL(req.url);
const pathname = url.pathname;
const filePath = resolve(distDir, pathname.slice(1));
const insideDist = filePath === distDir || filePath.startsWith(`${distDir}${sep}`);
if (!insideDist) {
return new Response('Forbidden', { status: 403 });
}
if (pathname !== '/' && existsSync(filePath)) {
return serveFile(filePath, pathname);
}
if (!pathname.includes('.') && existsSync(indexPath)) {
return serveIndex();
}
return new Response('Not Found', { status: 404 });
},
});
-16
View File
@@ -1,16 +0,0 @@
# ─── Stage 1: Build ─────────────────────────────────────────────────────────
FROM oven/bun:1 AS builder
WORKDIR /app
COPY apps/react/package.json apps/react/bun.lock ./
RUN bun install --frozen-lockfile
COPY apps/react .
RUN bun run build
# ─── Stage 2: Runtime (Bun static server) ──────────────────────────────────
FROM oven/bun:1-alpine
WORKDIR /app
COPY infra/docker/react-server.js ./server.js
COPY --from=builder /app/dist ./dist
EXPOSE 80
CMD ["bun", "server.js"]
-42
View File
@@ -1,42 +0,0 @@
# Use cargo-chef for dependency caching
FROM lukemathwalker/cargo-chef:latest-rust-1.89.0 AS chef
WORKDIR /app
FROM chef AS planner
COPY apps/rust-auth .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
# Utilize buildkit cache mounts for cargo
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/app/target \
cargo chef cook --release --recipe-path recipe.json
# Build application
COPY apps/rust-auth .
RUN --mount=type=cache,target=/usr/local/cargo/registry \
--mount=type=cache,target=/app/target \
cargo build --release && \
cp target/release/rust-auth /app/rust-auth
# Final runtime image
FROM debian:bookworm-slim AS runtime
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
libssl3 \
&& rm -rf /var/lib/apt/lists/*
# Add non-root user
RUN groupadd -g 1001 appgroup && \
useradd -u 1001 -g appgroup -s /bin/sh appuser
WORKDIR /app
COPY --from=builder /app/rust-auth /app/rust-auth
# Run as non-root
USER appuser
EXPOSE 3000
CMD ["./rust-auth"]
-40
View File
@@ -1,13 +1,5 @@
http:
routers:
# ── React SPA (domain root) ──
react:
rule: 'Host(`asepharyana.my.id`) || Host(`asepharyana.web.id`)'
entryPoints:
- websecure
tls: {}
service: react-service
# ── Scraper API ──
scraper:
rule: 'Host(`scraper.asepharyana.my.id`) || Host(`api.asepharyana.my.id`) || Host(`scraper.asepharyana.web.id`) || Host(`api.asepharyana.web.id`)'
@@ -18,40 +10,8 @@ http:
- common-chain@file
service: scraper-service
# ── Elysia API ──
elysia:
rule: 'Host(`elysia.asepharyana.my.id`) || Host(`elysia.asepharyana.web.id`)'
entryPoints:
- websecure
tls: {}
middlewares:
- common-chain@file
service: elysia-service
# ── Rust Auth API ──
rust-auth:
rule: 'Host(`auth.asepharyana.my.id`) || Host(`auth.asepharyana.web.id`)'
entryPoints:
- websecure
tls: {}
middlewares:
- common-chain@file
service: rust-auth-service
services:
react-service:
loadBalancer:
servers:
- url: 'http://react-web:80'
scraper-service:
loadBalancer:
servers:
- url: 'http://scraper-api:4091'
elysia-service:
loadBalancer:
servers:
- url: 'http://elysia-api:4092'
rust-auth-service:
loadBalancer:
servers:
- url: 'http://rust-auth:3000'