Commit Graph
15 Commits
Author SHA1 Message Date
Andras Bacsai 1a2a5362ad fix(security): secure remote command secrets and clone volume data 2026-10-27 09:47:18 +01:00
Andras BacsaiandClaude Opus 5.5 1e71561239 fix(backups): sign S3 uploads with the storage region
Closes #12264

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 22:28:48 +02:00
Andras Bacsai 554bd354bf fix: support host storage paths and clean up cancelled deployments
Allow validated host file and directory mounts outside resource directories
while protecting external paths from deletion.

Clean up cancelled deployment containers and clear tracked process IDs.
Preserve legacy KeyDB and Dragonfly password parsing, accept server backup
paths without extension restrictions, and allow Compose variable proxy ports.
2026-10-05 11:08:52 +02:00
Andras Bacsai e144b990c3 feat(horizon): add fixed-size per-queue worker pools on Coolify Cloud
Cloud production now runs one supervisor per queue (deployments, crons,
high, default, maintenance), so a busy queue cannot starve the others.
Add maintenance_queue() for slow Docker cleanups and a shared
horizon.worker_timeout config value. Self-hosted keeps the s6 supervisor.
2026-10-03 21:24:54 +02:00
Andras BacsaiandClaude Opus 5.5 1ee34a5ab2 fix(database-import): stop the restore when the import task fails or loses SSH
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>
2026-10-02 16:00:29 +02:00
Andras Bacsai 8b007edceb fix(database): skip MySQL system databases when restoring all databases
An all-databases MySQL/MariaDB restore also restored the mysql system
database, so after the next restart the root and app passwords were the
source ones and the MariaDB health check failed. The restore now skips mysql,
sys, performance_schema and information_schema by default. The new option
"Restore users and privileges" (restore_mysql_users in the API) keeps the
old behaviour.
2026-09-30 18:59:49 +02:00
Andras Bacsai 9e7cb60b0d feat: add import restore options, OAuth confirmation, and fixes
- 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
2026-09-30 13:35:22 +02:00
Andras BacsaiandClaude Opus 5.5 8246492bb9 fix(databases): stop and clean up interrupted or stale imports
- 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>
2026-09-26 22:18:17 +02:00
Andras BacsaiandClaude Opus 5.5 fbfe342f89 fix(databases): reserve start and restart atomically
Two parallel start requests both passed the in-progress check and got
200, because the start activity is created later by the queued action.
A per-database reservation (Cache::add, 600 s) is now taken before the
check, so the second request gets 409. The action releases it when it
creates its activity, skips, or fails. Restart, import, the deploy
API, MCP, and Livewire use the same reservation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 21:19:14 +02:00
Andras BacsaiandClaude Opus 5.5 a8117f9114 fix(databases): unblock interrupted imports and prevent double starts
- A Coolify restart now fails queued or running database imports, so
  they no longer block all later imports with 409.
- An import without progress for the SSH command timeout plus 30
  minutes (at least 2 hours) is stale and no longer blocks.
- The import sets its operation property when the activity is created,
  so a worker cannot save the activity without it.
- Start and restart refuse a second operation while a start, restart,
  or import is in progress, in the UI, the API (409), and actions.
- DatabaseStartJob runs only while its activity is still queued and
  the newest one, and holds a lock per database during the commands.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 10:40:53 +02:00
Andras BacsaiandClaude Opus 5.5 9e999a2782 fix(database): restore every supported backup format safely
- Detect the backup format before any database is changed. "All databases"
  imports no longer drop everything when the file cannot be restored.
- PostgreSQL: restore custom and tar archives with pg_restore and SQL with
  psql in both modes, including gzip; restore the #11481 custom-archive fix.
  Replacing existing data recreates the database for SQL backups.
- MySQL/MariaDB: accept a tar with one dump; reject dumps with more than one
  database in single mode instead of restoring them partially.
- MongoDB: restore plain and gzip archives and dump directories packed as
  tar; "Replace collections" maps to --drop.
- Prepare bz2, xz, and zip backups in the helper image, because database
  images do not ship those tools; stream S3 backups from the S3 helper.
- Show the exact restore script in the import form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 11:32:04 +02:00
Andras Bacsai d4a655c390 fix(database): keep S3 import credentials out of activity commands
Pass S3 endpoint and keys as helper container env vars and run mc alias
via those variables so the stored import command no longer contains
access keys or secrets. Start the helper in a separate remote process,
use the storage filesystem adapter for object checks, and remove a
credential temp file during import cleanup when the path is safe.
2026-09-09 14:27:31 +02:00
Andras Bacsai edcd44db89 fix: serialize database import starts per resource
Hold a cache lock keyed by database UUID across the active-import
check and remote_process so two concurrent requests cannot both
queue a restore against the same database.
2026-09-09 13:10:04 +02:00
Andras Bacsai 4accae95b5 feat(database): add replace-existing option for PostgreSQL restores
Allow single-database PostgreSQL imports to drop matching objects before restore. The API and import form accept replace_existing, which adds --clean --if-exists to pg_restore, and pg_restore now uses --exit-on-error.
2026-09-09 11:48:17 +02:00
Andras Bacsai ab3b3926aa feat: add database import API and Cloudflare DNS management
Queue database imports from upload, S3, or server paths via REST, and
manage Cloudflare DNS records from integration tokens and domain UIs.
2026-09-09 11:14:22 +02:00