Create, deploy, update, and troubleshoot Coolify applications with the official Coolify CLI. Use when user wants deploy via Coolify, app creation from GitHub...
---
name: coolify-deploy
description: Create, deploy, update, and troubleshoot Coolify applications with the official Coolify CLI. Use when user wants deploy via Coolify, app creation from GitHub, redeploy on push, env vars, logs, or fallback Docker/Traefik routing.
---
# Coolify Deploy
Use the **official `coolify` CLI first**. Use direct Docker + Traefik only as fallback.
## Core Rules
1. **Prefer CLI-managed apps** so deployments appear in Coolify UI and support push-to-deploy.
2. **Use `app create github` for private GitHub repos** and the correct GitHub App UUID.
3. **Verify both app status and HTTP 200** before calling a deploy finished.
4. **Use direct Docker only if Coolify creation is blocked**.
## When to Use
- Creating a new Coolify app
- Redeploying after code changes
- Debugging unhealthy deployments
- Adding env vars or checking deployment logs
## Required Info
- `server_uuid`
- `project_uuid`
- `environment_name` (usually `production`)
- `github_app_uuid` for private repos
- repo, branch, domain, exposed port
## Preferred Workflow
### 1. Verify CLI + context
```bash
coolify context verify
coolify github list --format=json
coolify app list --format=json
```
### 2. Create app from private GitHub repo
```bash
coolify app create github \
--server-uuid <server_uuid> \
--project-uuid <project_uuid> \
--environment-name production \
--github-app-uuid <github_app_uuid> \
--git-repository owner/repo \
--git-branch main \
--build-pack dockerfile \
--ports-exposes 80 \
--name <app-name> \
--domains http://<app>.<ip>.sslip.io \
--instant-deploy \
--format=json
```
### 3. Add env vars when needed
```bash
coolify app env create <app-uuid> --key PORT --value 80 --format=json
```
### 4. Force redeploy
```bash
coolify deploy uuid <app-uuid> --force --format=json
```
### 5. Verify success
```bash
coolify app get <app-uuid> --format=json
coolify app deployments list <app-uuid> --format=json
curl -I http://<domain>
```
## GitHub App Integration
List configured GitHub apps:
```bash
coolify github list --format=json
```
Use the **UUID** from this output in `coolify app create github --github-app-uuid ...`.
If a repo is private and `public` creation fails, switch to `github` creation.
## Common Issues
### App is `exited:unhealthy`
Check deployment logs first:
```bash
coolify app deployments list <app-uuid> --format=json
coolify app deployments logs <app-uuid>
```
Then verify:
- wrong GitHub App UUID
- wrong Dockerfile path
- missing env vars like `PORT`
- build/runtime errors
### Vite/Rollup native module error
Use Debian-based Node image:
```dockerfile
FROM node:20-slim AS builder
```
Avoid Alpine for builds that need native Rollup modules.
### nginx template expects `${PORT}`
Set env var in Coolify:
```bash
coolify app env create <app-uuid> --key PORT --value 80 --format=json
```
### Domain responds but UI still says `running:unknown`
Treat `HTTP 200 + finished deployment` as success. Coolify may still show `running:unknown`.
## Fallback: Direct Docker Deploy
Only use when CLI-managed app creation is blocked.
See `references/coolify-api.md` for direct Docker/Traefik fallback patterns.
## Quick Reference
```bash
coolify github list --format=json
coolify app create github --server-uuid <server> --project-uuid <project> --environment-name production --github-app-uuid <ghapp> --git-repository owner/repo --git-branch main --build-pack dockerfile --ports-exposes 80 --name myapp --domains http://myapp.<ip>.sslip.io --instant-deploy --format=json
coolify app env create <uuid> --key PORT --value 80 --format=json
coolify deploy uuid <uuid> --force --format=json
coolify app deployments list <uuid> --format=json
curl -I http://myapp.<ip>.sslip.io
```
don't have the plugin yet? install it then click "run inline in claude" again.
added explicit inputs with auth/external connection details, numbered procedure steps with inline edge cases, decision points for common failure modes (private vs public repos, unhealthy status, missing env vars), detailed output contract in JSON format, and clear outcome signals for success vs failure.
deploy and manage applications on Coolify infrastructure using the official CLI. use this skill when creating new apps from GitHub repos, redeploying after code changes, managing environment variables, or debugging unhealthy deployments. the CLI-first approach keeps deployments visible in the Coolify UI and enables push-to-deploy automation. fall back to direct Docker/Traefik only if Coolify app creation is blocked.
Coolify CLI context
coolify command installed and on PATHcoolify context verify)Application metadata
server_uuid: Coolify server identifierproject_uuid: Coolify project identifierenvironment_name: deployment target, usually productionapp_name: human-readable app identifiergit_repository: owner/repo format (e.g. acme/myapp)git_branch: branch to deploy, typically mainbuild_pack: build strategy, typically dockerfileports_exposes: container port to expose, typically 80domains: public domain(s) for the app (e.g. http://myapp.1.2.3.4.sslip.io)GitHub integration (private repos only)
github_app_uuid: UUID of configured GitHub App in Coolify (get from coolify github list --format=json)External connection: Coolify Server
coolify CLI context (SSH key or token)External connection: GitHub (for private repos)
app create github to fail silently; verify app UUID with coolify github listinput: Coolify CLI installed, authenticated context
procedure: run context verification and list available GitHub apps and existing apps.
coolify context verify
coolify github list --format=json
coolify app list --format=json
output: JSON output confirming active context, available GitHub Apps with UUIDs, and existing apps. if context fails, stop and reconfigure auth.
edge cases: if coolify command not found, install from official docs. if context verify fails, Coolify server is unreachable or credentials are stale.
input: verified context, server_uuid, project_uuid, github_app_uuid (if private repo), git_repository, git_branch, app_name, domains, ports_exposes
procedure: invoke CLI to create new app. use app create github for private repos (supply github_app_uuid). use app create public only for public GitHub repos to avoid GitHub App dependency.
coolify app create github \
--server-uuid <server_uuid> \
--project-uuid <project_uuid> \
--environment-name production \
--github-app-uuid <github_app_uuid> \
--git-repository <owner>/<repo> \
--git-branch <branch> \
--build-pack dockerfile \
--ports-exposes <port> \
--name <app_name> \
--domains <domain> \
--instant-deploy \
--format=json
output: JSON response containing app_uuid, status (typically pending or queued), and deployment metadata. capture app_uuid for subsequent commands.
edge cases: if app creation returns status failed with auth error, verify github_app_uuid exists and has read permission on repo. if CLI hangs for >30s, Coolify API is slow or unreachable; retry with timeout flag. if creation succeeds but returns no app_uuid in response, API response format changed; check CLI version compatibility.
input: app_uuid from step 2, environment variable name and value (e.g. PORT=80, NODE_ENV=production)
procedure: create or update env vars one at a time. common vars: PORT (required for nginx templating), NODE_ENV, DATABASE_URL.
coolify app env create <app_uuid> --key <KEY> --value <VALUE> --format=json
output: JSON response confirming env var created with key, value, and timestamp.
edge cases: if env var update returns not found error, app_uuid is invalid or app not yet fully provisioned; wait 10-15s and retry. if nginx template expects ${PORT} but var not set, deployment will fail with templating error.
input: app_uuid, optionally git_branch override
procedure: trigger immediate redeployment. use --force to bypass cache. useful after env var changes or to retry after transient failures.
coolify deploy uuid <app_uuid> --force --format=json
output: JSON response with new deployment UUID and status (queued, building, etc.).
edge cases: if force redeploy returns app currently deploying error, wait 30-60s for current deploy to finish before retrying. if redeploy starts but immediately moves to exited:unhealthy, check logs in step 5.
input: app_uuid, deployed domain
procedure: check both Coolify app status and HTTP connectivity. pull latest deployment logs if status is not healthy.
coolify app get <app_uuid> --format=json
coolify app deployments list <app_uuid> --format=json
coolify app deployments logs <app_uuid>
curl -I http://<domain>
output: app status JSON (check statuses.main field for health), deployment list JSON showing completed deployments, deployment logs (raw text), HTTP response code from curl (expect 200 or 3xx redirect).
edge cases: if curl -I returns connection refused, app container may not be listening on exposed port or Traefik routing not yet configured. wait 10-20s and retry. if app status shows running:unknown but curl returns 200, treat as success (Coolify status may lag). if logs show build failed or container exited, review build errors below in decision points.
if private GitHub repo: use app create github with --github-app-uuid <uuid>. get UUID from coolify github list --format=json. if UUID is wrong or GitHub App lacks permission, creation will fail with auth error. verify app UUID and repo access before retrying.
if public GitHub repo: optionally use app create public (no GitHub App UUID needed). if public creation fails but private creation works, repo may have changed to private.
if app status is exited:unhealthy or exited:error: check deployment logs via coolify app deployments logs <app_uuid>. common causes:
PORT, DATABASE_URL): add via step 3--ports-exposes specifies port Y; add env var PORT=Y and redeployif app uses Vite, Rollup, or native modules and build fails on Alpine: use Debian-based Node image (node:20-slim instead of node:20-alpine). Alpine lacks libc and build tools needed for native modules. update Dockerfile and redeploy.
if nginx template error (${PORT} not substituted): env var PORT is not set. run step 3 with --key PORT --value <port> (typically 80 or 3000) and force redeploy (step 4).
if domain responds with HTTP 200 but Coolify UI still shows running:unknown: UI status may lag or reflect a transient state during initialization. treat successful HTTP response + finished deployment as success. if domain returns error (5xx, timeout), check app logs.
if CLI command times out or returns network error: Coolify API is slow or unreachable. wait 30s and retry. if persistent, check Coolify server status and network connectivity.
if no Coolify CLI-managed app creation is possible (e.g. server is down, quota exceeded): fallback to direct Docker + Traefik routing. see references/coolify-api.md for direct API patterns. this approach will not appear in Coolify UI and does not support push-to-deploy.
successful app creation: JSON response with fields:
app_uuid: string, used for all subsequent commandsname: string, matches --name inputstatus: string, one of pending, queued, building, runningdomains: array of strings, public access URLssuccessful deployment: JSON response with fields:
deployment_uuid: stringstatus: string, one of queued, building, running, exited:success, exited:error, exited:unhealthycreated_at: ISO timestampsuccessful verification: all of:
status: "running" or statuses.main: "running"exited:successcurl -I <domain> returns HTTP 200, 301, or 302 (not 5xx, not connection refused)ERROR or FAILED entries in final 20 linesenv var creation: JSON response with fields:
key: stringvalue: stringcreated_at: ISO timestampall commands use --format=json to ensure parseable output. raw text output (logs, curl) is human-readable but not JSON.
runningexited:success statusfailed outcome: domain returns connection error, 5xx status, or timeout; app status is exited:error or exited:unhealthy; logs show build or runtime errors; commands return auth or timeout errors.