Import:
- Check every uuid in a bundle against a strict id format before any
write, and quote the SSH mux socket and key paths in local shell
commands. A bundle uuid could run commands in the Coolify container.
- Validate bundle fqdns, git source URLs, paths, networks, cron
expressions, and database ports; cap the number of items.
- Do not confirm that another team has a uuid.
- Refuse a project icon path with a uuid that is not a plain id.
Claim, finish, and migrate:
- Pass checklist step keys to wire:click with Js::from (stored XSS).
- Link only to https target server URLs.
- Validate target_instance_url in /transfer/complete; never prefill an
unverified URL for a transfer back; scope the transfer-back token to
write+deploy for 1 hour.
- Release on an owner marker only when it is newer than the own claim.
- Do not touch apps that only use the server as an additional
destination when an archive is released or deleted.
- Give Sentinel a new token on claim.
- Add a checklist step to remove the previous instance's SSH key.
- Block a transfer while backups or scheduled tasks run.
- Authorize refreshMigration and PrivateKey checkConnection, clear
tokens from Livewire state, hide migration log/error from members.
Archives:
- Refuse ip, user, port, private key, and Cloudflare tunnel changes.
- Throttle Enable management and require a free server slot for it and
for a transfer back.
- Skip cloud provider calls.
- Re-read force_disabled before each SSH command, so running jobs stop.
- Probe the import check target at the resolved address only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run metric requests in batches of eight workers, isolate endpoint failures,
and preserve CPU and memory history when Sentinel lacks a summary endpoint.
Repair Sentinel tokens before creating workers and bound SSH fetch timeouts.
Reauthorize team servers on refresh and hydration, clear stale metrics after
transfers or deletions, and resolve container metadata for team ID zero.
Use only root filesystem samples when mount fields are present, while
supporting legacy disk data. Add regression coverage for concurrent workers,
access changes, endpoint failures, and disk mapping.
Applications and service applications can now use the server resolver,
no resolver ("none"), or a custom resolver name. This allows servers
that mix Let's Encrypt domains with domains that use their own
certificates, such as Cloudflare Origin CA. The setting is available in
the UI and the API.
Closes#12138
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.
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.
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.
- refreshEnvs is now sent only to the environment variable list, and
rows no longer listen to it, so adding or removing variables cannot
queue an update for a removed row ("Snapshot missing"). Locking a row
refreshes that row directly; the compose editor gets its own event.
- saveCustomName() no longer saves a custom container name that another
application on the server already uses; it restores the stored value.
- Cancelling a GitHub runner uses the Coolify confirmation modal instead
of a native browser dialog.
Import now always claims the server and rebinds Sentinel. Remove the
SSH-written ownership file, the write_remote/rebind_sentinel/claim
options, and the POST /servers/{uuid}/claim endpoint. The migrator now
fails when the target cannot take management. Disabling management
records transfer.management_disabled so the server shows as
transferable, and the transfer and import pages are simplified.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Livewire rebuilds listener names from the session team on every event
call. After a team switch in another tab, open pages still listen on the
old team channel, so events failed with EventHandlerDoesNotExist (500),
or ran handlers that load resources scoped to the new team (404).
Store the team at mount and build team channel listeners from it. Events
for a team that is no longer the session team are ignored.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Delete Blade components, component classes, Livewire components and
views that nothing uses after the redesign.
- Delete tests that only compare Blade/CSS source text; keep the source
checks for authorization gates, stable wire:key values and escaping.
- Update stale tests to the current UI and behaviour.
- Update DESIGN.md to the current navigation and layout.
- Add a lesson: test behaviour, not source markup.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Login, registration and OAuth set a fake currentTeam attribute on the user.
When refreshSession() saved the user in the same request, the query wrote
a currentTeam column that does not exist. Keep the team only in the session
and read it through currentTeam().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review findings on the fleet metrics page.
Data correctness:
- bucket raw Sentinel samples into epoch-aligned windows (5m/30m/2h per range)
and average them, replacing per-server LTTB. Every server now reports the
same bucket timestamps, so the fleet sums add up point by point instead of
zigzagging between servers (and RX+TX really combine)
- keep only the root mount in disk history, matching HasMetrics::getDiskMetrics
- leave sparkline gaps as null instead of 0, so absent samples read as gaps
Robustness:
- normalize containerMetric in mount()/updatedContainerMetric(), so
/metrics?cmetric=foo no longer throws an undefined array key
- include the server uuid in the container row wire:key; system containers
share one Sentinel id across servers
- round the range start to the minute so the 60s history cache can hit
- cap the Sentinel curl with --max-time 10, so one hung request cannot stall
the serial per-server loop
UI:
- pass the spark time axis on first paint, so tooltips no longer show 1970
- show the active series name (RX/TX) in the server network chart tooltip
Refine the /metrics fleet page and align the per-server metrics page with it.
Fleet overview:
- add live sparklines to the CPU/Memory/Disk/Network KPI tiles (shared axis,
capped to ~40 points per sparkline)
- fill the Servers online + Containers tiles (fleet-health bar, hottest
container) so all six tiles read as one system
- scope-aware labels: drop the "Fleet" prefix and helper copy when a single
server is selected
Trend charts:
- hero layout: CPU spans full width, the other four form a 2x2 grid
- apply the same hero layout + skeleton to the per-server page for consistency
Hottest containers table:
- add a rank column and a per-row magnitude bar scaled to the busiest container
- fix a leaked Blade @break directive that rendered literally and forced
horizontal scroll on the Network tab
- keep the value column a fixed width so bars align across rows
Live refresh:
- add analytics-style loading feedback to the range tabs and server filter
- stable wire:key on table rows + width transitions on bars so data glides
on live refresh instead of snapping
Generalize the shared _sparkline partial (optional color/label/format) so it
serves non-traffic metrics without changing analytics behaviour.
Remove the enable/disable toggle from the server UI, logs page, and
Sentinel API so is_sentinel_enabled is derived and read-only. Enable
existing regular servers via migration, start Sentinel after validate-
and-install, and drop the daily ServerManagerJob restart.
Unify service backup history with pagination, schedule settings actions, S3 destination details, and team-safe access checks. Display server built-ins as read-only variables and add loading and empty states for searchable resources.
Add reusable domain URL parsing and input components, expose per-domain
redirect and indexing controls, and improve application and service domain
layouts across responsive breakpoints.
Ensure a Sentinel endpoint from instance FQDN/IP when enabling, use process dialogs for validation with install state, and tidy server create, boarding, metrics empty state, and log timestamps.
Add a local-only command palette action to show/hide the Server Timing
HUD via localStorage and a visibility event. Make the service heading
"Required variables missing" badge link to environment variables, with
tests covering both behaviors.
Surface unset required service env vars in the configuration checker
popup and sidebar, refresh on env updates, and keep the env table
horizontally scrollable with correct managed/hardcoded pagination order.
Move internal hostname loading and breadcrumb status into dedicated
Livewire components with live refresh. Merge public/internal access
into one Access section, bind Enter to save on the unsaved bar, and
drop x-teleport wrappers from popup and global search.
Standardize highlighted buttons, selected controls, and loading
indicators on coollabs accent colors; improve light-mode log toolbar
styling; enhance small popups with compact/icon modes; and align
navbars, helpers, and related layouts with matching tests.
Add an application Internal access section that loads the running
container hostname (skipped for Compose apps), densify configuration
diff and popup-small defaults, dock the server-timing HUD into the
mobile top bar, restyle the 2FA challenge with the auth shell, and
enforce 16px mobile form fonts to prevent iOS zoom.