Commit graph

1597 commits

Author SHA1 Message Date
Andras Bacsai
028fb5c22c Add ValidProxyConfigFilename rule for dynamic proxy config validation
Adds a new Laravel validation rule to prevent path traversal, hidden files, and invalid filenames in the dynamic proxy configuration feature. Validates filenames to ensure they contain only safe characters, don't exceed filesystem limits, and don't use reserved names.

- New Rule: ValidProxyConfigFilename with comprehensive validation
- Updated: NewDynamicConfiguration to use the new rule
- Added: 13 unit tests covering all validation scenarios

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 16:12:45 +01:00
Andras Bacsai
dca6d9f7aa fix: Prevent terminal disconnects when browser tab loses focus
Add visibility API handling to pause heartbeat monitoring when the browser tab is hidden, preventing false disconnection timeouts. When the tab becomes visible again, verify the connection is still alive or attempt reconnection.

Also remove the ApplicationStatusChanged event listener that was triggering terminal reloads whenever any application status changed across the team.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 20:48:03 +01:00
Andras Bacsai
5e8d11f732 refactor: replace queries with cached versions for performance improvements 2025-12-08 13:39:33 +01:00
Andras Bacsai
7c1f230bd3 fix: remove {{port}} template variable and ensure ports are always appended to preview URLs
The {{port}} template variable was undocumented and caused a double port bug
when used in preview URL templates. Since ports are always appended to the final
URL anyway, we remove {{port}} substitution entirely and ensure consistent port
handling across ApplicationPreview, PreviewsCompose, and the applicationParser helper.

Also fix PreviewsCompose.php which wasn't preserving ports at all, and improve
the Blade template formatting in previews-compose.blade.php.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-07 21:53:47 +01:00
Andras Bacsai
a0884b758f Fix logs not loading for single container services and applications
- Initialize logsLoaded as false to ensure init() triggers log loading
- Set logsLoaded=true after calling getLogs() in init()
- Allow services/PRs to load logs automatically when expandByDefault=true (single container)
- Previously, services would skip initial load unless refresh=true, now single containers work

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 14:19:31 +01:00
Andras Bacsai
511415770a Add server-level toggle to disable application image retention
Adds a new server-level setting that allows administrators to disable
per-application image retention globally for all applications on a server.
When enabled, Docker cleanup will only keep the currently running image
regardless of individual application retention settings.

Changes:
- Add migration for disable_application_image_retention boolean field
- Update ServerSetting model with cast
- Add checkbox in DockerCleanup page (Advanced section)
- Modify CleanupDocker action to check server-level setting
- Update Rollback page to show warning and disable inputs when server
  retention is disabled
- Add helper text noting server-level override capability

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:22:20 +01:00
Andras Bacsai
4ed7a4238a Add per-application Docker image retention for rollback capability
Implement a per-application setting (`docker_images_to_keep`) in `application_settings` table to control how many Docker images are preserved during cleanup. The cleanup process now:

- Respects per-application retention settings (default: 2 images)
- Preserves the N most recent images per application for easy rollback
- Always deletes PR images and keeps the currently running image
- Dynamically excludes application images from general Docker image prune
- Cleans up non-Coolify unused images to prevent disk bloat

Fixes issues where cleanup would delete all images needed for rollback.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:02:07 +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
9e0fa03434
Run proxy restart as background job with real-time logs (#7475) 2025-12-04 14:59:50 +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
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
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
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
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
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
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
b1a4853e03 Add missing import for ProxyTypes enum in Navbar component 2025-12-03 09:53:42 +01:00
Andras Bacsai
e110e32320 Fix Traefik warning persistence after proxy restart
When users updated Traefik configuration or version and restarted the proxy, the warning triangle icon showing outdated version info persisted until the weekly CheckTraefikVersionJob ran (Sundays at 00:00).

This was caused by the UI warning indicators reading from cached database columns (detected_traefik_version, traefik_outdated_info) that were only updated by the weekly scheduled job, not after proxy restarts.

Solution: Add version check to ProxyStatusChangedNotification listener that triggers automatically after proxy status changes to "running".

Changes:
- Add Traefik version check in ProxyStatusChangedNotification::handle()
- Triggers automatically when ProxyStatusChanged event fires with status="running"
- Removed duplicate version check from Navbar::restart() (now handled by event)
- Event fires after StartProxy/StopProxy actions complete via async jobs
- Gracefully handles missing versions.json data with warning log

Benefits:
- Version check happens AFTER proxy is confirmed running (more accurate)
- Reuses existing event infrastructure (ProxyStatusChanged)
- Works for all proxy restart scenarios (manual restart, config save + restart, etc.)
- No duplicate checks - single source of truth in event listener
- Async job runs in background (5-10 seconds) to update database
- User sees warning cleared after page refresh

Flow:
1. User updates config and restarts proxy (or manually restarts)
2. StartProxy action completes async, dispatches ProxyStatusChanged event
3. ProxyStatusChangedNotification listener receives event
4. Listener checks proxy status = "running", dispatches CheckTraefikVersionForServerJob
5. Job detects version via SSH, updates database columns
6. UI re-renders with cleared warnings

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 09:45:23 +01:00
Andras Bacsai
e10bd011c5 Enable timestamps in log display and improve styling for better readability 2025-12-03 09:09:12 +01:00
Andras Bacsai
2302a70a44
Fix: Docker build args injection regex to support service names (#7433) 2025-12-01 13:47:08 +01:00
Andras Bacsai
bf503861fc Add build args to Final Build Command Preview in UI
The "Final Build Command (Preview)" field now shows build arguments
that will be injected during deployment, matching the actual command
that runs. This provides transparency and helps users debug build issues.

Changes:
- Modified getDockerComposeBuildCommandPreviewProperty() to inject build args
- Uses same helper functions as deployment (generateDockerBuildArgs, injectDockerComposeBuildArgs)
- Respects use_build_secrets setting (build args only shown when disabled)
- Filters environment variables where is_buildtime = true

Example output:
docker compose -f ./docker-compose.yaml --env-file /artifacts/build-time.env build --build-arg FOO --build-arg BAR backend

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 13:45:14 +01:00
Andras Bacsai
7a28886c73
Merge branch 'next' into fix-port-modal-strip-prefixes 2025-12-01 13:43:41 +01:00
Andras Bacsai
abb568c600 fix: bypass port validation when saving advanced checkboxes
Add instantSaveSettings() method to save gzip, stripprefix, and
exclude_from_status checkboxes without triggering port validation modal.
These settings don't require domain/port validation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 13:39:15 +01:00
Andras Bacsai
627cec16fa
Merge branch 'next' into fix-traefik-startup 2025-11-28 17:54:48 +01:00
Andras Bacsai
cb0f2301f5 Fix: Traefik proxy startup issues - handle null versions and filter predefined networks
Fixes two critical issues preventing Traefik proxy startup:

1. TypeError when restarting proxy: Handle null return from get_traefik_versions()
   - Add null check before dispatching CheckTraefikVersionForServerJob
   - Log warning when version data is unavailable
   - Prevents: "Argument #2 must be of type array, null given"

2. Docker network error: Filter out predefined Docker networks
   - Add isDockerPredefinedNetwork() helper to centralize network filtering
   - Apply filtering in collectDockerNetworksByServer() before operations
   - Apply filtering in generateDefaultProxyConfiguration()
   - Prevents: "operation is not permitted on predefined default network"

Also: Move $cachedVersionsFile assignment after null check in Proxy.php

Tests: Added 7 new unit tests for network filtering function
All existing tests pass with no regressions

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 17:53:26 +01:00
Andras Bacsai
a25e553f88
Fix: Fragile service name parsing with hyphens (#7399) 2025-11-28 17:50:44 +01:00
Andras Bacsai
b7fcb0f362 Fix Alpine state reference and remove unused property in upgrade modal
- Fix incorrect Alpine state reference: Changed `this.$wire.showProgress` to `this.showProgress` in upgrade.blade.php:155
- Remove unused `$showProgress` property from Upgrade.php Livewire component
- The backend property was never set or used; all progress tracking is handled by Alpine state
- This fixes potential race conditions where the guard condition was not working as intended

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 17:48:52 +01:00
Andras Bacsai
8c40cc607a Fix: Fragile service name parsing in applyServiceApplicationPrerequisites
Changed from `->before('-')` to `->beforeLast('-')` to correctly parse service
names with hyphens. This fixes prerequisite application for ~230+ services
containing hyphens in their template names (e.g., docker-registry,
elasticsearch-with-kibana).

Added comprehensive test coverage for hyphenated service names and fixed
existing tests to use realistic CUID2 UUID format. All unit tests pass.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 17:42:04 +01:00
Andras Bacsai
4706bc23aa Refactor: Centralize service application prerequisites
Refactors the Appwrite and Beszel service-specific application settings
to use a centralized constant-based approach, following the same pattern
as NEEDS_TO_CONNECT_TO_PREDEFINED_NETWORK.

Changes:
- Added NEEDS_TO_DISABLE_GZIP constant for services requiring gzip disabled
- Added NEEDS_TO_DISABLE_STRIPPREFIX constant for services requiring stripprefix disabled
- Created applyServiceApplicationPrerequisites() helper function in bootstrap/helpers/services.php
- Updated all service creation flows to use the centralized helper:
  * app/Livewire/Project/Resource/Create.php (web handler)
  * app/Http/Controllers/Api/ServicesController.php (API handler - BUG FIX)
  * app/Livewire/Project/New/DockerCompose.php (custom compose handler)
  * app/Http/Controllers/Api/ApplicationsController.php (API custom compose handler)
- Added comprehensive unit tests for the new helper function

Benefits:
- Single source of truth for service prerequisites
- DRY - eliminates code duplication between web and API handlers
- Fixes bug where API-created services didn't get prerequisites applied
- Easy to extend for future services (just edit the constant)
- More maintainable and testable

Related commits: 3a94f1ea1 (Beszel), 02b18c86e (Appwrite)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 16:47:09 +01:00
Andras Bacsai
2c16727075
feat(ui): Logs color highlight based on log level (#7288) 2025-11-28 13:27:51 +01:00
Andras Bacsai
a95a4129c8
Merge branch 'next' into shadow/fix-service-beszel 2025-11-28 11:08:01 +01:00
Andras Bacsai
02b18c86e0
Fix:(service) Appwrite too many redirects error (#7364) 2025-11-28 11:07:41 +01:00
Andras Bacsai
25a96ad662
fix(docker): replace deprecated --time flag with -t for full compatibility across Docker versions (#6807) 2025-11-28 10:47:19 +01:00
Andras Bacsai
e5280fd3ad feat: add predefined network connection for pgAdmin and postgresus services 2025-11-28 10:29:13 +01:00
Andras Bacsai
1d054b23b8
Merge branch 'next' into shadow/fix-docker-time-command 2025-11-28 10:25:42 +01:00
Andras Bacsai
83f9fd8e20
fix(ui): incorrect caddy proxy config file path on proxy page (#6722) 2025-11-28 10:24:01 +01:00
Andras Bacsai
c4ebf951fa
Merge branch 'next' into shadow/improve-service-postgresus 2025-11-28 10:18:45 +01:00
Andras Bacsai
a4e4cc2c17 fix: update service creation logic to only connect pgAdmin to Docker network 2025-11-28 10:17:27 +01:00
Andras Bacsai
281a706231 fix: enhance validation for database names and filenames to prevent command injection 2025-11-27 14:51:23 +01:00
Andras Bacsai
0073d045fb fix: enhance security by validating and escaping database names, file paths, and proxy configuration filenames to prevent command injection 2025-11-27 14:36:31 +01:00
Andras Bacsai
c2e1379ba8 feat: add availableSharedVariables method and enhance env-var-input component for better password handling 2025-11-27 10:23:46 +01:00
Andras Bacsai
0298ddffbd fix: ensure syncData is called with both true and false parameters in submit method 2025-11-27 09:26:54 +01:00