520 Commits
Author SHA1 Message Date
Andras Bacsai 6012232e97 fix(server): rate limit failed server validations on cloud 2026-10-23 11:10:02 +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 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 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 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 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 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 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
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 Bacsai 9355728d03 fix(log-drains): validate custom log drain configuration (#12197) 2026-10-18 23:40:54 +02:00
Andras Bacsai c781cddbab fix(server-transfer): require update access to export bundles 2026-10-18 23:21:16 +02:00
Andras BacsaiandClaude Opus 5.5 7c14c0098e feat(server-transfer): run instance migration as a background job (#12180)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:03:45 +02:00
Andras Bacsai 33ee09fa87 feat(canvas): add interactive resource views and team avatars (#12160) 2026-10-14 09:28:10 +02:00
Andras Bacsai 448dc8ea0a feat(logging): strengthen secret redaction and add admin controls (#12151) 2026-10-13 20:43:19 +02:00
Andras Bacsai f63726279c Merge remote-tracking branch 'origin/release/v4.5' into sentinel-metrics-sidebar-page 2026-10-13 11:57:47 +02:00
Andras Bacsai f37761253d feat(server): set up Cloudflare tunnels with API tokens (#12157) 2026-10-13 11:32:26 +02:00
github-actions[bot] 8f5bb11bee Merge remote-tracking branch 'origin/main' into release/v4.5 2026-10-13 08:04:48 +00:00
Andras Bacsai dc6777a71d feat(server): paginate Docker images with adjustable page size
Reset pagination when search or page size changes and clamp page bounds.
Move disk usage badges beside the Images heading.
2026-10-13 10:02:19 +02:00
Andras Bacsai 83384a7b95 Merge remote-tracking branch 'origin/release/v4.5' into automation/sync-main-to-release-v4.5 2026-10-12 22:30:41 +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 af589f6da4 feat(proxy): make the Traefik certificate resolver configurable per server
Coolify always added tls.certresolver=letsencrypt to generated HTTPS
routers, so Traefik logged errors when the proxy used its own
certificates (for example Cloudflare Origin CA) without that resolver.
Add a server setting (default letsencrypt) in the proxy page and API.
An empty value omits the resolver from resource labels, the Coolify
dashboard routes, and the catch-all router.

Closes #12138
2026-10-11 10:19:40 +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
github-actions[bot] deff17a3b3 Merge remote-tracking branch 'origin/main' into next 2026-10-07 13:00:32 +00: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 8b30b34238 feat(proxy): add custom error pages and resource maintenance mode (#12112) 2026-10-07 13:24:42 +02:00
Andras Bacsai e7025612b8 feat(hostinger): add cloud provider integration (#11176) 2026-10-07 13:14:04 +02:00
Andras Bacsai 38861e1394 feat(github-runners): support deployment and build servers (#12109) 2026-10-07 12:45:08 +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 aa16cfb420 fix(servers): change the server role only through its checked flow 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 b08383805c fix(sentinel): prevent concurrent starts and duplicate restarts (#12100) 2026-10-05 21:56:17 +02:00
Andras Bacsai a331f91c49 fix(ui): validate secret manager settings and lock server-built lists
- SecretManagerLinks: validate settings when the integration token
  changes, and save only validated keys
- Service Domains: lock domainRows
- Server DockerImages: lock images
2026-10-05 21:23:29 +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 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 16a8c7999d feat(audit): log account, resource, and instance settings changes
Add audit events for account actions, server and application settings,
services, destinations, storage, backup schedules, and scheduled tasks.
Track changed fields and skip unchanged saves without logging file content.

Add regression coverage for audit events and changed-field detection.
2026-10-04 17:32:50 +02:00
Andras Bacsai 15b64d6c56 Move proxy TLS certificates to a separate page 2026-10-04 12:35:54 +02:00
Andras Bacsai 22900b6d12 fix(proxy): stop automatic proxy network reconnects on status checks
Remove the periodic ConnectProxyToNetworksJob dispatch from
PushServerUpdateJob, the synchronous connect in ServerCheckJob when the
proxy is found running, and the connect-on-add in the server
Destinations component. Drop the now-unused
proxy.connect_networks_interval_seconds config option.

Replace the rate-limit/interval tests with a test asserting that no
jobs are pushed when the proxy is running.
2026-10-04 00:36:28 +02:00
Andras Bacsai 50be16be8f revert(scheduler): go back to the cron scan and keep the reliability fixes
The missed daily backups on Coolify Cloud came from Redis evicting queue keys
(allkeys-lfu on a full instance), not from the scan of all schedules. The
next_run_at design (452259aac, 5c5740533) did not prevent that, and it added
stored state that must be kept in sync on every frequency, timezone, and server
change. It was not released, so remove it:
- revert next_run_at, its model hooks, the "Next run" UI, and the diagnostics
  changes; restore scheduled_job_states and the queue overlap lock
- a new migration removes the next_run_at columns and creates
  scheduled_job_states again where the removed migration already ran

Keep the changes that fix real problems:
- run the manager every minute from the scheduler with `scheduled:dispatch`,
  so a busy queue cannot delay it past the catch-up window
- load the server chain of scheduled backups with each chunk, which removes
  about 7,000 queries per run on Coolify Cloud
- catch Throwable for each schedule, so one broken schedule does not stop the
  others
- publish database and volume backups again when their queued job was not
  started after 60 minutes (for example, lost in Redis); log lost tasks and
  Docker cleanups as missed. A lost backup is not run again when a newer
  occurrence of the same schedule exists.
2026-10-02 08:05:18 +02:00
Andras Bacsai 3379f85c0a fix(security): authorize import file checks and Vultr status refresh
ImportForm::checkFile() and checkS3File() ran without authorization, so
a member with view access could check whether paths exist on the server
or probe S3. They now require update access, like the restore actions.
Server\Show::checkVultrInstanceStatus() now requires view access, like
the Hetzner and DigitalOcean checks.
2026-10-01 20:31:00 +02:00
Andras Bacsai bcc07dd47e feat(github-runners): allow public repositories and refuse pull request jobs by default
The runner group was limited to private repositories, so jobs from
public repositories never got a runner: Coolify still started a runner
for each matching job, which then waited idle until its timeout.

The runner group now allows every repository of the organization,
public ones too; existing private groups are updated. GitHub gives a
runner any queued job with matching labels, so pull request jobs are
refused inside the runner: a job-started hook fails jobs from
pull_request, pull_request_target and review events before any step
runs, and fails closed when the event is unknown. A new runner setting,
off by default, allows pull request jobs; the settings page then warns
to require approval for fork pull request workflows on GitHub.
2026-10-01 08:14:30 +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
Andras Bacsai ef90fe06f1 feat(proxy): back up acme.json before changes and allow restoring backups
Coolify copies acme.json to a timestamped backup before every change and
keeps the last 10. The proxy page lists the backups with Restore and Delete
for team admins, and the restore dialog can restart the proxy right away.
2026-09-30 18:10:10 +02:00
Andras BacsaiandClaude Opus 5.5 fd85b740f5 feat(github-runners): add ephemeral self-hosted runners on build servers (#12054)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:13:11 +02:00
Andras BacsaiandClaude Opus 5.5 03a056709d feat(server): add Docker registry logins page with per-server login (#12048)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 12:11:37 +02:00