sc-dokploy · git:20260902.cfd6b22 · 2026-09-02 · sha256 8b963002137ea22c
sc-dokploy git:20260902.cfd6b22A
Immutable. This exact content is served forever at /api/v1/blob/8b963002137ea22c.
---
name: sc-dokploy
description: "Dokploy CRUD, audit, and debug. List/create/update/delete projects, applications, compose services, and domains via REST API. Find stale domains, duplicate hosts, and *.traefik.me leftovers. Inspect status and recent deployments."
use_when: "Use when the task matches this skill scope: Dokploy CRUD, audit, and debug. List/create/update/delete projects, applications, compose services, and domains via REST API. Find stale domains, duplicate hosts, and *.traefik.me leftovers. Inspect status and recent deployments."
do_not_use_when: "Do not use when the task is outside this skill scope or a more specific SI-Coder skill owns the requested outcome."
required_tools: []
security_constraints: "Never request, print, or persist plaintext credentials in chat/tool payloads; use SI-Coder safe credential handoffs."
references: []
compatibility: "Standalone SI-Coder; host invocation syntax and available tools may vary."
---
# /sc-dokploy — Dokploy CRUD & Audit
Use this skill when the user wants to inspect, change, or clean up Dokploy state directly (without redeploying code).
## Pre-requisites
- `DOKPLOY_API_URL`, `DOKPLOY_API_KEY` — Dokploy admin
- SSH fallback to the Dokploy host (for orphan swarm services / Traefik file CRUD the REST API does NOT expose): `ssh -i ~/.ssh/<your_key> <user>@<your-dokploy-host>` with passwordless sudo.
If missing, route to `/sc-onboarding`.
## REST vs SSH
Dokploy REST API covers projects, applications, compose, domains, deploy/start/stop, monitoring read. It does **NOT** cover:
- `docker service rm` (orphan swarm services)
- `rm /etc/dokploy/traefik/dynamic/<file>.yml` (orphan Traefik routers)
- container exec / kill / log tail beyond the dashboard
For those, SSH in directly. Useful one-liners:
```bash
ssh -i ~/.ssh/<your_key> <user>@<your-dokploy-host> 'sudo -n docker service ls'
ssh -i ~/.ssh/<your_key> <user>@<your-dokploy-host> 'sudo -n ls /etc/dokploy/traefik/dynamic/'
ssh -i ~/.ssh/<your_key> <user>@<your-dokploy-host> 'sudo -n docker service rm <name>'
ssh -i ~/.ssh/<your_key> <user>@<your-dokploy-host> 'sudo -n rm /etc/dokploy/traefik/dynamic/<name>.yml' # Traefik file watcher reloads in ~5-10s
```
**Orphan-service pattern**: when a Dokploy app is recreated, the old swarm service and its Traefik dynamic config can survive deletion. Both compete for the same `Host(...)` rule. Symptom: prod serves an old image even after a fresh deploy. Diagnosis: `docker service ls` shows two services for the same project, and two `.yml` files in `traefik/dynamic/` bind the same domain. Fix: remove the orphan file + service.
## CORE RULES
1. **Idempotency**: `domain.create` may 4xx on duplicate; treat that as a no-op, not an error.
2. **Don't delete domains blindly**: only delete domains via `audit.js`'s `selectDomainsToDelete` — keep the desired canonical host, drop `*.traefik.me` and duplicates.
3. **Never rename the Dokploy control host**: whatever hostname is in `DOKPLOY_API_URL` is the control plane. Never rewrite it inside scripts — read it from env.
4. **`x-api-key` header, not Bearer**: Dokploy uses `x-api-key`, NOT `Authorization: Bearer`.
## Scripts
### `projects.js` — Project CRUD
```bash
node scripts/projects.js list
node scripts/projects.js create <name>
node scripts/projects.js show <name>
```
### `apps.js` — Application CRUD
```bash
node scripts/apps.js list --project <name>
node scripts/apps.js show --project <name> --app <name>
node scripts/apps.js deploy --project <name> --app <name>
```
### `compose.js` — Compose service CRUD
```bash
node scripts/compose.js list --project <name>
node scripts/compose.js show --compose <composeName>
node scripts/compose.js env --compose <composeName>
node scripts/compose.js deploy --compose <composeName>
```
### `domains.js` — Domain CRUD
```bash
node scripts/domains.js list-app --app-id <id>
node scripts/domains.js list-compose --compose-id <id>
node scripts/domains.js create-app --app-id <id> --host <host> [--port N]
node scripts/domains.js create-compose --compose-id <id> --host <host> --port <n> --service <name>
node scripts/domains.js delete --domain-id <id>
```
### `audit.js` — Sweep
Reports across all projects:
- `*.traefik.me` placeholder hosts that should be removed
- Duplicate hosts on the same service
- Applications with no domain configured
- Compose services missing INSTANCE_SECRET
```bash
node scripts/audit.js [--fix] # --fix removes stale domains
```
### `debug.js` — Status & recent deployments
```bash
node scripts/debug.js status --project <name> --app <name>
node scripts/debug.js status --compose <composeName>
node scripts/debug.js deployments --app-id <id>
```
## API endpoint reference (Dokploy)
| Action | Endpoint | Method |
|---|---|---|
| List projects | `/project.all` | GET |
| Create project | `/project.create` | POST `{ name }` |
| Get application | `/application.one?applicationId=` | GET |
| Update application | `/application.update` | POST |
| Deploy application | `/application.deploy` | POST `{ applicationId }` |
| Get compose | `/compose.one?composeId=` | GET |
| Update compose | `/compose.update` | POST |
| Deploy compose | `/compose.deploy` | POST `{ composeId }` |
| Deploy compose template | `/compose.deployTemplate` | POST `{ environmentId, id }` |
| Create domain | `/domain.create` | POST |
| Delete domain | `/domain.delete` | POST `{ domainId }` |
| List GitHub providers | `/github.githubProviders` | GET |
| Save app GH provider | `/application.saveGithubProvider` | POST |
Auth: `x-api-key: <DOKPLOY_API_KEY>`.
## Note on logs
Dokploy build logs are NOT exposed over the REST API (as of this skill's last update). On deployment failure, point the user at the Dokploy dashboard:
`<DOKPLOY_API_URL without /api> → project → service → Deployments`
## Existing domain vs public-IP fallback
For a port-exposed managed service or webapp that can run without DNS, domain configuration is an enhancement, not an install dependency:
1. If the deployment/app already has a canonical domain and its DNS/TLS route is configured, **preserve and prefer that domain for browser/UI access**. Never replace a working existing domain with a newly invented subdomain.
2. If no domain is configured, do not block a healthy install solely for DNS. Keep the declared public port reachable on the server public IP when the app's security model allows it, and report `http://<public-ip>:<port>` as the fallback.
3. When both exist, the domain is the primary UI/embedded origin; public IP is fallback/diagnostic only.
4. Domain provider automation runs only for an explicit desired domain or an existing project domain that needs repair. Missing Hostinger/Cloudflare credentials must not cause an unrelated port-based runtime install to fail.
5. Existing-domain creation errors are idempotent no-ops. Do not delete or recreate a working route merely to make the automation own it.