Coolify Management
Analyze Coolify applications, services, deployments, and server health.
Phase 1: Discovery
#!/bin/bash
TOKEN="${COOLIFY_API_TOKEN}"
BASE="${COOLIFY_BASE_URL:-https://app.coolify.io}/api/v1"
AUTH=(-H "Authorization: Bearer ${TOKEN}" -H "Accept: application/json")
echo "=== Servers ==="
curl -s "${BASE}/servers" "${AUTH[@]}" \
| jq -r '.[] | "\(.id)\t\(.name)\t\(.ip)\t\(.settings.is_reachable)\t\(.settings.is_usable)"' \
| column -t | head -10
echo ""
echo "=== Applications ==="
curl -s "${BASE}/applications" "${AUTH[@]}" \
| jq -r '.[] | "\(.uuid)\t\(.name)\t\(.status)\t\(.fqdn // "no-domain")\t\(.build_pack)\t\(.git_repository // "dockerimage")"' \
| column -t | head -20
echo ""
echo "=== Services ==="
curl -s "${BASE}/services" "${AUTH[@]}" \
| jq -r '.[] | "\(.uuid)\t\(.name)\t\(.status)\t\(.type)"' \
| column -t | head -20
echo ""
echo "=== Databases ==="
curl -s "${BASE}/databases" "${AUTH[@]}" \
| jq -r '.[] | "\(.uuid)\t\(.name)\t\(.type)\t\(.status)\t\(.is_public)"' \
| column -t | head -20
echo ""
echo "=== Teams ==="
curl -s "${BASE}/teams" "${AUTH[@]}" \
| jq -r '.[] | "\(.id)\t\(.name)\t\(.members | length) members"' \
| column -t
Phase 2: Analysis
#!/bin/bash
TOKEN="${COOLIFY_API_TOKEN}"
BASE="${COOLIFY_BASE_URL:-https://app.coolify.io}/api/v1"
AUTH=(-H "Authorization: Bearer ${TOKEN}" -H "Accept: application/json")
echo "=== Application Details ==="
for APP_UUID in $(curl -s "${BASE}/applications" "${AUTH[@]}" | jq -r '.[].uuid'); do
curl -s "${BASE}/applications/${APP_UUID}" "${AUTH[@]}" \
| jq '{name, status, fqdn, build_pack, git_repository, git_branch, docker_compose_location, health_check_path, health_check_enabled, limits_memory, limits_cpus}' 2>/dev/null
done | head -30
echo ""
echo "=== Recent Deployments ==="
for APP_UUID in $(curl -s "${BASE}/applications" "${AUTH[@]}" | jq -r '.[].uuid'); do
APP_NAME=$(curl -s "${BASE}/applications/${APP_UUID}" "${AUTH[@]}" | jq -r '.name')
curl -s "${BASE}/applications/${APP_UUID}/deployments" "${AUTH[@]}" \
| jq -r ".[:3][] | \"${APP_NAME}\t\(.status)\t\(.created_at)\t\(.deployment_uuid[0:8])\"" 2>/dev/null
done | column -t | head -20
echo ""
echo "=== Server Resources ==="
for SERVER_ID in $(curl -s "${BASE}/servers" "${AUTH[@]}" | jq -r '.[].id'); do
curl -s "${BASE}/servers/${SERVER_ID}/resources" "${AUTH[@]}" \
| jq '{server_id: "'${SERVER_ID}'", applications: (.applications | length), databases: (.databases | length), services: (.services | length)}' 2>/dev/null
done
echo ""
echo "=== Environment Variables (counts) ==="
for APP_UUID in $(curl -s "${BASE}/applications" "${AUTH[@]}" | jq -r '.[].uuid'); do
APP_NAME=$(curl -s "${BASE}/applications/${APP_UUID}" "${AUTH[@]}" | jq -r '.name')
COUNT=$(curl -s "${BASE}/applications/${APP_UUID}/envs" "${AUTH[@]}" | jq 'length' 2>/dev/null)
echo "${APP_NAME}: ${COUNT:-0} env vars"
done
echo ""
echo "=== S3 Storage Configs ==="
curl -s "${BASE}/s3" "${AUTH[@]}" \
| jq -r '.[] | "\(.name)\t\(.endpoint)\t\(.bucket)\t\(.is_usable)"' \
| column -t
Output Format
COOLIFY ANALYSIS
=================
App Status Build-Pack Domain Last Deploy Health
──────────────────────────────────────────────────────────────────────────────
web-frontend running nixpacks app.example.com 2h ago enabled
api-backend running dockerfile api.example.com 1d ago enabled
worker running docker none 3h ago disabled
Servers: 2 reachable | Databases: 3 | Services: 2
Deployments: 15 recent (13 success, 2 failed)
Safety Rules
- Read-only: Only use GET endpoints against the Coolify API
- Never deploy, restart, or delete applications without confirmation
- Env vars: Never output environment variable values, only counts
- Self-hosted: Ensure base URL points to the correct Coolify instance
Anti-Hallucination Rules
- NEVER assume resource names — always discover via CLI/API in Phase 1 before referencing in Phase 2.
- NEVER fabricate metric names or dimensions — verify against the service documentation or
--help output.
- NEVER mix CLI commands between service versions — confirm which version/API you are targeting.
- ALWAYS use the discovery → verify → analyze chain — every resource referenced must have been discovered first.
- ALWAYS handle empty results gracefully — an empty response is valid data, not an error to retry.
Counter-Rationalizations
| Shortcut |
Counter |
Why |
| "I'll skip discovery and check known resources" |
Always run Phase 1 discovery first |
Resource names change, new resources appear — assumed names cause errors |
| "The user only asked for a quick check" |
Follow the full discovery → analysis flow |
Quick checks miss critical issues; structured analysis catches silent failures |
| "Default configuration is probably fine" |
Audit configuration explicitly |
Defaults often leave logging, security, and optimization features disabled |
| "Metrics aren't needed for this" |
Always check relevant metrics when available |
API/CLI responses show current state; metrics reveal trends and intermittent issues |
| "I don't have access to that" |
Try the command and report the actual error |
Assumed permission failures prevent useful investigation; actual errors are informative |
1---2name: managing-coolify3description: Use when working with Coolify — coolify self-hosted PaaS management covering application inventory, service status, deployment history, server resource utilization, database instances, S3 storage configurations, webhook settings, and team management. Use for managing Coolify-based infrastructure.4---56# Coolify Management78Analyze Coolify applications, services, deployments, and server health.910## Phase 1: Discovery1112```bash13#!/bin/bash14TOKEN="${COOLIFY_API_TOKEN}"15BASE="${COOLIFY_BASE_URL:-https://app.coolify.io}/api/v1"16AUTH=(-H "Authorization: Bearer ${TOKEN}" -H "Accept: application/json")1718echo "=== Servers ==="19curl -s "${BASE}/servers" "${AUTH[@]}" \20 | jq -r '.[] | "\(.id)\t\(.name)\t\(.ip)\t\(.settings.is_reachable)\t\(.settings.is_usable)"' \21 | column -t | head -102223echo ""24echo "=== Applications ==="25curl -s "${BASE}/applications" "${AUTH[@]}" \26 | jq -r '.[] | "\(.uuid)\t\(.name)\t\(.status)\t\(.fqdn // "no-domain")\t\(.build_pack)\t\(.git_repository // "dockerimage")"' \27 | column -t | head -202829echo ""30echo "=== Services ==="31curl -s "${BASE}/services" "${AUTH[@]}" \32 | jq -r '.[] | "\(.uuid)\t\(.name)\t\(.status)\t\(.type)"' \33 | column -t | head -203435echo ""36echo "=== Databases ==="37curl -s "${BASE}/databases" "${AUTH[@]}" \38 | jq -r '.[] | "\(.uuid)\t\(.name)\t\(.type)\t\(.status)\t\(.is_public)"' \39 | column -t | head -204041echo ""42echo "=== Teams ==="43curl -s "${BASE}/teams" "${AUTH[@]}" \44 | jq -r '.[] | "\(.id)\t\(.name)\t\(.members | length) members"' \45 | column -t46```4748## Phase 2: Analysis4950```bash51#!/bin/bash52TOKEN="${COOLIFY_API_TOKEN}"53BASE="${COOLIFY_BASE_URL:-https://app.coolify.io}/api/v1"54AUTH=(-H "Authorization: Bearer ${TOKEN}" -H "Accept: application/json")5556echo "=== Application Details ==="57for APP_UUID in $(curl -s "${BASE}/applications" "${AUTH[@]}" | jq -r '.[].uuid'); do58 curl -s "${BASE}/applications/${APP_UUID}" "${AUTH[@]}" \59 | jq '{name, status, fqdn, build_pack, git_repository, git_branch, docker_compose_location, health_check_path, health_check_enabled, limits_memory, limits_cpus}' 2>/dev/null60done | head -306162echo ""63echo "=== Recent Deployments ==="64for APP_UUID in $(curl -s "${BASE}/applications" "${AUTH[@]}" | jq -r '.[].uuid'); do65 APP_NAME=$(curl -s "${BASE}/applications/${APP_UUID}" "${AUTH[@]}" | jq -r '.name')66 curl -s "${BASE}/applications/${APP_UUID}/deployments" "${AUTH[@]}" \67 | jq -r ".[:3][] | \"${APP_NAME}\t\(.status)\t\(.created_at)\t\(.deployment_uuid[0:8])\"" 2>/dev/null68done | column -t | head -206970echo ""71echo "=== Server Resources ==="72for SERVER_ID in $(curl -s "${BASE}/servers" "${AUTH[@]}" | jq -r '.[].id'); do73 curl -s "${BASE}/servers/${SERVER_ID}/resources" "${AUTH[@]}" \74 | jq '{server_id: "'${SERVER_ID}'", applications: (.applications | length), databases: (.databases | length), services: (.services | length)}' 2>/dev/null75done7677echo ""78echo "=== Environment Variables (counts) ==="79for APP_UUID in $(curl -s "${BASE}/applications" "${AUTH[@]}" | jq -r '.[].uuid'); do80 APP_NAME=$(curl -s "${BASE}/applications/${APP_UUID}" "${AUTH[@]}" | jq -r '.name')81 COUNT=$(curl -s "${BASE}/applications/${APP_UUID}/envs" "${AUTH[@]}" | jq 'length' 2>/dev/null)82 echo "${APP_NAME}: ${COUNT:-0} env vars"83done8485echo ""86echo "=== S3 Storage Configs ==="87curl -s "${BASE}/s3" "${AUTH[@]}" \88 | jq -r '.[] | "\(.name)\t\(.endpoint)\t\(.bucket)\t\(.is_usable)"' \89 | column -t90```9192## Output Format9394```95COOLIFY ANALYSIS96=================97App Status Build-Pack Domain Last Deploy Health98──────────────────────────────────────────────────────────────────────────────99web-frontend running nixpacks app.example.com 2h ago enabled100api-backend running dockerfile api.example.com 1d ago enabled101worker running docker none 3h ago disabled102103Servers: 2 reachable | Databases: 3 | Services: 2104Deployments: 15 recent (13 success, 2 failed)105```106107## Safety Rules108109- **Read-only**: Only use GET endpoints against the Coolify API110- **Never deploy, restart, or delete** applications without confirmation111- **Env vars**: Never output environment variable values, only counts112- **Self-hosted**: Ensure base URL points to the correct Coolify instance113114## Anti-Hallucination Rules1151161. **NEVER assume resource names** — always discover via CLI/API in Phase 1 before referencing in Phase 2.1172. **NEVER fabricate metric names or dimensions** — verify against the service documentation or `--help` output.1183. **NEVER mix CLI commands between service versions** — confirm which version/API you are targeting.1194. **ALWAYS use the discovery → verify → analyze chain** — every resource referenced must have been discovered first.1205. **ALWAYS handle empty results gracefully** — an empty response is valid data, not an error to retry.121122## Counter-Rationalizations123124| Shortcut | Counter | Why |125|----------|---------|-----|126| "I'll skip discovery and check known resources" | Always run Phase 1 discovery first | Resource names change, new resources appear — assumed names cause errors |127| "The user only asked for a quick check" | Follow the full discovery → analysis flow | Quick checks miss critical issues; structured analysis catches silent failures |128| "Default configuration is probably fine" | Audit configuration explicitly | Defaults often leave logging, security, and optimization features disabled |129| "Metrics aren't needed for this" | Always check relevant metrics when available | API/CLI responses show current state; metrics reveal trends and intermittent issues |130| "I don't have access to that" | Try the command and report the actual error | Assumed permission failures prevent useful investigation; actual errors are informative |131