fix(mcp v2.4.4): only attach traefik-enabled containers to coolify proxy net

v2.4.3 attached every stack container to the `coolify` network so
Traefik could reach the public container. But that network also hosts
coolify-db (alias `postgres`) and coolify-redis (alias `redis`).
Docker's embedded DNS resolves unqualified hostnames to the first
container with that name on the network, so once Twenty's
`postgres-<uuid>` joined the coolify network, Twenty's connection
string `postgres://postgres:5432/...` started resolving to coolify-db
and auth-failing in a tight restart loop.

Coolify's own pipeline only attaches the proxied container — filter
by the `traefik.enable=true` label so internal stack members (db,
redis, worker) stay isolated on the project network.

Made-with: Cursor
This commit is contained in:
2026-04-27 12:36:44 -07:00
parent 8b5c876f91
commit d6b8ba4d67
2 changed files with 23 additions and 9 deletions

View File

@@ -91,7 +91,7 @@ const GITEA_API_URL = process.env.GITEA_API_URL ?? 'https://git.vibnai.com';
export async function GET() {
return NextResponse.json({
name: 'vibn-mcp',
version: '2.4.3',
version: '2.4.4',
authentication: {
scheme: 'Bearer',
tokenPrefix: 'vibn_sk_',

View File

@@ -104,24 +104,38 @@ export async function composeUp(
}
/**
* Attach every container belonging to this Coolify resource to the
* `coolify` proxy network. Idempotent — `network connect` errors when
* the container is already attached, which we ignore.
* Attach the public-facing containers of a Coolify resource to the
* `coolify` proxy network so Traefik can reach them.
*
* IMPORTANT: only attach containers that have Traefik labels. The
* coolify network is shared across the whole platform (it hosts
* coolify-db, coolify-redis, etc.) and Docker's embedded DNS resolves
* unqualified hostnames like `postgres` and `redis` to the FIRST
* container with that name on the network. If we attach Twenty's
* `postgres-<uuid>` container to coolify, Twenty's
* `postgres://postgres:5432/...` connection string starts resolving
* to `coolify-db` instead, which fails auth (different password).
*
* Coolify's own deploy pipeline does the same selective attach — only
* the proxied container goes on the proxy network. Idempotent —
* already-attached containers are no-ops.
*/
export async function attachToCoolifyProxyNetwork(
uuid: string,
): Promise<void> {
// List containers on the resource's project network. Coolify names
// the bridge network after the resource UUID, so all stack members
// are reachable through it.
// List running containers on the resource's project network with
// their `traefik.enable` label. Only those with `traefik.enable=true`
// need to be reachable by the proxy.
const ls = await runOnCoolifyHost(
`docker ps --filter network=${uuid} --format '{{.Names}}'`,
`docker ps --filter network=${uuid} --format '{{.Names}}|{{.Label "traefik.enable"}}'`,
{ timeoutMs: 10_000 },
);
const names = ls.stdout
.split('\n')
.map(s => s.trim())
.filter(Boolean);
.filter(Boolean)
.filter(line => line.endsWith('|true'))
.map(line => line.split('|')[0]);
if (names.length === 0) return;
// Attach each one. `|| true` so already-connected returns 0.
const attaches = names.map(n =>