1643 Commits
Author SHA1 Message Date
Andras Bacsai 3c5a664b95 test(database): verify runtime DNS resolution in generated proxy config 2026-10-09 14:55:44 +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 f87f80ae96 feat(dns): add opt-in Cloudflare proxy mode for new DNS records 2026-10-09 13:52:20 +02:00
Andras Bacsai f39c884cc7 fix(servers): support IPv6 server addresses everywhere
Store server IPs in one form (no brackets, short lower-case IPv6) and
write each address in the form its context needs:

- URLs and host:port (Sentinel, database URLs, SFTP backup download,
  DNS servers, SMTP, webhook base URLs, links, health checks) get
  brackets through formatHostForUrl().
- Traefik Host() rules use the address without brackets, so IPv6
  domains no longer return 404; saved labels are fixed at deploy.
  Caddy keeps the brackets.
- SSH keeps the plain address.
- Hetzner gives an IPv6 /64 network; IPv6-only servers now get the
  server address (prefix::1) instead of the unusable prefix::64.
- sslip labels, registry image names with an IPv6 host, the API domain
  list, allowlist matching and duplicate checks handle IPv6.

A migration normalizes stored IPv6 server addresses, repairs Hetzner
servers saved as ::64 that are not reachable, and adds brackets to
saved Sentinel URLs.
2026-10-09 13:50:28 +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
Andras BacsaiandClaude Opus 5.5 376e7aab24 feat(upgrade): block upgrades when the disk is almost full
An upgrade pulls new images and recreates the Coolify containers. A full
disk during an upgrade can leave Coolify broken.

- Measure free space on the Docker root dir and /data/coolify of localhost;
  require 5 GB. An unknown value does not block.
- Manual upgrade: show the free and required space, with Run Docker cleanup,
  Check again, and a confirmed Upgrade anyway override.
- Automatic upgrade: skip it and notify the team (disk usage channels, at
  most once per 24 hours per server).
- upgrade.sh: stop before any change when the disk is low. A new 5th
  argument skips the check (used by the override).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:26:53 +02:00
Andras BacsaiandClaude Opus 5.5 b850a06d26 fix(cache): write config and route cache files atomically
Laravel writes bootstrap/cache/config.php in place, so the file is empty
until the write ends. app:init rebuilds the cache on every container start
while PHP-FPM already serves requests. A request could read the empty file
(TypeError in LoadConfiguration), and OPcache with validate_timestamps=0
kept it, so every request failed until a restart.

Write to a temporary file in the same directory and rename it over the
target. A failed write now keeps the old file instead of an empty one.

Fixes #12120

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 13:26:48 +02:00
Andras Bacsai 8c4aa7bb00 feat(git): allow IPv4 and IPv6 addresses in repository URLs
Accept HTTP(S), git:// and SCP-style SSH repository URLs whose host is an
IP address, including bracketed IPv6 such as git@[2a01:4f8::1]:org/repo.git.
The clone runs on the user's deployment server, so the IP block did not
protect Coolify, and SSH URLs with IPv4 already passed.

Loopback, link-local and other reserved addresses are still rejected as
internal hosts. Brackets are allowed only around a valid IPv6 host.
2026-10-09 09:31:07 +02:00
Andras Bacsai 247015e30a fix(docker): match legacy Compose containers by UUID in names
Resolve application owners from dash-separated UUIDs in Compose service or coolify.name labels, and include service-prefixed names in Docker filters.

Add regression coverage for custom Compose start commands, status updates, and UUID boundary matching.
2026-10-09 08:45:32 +02:00
Andras Bacsai ea1199bf8e fix(compose): allow required and alternative variables in network names
Accept the `?`, `:?`, `+` and `:+` interpolation operators in Compose
network names, such as `${CONTAINER_NAME?error}`. The validation added
in v4.4.0 only knew `-` and `:-`, so these valid files stopped deploying.

The text after `?` is an error message and is not used as the default of
the created environment variable. Unsafe operands are still rejected.

Fixes #12126
2026-10-09 08:45:03 +02:00
Andras Bacsai 34366a47b5 fix(infisical): expand secret references when fetching secrets
Older Infisical versions default expandSecretReferences to false, so
values like prefix-${OTHER_KEY} reached containers unexpanded. Request
expanded values explicitly on the v4 endpoint and the v3 fallback.

Fixes #12128
2026-10-09 08:30:00 +02:00
Andras Bacsai 065d4825d3 fix(backups): pin S3 endpoint DNS for mc cp uploads
mc --resolve applies per invocation and is not stored in the alias, so
mc cp resolved the S3 host again inside the helper container. On hosts
with split DNS this failed with "no such host", and the upload did not
use the IP validated by SafeWebhookUrl.

Fixes #12129
2026-10-09 08:29:53 +02:00
Andras BacsaiandClaude Opus 5.5 6a0a4e889b fix(github): show why the GitHub App install callback fails instead of a bare 403
The install callback swallowed every verification error (clock skew, network,
missing key, GitHub API errors) and returned an opaque 403. It also compared
the state's team with the session team, so switching teams during the GitHub
install returned 403.

- Return the verification reason, log it, and redirect to the GitHub App page
  with an error toast (JSON requests still get 403 with the reason)
- Check membership of the state's team, and switch the session to it
- Show flashed errors on the GitHub App page

Fixes #12122

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 08:29:39 +02:00
Andras Bacsai d07bc9c0ff fix(docker): preserve resource containers during cleanup 2026-10-09 08:22:08 +02:00
🏔️ Peak 3f953d1dce revert(git): stop forcing HTTP/1.1 for repository imports (#12080) 2026-10-08 18:10:07 +02:00
Andras Bacsai 3b33e8a4ab fix(domains): stop the DNS poll from flooding the high queue
The Domains page polls every 2 seconds while a DNS check runs. Each poll
parsed the compose file, and the parser queued one ServerFilesFromServerJob
per volume. The jobs starved the DNS check jobs and deployments.

- Skip the compose parse in pollDnsChecks and keep the known services.
- Make ServerFilesFromServerJob unique per resource until it runs.

Fixes #12098
2026-10-08 13:43:45 +02:00
Andras BacsaiandClaude Opus 5.5 44e4566a9b fix(analytics): regenerate stored Caddy labels when toggling traffic analytics
Caddy logs a site only when its container labels contain the log
directives. Deployments reuse the stored custom_labels, so applications
whose labels were stored before analytics was enabled never got the log
directives, and a redeploy did not help.

Toggling traffic analytics on a Caddy server now regenerates the stored
labels of applications with read-only labels. The destination uses the
current server instance, because the cached server can still have the
old analytics setting.

Fixes #12117

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 12:38:26 +02:00
Andras Bacsai be7369c9cc fix(deployment): keep the commit message when a deployment does not clone
The commit message was read only during the repository clone. Deployments
that skipped the build or failed before the clone showed only the commit
hash. They now reuse the message stored by an earlier deployment of the
same application and commit.

Closes #12116
2026-10-08 12:19:01 +02:00
Andras Bacsai e0639a8e6d fix(applications): normalize nested base64 custom labels (#11473) 2026-10-07 16:44:59 +02:00
Andras Bacsai 76d3386a4d refactor(forms): unify searchable and multi-select listboxes
Replace datalist and searchable-listbox components with the shared listbox and migrate form fields.

Deduplicate superseded Livewire updates to prevent repeated array update hooks, with regression coverage.
2026-10-07 15:37:03 +02:00
Andras Bacsai 0bf7719491 feat(cloudflared): add tunnel updates with background container restart
Add an authorized update button with activity logs to pull the latest image and recreate the tunnel container in the background.

Persist new Compose files under /data/coolify/cloudflared and support existing /tmp configurations. Cover updates, missing configuration, and member restrictions with tests.
2026-10-07 14:54:17 +02:00
Brandon BridgesandAndras Bacsai c728089804 fix(deploy): keep build helper containers out of --add-host (#11781)
Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
2026-10-07 14:27:11 +02:00
Andras Bacsai a6655fe992 fix(traffic): merge overflow paths and distinguish rows by domain
Combine Sentinel overflow rows into one unlinked "Other paths" row.
Show domains beside paths and include them in Livewire row keys.
Add regression coverage for overflow aggregation across app keys.
2026-10-07 13:40:02 +02:00
Andras Bacsai d08c082d07 Merge remote-tracking branch 'origin/main' 2026-10-07 13:31:27 +02:00
Andras Bacsai 81045b2dc2 fix(compose): deploy large Compose files such as Sentry self-hosted
Sentry self-hosted (getsentry/self-hosted 26.8.0) could not be deployed
as a Docker Compose application. Three separate problems blocked it:

- YAML collection aliases: the first fix raised the limit to 256 only in
  Application::oldRawParser(). The safety check added in v4.4.0
  (validateDockerComposeForInjection) and all other Compose parse calls
  still used the Symfony default of 128, so the Sentry file (133 aliases)
  failed with "Maximum number of collection aliases (128) exceeded".
  Add parseDockerComposeYaml() and use it for every Compose parse.
- Argument list too long: the deployment job sent the generated Compose
  file as base64 inside the SSH command. Linux limits one argument to
  128 KiB, and the Sentry file is about 370 KB. execute_remote_command()
  now accepts an 'input' key that streams content over SSH stdin, and
  the job writes the Compose file with it.
- A list-style build arg without a value (build.args: [SENTRY_IMAGE])
  merged into a map environment kept its numeric key, so Docker Compose
  rejected the file with "non-string key in ...environment: 0". It now
  becomes NAME with no value, as in Compose.

Closes #11725
2026-10-07 13:30:42 +02:00
Andras Bacsai 522ed390ce feat(search): add settings search to the command palette (#12111) 2026-10-07 13:24:21 +02:00
Andras Bacsai 38861e1394 feat(github-runners): support deployment and build servers (#12109) 2026-10-07 12:45:08 +02:00
Andras Bacsai 8319ae7397 Merge remote-tracking branch 'origin/main' 2026-10-07 12:44:37 +02:00
Andras Bacsai 575bfaa085 feat(analytics): add configurable client IP storage modes
Allow full, anonymized, or disabled IP recording per server through the UI
and API, and pass the selected mode to Sentinel. Adapt traffic breakdowns
to the effective IP mode, including views that aggregate multiple servers.
2026-10-07 12:35:22 +02:00
Andras Bacsai c9cce7ea2b fix(traffic): show geo globe when country data becomes available (#12108) 2026-10-07 12:28:59 +02:00
Andras Bacsai 407c384b09 feat(backups): add configurable missing volume backup alerts
Check enabled volume backup schedules hourly and notify teams when no
execution occurs within the configured number of days. Expose the alert
threshold in the UI and API, with alerts disabled by default.

Route volume backup results and warnings to the appropriate Telegram
backup threads.
2026-10-07 09:37:35 +02:00
Andras Bacsai 58db0eba6f feat(backups): notify teams of volume backup results
Send success and failure notifications through enabled backup channels.
Route successful backups with warnings through failure channels.
2026-10-07 09:24:10 +02:00
Andras Bacsai d54c03730d feat(scheduler): make scheduled job dispatch mode configurable
Default to sequential dispatch on self-hosted instances and concurrent
per-type dispatch on Coolify Cloud. Allow SCHEDULED_JOBS_DISPATCH_MODE
to override the default, falling back for invalid values.

Cover defaults, overrides, and fallback behavior in scheduler tests.
2026-10-06 23:16:40 +02:00
Andras Bacsai 393dcbb6cd fix(logs): wrap viewer in a root element for parent re-renders 2026-10-06 22:09:27 +02:00
Andras Bacsai 56497d50cf fix(deployments): include scheduled jobs in progress checks
Count running scheduled tasks, database backups, and volume backups,
excluding runs older than their job timeout. Report scheduled job counts
and keep the progress check active while any scheduled jobs are running.
2026-10-06 21:59:16 +02:00
Andras Bacsai be72005980 fix(deployments): expire missing Horizon jobs after deployment timeout
Keep reserved jobs active and bound missing Horizon records by the server's
 deployment timeout. Add regression coverage for active and finished jobs.

Use UTC PostgreSQL sessions and bump the release version to 4.4.1.
2026-10-06 21:51:58 +02:00
Andras Bacsai 41ed5b7a69 test: fix stale and flaky tests
- Update tests whose expectations no longer matched intended changes
  (GitHub App redirect, wildcard domains, container IDs, nightly
  install folders, localhost metadata, Sentinel restart on save)
- Seed the instance settings the 2FA profile test needs
- Run the global Pest hooks for all test folders and release the
  Laravel application after each test, so tests do not leak state
- Replace a class alias mock that broke later tests
- Generate factory names that always pass name validation; Faker names
  with apostrophes or short words made form tests fail at random
2026-10-06 13:01:49 +02:00
Andras Bacsai aa16cfb420 fix(servers): change the server role only through its checked flow 2026-10-06 12:56:57 +02:00
Andras Bacsai 9e20084302 fix(auth): build email verification links from the instance URL 2026-10-06 12:56:57 +02:00
Andras Bacsai f1d3883ab2 fix(servers): authorize every Docker images request 2026-10-06 12:56:57 +02:00
Andras Bacsai 5e92a7267c fix(cleanup): prune audit events in batches and delete old finished runner executions 2026-10-06 12:56:57 +02:00
Andras Bacsai ecf969e35d fix(audit): remove credentials from URLs before storing audit changes 2026-10-06 12:56:57 +02:00
Andras Bacsai 5d20f54f71 fix(webhooks): use a neutral reply for manual webhooks without a match 2026-10-06 12:56:50 +02:00
Andras Bacsai c2a3333df4 fix(runners): limit stored workflow and job names to the column length 2026-10-06 12:56:50 +02:00
Andras Bacsai 055f5c0622 fix(api): accept numeric resource limits when creating databases 2026-10-06 12:56:50 +02:00
Andras Bacsai 78f52310e5 fix(dns): only create or replace records for the resource's own domains 2026-10-06 12:56:50 +02:00
Andras Bacsai 804d05b9b6 fix(backups): close backup directories to other users on non-root servers 2026-10-06 12:56:50 +02:00
Andras Bacsai 3e6f6bfdad fix(ssh): keep the command and its secrets out of timeout errors 2026-10-06 12:56:50 +02:00
Andras Bacsai e79347295a fix(compose): allow upgrades with legacy soketi overrides
Add an inactive soketi placeholder to production and nightly Compose
files so old custom overrides remain valid without starting soketi.
Cover partial and full legacy overrides with regression tests.
2026-10-06 11:29:33 +02:00
Andras Bacsai 116806df1b fix(compose): allow content files outside the resource directory again
Since aabd12737 a Compose bind volume with a content block had to stay
inside the resource directory. Services and Compose applications saved
in v4.3.23 with other paths, and Git Compose files with them, no longer
started or deployed.

Only admins and owners can edit Compose files, and they can already
write any host file with a plain bind mount, so the rule added no
security.

- Write content files to their host path again, as in v4.3.23
- Keep shell escaping and the safe-character checks on volume sources,
  so injection attempts are still rejected
2026-10-06 11:03:39 +02:00