# Dicto reference setup

A sanitized core example derived from the maintained deployment snapshot named
in `versions.yaml`. It preserves the `/api` and `/management/` layout, separate
API/migration/jobs roles, PostgreSQL, RustFS, and optional GPU services behind an
LLM gateway. It is an example for a **new installation**, not a migration script
or a full copy of the production environment.

See https://docs.tools.dicto.org/install/reference for the topology and component
guides. No Dicto source checkout is needed. Private images still require pull
access; image access is independent of access to product source.

## Files

```text
compose.yaml                     # core services, HTTPS proxy, optional gateway
secrets.env.example              # copy to secrets.env; supply your own values
versions.yaml                    # provenance, versions, validation limits
database/Dockerfile              # PostgreSQL 18.3 + vector/textsearch extensions
server/server.yaml               # API, jobs and migrator configuration
app-management/public.env        # public browser runtime configuration
config/app.yaml                  # managed desktop example
llm-server/models.json           # public aliases mapped to model backends
transcription/compose.yaml       # optional Whisper GPU overlay
transcription/Dockerfile         # vLLM 0.26.0 with audio dependencies
llm/compose.yaml                 # optional GPT-OSS 120B GPU overlay
monitoring/                      # optional Prometheus overlay
proxy/README.md                  # URL routing and HTTPS requirements
checks/README.md                 # expected checks and what they establish
schemas/                        # exported server/app schemas, added to download
checksums.sha256                 # generated from all bundled files
```

## 1. Requirements and inputs

Use a separate Linux Docker host or isolated new project. This Compose stack
owns host ports 80/443; do not start its Traefik alongside an existing proxy on
those ports. Supply a real DNS hostname pointing to the host and an email for
ACME. Internet-accessible TCP 443 is needed for the provided TLS challenge.
For an internal-only host, integrate your existing certificate/proxy setup as
described in `proxy/README.md`.

Install Docker Engine and Compose v2 with GPU reservations support. For the
self-hosted profile, configure NVIDIA Container Toolkit and sufficient GPUs,
VRAM, RAM and cache disk for the selected models. The preserved reference
allocations are GPUs 0/1 for Whisper and GPU 2 for GPT-OSS. The original host has
96 GB-class GPUs; the assignments are not minimum hardware requirements. Adjust
and validate memory/concurrency for your hardware before starting model servers.
The examples target Linux AMD64; GPU inference is not a Docker Desktop recipe.

Authenticate to GHCR with credentials authorized to pull the private Dicto and
gateway images. Model access/download terms are separate from registry access.
Verify the bundle after extraction, from this directory:

```sh
sha256sum --check checksums.sha256
cp secrets.env.example secrets.env
chmod 600 secrets.env
openssl rand -hex 32
```

Run the last command separately for each new secret. Replace every `REPLACE_`
value, set `DICTO_HOST`, `ACME_EMAIL`, and bootstrap administrator credentials.
Use a hex database password because it is embedded in a connection URL. Preserve
the auth secret and storage credentials for the lifetime of the installation.

Replace **all** occurrences of `dicto.example.org` in `server/server.yaml`,
`app-management/public.env` and `config/app.yaml` with your hostname. Changing
`DICTO_HOST` only changes proxy routing; it does not rewrite these files.

## 2. Select the inference profile

### Existing endpoints

Set `CHAT_BASE_URL`, `CHAT_API_KEY`, `TRANSCRIPTION_BASE_URL` and
`TRANSCRIPTION_API_KEY` in `secrets.env` for your providers. API roots include
their required `/v1` prefix. In `server/server.yaml`, replace `provider_model`
values with the model IDs your endpoints accept. Configure only models and
capabilities that your provider implements.

Use the core file alone in commands:

```sh
docker compose --env-file secrets.env config --quiet
```

### Self-hosted Whisper and GPT-OSS

Set `INFERENCE_API_KEY`, `CHAT_API_KEY` and `TRANSCRIPTION_API_KEY` to the same
new random value. Keep both base URLs at `http://llm-server:8000/v1`. The gateway
is reachable by the backend over Docker networking; model/probe ports bind only
to host loopback. Neither model server is publicly routed by Traefik.

The portable Whisper example uses public `openai/whisper-large-v3`. The maintained
deployment uses a local fine-tuned checkpoint and additional runtime patches;
those weights/patches are not distributed here. Token-logprob, diarization and
realtime capabilities are deliberately not advertised in this sample.
GPT-OSS uses the maintained vLLM version, model, parser and GPU assignment.
No model revision pin is asserted; record resolved revisions after download.

Use this complete Compose prefix for **every** command in the self-hosted profile:

```sh
docker compose --env-file secrets.env -f compose.yaml -f transcription/compose.yaml -f llm/compose.yaml --profile self-hosted-ai config --quiet
docker compose --env-file secrets.env -f compose.yaml -f transcription/compose.yaml -f llm/compose.yaml --profile self-hosted-ai up --build -d whisper-loadbalancer llm-gpt-oss-120b llm-server
```

Models can take many minutes to download, compile and load. Check logs and
perform the inference checks in `checks/README.md` before relying on Dicto.

## 3. Validate configuration, initialize storage, run migrations

The following commands use the core prefix. In the self-hosted profile, substitute
the full prefix above so subsequent `up` commands retain that profile's services.

```sh
docker compose --env-file secrets.env run --rm --no-deps migrator validate-config
docker compose --env-file secrets.env run --rm --no-deps migrator validate-config --resolve-env
docker compose --env-file secrets.env up --build -d postgres storage storage-init
docker compose --env-file secrets.env up --build -d
docker compose --env-file secrets.env ps --all
```

`storage-init` creates the private `recordings` bucket and exits; `migrator` runs
database migrations and exits. Their exit code must be zero. API and jobs wait
for both initialization steps. Do not skip migrations or change their image
independently of the API/jobs image.

## 4. Sign in and verify

Open `https://YOUR_HOST/management/` and sign in with the bootstrap account.
Check browser network requests use `https://YOUR_HOST/api`, not Docker names.
Connect an approved client to that same API URL and perform a short recording,
playback and transcription. For chat, perform a separate prompt/response check.
See `checks/README.md`; a successful YAML/Compose check does not prove inference
or a complete installation works.

After first sign-in, replace the `seed` section with:

```yaml
seed:
  admin:
    enabled: false
```

Remove the bootstrap administrator credentials from `secrets.env` after
replacing the complete seed section. Recreate API and jobs with your selected
Compose prefix.
The seeder skips an existing populated database; it is not password recovery.

## Operations and scope

Use the same Compose files/profile for logs, restarts and updates. Named volumes
hold the database, recordings, uploads, certificates and model/metrics caches.
`docker compose down` stops this stack; **`down --volumes` deletes its data**.
Back up database, object storage, uploads and private configuration together and
test restoration before upgrades. Do not attach this sample to production data
volumes or assume an older image reverses migrations.

To add monitoring, append `-f monitoring/compose.yaml` to your selected Compose
prefix and start `prometheus`. Its UI is bound to `127.0.0.1:9090`; use an SSH
tunnel or controlled internal access. The scrape target is `server:9464`.

The maintained deployment also has SSO/passkeys, custom model checkpoints,
realtime/diarization, Scripto's separate agent service, document workers,
retrieval and organization-specific plugins. They are outside this core example.
Enabling a UI feature does not provision those dependencies. Credentials,
organization identities, clinical data, model weights and product source are
not included. See `versions.yaml` for the exact validation scope of this export.
