Hosting the app¶
cartolex api serves the app without opening a browser, for a server or a
container. The same app runs locally (cartolex), so what works on one
computer works hosted.
# one project
cartolex api /srv/maps/coast --host 0.0.0.0 --port 8000 --allowed-host maps.example.org
# many projects, one folder each, chosen by the route: /api/projects/<id>/…
cartolex api --projects-root /srv/maps --host 0.0.0.0 --allowed-host maps.example.org
The command prints the launch link (http://…/launch?token=…), which opens
the app once in a browser and signs that browser in. Keep it private: whoever
holds it holds the project. A new start gives a new link.
Host names¶
The app answers only to the names it is given (--allowed-host, repeated for
several) and, for one project, to the loopback names; any other Host is
refused. Put the public name the browsers use, the one of the reverse proxy.
With many projects (--projects-root), the loopback names are not added: add
127.0.0.1 if a health check calls the app from the same machine.
HTTPS, sign-in and several people¶
Put the app behind a reverse proxy that ends HTTPS and forwards to it, and
pass --secure-cookies so the session cookies are sent over HTTPS only. The
app sends no CORS header, and refuses a change asked from another site.
A service with its own accounts passes its sign-in to the app
(AppSettings.authenticate: a request to a Principal) and its own rules
(AppSettings.authorizer: may this principal do this action on this
resource?), through a small Python program of its own that calls
cartolex.app.create_app and serves it with uvicorn. See The app and its API.
A hosted service never deletes a project’s folder from the app
(project_delete_hosted): whoever runs the service removes projects from its
folder. The site builds and exported files of a project can be deleted from its
Share screen by whoever the service’s rules allow (the action share.delete).
The container¶
deploy/Dockerfile builds an image of the app with the language models of the
extraction:
docker build -f deploy/Dockerfile -t cartolex . # from the repository
docker volume create cartolex-project
docker run --rm -v cartolex-project:/project cartolex \
init /project --name "Coastal map" --field "Coastal and marine systems" --languages en,fr
docker run -d --name cartolex --read-only --tmpfs /tmp \
-p 127.0.0.1:8000:8000 -v cartolex-project:/project --stop-timeout 30 \
cartolex api /project --host 0.0.0.0 --port 8000 --data-dir /tmp/cartolex \
--allowed-host maps.example.org
docker logs cartolex # the launch link, then one JSON line per request
A user without rights: the app runs as
cartolex(uid 10001), not root.A read-only root filesystem: run it with
--read-only --tmpfs /tmp. The app writes only into the project (the volume/project) and into/tmp(its own folder/tmp/cartolex, the numeric libraries’ caches).One volume:
/project, the project folder. Back up itsproject.json,sources/,decisions/andcache/ai/(The project format, cartolex-project/1).The health route:
GET /api/healthanswers{"status": "ok"}without a session; the image’sHEALTHCHECKcalls it.Logs: one JSON object per line on the standard error, with a request id and the route’s template, never a name, a text or a key.
The AI key:
-e MISTRAL_API_KEY=…lets the AI clean-up run by API; without it, the AI clean-up with a copilot still works.Stopping:
docker stopsends a signal the app handles: running jobs are cancelled at their next safe point and the project is closed (its lock removed). Give it time (--stop-timeout 30).
After a crash. A project opened for writing holds a lock (/project/.lock)
that names its process and its machine. A container that was killed leaves it
behind, and a new container (another machine name, perhaps the same process
number) cannot tell that its holder is gone: the app refuses to open the
project and names the lock. When you are sure no other container uses the
volume, remove it:
docker run --rm -v cartolex-project:/project --entrypoint rm cartolex /project/.lock
Build the image without the language models (--build-arg WITH_MODELS=0) to
install only those of your corpus languages afterwards (cartolex models add).