kctl-dokploy 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. kctl_dokploy-0.5.0/.gitignore +33 -0
  2. kctl_dokploy-0.5.0/CHANGELOG.md +61 -0
  3. kctl_dokploy-0.5.0/PKG-INFO +18 -0
  4. kctl_dokploy-0.5.0/README.md +475 -0
  5. kctl_dokploy-0.5.0/e2e/.gitignore +3 -0
  6. kctl_dokploy-0.5.0/e2e/README.md +30 -0
  7. kctl_dokploy-0.5.0/e2e/fixtures/auth.ts +20 -0
  8. kctl_dokploy-0.5.0/e2e/package.json +15 -0
  9. kctl_dokploy-0.5.0/e2e/playwright.config.ts +15 -0
  10. kctl_dokploy-0.5.0/e2e/tests/smoke/connectivity.spec.ts +12 -0
  11. kctl_dokploy-0.5.0/pyproject.toml +46 -0
  12. kctl_dokploy-0.5.0/skills/dokploy-admin/SKILL.extra.md +289 -0
  13. kctl_dokploy-0.5.0/skills/dokploy-admin/SKILL.md +864 -0
  14. kctl_dokploy-0.5.0/src/kctl_dokploy/SKILL.extra.md +50 -0
  15. kctl_dokploy-0.5.0/src/kctl_dokploy/__init__.py +3 -0
  16. kctl_dokploy-0.5.0/src/kctl_dokploy/__main__.py +5 -0
  17. kctl_dokploy-0.5.0/src/kctl_dokploy/cli.py +270 -0
  18. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/__init__.py +0 -0
  19. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/aliases.py +94 -0
  20. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/applications.py +339 -0
  21. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/audit.py +488 -0
  22. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/autodeploy.py +212 -0
  23. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/backups.py +601 -0
  24. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/backups_flow.py +423 -0
  25. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/backups_pull.py +814 -0
  26. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/backups_restore.py +389 -0
  27. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/bulk.py +331 -0
  28. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/certificates.py +154 -0
  29. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/cluster.py +178 -0
  30. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/compose.py +659 -0
  31. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/config_cmd.py +150 -0
  32. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/dashboard.py +157 -0
  33. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/databases.py +378 -0
  34. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/deploy.py +843 -0
  35. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/deployments.py +324 -0
  36. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/diagnose.py +986 -0
  37. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/docker.py +172 -0
  38. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/doctor_cmd.py +82 -0
  39. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/domains.py +211 -0
  40. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/env.py +208 -0
  41. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/environments.py +167 -0
  42. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/git.py +218 -0
  43. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/maintenance.py +510 -0
  44. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/migrate.py +150 -0
  45. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/monitoring.py +182 -0
  46. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/mounts.py +151 -0
  47. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/notifications.py +239 -0
  48. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/patches.py +260 -0
  49. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/pipeline.py +570 -0
  50. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/ports.py +109 -0
  51. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/projects.py +162 -0
  52. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/redirects.py +105 -0
  53. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/registry.py +146 -0
  54. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/report.py +533 -0
  55. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/schedules.py +172 -0
  56. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/security_cmd.py +96 -0
  57. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/servers.py +345 -0
  58. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/settings.py +184 -0
  59. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/setup.py +760 -0
  60. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/skill_cmd.py +76 -0
  61. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/status.py +25 -0
  62. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/template.py +414 -0
  63. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/users.py +163 -0
  64. kctl_dokploy-0.5.0/src/kctl_dokploy/commands/volume_backups.py +237 -0
  65. kctl_dokploy-0.5.0/src/kctl_dokploy/core/__init__.py +0 -0
  66. kctl_dokploy-0.5.0/src/kctl_dokploy/core/async_client.py +27 -0
  67. kctl_dokploy-0.5.0/src/kctl_dokploy/core/callbacks.py +39 -0
  68. kctl_dokploy-0.5.0/src/kctl_dokploy/core/client.py +58 -0
  69. kctl_dokploy-0.5.0/src/kctl_dokploy/core/config.py +134 -0
  70. kctl_dokploy-0.5.0/src/kctl_dokploy/core/deploy_ops.py +535 -0
  71. kctl_dokploy-0.5.0/src/kctl_dokploy/core/deploy_validators.py +455 -0
  72. kctl_dokploy-0.5.0/src/kctl_dokploy/core/deployer.py +1315 -0
  73. kctl_dokploy-0.5.0/src/kctl_dokploy/core/exceptions.py +56 -0
  74. kctl_dokploy-0.5.0/src/kctl_dokploy/core/health_ops.py +158 -0
  75. kctl_dokploy-0.5.0/src/kctl_dokploy/core/helpers.py +122 -0
  76. kctl_dokploy-0.5.0/src/kctl_dokploy/core/lan_ip.py +51 -0
  77. kctl_dokploy-0.5.0/src/kctl_dokploy/core/local_reconciler.py +315 -0
  78. kctl_dokploy-0.5.0/src/kctl_dokploy/core/manifest.py +399 -0
  79. kctl_dokploy-0.5.0/src/kctl_dokploy/core/migration_manifest.py +87 -0
  80. kctl_dokploy-0.5.0/src/kctl_dokploy/core/migrator.py +515 -0
  81. kctl_dokploy-0.5.0/src/kctl_dokploy/core/notify_ops.py +306 -0
  82. kctl_dokploy-0.5.0/src/kctl_dokploy/core/output.py +8 -0
  83. kctl_dokploy-0.5.0/src/kctl_dokploy/core/plugins.py +57 -0
  84. kctl_dokploy-0.5.0/src/kctl_dokploy/core/preflight.py +495 -0
  85. kctl_dokploy-0.5.0/src/kctl_dokploy/core/resolve.py +146 -0
  86. kctl_dokploy-0.5.0/src/kctl_dokploy/core/troubleshoot.py +472 -0
  87. kctl_dokploy-0.5.0/src/kctl_dokploy/core/utils.py +93 -0
  88. kctl_dokploy-0.5.0/src/kctl_dokploy/core/validators.py +225 -0
  89. kctl_dokploy-0.5.0/tests/__init__.py +0 -0
  90. kctl_dokploy-0.5.0/tests/commands/__init__.py +0 -0
  91. kctl_dokploy-0.5.0/tests/commands/test_applications.py +130 -0
  92. kctl_dokploy-0.5.0/tests/commands/test_autodeploy.py +144 -0
  93. kctl_dokploy-0.5.0/tests/commands/test_backups.py +159 -0
  94. kctl_dokploy-0.5.0/tests/commands/test_backups_deleted_commands.py +52 -0
  95. kctl_dokploy-0.5.0/tests/commands/test_backups_flow.py +54 -0
  96. kctl_dokploy-0.5.0/tests/commands/test_backups_pull.py +567 -0
  97. kctl_dokploy-0.5.0/tests/commands/test_backups_restore.py +870 -0
  98. kctl_dokploy-0.5.0/tests/commands/test_certificates.py +110 -0
  99. kctl_dokploy-0.5.0/tests/commands/test_compose.py +149 -0
  100. kctl_dokploy-0.5.0/tests/commands/test_config_cmd.py +75 -0
  101. kctl_dokploy-0.5.0/tests/commands/test_dashboard.py +71 -0
  102. kctl_dokploy-0.5.0/tests/commands/test_databases.py +128 -0
  103. kctl_dokploy-0.5.0/tests/commands/test_deployments.py +104 -0
  104. kctl_dokploy-0.5.0/tests/commands/test_diagnose.py +113 -0
  105. kctl_dokploy-0.5.0/tests/commands/test_docker.py +102 -0
  106. kctl_dokploy-0.5.0/tests/commands/test_domains.py +129 -0
  107. kctl_dokploy-0.5.0/tests/commands/test_env.py +84 -0
  108. kctl_dokploy-0.5.0/tests/commands/test_git.py +103 -0
  109. kctl_dokploy-0.5.0/tests/commands/test_maintenance.py +138 -0
  110. kctl_dokploy-0.5.0/tests/commands/test_monitoring.py +85 -0
  111. kctl_dokploy-0.5.0/tests/commands/test_notifications.py +105 -0
  112. kctl_dokploy-0.5.0/tests/commands/test_pipeline.py +118 -0
  113. kctl_dokploy-0.5.0/tests/commands/test_projects.py +50 -0
  114. kctl_dokploy-0.5.0/tests/commands/test_registry.py +90 -0
  115. kctl_dokploy-0.5.0/tests/commands/test_servers.py +97 -0
  116. kctl_dokploy-0.5.0/tests/commands/test_service_logs_follow.py +42 -0
  117. kctl_dokploy-0.5.0/tests/commands/test_settings.py +86 -0
  118. kctl_dokploy-0.5.0/tests/commands/test_setup.py +161 -0
  119. kctl_dokploy-0.5.0/tests/commands/test_status.py +43 -0
  120. kctl_dokploy-0.5.0/tests/commands/test_users.py +110 -0
  121. kctl_dokploy-0.5.0/tests/conftest.py +174 -0
  122. kctl_dokploy-0.5.0/tests/core/__init__.py +0 -0
  123. kctl_dokploy-0.5.0/tests/core/test_client.py +114 -0
  124. kctl_dokploy-0.5.0/tests/core/test_config.py +134 -0
  125. kctl_dokploy-0.5.0/tests/core/test_deploy_ops.py +177 -0
  126. kctl_dokploy-0.5.0/tests/core/test_deploy_validators.py +484 -0
  127. kctl_dokploy-0.5.0/tests/core/test_deployer.py +671 -0
  128. kctl_dokploy-0.5.0/tests/core/test_exceptions.py +75 -0
  129. kctl_dokploy-0.5.0/tests/core/test_health_ops.py +57 -0
  130. kctl_dokploy-0.5.0/tests/core/test_lan_ip.py +36 -0
  131. kctl_dokploy-0.5.0/tests/core/test_local_reconciler.py +356 -0
  132. kctl_dokploy-0.5.0/tests/core/test_manifest.py +414 -0
  133. kctl_dokploy-0.5.0/tests/core/test_migrator.py +103 -0
  134. kctl_dokploy-0.5.0/tests/core/test_notify_ops.py +92 -0
  135. kctl_dokploy-0.5.0/tests/core/test_output.py +126 -0
  136. kctl_dokploy-0.5.0/tests/core/test_preflight.py +121 -0
  137. kctl_dokploy-0.5.0/tests/core/test_resolve.py +107 -0
  138. kctl_dokploy-0.5.0/tests/core/test_troubleshoot.py +180 -0
  139. kctl_dokploy-0.5.0/tests/core/test_utils.py +109 -0
  140. kctl_dokploy-0.5.0/tests/core/test_validators.py +126 -0
@@ -0,0 +1,33 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ *.egg
6
+ dist/
7
+ build/
8
+ .eggs/
9
+
10
+ # Virtual environments
11
+ .venv/
12
+ venv/
13
+
14
+ # IDE
15
+ .idea/
16
+ .vscode/
17
+ *.swp
18
+ *.swo
19
+
20
+ # Testing
21
+ .pytest_cache/
22
+ .coverage
23
+ htmlcov/
24
+ .mypy_cache/
25
+ .ruff_cache/
26
+
27
+ # OS
28
+ .DS_Store
29
+ Thumbs.db
30
+
31
+ # Environment
32
+ .env
33
+ .env.local
@@ -0,0 +1,61 @@
1
+ # Changelog
2
+
3
+ All notable changes to kctl-dokploy.
4
+
5
+ ## [0.4.3] — 2026-04-19
6
+
7
+ ### Added
8
+ - `backups pull` / `run-wait` / `download` log lines now carry an `[HH:MM:SS]`
9
+ wall-clock prefix. Operators can see elapsed time between phases (trigger →
10
+ S3 poll → download → decompress → drop-recreate → pg_restore) at a glance.
11
+ Implemented via a local `_TimestampedLog` wrapper that delegates to the
12
+ shared `OutputManager` — no cross-CLI behavior change.
13
+
14
+ ## [0.4.2] — 2026-04-19
15
+
16
+ ### Fixed
17
+ - `backups pull` (and `backups run-wait`) now discover backups under the
18
+ NEW hierarchical S3 layout used by current Dokploy versions. Previous
19
+ Dokploy releases wrote objects under a flat
20
+ `<backup.prefix>-<timestamp>.<ext>` layout; recent Dokploy versions now
21
+ write them under `<compose.appName>_<serviceName>/<backup.prefix>/<timestamp>.<ext>`
22
+ (falling back to `<compose.appName>/<backup.prefix>/<timestamp>.<ext>`
23
+ when no `serviceName` is set on the backup config). The pull helper was
24
+ only scanning `<backup.prefix>` and therefore picked stale files (or
25
+ timed out waiting for a fresh trigger) on upgraded instances. The
26
+ helper now scans all candidate prefixes and returns the globally-newest
27
+ object. Non-compose backup types (postgres/mysql/mariadb/mongo) retain
28
+ the single-prefix behavior. Matches are filtered by DB name as
29
+ defense-in-depth.
30
+
31
+ ## [0.4.1] — 2026-04-19
32
+
33
+ ### Added
34
+ - `backups pull <backup_id> --target-db ...` — one-command end-to-end flow:
35
+ trigger (optional) → wait → download → decompress → drop+recreate target
36
+ DB → pg_restore. Supports both Dokploy-managed target composes
37
+ (`--target-compose`) and raw postgres hosts (`--target-host` for local
38
+ dev). Auto-detects custom vs plain SQL format via PGDMP magic bytes.
39
+ - `backups run-wait <backup_id>` — trigger a manual backup and poll S3
40
+ until the new object appears. Prints the resulting S3 key.
41
+ - `backups download <s3_key> --destination <id>` — standalone S3 download
42
+ using a Dokploy destination's stored credentials.
43
+
44
+ ### Fixed
45
+ - `backups list-files` now talks to S3 directly via boto3, bypassing
46
+ Dokploy's buggy `/backup.listBackupFiles` endpoint. No longer errors
47
+ with "Input validation failed" when called without `--search`; lists
48
+ everything under the destination by default. Added `--prefix` for
49
+ S3-side filtering and `--limit` (default 200). Removed the `--server`
50
+ flag which was not actually needed for direct S3 access.
51
+ - `dokploy-admin` SKILL.extra.md runbook now matches the actual CLI
52
+ surface — previously documented 5 commands (`dump-compose`, `download`,
53
+ `run-wait`, `refresh`, `restore-local`) that had been removed in the
54
+ Dokploy-native redesign. `download` / `run-wait` / `pull` (formerly
55
+ `refresh`) are now re-introduced as thin boto3 helpers.
56
+
57
+ ### Notes
58
+ - SSH-based commands (`dump-compose`, `restore-local`, `refresh`) remain
59
+ deleted — the Dokploy-native SSE restore (`backups restore`) is the
60
+ right tool for Dokploy-managed targets. `backups pull` fills the gap
61
+ for dev loops targeting a raw postgres on the developer's workstation.
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.4
2
+ Name: kctl-dokploy
3
+ Version: 0.5.0
4
+ Summary: Kodemeio Dokploy CLI — manage Dokploy deployment platform
5
+ Requires-Python: >=3.12
6
+ Requires-Dist: boto3>=1.35.0
7
+ Requires-Dist: httpx>=0.28.0
8
+ Requires-Dist: kctl-lib>=0.4.0
9
+ Requires-Dist: pydantic>=2.10.0
10
+ Requires-Dist: pyyaml>=6.0.2
11
+ Requires-Dist: rich>=13.9.0
12
+ Requires-Dist: typer>=0.15.0
13
+ Provides-Extra: dev
14
+ Requires-Dist: mypy>=1.14.0; extra == 'dev'
15
+ Requires-Dist: pytest-httpx>=0.35.0; extra == 'dev'
16
+ Requires-Dist: pytest>=8.3.0; extra == 'dev'
17
+ Requires-Dist: ruff>=0.9.0; extra == 'dev'
18
+ Requires-Dist: types-pyyaml>=6.0.0; extra == 'dev'
@@ -0,0 +1,475 @@
1
+ # kctl-dokploy
2
+
3
+ Kodemeio Dokploy CLI -- manage your Dokploy deployment platform and run declarative 13-phase deployment pipelines.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ uv tool install ./packages/kctl-dokploy
9
+ ```
10
+
11
+ To upgrade after code changes:
12
+
13
+ ```bash
14
+ uv tool install --force --reinstall ./packages/kctl-dokploy
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```bash
20
+ # Configure connection (interactive)
21
+ kctl-dokploy config init
22
+
23
+ # Verify connectivity
24
+ kctl-dokploy config test
25
+
26
+ # Dashboard overview
27
+ kctl-dokploy dashboard show
28
+
29
+ # List all projects
30
+ kctl-dokploy projects list
31
+
32
+ # List all compose services
33
+ kctl-dokploy compose list
34
+ ```
35
+
36
+ ### Deploy Workflow
37
+
38
+ The primary workflow uses declarative YAML manifests stored in `deploys/instances/`.
39
+
40
+ ```bash
41
+ # Full deploy (all phases in one command)
42
+ kctl-dokploy deploy apply -f deploys/instances/production/mac-react-sfa.yaml
43
+
44
+ # Staged deploy (for troubleshooting)
45
+ kctl-dokploy deploy setup -f deploys/instances/production/mac-react-sfa.yaml # Stage 1
46
+ kctl-dokploy deploy run -f deploys/instances/production/mac-react-sfa.yaml # Stage 2
47
+ kctl-dokploy deploy post -f deploys/instances/production/mac-react-sfa.yaml # Stage 3
48
+
49
+ # Batch deploy all manifests in a directory
50
+ kctl-dokploy deploy apply-all -d deploys/instances/production/
51
+
52
+ # Validate a manifest without deploying
53
+ kctl-dokploy deploy validate -f deploys/instances/production/mac-react-sfa.yaml
54
+
55
+ # Check current state vs manifest (dry-run)
56
+ kctl-dokploy deploy status -f deploys/instances/production/mac-react-sfa.yaml
57
+
58
+ # Dry-run any stage
59
+ kctl-dokploy deploy apply -f deploys/instances/production/mac-react-sfa.yaml --dry-run
60
+ ```
61
+
62
+ ### Preflight Checks
63
+
64
+ ```bash
65
+ # Run preflight gates before deploying
66
+ kctl-dokploy deploy preflight -f deploys/instances/production/mac-react-sfa.yaml
67
+
68
+ # Run preflight for all manifests in a directory
69
+ kctl-dokploy deploy preflight-all -d deploys/instances/production/
70
+
71
+ # Filter by server
72
+ kctl-dokploy deploy preflight-all -d deploys/instances/production/ --server mac-prod-01
73
+
74
+ # Run specific gates only
75
+ kctl-dokploy deploy preflight -f <manifest> --gates dns,database,env_sync
76
+ ```
77
+
78
+ ### Troubleshooting
79
+
80
+ ```bash
81
+ # Diagnose a failed deployment by manifest
82
+ kctl-dokploy deploy troubleshoot -f deploys/instances/production/mac-react-sfa.yaml
83
+
84
+ # Diagnose by compose service ID
85
+ kctl-dokploy deploy troubleshoot --compose OEK_dJRQZZMo9HKbQrQ0z
86
+
87
+ # View deployment logs
88
+ kctl-dokploy compose deployments logs --compose <id>
89
+ ```
90
+
91
+ ### Live Container Log Streaming
92
+
93
+ `kctl-dokploy compose service-logs` fetches runtime container stdout/stderr
94
+ (the actual Odoo/postgres/etc. output — not Dokploy build logs). By default
95
+ it returns a snapshot; pass `-f` / `--follow` to stream until Ctrl-C.
96
+
97
+ ```bash
98
+ # Snapshot — last 200 lines for a specific service
99
+ kctl-dokploy compose service-logs <compose-id> --service odoo-web --tail 200
100
+
101
+ # Live tail — streams via SSH to the compose's server
102
+ kctl-dokploy compose service-logs <compose-id> --service odoo-web -f
103
+ ```
104
+
105
+ Remote streaming uses `ssh ... docker logs -f <container>` with a 10s
106
+ connect timeout and `StrictHostKeyChecking=accept-new`. Local composes
107
+ skip SSH and invoke `docker logs -f` directly. `kctl-odoo logs tail` wraps
108
+ this command for Odoo-specific filters (module, request, level).
109
+
110
+ ### Server Migration
111
+
112
+ ```bash
113
+ kctl-dokploy deploy migrate validate -f deploys/migrations/mac-to-dedicated.yaml
114
+ kctl-dokploy deploy migrate plan -f deploys/migrations/mac-to-dedicated.yaml
115
+ kctl-dokploy deploy migrate apply -f deploys/migrations/mac-to-dedicated.yaml
116
+ kctl-dokploy deploy migrate apply -f deploys/migrations/mac-to-dedicated.yaml --resume
117
+ kctl-dokploy deploy migrate rollback -f deploys/migrations/mac-to-dedicated.yaml
118
+ kctl-dokploy deploy migrate cleanup -f deploys/migrations/mac-to-dedicated.yaml
119
+ ```
120
+
121
+ ### Compose Postgres Backup → S3 → Local Restore
122
+
123
+ `backups restore` streams Dokploy's native SSE restore endpoint. Dokploy's server
124
+ does `pg_restore` via `docker exec` — no SSH or temp files from the client side.
125
+
126
+ **One-time setup** (register the S3 bucket on the target Dokploy):
127
+
128
+ ```bash
129
+ kctl-dokploy --profile local backups add-destination \
130
+ --name hz-tpp-postgres-backup --bucket hz-tpp-postgres-backup \
131
+ --access-key "$HZ_ACCESS" --secret-key "$HZ_SECRET" \
132
+ --region fsn1 --endpoint https://fsn1.your-objectstorage.com
133
+ ```
134
+
135
+ > Set destination `provider: "Other"` (not `"s3"`) for Hetzner Object Storage.
136
+ > rclone rejects `"s3"` as a provider value for this endpoint type.
137
+
138
+ **One-shot restore** (latest S3 key for a database):
139
+
140
+ ```bash
141
+ kctl-dokploy -p local backups restore \
142
+ --compose <local-compose-id> \
143
+ --destination <local-dest-id> \
144
+ --database-name tpp_odoo_erp \
145
+ --service-name postgres \
146
+ --database-user odoo \
147
+ --latest tpp_odoo_erp
148
+ ```
149
+
150
+ Streams log lines prefixed `[Dokploy]` to stdout. Exit 0 on success,
151
+ 1 on Dokploy error, 2 on transport/auth failure.
152
+
153
+ **Prerequisites:**
154
+ - Target DB must already exist with `OWNER=odoo` — Dokploy's restore does not create it.
155
+ Use `SERVICE_DATABASES` in the `kodemeio-postgres` compose env to pre-create on start.
156
+ - `odoo` role must be SUPERUSER on the target postgres instance.
157
+ - `--service-name` and `--database-user` are required; omitting either causes an
158
+ immediate exit 1 (empty `pg_restore -U ''` or wrong container).
159
+
160
+ See `runbooks/postgres-restore.md` for the full reference including historical-key
161
+ restore, metadata flag table, and common compose IDs.
162
+
163
+ ## Command Groups
164
+
165
+ ### Top-level Groups
166
+
167
+ | Group | Description |
168
+ |------------------|---------------------------------------------------------------------|
169
+ | `config` | CLI configuration (profiles, init, add, use, show, validate) |
170
+ | `projects` | Dokploy project CRUD and environment management |
171
+ | `applications` | Application service management (non-compose apps) |
172
+ | `compose` | Docker Compose service management (Dokploy's primary service type) |
173
+ | `servers` | Server management, monitoring, and cluster operations |
174
+ | `databases` | Managed database service management (Dokploy-managed DBs) |
175
+ | `registry` | Container registry configuration and access |
176
+ | `users` | User CRUD, roles, and invite management |
177
+ | `git` | Git provider integration (GitHub, GitLab, Bitbucket) |
178
+ | `notifications` | Notification channel management (Slack, email, webhook) |
179
+ | `certificates` | SSL/TLS certificate management |
180
+ | `settings` | Dokploy platform settings (SMTP, S3, general) |
181
+ | `docker` | Docker image and container utilities |
182
+ | `dashboard` | Platform overview and health summary |
183
+ | `diagnose` | Diagnostics, maintenance, and platform health checks |
184
+ | `deploy` | Declarative deployment pipeline (13-phase, manifest-driven) |
185
+ | `report` | Platform usage and deployment reports |
186
+ | `template` | Deployment template management |
187
+ | `audit` | Audit log queries and export |
188
+ | `setup` | Platform initial setup and onboarding |
189
+
190
+ ### Compose Sub-Groups
191
+
192
+ The `compose` group mirrors Dokploy's UI tabs for managing individual services:
193
+
194
+ | Sub-group | Description |
195
+ |-------------------|----------------------------------------------------------------|
196
+ | `compose backups` | Backup CRUD + native restore workflow (`restore`, `add-destination`, `destinations`, `list-files`) |
197
+ | `compose domains` | Traefik domain routing and SSL configuration |
198
+ | `compose env` | Environment variable management (push, pull, diff) |
199
+ | `compose deployments` | Deployment history, logs, and redeploy triggers |
200
+ | `compose schedules` | Cron job / scheduled task management |
201
+ | `compose patches` | Service patch application |
202
+ | `compose volume-backups` | Volume backup configuration |
203
+ | `compose mounts` | Volume mount management |
204
+ | `compose ports` | Port mapping management |
205
+ | `compose security` | Service-level security settings |
206
+ | `compose redirects` | HTTP redirect rules |
207
+ | `compose bulk` | Bulk operations across multiple compose services |
208
+
209
+ ### Server Sub-Groups
210
+
211
+ | Sub-group | Description |
212
+ |---------------------|------------------------------------------------------|
213
+ | `servers monitoring` | Server resource monitoring (CPU, memory, disk) |
214
+ | `servers cluster` | Swarm/cluster node management |
215
+
216
+ ### Project Sub-Groups
217
+
218
+ | Sub-group | Description |
219
+ |-------------------------|-------------------------------------------------|
220
+ | `projects environments` | Dokploy environment management per project |
221
+
222
+ ### Deploy Sub-Commands
223
+
224
+ | Sub-command | Description |
225
+ |--------------------------|--------------------------------------------------------------|
226
+ | `deploy apply` | All-in-one: run all 13 phases in sequence |
227
+ | `deploy apply-all` | Batch apply all manifests in a directory |
228
+ | `deploy setup` | Stage 1: DNS + DB + compose + env + domain (idempotent) |
229
+ | `deploy run` | Stage 2: trigger redeploy + wait for healthy |
230
+ | `deploy post` | Stage 3: backup config + schedules + post-deploy hooks |
231
+ | `deploy preflight` | Run pre-deploy gate checks on a single manifest |
232
+ | `deploy preflight-all` | Run pre-deploy gate checks on all manifests in a directory |
233
+ | `deploy validate` | Validate manifest YAML without deploying |
234
+ | `deploy verify` | Pre-deploy validation + post-deploy smoke tests |
235
+ | `deploy status` | Dry-run all phases to preview current state |
236
+ | `deploy list` | List all discovered manifests and their domains |
237
+ | `deploy troubleshoot` | Diagnose failed deployment (logs, health, error type) |
238
+ | `deploy migrate` | Server-to-server migration pipeline |
239
+
240
+ ## Deploy Pipeline
241
+
242
+ `kctl-dokploy deploy apply` runs a 13-phase pipeline orchestrating multiple kctl-* CLIs:
243
+
244
+ | # | Phase | CLI Used | Description |
245
+ |---|-------------|----------------|-----------------------------------------------------------|
246
+ | 0 | preflight | kctl-dokploy | 10 gates: server, firewall, DNS, image pull, DB, compose, env sync (OIDC), source, network, SSL |
247
+ | 1 | dns | kctl-cf | Create/verify Cloudflare DNS record |
248
+ | 2 | database | kctl-pg | Create PostgreSQL database + application role |
249
+ | 3 | registry | kctl-dokploy | Ensure container registry access configured |
250
+ | 4 | compose | kctl-dokploy | Create or update Dokploy compose service |
251
+ | 5 | environment | kctl-dokploy | Push env vars from manifest + env file |
252
+ | 6 | domain | kctl-dokploy | Configure Traefik domain routing + SSL |
253
+ | 7 | deploy | kctl-dokploy | Trigger redeploy |
254
+ | 8 | verify | kctl-dokploy | Wait for healthcheck to pass |
255
+ | 9 | backup | kctl-dokploy | Configure backup destination + schedule |
256
+ | 10 | schedules | kctl-dokploy | Set up cron jobs (vacuum, session cleanup, etc.) |
257
+ | 11 | volume-backups | kctl-dokploy | Configure volume backup destinations |
258
+ | 12 | post-deploy | kctl-odoo | Install Odoo bundles/profiles (for Odoo service types) |
259
+
260
+ ### Preflight Gates
261
+
262
+ The preflight phase runs 10 gates before any infrastructure changes:
263
+
264
+ | Gate | Checks |
265
+ |---------------|-------------------------------------------------------------|
266
+ | `server` | Dokploy API reachable, server exists in inventory |
267
+ | `firewall` | Required ports accessible |
268
+ | `dns` | DNS record exists and resolves correctly |
269
+ | `image_pull` | Container image pullable from registry |
270
+ | `database` | PostgreSQL credentials valid, DB server reachable |
271
+ | `compose` | Compose service in valid state (not mid-deploy) |
272
+ | `env_sync` | OIDC and required env vars present in env file |
273
+ | `source` | Git source branch/ref accessible |
274
+ | `network` | `dokploy-network` exists on target server |
275
+ | `ssl` | SSL certificate valid and not near expiry |
276
+
277
+ ### Manifest Format
278
+
279
+ Manifests follow the `{tenant}-{stack}-{app}.yaml` naming convention:
280
+
281
+ ```yaml
282
+ # deploys/instances/production/mac-react-sfa.yaml
283
+ extends: bases/react-pwa.yaml
284
+
285
+ instance:
286
+ name: mac-react-sfa
287
+
288
+ type: react-pwa
289
+ project: mac
290
+ server: mac-prod-01
291
+
292
+ domain:
293
+ host: sfa.mandiriagro.com
294
+
295
+ healthcheck:
296
+ path: /
297
+ expected_status: 200
298
+
299
+ env_file: deploys/env/production/mac-react-sfa.env
300
+ ```
301
+
302
+ ## Global Options
303
+
304
+ ```
305
+ --json Output as JSON (machine-readable)
306
+ --quiet, -q Suppress informational messages
307
+ --format, -f Output format: pretty, json, csv, yaml
308
+ --no-header Omit headers in CSV output
309
+ --debug Enable debug logging
310
+ --profile, -p Use a named config profile
311
+ --url Dokploy API URL override
312
+ --api-key API key override
313
+ --version, -V Show version and exit
314
+ ```
315
+
316
+ ## Command Aliases
317
+
318
+ Hidden short aliases are available for common operations:
319
+
320
+ | Alias | Expands to |
321
+ |-------|---------------------------|
322
+ | `cl` | `compose list` |
323
+ | `cs` | `compose start <id>` |
324
+ | `cr` | `compose redeploy <id>` |
325
+ | `sl` | `servers list` |
326
+ | `pl` | `projects list` |
327
+ | `ds` | `dashboard show` |
328
+ | `dg` | `diagnose run` |
329
+ | `dl` | `deployments list` |
330
+ | `bl` | `backups list` |
331
+
332
+ Example:
333
+
334
+ ```bash
335
+ kctl-dokploy cl # same as: kctl-dokploy compose list
336
+ kctl-dokploy cr OEK_dJRQZZMo9HKbQ # same as: kctl-dokploy compose redeploy <id>
337
+ ```
338
+
339
+ ## Configuration
340
+
341
+ ### Profiles
342
+
343
+ kctl-dokploy supports named profiles for managing multiple Dokploy instances:
344
+
345
+ ```bash
346
+ # Create a profile (interactive)
347
+ kctl-dokploy config init
348
+
349
+ # Add a profile manually
350
+ kctl-dokploy config add production \
351
+ --url https://dokploy.kodeme.io \
352
+ --api-key $DOKPLOY_API_KEY
353
+
354
+ # Add a staging profile
355
+ kctl-dokploy config add staging \
356
+ --url https://dokploy-stg.kodeme.io \
357
+ --api-key $DOKPLOY_STAGING_KEY
358
+
359
+ # Switch default profile
360
+ kctl-dokploy config use production
361
+
362
+ # Use per-command
363
+ kctl-dokploy --profile staging compose list
364
+
365
+ # List all profiles
366
+ kctl-dokploy config profiles
367
+
368
+ # Show current profile (secrets masked)
369
+ kctl-dokploy config show
370
+ ```
371
+
372
+ ### Config File
373
+
374
+ Configuration is stored in `~/.config/kodemeio/config.yaml` under the `dokploy` service key, shared with all other kctl-* CLIs.
375
+
376
+ ```yaml
377
+ # ~/.config/kodemeio/config.yaml (example shape)
378
+ profiles:
379
+ default: production
380
+ production:
381
+ dokploy:
382
+ url: https://dokploy.kodeme.io
383
+ api_key: ${DOKPLOY_API_KEY} # env var expansion supported
384
+ ```
385
+
386
+ ## Shell Completions
387
+
388
+ ```bash
389
+ # Generate and install for your shell
390
+ kctl-dokploy --install-completion bash
391
+ kctl-dokploy --install-completion zsh
392
+ kctl-dokploy --install-completion fish
393
+
394
+ # Or use the skill subcommand
395
+ kctl-dokploy skill completions install
396
+ ```
397
+
398
+ ## Plugin Development
399
+
400
+ kctl-dokploy supports extending the CLI via Python entry points. Create a package that registers a Typer app under the `kctl_dokploy.plugins` entry point group:
401
+
402
+ ```toml
403
+ # In your plugin's pyproject.toml
404
+ [project.entry-points."kctl_dokploy.plugins"]
405
+ my_plugin = "my_plugin.cli:app"
406
+ ```
407
+
408
+ The plugin's `app` (a `typer.Typer` instance) will be registered as a command group automatically on startup.
409
+
410
+ ## Development
411
+
412
+ ### Running Tests
413
+
414
+ ```bash
415
+ cd packages/kctl-dokploy
416
+ uv run pytest tests/ -v
417
+ ```
418
+
419
+ ### Linting and Formatting
420
+
421
+ ```bash
422
+ cd packages/kctl-dokploy
423
+ uv run ruff check src/
424
+ uv run ruff format src/
425
+ ```
426
+
427
+ ### Type Checking
428
+
429
+ ```bash
430
+ cd packages/kctl-dokploy
431
+ uv run mypy src/kctl_dokploy/
432
+ ```
433
+
434
+ ### Project Structure
435
+
436
+ ```
437
+ packages/kctl-dokploy/
438
+ src/kctl_dokploy/
439
+ cli.py Main app + command group registration
440
+ __init__.py Version (0.3.5)
441
+ core/
442
+ callbacks.py Global option handling (AppContext)
443
+ api_client.py HTTP client wrapping kctl-lib APIClient
444
+ deployer.py 13-phase Deployer class
445
+ manifest.py DeployManifest Pydantic model + YAML loader
446
+ preflight.py Preflight gate runner
447
+ troubleshoot.py Deployment diagnosis engine
448
+ deploy_validators.py Pre/post deploy validators
449
+ commands/
450
+ aliases.py Short command aliases
451
+ deploy.py Declarative deployment pipeline
452
+ compose.py Compose service management
453
+ servers.py Server management
454
+ projects.py Project management
455
+ diagnose.py Diagnostic commands
456
+ ... (30+ command modules)
457
+ tests/ pytest test suite
458
+ pyproject.toml Package metadata and tool config
459
+ README.md This file
460
+ ```
461
+
462
+ ### Workspace Commands
463
+
464
+ From the monorepo root:
465
+
466
+ ```bash
467
+ # Install all workspace packages
468
+ uv sync --all-extras --all-packages
469
+
470
+ # Run kctl-dokploy tests only
471
+ uv run pytest packages/kctl-dokploy/tests/ -v
472
+
473
+ # Lint all packages
474
+ uv run ruff check packages/*/src/
475
+ ```
@@ -0,0 +1,3 @@
1
+ node_modules/
2
+ playwright-report/
3
+ test-results/
@@ -0,0 +1,30 @@
1
+ # kctl-dokploy E2E Tests
2
+
3
+ Playwright-based E2E tests for kctl-dokploy against live staging services.
4
+
5
+ ## Setup
6
+
7
+ ```bash
8
+ pnpm install
9
+ pnpm run install-browsers
10
+ ```
11
+
12
+ ## Run
13
+
14
+ ```bash
15
+ # Against staging
16
+ export DOKPLOY_URL=https://dokploy.kodeme.io
17
+ export DOKPLOY_TOKEN=<your-token>
18
+ pnpm test
19
+
20
+ # Smoke tests only
21
+ pnpm test:smoke
22
+
23
+ # Visible browser
24
+ pnpm test:headed
25
+ ```
26
+
27
+ ## Env Vars
28
+
29
+ - `DOKPLOY_URL` — Base URL (default: https://dokploy.kodeme.io)
30
+ - `DOKPLOY_TOKEN` — API token
@@ -0,0 +1,20 @@
1
+ import { test as base } from "@playwright/test";
2
+
3
+ export interface AuthFixtures {
4
+ apiToken: string;
5
+ baseUrl: string;
6
+ }
7
+
8
+ export const test = base.extend<AuthFixtures>({
9
+ apiToken: async ({}, use) => {
10
+ const token = process.env.DOKPLOY_TOKEN;
11
+ if (!token) throw new Error("DOKPLOY_TOKEN env var required");
12
+ await use(token);
13
+ },
14
+ baseUrl: async ({}, use) => {
15
+ const url = process.env.DOKPLOY_URL || "https://dokploy.kodeme.io";
16
+ await use(url);
17
+ },
18
+ });
19
+
20
+ export { expect } from "@playwright/test";
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "kctl-dokploy-e2e",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "test": "playwright test",
7
+ "test:smoke": "playwright test --project=smoke",
8
+ "test:headed": "playwright test --headed",
9
+ "install-browsers": "playwright install chromium"
10
+ },
11
+ "devDependencies": {
12
+ "@playwright/test": "^1.48.0",
13
+ "typescript": "^5.5.0"
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ import { defineConfig } from "@playwright/test";
2
+
3
+ export default defineConfig({
4
+ testDir: "./tests",
5
+ timeout: 60_000,
6
+ retries: 1,
7
+ reporter: "list",
8
+ use: {
9
+ baseURL: process.env.DOKPLOY_URL || "https://dokploy.kodeme.io",
10
+ },
11
+ projects: [
12
+ { name: "smoke", testMatch: /smoke\/.*\.spec\.ts/ },
13
+ { name: "scenarios", testMatch: /scenarios\/.*\.spec\.ts/ },
14
+ ],
15
+ });
@@ -0,0 +1,12 @@
1
+ import { test, expect } from "../../fixtures/auth";
2
+
3
+ test.describe("Connectivity", () => {
4
+ test.skip(!process.env.DOKPLOY_TOKEN, "DOKPLOY_TOKEN not set");
5
+
6
+ test("API endpoint is reachable", async ({ request, apiToken, baseUrl }) => {
7
+ const response = await request.get(`${baseUrl}/api/health`, {
8
+ headers: { Authorization: `Bearer ${apiToken}` },
9
+ });
10
+ expect([200, 204]).toContain(response.status());
11
+ });
12
+ });