One image for the whole app: engine, API and dashboard on one port

The backend image now builds the SPA and serves it on the API's own origin
(fluksio/spa.py), so an instance is a single container with no proxy, DNS,
port 80 or .env: `docker compose up -d` with the new compose.yml runs it on
localhost:8080. It starts on fluksio serve (persisted secret key, first
admin printed once) and brings its own Redis when REDIS_HOST is unset.

Slimmer: python:3.13-slim, no dev group, uv once, fastapi without the cloud
CLI. Optional features are per-feature extras (mqtt, influx, email, sentry,
ml, server for all) picked with the EXTRAS build argument; numpy moved to
`ml`. ffmpeg left the image for imageio-ffmpeg via the Modules screen.

The operator stack runs the same image with app. and api. routed to it; the
nginx frontend service, the LAN nginx proxy and DOMAIN in the backend are
gone, and the MCP issuer is FRONTEND_HOST.
This commit is contained in:
2026-10-16 11:40:02 +02:00
parent 9d9dac0bd0
commit dea25ec08d
39 changed files with 573 additions and 728 deletions
+7 -4
View File
@@ -5,13 +5,16 @@ and run flows with the permissions of the user who authorizes it.
## Connect an agent
Set `MCP_ENABLED=true` in the engine's environment and restart it. The Python
package defaults to off; the Docker template enables it.
Set `MCP_ENABLED=true` in the engine's environment and restart it, under
`environment` in `compose.yml` for the Docker container. It defaults to off.
Configure your MCP client with an HTTP endpoint:
- Local Docker stack: `http://api.localhost/mcp`
- Deployment: `https://api.<your-domain>/mcp`
- Docker container: `http://localhost:8080/mcp`
- Deployment: `https://<your-domain>/mcp`
The endpoint has to be the address in `FRONTEND_HOST`, which is also the
issuer of the client's tokens.
The client registers, opens browser authorization, and receives an OAuth
token after you approve access. The issuer and browser redirects use
+2 -2
View File
@@ -10,8 +10,8 @@ export FLUKSIO=http://127.0.0.1:8000/api/v1
```
Use the port printed by `fluksio serve`. For Docker, use
`http://api.localhost/api/v1`, `http://<host-ip>:8080/api/v1` on a LAN stack,
or `https://api.<your-domain>/api/v1` for a deployment.
`http://localhost:8080/api/v1`, or `https://<your-domain>/api/v1` for a
deployment.
All paths below are relative to this base. Timestamps in responses are
ISO 8601 and always carry their UTC offset.
+5 -4
View File
@@ -11,8 +11,9 @@ For the browser dashboard, sign up at [fluksio.com](https://fluksio.com), add
an instance, then run `fluksio enroll <code>` in the same directory.
Use `fluksio --help` or `fluksio COMMAND --help` for command options.
`pip install 'fluksio[server]'` adds MQTT, InfluxDB, outbound mail and error
reporting. A machine that only executes remote nodes can install
`pip install 'fluksio[server]'` adds MQTT, InfluxDB, outbound mail, error
reporting and numpy, or name only what you need, such as `fluksio[mqtt]`. A
machine that only executes remote nodes can install
[`fluksio-worker`](workers.md).
## Where an instance lives
@@ -123,7 +124,7 @@ Starts the same agent as the standalone `fluksio-worker` command:
```sh
FLUKSIO_WORKER_TOKEN=your-token fluksio worker \
--url wss://api.example.com/api/v1/workers/attach --labels gpu
--url wss://fluksio.example.com/api/v1/workers/attach --labels gpu
```
Create the worker token on the engine first. See [Remote workers](workers.md)
@@ -140,7 +141,7 @@ is a fallback.
### `fluksio login`
```sh
fluksio login --url https://api.example.com
fluksio login --url https://fluksio.example.com
```
Prompts for credentials and saves an API token for a remote engine.
+6 -5
View File
@@ -144,6 +144,7 @@ import subprocess
import tempfile
import fluksio
import imageio_ffmpeg
# H.264 Constrained Baseline, at most 640x360 and 15 fps, mono AAC.
PANEL = [
@@ -157,10 +158,11 @@ PANEL = [
def process(clip):
source = fluksio.load_artifact(clip)
ffmpeg = imageio_ffmpeg.get_ffmpeg_exe()
with tempfile.TemporaryDirectory() as tmp:
target = os.path.join(tmp, "panel.mp4")
subprocess.run(
["ffmpeg", "-nostdin", "-loglevel", "error", "-i", source, *PANEL, target],
[ffmpeg, "-nostdin", "-loglevel", "error", "-i", source, *PANEL, target],
check=True,
timeout=600,
)
@@ -169,10 +171,9 @@ def process(clip):
```
Use it only for clips headed for such a panel. Browsers play the originals,
and the result plays there too, just smaller. The node needs `ffmpeg` on the
`PATH`. The Docker image includes it only when built with
[`WITH_FFMPEG=true`](../reference/configuration.md#image-options) in `.env`.
Otherwise run the node on a [remote worker](workers.md) that has it.
and the result plays there too, just smaller. Add `imageio-ffmpeg` on the
**Modules** screen first. It brings a static `ffmpeg` build for Linux on x86
and ARM, so nothing has to be installed into the image.
### Speech to and from a panel
+3 -3
View File
@@ -9,7 +9,7 @@ WebSocket. Keep one engine; add workers where the hardware lives.
On the engine, use a superuser access token. In these examples:
- `API_URL` is the engine's API base, including `/api/v1`, such as
`https://api.example.com/api/v1` or `http://localhost:8080/api/v1` for a LAN stack.
`https://fluksio.example.com/api/v1` or `http://localhost:8080/api/v1` for a Docker container.
- `TOKEN` is your superuser bearer token. The login endpoint
`POST /api/v1/login/access-token` accepts form fields `username` and `password`.
@@ -36,7 +36,7 @@ pip install fluksio-worker
export FLUKSIO_WORKER_TOKEN='<token from the engine>'
fluksio-worker \
--url wss://api.example.com/api/v1/workers/attach \
--url wss://fluksio.example.com/api/v1/workers/attach \
--labels gpu,cuda12 \
--python /opt/torch-venv/bin/python
```
@@ -163,7 +163,7 @@ in `$DATA_DIR/provisioners.json`, replacing the example addresses and paths:
"name": "hpc",
"login": "me@login.cluster",
"ssh_key": "/secrets/hpc_ed25519",
"engine_url": "wss://api.example.com/api/v1/workers/attach",
"engine_url": "wss://fluksio.example.com/api/v1/workers/attach",
"max_idle_s": 300,
"provision_timeout_s": 900,
"profiles": [{