Commit graph

13933 commits

Author SHA1 Message Date
Andras Bacsai
ed979f42ef Fix SSH multiplexing contention for concurrent scheduled tasks (#6736)
When multiple scheduled tasks or database backups run concurrently on
the same server, they compete for the same SSH multiplexed connection
socket, causing race conditions and SSH exit code 255 errors.

This fix adds a `disableMultiplexing` parameter to bypass SSH
multiplexing for jobs that may run concurrently:

- Add `disableMultiplexing` param to `generateSshCommand()`
- Add `disableMultiplexing` param to `instant_remote_process()`
- Update `ScheduledTaskJob` to use `disableMultiplexing: true`
- Update `DatabaseBackupJob` to use `disableMultiplexing: true`
- Add debug logging to track execution without multiplexing
- Add unit tests for the new parameter

Each backup and scheduled task now gets an isolated SSH connection,
preventing contention on the shared multiplexed socket.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 09:54:30 +01:00
Andras Bacsai
558a885fdc
Fix Nixpacks null environment variable parsing error (#7493) 2025-12-04 16:29:56 +01:00
Andras Bacsai
f5ad372def
Add collapsible option to GetLogs component (#7495) 2025-12-04 15:37:48 +01:00
Andras Bacsai
3f96d467bf
Refactor: Move sentinel update checks to ServerManagerJob and add tests for hourly dispatch (#7491) 2025-12-04 15:37:21 +01:00
Andras Bacsai
cbba7f0a67 Add collapsible option to GetLogs component and improve toolbar layout
Added a new `collapsible` property to GetLogs component that allows disabling the expandable header, useful for log viewers in dedicated pages and slide-overs. Applied this to Sentinel logs, Proxy logs, and Coolify Proxy log pages. Also improved the toolbar by moving the lines counter to the left side with an inline prefix label and repositioning the match counter next to it for better organization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:37:14 +01:00
Andras Bacsai
b0f6693fd4
Style PostgreSQL type docs links to match service list (#7494) 2025-12-04 15:33:00 +01:00
Andras Bacsai
ddb7437a63 Style PostgreSQL type docs links to match service list pattern
Replace text "Documentation" links with SVG icons positioned in top-right corner, matching the established design pattern used in the service list. Update all four PostgreSQL type options: PostgreSQL 17, Supabase, PostGIS, and PGVector.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:28:52 +01:00
Andras Bacsai
d6bd0941e7 refactor: simplify utility classes in CSS and Blade templates 2025-12-04 15:19:23 +01:00
Andras Bacsai
42f08a99fb Fix Nixpacks null environment variable parsing error
Filter out null and empty environment variables when generating Nixpacks build
configuration to prevent JSON parsing errors. Environment variables with null or
empty values were being passed as `--env KEY=` which created invalid JSON with
null values, causing deployment failures.

This fix ensures only valid non-empty environment variables are included in both
user-defined and auto-generated COOLIFY_* environment variables.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:10:39 +01:00
Andras Bacsai
70ff73e954 Merge branch 'next' into macau-v1
Resolved conflicts in ServerManagerJob.php by:
- Keeping sentinel update check code from macau-v1
- Preserving sentinel restart code from next branch
- Ensuring no duplicate code blocks
2025-12-04 15:07:36 +01:00
Andras Bacsai
9e0fa03434
Run proxy restart as background job with real-time logs (#7475) 2025-12-04 14:59:50 +01:00
Andras Bacsai
4002044877 Refactor: Move sentinel update checks to ServerManagerJob and add tests for hourly dispatch 2025-12-04 14:58:18 +01:00
Andras Bacsai
b59bf454b9
Remove webhook maintenance mode replay feature (#7455) 2025-12-04 14:56:38 +01:00
Andras Bacsai
bf9f78538e Remove webhook maintenance directory from Docker configurations 2025-12-04 14:55:07 +01:00
Andras Bacsai
21f3ef6f9f
Fix PostgREST misclassification and empty Domains section (#7442) 2025-12-04 14:53:36 +01:00
Andras Bacsai
18d3be5ef6
fix: move base directory path normalization to frontend (#7437) 2025-12-04 14:52:44 +01:00
Andras Bacsai
05eed974cb
Add log search, download, and collapsible sections (#7484) 2025-12-04 13:55:40 +01:00
Andras Bacsai
8406eb57c5 Fix timestamp toggle in get-logs component
Updated the timestamp rendering condition to check both $timestamp and $showTimeStamps, ensuring the "Toggle Timestamps" button properly controls timestamp visibility in the log viewer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 13:51:06 +01:00
Andras Bacsai
1b4de18323 Add DoS prevention to decodeHtml function in get-logs component
Added maximum iteration limit (maxIterations = 3) to the decodeHtml function to prevent potential DoS attacks from deeply nested HTML entities. This matches the implementation in deployment/show.blade.php and ensures the function cannot be exploited for excessive CPU usage.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 13:46:25 +01:00
Andras Bacsai
554daf4f71
Set deployment status to IN_PROGRESS when queuing builds (#7487) 2025-12-04 13:42:04 +01:00
Andras Bacsai
76afc6841f Set deployment status to IN_PROGRESS when queuing builds
Update the deployment status to IN_PROGRESS immediately when a build is queued, rather than waiting for the job to start. This ensures the UI reflects the correct status without delay.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 13:41:12 +01:00
Andras Bacsai
bf8dcac88c Move inline styles to global CSS file
Moved .log-highlight styles from Livewire component views to resources/css/app.css for better separation of concerns and reusability. This follows Laravel and Livewire best practices by keeping styles in the appropriate location rather than inline in component views.

Changes:
- Added .log-highlight styles to resources/css/app.css
- Removed inline <style> tags from deployment/show.blade.php
- Removed inline <style> tags from get-logs.blade.php
- Added XSS security test for log viewer
- Applied code formatting with Laravel Pint

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 13:15:01 +01:00
Andras Bacsai
2fd34f3d57
Add RustFS one-click service (#7486) 2025-12-04 11:45:08 +01:00
Andras Bacsai
0dfc74ca5a
Update app/Livewire/Project/Application/Deployment/Show.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-12-04 11:42:39 +01:00
Andras Bacsai
277ebec525 Update RustFS logo to use PNG icon from GitHub
Replace SVG logo with official PNG icon from RustFS GitHub organization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 11:42:31 +01:00
Andras Bacsai
6d3e7b7d93 Add RustFS one-click service template
Add RustFS service definition with Docker Compose configuration and SVG logo for Coolify's service marketplace. Includes S3-compatible object storage setup with health checks and configurable environment variables.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 11:35:21 +01:00
Andras Bacsai
f8146f5a59 Add log search, download, and collapsible sections with lazy loading
Features:
- Add client-side search filtering for runtime and deployment logs
- Add log download functionality (respects search filters)
- Make runtime log sections collapsible by default
- Auto-expand single container and lazy load logs on first expand
- Match deployment and runtime log view heights (40rem)
- Add debug toggle for deployment logs
- Improve scroll behavior with follow logs feature

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 10:57:58 +01:00
Andras Bacsai
2fc870c6eb Fix ineffective restartInitiated guard with proper debouncing
The guard was setting and immediately resetting the flag in the same
synchronous execution, providing no actual protection. Now the flag
stays true until proxy reaches a stable state (running/exited/error)
via WebSocket notification, with additional client-side guard.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 08:57:03 +01:00
Andras Bacsai
46384170aa
Fix: Service status stuck at starting after stop (#7479) 2025-12-04 08:27:42 +01:00
Andras Bacsai
c53988e91d Fix: Cancel in-progress deployments when stopping service
When stopping a service that's currently deploying, mark any IN_PROGRESS or QUEUED activities as CANCELLED. This prevents the status from remaining stuck at "starting" after containers are stopped.

Follows the existing pattern used in forceDeploy().
2025-12-04 08:23:32 +01:00
Andras Bacsai
c464c67cba
Fix: Pass backup timeout to remote SSH process (#7476) 2025-12-03 20:10:18 +01:00
Andras Bacsai
d3eaae1aea Increase scheduled task timeout limit to 36000 seconds
Extended the maximum allowed timeout for scheduled tasks from 3600 to 36000 seconds (10 hours). Also passes the configured timeout to instant_remote_process() so the SSH command respects the timeout setting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 20:04:55 +01:00
Andras Bacsai
05fc5d70c5 Fix: Pass backup timeout to remote SSH process
Allows user-configured backup timeouts > 3600 to be respected. Previously, the SSH process used a hardcoded 3600 second timeout regardless of the job timeout setting. Now the timeout is passed through to instant_remote_process() for all backup operations.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:37:38 +01:00
Andras Bacsai
d53a12182e Add localhost hint for proxy restart logs
When restarting the proxy on localhost (server id 0), shows a warning
banner in the logs sidebar explaining that the connection may be
temporarily lost and to refresh the browser if logs stop updating.

Also cleans up notification noise by commenting out intermediate
status notifications (restarting, starting, stopping) that were
redundant with the visual status indicators.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:33:33 +01:00
Andras Bacsai
387a093f04 Fix container name conflict during proxy restart
The error "container name already in use" occurred because the container
wasn't fully removed before docker compose up tried to create a new one.

Changes:
- Removed redundant stop/remove logic from START PHASE (was duplicating STOP PHASE)
- Made STOP PHASE more robust:
  - Increased wait iterations from 10 to 15
  - Added force remove on each iteration in case container got stuck
  - Added final verification and force cleanup after the loop
  - Added better logging to show removal progress

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:30:27 +01:00
Andras Bacsai
36da7174d5 Combine stop+start into single activity for real-time logs
Instead of calling StopProxy::run() (synchronous) then StartProxy::run()
(async), now we build a single command sequence that includes both stop
and start phases. This creates one Activity immediately via remote_process(),
so the UI receives the activity ID right away and can show logs in real-time
from the very beginning of the restart operation.

Key changes:
- Removed dependency on StopProxy and StartProxy actions
- Build combined command sequence inline in buildRestartCommands()
- Use remote_process() directly which returns Activity immediately
- Increased timeout from 60s to 120s to accommodate full restart
- Activity ID dispatched to UI within milliseconds of job starting

Flow is now:
1. Job starts → sets "restarting" status
2. Commands built synchronously (fast, no SSH)
3. remote_process() creates Activity and dispatches CoolifyTask job
4. Activity ID sent to UI immediately via WebSocket
5. UI opens activity monitor with real-time streaming logs
6. Logs show "Stopping proxy..." then "Starting proxy..." as they happen

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:21:26 +01:00
Andras Bacsai
340e42aefd Dispatch restarting status immediately when job starts
Set proxy status to 'restarting' and dispatch ProxyStatusChangedUI event
at the very beginning of handle() method, before StopProxy runs. This
notifies the UI immediately so users know a restart is in progress,
rather than waiting until after the stop operation completes.

Also simplified unit tests to focus on testable job configuration
(middleware, tries, timeout) without complex SchemalessAttributes mocking.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:18:13 +01:00
Andras Bacsai
c42fb81347 Fix restart initiated duplicate and restore activity logs
- Add restartInitiated flag to prevent duplicate "Proxy restart initiated" messages
- Restore ProxyStatusChangedUI dispatch with activityId in RestartProxyJob
- This allows the UI to open the activity monitor and show logs during restart
- Simplified restart message (removed redundant "Monitor progress" text)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:11:56 +01:00
Andras Bacsai
b00d8902f4 Fix duplicate proxy restart notifications
- Remove redundant ProxyStatusChangedUI dispatch from RestartProxyJob
  (ProxyStatusChanged event already triggers the listener that dispatches it)
- Remove redundant Traefik version check from RestartProxyJob
  (already handled by ProxyStatusChangedNotification listener)
- Add lastNotifiedStatus tracking to prevent duplicate toasts
- Remove notifications for unknown/default statuses (too noisy)
- Simplify RestartProxyJob to only handle stop/start logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 16:09:47 +01:00
Andras Bacsai
dae6803173 fix: restore original base_directory on compose validation failure
The Application::loadComposeFile method's finally block always saves
the model, which was persisting invalid base_directory values when
validation failed.

Changes:
- Add restoreBaseDirectory and restoreDockerComposeLocation parameters
  to loadComposeFile() in both Application model and General component
- The finally block now restores BOTH base_directory and
  docker_compose_location to the provided original values before saving
- When called from submit(), pass the original DB values so they are
  restored on failure instead of the new invalid values

This ensures invalid paths are never persisted to the database.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 15:57:15 +01:00
Andras Bacsai
e4810a28d2 Make proxy restart run as background job to prevent localhost lockout
When restarting the proxy on localhost (where Coolify is running), the UI becomes inaccessible because the connection is lost. This change makes all proxy restarts run as background jobs with WebSocket notifications, allowing the operation to complete even after connection loss.

Changes:
- Enhanced ProxyStatusChangedUI event to carry activityId for log monitoring
- Updated RestartProxyJob to dispatch status events and track activity
- Simplified Navbar restart() to always dispatch job for all servers
- Enhanced showNotification() to handle activity monitoring and new statuses
- Added comprehensive unit and feature tests

Benefits:
- Prevents localhost lockout during proxy restarts
- Consistent behavior across all server types
- Non-blocking UI with real-time progress updates
- Automatic activity log monitoring
- Proper error handling and recovery

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:30:12 +01:00
Andras Bacsai
1499135409 fix: prevent invalid paths from being saved to database
Move compose file validation BEFORE database save to prevent invalid
base directory and docker compose location values from being persisted
when validation fails.

Changes:
- Move compose file validation before $this->application->save()
- Restore original values when validation fails
- Add resetErrorBag() to clear stale validation errors

This fixes two bugs:
1. Invalid paths were saved to DB even when validation failed
2. Error messages persisted after correcting to valid path

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:30:04 +01:00
Andras Bacsai
8714d9bd03 fix: apply frontend path normalization to general settings page
Apply the same frontend path normalization pattern from commit f6398f7cf
to the General Settings page for consistency across all forms.

Changes:
- Add Alpine.js path normalization to Docker Compose section (base directory + compose location)
- Add Alpine.js path normalization to non-Docker Compose section (base directory + dockerfile location)
- Change wire:model to wire:model.defer to prevent backend requests during tab navigation
- Add @blur event handlers for immediate path normalization feedback
- Backend normalization remains as defensive fallback

This ensures consistent validation behavior and fixes potential tab focus
issues on the General Settings page.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:30:04 +01:00
Andras Bacsai
981fc127b5 fix: move base directory path normalization to frontend
Change wire:model.blur to wire:model.defer to prevent backend requests
during form navigation. Add Alpine.js path normalization functions that
run on blur, fixing tab focus issues while keeping path validation
purely on the frontend.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:30:04 +01:00
Andras Bacsai
b55aaf34d3
Decouple ServerStorageCheckJob from Sentinel sync (#7454) 2025-12-03 10:29:10 +01:00
Andras Bacsai
7b99fc77b1
Add runtime and buildtime properties to environment variables (#7470) 2025-12-03 10:26:44 +01:00
Andras Bacsai
1998314340 Add runtime and buildtime properties to environment variable booted method 2025-12-03 10:25:38 +01:00
Andras Bacsai
74bb8f49ce Fix: Correct time inconsistency in ServerStorageCheckIndependenceTest
Move Carbon::setTestNow() to the beginning of each test before creating
test data. Previously, tests created servers using now() (real current
time) and only afterwards called Carbon::setTestNow(), making
sentinel_updated_at inconsistent with the test clock.

This caused staleness calculations to use different timelines:
- sentinel_updated_at was based on real time (e.g., Dec 2024)
- Test execution time was frozen at 2025-01-15

Now all timestamps use the same frozen test time, making staleness
checks predictable and tests reliable regardless of when they run.

Affected tests (all 7 test cases in the file):
- does not dispatch storage check when sentinel is in sync
- dispatches storage check when sentinel is out of sync
- dispatches storage check when sentinel is disabled
- respects custom hourly storage check frequency when sentinel is out of sync
- handles VALID_CRON_STRINGS mapping correctly when sentinel is out of sync
- respects server timezone for storage checks when sentinel is out of sync
- does not dispatch storage check outside schedule

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:22:09 +01:00
Andras Bacsai
56a0143a25 Fix: Prevent ServerStorageCheckJob duplication when Sentinel is active
When Sentinel is enabled and in sync, ServerStorageCheckJob was being
dispatched from two locations causing unnecessary duplication:
1. PushServerUpdateJob (every ~30s with real-time filesystem data)
2. ServerManagerJob (scheduled cron check via SSH)

This commit modifies ServerManagerJob to only dispatch ServerStorageCheckJob
when Sentinel is out of sync or disabled. When Sentinel is active and in sync,
PushServerUpdateJob provides real-time storage data, making the scheduled SSH
check redundant.

Benefits:
- Eliminates duplicate storage checks when Sentinel is working
- Reduces unnecessary SSH overhead
- Storage checks still run as fallback when Sentinel fails
- Maintains scheduled checks for servers without Sentinel

Updated tests to reflect new behavior:
- Storage check NOT dispatched when Sentinel is in sync
- Storage check dispatched when Sentinel is out of sync or disabled
- All timezone and frequency tests updated accordingly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 10:05:10 +01:00
Andras Bacsai
fb8eb3fa37
Fix Traefik warning persistence after proxy configuration update (#7466) 2025-12-03 09:57:14 +01:00