# Deploying and operating

> Running a server under a restart policy, keeping tasks across restarts, and what to put in front of it.

Source: https://opendecisio.com/docs/operating/

A decisio server is a model server, not a hardened public endpoint: run it on a private network, behind your own proxy, under something that restarts it.

 

[Figure: A dead engine does not serve again: the server says so and exits, and something restarts it. A server starts, becomes healthy, and serves. If its engine dies, every request is answered with 503, /health answers 503 with the reason, and the server exits with code 70 for a restart policy to act on.]

 

## TL;DR

 

Wait until a server you started is ready, then check what it serves:

 

```
until curl -sf http://127.0.0.1:8000/health > /dev/null; do sleep 5; done
curl -s http://127.0.0.1:8000/health
```

 

Run against the CPU stand-in at v0.11.1 on 2026-10-14.

  

| Word | Meaning |
| --- | --- |
| restart policy | what brings the server back after it exits: Compose’s `restart: unless-stopped`, systemd’s `Restart=on-failure`, or Kubernetes’ `restartPolicy: Always` |
| exit code 70 | what the server exits with when its engine has died |
| single-tenant | one server per trust boundary: its cache and registered tasks are shared by every caller |

 

Common mistake

Docker restarts a container when its process exits, not when its `HEALTHCHECK` reports it unhealthy. It is the server’s exit that brings a new one up, so give the container a restart policy.

 

## 1. Run it under a restart policy

 

An engine that has failed does not serve again, so the server ends itself and leaves the restart to whatever runs it: compose `restart: unless-stopped`, as `compose.yaml` has it; systemd `Restart=on-failure`; Kubernetes’ default `restartPolicy: Always`, with a liveness probe on `/health`. The new server loads the engine again, so requests sent until it is healthy are refused. [Health and monitoring](https://opendecisio.com/docs/health/) says exactly what happens from the moment the engine dies.

 

## 2. Keep tasks across restarts

 

Registered tasks live in the server’s memory. [Teach it your question](https://opendecisio.com/docs/tasks/#5-list-export-reload-delete) shows how to export them and load them again at start.

 

## 3. Put a proxy in front

 

Decisio is a model server, not a hardened public endpoint.

 

- It is designed to run behind your own proxy on a private network. The server binds to `127.0.0.1` by default; do not expose it directly to the internet.
- There is no authentication on any route. Put authentication, rate limiting and request-size limits in the proxy.
- `POST /v1/tasks`, `POST /v1/tasks/import`, `DELETE /v1/tasks/{id}` and the abstention routes change server state. Restrict them to trusted callers.
- `--debug-readout` exposes raw model readouts; leave it off in production.
- The image route accepts image payloads from requests; size limits belong in the proxy.
- vLLM's own security guidance applies to the engine underneath: [https://docs.vllm.ai/en/stable/usage/security/](https://docs.vllm.ai/en/stable/usage/security/)

 

A decisio server is single-tenant. Its prefix cache and registered tasks are shared by every caller, so response timing can reveal whether another caller recently sent the same text, and one caller's registered task answers another's identical question. Run one server per trust boundary.

 

## What next

 

- [Health and monitoring](https://opendecisio.com/docs/health/): what to watch, and what a dead engine looks like.
- [Troubleshooting](https://opendecisio.com/docs/troubleshooting/): symptoms and what the documentation says to do.
- [Upgrading](https://opendecisio.com/docs/upgrading/): what changes for a running deployment between releases.
