On cloud, StartService and DeployServiceApplication dispatched their
CoolifyTask on the high queue, so service starts competed with all other
high jobs. remote_process() and CoolifyTask now accept a queue (default
high); start paths pass deployment_queue(). The queued RestartDatabase
action also runs on deployment_queue() instead of the default queue.
An import task can now run until the SSH command timeout (capped below the
Horizon worker timeout). When the CoolifyTask fails, times out, or its SSH
command ends with 124/255, Coolify stops the restore in the database
container and keeps the import in progress until the stop has run, so the
database stays blocked. The restore reports its own 124/255 as 1.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- database import: add keep_owners (restore PostgreSQL owners and
privileges) and sqlite_database (pick the target SQLite file) to the
API, OpenAPI spec, and import form
- oauth: require password confirmation and support team selection on
OAuth login
- remote process: send team broadcast events to the team of the server
that ran the process instead of the causer's user id
- servers API: handle the legacy build server setting
- compose: support parent bind paths and volume driver options
- dns: improve record hints and provider management
- notifications: fix throttling and missing backup notifications
- ui: rework the confirmation modal
- add feature and unit tests for the new behavior
remote_process() stored the full shell command as plain text in
activity_log and kept it for 60 days. Database starts store the compose file
with the database passwords, imports store S3 keys, and the Cloudflare
tunnel setup stores its token.
- Store the command encrypted. The queue worker decrypts it right before the
SSH call and still reads plain commands of tasks queued before the upgrade.
- Remove the command when the task is finished: after a successful run, in
failed() when no attempt is left, and for a stopped import. A failed attempt
that the queue retries keeps it.
- Do not write a command preview into the error log.
- Migration: remove stored commands from activities that no longer run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Imports store their cleanup data (names and paths, no credentials)
on the activity. When Coolify fails an import after a restart or as
stale, it queues a stop of the restore inside the database container
(only processes of that operation and their children, bottom-up so
the database server is not affected) and the normal cleanup.
- The cleanup runs once per import, and a stopped CoolifyTask does
not run again when the queue retries it.
- The stop message stays on the activity: RunRemoteProcess saves the
process id at start from the stored properties and keeps a stop
status at the end, and CoolifyTask::failed() keeps the message.
- Regenerate the OpenAPI spec (409 for database start, restart, and
import, plus earlier API changes that were missing).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Major architectural improvements:
- Merged download and restore into single atomic operation
- Eliminated separate S3DownloadFinished event (redundant)
- Files now transfer directly: S3 → helper container → server → database container
- Removed download progress tracking in favor of unified restore progress
UI/UX improvements:
- Unified restore method selection with visual cards
- Consistent "File Information" display between local and S3 restore
- Single slide-over for all restore operations (removed separate S3 download monitor)
- Better visual feedback with loading states
Security enhancements:
- Added isSafeTmpPath() helper for path traversal protection
- URL decode validation to catch encoded attacks
- Canonical path resolution to prevent symlink attacks
- Comprehensive path validation in all cleanup events
Cleanup improvements:
- S3RestoreJobFinished now handles all cleanup (helper container + all temp files)
- RestoreJobFinished uses new isSafeTmpPath() validation
- CoolifyTask dispatches cleanup events even on job failure
- All cleanup uses non-throwing commands (2>/dev/null || true)
Other improvements:
- S3 storage policy authorization on Show component
- Storage Form properly syncs is_usable state after test
- Removed debug code and improved error handling
- Better command organization and documentation
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
- Add retry configuration to CoolifyTask (3 tries, 600s timeout)
- Add retry configuration to ScheduledTaskJob (3 tries, configurable timeout)
- Add retry configuration to DatabaseBackupJob (2 tries)
- Implement exponential backoff for all jobs (30s, 60s, 120s intervals)
- Add failed() handlers with comprehensive error logging to scheduled-errors channel
- Add execution tracking: started_at, retry_count, duration (decimal), error_details
- Add configurable timeout field to scheduled tasks (60-3600s, default 300s)
- Update UI to include timeout configuration in task creation/editing forms
- Increase ScheduledJobManager lock expiration from 60s to 90s for high-load environments
- Implement safe queue cleanup with restart vs runtime modes
- Restart mode: aggressive cleanup (marks all processing jobs as failed)
- Runtime mode: conservative cleanup (only marks jobs >12h as failed, skips deployments)
- Add cleanup:redis --restart flag for system startup
- Integrate cleanup into Dev.php init() for development environment
- Increase scheduled-errors log retention from 7 to 14 days
- Create comprehensive test suite (unit and feature tests)
- Add TESTING_GUIDE.md with manual testing instructions
Fixes issues with jobs failing after single attempt and "attempted too many times" errors