4127 Commits
Author SHA1 Message Date
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 17957fbb4c feat(ui): restyle sidebar footer user menu and toggle icon
Put the user menu above the toggle in the collapsed sidebar, make the
user menu a full-width 3D button with rounded corners, and use a new
sidebar toggle icon everywhere.
2026-10-09 13:50:07 +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 Bacsai b39a8e647c fix(ui): center resource table names without a description
Hide the empty description line in the environment resources table so
it takes no space. Names without a description now sit level with the
other cells, and on narrow screens the domain follows the name directly.

Fixes #12127
2026-10-09 08:29:51 +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 df953bdcd1 fix(upgrade): prevent duplicate upgrades and stalled progress polling
Block new upgrades while a recent upgrade is running, allowing retries after 15 minutes without a status update.

Add request timeouts and polling guards to keep upgrade progress responsive during restarts.
2026-10-09 08:01:20 +02:00
Andras Bacsai f86a02f409 fix(logs): fall back to default level filters when saved filters are invalid
Malformed JSON in the coolify-log-filters localStorage key threw during
runtime log viewer startup. Read the saved value safely and keep only
boolean values for known levels.

Fixes #12101
2026-10-08 13:39:26 +02:00
rosslh d932ac5d59 fix(ui): center card titles when the description is empty
Only render the card description when it has text, and center the title
against the icon. Removing the description placeholders left an empty
description element in items-start rows, so titles without a description
were pinned to the top of the icon.

Closes #12102
2026-10-08 12:18:10 +02:00
Andras Bacsai f412e70634 fix(terminal): list lazily loaded containers in the resource terminal picker
The container picker read its options from an Alpine x-data snapshot taken
on the first render, before wire:init loaded the containers. Livewire keeps
the Alpine state when it morphs, so resources with multiple containers
showed an empty picker. Publish the options as a Livewire property and
entangle them in Alpine.

Closes #12110
2026-10-07 17:59:29 +02:00
Andras BacsaiandClaude Opus 5.5 d6a36c068f fix(navbar): remove truncated page search hint from search button
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 17:59:10 +02:00
Andras Bacsai 1abcd3dad8 fix(forms): reduce listbox trigger height to 2rem 2026-10-07 16:57:50 +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
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 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 7d17c6ff8b fix(domains): skip favicons for private network hosts (#12107) 2026-10-07 12:28:48 +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 393dcbb6cd fix(logs): wrap viewer in a root element for parent re-renders 2026-10-06 22:09:27 +02:00
Andras Bacsai c5bcb31f73 fix(databases): import from the source the user selected
A staged upload always won over a server path, so an old upload that
was never imported could be restored instead of the chosen file.

- Record the selected source (checked server file or finished upload)
  and import only from it
- Delete a stale staged upload when another source is used
2026-10-06 10:29:04 +02:00
Andras Bacsai 88ba00db2b fix(ui): pass values to Alpine correctly in component attributes
Blade does not compile @js() inside component tag attributes, so Alpine
got the literal text and threw an expression error.

- The environment variable editor closes again after an update
- The change email button in the profile gets a valid disabled state
2026-10-06 06:59:22 +02:00
Andras Bacsai ca203bc9fa fix(ui): keep the light custom theme rule for white surfaces
A comment in app.css contained "*/", which ended the comment early.
The minifier then dropped the next rule, so white panels in the light
custom theme were not tinted.
2026-10-06 06:59:22 +02:00
Andras Bacsai 93e7fa7f34 feat(dashboard): show pending team invitations
Login no longer accepts invitations, so the dashboard lists the
unexpired invitations for the user's email with a link to the
invitation page, where the user accepts them.
2026-10-05 23:42:01 +02:00
Andras Bacsai 35c38b1dde fix(database): reject blocked starts before queueing operations
Check start prerequisites in database and deploy APIs and MCP controls.
Return HTTP 422 for blocked API starts and restarts. Show restart notices
and open UI logs only after an operation is queued.

Add API regression tests for blocked ClickHouse starts and restarts.
2026-10-05 14:59:59 +02: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
Andras Bacsai 439ee6faea fix: restrict proxy content access and scope backup storage to owners
- Hide proxy configuration contents from users without update permission.
- Select and validate backup S3 storage against the resource's team.
- Keep scheduled branch syncs green while a conflict PR remains open.
- Document external mount permissions and Sentinel traffic limits.
- Add regression coverage for authorization and backup storage selection.
2026-10-05 13:20:19 +02: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 2aead9c914 refactor(analytics): remove application traffic overview card 2026-10-05 11:28:03 +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 774e6bf178 feat(account): add self-service deletion and cancellation flow (#12088) 2026-10-05 09:17:10 +02:00
Andras Bacsai 34e4da1095 fix(ui): copy DNS record values on plain http instances
On non-secure origins the copy button falls back to execCommand('copy')
with a temporary textarea. The textarea was appended to <body>, outside
the x-trap focus trap of the DNS entries modal, so the trap pulled focus
back and the selection was lost before the copy. The button showed
success, but nothing was copied.

Append the textarea next to the button, select it explicitly, and
restore focus afterwards. "Copy all" now uses the shared copyButton
handler instead of its own duplicate fallback that ignored failures.

Closes #12075
2026-10-04 20:36:49 +02:00
Andras Bacsai e837a4f0b4 style(ui): use neutral colors for selection checkmarks 2026-10-04 13:46:21 +02:00
Andras Bacsai 9850793109 Merge remote-tracking branch 'origin/main' into pr-11788-encrypted-audit-change-details 2026-10-04 13:13:16 +02:00
Andras Bacsai c4f96a7185 fix(analytics): label zero response status in traffic breakdowns 2026-10-04 12:42:17 +02:00
Andras Bacsai 15b64d6c56 Move proxy TLS certificates to a separate page 2026-10-04 12:35:54 +02:00
Andras Bacsai 51c1a2ad4a fix: add column headers to analytics tables 2026-10-04 12:35:53 +02:00
Andras Bacsai 4c2253c2ad fix(previews): restrict PR loading and status updates to GitHub Apps
Add Application::isGithubAppSource(), which checks that the source is a
GithubApp, and use it in place of is_github_based() for pull request
status updates in ApplicationDeploymentJob and for the "Load pull
requests" action in the previews view.

Previews::load_prs now throws an error for non-GitHub App sources
instead of calling the GitHub API with a GitLab or other source. Also
adds a test checking that GitLab sources don't show or load GitHub pull
requests.
2026-10-04 12:29:48 +02:00
Andras Bacsai 83d19800a6 feat(audit): store encrypted field-level changes on mutations
Record old/new values for auditable create, update, and delete actions, persist them encrypted on audit events, expose them in the API, and let the team audit log expand a field-level before/after view. Sensitive, hidden, and identifier fields stay out of the change payload.
2026-10-04 12:26:00 +02:00
Andras Bacsai 66cc64e0d9 fix(sentinel): repair stalled Sentinel and show why pushes fail
- Restart a running Sentinel that has not pushed for 10 minutes, at most
  once per hour. The restart applies the current URL and token.
- Restart an unhealthy Sentinel. Do not restart while its health check
  starts or while its API does not answer yet, which caused restart loops.
- Remember why pushes fail: the reason Coolify rejects a push, and the last
  push error from Sentinel's /api/push-status. Show it on the Sentinel page
  while Sentinel is out of sync.
- When the instance URL or public IP changes, move remote servers that use
  the generated Sentinel URL to the new URL. Custom URLs stay.
2026-10-04 12:03:54 +02:00
Andras Bacsai c3b32322eb fix(volume-backups): back off failed container and S3 recovery
Recovery attempts now back off exponentially, stop after 8 attempts, and
mark the execution as needing attention with a failure category. The
scheduler dispatches at most 100 recovery jobs per run, and a pending S3
cleanup no longer blocks new backups. S3 delete errors now raise with
their cause.
2026-10-03 21:25:11 +02:00
Andras Bacsai c0d81d4c9c fix(auth): accept Entra ID xms_edov claim as verified OIDC email
Microsoft Entra ID never sends email_verified, so existing accounts could
not be linked through OIDC. Treat a boolean true xms_edov claim (email
domain owner verified) as equivalent, via a shared
OidcUser::claimsVerifyEmail() helper used for both ID token and userinfo
claims.

Document the Entra ID issuer URL and required optional claims in the
OIDC settings helper text, and add tests covering xms_edov handling.
2026-10-02 18:51:16 +02:00
Andras Bacsai 2f3a5088ee fix(ui): offset focus ring on highlighted buttons with outline gap
Highlighted buttons use the accent color, so the flush box-shadow focus
ring looked like a stray border. Use an offset accent outline instead and
keep the regular depth shadow on focus and hover-focus.
2026-10-02 16:58:42 +02:00
Andras Bacsai 5b1fcd6e13 feat(auth): show OAuth-only registration notice on login page
Move the user creation check from OauthLoginService into
OauthSetting::allowsUserCreation(), so the login view can use it.
The login view now gets a can_register_with_oauth flag. The flag is
true when an enabled OAuth provider allows creating new users. The
view uses it to show the new auth.register_with_oauth message.
Add translations for the message in all locales, plus test coverage.
2026-10-02 16:45:33 +02:00
Andras Bacsai b1ddde2b64 fix(auth): enforce Google hosted domain and block password-user linking
Treat the Google "Hosted domain" setting as an enforced Workspace
restriction: compare it to the hd claim case-insensitively with spaces
trimmed, and accept "*" for any Workspace account while still rejecting
personal Google accounts.

Exempt pre-upgrade OAuth users from the email verification check only
when they have no password. A flagged user with a password no longer gets
an unverified provider email linked to their account.

Update the hosted domain helper text and add tests for both cases.
2026-10-02 16:11:21 +02:00
Andras BacsaiandClaude Opus 5.5 3dabda5c56 fix(oauth): require a verified provider email for password users and use the instance callback URL
- Only password-less users from before OAuth identities skip the provider
  email verification claim. Otherwise an unverified provider account with
  the email of a password user (including root) could sign in as them.
- Build the default callback URL from the instance URL, not the request
  Host header, and do not save it during a login.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:01:10 +02:00