6982 Commits
Author SHA1 Message Date
Andras BacsaiandClaude Opus 5.5 95d796e922 feat(deployments): compact history beside logs with in-place switching
- Fit the embedded history to the logs height and page size to the screen
- Show status as a dot with short start time; add source, duration, and
  server as a second line; make whole rows clickable
- Switch the logs viewer to another deployment without a page load
- Use View and Export menus and the runtime logs search in the toolbar
- Export visible logs from the server with secrets hidden; redact app
  secrets in the full log download

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 12:34:08 +02:00
Andras Bacsai 3bfeb14b7d style(logs): show deployment status dots like the service menu
Deployment options get the same status dot and Stopped caption as
services instead of colored badges, so the listbox no longer needs
labelClass.
2026-10-23 12:25:57 +02:00
Andras Bacsai 2e7cf8633b feat(logs): pick runtime log streams from service selectors
Replace the container accordion with Deployment and Service selectors
that show one stream, merging replica containers by timestamp. The
viewer fills the page, opens in text view, keeps whitespace, and only
lets grid rows expand when the detail shows more than the row.

Based on the proposal in discussion #12176 by PhilippMolitor.
2026-10-23 11:55:44 +02:00
Andras Bacsai 6012232e97 fix(server): rate limit failed server validations on cloud 2026-10-23 11:10:02 +02:00
Andras Bacsai 7acfcdff24 feat(ui): reorganize resource settings and domain port editing 2026-10-22 20:26:41 +02:00
Andras Bacsai c454f84545 fix(server-transfer): keep imported data exact and guard archived servers
- Skip TrimStrings and ConvertEmptyStringsToNull on the import route; an empty shared variable failed the whole import
- Keep compose parser versions, static ports, legacy variable keys, and only the bundle's variables and destinations
- Give the transfer back token the deploy permission that the import needs
- Move the Cloudflare tunnel DNS record with the server and park it on the source
- Refuse cloud server deletes, power on, tunnel and DNS changes, and scp for archives; skip their backup alerts and provider polling
- Add a column-level round-trip test, archive guard tests, and a live full-coverage transfer test
- Advance the GitLab App sequence in the dev seeder
2026-10-22 15:52:20 +02:00
Andras Bacsai 59928035b7 feat(forms): add copy button to password inputs by default 2026-10-22 13:43:44 +02:00
Andras Bacsai c465371356 Merge remote-tracking branch 'origin/main' into fix/secret-manager-request-timeout
# Conflicts:
#	other/nightly/versions.json
#	tests/Feature/Security/IntegrationTokenFormTest.php
#	versions.json
2026-10-21 22:44:50 +02:00
Andras BacsaiandClaude Opus 5.5 dbc3fb91bf fix(cdn): fetch versions.json once per hour, spread evenly across instances
- Retry CDN requests only for transient errors and honor Retry-After
  (Cloudflare error 1200 sends 60 s), with jitter.
- Read helper and Sentinel versions from the local versions.json, which
  the hourly update check refreshes, instead of fetching per job/server.
- Replace the random 0-600 s delay with a stable per-instance offset
  inside the cron interval (max 1 h).
- Manual update checks and upgrades make one CDN attempt only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:10:48 +02:00
Andras BacsaiandClaude Opus 5.5 c4bc9ae8bf fix(canvas): show servers without resources on the servers canvas
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 18:02:02 +02:00
Andras BacsaiandClaude Opus 5.5 b1f2abf868 fix(cloud): refresh local versions.json hourly on every node
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 17:18:56 +02:00
Andras Bacsai 666ae60c2c Merge remote-tracking branch 'origin/main' into release/v4.5 2026-10-21 16:49:31 +02:00
Andras Bacsai d404da904f feat(app-key): re-encrypt stored secrets after key rotation 2026-10-21 16:47:51 +02:00
Andras Bacsai d730ab48fd feat(security): add command to re-encrypt secrets after key rotation 2026-10-21 16:47:40 +02:00
Andras Bacsai e9f69ce95b Merge remote-tracking branch 'origin/main' into fix/secret-manager-request-timeout 2026-10-21 16:23:00 +02:00
🏔️ Peak ff642008f1 fix(security): releease v4.4.7 (#12257) 2026-10-21 16:18:27 +02:00
peaklabs-dev eeda30719f feat(cdn): add patch.sh to sync:cdn 2026-10-21 16:16:13 +02:00
Andras BacsaiandClaude Opus 5.5 64b748008e fix(server): list the active private key first
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 11:28:48 +02:00
Andras Bacsai 0732e74553 fix(server-transfer): require deploy permission for import checks
Require write and deploy abilities on the import check endpoint, and clarify the target token permissions in transfer messages and UI.
2026-10-20 14:15:30 +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
e0f6b41dac chore: merge main into release/v4.5 (#12206)
Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Andras Bacsai <andrasbacsai@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 13:26:07 +02:00
Andras Bacsai 87dade4517 fix(secret-manager): add configurable request timeout for Infisical and Vault 2026-10-20 13:00:38 +02:00
Andras Bacsai 2ade696375 fix(storage): resolve ${VAR:-default} bind sources and safe conversion (#12227) 2026-10-20 11:41:54 +02:00
Andras Bacsai 5925c8403a fix(log-drain): replace server name whitespace with hyphens (#12239) 2026-10-20 11:29:11 +02:00
Andras Bacsai d55852ee94 fix(proxy): persist running status from Sentinel push updates (#12237) 2026-10-20 10:49:26 +02:00
Andras Bacsai bf957e425f fix(docker): parse quoted and hyphenated custom docker option values (#12208) 2026-10-19 23:12:16 +02:00
Andras Bacsai cf71fda5c1 feat(gitea): add Gitea App sources and private repo deployments (#12234) 2026-10-19 21:58:30 +02:00
Andras Bacsai 71131804f6 fix: require notification and log drain fields only when enabled (#12232) 2026-10-19 21:47:33 +02:00
Andras Bacsai 62be8674bc feat(proxy): add optional permanent redirects for apps and services (#12233) 2026-10-19 21:46:12 +02:00
Andras Bacsai 5ae125ad39 fix(tasks): run scheduled tasks only in running app containers (#12226) 2026-10-19 21:28:54 +02:00
Andras Bacsai 6d36605176 fix(proxy): require coolify-proxy container name outside Swarm (#12225) 2026-10-19 21:23:12 +02:00
Andras Bacsai c089f8a328 fix(backups): use configured databases when container env is missing (#12212) 2026-10-19 21:21:53 +02:00
Andras Bacsai d043c10c11 fix(postgresql): set PGPASSWORD for healthchecks and backups (#12224) 2026-10-19 21:20:17 +02:00
Andras Bacsai 3acfa6b9a6 fix(telegram): show API errors when sending test notifications (#12219) 2026-10-19 21:17:35 +02:00
Andras Bacsai 59793b060c fix(api): point rejected fqdn field to domains on application writes (#12217) 2026-10-19 21:07:51 +02:00
Andras Bacsai 3b407c8413 fix(backups): send Content-MD5 for S3-only volume backups on Object Lock (#12215) 2026-10-19 21:05:38 +02:00
Andras BacsaiandClaude Opus 5.5 63153aa8b4 fix(cloud): rework unsubscribed team cleanup and account deletion (#12210)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:32:16 +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
Andras BacsaiandClaude Opus 5.5 ad6e929a93 feat(gpu): fix GPU compose settings and show detected server GPUs
- Build a valid compose device request (device_ids list, options mapping, blank driver)
- Map --gpus N to count and drop --gpus when GPU settings are enabled
- Validate only changed GPU values so stored legacy values keep working
- Detect NVIDIA GPUs and the container toolkit with the server details
- Show detected GPUs with a refresh button in the application GPU section

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 15:00:31 +02:00
Andras BacsaiandClaude Opus 5.5 f9e4323839 fix(patches): turn on automatic updates with the time in the Maintenance window field
Turn on used the saved time and the confirmation showed the time from
page load, so an unsaved new time was ignored. Turn on now validates
and saves the time in the field, and the confirmation refers to the
field instead of a fixed time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:54:46 +02:00
Andras BacsaiandClaude Opus 5.5 3bc7e47a86 feat(patches): confirm before turning automatic security updates on or off
Automatic security updates now have their own "Turn on" / "Turn off"
action with a confirmation, instead of a field that the Save bar
applied. The confirmation explains what can stop:

- Docker from the operating system packages (docker.io, moby-engine)
  restarts on a security update, so all containers stop and start.
- Docker CE from the Docker repository is not updated: its repository
  has no security origin (apt) and no security advisories (dnf).
  Checked on Debian 12 (unattended-upgrade --dry-run skips docker-ce)
  and CentOS Stream 9.
- Services that use an updated library can restart; a new kernel is
  installed without a reboot.

The on/off state is locked, so only the confirmed action can change it.
A new maintenance window is applied to the server on Save only when the
updates are on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 13:51:21 +02:00
Andras Bacsai 975048bad8 fix(security): encrypt plaintext secrets at rest 2026-10-19 12:28:23 +02:00
Andras BacsaiandClaude Opus 5.5 fb317d7129 chore: remove Sentry integration
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 11:14:35 +02:00
Andras BacsaiandClaude Opus 5.5 f32ecca44c feat(patches): record package updates, reboots, and auto-update changes in the audit log
- ui.server.packages_update_requested: user, server, packages (or all),
  package manager, and the activity of the update.
- ui.server.packages_update_finished: written when the remote process
  finishes (also when it fails), with the result and the exit code of
  the activity. The update gets a fresh type_uuid (an indexed activity
  property), so the listener finds exactly this activity. The actor
  comes from the request, because the listener runs in the queue.
- ui.server.reboot_requested with result started or failed.
- ui.server.auto_security_updates_updated (enabled, time, package
  manager, result) and ui.server.patch_settings_updated for a changed
  check frequency.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:44:03 +02:00
Andras BacsaiandClaude Opus 5.5 83ea5cc1f7 feat(servers): show the patch status of each server in the server list
- ServerSetting::patchStatus() summarizes the saved patch check
  (updates, security updates, reboot required, error). Results saved
  before security and reboot detection count as 0 and false.
- Grid cards show "N security updates", "N updates", "Patch check
  failed", and "Reboot required" badges; the table gets a Patches
  column from lg. The badge text is searchable.
- The toolbar shows a one-line team summary, for example "Patches: 2
  servers with updates · 1 with security updates · 1 needs a reboot".
- Badges and the summary are shown only for servers where the user can
  view the security pages (viewSecurity on the server), so members do
  not see them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:41:59 +02:00
Andras BacsaiandClaude Opus 5.5 4ca0b4415c feat(patches): add automatic security updates per server
- New server settings: is_auto_security_updates_enabled and
  auto_security_updates_time (maintenance window, HH:MM in the time zone
  of the server). Both move with a server transfer.
- Debian/Ubuntu: install unattended-upgrades and write
  52coolify-unattended-upgrades. `#clear` drops the distro origin lists,
  so only the security origins stay (Debian <codename>-security, Ubuntu
  <codename>-security, and the Ubuntu Pro ESM security origins). A
  drop-in for apt-daily-upgrade.timer sets the time.
  https://manpages.debian.org/bookworm/apt/apt.conf.5.en.html
  https://github.com/mvo5/unattended-upgrades/blob/master/README.md
- RHEL family: install dnf-automatic (dnf5-plugin-automatic on dnf5),
  set upgrade_type = security and apply_updates = yes in
  /etc/dnf/automatic.conf, and add a drop-in for dnf-automatic.timer
  (dnf4) or dnf5-automatic.timer (dnf5).
  https://dnf.readthedocs.io/en/latest/automatic.html
  https://dnf5.readthedocs.io/en/latest/dnf5_plugins/automatic.8.html
- Off removes the Coolify files, so the operating system default comes
  back. Other package managers show "not supported".
- The schedule and the automatic updates share one form and one
  unsaved bar. The remote commands run only when the automatic update
  settings change; a failure keeps the old setting.
- Commands are written for non-root SSH users (tee and single sh -c
  scripts) and were run in Debian 12, Ubuntu 24.04, Rocky 9, and Fedora
  containers as root and as a sudo user.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:41:42 +02:00
Andras BacsaiandClaude Opus 5.5 3da85e2c07 feat(patches): mark security updates, reboot state, and risky packages
- Security updates: apt marks a package from a "-security" suite (Debian
  12 now reports oldstable-security). dnf reads `dnf updateinfo list
  --security` (dnf5 keeps updateinfo as an alias of advisory). zypper
  uses `zypper -x patch --dry-run --category security`, because
  `zypper -x list-patches` ignores --category and has no package names.
  pacman and apk cannot tell, so they show no security count.
  https://dnf5.readthedocs.io/en/latest/commands/advisory.8.html
  https://github.com/openSUSE/zypper/blob/master/doc/zypper.8.txt
- Reboot required: /var/run/reboot-required, `needrestart -b` (KSTA 2
  or 3), `dnf needs-restarting -r` (matched by text, because a missing
  plugin also exits 1), and `zypper needs-rebooting` (exit 102).
  https://github.com/liske/needrestart/blob/master/README.batch.md
  https://dnf-plugins-core.readthedocs.io/en/latest/needs_restarting.html
- An explicit risk list per package manager (Docker engine, kernels,
  libc/glibc/musl, systemd, dbus, openssh) replaces the "name contains
  docker/kernel" guess on the page and in every notification channel.
- The page shows security and reboot badges, a security count, and the
  risk of each package. "Reboot server" (with confirmation, update
  policy on the loaded server) schedules the reboot with systemd-run and
  checks the server again five minutes later. Archived (transferred)
  servers are never touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:39:51 +02:00
Andras BacsaiandClaude Opus 5.5 6806ed31fa feat(patches): save check results and run checks in a queued job
- server_settings gets patch_check_result (JSON), patch_check_error,
  patch_checked_at, and patch_check_frequency.
- The patches page shows the saved result and "Last checked" on load.
  "Check for updates" queues ServerPatchCheckJob (manual) instead of
  running SSH in the Livewire request. The job saves the result and
  broadcasts ServerPatchCheckFinished on the server team channel; the
  page reloads the saved result (with a 10 s poll as a fallback).
- A finished package update (callEventOnFinish) queues a new check on
  the server side, so the page no longer depends on the browser.
  ServerPackageUpdated is removed.
- The check frequency is a server setting (cron or preset, at most once
  per hour). Empty keeps the staggered weekly default.
- The failure notification is sent only when the state changes from ok
  to error, not on every check.
- Page access needs viewSecurity and every action needs update on the
  loaded server; a member gets 403. Updates accept only a package from
  the saved result.
- Server transfer: the frequency moves, the last result stays on the
  source (runtime).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:28:51 +02:00
Andras BacsaiandClaude Opus 5.5 df17797d8f fix(patches): run apt without prompts, check pacman safely, show dnf versions
- apt: use apt-get with DEBIAN_FRONTEND=noninteractive and keep changed
  configuration files (--force-confdef/--force-confold). A single package
  uses install --only-upgrade, so it is never installed when missing.
- pacman: do not run `pacman -Sy` on the live database during the check.
  Use checkupdates (with fakeroot) or a temporary sync database, the same
  method checkupdates uses. pacman 7 downloads as the alpm user, so the
  temporary directory is 755. Arch allows only "Update all" (-Syu), because
  partial upgrades are unsupported.
  https://man.archlinux.org/man/checkupdates.8
  https://wiki.archlinux.org/title/System_maintenance#Partial_upgrades_are_unsupported
- dnf: list upgrades with `repoquery --upgrades --latest-limit 1 --qf`
  (dnf5 needs the explicit \n, dnf4 prints empty lines) and read the
  current versions from `rpm -qa`. The package name has no .arch suffix.
  https://dnf5.readthedocs.io/en/latest/changes_from_dnf4.html

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 10:21:59 +02:00
Andras Bacsai 3d8cea9e3c feat(rollback): list Docker registry images of recent deployments
Rollback now also lists the commit images of the last 10 successful
deployments when the application pushes to a Docker registry. The
deployment pulls such an image when the server no longer has it.
The page and the API share GetRollbackImages, and the API returns a
source field (local or registry).
2026-10-19 10:10:48 +02:00