Commit graph

4874 commits

Author SHA1 Message Date
Andras Bacsai
475cfd78cd fix: Prevent N+1 query in LocalPersistentVolume.isDockerComposeResource()
Use relationLoaded() check before accessing the application relationship
to avoid triggering individual queries for each volume when rendering
storage lists. Update Storage.php to eager load the relationship.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 21:23:46 +01:00
Andras Bacsai
f152ec00ad fix: Detect read-only Docker volumes with long-form syntax and enable refresh
- Fixed isReadOnlyVolume() to detect both short-form (:ro) and long-form (read_only: true) Docker Compose volume syntax
- Fixed path matching to use mount_path only (fs_path is transformed during parsing from ./file to absolute path)
- Added "Load from server" button for read-only volumes to allow users to refresh content
- Changed loadStorageOnServer() authorization from 'update' to 'view' since loading is a read operation
- Added helper text to Content field warning users that content may be outdated
- Applied fixes to both LocalFileVolume and LocalPersistentVolume models

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 14:18:58 +01:00
Andras Bacsai
07153de68d
Fix deployment marked as failed after healthy container rolling update (#7583) 2025-12-11 10:01:00 +01:00
Andras Bacsai
a2e5b2d67d Fix deployment marked as failed when healthy container completes rolling update
Prevent deployment status from regressing to FAILED after it's marked as FINISHED by:
1. Calling completeDeployment() first in post_deployment() before any operations that could fail
2. Wrapping all post-deployment side effects in try-catch blocks
3. Adding FINISHED to terminal states that cannot be changed
4. Protecting ExecuteRemoteCommand from overwriting FINISHED status

This fixes the issue where a deployment with a healthy container and successful rolling update was still marked as Failed in the UI.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 09:42:02 +01:00
Andras Bacsai
18675c8a4d
Fix restart counter persistence and add crash loop example (#7582) 2025-12-11 09:40:56 +01:00
Andras Bacsai
9598562ca0
Fix deployment logs overlap with indicator (#7580) 2025-12-11 09:40:39 +01:00
Andras Bacsai
c6a89087c5 Refactor deployment indicator to use server-side route detection
Replace client-side JavaScript URL checking with Laravel's routeIs() for determining when to reduce indicator opacity. This simplifies the code and uses route names as the source of truth.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 09:39:56 +01:00
Andras Bacsai
01308dede5 Fix restart counter persistence and add crash loop example
- Move restart counter reset from Livewire to ApplicationDeploymentJob to prevent race conditions with GetContainersStatus
- Remove artificial restart_type=manual tracking (never used in codebase)
- Add Crash Loop Example in seeder for testing restart tracking UI

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 09:39:55 +01:00
Andras Bacsai
918dc788ce
Remove duplicate getArchDockerInstallCommand() method (#7581) 2025-12-11 09:31:43 +01:00
Andras Bacsai
206a9c03d2 Remove duplicate getArchDockerInstallCommand() method
The method was defined twice with the first (outdated) definition using
-Syyy and lacking proper flags. Keep the improved version that uses -Syu
with --needed for idempotency and proper systemctl ordering.
2025-12-11 09:25:35 +01:00
Andras Bacsai
56102f6321 Prevent multiple deploymentFinished event dispatches
Add flag to ensure event is only dispatched once, avoiding wasteful
duplicate dispatches during the race condition window before Livewire
removes wire:poll from the DOM.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 09:25:22 +01:00
Andras Bacsai
d9762e0310 Fix deployment log follow feature stopping mid-deployment
Removed auto-disable behaviors that caused follow logs to stop unexpectedly:
- Removed scroll detection that disabled following when user scrolled >50px from bottom
- Removed fullscreen exit handler that disabled following
- Removed ServiceChecked event listener that caused unnecessary flickers

Follow logs now only stops when:
- User explicitly clicks the Follow Logs button
- Deployment finishes (auto-scrolls to end first, then disables after 500ms delay)

Also improved get-logs component with memory optimizations:
- Limited display to last 2000 lines to prevent memory exhaustion
- Added debounced search (300ms) and scroll handling (150ms)
- Optimized DOM rendering

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 09:14:27 +01:00
Andras Bacsai
56394ba093 fix: return actual error message from token validation endpoint
- Return the specific error from validateProviderToken() instead of
  generic "Failed to validate token." message
- Update test to expect the actual error message

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 13:22:53 +01:00
Andras Bacsai
596b1cb76e refactor: extract token validation into reusable method
- Add validateProviderToken() helper method to reduce code duplication
- Use request body only ($request->json()->all()) to avoid route parameter conflicts
- Add proper logging for token validation failures
- Add missing DB import to migration file
- Minor test formatting fix

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 12:56:57 +01:00
Andras Bacsai
10003cec3d fix: add UUID support to CloudProviderToken model
- Add uuid column to cloud_provider_tokens table via migration
- Update CloudProviderToken to extend BaseModel for auto UUID generation
- Generate UUIDs for existing records in migration
- Fixes null uuid issue in API responses

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 08:59:13 +01:00
Andras Bacsai
ef0a1241b0 fix: rename validate() to validateToken() to avoid parent method conflict
The validate() method conflicted with Controller::validate(). Renamed to
validateToken() to resolve the declaration compatibility issue.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 08:57:04 +01:00
Andras Bacsai
62c394d3a1 feat: add Hetzner server provisioning API endpoints
Add complete API support for Hetzner server provisioning, matching UI functionality:

Cloud Provider Token Management:
- POST /api/v1/cloud-tokens - Create and validate tokens
- GET /api/v1/cloud-tokens - List all tokens
- GET /api/v1/cloud-tokens/{uuid} - Get specific token
- PATCH /api/v1/cloud-tokens/{uuid} - Update token name
- DELETE /api/v1/cloud-tokens/{uuid} - Delete token
- POST /api/v1/cloud-tokens/{uuid}/validate - Validate token

Hetzner Resource Discovery:
- GET /api/v1/hetzner/locations - List datacenters
- GET /api/v1/hetzner/server-types - List server types
- GET /api/v1/hetzner/images - List OS images
- GET /api/v1/hetzner/ssh-keys - List SSH keys

Server Provisioning:
- POST /api/v1/servers/hetzner - Create server with full options

Features:
- Token validation against provider APIs before storage
- Smart SSH key management with MD5 fingerprint deduplication
- IPv4/IPv6 network configuration with preference logic
- Cloud-init script support with YAML validation
- Team-based isolation and security
- Comprehensive test coverage (40+ test cases)
- Complete documentation with curl examples and Yaak collection

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-10 08:38:09 +01:00
Andras Bacsai
6e15d8e5f8
Add ValidProxyConfigFilename rule for dynamic proxy config validation (#7544) 2025-12-09 16:32:41 +01:00
Andras Bacsai
7c552e8a6a
Fix API response to return fqdn instead of non-existent domains attribute (#7546) 2025-12-09 16:29:02 +01:00
Andras Bacsai
32e047e512 Fix API response to return fqdn instead of non-existent domains attribute
The Application model stores domain as 'fqdn' not 'domains'. The API response
was incorrectly using data_get($application, 'domains') which always returned
null. Fixed all 5 application creation endpoint responses.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 16:26:08 +01:00
Andras Bacsai
5ec3f39b9b
Add autogenerate_domain API parameter for applications (#7515) 2025-12-09 16:19:49 +01:00
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
ebac90097a fix: Escape container name in orphaned PR cleanup job
Add shell escaping with escapeshellarg() for container names in the
docker rm command to prevent command injection. Also add validation
to skip containers with missing names and log a warning.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 20:09:00 +01:00
Andras Bacsai
86a02a12e6
Update app/Actions/Application/CleanupPreviewDeployment.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-12-08 17:35:13 +01:00
Andras Bacsai
945cce9587 feat: Add scheduled job to cleanup orphaned PR containers
Add CleanupOrphanedPreviewContainersJob that runs daily to find and remove any PR preview containers that weren't properly cleaned up when their PR was closed.

The job:
- Scans all functional servers for containers with coolify.pullRequestId label
- Checks if the corresponding ApplicationPreview record exists in the database
- Removes containers where the preview record no longer exists (truly orphaned)
- Acts as a safety net for webhook failures or race conditions

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 17:15:52 +01:00
Andras Bacsai
d27070b215 fix: Add comprehensive PR cleanup to GitLab, Bitbucket, and Gitea webhooks
Create a shared CleanupPreviewDeployment action that unifies PR cleanup logic across all Git providers. Previously, GitHub had comprehensive cleanup (cancels active deployments, kills helper containers, removes all PR containers), while GitLab, Bitbucket, and Gitea only did basic cleanup (delete preview record and remove one container by name).

This fix ensures all providers properly clean up orphaned PR containers when a PR is closed/merged, preventing security issues and resource waste. Also fixes early return bug in GitLab webhook handler.

Fixes #2610

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 17:10:39 +01:00
Andras Bacsai
5e8d11f732 refactor: replace queries with cached versions for performance improvements 2025-12-08 13:39:33 +01:00
Andras Bacsai
bb83f4e5c3
Add Arch Linux server support and fix package sanitization (#7531) 2025-12-08 09:18:14 +01:00
Andras Bacsai
089007919d Add package validation guard and make pacman idempotent
- Add explicit validation in UpdatePackage to require package name when
  'all' is false, preventing empty package commands being sent to servers
- Add --needed flag to pacman install in InstallDocker for idempotent
  Docker installation on Arch Linux

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 09:17:24 +01:00
Andras Bacsai
9bb77da9a4 Add Arch Linux server support and fix package sanitization
- Add Arch Linux (pacman) support to server operations: CheckUpdates, InstallDocker, InstallPrerequisites, UpdatePackage
- Implement parsePacmanOutput() to parse 'pacman -Qu' output format
- Add security improvement: package name sanitization to prevent command injection
- Initialize variables in CheckUpdates to prevent undefined variable errors in catch block
- Use proper Arch pacman flags: -Syu for full system upgrade before operations

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 09:02:00 +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
847c4f4627
fix: add Arch Linux support for Docker installation (#7408) 2025-12-07 19:08:20 +01:00
Andras Bacsai
eb743cf690 Add autogenerate_domain API parameter for applications
Allows API consumers to control domain auto-generation behavior. When autogenerate_domain is true (default) and no custom domains are provided, the system auto-generates a domain using the server's wildcard domain or sslip.io fallback.

- Add autogenerate_domain parameter to all 5 application creation endpoints
- Add validation and allowlist rules
- Implement domain auto-generation logic across all application types
- Add comprehensive unit tests for the feature

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 21:16:04 +01:00
Andras Bacsai
f0fbaf3652
Fix logs not loading for single container services (#7509) 2025-12-05 14:20:25 +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
b299ceb445
Add Garage as a one-click service (#7508) 2025-12-05 13:49:03 +01:00
Andras Bacsai
0f54c194d7 Add Garage as a one-click service
Adds support for deploying Garage (S3-compatible object storage) as a
one-click service in Coolify. Includes service template with TOML config,
automatic URL generation for S3, Web, and Admin endpoints with reverse
proxy configuration, and UI fields for credentials and access tokens.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 13:46:57 +01:00
Andras Bacsai
21429a26b1
Add per-application Docker image retention for rollback (#7504) 2025-12-05 13:00:18 +01:00
Andras Bacsai
62aa7397da Fix grep regex escaping for extended regex (ERE)
Replace preg_quote() with proper ERE escaping since grep -E uses
extended regex syntax, not PHP/PCRE. This ensures special characters
in registry URLs (dots, etc.) are properly escaped.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:57:57 +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
439afca642 Inject commit-based image tags for Docker Compose build services
For Docker Compose applications with build directives, inject commit-based
image tags (uuid_servicename:commit) to enable rollback functionality.
Previously these services always used 'latest' tags, making rollback impossible.

- Only injects tags for services with build: but no explicit image:
- Uses pr-{id} tags for pull request deployments
- Respects user-defined image: fields (preserves user intent)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:41:47 +01:00
Andras Bacsai
710dc3ca4b Add Docker Compose support for image retention during cleanup
Support for Docker Compose applications with build: directives that create
images with uuid_servicename naming pattern (e.g., app-uuid_web:commit).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:17:23 +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
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
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
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