Add persistent multi-user sessions and Docker deployment
This commit is contained in:
parent
51a6e845d1
commit
104577c826
24 changed files with 2094 additions and 468 deletions
95
DEPLOYMENT.md
Normal file
95
DEPLOYMENT.md
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
# Docker Deployment
|
||||
|
||||
The production image builds the Vue frontend with Node 22, installs the Python runtime dependencies into the official Python 3.14 slim image, and runs Uvicorn as UID/GID `10001` with one worker. Application data is stored in the `translator-data` named volume at `/app/data`.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine with the Compose plugin
|
||||
- `config/llms.json` containing the production LLM endpoints and credentials
|
||||
- Bootstrap administrator environment variables for a new Docker volume
|
||||
|
||||
The configuration files are not copied into the image or build context. Compose mounts them read-only. Docker uses the empty `config/users.docker.json`, so the repository's documented local development account is never imported into a production volume.
|
||||
|
||||
## Environment
|
||||
|
||||
Create a deployment `.env` beside `compose.yml`. Compose reads this file for variable substitution; it is excluded from Git and the Docker build context.
|
||||
|
||||
Minimal example using the persistent JWT secret generated in `/app/data`:
|
||||
|
||||
```dotenv
|
||||
APP_PORT=8000
|
||||
JWT_EXPIRE_HOURS=24
|
||||
LLM_TIMEOUT_SECONDS=180
|
||||
TRANSLATION_CHUNK_CHARS=1500
|
||||
```
|
||||
|
||||
Before the first startup of a new volume, add deployment-specific bootstrap credentials:
|
||||
|
||||
```dotenv
|
||||
BOOTSTRAP_ADMIN_ID=admin
|
||||
BOOTSTRAP_ADMIN_PASSWORD=replace-with-a-long-random-password
|
||||
```
|
||||
|
||||
The bootstrap variables are only used when the database contains no users. Remove them from `.env` after the first successful startup and recreate the container with `docker compose up -d --force-recreate`.
|
||||
|
||||
By default, the application creates `/app/data/.jwt-secret` with mode `0600`. Because the data directory is a named volume, tokens remain valid across container replacement. To manage the secret externally instead, set a stable random value:
|
||||
|
||||
```dotenv
|
||||
JWT_SECRET_KEY=replace-with-at-least-48-random-bytes
|
||||
```
|
||||
|
||||
Do not rotate `JWT_SECRET_KEY` unintentionally; rotation invalidates existing login tokens. Generate values with a secrets manager or a command such as `openssl rand -base64 48`, and do not commit the resulting `.env`.
|
||||
|
||||
## Configuration
|
||||
|
||||
`config/llms.json` is required and readiness fails when it contains no model definitions. It may contain API keys, so limit host access while ensuring UID `10001` in the container can read the bind-mounted file. Compose imports the empty `config/users.docker.json` once and creates the first administrator from bootstrap variables. Later user administration is stored in SQLite. A custom legacy file containing `password_plain` must be migrated once outside the read-only container so the plaintext can be removed.
|
||||
|
||||
The container receives these fixed paths:
|
||||
|
||||
```text
|
||||
DATABASE_PATH=/app/data/translator.db
|
||||
JWT_SECRET_FILE=/app/data/.jwt-secret
|
||||
LLMS_CONFIG_PATH=/app/config/llms.json
|
||||
USERS_CONFIG_PATH=/app/config/users.json
|
||||
```
|
||||
|
||||
## Start And Verify
|
||||
|
||||
Build and start the service:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
docker compose ps
|
||||
docker compose logs -f translator
|
||||
```
|
||||
|
||||
The service is available at `http://localhost:${APP_PORT:-8000}`. Docker checks `GET /api/health/ready` every 30 seconds. This readiness check validates SQLite access and that at least one LLM configuration loaded; it does not contact the remote LLM endpoint.
|
||||
|
||||
To test readiness directly:
|
||||
|
||||
```bash
|
||||
curl --fail http://localhost:8000/api/health/ready
|
||||
```
|
||||
|
||||
## Operations
|
||||
|
||||
Deploy an updated image with:
|
||||
|
||||
```bash
|
||||
docker compose build --pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Stop without deleting persistent data:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
Do not add `--volumes` unless the database and generated JWT secret should be permanently removed. Compose allows 190 seconds for shutdown, while Uvicorn allows in-flight requests up to 180 seconds before forcing shutdown.
|
||||
|
||||
Back up the named volume before upgrades. For a consistent simple backup, stop the service first and copy the volume contents with your standard Docker volume backup tooling. The volume contains the SQLite database, WAL files when present, and the generated JWT secret.
|
||||
|
||||
## Reverse Proxy
|
||||
|
||||
Terminate TLS in a reverse proxy and forward traffic to port `8000`. Preserve the same origin for the frontend and `/api` routes. Do not expose the LLM configuration files, data volume, or Docker socket through the proxy.
|
||||
Loading…
Add table
Add a link
Reference in a new issue