From 1f37d4bc91d20f163845bf3b7375c668a1cc7805 Mon Sep 17 00:00:00 2001 From: Mark Henderson Date: Thu, 23 Apr 2026 16:31:44 -0700 Subject: [PATCH] fix(coolify): remove disallowed fields from dockercompose create payload Coolify's /applications/dockercompose endpoint rejects build_pack (it hardcodes dockercompose), is_force_https_enabled, and docker_compose_domains at creation time. Move those to a follow-up PATCH call that runs immediately after creation. Made-with: Cursor --- lib/coolify.ts | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/coolify.ts b/lib/coolify.ts index 6edca71..7a55c81 100644 --- a/lib/coolify.ts +++ b/lib/coolify.ts @@ -516,29 +516,43 @@ export interface CreateDockerComposeAppOpts { export async function createDockerComposeApp( opts: CreateDockerComposeAppOpts, ): Promise<{ uuid: string }> { + // NOTE: the /applications/dockercompose endpoint has a restricted + // field allowlist vs the PATCH endpoint. It rejects `build_pack` + // (hardcoded to "dockercompose"), `is_force_https_enabled`, and + // `docker_compose_domains` — those must be set via PATCH afterward. const body = stripUndefined({ project_uuid: opts.projectUuid, server_uuid: opts.serverUuid ?? COOLIFY_DEFAULT_SERVER_UUID, environment_name: opts.environmentName ?? 'production', destination_uuid: opts.destinationUuid ?? COOLIFY_DEFAULT_DESTINATION_UUID, - build_pack: 'dockercompose', name: opts.name, description: opts.description, docker_compose_raw: opts.composeRaw, - is_force_https_enabled: opts.isForceHttpsEnabled ?? true, instant_deploy: opts.instantDeploy ?? false, - // domains for compose are set via docker_compose_domains after creation - docker_compose_domains: opts.composeDomains - ? JSON.stringify(opts.composeDomains.map(({ service, domain }) => ({ - name: service, - domain: `https://${domain.replace(/^https?:\/\//, '')}`, - }))) - : undefined, + autogenerate_domain: false, }); - return coolifyFetch('/applications/dockercompose', { + const created = await coolifyFetch('/applications/dockercompose', { method: 'POST', body: JSON.stringify(body), - }); + }) as { uuid: string }; + + // Set domains + https enforcement via PATCH (compose-aware) + if (opts.composeDomains && opts.composeDomains.length > 0) { + await coolifyFetch(`/applications/${created.uuid}`, { + method: 'PATCH', + body: JSON.stringify(stripUndefined({ + is_force_https_enabled: opts.isForceHttpsEnabled ?? true, + docker_compose_domains: JSON.stringify( + opts.composeDomains.map(({ service, domain }) => ({ + name: service, + domain: `https://${domain.replace(/^https?:\/\//, '')}`, + })), + ), + })), + }); + } + + return created; } export async function updateApplication(