This document describes the Coolify deployment workflow provided by the automation-templates repository. The workflow enables standardized, automated deployments to Coolify-hosted applications via the Coolify REST API.
The Coolify deployment workflow provides:
- REST API Integration: Direct integration with Coolify's REST API for programmatic deployments
- Wait for Completion: Optional polling for deployment status
- Force Rebuild: Trigger complete rebuilds when needed
- Tag-based Deployment: Deploy specific image versions
- Error Handling: Comprehensive error handling with detailed messages
- Status Tracking: Real-time deployment status with GitHub job summaries
Coolify offers two deployment methods:
| Method | Trigger | Use Case |
|---|---|---|
| GitHub App (Webhooks) | Automatic on every push | Simple projects, auto-deploy |
| REST API (this workflow) | Manual/controlled via GitHub Actions | CI/CD pipelines, multi-environment |
Use this REST API workflow when:
- You build Docker images externally (in GitHub Actions) before deploying
- You need deployments only after tests/scans pass
- You have multiple environments (staging → production)
- You want deployment status feedback in GitHub Actions
- You need manual approval gates
Use the GitHub App when:
- You want automatic deployments on every push
- Coolify builds your Docker image
- You have a simple single-environment setup
Note: If you use the GitHub App with Auto Deploy enabled, you don't need this workflow. Webhooks are handled automatically by the GitHub App integration.
name: Deploy to Coolify
on:
push:
branches: [main]
jobs:
deploy:
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'your-app-uuid-here'
secrets: inheritname: Deploy to Coolify
on:
push:
branches: [main]
jobs:
deploy:
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'your-app-uuid-here'
wait-for-completion: true
wait-timeout: 600
secrets: inherit| Parameter | Type | Description |
|---|---|---|
coolify-url |
string | Coolify instance URL (without trailing slash) |
app-uuid |
string | UUID of the Coolify application to deploy |
| Parameter | Type | Default | Description |
|---|---|---|---|
force |
boolean | false |
Force a complete rebuild of the application |
tag |
string | '' |
Specific image tag to deploy (empty = latest) |
wait-for-completion |
boolean | false |
Wait for deployment to complete before finishing |
wait-timeout |
number | 300 |
Timeout in seconds when waiting for completion |
fail-on-error |
boolean | true |
Fail the workflow if deployment fails or times out |
runs-on |
string | ubuntu-latest |
Runner to use (String or JSON array) |
The runs-on parameter supports both GitHub-hosted and self-hosted runners:
# GitHub-hosted (string)
runs-on: 'ubuntu-latest'
# Self-hosted (JSON array)
runs-on: '["self-hosted", "linux"]'
runs-on: '["self-hosted", "linux", "docker"]'See Self-Hosted Runner Documentation for details.
| Secret | Required | Description |
|---|---|---|
COOLIFY_API_TOKEN |
Yes | API token for Coolify authentication |
| Output | Type | Description |
|---|---|---|
deployment-id |
string | UUID of the triggered deployment |
deployment-status |
string | Final status: started, success, failed, timeout |
deployment-url |
string | URL to view the deployment in Coolify |
The default mode triggers the deployment and completes immediately without waiting:
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'abc123'
# wait-for-completion: false (default)Pros:
- Fastest workflow execution
- No timeout concerns
- Suitable for non-critical deployments
Cons:
- No immediate feedback on deployment success
- Must check Coolify dashboard for status
Polls the Coolify API until deployment finishes:
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'abc123'
wait-for-completion: true
wait-timeout: 600 # 10 minutesPros:
- Immediate feedback in GitHub Actions
- Can trigger subsequent jobs based on success
- Clear failure indication in workflow
Cons:
- Longer workflow execution time
- Consumes GitHub Actions minutes while polling
When wait-for-completion is enabled, the workflow tracks these statuses:
| Status | Description | Workflow Result |
|---|---|---|
success / finished / deployed |
Deployment completed successfully | Success |
failed / error / cancelled |
Deployment failed | Failure (if fail-on-error: true) |
running / pending / queued / building |
Deployment in progress | Continue polling |
timeout |
Wait timeout exceeded | Failure (if fail-on-error: true) |
jobs:
deploy:
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'abc123'
tag: 'v1.2.3'
secrets: inheritjobs:
deploy:
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'abc123'
force: true
secrets: inheritjobs:
deploy:
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'abc123'
wait-for-completion: true
secrets: inherit
notify:
name: Send Notification
needs: deploy
if: always()
runs-on: ubuntu-latest
steps:
- name: Notify on Success
if: needs.deploy.outputs.deployment-status == 'success'
run: echo "Deployment successful!"
- name: Notify on Failure
if: needs.deploy.outputs.deployment-status == 'failed'
run: echo "Deployment failed!"jobs:
build:
uses: bauer-group/automation-templates/.github/workflows/docker-build.yml@main
with:
publish-to: 'ghcr'
ghcr-image-name: 'my-org/my-app'
auto-tags: true
secrets: inherit
deploy:
needs: build
if: github.ref == 'refs/heads/main'
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'abc123'
wait-for-completion: true
secrets: inheritjobs:
build:
uses: bauer-group/automation-templates/.github/workflows/docker-build.yml@main
with:
publish-to: 'ghcr'
auto-tags: true
secrets: inherit
deploy-staging:
needs: build
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'staging-app-uuid'
wait-for-completion: true
secrets: inherit
deploy-production:
needs: deploy-staging
if: github.ref == 'refs/heads/main'
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'production-app-uuid'
wait-for-completion: true
wait-timeout: 900
secrets: inherit- Navigate to:
github.com/organizations/YOUR-ORG/settings/secrets/actions - Click "New organization secret"
- Name:
COOLIFY_API_TOKEN - Value: Your Coolify API token
- Repository access: Select repositories or "All repositories"
- Navigate to:
github.com/YOUR-ORG/YOUR-REPO/settings/secrets/actions - Click "New repository secret"
- Name:
COOLIFY_API_TOKEN - Value: Your Coolify API token
- Open your Coolify dashboard
- Navigate to: Security > API Tokens
- Click "Create New Token"
- Enter a descriptive name:
GitHub Actions - YOUR-REPO - Copy the token immediately - it is only shown once!
- Store as GitHub secret:
COOLIFY_API_TOKEN
Important: The REST API must be enabled in Coolify. If you see "API not enabled", go to Settings and enable the REST API.
| Code | Error | Resolution |
|---|---|---|
401 |
Unauthorized | Check COOLIFY_API_TOKEN is valid |
403 |
Forbidden | Verify token has deployment permissions |
404 |
Not Found | Check app-uuid is correct |
422 |
Validation Error | Review request parameters |
429 |
Rate Limited | Wait and retry, or reduce deployment frequency |
5xx |
Server Error | Coolify server issue, retry later |
1. "COOLIFY_API_TOKEN secret is not set"
- Ensure the secret is configured at organization or repository level
- Check the secret name matches exactly:
COOLIFY_API_TOKEN - Verify repository has access to organization secrets
2. "Application not found"
- Verify the
app-uuidis correct - Check the application exists in Coolify
- Ensure the API token has access to this application
3. "Deployment timed out"
- Increase
wait-timeoutvalue - Check Coolify server performance
- Review application logs in Coolify
4. "Cannot wait for completion - no deployment ID"
- Some Coolify versions may not return deployment IDs
- Deployment was likely triggered successfully
- Check Coolify dashboard for status
The workflow uses the Coolify REST API. The API base URL is https://your-coolify-instance.com/api/v1.
Triggers a deployment for one or more applications.
GET /api/v1/deployQuery Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
uuid |
string | Yes | Application UUID (comma-separated for multiple) |
force |
boolean | No | Force rebuild without cache (default: false) |
tag |
string | No | Specific image tag to deploy |
Headers:
Authorization: Bearer <COOLIFY_API_TOKEN>
Accept: application/jsonResponse (200 OK):
{
"deployments": [
{
"message": "Deployment started",
"resource_uuid": "abc123",
"deployment_uuid": "dep-xyz-789"
}
]
}You can also trigger a deployment for a specific application:
GET /api/v1/applications/{uuid}/start
POST /api/v1/applications/{uuid}/startCheck the status of a running deployment:
GET /api/v1/deployments/{deployment_uuid}Response:
{
"status": "running",
"started_at": "2024-01-15T10:30:00Z",
"finished_at": null,
"logs": "..."
}For the complete API reference, see the Coolify API Documentation.
For production deployments, always enable wait-for-completion:
with:
wait-for-completion: true
wait-timeout: 600
fail-on-error: trueUse GitHub Actions job dependencies for staged rollouts:
jobs:
deploy-staging:
# ...
deploy-production:
needs: deploy-staging
# Only runs if staging succeedsDeploy specific versions instead of latest:
with:
tag: ${{ github.ref_name }} # Use Git tag as image tagConfigure timeouts based on your application:
| Application Type | Recommended Timeout |
|---|---|
| Static sites | 120s |
| Node.js apps | 300s |
| Large applications | 600s |
| Applications with migrations | 900s |
Use fail-on-error: false for non-blocking deployments:
with:
wait-for-completion: true
fail-on-error: false
# Then check status in subsequent stepsSee docker-build.md for Docker build configuration.
jobs:
build:
uses: bauer-group/automation-templates/.github/workflows/docker-build.yml@main
with:
publish-to: 'ghcr'
secrets: inherit
deploy:
needs: build
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
with:
coolify-url: 'https://coolify.example.com'
app-uuid: 'your-app-uuid'
secrets: inheritCombine with Teams notifications for deployment alerts:
jobs:
deploy:
uses: bauer-group/automation-templates/.github/workflows/coolify-deploy.yml@main
# ...
notify:
needs: deploy
if: always()
uses: bauer-group/automation-templates/.github/workflows/teams-notifications.yml@main
with:
status: ${{ needs.deploy.outputs.deployment-status }}
secrets: inheritCheck the workflow logs for detailed information:
- Go to Actions tab in your repository
- Click on the failed workflow run
- Expand the "Deploy to Coolify" job
- Review step outputs for error messages
curl -X GET \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Accept: application/json" \
"https://coolify.example.com/api/v1/deploy?uuid=YOUR_UUID&force=false"- Open Coolify dashboard
- Navigate to your application
- The UUID is in the URL:
/project/xxx/application/YOUR-UUID
- Documentation: See examples in
github/workflows/examples/coolify-deploy/ - Issues: Report issues in the automation-templates repository
- Coolify Docs: https://coolify.io/docs