Service graph¶
About this page
This documents a stack generated from soliplex-template. A generated
project ships its own copy of this page without this note.
The stack is defined in docker-compose.yml. Several services cooperate; two
of them share the RAG vector store through a bind mount.
graph LR
browser([Browser]) -->|9000/9443| nginx
nginx -->|/api/ /mcp/| backend
backend -->|reads LanceDB| ragdb[(rag/db)]
ingester[haiku-ingester] -->|writes LanceDB| ragdb
ingester -->|convert/chunk| docling[docling-serve]
ingester -->|job queue| postgres[(postgres)]
backend -->|threads + authz| postgres
nginx¶
Serves the Flutter web frontend and reverse-proxies /api/ and /mcp/ to
backend:8000. The web client is copied in nginx/Dockerfile from the
published ghcr.io/soliplex/frontend-web image, whose tag picks the release; its assets
sit under a v<release-tag>/ directory, which nginx/nginx.conf caches for
a year, while index.html is never cached, so a new release reaches browsers
on their next load. Terminates TLS on host port 9443 with a self-signed cert.
backend¶
Runs soliplex-cli serve /environment, from an image built on the published
soliplex release image (see Backend image & dependencies). The --reload=config
flag means edits under backend/environment/ take effect without a rebuild,
and one --reload-dirs flag per project on its PYTHONPATH (this project's
own package, plus any added with src_projects.py) restarts it when their
code changes.
soliplex-dev¶
A one-shot task runner, not a long-running service: profiles: ["devmode"]
keeps it out of docker compose up. It exists for commands that need the
stack's config, secrets and databases and write access to the project
directories under src/.
It is built on the backend's own image (soliplex-dev/Dockerfile, with
compose passing the backend's image in as service:backend), plus every
src/ project's dev dependency group, so a project's tests run here against
the backend's versions (see
Custom Python package). It
mirrors the backend's secrets, mounts and environment — the same /app/src
paths, and the very same PYTHONPATH (a YAML alias, so the two cannot
drift). So an audit run here sees exactly what the backend sees:
The one difference is that src/ is mounted read-write (the backend
mounts the same tree read-only). Pass -w /app/src/<project> for anything
that must run from a project's own root — alembic writes into its
versions/ directory and prepends . to sys.path:
docker compose run --rm -w /app/src/soliplex soliplex-dev \
/app/.venv/bin/alembic -x soliplex.installation_path=/environment \
revision --autogenerate -m "add a column"
Any project directory under src/ works, not just a soliplex checkout.
haiku-ingester¶
The writer for the LanceDB at rag/db/. Runs haiku-ingester serve with a
Postgres-backed job queue (its own soliplex_ingester database), an async
worker pool, retries + a dead-letter queue, and an HTTP control plane on host
port 8765. There is a single-writer constraint: only one
ingester per LanceDB. The backend reads the same store through a bind mount.
See RAG pipeline.
haiku-rag¶
A one-shot runner for the haiku-rag CLI, held out of
docker compose up by profiles: ["tools"] (docker compose run enables the
profile itself). It shares the ingester's image, mounts, environment and
queue-password secret, and passes whatever follows the service name straight to
the CLI:
Its entrypoint exports INGESTER_DB_PASSWORD from the Docker secret first,
which every CLI call needs: haiku.rag.yaml interpolates that variable into
the queue dburi and haiku.rag expands the whole file before running the
subcommand. Reads are safe while the stack is up; writing a store the ingester
owns needs docker compose stop haiku-ingester first.
docling-serve¶
A stateless document converter. Runs the upstream -cpu image
directly; its variant/version are chosen at generation and baked
into docker-compose.yml — re-point by editing that line and
committing (see the stack's docling-serve/README.md for the
variants, the tagging policy, and a local-build recipe).
tui¶
Soliplex's Textual terminal client, served
as a web app over textual-serve; nginx proxies it at /tui/, so open
https://myproject.localhost:9443/tui/. The same client is bundled in
the backend image — to run it from the command line, see
Using the TUI.
postgres¶
Creates the stack's databases on first boot via postgres/config/init.sh:
soliplex_agui(thread persistence)soliplex_authz(authorization policy)-
soliplex_ingester(the haiku-ingester job queue) -
soliplex_gitea(Gitea's backing store)
Each gets a dedicated low-privilege role whose password is a Docker secret.
Init runs only on an empty data volume; to re-run it,
docker compose down -v first.
gitea¶
A local Gitea instance (rootless image), backed by
the soliplex_gitea Postgres database. nginx reverse-proxies it under /gitea/
on the HTTPS port — open https://myproject.localhost:9443/gitea/ — and its
built-in SSH and HTTP are published on host ports 2222 and 3000. State lives
in the gitea_data / gitea_config named volumes. Provision it after first
boot with scripts/init_gitea.py — see
Provision Gitea.