11 KiB
name: coolify-deploy description: Deploy new projects to the local self-hosted Coolify instance from end to end. Use when the user wants to take a local project (or a new idea) and ship it to Coolify: scaffold a compliant Dockerfile/compose, create a GitHub repo, push, register the app in Coolify, deploy it, and verify. Also covers rollback to a previous commit and redeploys. Distinct from coolify-agent (which operates already-deployed apps) and the proxmox-agent (host operations).
Coolify Deploy Skill
Use this skill to take a project from "local code" to "live on
https://<name>.urieljareth.org". It wraps the existing repo tooling
(Proxmox SSH, Coolify API, Cloudflare API) plus new GitHub scaffolding into a
single end-to-end pipeline.
⚠️ Instance reality check (READ FIRST — re-verified 2026-08-29, v4.3.14)
The /applications/* 404 is a Cloudflare edge block, not a Coolify limitation.
Same token, same route: 404 via https://coolify.urieljareth.org, 200 via the
origin http://192.168.0.117:8000/api/v1 ($env:COOLIFY_API_URL_ORIGIN) —
including /github-apps. The instance's own openapi.yaml (inside the container
at /var/www/html/openapi.yaml) declares the full applications namespace, so the
complete API contract applies when you call the origin. Two more facts:
- State-changing endpoints are POST-only since v4.2 —
GET /deploy?uuid=now answers 405"This endpoint has changed to a POST request."; use-Method POST(see notes §10.1). - The origin is plain HTTP inside the LAN — fine for ops from this machine; do not expose it.
Consequences:
- Creating/configuring git-based build-from-source apps via the API should now
work by calling the origin (
POST /applications/public,/dockerfile,/private-deploy-key, …). Not yet exercised end-to-end on 4.3.14 — verify on the next deploy before retiring the UI flow. - The Playwright UI flow (
scripts/coolify-ui/*.mjs, needsCOOLIFY_EMAIL/COOLIFY_PASSWORD) and the direct DB INSERT path (§8 of the notes) remain valid fallbacks. - What works through either path:
/resources(inventory+status),/projects,/security/keys,/services,/deploy(POST),/deployments/{uuid}.
Full playbook + gotchas (UTF-8 BOM breaks Coolify's YAML parser, "Reload Compose File" is
mandatory, don't queue concurrent deploys, PowerShell ReadAllText for key payloads, etc.):
references/coolify-4.1.2-notes.md (§11 has the
2026-08-29 re-verification). Re-verify the API surface with GET /version if the instance
was upgraded.
NEW (2026-07-27): There is also a third path for creating apps — direct DB
INSERT via SSH → pct → docker exec → psql. See
references/coolify-4.1.2-notes.md §8.
This is the fastest path when you have SSH access to the Proxmox host. The key gotcha: you
MUST also INSERT a matching application_settings row or deploys crash with
"disable_build_cache on null" — and stuck deploy queues must be cleared manually (§8.4).
When to use
- "Deploy this project to Coolify"
- "Create a new GitHub repo and ship it to Coolify"
- "Roll back the Coolify app to yesterday's commit"
- "Generate a Dockerfile that works on this Coolify instance"
- "Validate my repo against the Coolify hard rules before pushing"
When NOT to use
- Operating an already-deployed app (logs, restart, env edits) → use
coolify_skill/SKILL.mdinstead. - Proxmox host or LXC maintenance → use
agent/SKILL.md. - Editing Cloudflare tunnel routes → dashboard-managed, see
docs/runbooks/cloudflare-tunnel.md.
Prerequisites (one-time setup)
.env.local.ps1must contain at minimumCOOLIFY_TOKENandGITHUB_TOKEN. Seereferences/templates/env.local.template.ps1.GITHUB_TOKENis a GitHub PAT (classic withreposcope, or fine-grained withContents: Read+Write+Metadata: Read). Generate at https://github.com/settings/tokens.git pushto GitHub uses Windows Credential Manager (wincred) — no need to embed the PAT in the git URL. The PAT is only for GitHub REST API calls (creating repos, listing).- The authenticated GitHub account is
urieljarethbusiness-cpu(verified viagit credential fill). Override withGITHUB_OWNERif needed. - Operational verification needs Node + Playwright. Run
npm installonce in the manager repo root (H:\MegaSync\Proyectos\Proxmox & Coolify Manager). Chromium binaries cache at%LOCALAPPDATA%\ms-playwright. If Node is missing,Test-ServiceOnline.ps1falls back to curl-only (browser layer is skipped, not failed).
Pipeline
There are two pipelines, one per deploy strategy. Pick based on whether your project ships as a single Dockerfile-built app or as a multi-container Docker Compose stack.
A. Single-app (Dockerfile) — Publish-ProjectToCoolify.ps1
local project
→ Initialize-CoolifyProject.ps1 (optional: scaffold Dockerfile/compose)
→ Test-PreDeployChecklist.ps1 (gate; enforces AGENTS-coolify-apps.md)
→ New-GitHubRepo.ps1 (create repo, idempotent)
→ git push origin main (uses wincred, not the PAT)
→ New-CoolifyApplication.ps1 (project + env + app + envs + deploy)
→ Test-PostDeploy.ps1 (Coolify state: containers, proxy logs, sibling DNS)
→ Test-ServiceOnline.ps1 (OPERATIONAL: HTTP 200 + Playwright page render)
Use Publish-ProjectToCoolify.ps1 to run all seven steps in sequence with one
confirmation per step.
B. Multi-container stack (Docker Compose) — New-CoolifyService.ps1
For projects that ship a docker-compose.coolify.yml (app + sibling DB +
optional sidecars). Reads the local compose file and POSTs it to Coolify's
/services endpoint — the modern replacement for the deprecated
/applications/dockercompose.
local project (with docker-compose.coolify.yml)
→ Test-PreDeployChecklist.ps1 (gate; enforces AGENTS-coolify-apps.md)
→ New-GitHubRepo.ps1 + git push (only if the repo isn't already on GitHub)
→ New-CoolifyService.ps1 (project + env + service + urls + envs + deploy)
→ Test-PostDeploy.ps1 (Coolify state: containers, proxy logs, sibling DNS)
→ Test-ServiceOnline.ps1 (OPERATIONAL: HTTP 200 + Playwright page render)
The compose MUST satisfy the hard rules (no published 80/443, DB by service
name, SERVICE_FQDN_<svc>_<port> placeholders so Coolify wires routes, named
volumes, healthchecks). The urls payload in New-CoolifyService.ps1 maps
one service (e.g. web) to the primary FQDN; pass -ExtraUrls for
multi-public-service stacks.
The final step (Test-ServiceOnline.ps1) is the definition of done for
both pipelines: the service is only considered live when (a) the FQDN returns
HTTP 2xx via curl and (b) a real Chromium browser loads the page with no
uncaught JS errors. It retries for ~80 seconds to allow Traefik/TLS warm-up.
For rollback: Invoke-CoolifyRollback.ps1 pushes the chosen commit to a
rollback/<sha> branch (main stays untouched), repoints the Coolify app, and
redeploys.
Hard rules (must hold for every app)
Read docs/AGENTS-coolify-apps.md for the
canonical version. Summary:
- Sibling DB by service name, never
localhost. - External
coolifynetwork if the app needs shared Coolify services. - Never publish host ports
80/443— Traefik owns them. - FQDN =
https://<name>.urieljareth.orgset before first deploy. TLS via DNS challenge, not HTTP-01. - Secrets as env vars only, never committed or baked.
- Healthcheck on a DB-independent endpoint.
- Named volumes for data that must survive redeploys.
Test-PreDeployChecklist.ps1 enforces these automatically.
Safety policy
- Read-only by default. The first run of any deploy flow only inspects.
- Confirm before mutating. Each step that creates a repo, pushes commits,
creates a Coolify resource, or triggers a deploy asks for confirmation
unless
-Forceis supplied. - Never write secrets into the repo. Tokens live in
.env.local.ps1(gitignored). The skill scripts accept env files but never echo their values. - No force-push to main during rollback. The rollback branch carries the target SHA; main is only moved if the operator does it explicitly.
- State the rollback path before any risky change.
Tooling
See TOOLS.md for the command reference. The scripts in
deploy_skill/scripts/ reuse:
scripts/Invoke-ProxmoxSsh.ps1for any LXC 102 / Docker inspection.coolify_skill/scripts/Invoke-CoolifyApi.ps1for all Coolify API calls.scripts/Invoke-CloudflareApi.ps1if the user asks to add a tunnel route (rare; tunnel is dashboard-managed).
Reference docs
docs/AGENTS-coolify-apps.md— the compatibility contract every project must satisfy. Read before scaffolding.docs/proxmox-inventory.md— verified topology.docs/runbooks/coolify-docker.md— Docker operations inside LXC 102.coolify_skill/references/ops/— per-endpoint Coolify API reference. Search withrg, do not load all.references/templates/— Dockerfile/compose/env templates that already satisfy the hard rules.
Common workflows
1. New project, full pipeline
. .\.env.local.ps1
.\deploy_skill\scripts\Publish-ProjectToCoolify.ps1 `
-AppPath .\my-new-app `
-AppName my-new-app `
-Fqdn https://my-new-app.urieljareth.org `
-Stack node -AppPort 8080 -Init
2. Existing local repo, just register + deploy
.\deploy_skill\scripts\Publish-ProjectToCoolify.ps1 `
-AppPath .\existing-app `
-AppName existing-app `
-Fqdn https://existing-app.urieljareth.org `
-AppPort 3000
2b. Multi-container stack (Docker Compose) — register + deploy
.\deploy_skill\scripts\New-CoolifyService.ps1 `
-AppPath .\my-stack `
-AppName my-stack `
-ComposeFile docker-compose.coolify.yml `
-Fqdn https://my-stack.urieljareth.org `
-PrimaryService web `
-EnvFile .\my-stack\.env.coolify `
-InstantDeploy
3. Rollback to a previous commit
.\deploy_skill\scripts\Invoke-CoolifyRollback.ps1 `
-AppPath .\my-app `
-ApplicationUuid og88wk4 `
-CommitSha a1b2c3d
4. Only validate, no deploy
.\deploy_skill\scripts\Test-PreDeployChecklist.ps1 -Path .\my-app -ExpectedPort 8080 -Strict
5. Verify an already-deployed service is truly live (HTTP 200 + browser)
.\deploy_skill\scripts\Test-ServiceOnline.ps1 `
-Fqdn https://my-app.urieljareth.org `
-ExpectTitle "My App" -Retries 8
This is the operational gate — the answer to "did the deploy actually ship a working page?". Use it after any redeploy, env change, or rollback. It captures a PNG screenshot as evidence.