docs: apps.create pathways, volumes tools, stale-volume cookbook (v2.3)

Documents the new image/composeRaw apps.create pathways with guidance
on when to use each (third-party SaaS vs user code). Adds sections on
choosing the right pathway and the canonical stale-volume recovery flow
using apps.volumes.list + apps.volumes.wipe + apps.exec.

Renumbers troubleshooting sections 11.4-11.9 to accommodate the new
entries without disrupting existing content.

Made-with: Cursor
This commit is contained in:
2026-04-23 16:21:38 -07:00
parent 537e697dab
commit bed0ed5049
2 changed files with 54 additions and 6 deletions

View File

@@ -109,13 +109,15 @@ Version: **2.1.0**.
|---|---|---|
| `apps.list` | All Coolify apps in the workspace. | — |
| `apps.get` | Single app details (status, fqdn, domains, git info). | `{ uuid }` |
| `apps.create` | Create a Coolify app from a Gitea repo in the workspace's org. Clones over **HTTPS with the workspace bot's PAT embedded in the URL** — SSH is not used because Gitea's SSH isn't reachable on the default port. Auto-domain `{name}.{slug}.vibnai.com`. | `{ repo, branch?, name?, ports?, buildPack?, domain?, envs?, instantDeploy?, dockerComposeLocation?, dockerfileLocation?, baseDirectory? }` |
| `apps.create` | Create a Coolify app. **Three pathways** depending on the source — choose the right one for the job: **(1) Gitea repo** (user's own code): pass `repo`. Clones over HTTPS+PAT; no SSH. **(2) Docker image** (pre-built third-party app, e.g. `nginx:alpine`): pass `image`. No repo created. **(3) Inline Docker Compose YAML** (multi-service third-party app, e.g. Twenty, Directus): pass `composeRaw` with the full compose YAML as a string. No repo created. Use pathways 2 and 3 for any third-party SaaS app — they are faster, simpler, and avoid stale-git-state issues. Auto-domain `{name}.{slug}.vibnai.com` for all pathways. | **Pathway 1 (repo):** `{ repo, branch?, name?, ports?, buildPack?, domain?, envs?, instantDeploy?, dockerComposeLocation?, dockerfileLocation?, baseDirectory? }` **Pathway 2 (image):** `{ image, name?, ports?, domain?, envs?, instantDeploy? }` **Pathway 3 (compose):** `{ composeRaw, name?, domain?, composeService?, composeDomains?, envs?, instantDeploy? }``composeDomains` is `[{ service, domain }]`; defaults to `[{ service: "server", domain: auto }]` |
| `apps.update` | PATCH a whitelisted set of fields (name, description, git branch/commit, ports, build commands, base directory, Dockerfile location, docker-compose location…). Returns `applied`, `ignored`, and `rerouted` arrays so the agent can see exactly what persisted; setting `fqdn`/`domains`/`docker_compose_domains` returns a `rerouted` entry pointing at `apps.domains.set`, and setting `git_repository` returns one pointing at `apps.rewire_git`. | `{ uuid, patch }` |
| `apps.rewire_git` | Re-point an app's `git_repository` at the canonical HTTPS+PAT clone URL. Use to recover older apps that were created with SSH URLs, or to refresh a rotated bot PAT. | `{ uuid, repo? }``repo` optional; inferred from current URL if omitted |
| `apps.delete` | Destroy the app. Volumes kept by default. | `{ uuid, confirm }``confirm` must equal the app's exact name |
| `apps.deploy` | Trigger a new deployment. | `{ uuid, force? }` |
| `apps.deployments` | List recent deployments + status. | `{ uuid }` |
| `apps.logs` | Runtime logs for a running app. Compose-aware: returns per-service logs for `dockercompose` build packs, single stream for `dockerfile`/`nixpacks`. Includes container status and any diagnostic warnings. | `{ uuid, service?, lines? }``service` filter (compose only), `lines` default 200, max 5000 |
| `apps.volumes.list` | List Docker volumes belonging to an app (name + size in bytes). Use before `apps.volumes.wipe` to know exact volume names. | `{ uuid }` |
| `apps.volumes.wipe` | **Destructive / irreversible.** Stop all app containers, remove a specific volume, leave it ready for a fresh `apps.deploy`. Use to recover from stale DB state on first boot (the most common compose app failure). `confirm` must equal the exact volume name. | `{ uuid, volume, confirm }` |
| `apps.exec` | Run a one-shot command inside an app container (via `docker exec` on the Coolify host). Compose-aware: pass `service` when the app has >1 container. Returns `{ container, service, code, stdout, stderr, truncated, durationMs, containerHealth }`. Default timeout 60s (max 10 min); default output cap 1 MB (max 5 MB). Command is run through `sh -lc` so shell syntax works. Use this for database migrations, seeds, CLI invocations, and ad-hoc debugging. Every call is audit-logged (command + target, not output). | `{ uuid, command, service?, user?, workdir?, timeout_ms?, max_bytes? }` |
| `apps.domains.list` | Current domain set. | `{ uuid }` |
| `apps.domains.set` | Replace the domain set. All entries must end with `.{slug}.vibnai.com`. Compose-aware: for `dockercompose` apps the domain is attached to a specific service (`server` by default; override with `service`). | `{ uuid, domains: string[], service? }` |
@@ -581,7 +583,7 @@ The MCP descriptor at `GET /api/mcp` reports a semver `version`. Tool names
are append-only within a major version — agents can cache the tool list
safely for the duration of a conversation but should re-fetch on 404.
Current version: **2.2.0**.
Current version: **2.3.0**.
- **1.x** — session-cookie-only MCP, no tenant keys.
- **2.0** — `vibn_sk_…` keys, workspace-scoped Gitea bot + Coolify project.
@@ -590,6 +592,9 @@ Current version: **2.2.0**.
- **2.2** — per-workspace GCS object storage (`storage.*`), compose-aware
domain routing, runtime log tailing (`apps.logs`), in-container command
execution (`apps.exec`), and diagnostic `apps.update` responses.
- **2.3** — `apps.create` Docker-image and inline-composeRaw pathways (no
Gitea repo required for third-party apps), `apps.volumes.list` +
`apps.volumes.wipe` for self-service volume recovery.
---
@@ -654,7 +659,50 @@ single-container apps use `domains` (comma-separated string).
3. `apps.logs { uuid, service: "server", lines: 200 }` — look for
startup errors like `EADDRINUSE` or config failures.
### 11.4 "Healthcheck times out on first deploy"
### 11.4 "Choosing the right `apps.create` pathway"
| Situation | Use |
|---|---|
| User's own code lives in their Gitea org | `repo` (pathway 1) |
| Single-container third-party app (nginx, redis, a docker image) | `image` (pathway 2) |
| Multi-service third-party app (Twenty, Directus, Cal.com, Plane…) | `composeRaw` (pathway 3) |
**Never** create a Gitea repo just to host a third-party app's compose file. Use `composeRaw` instead — it's faster, has no git-clone overhead, and avoids the partial-state problems that can happen when Coolify clones a fork.
For `composeRaw`, fetch the app's official `docker-compose.yml` (from GitHub/DockerHub) and pass it inline. Override any hard-coded image tags with pinned versions for reproducibility.
### 11.5 "Compose app fails on second+ deploy — relation/table does not exist"
Classic stale volume problem. Sequence of events:
1. First deploy: Postgres starts and auto-creates an empty `default` database (from `POSTGRES_DB` env var)
2. App server starts, tries to `CREATE DATABASE` or `DROP DATABASE` inside a transaction → Postgres rejects it
3. Deploy fails, containers stop — but the volume persists with the half-initialized DB
4. Second deploy: Postgres finds existing data, skips init — but schema is corrupt/incomplete
5. Server errors cascade forever
**Fix:**
```json
// Step 1: find the volume
{ "action": "apps.volumes.list", "params": { "uuid": "<app-uuid>" } }
// → { "volumes": [{ "name": "abc123_db-data", "sizeBytes": 8192 }] }
// Step 2: wipe it
{ "action": "apps.volumes.wipe", "params": { "uuid": "<app-uuid>", "volume": "abc123_db-data", "confirm": "abc123_db-data" } }
// Step 3: redeploy clean
{ "action": "apps.deploy", "params": { "uuid": "<app-uuid>" } }
```
If Postgres still auto-creates the database before the app server runs migrations, use `apps.exec` to drop it outside a transaction:
```json
{ "action": "apps.exec", "params": { "uuid": "<app-uuid>", "service": "db", "command": "psql -U postgres -c 'DROP DATABASE IF EXISTS \"default\";'" } }
```
Then redeploy.
### 11.7 "Healthcheck times out on first deploy"
Docker Compose healthchecks have a `start_period` grace window. Apps
that run long-running migrations on first boot (Twenty, Directus,
@@ -667,7 +715,7 @@ start, typically 120600s.
- Alternatively, handle migrations out-of-band via `apps.exec` and let
the default healthcheck succeed instantly.
### 11.5 "I can't tell what's inside the container"
### 11.8 "I can't tell what's inside the container"
`apps.exec` is the escape hatch. Useful shell one-liners:
@@ -685,7 +733,7 @@ Output is capped at 1 MB by default (bump with `max_bytes`). Commands
that could exceed the wall-clock timeout should bump `timeout_ms`
(max 600000 = 10 minutes).
### 11.6 "The agent wants to run something interactively"
### 11.9 "The agent wants to run something interactively"
It can't. `apps.exec` is strictly non-interactive: no TTY, no stdin,
no session resumption. For migrations and CLI invocations this is the

Submodule vibn-frontend updated: 8c83f8c490...6d71c63053