Updated configurations for deployment
This commit is contained in:
parent
81a1ac85af
commit
7b30f17065
9 changed files with 396 additions and 214 deletions
288
faceai/README.md
288
faceai/README.md
|
|
@ -5,7 +5,8 @@ This folder scaffolds the new FaceAI app described in the integration plan.
|
|||
It includes:
|
||||
|
||||
- a Vue frontend for the FaceAI upload and polling flow
|
||||
- a Node/Express backend for session exchange, mocked searches, and return handoff
|
||||
- a Node/Express backend for session exchange, queueing, and return handoff
|
||||
- a dedicated processor runner that consumes matcher jobs from Redis and executes `face_matcher`
|
||||
- a local legacy simulator so the launch and return flow can be tested without the old Java site
|
||||
- a Dockerized PHP Apache stack for exercising the real `www/faceai_handoff.php` and `www/faceai_return.php` bridge files
|
||||
|
||||
|
|
@ -16,64 +17,91 @@ faceai/
|
|||
apps/
|
||||
backend/
|
||||
frontend/
|
||||
processor/
|
||||
docker/
|
||||
Dockerfile
|
||||
```
|
||||
|
||||
## What The Local Test Covers
|
||||
## Runtime Topology
|
||||
|
||||
The scaffold currently expects four runtime roles:
|
||||
|
||||
- `faceai`: public HTTP service on port `3001`, serving the built Vue app and the authenticated API
|
||||
- `processor`: background matcher runner consuming BullMQ jobs from Redis and executing the Linux `face_matcher` binary
|
||||
- `redis`: short-lived queue and search-state store
|
||||
- `legacy-php`: local-only PHP Apache simulator for exercising the real bridge files under `www/`
|
||||
|
||||
For hosted deployment, the long-lived application topology is `faceai` + `processor` + `redis`. The PHP simulator stays local-only and the real legacy site remains on its existing stack.
|
||||
|
||||
## What The End-To-End Local Test Covers
|
||||
|
||||
The local simulator exercises the exact flow the plan is aiming for:
|
||||
|
||||
1. a legacy-like race page shows a `Face ID` button instead of `tipoPuntoFoto`
|
||||
2. clicking it hits a mock legacy handoff endpoint
|
||||
1. a legacy-like race page loads the original `www/_js/rus-ecom-240621.js` script and shows a `Face ID` button instead of `tipoPuntoFoto`
|
||||
2. clicking it hits the real PHP handoff bridge at `www/faceai_handoff.php`
|
||||
3. the backend signs a short-lived handoff token and redirects to the Vue app
|
||||
4. the Vue app exchanges the token for its own FaceAI session cookie
|
||||
5. the user uploads a selfie and starts a mocked race-scoped search
|
||||
5. the user uploads a selfie and starts a Redis-backed race-scoped search
|
||||
6. the frontend polls until the job completes
|
||||
7. FaceAI requests a signed return URL
|
||||
8. the browser is redirected back to a legacy-like filtered race page showing only the matched photos
|
||||
8. the browser is redirected back to the real PHP return bridge at `www/faceai_return.php`
|
||||
9. the PHP bridge fetches the signed result from FaceAI and renders a filtered legacy-like race page
|
||||
|
||||
## Local Run
|
||||
## Local Testing With The Legacy PHP Simulator
|
||||
|
||||
This is the recommended local test path because it exercises the public site, the processor, Redis, and the real PHP bridge files together.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker Desktop or another Docker Engine with Compose support
|
||||
- local npm dependencies installed in this `faceai/` workspace
|
||||
|
||||
### Start The Stack
|
||||
|
||||
From this folder:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Then open:
|
||||
|
||||
```text
|
||||
http://localhost:3001/dev/legacy/race?raceId=101&lang=it
|
||||
```
|
||||
|
||||
That page simulates the old site and launches the FaceAI app at `http://localhost:5173`.
|
||||
|
||||
## Docker Run With PHP Simulator
|
||||
|
||||
If you do not have PHP locally, use Docker instead:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run build
|
||||
docker compose up --build
|
||||
```
|
||||
|
||||
The Docker stack reuses the local FaceAI workspace and only containerizes the runtime services. That means PHP is fully containerized, while the Node service runs inside Docker against the already-installed local workspace dependencies and the already-built frontend assets.
|
||||
The checked-in `docker-compose.yml` starts:
|
||||
|
||||
This starts:
|
||||
- FaceAI public site on `http://localhost:3001`
|
||||
- processor runner on the internal Compose network
|
||||
- Redis on the internal Compose network
|
||||
- PHP Apache serving `../www` on `http://localhost:8080`
|
||||
|
||||
- FaceAI app on `http://localhost:3001`
|
||||
- PHP Apache serving `www` on `http://localhost:8080`
|
||||
The local stack also mounts:
|
||||
|
||||
For the end-to-end test through the PHP bridge, open:
|
||||
- `../bin/Face_Recognition_Unix` into the processor container as the matcher binary source
|
||||
- `../test_pkl` into the processor container as fallback PKL test data
|
||||
- `../www` into the PHP container so the real bridge files are used
|
||||
|
||||
### Run The Browser Test
|
||||
|
||||
Open:
|
||||
|
||||
```text
|
||||
http://localhost:8080/faceai_simulator.php?raceId=101&lang=it
|
||||
```
|
||||
|
||||
That page loads the original race-page JavaScript from `www/_js/rus-ecom-240621.js`, lets the script replace the visible `tipoPuntoFoto` selector with the new `Face ID` button, and launches the real PHP handoff bridge at `www/faceai_handoff.php`.
|
||||
That page simulates the legacy race page, loads the original race-page JavaScript from `www/_js/rus-ecom-240621.js`, lets the script replace the visible `tipoPuntoFoto` selector with the new `Face ID` button, and launches the real PHP handoff bridge at `www/faceai_handoff.php`.
|
||||
|
||||
### Expected Local Flow
|
||||
|
||||
Use the page above and verify this sequence:
|
||||
|
||||
1. the simulator page renders on port `8080`
|
||||
2. the visible checkpoint selector is replaced with the `Face ID` launch button
|
||||
3. clicking `Face ID` redirects through `faceai_handoff.php` into `http://localhost:3001/auth/callback?token=...`
|
||||
4. the FaceAI app establishes its session and loads the upload flow
|
||||
5. uploading a selfie creates a queued search that the processor picks up
|
||||
6. when polling completes, FaceAI redirects back to `http://localhost:8080/faceai_return.php?...`
|
||||
7. the PHP return page renders the filtered photo list from the FaceAI result payload
|
||||
|
||||
### Rebuild Notes
|
||||
|
||||
If you change frontend code and want Docker to serve the updated UI, rebuild first with:
|
||||
|
||||
|
|
@ -81,62 +109,38 @@ If you change frontend code and want Docker to serve the updated UI, rebuild fir
|
|||
npm run build
|
||||
```
|
||||
|
||||
## Production Deployment From Registry
|
||||
If you want to stop and remove the local containers afterward, run:
|
||||
|
||||
The published container is the user-facing FaceAI site only. It already contains:
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
- the Node/Express backend
|
||||
- the built Vue frontend assets served by that backend
|
||||
## Optional Backend And Frontend Dev Loop
|
||||
|
||||
It does not include:
|
||||
If you only want to iterate on the app without the PHP simulator, you can still run the public site and the processor separately. The queue-backed flow now requires Redis and the processor, so `npm run dev` alone is no longer the full stack.
|
||||
|
||||
- the legacy PHP simulator
|
||||
- the existing `www` site
|
||||
- the future queue/processor worker
|
||||
One workable loop is:
|
||||
|
||||
In production, deploy a single FaceAI container behind HTTPS on its own host name, for example `faceai.regalamiunsorriso.it`, and keep the legacy site on its existing stack.
|
||||
```bash
|
||||
npm install
|
||||
docker compose up redis -d
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### What The Production Container Exposes
|
||||
Then start the processor in a second shell, either with its own local environment or by keeping the Compose-managed processor service running.
|
||||
|
||||
- HTTP service on port `3001` inside the container
|
||||
- health endpoint at `/health`
|
||||
- frontend and API from the same process
|
||||
## Docker Compose Deployment For The Public Site And Matcher Runner
|
||||
|
||||
The image should be run with a reverse proxy or ingress that terminates TLS and forwards traffic to the container.
|
||||
The checked-in `docker-compose.yml` is for local integration testing because it also includes the PHP simulator and local bind mounts. For hosted deployment, keep the same three-service application topology but remove `legacy-php` and replace the local mounts with your production matcher and PKL paths.
|
||||
|
||||
### Required Runtime Configuration
|
||||
The public FaceAI site and the matcher runner can both use the same application image. The difference is only the process command:
|
||||
|
||||
Set these environment variables for production:
|
||||
- `npm run start` for the public site
|
||||
- `npm run start:processor` for the matcher runner
|
||||
|
||||
| Variable | Required | Example | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `NODE_ENV` | yes | `production` | disables development defaults |
|
||||
| `PORT` | optional | `3001` | internal listen port |
|
||||
| `FACEAI_FRONTEND_URL` | yes | `https://faceai.regalamiunsorriso.it` | URL used when the legacy bridge redirects into the app |
|
||||
| `FACEAI_PUBLIC_BASE_URL` | yes | `https://faceai.regalamiunsorriso.it` | public base URL used for local links and return flow generation |
|
||||
| `FACEAI_LEGACY_RETURN_URL` | yes | `https://www.regalamiunsorriso.it/faceai_return.php` | legacy endpoint that receives the signed FaceAI result handoff |
|
||||
| `FACEAI_SHARED_SECRET` | yes | long random secret | shared signing secret between FaceAI and the legacy handoff/return bridge |
|
||||
| `FACEAI_SESSION_COOKIE` | optional | `rus_faceai_session` | cookie name for the FaceAI session |
|
||||
| `FACEAI_ENABLE_LOCAL_LEGACY_STATIC` | recommended | `0` | disables development-only static serving of local legacy assets |
|
||||
### Production Compose Example
|
||||
|
||||
Do not enable `FACEAI_ENABLE_LOCAL_LEGACY_STATIC` in production. That mode exists only for local simulator flows.
|
||||
|
||||
### Legacy-Side Configuration That Must Match
|
||||
|
||||
The container will not work correctly in production unless the legacy bridge is configured consistently.
|
||||
|
||||
The legacy site must:
|
||||
|
||||
- redirect users into `FACEAI_FRONTEND_URL` with a valid signed handoff token
|
||||
- use the same `FACEAI_SHARED_SECRET` as the FaceAI container
|
||||
- expose the configured `FACEAI_LEGACY_RETURN_URL`
|
||||
- validate the signed return token and fetch the result payload from FaceAI
|
||||
|
||||
The shared secret is the trust boundary between the legacy site and FaceAI. Treat it like any other production secret and inject it through the platform secret store, not through source control.
|
||||
|
||||
### Example Docker Compose For Production
|
||||
|
||||
Replace the registry path and secret values with the real ones from Forgejo.
|
||||
Replace the registry path, secrets, and host paths with the real deployment values.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
|
|
@ -147,35 +151,104 @@ services:
|
|||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: 3001
|
||||
FACEAI_FRONTEND_URL: https://faceai.regalamiunsorriso.it
|
||||
FACEAI_PUBLIC_BASE_URL: https://faceai.regalamiunsorriso.it
|
||||
FACEAI_FRONTEND_URL: https://ai.regalamiunsorriso.it
|
||||
FACEAI_PUBLIC_BASE_URL: https://ai.regalamiunsorriso.it
|
||||
FACEAI_LEGACY_RETURN_URL: https://www.regalamiunsorriso.it/faceai_return.php
|
||||
FACEAI_SHARED_SECRET: change-this-to-a-long-random-secret
|
||||
FACEAI_SESSION_COOKIE: rus_faceai_session
|
||||
FACEAI_REDIS_URL: redis://redis:6379
|
||||
FACEAI_QUEUE_NAME: faceai-searches
|
||||
FACEAI_RUNTIME_ROOT: /data/runtime
|
||||
FACEAI_UPLOAD_ROOT: /data/runtime/uploads
|
||||
FACEAI_ENABLE_LOCAL_LEGACY_STATIC: 0
|
||||
volumes:
|
||||
- faceai-runtime:/data/runtime
|
||||
ports:
|
||||
- "127.0.0.1:3001:3001"
|
||||
depends_on:
|
||||
- redis
|
||||
|
||||
processor:
|
||||
image: registry.example.com/my-namespace/faceai:latest
|
||||
container_name: regalami-faceai-processor
|
||||
restart: unless-stopped
|
||||
command: npm run start:processor
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
FACEAI_REDIS_URL: redis://redis:6379
|
||||
FACEAI_QUEUE_NAME: faceai-searches
|
||||
FACEAI_RUNTIME_ROOT: /data/runtime
|
||||
FACEAI_PKL_ROOT: /data/pkl
|
||||
FACEAI_MATCHER_BINARY: /opt/face-recognition/face_matcher
|
||||
FACEAI_WORKER_CONCURRENCY: 2
|
||||
FACEAI_WORKER_TIMEOUT_MS: 300000
|
||||
volumes:
|
||||
- faceai-runtime:/data/runtime
|
||||
- /srv/faceai/pkl:/data/pkl:ro
|
||||
- /srv/faceai/bin/Face_Recognition_Unix:/opt/face-recognition:ro
|
||||
depends_on:
|
||||
- redis
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: regalami-faceai-redis
|
||||
restart: unless-stopped
|
||||
command: redis-server --appendonly no
|
||||
|
||||
volumes:
|
||||
faceai-runtime:
|
||||
```
|
||||
|
||||
This pattern assumes a reverse proxy on the host publishes `https://faceai.regalamiunsorriso.it` and forwards to `127.0.0.1:3001`.
|
||||
This pattern assumes a reverse proxy on the host publishes `https://ai.regalamiunsorriso.it` and forwards to `127.0.0.1:3001`. The processor is internal-only and does not expose any public port.
|
||||
|
||||
### Example Docker Run
|
||||
### Required Runtime Configuration
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name regalami-faceai \
|
||||
--restart unless-stopped \
|
||||
-p 127.0.0.1:3001:3001 \
|
||||
-e NODE_ENV=production \
|
||||
-e PORT=3001 \
|
||||
-e FACEAI_FRONTEND_URL=https://faceai.regalamiunsorriso.it \
|
||||
-e FACEAI_PUBLIC_BASE_URL=https://faceai.regalamiunsorriso.it \
|
||||
-e FACEAI_LEGACY_RETURN_URL=https://www.regalamiunsorriso.it/faceai_return.php \
|
||||
-e FACEAI_SHARED_SECRET=change-this-to-a-long-random-secret \
|
||||
-e FACEAI_SESSION_COOKIE=rus_faceai_session \
|
||||
-e FACEAI_ENABLE_LOCAL_LEGACY_STATIC=0 \
|
||||
registry.example.com/my-namespace/faceai:latest
|
||||
```
|
||||
Shared application settings:
|
||||
|
||||
| Variable | Required | Example | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `NODE_ENV` | yes | `production` | disables development defaults |
|
||||
| `FACEAI_REDIS_URL` | yes | `redis://redis:6379` | queue and search-state backend |
|
||||
| `FACEAI_QUEUE_NAME` | optional | `faceai-searches` | BullMQ queue name |
|
||||
| `FACEAI_RUNTIME_ROOT` | yes | `/data/runtime` | shared writable runtime root between site and processor |
|
||||
| `FACEAI_SHARED_SECRET` | yes | long random secret | trust boundary between FaceAI and the legacy bridge |
|
||||
|
||||
Public site settings:
|
||||
|
||||
| Variable | Required | Example | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `PORT` | optional | `3001` | internal listen port |
|
||||
| `FACEAI_FRONTEND_URL` | yes | `https://ai.regalamiunsorriso.it` | URL used when the legacy bridge redirects into the app |
|
||||
| `FACEAI_PUBLIC_BASE_URL` | yes | `https://ai.regalamiunsorriso.it` | public base URL used for local links and return flow generation |
|
||||
| `FACEAI_LEGACY_RETURN_URL` | yes | `https://www.regalamiunsorriso.it/faceai_return.php` | legacy endpoint that receives the signed FaceAI result handoff |
|
||||
| `FACEAI_SESSION_COOKIE` | optional | `rus_faceai_session` | cookie name for the FaceAI session |
|
||||
| `FACEAI_UPLOAD_ROOT` | optional | `/data/runtime/uploads` | upload directory inside the shared runtime volume |
|
||||
| `FACEAI_ENABLE_LOCAL_LEGACY_STATIC` | recommended | `0` | disables development-only static serving of local legacy assets |
|
||||
|
||||
Processor settings:
|
||||
|
||||
| Variable | Required | Example | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `FACEAI_PKL_ROOT` | yes | `/data/pkl` | mounted race-to-PKL dataset root |
|
||||
| `FACEAI_TEST_PKL_ROOT` | optional | `/data/pkl/test` | local-only fallback PKL location |
|
||||
| `FACEAI_MATCHER_BINARY` | yes | `/opt/face-recognition/face_matcher` | matcher executable inside the processor container |
|
||||
| `FACEAI_WORKER_CONCURRENCY` | optional | `2` | BullMQ worker concurrency |
|
||||
| `FACEAI_WORKER_TIMEOUT_MS` | optional | `300000` | matcher timeout in milliseconds |
|
||||
|
||||
Do not enable `FACEAI_ENABLE_LOCAL_LEGACY_STATIC` in production. That mode exists only for local simulator flows.
|
||||
|
||||
### Legacy-Side Configuration That Must Match
|
||||
|
||||
The deployment will not work correctly unless the legacy bridge is configured consistently.
|
||||
|
||||
The legacy site must:
|
||||
|
||||
- redirect users into `FACEAI_FRONTEND_URL` with a valid signed handoff token
|
||||
- use the same `FACEAI_SHARED_SECRET` as the FaceAI deployment
|
||||
- expose the configured `FACEAI_LEGACY_RETURN_URL`
|
||||
- validate the signed return token and fetch the result payload from FaceAI
|
||||
|
||||
The shared secret is the trust boundary between the legacy site and FaceAI. Treat it like any other production secret and inject it through the platform secret store, not through source control.
|
||||
|
||||
### Reverse Proxy Expectations
|
||||
|
||||
|
|
@ -188,25 +261,27 @@ The app should sit behind HTTPS. In practice that means:
|
|||
|
||||
### Post-Deploy Validation
|
||||
|
||||
After the container is up, validate at least the following:
|
||||
After the Compose stack is up, validate at least the following:
|
||||
|
||||
1. `GET /health` returns `{"ok":true}` through the public FaceAI host.
|
||||
2. The legacy handoff endpoint redirects to `https://faceai.../auth/callback?token=...`.
|
||||
3. FaceAI can exchange the token and establish a session.
|
||||
4. Completing a search produces a redirect URL that points to `FACEAI_LEGACY_RETURN_URL`.
|
||||
5. The legacy return endpoint can resolve the signed result and render the filtered race page.
|
||||
4. A search is enqueued in Redis and picked up by the processor.
|
||||
5. Completing a search produces a redirect URL that points to `FACEAI_LEGACY_RETURN_URL`.
|
||||
6. The legacy return endpoint can resolve the signed result and render the filtered race page.
|
||||
|
||||
### Current Production Limitations
|
||||
|
||||
This image can be published and deployed, but the current scaffold still has important limitations:
|
||||
This scaffold can now be deployed with the public site, processor, and Redis, but it still has important limitations:
|
||||
|
||||
- sessions and search results are stored only in memory, so container restarts lose state
|
||||
- there is no real queue or processor yet
|
||||
- there is no persistent storage layer yet
|
||||
- search state is short-lived in Redis and is not backed by a durable database
|
||||
- runtime uploads and matcher output still need an agreed production retention and cleanup policy
|
||||
- the final production PKL/NAS layout is not yet locked down
|
||||
- the backend currently sets the FaceAI session cookie with `secure: false`, which should be hardened before final public rollout
|
||||
- the local simulator endpoints under `/dev/*` are still present in the app and should be treated as non-production scaffolding
|
||||
- the processor CSV parser is still based on the current scaffolded matcher output assumptions
|
||||
|
||||
So the registry deployment is appropriate for early hosted integration and controlled production-like rollout, but not yet for the final hardened architecture described in the integration plan
|
||||
So the Compose deployment is appropriate for hosted integration and controlled production-like rollout, but not yet for the final hardened architecture described in the integration plan.
|
||||
|
||||
## Environment
|
||||
|
||||
|
|
@ -219,6 +294,13 @@ FACEAI_PUBLIC_BASE_URL=http://localhost:3001
|
|||
FACEAI_LEGACY_RETURN_URL=http://localhost:3001/dev/legacy/return
|
||||
FACEAI_SHARED_SECRET=change-me
|
||||
FACEAI_SESSION_COOKIE=rus_faceai_session
|
||||
FACEAI_REDIS_URL=redis://redis:6379
|
||||
FACEAI_QUEUE_NAME=faceai-searches
|
||||
FACEAI_RUNTIME_ROOT=/data/runtime
|
||||
FACEAI_UPLOAD_ROOT=/data/runtime/uploads
|
||||
FACEAI_PKL_ROOT=/data/pkl
|
||||
FACEAI_TEST_PKL_ROOT=/data/pkl/test
|
||||
FACEAI_MATCHER_BINARY=/opt/face-recognition/face_matcher
|
||||
```
|
||||
|
||||
If you want FaceAI to return through the new PHP bridge prepared under `www`, point `FACEAI_LEGACY_RETURN_URL` to that endpoint instead, for example `http://localhost/faceai_return.php` or the equivalent URL in your local PHP setup.
|
||||
|
|
@ -231,8 +313,8 @@ FACEAI_LEGACY_RETURN_URL=http://localhost:8080/faceai_return.php
|
|||
|
||||
## Notes
|
||||
|
||||
- The backend currently uses in-memory stores and mocked search results.
|
||||
- No database or real queue is wired yet.
|
||||
- Search orchestration now uses Redis and a dedicated processor worker.
|
||||
- The checked-in Compose file is meant for local integration testing, not as-is production use.
|
||||
- The local legacy simulator is intentionally backend-driven so the handoff can be tested without compiling the existing Java application.
|
||||
- `www/faceai_simulator.php` exists only for local testing. It does not replace the actual JSP race page.
|
||||
- The final legacy integration still needs a real signed identity source and a real return-filter implementation on the old site.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ WORKDIR /app
|
|||
COPY package.json ./
|
||||
COPY apps/frontend/package.json apps/frontend/package.json
|
||||
COPY apps/backend/package.json apps/backend/package.json
|
||||
COPY apps/processor/package.json apps/processor/package.json
|
||||
|
||||
RUN npm install
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue