276 Commits
Author SHA1 Message Date
033f0c84da v4.7 (#12478)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Co-authored-by: Aditya Tripathi <aditya@climactic.co>
2026-11-06 14:25:02 +01:00
Andras BacsaiandClaude Opus 5.5 878d77bd66 fix(database): make the Redis health check ping with the password
The check was [CMD-SHELL, redis-cli, ping], so Docker ran only redis-cli
and it always passed. redis-cli also exits 0 on NOAUTH and LOADING.
The check now pings with the server password and requires PONG. With a
custom redis.conf that sets its own requirepass, it requires PONG or NOAUTH.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 12:37:36 +01:00
Andras BacsaiandClaude Opus 5.5 21d1ad4874 fix(backups): upload to S3 endpoints with a path, like Supabase Storage
The MinIO client rejects endpoints such as `/storage/v1/s3`. Transfers to
these endpoints now use curl with a presigned URL that Coolify signs, for
database backups, volume backups, and S3 restores.

Closes #8530

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 21:43:47 +01:00
Andras Bacsai f21acdc3e4 fix(notifications): notify when a resource stops unexpectedly
Status checks now queue a delayed check for each application, preview,
service part, or database that goes from up to exited. After 2 minutes
it sends the "Resource status changes" notification if the resource is
still stopped, no deployment runs, and Coolify did not stop it. Each
resource sends at most one notification in 15 minutes.

Closes #9493
2026-11-03 20:18:50 +01:00
Andras BacsaiandClaude Opus 5.5 7f521e496d fix(s3): add a setting to skip TLS verification for S3 storages
S3 storages with a self-signed or private CA certificate failed with
"cURL error 60", because the Coolify container and the backup helper do
not use the CA certificates of the host. The new opt-in setting turns off
the certificate check in the PHP S3 clients and sets MC_INSECURE for mc.

Closes #9762

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 18:59:52 +01:00
peaklabs-dev 32574d76b1 Merge remote-tracking branch 'origin/main' into next 2026-11-02 16:12:51 +01:00
Andras BacsaiandClaude Opus 5.5 1af7de8a85 fix(backups): pin a reachable IP for S3 uploads on IPv6-only servers
mc keeps one --resolve IP per host, and Coolify always pinned the IPv4
address of a dual-stack endpoint. On servers without IPv4, uploads failed
with "network is unreachable". A helper container on the upload network
now connects to each validated IP, IPv4 first, and the first IP that
connects is pinned. S3 restores are now pinned in the same way.

Closes #12397

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 14:38:49 +01:00
Andras Bacsai 6f1905b7b0 fix(access): enforce member grants on more actions
- Require write access on the target environment to clone or move a resource
- Check read access on shared variables before a reference is added or resolved
- Limit team credentials, git sources, and imports of other backups to team-wide writers
- Require the delete level for backup, volume, storage, and task deletes
- Require create access for previews, new projects, and git sources
- Use the token team for the access scope, and check team-wide access on Livewire updates
- Require instance admin to toggle the API and MCP server
- Hide server pickers and broadcast details from members without access
2026-10-30 16:11:10 +01:00
Andras Bacsai ef57eea320 fix(backups): sign mc requests with S3v4 and retry failed S3 uploads 2026-10-28 10:35:46 +01:00
Andras BacsaiandClaude Opus 5.5 a2c048c999 fix(database): recreate TCP proxies that run an outdated configuration
Proxies started before v4.4.4 kept the old nginx config after an upgrade:
the upstream IP was resolved only once and IPv6 connections were reset.

- Label new proxies with a configuration version
- Status checks (Sentinel and SSH) recreate a running proxy with an
  older or missing version once, at most every 10 minutes
- Remove the old proxy only after the image pull, so a failed pull
  keeps it running

Closes #10198

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 16:24:55 +01:00
Andras Bacsai 1039368491 fix(s3): support virtual-hosted-style URLs for S3 storages
Add a "Use path-style URLs" setting to S3 storages. It is detected from
the endpoint (Alibaba OSS, Tencent COS, Volcengine/BytePlus TOS), and the
connection test switches to virtual-hosted style when the provider
rejects path-style requests. Backups pass `--path off` to mc.

Closes #10347
2026-10-27 15:53:16 +01:00
Andras Bacsai 1a2a5362ad fix(security): secure remote command secrets and clone volume data 2026-10-27 09:47:18 +01:00
Andras Bacsai 1017a5b307 fix(deploy): use SSH user registry credentials for host image pulls (#12216) 2026-10-26 13:00:06 +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 BacsaiandClaude Opus 5.5 65a7bd5c05 chore: merge main into release/v4.5
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 13:37:20 +02:00
Andras Bacsai d043c10c11 fix(postgresql): set PGPASSWORD for healthchecks and backups (#12224) 2026-10-19 21:20:17 +02:00
Andras Bacsai dd456625ec Merge remote-tracking branch 'origin/release/v4.5' into release/v4.5 2026-10-19 15:03:38 +02:00
22a8c09dd6 Next (#12202)
Co-authored-by: Aditya Tripathi <aditya@climactic.co>
Co-authored-by: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: rosslh <ross@rosshill.ca>
Co-authored-by: Abdulfetah Suudi <suudiabdulfetah@gmail.com>
Co-authored-by: Dharmveer <51308779+dharmveer97@users.noreply.github.com>
Co-authored-by: Maxwell <136101+mxswd@users.noreply.github.com>
2026-10-19 10:07:23 +02:00
Andras BacsaiandClaude Opus 5.5 a82d32c946 chore: merge main into release/v4.5
Resolve conflicts between main's security fixes and v4.5 features:
- Keep v4.5 features (log redaction, multi-S3 backups, transfer flow,
  scheduled task modal, sidebar) and port main's fixes into them.
- Reuse RequiresDeployAbility for the Hostinger create endpoint.
- Align MCP tool abilities and descriptions with main's new deploy
  requirements, and use deploy tokens in the affected MCP tests.
- Drop the duplicate DockerCleanupJobTest helper and tests, and the
  exportBundle test for a method v4.5 removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:00:05 +02:00
Andras BacsaiandClaude Opus 5.5 0eeb630ccd fix(compose): use explicit compose file paths and remove volumes by name (#12199)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 00:00:48 +02:00
e3d4411ff2 chore: merge main into release/v4.5 (#12192)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Furox <177975472+Furox-Art@users.noreply.github.com>
Co-authored-by: johandenhollander <johan.den.hollander@finalist.nl>
Co-authored-by: João Cruz <161638790+SrJooJ@users.noreply.github.com>
Co-authored-by: Saim Hashmi <hashmisaim037@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-18 23:43:20 +02:00
Andras BacsaiandClaude Opus 5.5 8ed31bb96e feat(env): restore Coolify default variables with a per-resource option
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:55:53 +02:00
Andras Bacsai 0e3b6e5aa6 fix(databases): apply custom configs on servers with a strict umask
A custom config file written with tee gets the server umask. With umask
027 or 077 the file is not readable by the container user, so MySQL and
MariaDB ignored the whole config without an error.

- Set mode 644 on the MySQL, MariaDB, PostgreSQL, and MongoDB custom
  config files after each write.
- Close the multiplexed SSH connection when the server user, IP, or port
  changes, so the next command does not run as the old user.

Closes #11600
2026-10-16 21:28:21 +02:00
Andras Bacsai 200af07225 Merge remote-tracking branch 'origin/release/v4.5' into automation/sync-main-to-release-v4.5 2026-10-12 21:38:45 +02:00
Andras Bacsai 8e0f4d0dfa fix(database): prevent duplicate environment variables on start and clone
- Stop the Redis username accessor from creating REDIS_USERNAME on read
- Keep source values when cloning applications (no duplicate NIXPACKS_NODE_VERSION)
- Match exact keys when adding default database environment variables
- Write content files before database containers start
- Resolve the database proxy upstream through Docker DNS on each connection
- Remove existing duplicate REDIS_USERNAME and NIXPACKS_NODE_VERSION rows
2026-10-09 14:53:05 +02:00
Andras Bacsai 45d165e82e fix(database): listen on IPv6 in public TCP proxy when network has IPv6
Docker publishes the proxy port on [::] too and forwards it to the
container's IPv6 address when the network has IPv6 enabled. nginx
listened only on IPv4, so every IPv6 connection was reset.

Add listen [::]:<port> when the destination network has IPv6 enabled.
Networks without IPv6 keep the IPv4-only listener.

Fixes #12133
2026-10-09 13:31:25 +02:00
github-actions[bot] 2293cfedcf Merge remote-tracking branch 'origin/main' into next 2026-10-05 21:19:10 +00:00
Andras Bacsai 7f12e3b513 fix(databases): keep the server password of existing Redis databases
v4.3.23 started Redis with the stored REDIS_PASSWORD value as it is and
unquoted, and the connection URLs used the same value. 4.4.0 resolved a
shared variable reference for the start command only, so after the first
restart the server password changed and no longer matched the URLs.

- Add legacy_password_quoting to standalone_redis; existing databases
  keep the v4.3.23 server password
- New databases resolve REDIS_PASSWORD (local, shared or remote secret)
  and quote it in the start command
- Connection URLs use the same password as the server
- Hide the flag in the API, as for KeyDB and Dragonfly
2026-10-05 22:49:36 +02:00
github-actions[bot] 9d5ce66674 Merge remote-tracking branch 'origin/main' into next 2026-10-05 19:47:56 +00:00
Andras Bacsai 152e06cf43 fix(databases): let REDIS_PASSWORD override the KeyDB and Dragonfly password
The stored password is the default. Before, a local REDIS_PASSWORD was
rewritten to the stored password, and a shared one replaced the stored
password, so the old password was lost.

- A local, shared, or remote secret REDIS_PASSWORD sets the server
  password; the stored password and the variable are not changed
- Removing the variable, or an empty value, uses the stored password
- Connection URLs show the password in use; for a remote secret they
  show the reference, not the secret
- Databases created before this release keep the v4.3.23 behavior
2026-10-05 21:25:57 +02:00
github-actions[bot] 96a5b4f959 Merge remote-tracking branch 'origin/main' into next 2026-10-05 12:32:36 +00:00
Andras Bacsai 88efc0716e fix: enforce resource team isolation and preserve ClickHouse data
Scope resource permissions and related records to the owning team across
team switches, cloning, deployments, and resource operations.

Merge ClickHouse volume mounts, preserve anonymous data volumes on stop,
and require adopting current data before starting or restarting.

Fix file storage deletion checks and add regression coverage.
2026-10-05 14:23:04 +02:00
github-actions[bot] edbe9020d2 Merge remote-tracking branch 'origin/main' into next 2026-10-05 10:29:31 +00:00
Andras Bacsai 4227ec6ebf fix(storage): require deploy permission for external host writes
Require deploy or root token access when creating managed mounts outside
resource directories or changing their file contents through the API.

Synchronize KeyDB and Dragonfly passwords with local and shared
REDIS_PASSWORD values while preserving secret manager resolution.
2026-10-05 12:03:37 +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
peaklabs-dev 189207a7a5 refactor(database): rename FlushCacheDatabase action to FlushDatabase 2026-10-04 23:07:05 +02:00
peaklabs-dev 1e70c73215 refactor(database): simplify flush command and drop password escaping 2026-10-04 23:07:04 +02:00
peaklabs-dev f5b221e3f3 fix(database): flush KeyDB and TLS Dragonfly and detect failed flushes 2026-10-04 23:07:04 +02:00
Aditya Tripathi e67b27040f test(database): cover Heading::flush workflow; document sudo-parser limitation
Addresses CodeRabbit review on #11513:
- Add Livewire feature tests for Heading::flush() covering success +
  audit event, non-cache guard, denied manage permission, and menu
  visibility for cache vs non-cache databases.
- Document the pre-existing parseCommandsByLineForSudo() limitation that
  mutates passwords containing shell sequences on non-root servers.
2026-10-04 22:57:33 +02:00
Aditya Tripathi 52cad11f34 feat(database): add flush cache option for Redis, KeyDB and Dragonfly
Adds a Flush cache action to the database heading for the three
Redis-protocol cache databases. It runs FLUSHALL ASYNC inside the
running container to clear all keys without stopping the container.

The option is hidden for SQL/Mongo databases and only shown while the
database is running. A confirmation modal requires typing the database
name before flushing. The redis-cli password is shell-escaped to
prevent command injection.
2026-10-04 22:57:27 +02:00
Andras Bacsai 3575234b38 fix(docker-cleanup): clean after a resource stop only when the disk needs it
A stop or delete no longer queues a full cleanup each time. It skips the
cleanup when one finished on the server in the last hour, and the queued
run only cleans when disk usage is at or above the server cleanup
threshold. The docker_cleanup API flag keeps its default of true.
2026-10-03 21:25:17 +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 Bacsai f1f7272494 fix(queue): run service and database start commands on the deployment queue
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.
2026-10-03 20:50:49 +02:00
Andras BacsaiandClaude Opus 5.5 9978929779 fix(databases): keep the server password of existing KeyDB and Dragonfly databases
The start command now quotes the password. Databases created before this
release keep the unquoted v4.3.23 argument when quoting would change the
password the server receives, until their password changes. Remote secret
passwords are always quoted exactly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:00:41 +02:00
Andras BacsaiandClaude Opus 5.5 9bdbbeef7a fix(secret-manager): use remote secret values exactly and check them before a restart
- Write remote secret values as exact dotenv literals in the service .env
  file and escape "$" where they go directly into a generated compose file
  (environment, start commands, healthchecks).
- Resolve remote secrets before a service or database restart stops the
  running resource, and show the secret manager error instead of a generic
  start failure (new RemoteSecretException).
- Cache fetched key names for the autocomplete and rate limit how often a
  user can contact the secret manager.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:00:41 +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 658ac6bca5 fix(database): check MongoDB health with ping
The MongoDB health check passed only on the writable primary
(db.hello().isWritablePrimary or isMaster().ismaster). A replica set
that was never initiated, which is common for Prisma setups, and any
non-primary member were reported unhealthy after a restart.

The check now runs db.adminCommand({ ping: 1 }) with mongosh or the
legacy mongo shell. Ping needs no authentication, passes on every
running member, and still fails when mongod is not reachable.
2026-10-01 07:16:27 +02:00
Andras Bacsai b13fa4dad0 fix(database): choose the MongoDB health check shell at run time
The health check from #11730 picked mongosh or the legacy mongo shell
from the image name (mongo:4*). Images without mongosh whose name does
not start with mongo:4, such as mongo:3.6 or registry mirrors of
mongo:4.4, ran a missing mongosh (exit 127) and stayed unhealthy.

The check now uses mongosh when the container has it and falls back
to the legacy mongo shell otherwise.

Replace the test that only checked the source text with tests that run
the generated script with fake shells.
2026-09-30 20:48:54 +02:00
Andras Bacsai 0604101781 Merge pull request #11730 from cbratschi/codex/fix-mongodb-healthcheck
fix(database): use MongoDB writable-primary health check
2026-09-30 20:45:48 +02:00
Andras Bacsai a2cd6351b2 fix(databases): keep SSL certificate files and CA in sync with each engine
- Regenerate SSL Certificates now writes server.crt/server.key for every
  engine except MongoDB, which keeps the combined server.pem. Before, the
  button always wrote server.pem, so Postgres, MySQL, MariaDB, Redis, KeyDB
  and Dragonfly failed to start after a regenerate.
- The certificate renewal job uses the same rule, so MongoDB no longer
  switches to server.crt/server.key on renewal and fails on restart.
- Starting an SSL database writes the CA that signs its certificate to
  /data/coolify/ssl/coolify-ca.crt, so a stale CA file (for example one
  written by another server entry for the same host) no longer causes
  "certificate signature failure".
- Saving a custom CA certificate that does not match the stored CA
  private key is rejected.
- The CA file write commands live in SslHelper::caCertificateFileCommands().

Fixes #10388
Fixes #6771
Fixes #11926
2026-09-30 19:01:11 +02:00