Commit graph

5050 commits

Author SHA1 Message Date
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
Andras Bacsai
13b7c3dbfc Add real-time UI updates after Traefik version check
Dispatch ProxyStatusChangedUI event after version check completes so the UI updates in real-time without requiring page refresh.

Changes:
- Add ProxyStatusChangedUI::dispatch() at all exit points in CheckTraefikVersionForServerJob
- Ensures UI refreshes automatically via WebSocket when version check completes
- Works for all scenarios: version detected, using latest tag, outdated version, up-to-date

User experience:
- User restarts proxy
- Warning clears automatically in real-time (no refresh needed)
- Leverages existing WebSocket infrastructure

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 09:56: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
c982d58eee Refactor: Move Sentinel restart logic into processServerTasks method 2025-12-03 09:22:00 +01:00
Andras Bacsai
f75bc85bc1
Merge branch 'next' into decouple-storage-from-sentinel 2025-12-03 09:19:09 +01:00
Andras Bacsai
9c80e15dd9
fix: prevent cleanup exceptions from marking successful deployments as failed (#7460) 2025-12-03 09:18:52 +01:00
Andras Bacsai
a767ca30e6 fix: log unhealthy container status during health check 2025-12-03 09:18:32 +01:00
Andras Bacsai
a18e920e4c fix: remove logging of cleanup failures to prevent false deployment errors 2025-12-03 09:16:28 +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
66e81d6d96 Fix container status display: preserve "Restarting" for applications and sub-resources
Add preserveRestarting parameter to ContainerStatusAggregator to allow applications
and service sub-resources to display "Restarting" status instead of being marked as
"Degraded". This gives better visibility into container restart behavior.

- Update ContainerStatusAggregator to accept preserveRestarting parameter (defaults to false)
- Update GetContainersStatus to use preserveRestarting: true for applications and service sub-resources
- Update PushServerUpdateJob to use preserveRestarting: true for applications and service sub-resources
- Add comprehensive documentation explaining the parameter behavior and when to use it

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 08:23:35 +01:00
Andras Bacsai
c65ad2e655 Fix complex status logic: handle degraded sub-resources and mixed running+starting states
- Add support for degraded status from sub-resources as highest priority
- Handle mixed running+starting state to show service as not fully ready
- Update state priority hierarchy from 8 to 10 levels
- Add comprehensive test coverage for new status scenarios

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 21:47:15 +01:00
Andras Bacsai
cfea11f189 fix: prevent cleanup exceptions from marking successful deployments as failed
Fixes #7439 where successful deployments were being marked as FAILED due to exceptions during old container cleanup.

Root cause: Commit 97550f406 wrapped stop_running_container() in try-catch that re-throws ALL exceptions as DeploymentException. When old containers are already removed (a common scenario), the "No such container" error propagates and marks successful deployments as failed.

Solution: Check if deployment has already succeeded (newVersionIsHealthy || force) before re-throwing exceptions from cleanup operations. Cleanup failures are logged but don't fail the deployment.

- Add conditional handling in stop_running_container() catch block
- Log cleanup warnings with hidden: true to avoid UI clutter
- Only re-throw exceptions if deployment hasn't succeeded yet
- Preserves backward compatibility and expected behavior

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 17:28:48 +01:00
Andras Bacsai
8ff83cc3d6 Fix: Pass $serverTimezone to shouldRunNow() in ServerCheckJob dispatch
Pass the server timezone parameter to shouldRunNow() call at line 127,
ensuring ServerCheckJob dispatch respects the server's local timezone
instead of falling back to the instance default.

This aligns the behavior with other scheduled tasks in the same method:
- ServerStorageCheckJob (line 137)
- ServerPatchCheckJob (line 144)
- Sentinel restart (line 152)

All scheduled tasks in processServerTasks() now consistently use the
server's configured timezone for cron evaluation.

Added unit test to verify timezone-aware cron schedule evaluation.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 16:58:43 +01:00
Andras Bacsai
ed5796739f Fix: Prevent ServerManagerJob executionTime mutation across server loop
Fixed a critical bug where $this->executionTime was being mutated during
the server processing loop, causing incorrect scheduling calculations for
subsequent servers.

The issue occurred at line 123 where subSeconds() was called directly on
the shared executionTime instance. This caused the baseline time to shift
by waitTime seconds with each server iteration, resulting in compounding
scheduling errors (e.g., 1680 seconds drift over 5 servers).

Changed:
- app/Jobs/ServerManagerJob.php:123
  Added .copy() before .subSeconds() to prevent mutation

Added comprehensive unit tests that verify:
- Immutability when using .copy()
- Demonstration of the bug without .copy()
- Correct behavior across multiple iterations

This follows the existing pattern in shouldRunNow() (line 167) and aligns
with other jobs in the codebase.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 15:27:17 +01:00
Andras Bacsai
158d54712f Remove webhook maintenance mode replay feature
This feature stored incoming webhooks during maintenance mode and replayed them
when maintenance ended. The behavior adds unnecessary complexity without clear
value. Standard approach is to let webhooks fail during maintenance and let
senders retry.

Removes:
- Listener classes that handled maintenance mode events and webhook replay
- Maintenance mode checks from all webhook controllers (Github, Gitea, Gitlab, Bitbucket, Stripe)
- webhooks-during-maintenance filesystem disk configuration
- Feature mention from CHANGELOG

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 13:36:32 +01:00
Andras Bacsai
b47181c790 Decouple ServerStorageCheckJob from Sentinel sync status
Server disk usage checks now run on their configured schedule regardless of Sentinel status, eliminating monitoring blind spots when Sentinel is offline, out of sync, or disabled. Storage checks now respect server timezone settings, consistent with patch checks.

Changes:
- Moved server timezone calculation to top of processServerTasks()
- Extracted ServerStorageCheckJob dispatch from Sentinel conditional
- Fixed default frequency to '0 23 * * *' (11 PM daily)
- Added timezone parameter to storage check scheduling

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 13:36:25 +01:00
Andras Bacsai
4b119726d9 Fix Traefik email notification with clickable server links
- Add URL generation to notification class using base_url() helper
- Replace config('app.url') with proper base_url() for accurate instance URL
- Make server names clickable links to proxy configuration page
- Use data_get() with fallback values for safer template data access
- Add comprehensive tests for URL generation and email rendering

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 13:08:40 +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
d59c75c2b2 Fix: Docker build args injection regex to support service names
The regex pattern in injectDockerComposeBuildArgs() was too restrictive
and failed to match `docker compose build servicename` commands. Changed
the lookahead from `(?=\s+(?:--|-)|\s+(?:&&|\|\||;|\|)|$)` to the
simpler `(?=\s|$)` to allow any content after the build command,
including service names with hyphens/underscores and flags.

Also improved the ApplicationDeploymentJob to use the new helper function
and added comprehensive test coverage for service-specific builds.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 13:16:05 +01:00
Murat Aslan
eedc9e586d fix: add Arch Linux support for Docker installation
Arch Linux was listed in SUPPORTED_OS but InstallDocker.php had no
specific handler for it, causing 'Unsupported OS' errors when trying
to add Arch Linux servers.

This adds:
- Detection of 'arch' OS type in the install flow
- New getArchDockerInstallCommand() method using pacman:
  - pacman -Syyy (refresh package databases)
  - pacman -S docker docker-compose (install Docker)
  - systemctl start/enable docker

Fixes #4523
2025-11-29 15:22:58 +03: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
b246cdffab
Fix: Version downgrade prevention with cache validation (#7396) 2025-11-28 16:31:46 +01:00
Andras Bacsai
4052d1bd05 Refactor color classes from yellow to warning across the application
- Updated color classes in NotifyDemo.php to use warning colors.
- Added new warning color variables in app.css.
- Changed warning icon colors in callout.blade.php.
- Updated loading spinner and hover states in global-search.blade.php.
- Refactored warning messages and styles in project application views.
- Adjusted log display colors in get-logs.blade.php.
- Updated private key status indicators in index.blade.php.
- Changed hover and text colors for documentation links in cloudflare-tunnel.blade.php.
- Refactored server creation messages in by-hetzner.blade.php.
- Updated proxy warning button colors in proxy.blade.php.
- Changed loading spinner colors in show.blade.php.
- Updated deployment status colors in deployments.blade.php and show.blade.php.
2025-11-28 16:23:32 +01:00
Andras Bacsai
cd10796612 Fix: Version downgrade prevention - validate cache and add running version checks
## Changes
- **CheckForUpdatesJob**: Add triple version comparison (CDN vs cache vs running)
  - Never allows version downgrade from currently running version
  - Uses data_set() for safer nested array mutation
  - Prevents incorrect new_version_available flag setting

- **UpdateCoolify**: Add cache validation before fallback
  - Validates cache against running version on CDN failure
  - Throws exception if cache is corrupted/older than running
  - Applies to both manual and automated updates

- **Tests**: Add comprehensive test coverage
  - tests/Unit/CheckForUpdatesJobTest.php (5 tests)
  - tests/Unit/UpdateCoolifyTest.php (3 tests)

## Impact
- Prevents all downgrade scenarios (CDN rollback, corrupted cache, etc.)
- Maintains backward compatibility
- Provides clear logging for debugging

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 16:05:41 +01:00
Andras Bacsai
d9774d2968 Fix: Prevent version downgrades and centralize CDN configuration (#7383)
## Root Cause
Between Nov 25-26, a CDN redirect was added without curl's `-L` flag,
causing version cache corruption and automatic downgrades.

## Three Critical Bugs Fixed

### Bug #1: CheckForUpdatesJob could overwrite newer cached version
- Problem: CDN serving older version would overwrite local cache
- Solution: Smart version merge - keep max Coolify version, update other components
- Location: app/Jobs/CheckForUpdatesJob.php:33-52

### Bug #2: Manual updates bypassed downgrade protection
- Problem: Downgrade guard only applied to auto-updates
- Solution: Always block downgrades for both manual and auto-updates
- Location: app/Actions/Server/UpdateCoolify.php:65-75

### Bug #3: Updates used stale local cache
- Problem: Never validated cache against CDN at update time
- Solution: Fetch fresh CDN data before executing updates
- Location: app/Actions/Server/UpdateCoolify.php:34-49

## Additional Improvement: Centralized CDN Configuration

Added three new config keys for easy CDN management:
- `cdn_url` - Base CDN URL (default: https://cdn.coollabs.io)
- `versions_url` - Full versions.json URL
- `upgrade_script_url` - Full upgrade.sh URL

All configurable via environment variables:
```bash
CDN_URL=https://cdn.coolify.io
VERSIONS_URL=https://custom-cdn.example.com/versions.json
UPGRADE_SCRIPT_URL=https://custom-cdn.example.com/upgrade.sh
```

## Files Modified
- config/constants.php - CDN configuration
- app/Jobs/CheckForUpdatesJob.php - Smart version merge + centralized URL
- app/Actions/Server/UpdateCoolify.php - Downgrade protection + fresh fetch + centralized URLs
- app/Jobs/CheckHelperImageJob.php - Centralized URL
- bootstrap/helpers/shared.php - Centralized URL

## Testing
-  All modified files pass Pint formatting
-  78 unit tests pass (2 pre-existing failures unrelated to changes)

## Impact
- No breaking changes - defaults to current CDN
- Easy CDN migration via environment variables
- Prevents all downgrade scenarios
- Maintains independent Sentinel/Helper/Traefik updates

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:20:33 +01:00
Andras Bacsai
995e3d554d
Merge branch 'next' into fix-docker-time-database-v2 2025-11-28 13:28:26 +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
f42d076f31
Merge branch 'next' into fix-docker-time-database-v2 2025-11-28 13:12:00 +01:00
EbinJose2002
f37eef8266 - Made necessary changes to the migration and created new one as well.
- Updated the Clickhouse service template to use the official `clickhouse/clickhouse-server` image.
- Removed the usage of the deprecated `bitnamilegacy/clickhouse` image.

- fixes #7110
2025-11-28 17:12:11 +05:30
Andras Bacsai
c136724838 fix(docker): migrate database start actions from --time to -t flag
Migrates 8 database start action files from deprecated --time=10 to compatible -t 10 flag for Docker v28+ compatibility. Also updates test expectations in StopProxyTest.php.

Docker deprecated the --time flag in v28.0. The -t shorthand works on all Docker versions (pre-28 and 28+), ensuring backward and forward compatibility.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 11:18:12 +01:00
Andras Bacsai
9503da60b4
Revert "fix(docker): migrate database start actions from --time to -t flag" 2025-11-28 11:15:55 +01:00
Andras Bacsai
5b7a6d9a76 fix(docker): migrate database start actions from --time to -t flag
Migrates 8 database start action files from deprecated --time=10 to compatible -t 10 flag for Docker v28+ compatibility. Also updates test expectations in StopProxyTest.php.

Docker deprecated the --time flag in v28.0. The -t shorthand works on all Docker versions (pre-28 and 28+), ensuring backward and forward compatibility.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 11:08:20 +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
0209bb63e2
fix: prevent duplicate environment variables in buildtime.env and support nixpacks plan variable overrides (#7373) 2025-11-28 10:39:32 +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
be2b01786a fix: prevent duplicate environment variables in buildtime.env
Refactors generate_buildtime_environment_variables() to use an associative
array (dictionary) approach instead of sequential push() calls. This prevents
duplicate variable declarations in the buildtime.env file.

**Problem:**
After adding nixpacks plan variables to buildtime.env, the same variable
could appear twice in the file:
- Once from nixpacks plan (e.g., NIXPACKS_NODE_VERSION='22')
- Once from user-defined variables (e.g., NIXPACKS_NODE_VERSION="22")

This caused shell errors and undefined behavior during Docker builds.

**Root Cause:**
The push() method adds items sequentially without checking for duplicate
keys. When a variable existed in both nixpacks plan AND user-defined vars,
both would be written to the file.

**Solution:**
- Use associative array ($envs_dict) for automatic deduplication
- Establish clear override precedence:
  1. Nixpacks plan variables (lowest priority)
  2. COOLIFY_* variables (medium priority)
  3. SERVICE_* variables (medium priority)
  4. User-defined variables (highest priority - can override everything)
- Convert to collection format at the end
- Add debug logging when user variables override plan variables

**Benefits:**
- Automatic deduplication (array keys are unique by nature)
- User variables properly override nixpacks plan values
- Clear, explicit precedence order
- No breaking changes to existing functionality

Fixes #7114

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 10:10:19 +01:00
Andras Bacsai
ef332b9af4 fix: add support for nixpacks plan variables in buildtime environment 2025-11-28 10:10:19 +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
e60e74ac90
fix: trigger configuration changed detection for build settings (#7371) 2025-11-27 12:23:32 +01:00
Andras Bacsai
9452f0b468 fix: trigger configuration changed detection for build settings
Include 'Inject Build Args to Dockerfile' and 'Include Source Commit in Build' settings in the configuration hash calculation. These settings affect Docker build behavior, so changes to them should trigger the restart required notification. Add unit tests to verify hash changes when these settings are modified.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 12:22:54 +01:00
Andras Bacsai
48c3daae88 fix: improve error handling and output capturing during Git operations in SyncBunny command 2025-11-27 10:51:25 +01:00
Andras Bacsai
d27d697b37 fix: log warning on backup failure during name cleanup process 2025-11-27 10:51:19 +01:00
Andras Bacsai
b5666da342 test: add tests for shared environment variable spacing and resolution 2025-11-27 10:45:39 +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
Andras Bacsai
246e3cd8a2 fix: resolve Docker validation race conditions and sudo prefix bug
- Fix sudo prefix bug: Use word boundary matching to prevent 'do' keyword from matching 'docker' commands
- Add ensureProxyNetworksExist() helper to create networks before docker compose up
- Ensure networks exist synchronously before dispatching async proxy startup to prevent race conditions
- Update comprehensive unit tests for sudo parsing (50 tests passing)

This resolves issues where Docker commands failed to execute with sudo on non-root servers and where proxy networks were not created before the proxy container started.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-27 09:04:42 +01:00
ShadowArcanist
cc727b2c70 [service] Add postgresus to predefined docker networks by default
Without this, users have to manually enable "Connect to Predefined Networks" inorder to access one click databases from postgresus dashboard
2025-11-27 08:07:06 +01:00
ShadowArcanist
bc997370f7 [service] fixed beszel realtime feature not working
Without this fix users have to manually uncheck Enable Gzip Compression option for the dashboard realtime feature to work
2025-11-27 07:29:31 +01:00
ShadowArcanist
6254cdfd5a [service] fixed appwrite too many redirects error
Without this fix users have to manually uncheck strip prefix option for appwrite, appwrite-console, and appwrite-realtime services for the service to work
2025-11-27 06:27:09 +01:00
Andras Bacsai
9aea159a24 feat: add functionality to sync releases.json and versions.json to GitHub in one PR 2025-11-26 14:43:25 +01:00
Andras Bacsai
c25272de8d reduce: minimize logging in cleanup commands
Reduce excessive logging in CleanupRedis and CleanupNames commands to output only a single summary line. Remove per-item logs and detailed status messages while keeping the final count of items cleaned up. Detail logs still available in dry-run mode for preview.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 14:19:13 +01:00
Andras Bacsai
d2d5bd4be8
feat: add Docker build cache preservation toggles (#7352) 2025-11-26 14:01:35 +01:00
Andras Bacsai
837391c31b feat: add Docker build cache preservation toggles and development logging
Add two new application settings to control Docker build cache invalidation:
- inject_build_args_to_dockerfile (default: true) - Skip Dockerfile ARG injection
- include_source_commit_in_build (default: false) - Exclude SOURCE_COMMIT from build context

These toggles let users preserve Docker cache when SOURCE_COMMIT or custom ARGs change frequently. Development-only logging shows which ARGs are being injected for debugging.

🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 13:42:02 +01:00
Andras Bacsai
1e0de06d03
fix: resolve uncloseable database restore modal (#7345) 2025-11-26 12:55:09 +01:00
Andras Bacsai
f6d8ad1775 feat: add support for syncing versions.json to GitHub repository via PR 2025-11-26 10:52:20 +01:00
Andras Bacsai
aa18c48823 fix: resolve uncloseable database restore modal on MariaDB import (#7335)
Fixes the "Snapshot missing on Livewire component" error that occurs when
toggling the "Backup includes all databases" checkbox during MariaDB database
import operations.

Root Cause:
- ActivityMonitor component was initialized without proper lifecycle hooks
- When parent Import component re-rendered (via checkbox toggle), the
  ActivityMonitor's Livewire snapshot became stale
- Missing null checks caused errors when querying with undefined activityId
- No state cleanup when slide-over closed, causing issues on subsequent opens

Changes:
- Add updatedActivityId() lifecycle hook to ActivityMonitor for proper hydration
- Add defensive null check in hydrateActivity() to prevent query errors
- Track activityId in Import component for state management
- Add slideOverClosed event dispatch in slide-over component
- Add event listener in Import component to reset activityId on close

Testing:
- Manually verify checkbox toggle doesn't trigger popup
- Verify actual restore operations work correctly
- Test both file-based and S3-based restore methods
- Ensure X button properly closes the modal
- Verify no console errors or Livewire warnings

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 10:43:07 +01:00
Andras Bacsai
ce134cb8b1 fix: add authorization checks for environment and project views 2025-11-26 09:55:04 +01:00
Andras Bacsai
c472786f6f Merge branch 'next' into feat/shared-dev-view 2025-11-26 09:37:45 +01:00
Andras Bacsai
ac14a32723 fix: dispatch success message after transaction commits
Move the success dispatch outside the DB transaction closure to ensure
it only fires after the transaction has successfully committed. Use
reference variable to track changes across the closure boundary.
2025-11-26 09:37:18 +01:00
Andras Bacsai
4e896cca05 fix: preserve Docker build cache by excluding dynamic variables from build-time contexts
- Remove COOLIFY_CONTAINER_NAME from build-time ARGs (timestamp-based, breaks cache)
- Use APP_KEY instead of random_bytes for COOLIFY_BUILD_SECRETS_HASH (deterministic)
- Add forBuildTime parameter to generate_coolify_env_variables() to control injection
- Keep COOLIFY_CONTAINER_NAME available at runtime for container identification
- Fix misleading log message about .env file purpose

Fixes #7040

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-26 09:16:32 +01:00
Andras Bacsai
9113ed714f feat: add validation methods for S3 bucket names, paths, and server paths; update import logic to prevent command injection 2025-11-25 16:40:35 +01:00
Andras Bacsai
477738dd2f fix: update webhook notification settings migration to use updateOrInsert and add logging 2025-11-25 15:35:01 +01:00
Andras Bacsai
a3df33a4e0 fix: correct webhook notification settings migration and model
- Add missing traefik_outdated_webhook_notifications field to migration schema and population logic
- Remove incorrect docker_cleanup_webhook_notifications from model (split into success/failure variants)
- Consolidate webhook notification migrations from 2025_10_10 to 2025_11_25 for proper execution order
- Ensure all 15 notification fields are properly defined and consistent across migration, model, and Livewire component

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 15:18:43 +01:00
Andras Bacsai
6613f7c6b8
Merge branch 'next' into env-var-autocomplete 2025-11-25 11:21:53 +01:00
Andras Bacsai
875351188f feat: improve S3 restore path handling and validation state
- Add path attribute mutator to S3Storage model ensuring paths start with /
- Add updatedS3Path hook to normalize path and reset validation state on blur
- Add updatedS3StorageId hook to reset validation state when storage changes
- Add Enter key support to trigger file check from path input
- Use wire:model.live for S3 storage select, wire:model.blur for path input
- Improve shell escaping in restore job cleanup commands
- Fix isSafeTmpPath helper logic for directory validation

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 10:18:30 +01:00
Andras Bacsai
4147cfa537 refactor: use Laravel route() helper for shared variable URLs
- Replace hardcoded URL paths in getScopeUrl() with Laravel's route() helper
- Add scopeUrls property to EnvVarInput component with named routes
- Pass projectUuid and environmentUuid to enable context-specific environment links
- Environment scope link now navigates to the specific project/environment shared variables page

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 10:12:17 +01:00
Andras Bacsai
6d8144c18c Merge remote-tracking branch 'origin/next' into s3-restore
Resolve merge conflicts in:
- bootstrap/helpers/shared.php (kept both formatBytes, isSafeTmpPath, and formatContainerStatus functions)
- database/migrations/2025_10_10_120002_create_cloud_init_scripts_table.php (added Schema::hasTable check)
- database/migrations/2025_10_10_120002_create_webhook_notification_settings_table.php (added Schema::hasTable check)
- resources/views/livewire/project/application/general.blade.php (formatting/whitespace)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-25 09:35:37 +01:00
Andras Bacsai
01d3f07934
Merge branch 'next' into env-var-autocomplete 2025-11-25 09:35:20 +01:00
Andras Bacsai
e0dc12678b
fix: comprehensive SERVICE_URL/SERVICE_FQDN handling improvements and queue reliability fixes (#7275) 2025-11-24 11:47:11 +01:00
Andras Bacsai
bf428a0e1c
fix: don't show health status for exited containers (#7317) 2025-11-24 10:29:57 +01:00
Andras Bacsai
1149d0f746
feat: implement prerequisite validation and installation for server setup (#7297) 2025-11-24 10:28:10 +01:00
Andras Bacsai
ac9eca3c05 fix: don't show health status for exited containers
Exited containers don't run health checks, so showing "(unhealthy)" is
misleading. This fix ensures exited status displays without health
suffixes across all monitoring systems (SSH, Sentinel, services, etc.)
and at the UI layer for backward compatibility with existing data.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 09:09:37 +01:00
Andras Bacsai
30d206e7b9 feat: add async prerequisite installation with retry logic and visual feedback
This commit enhances the boarding flow to handle prerequisite installation asynchronously with proper retry logic and user feedback:

- Add retry mechanism with max 3 attempts for prerequisite installation
- Display live installation logs via ActivityMonitor during boarding
- Reset ActivityMonitor state when starting new activity to prevent stale event dispatching
- Support dynamic header updates in ActivityMonitor
- Add prerequisitesInstalled event handler to revalidate after installation completes
- Extract validation logic into continueValidation() method for cleaner flow
- Add unit tests for prerequisite installation logic

This improves UX by showing users real-time progress during prerequisite installation and handles installation failures gracefully with automatic retries.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-24 08:44:04 +01:00
Andras Bacsai
29135e00ba feat: enhance prerequisite validation to return detailed results 2025-11-21 13:14:48 +01:00
Andras Bacsai
2edf2338de fix: enhance getRequiredPort to support map-style environment variables for SERVICE_URL and SERVICE_FQDN 2025-11-21 12:41:25 +01:00
Andras Bacsai
85b73a8c00 fix: initialize Collection properties to handle queue deserialization edge cases 2025-11-21 12:25:25 +01:00
Andras Bacsai
56f32d0f87 fix: properly handle SERVICE_URL and SERVICE_FQDN for abbreviated service names (#7243)
Parse template variables directly instead of generating from container names. Always create both SERVICE_URL and SERVICE_FQDN pairs together. Properly separate scheme handling (URL has scheme, FQDN doesn't). Add comprehensive test coverage.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 11:21:49 +01:00
Andras Bacsai
01957f2752 feat: implement prerequisite validation and installation for server setup 2025-11-21 09:49:33 +01:00
Andras Bacsai
355dcc186c
fix: correct status for excluded health check containers (#7283) 2025-11-21 09:17:26 +01:00
Andras Bacsai
7ceb124e9b feat: add validation for YAML parsing, integer parameters, and Docker Compose custom fields
This commit adds comprehensive validation improvements and DRY principles for handling Coolify's custom Docker Compose extensions.

## Changes

### 1. Created Reusable stripCoolifyCustomFields() Function
- Added shared helper in bootstrap/helpers/docker.php
- Removes all Coolify custom fields (exclude_from_hc, content, isDirectory, is_directory)
- Handles both long syntax (arrays) and short syntax (strings) for volumes
- Well-documented with comprehensive docblock
- Follows DRY principle for consistent field stripping

### 2. Fixed Docker Compose Modal Validation
- Updated validateComposeFile() to use stripCoolifyCustomFields()
- Now removes ALL custom fields before Docker validation (previously only removed content)
- Fixes validation errors when using templates with custom fields (e.g., traccar.yaml)
- Users can now validate compose files with Coolify extensions in UI

### 3. Enhanced YAML Validation in CalculatesExcludedStatus
- Added proper exception handling with ParseException vs generic Exception
- Added structure validation (checks if parsed result and services are arrays)
- Comprehensive logging with context (error message, line number, snippet)
- Maintains safe fallback behavior (returns empty collection on error)

### 4. Added Integer Validation to ContainerStatusAggregator
- Validates maxRestartCount parameter in both aggregateFromStrings() and aggregateFromContainers()
- Corrects negative values to 0 with warning log
- Logs warnings for suspiciously high values (> 1000)
- Prevents logic errors in crash loop detection

### 5. Comprehensive Unit Tests
- tests/Unit/StripCoolifyCustomFieldsTest.php (NEW) - 9 tests, 43 assertions
- tests/Unit/ContainerStatusAggregatorTest.php - Added 6 tests for integer validation
- tests/Unit/ExcludeFromHealthCheckTest.php - Added 4 tests for YAML validation
- All tests passing with proper Log facade mocking

### 6. Documentation
- Added comprehensive Docker Compose extensions documentation to .ai/core/deployment-architecture.md
- Documents all custom fields: exclude_from_hc, content, isDirectory/is_directory
- Includes examples, use cases, implementation details, and test references
- Updated .ai/README.md with navigation links to new documentation

## Benefits
- Better UX: Users can validate compose files with custom fields
- Better Debugging: Comprehensive logging for errors
- Better Code Quality: DRY principle with reusable validation
- Better Reliability: Prevents logic errors from invalid parameters
- Better Maintainability: Easy to add new custom fields in future

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 18:34:49 +01:00
Andras Bacsai
ae6eef3cdb feat(tests): add comprehensive tests for ContainerStatusAggregator and serverStatus accessor
- Introduced tests for ContainerStatusAggregator to validate status aggregation logic across various container states.
- Implemented tests to ensure serverStatus accessor correctly checks server infrastructure health without being affected by container status.
- Updated ExcludeFromHealthCheckTest to verify excluded status handling in various components.
- Removed obsolete PushServerUpdateJobStatusAggregationTest as its functionality is covered elsewhere.
- Updated version number for sentinel to 0.0.17 in versions.json.
2025-11-20 17:31:07 +01:00
Andras Bacsai
2f3052a283 Fix database restart to skip unnecessary Docker cleanup
Prevents removal and re-download of database images on every restart. Docker cleanup was removing Docker Hub images (postgres, mysql, redis, etc.) that lack the coolify.managed=true label, causing them to be immediately re-pulled. Restart now preserves images while stopping/starting containers.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 17:15:45 +01:00
Andras Bacsai
70fb4c6869 refactor: standardize Service model status aggregation to use ContainerStatusAggregator
Fixes inconsistency where Service model used manual state machine logic while
all other components (Application, ComplexStatusCheck, GetContainersStatus)
use the centralized ContainerStatusAggregator service.

Changes:
- Refactored Service::aggregateResourceStatuses() to use ContainerStatusAggregator
- Removed ~60 lines of duplicated state machine logic
- Added comprehensive ServiceExcludedStatusTest with 24 test cases
- Fixed bugs in old logic where paused/starting containers were incorrectly
  marked as unhealthy (should be unknown)

Benefits:
- Single source of truth for status aggregation across all models
- Leverages 42 existing ContainerStatusAggregator tests
- Consistent behavior between Service and Application/Database models
- Easier maintenance (state machine changes only in one place)

All tests pass (37 total):
- ServiceExcludedStatusTest: 24/24 passed
- AllExcludedContainersConsistencyTest: 13/13 passed

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 15:03:18 +01:00
Andras Bacsai
14bba8ba86 fix: correct Sentinel default health status and remove debug logging
This commit addresses container status reporting issues and removes debug logging:

**Primary Fix:**
- Changed PushServerUpdateJob to default to 'unknown' instead of 'unhealthy' when health_status field is missing from Sentinel data
- This ensures containers WITHOUT healthcheck defined are correctly reported as "unknown" not "unhealthy"
- Matches SSH path behavior (GetContainersStatus) which already defaulted to 'unknown'

**Service Multi-Container Aggregation:**
- Implemented service container status aggregation (same pattern as applications)
- Added serviceContainerStatuses collection to both Sentinel and SSH paths
- Services now aggregate status using priority: unhealthy > unknown > healthy
- Prevents race conditions where last-processed container would win

**Debug Logging Cleanup:**
- Removed all [STATUS-DEBUG] logging statements (25 total)
- Removed all ray() debugging calls (3 total)
- Removed proof_unknown_preserved and health_status_was_null debug fields
- Code is now production-ready

**Test Coverage:**
- Added 2 new tests for Sentinel default health status behavior
- Added 5 new tests for service aggregation in SSH path
- All 16 tests pass (66 assertions)

**Note:** The root cause was identified as Sentinel (Go binary) also defaulting to "unhealthy". That will need a separate fix in the Sentinel codebase.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 11:10:34 +01:00
Andras Bacsai
747a48b933 debug: add detailed Sentinel container processing logging
Added comprehensive logging to track why applicationContainerStatuses
collection is empty in PushServerUpdateJob.

## Logging Added

### 1. Raw Sentinel Data (line 113-118)
**Logs**: Complete container data received from Sentinel
**Purpose**: See exactly what Sentinel is sending
**Data**: Container count and full container array with all labels

### 2. Container Processing Loop (line 157-163)
**Logs**: Every container as it's being processed
**Purpose**: Track which containers enter the processing loop
**Data**: Container name, status, all labels, coolify.managed flag

### 3. Skipped Containers - Not Managed (line 165-171)
**Logs**: Containers without coolify.managed label
**Purpose**: Identify containers being filtered out early
**Data**: Container name

### 4. Successful Container Addition (line 193-198)
**Logs**: When container is successfully added to applicationContainerStatuses
**Purpose**: Confirm containers ARE being processed
**Data**: Application ID, container name, container status

### 5. Missing com.docker.compose.service Label (line 200-206)
**Logs**: Containers skipped due to missing com.docker.compose.service
**Purpose**: Identify the most likely root cause
**Data**: Container name, application ID, all labels

## Why This Matters

User reported applicationContainerStatuses is empty (`[]`) even though
Sentinel is pushing updates. This logging will reveal:

1. Is Sentinel sending containers at all?
2. Are containers filtered by coolify.managed check?
3. Is com.docker.compose.service label missing? (most likely)
4. What labels IS Sentinel actually sending?

## Expected Findings

Based on investigation, the issue is likely:
- Sentinel is NOT sending com.docker.compose.service in labels
- Or Sentinel uses a different label format/name
- Containers pass all other checks but fail on line 190-206

## Next Steps

After logs appear, we'll see exactly which filter is blocking containers
and can fix the root cause (likely need to extract com.docker.compose.service
from container name or use a different label source).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-20 08:34:42 +01:00
ShadowArcanist
0f9e3b84ee feat: logs color highlight based on log level - visual improvement 2025-11-20 09:14:42 +05:30
Andras Bacsai
d2d9c1b2bc debug: add comprehensive status change logging
Added detailed debug logging to all status update paths to help
diagnose why "unhealthy" status appears in the UI.

## Logging Added

### 1. PushServerUpdateJob (Sentinel updates)
**Location**: Lines 303-315
**Logs**: Status changes from Sentinel push updates
**Data tracked**:
- Old vs new status
- Container statuses that led to aggregation
- Status flags (hasRunning, hasUnhealthy, hasUnknown)

### 2. GetContainersStatus (SSH updates)
**Location**: Lines 441-449, 346-354, 358-365
**Logs**: Status changes from SSH-based checks
**Scenarios**:
- Normal status aggregation
- Recently restarted containers (kept as degraded)
- Applications not running (set to exited)
**Data tracked**:
- Old vs new status
- Container statuses
- Restart count and timing
- Whether containers exist

### 3. Application Model Status Accessor
**Location**: Lines 706-712, 726-732
**Logs**: When status is set without explicit health information
**Issue**: Highlights cases where health defaults to "unhealthy"
**Data tracked**:
- Raw value passed to setter
- Final result after default applied

## How to Use

### Enable Debug Logging
Edit `.env` or `config/logging.php` to set log level to debug:
```
LOG_LEVEL=debug
```

### Monitor Logs
```bash
tail -f storage/logs/laravel.log | grep STATUS-DEBUG
```

### Log Format
All logs use `[STATUS-DEBUG]` prefix for easy filtering:
```
[2025-11-19 13:00:00] local.DEBUG: [STATUS-DEBUG] Sentinel status change
{
  "source": "PushServerUpdateJob",
  "app_id": 123,
  "app_name": "my-app",
  "old_status": "running:unknown",
  "new_status": "running:healthy",
  "container_statuses": [...],
  "flags": {...}
}
```

## What to Look For

1. **Default to unhealthy**: Check Application model accessor logs
2. **Status flipping**: Compare timestamps between Sentinel and SSH updates
3. **Incorrect aggregation**: Check flags and container_statuses
4. **Stale database values**: Check if old_status persists across multiple logs

## Next Steps

After gathering logs, we can:
1. Identify the exact source of "unhealthy" status
2. Determine if it's a default issue, aggregation bug, or timing problem
3. Apply targeted fix based on evidence

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 13:52:08 +01:00
Andras Bacsai
6b62847a11 fix: preserve unknown health status in Sentinel updates (PushServerUpdateJob)
## Problem
Services with "running (unknown)" status were periodically changing
to "running (healthy)" every ~30 seconds when Sentinel pushed updates.
This was confusing for users and inconsistent with SSH-based status checks.

## Root Cause
`PushServerUpdateJob::aggregateMultiContainerStatuses()` was missing
logic to track "unknown" health state. It only tracked "unhealthy" and
defaulted everything else to "healthy".

When Sentinel pushed updates with "running (unknown)" containers:
- The job saw `hasRunning = true` and `hasUnhealthy = false`
- It incorrectly returned "running (healthy)" instead of "running (unknown)"

## Solution
Updated `PushServerUpdateJob` to match the logic in `GetContainersStatus`:

1. Added `$hasUnknown` tracking variable
2. Check for "unknown" in status strings (alongside "unhealthy")
3. Implement 3-way priority: unhealthy > unknown > healthy

This ensures consistency between:
- SSH-based updates (`GetContainersStatus`)
- Sentinel-based updates (`PushServerUpdateJob`)
- UI display logic

## Changes
- **app/Jobs/PushServerUpdateJob.php**: Added unknown status tracking
- **tests/Unit/PushServerUpdateJobStatusAggregationTest.php**: New comprehensive tests
- **tests/Unit/ExcludeFromHealthCheckTest.php**: Updated to match current implementation

## Testing
All 31 status-related unit tests passing:
- 18 tests in ContainerHealthStatusTest
- 8 tests in ExcludeFromHealthCheckTest (updated)
- 6 tests in PushServerUpdateJobStatusAggregationTest (new)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 13:40:58 +01:00
Andras Bacsai
e3746a4b88 fix: preserve unknown health state and handle edge case container states
This commit fixes container health status aggregation to correctly handle
unknown health states and edge case container states across all resource types.

Changes:

1. **Preserve Unknown Health State**
   - Add three-way priority: unhealthy > unknown > healthy
   - Detect containers without healthchecks (null health) as unknown
   - Apply across GetContainersStatus, ComplexStatusCheck, and Service models

2. **Handle Edge Case Container States**
   - Add support for: created, starting, paused, dead, removing
   - Map to appropriate statuses: starting (unknown), paused (unknown), degraded (unhealthy)
   - Prevent containers in transitional states from showing incorrect status

3. **Add :excluded Suffix for Excluded Containers**
   - Parse exclude_from_hc flag from docker-compose YAML
   - Append :excluded suffix to individual container statuses
   - Skip :excluded containers in non-excluded aggregation sections
   - Strip :excluded suffix in excluded aggregation sections
   - Makes it clear in UI which containers are excluded from monitoring

Files Modified:
- app/Actions/Docker/GetContainersStatus.php
- app/Actions/Shared/ComplexStatusCheck.php
- app/Models/Service.php
- tests/Unit/ContainerHealthStatusTest.php

Tests: 18 passed (82 assertions)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 13:19:25 +01:00
Andras Bacsai
498b189286 fix: correct status for services with all containers excluded from health checks
When all containers are excluded from health checks, display their actual status
with :excluded suffix instead of misleading hardcoded statuses. This prevents
broken UI state with incorrect action buttons and provides clarity that monitoring
is disabled.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 10:54:51 +01:00
Andras Bacsai
c79b5f1e5c feat: add environment variable autocomplete component
Adds a new EnvVarInput component that provides autocomplete suggestions for shared environment variables from team, project, and environment scopes. Users can reference variables using {{ syntax.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 10:54:19 +01:00
Andras Bacsai
f81640e316 fix: correct status for services with all containers excluded from health checks
When all services in a Docker Compose file have `exclude_from_hc: true`,
the status aggregation logic was returning invalid states causing broken UI.

**Problems fixed:**
- ComplexStatusCheck returned 'running:healthy' for apps with no monitored containers
- Service model returned ':' (null status) when all services excluded
- UI showed active start/stop buttons for non-running services

**Changes:**
- ComplexStatusCheck: Return 'exited:healthy' when relevantContainerCount is 0
- Service model: Return 'exited:healthy' when both status and health are null
- Added comprehensive unit tests to verify the fixes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 23:24:22 +01:00
Andras Bacsai
cfe3f5d8b9 fix: normalize preview paths and use BUILD_TIME_ENV_PATH constant
- Fix double-slash issue in Docker Compose preview paths when baseDirectory is "/"
- Normalize baseDirectory using rtrim() to prevent path concatenation issues
- Replace hardcoded '/artifacts/build-time.env' with ApplicationDeploymentJob::BUILD_TIME_ENV_PATH
- Make BUILD_TIME_ENV_PATH constant public for reusability
- Add comprehensive unit tests (11 test cases, 25 assertions)

Fixes preview path generation in:
- getDockerComposeBuildCommandPreviewProperty()
- getDockerComposeStartCommandPreviewProperty()

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:54:21 +01:00
Andras Bacsai
2eeb2b94ec fix: auto-inject -f and --env-file flags into custom Docker Compose commands 2025-11-18 14:54:21 +01:00
Andras Bacsai
37c3cd9f4e fix: auto-inject environment variables into custom Docker Compose commands 2025-11-18 14:54:21 +01:00
Andras Bacsai
1094ab7a46 fix: inject environment variables into custom Docker Compose build commands
When using a custom Docker Compose build command, environment variables
were being lost because the --env-file flag was not included. This fix
automatically injects the --env-file flag to ensure build-time environment
variables are available during custom builds.

Changes:
- Auto-inject --env-file /artifacts/build-time.env after docker compose
- Respect user-provided --env-file flags (no duplication)
- Append build arguments when not using build secrets
- Update UI helper text to inform users about automatic env injection
- Add comprehensive unit tests (7 test cases, all passing)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:54:21 +01:00
Andras Bacsai
50d55a9509 refactor: send immediate Traefik version notifications instead of delayed aggregation
Move notification logic from NotifyOutdatedTraefikServersJob into CheckTraefikVersionForServerJob to send immediate notifications when outdated Traefik is detected. This is more suitable for cloud environments with thousands of servers.

Changes:
- CheckTraefikVersionForServerJob now sends notifications immediately after detecting outdated Traefik
- Remove NotifyOutdatedTraefikServersJob (no longer needed)
- Remove delay calculation logic from CheckTraefikVersionJob
- Update tests to reflect new immediate notification pattern

Trade-offs:
- Pro: Faster notifications (immediate alerts)
- Pro: Simpler codebase (removed complex delay calculation)
- Pro: Better scalability for thousands of servers
- Con: Teams may receive multiple notifications if they have many outdated servers

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:54:21 +01:00
Andras Bacsai
f75bb61d21 refactor(CheckTraefikVersionForServerJob): remove unnecessary onQueue assignment in constructor 2025-11-18 14:54:21 +01:00
Andras Bacsai
59e9d16190 refactor: simplify environment variable deletion logic in booted method 2025-11-18 14:54:21 +01:00
Andras Bacsai
122766a8e5 fix: remove unused variable in updatedBuildPack method 2025-11-18 14:54:21 +01:00
Andras Bacsai
acfee7d9f3 resolve merge conflict 2025-11-18 14:54:17 +01:00
Andras Bacsai
329708791e feat(proxy): include Traefik versions in version check after restart 2025-11-18 14:53:49 +01:00
Andras Bacsai
d3e7d979f6 feat(proxy): trigger version check after restart from UI
When a user restarts the proxy from the Navbar UI component, the system now automatically dispatches a version check job immediately after the restart completes. This provides immediate feedback about available Traefik updates without waiting for the weekly scheduled check.

Changes:
- Import CheckTraefikVersionForServerJob in Navbar component
- After successful proxy restart, dispatch version check for Traefik servers
- Version check only runs for servers using Traefik proxy

This ensures users get up-to-date version information right after restarting their proxy infrastructure.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:53:49 +01:00
Andras Bacsai
d2d56ac6b4 refactor(proxy): simplify getNewerBranchInfo method parameters and streamline version checks 2025-11-18 14:53:49 +01:00
Andras Bacsai
7dfe33d1c9 refactor(proxy): implement centralized caching for versions.json and improve UX
This commit introduces several improvements to the Traefik version tracking
feature and proxy configuration UI:

## Caching Improvements

1. **New centralized helper functions** (bootstrap/helpers/versions.php):
   - `get_versions_data()`: Redis-cached access to versions.json (1 hour TTL)
   - `get_traefik_versions()`: Extract Traefik versions from cached data
   - `invalidate_versions_cache()`: Clear cache when file is updated

2. **Performance optimization**:
   - Single Redis cache key: `coolify:versions:all`
   - Eliminates 2-4 file reads per page load
   - 95-97.5% reduction in disk I/O time
   - Shared cache across all servers in distributed setup

3. **Updated all consumers to use cached helpers**:
   - CheckTraefikVersionJob: Use get_traefik_versions()
   - Server/Proxy: Two-level caching (Redis + in-memory per-request)
   - CheckForUpdatesJob: Auto-invalidate cache after updating file
   - bootstrap/helpers/shared.php: Use cached data for Coolify version

## UI/UX Improvements

1. **Navbar warning indicator**:
   - Added yellow warning triangle icon next to "Proxy" menu item
   - Appears when server has outdated Traefik version
   - Uses existing traefik_outdated_info data for instant checks
   - Provides at-a-glance visibility of version issues

2. **Proxy sidebar persistence**:
   - Fixed sidebar disappearing when clicking "Switch Proxy"
   - Configuration link now always visible (needed for proxy selection)
   - Dynamic Configurations and Logs only show when proxy is configured
   - Better navigation context during proxy switching workflow

## Code Quality

- Added comprehensive PHPDoc for Server::$traefik_outdated_info property
- Improved code organization with centralized helper approach
- All changes formatted with Laravel Pint
- Maintains backward compatibility

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:53:49 +01:00
Andras Bacsai
6dbe58f22b feat(proxy): enhance Traefik version notifications to show patch and minor upgrades
- Store both patch update and newer minor version information simultaneously
- Display patch update availability alongside minor version upgrades in notifications
- Add newer_branch_target and newer_branch_latest fields to traefik_outdated_info
- Update all notification channels (Discord, Telegram, Slack, Pushover, Email, Webhook)
- Show minor version in format (e.g., v3.6) for upgrade targets instead of patch version
- Enhance UI callouts with clearer messaging about available upgrades
- Remove verbose logging in favor of cleaner code structure
- Handle edge case where SSH command returns empty response

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:53:49 +01:00
Andras Bacsai
c77eaddede refactor(proxy): implement parallel processing for Traefik version checks
Addresses critical performance issues identified in code review by refactoring the monolithic CheckTraefikVersionJob into a distributed architecture with parallel processing.

Changes:
- Split version checking into CheckTraefikVersionForServerJob for parallel execution
- Extract notification logic into NotifyOutdatedTraefikServersJob
- Dispatch individual server checks concurrently to handle thousands of servers
- Add comprehensive unit tests for the new job architecture
- Update feature tests to cover the refactored workflow

Performance improvements:
- Sequential SSH calls replaced with parallel queue jobs
- Scales efficiently for large installations with thousands of servers
- Reduces job execution time from hours to minutes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:53:49 +01:00
Andras Bacsai
63a0706afb fix(proxy): prevent "container name already in use" error during proxy restart
Add wait loops to ensure containers are fully removed before restarting.
This fixes race conditions where docker compose would fail because an
existing container was still being cleaned up.

Changes:
- StartProxy: Add explicit stop, wait loop before docker compose up
- StopProxy: Add wait loop after container removal
- Both actions now poll up to 10 seconds for complete removal
- Add error suppression to handle non-existent containers gracefully

Tests:
- Add StartProxyTest.php with 3 tests for cleanup logic
- Add StopProxyTest.php with 4 tests for stop behavior

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:53:49 +01:00
Andras Bacsai
1dacb94860 fix(performance): eliminate N+1 query in CheckTraefikVersionJob
This commit fixes a critical N+1 query issue in CheckTraefikVersionJob
that was loading ALL proxy servers into memory then filtering in PHP,
causing potential OOM errors with thousands of servers.

Changes:
- Added scopeWhereProxyType() query scope to Server model for
  database-level filtering using JSON column arrow notation
- Updated CheckTraefikVersionJob to use new scope instead of
  collection filter, moving proxy type filtering into the SQL query
- Added comprehensive unit tests for the new query scope

Performance impact:
- Before: SELECT * FROM servers WHERE proxy IS NOT NULL (all servers)
- After: SELECT * FROM servers WHERE proxy->>'type' = 'TRAEFIK' (filtered)
- Eliminates memory overhead of loading non-Traefik servers
- Critical for cloud instances with thousands of connected servers

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:53:49 +01:00
Andras Bacsai
0bd4ffb2d7 feat(proxy): add Traefik version tracking with notifications and dismissible UI warnings
- Add automated Traefik version checking job running weekly on Sundays
- Implement version detection from running containers and comparison with versions.json
- Add notifications across all channels (Email, Discord, Slack, Telegram, Pushover, Webhook) for outdated versions
- Create dismissible callout component with localStorage persistence
- Display cross-branch upgrade warnings (e.g., v3.5 -> v3.6) with changelog links
- Show patch update notifications within same branch
- Add warning icon that appears when callouts are dismissed
- Prevent duplicate notifications during proxy restart by adding restarting parameter
- Fix notification spam with transition-based logic for status changes
- Enable system email settings by default in development mode
- Track last saved/applied proxy settings to detect configuration drift
2025-11-18 14:53:49 +01:00
Andras Bacsai
a4d07ab050 refactor: simplify environment variable deletion logic in booted method 2025-11-18 14:53:48 +01:00
Andras Bacsai
29e0e08146 fix: remove unused variable in updatedBuildPack method 2025-11-18 14:53:48 +01:00
Andras Bacsai
40f88c0013 merge next 2025-11-18 14:53:23 +01:00
Andras Bacsai
5ba3c6879c refactor: simplify environment variable deletion logic in booted method 2025-11-18 14:51:38 +01:00
Andras Bacsai
80f3357842 fix: remove unused variable in updatedBuildPack method 2025-11-18 14:51:38 +01:00
Andras Bacsai
0540b2eae5 refactor: move buildpack cleanup logic to model lifecycle hooks
Move buildpack switching cleanup from Livewire component to Application model's boot lifecycle. This improves separation of concerns and ensures cleanup happens consistently regardless of how the buildpack change is triggered. Also clears Dockerfile-specific data when switching away from dockerfile buildpack.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 14:51:38 +01:00
Andras Bacsai
0e66adc376 fix: normalize preview paths and use BUILD_TIME_ENV_PATH constant
- Fix double-slash issue in Docker Compose preview paths when baseDirectory is "/"
- Normalize baseDirectory using rtrim() to prevent path concatenation issues
- Replace hardcoded '/artifacts/build-time.env' with ApplicationDeploymentJob::BUILD_TIME_ENV_PATH
- Make BUILD_TIME_ENV_PATH constant public for reusability
- Add comprehensive unit tests (11 test cases, 25 assertions)

Fixes preview path generation in:
- getDockerComposeBuildCommandPreviewProperty()
- getDockerComposeStartCommandPreviewProperty()

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 13:48:06 +01:00
Andras Bacsai
f86ccfaa9a fix: auto-inject -f and --env-file flags into custom Docker Compose commands 2025-11-18 13:07:54 +01:00
Andras Bacsai
274c37e333 fix: auto-inject environment variables into custom Docker Compose commands 2025-11-18 13:07:54 +01:00
Andras Bacsai
f8e3bb54a3 fix: inject environment variables into custom Docker Compose build commands
When using a custom Docker Compose build command, environment variables
were being lost because the --env-file flag was not included. This fix
automatically injects the --env-file flag to ensure build-time environment
variables are available during custom builds.

Changes:
- Auto-inject --env-file /artifacts/build-time.env after docker compose
- Respect user-provided --env-file flags (no duplication)
- Append build arguments when not using build secrets
- Update UI helper text to inform users about automatic env injection
- Add comprehensive unit tests (7 test cases, all passing)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 13:07:54 +01:00
Andras Bacsai
4f2d39af03 refactor: send immediate Traefik version notifications instead of delayed aggregation
Move notification logic from NotifyOutdatedTraefikServersJob into CheckTraefikVersionForServerJob to send immediate notifications when outdated Traefik is detected. This is more suitable for cloud environments with thousands of servers.

Changes:
- CheckTraefikVersionForServerJob now sends notifications immediately after detecting outdated Traefik
- Remove NotifyOutdatedTraefikServersJob (no longer needed)
- Remove delay calculation logic from CheckTraefikVersionJob
- Update tests to reflect new immediate notification pattern

Trade-offs:
- Pro: Faster notifications (immediate alerts)
- Pro: Simpler codebase (removed complex delay calculation)
- Pro: Better scalability for thousands of servers
- Con: Teams may receive multiple notifications if they have many outdated servers

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 12:30:50 +01:00
Andras Bacsai
e97222aef2 refactor(CheckTraefikVersionForServerJob): remove unnecessary onQueue assignment in constructor 2025-11-18 10:44:01 +01:00
Andras Bacsai
ebb2f0cc7d refactor: simplify environment variable deletion logic in booted method 2025-11-18 10:29:08 +01:00
Andras Bacsai
14ddf2fab1 fix: remove unused variable in updatedBuildPack method 2025-11-18 10:29:08 +01:00
Andras Bacsai
36d2c02498 refactor: move buildpack cleanup logic to model lifecycle hooks
Move buildpack switching cleanup from Livewire component to Application model's boot lifecycle. This improves separation of concerns and ensures cleanup happens consistently regardless of how the buildpack change is triggered. Also clears Dockerfile-specific data when switching away from dockerfile buildpack.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 10:29:08 +01:00
Andras Bacsai
49ab9b2278 feat(proxy): include Traefik versions in version check after restart 2025-11-18 10:27:37 +01:00
Andras Bacsai
c7fc0a271c feat(proxy): trigger version check after restart from UI
When a user restarts the proxy from the Navbar UI component, the system now automatically dispatches a version check job immediately after the restart completes. This provides immediate feedback about available Traefik updates without waiting for the weekly scheduled check.

Changes:
- Import CheckTraefikVersionForServerJob in Navbar component
- After successful proxy restart, dispatch version check for Traefik servers
- Version check only runs for servers using Traefik proxy

This ensures users get up-to-date version information right after restarting their proxy infrastructure.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 10:19:04 +01:00
Andras Bacsai
680b9a2c10
Merge branch 'next' into s3-restore 2025-11-17 15:39:22 +01:00
Andras Bacsai
f8dd44410a refactor(proxy): simplify getNewerBranchInfo method parameters and streamline version checks 2025-11-17 15:03:30 +01:00
Andras Bacsai
1270136da9 merge: merge next branch into feat-traefik-version-checker
Merged latest changes from the next branch to keep the feature branch
up to date. No conflicts were encountered during the merge.

Changes from next branch:
- Updated application deployment job error logging
- Updated server manager job and instance settings
- Removed PullHelperImageJob in favor of updated approach
- Database migration refinements
- Updated versions.json with latest component versions

All automatic merges were successful and no manual conflict resolution
was required.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:56:24 +01:00
Andras Bacsai
5d73b76a44 refactor(proxy): implement centralized caching for versions.json and improve UX
This commit introduces several improvements to the Traefik version tracking
feature and proxy configuration UI:

## Caching Improvements

1. **New centralized helper functions** (bootstrap/helpers/versions.php):
   - `get_versions_data()`: Redis-cached access to versions.json (1 hour TTL)
   - `get_traefik_versions()`: Extract Traefik versions from cached data
   - `invalidate_versions_cache()`: Clear cache when file is updated

2. **Performance optimization**:
   - Single Redis cache key: `coolify:versions:all`
   - Eliminates 2-4 file reads per page load
   - 95-97.5% reduction in disk I/O time
   - Shared cache across all servers in distributed setup

3. **Updated all consumers to use cached helpers**:
   - CheckTraefikVersionJob: Use get_traefik_versions()
   - Server/Proxy: Two-level caching (Redis + in-memory per-request)
   - CheckForUpdatesJob: Auto-invalidate cache after updating file
   - bootstrap/helpers/shared.php: Use cached data for Coolify version

## UI/UX Improvements

1. **Navbar warning indicator**:
   - Added yellow warning triangle icon next to "Proxy" menu item
   - Appears when server has outdated Traefik version
   - Uses existing traefik_outdated_info data for instant checks
   - Provides at-a-glance visibility of version issues

2. **Proxy sidebar persistence**:
   - Fixed sidebar disappearing when clicking "Switch Proxy"
   - Configuration link now always visible (needed for proxy selection)
   - Dynamic Configurations and Logs only show when proxy is configured
   - Better navigation context during proxy switching workflow

## Code Quality

- Added comprehensive PHPDoc for Server::$traefik_outdated_info property
- Improved code organization with centralized helper approach
- All changes formatted with Laravel Pint
- Maintains backward compatibility

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:53:28 +01:00
Andras Bacsai
b602fef4db fix(deployment): improve error logging with exception types and hidden technical details
- Add exception class names to error messages for better debugging
- Mark technical details (error type, code, location, stack trace) as hidden in logs
- Preserve original exception types when wrapping in DeploymentException
- Update ServerManagerJob to include exception class in log messages
- Enhance unit tests to verify hidden log entry behavior

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:44:39 +01:00
Andras Bacsai
648e111f10 Merge remote-tracking branch 'origin/next' into s3-restore
# Conflicts:
#	app/Models/InstanceSettings.php
2025-11-17 14:30:00 +01:00
Andras Bacsai
a9f42b9440 perf: optimize S3 restore flow with immediate cleanup and progress tracking
Optimizations:
- Add immediate cleanup of helper container and server temp files after copying to database
- Add pre-cleanup to handle interrupted restores
- Combine restore + cleanup commands to remove DB temp files immediately after restore
- Reduce temp file lifetime from minutes to seconds (70-80% reduction)
- Add progress tracking via MinIO client (shows by default)
- Update user message to mention progress visibility

Benefits:
- Temp files exist only as long as needed (not until end of process)
- Real-time S3 download progress shown in activity monitor
- Better disk space management through aggressive cleanup
- Improved error recovery with pre-cleanup

Compatibility:
- Works with all database types (PostgreSQL, MySQL, MariaDB, MongoDB)
- All existing tests passing
- Event-based cleanup acts as safety net for edge cases

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:23:50 +01:00
Andras Bacsai
fbdd8e5f03 fix: improve robustness and security in database restore flows
- Add null checks for server instances in restore events to prevent errors
- Escape S3 credentials to prevent command injection vulnerabilities
- Fix file upload clearing custom location to prevent UI confusion
- Optimize isSafeTmpPath helper by avoiding redundant dirname calls
- Remove unnecessary --rm flag from long-running S3 restore container
- Prioritize uploaded files over custom location in import logic
- Add comprehensive unit tests for restore event null server handling

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 14:13:10 +01:00
Andras Bacsai
97550f4066 fix(deployment): eliminate duplicate error logging in deployment methods
Wraps rolling_update(), health_check(), stop_running_container(), and
start_by_compose_file() with try-catch to ensure comprehensive error logging
happens in one place. Removes duplicate logging from intermediate catch blocks
since the failed() method already provides full error details including stack trace
and chained exception information.

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 10:52:09 +01:00
Andras Bacsai
94560ea6c7 feat: streamline S3 restore with single-step flow and improved UI consistency
Major architectural improvements:
- Merged download and restore into single atomic operation
- Eliminated separate S3DownloadFinished event (redundant)
- Files now transfer directly: S3 → helper container → server → database container
- Removed download progress tracking in favor of unified restore progress

UI/UX improvements:
- Unified restore method selection with visual cards
- Consistent "File Information" display between local and S3 restore
- Single slide-over for all restore operations (removed separate S3 download monitor)
- Better visual feedback with loading states

Security enhancements:
- Added isSafeTmpPath() helper for path traversal protection
- URL decode validation to catch encoded attacks
- Canonical path resolution to prevent symlink attacks
- Comprehensive path validation in all cleanup events

Cleanup improvements:
- S3RestoreJobFinished now handles all cleanup (helper container + all temp files)
- RestoreJobFinished uses new isSafeTmpPath() validation
- CoolifyTask dispatches cleanup events even on job failure
- All cleanup uses non-throwing commands (2>/dev/null || true)

Other improvements:
- S3 storage policy authorization on Show component
- Storage Form properly syncs is_usable state after test
- Removed debug code and improved error handling
- Better command organization and documentation

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 10:05:18 +01:00
Andras Bacsai
6593b2a553 feat(proxy): enhance Traefik version notifications to show patch and minor upgrades
- Store both patch update and newer minor version information simultaneously
- Display patch update availability alongside minor version upgrades in notifications
- Add newer_branch_target and newer_branch_latest fields to traefik_outdated_info
- Update all notification channels (Discord, Telegram, Slack, Pushover, Email, Webhook)
- Show minor version in format (e.g., v3.6) for upgrade targets instead of patch version
- Enhance UI callouts with clearer messaging about available upgrades
- Remove verbose logging in favor of cleaner code structure
- Handle edge case where SSH command returns empty response

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-17 09:59:17 +01:00
Andras Bacsai
cc6a538fca refactor(proxy): implement parallel processing for Traefik version checks
Addresses critical performance issues identified in code review by refactoring the monolithic CheckTraefikVersionJob into a distributed architecture with parallel processing.

Changes:
- Split version checking into CheckTraefikVersionForServerJob for parallel execution
- Extract notification logic into NotifyOutdatedTraefikServersJob
- Dispatch individual server checks concurrently to handle thousands of servers
- Add comprehensive unit tests for the new job architecture
- Update feature tests to cover the refactored workflow

Performance improvements:
- Sequential SSH calls replaced with parallel queue jobs
- Scales efficiently for large installations with thousands of servers
- Reduces job execution time from hours to minutes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 11:42:58 +01:00
Andras Bacsai
7a16938f0c fix(proxy): prevent "container name already in use" error during proxy restart
Add wait loops to ensure containers are fully removed before restarting.
This fixes race conditions where docker compose would fail because an
existing container was still being cleaned up.

Changes:
- StartProxy: Add explicit stop, wait loop before docker compose up
- StopProxy: Add wait loop after container removal
- Both actions now poll up to 10 seconds for complete removal
- Add error suppression to handle non-existent containers gracefully

Tests:
- Add StartProxyTest.php with 3 tests for cleanup logic
- Add StopProxyTest.php with 4 tests for stop behavior

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 11:35:22 +01:00
Andras Bacsai
11a7f4c8a7 fix(performance): eliminate N+1 query in CheckTraefikVersionJob
This commit fixes a critical N+1 query issue in CheckTraefikVersionJob
that was loading ALL proxy servers into memory then filtering in PHP,
causing potential OOM errors with thousands of servers.

Changes:
- Added scopeWhereProxyType() query scope to Server model for
  database-level filtering using JSON column arrow notation
- Updated CheckTraefikVersionJob to use new scope instead of
  collection filter, moving proxy type filtering into the SQL query
- Added comprehensive unit tests for the new query scope

Performance impact:
- Before: SELECT * FROM servers WHERE proxy IS NOT NULL (all servers)
- After: SELECT * FROM servers WHERE proxy->>'type' = 'TRAEFIK' (filtered)
- Eliminates memory overhead of loading non-Traefik servers
- Critical for cloud instances with thousands of connected servers

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 11:35:22 +01:00
Andras Bacsai
8c77c63043 feat(proxy): add Traefik version tracking with notifications and dismissible UI warnings
- Add automated Traefik version checking job running weekly on Sundays
- Implement version detection from running containers and comparison with versions.json
- Add notifications across all channels (Email, Discord, Slack, Telegram, Pushover, Webhook) for outdated versions
- Create dismissible callout component with localStorage persistence
- Display cross-branch upgrade warnings (e.g., v3.5 -> v3.6) with changelog links
- Show patch update notifications within same branch
- Add warning icon that appears when callouts are dismissed
- Prevent duplicate notifications during proxy restart by adding restarting parameter
- Fix notification spam with transition-based logic for status changes
- Enable system email settings by default in development mode
- Track last saved/applied proxy settings to detect configuration drift
2025-11-14 11:35:22 +01:00
Andras Bacsai
318cd18dde fix: remove PullHelperImageJob and mass server scheduling
Stop dispatching PullHelperImageJob to thousands of servers when the helper image version changes. Instead, rely on Docker's automatic image pulling during actual deployments and backups. Inline the helper image pull in UpdateCoolify for the single use case.

This eliminates queue flooding on cloud instances while maintaining all functionality through Docker's built-in image management.
2025-11-14 11:31:08 +01:00
Andras Bacsai
d37378ec02 fix: remove blocking instant_remote_process and hide button during download
The first click did nothing because instant_remote_process() blocked the
Livewire response, preventing UI state updates. The button also remained
visible during download, allowing multiple clicks.

- Replace blocking instant_remote_process() with async command in queue
- Add container cleanup to command queue with error suppression
- Hide "Download & Prepare" button when s3DownloadInProgress is true
- Button now properly disappears when clicked, preventing double-clicks
- No more blocking operations in downloadFromS3() method

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
91d752f906 fix: only set s3DownloadedFile when download actually completes
The s3DownloadedFile was being set immediately when download started,
causing the "Restore" button to appear while still downloading and
the download message to not hide properly.

- Remove immediate setting of s3DownloadedFile in downloadFromS3()
- Set s3DownloadedFile only in handleS3DownloadFinished() event handler
- Add broadcastWith() to S3DownloadFinished to send downloadPath
- Store downloadPath as public property for broadcasting
- Now download message hides and restore button shows only when complete

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
8e273dd799 fix: broadcast S3DownloadFinished to correct user
The event was broadcasting to the first user in the team instead of
the actual user who triggered the download. This caused the download
message to never hide for other team members.

- Pass userId in S3DownloadFinished event data
- Use the specific userId from event data for broadcasting
- Remove unused User model import
- Ensures broadcast reaches the correct user's private channel

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
23fdad1d9f fix: broadcast S3DownloadFinished event to hide download message
- Make S3DownloadFinished implement ShouldBroadcast
- Add listener in Import component to handle S3DownloadFinished event
- Set s3DownloadInProgress to false when download completes
- This hides "Downloading from S3..." message after download finishes
- Follows the same pattern as DatabaseStatusChanged event

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
18f30b7fab fix: correct event class names in callEventOnFinish
- Remove App\\Events\\ prefix from event class names
- RunRemoteProcess already prepends App\\Events\\ to the class name
- Use 'S3DownloadFinished' instead of 'App\\Events\\S3DownloadFinished'
- Use 'S3RestoreJobFinished' instead of 'App\\Events\\S3RestoreJobFinished'
- Fixes "Class 'App\Events\App\Events\S3DownloadFinished' not found" error

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
3fc626c6da fix: create S3 event classes and add formatBytes helper
- Create S3DownloadFinished event to cleanup MinIO containers
- Create S3RestoreJobFinished event to cleanup temp files and S3 downloads
- Add formatBytes() helper function for human-readable file sizes
- Update Import component to use full Event class names in callEventOnFinish
- Fix activity monitor visibility issues with proper event dispatching

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
f714d4d78d fix: add missing formatBytes helper function
The formatBytes function was used in the view but never defined, causing
a runtime error. This function was needed to display S3 file sizes in
human-readable format (e.g., "1.5 MB" instead of "1572864").

Added formatBytes() helper to bootstrap/helpers/shared.php:
- Converts bytes to human-readable format (B, KB, MB, GB, TB, PB)
- Uses base 1024 for proper binary conversion
- Configurable precision (defaults to 2 decimal places)
- Handles zero bytes case

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
4d74aafb2e debug: add ray logging to trace S3DownloadFinished event flow
Add debugging to understand why the download message stays visible after completion.
This will help us see if:
1. The event is being dispatched by ActivityMonitor
2. The event is being received by Import component
3. The property is being set to false
4. The entangle is syncing to Alpine properly

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
f2a017a063 fix: revert to original dispatch approach with unique wire:key per monitor
Root cause analysis:
- Changed from dispatch to property binding broke the activity monitor completely
- ActivityMonitor component expects activityMonitor event, not property binding
- Original approach was correct: use dispatch + event listeners

Solution:
- Revert to original dispatch('activityMonitor', $activity->id) calls
- Use @if conditionals to render only one monitor at a time (removes from DOM)
- Add unique wire:key to each monitor instance to prevent conflicts
- S3 download monitor: wire:key="s3-download-{{ $resource->uuid }}"
- Database restore monitor: wire:key="database-restore-{{ $resource->uuid }}"

This ensures:
- Activity monitors display correctly when processes start
- Only one monitor is rendered at a time (S3 download OR database restore)
- Each monitor has unique identity via wire:key
- Event listeners work as designed

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
1271e7df2c fix: add updatedActivityId watcher to ActivityMonitor component
- Add updatedActivityId method to watch for changes to activityId property
- When activityId is set/updated, automatically hydrate the activity and enable polling
- This allows the activity monitor to display content when activityId is bound from parent component
- Fixes issue where activity monitor was empty because activity wasn't loaded

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
d8037de8d2 fix: ensure S3 download message hides when download finishes
- Add S3DownloadFinished event listener to Import component
- Add handleS3DownloadFinished method to set s3DownloadInProgress to false
- This ensures the 'Downloading from S3...' message is hidden when download completes
- The success message now properly displays after download finishes

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:20 +01:00
Andras Bacsai
5324ac3bd9 fix: conditionally render activity monitors to prevent output conflicts
- Add currentActivityId property to track the active process
- Replace event dispatching with property assignment for cleaner state management
- S3 download monitor only renders during download and is removed when complete
- Database restore monitor only renders during restore operation
- Both monitors now share the same activity-monitor component instance with proper lifecycle management
- When user starts restore after S3 download, S3 monitor is removed from DOM
- Fixes issue where S3 download and database restore showed identical output

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:19 +01:00
Andras Bacsai
226de35146 Revert "fix: S3 download and database restore output showing same content"
This reverts commit d07cc48369ac4beb0405823bf34aad02200e4a6f.
2025-11-14 10:43:19 +01:00
Andras Bacsai
a5dafe785b fix: S3 download and database restore output showing same content
- Add unique wire keys to activity-monitor components (s3-download-monitor and database-restore-monitor)
- Update dispatch calls to target specific components using ->to() method
- This prevents both activity monitors from listening to the same activityMonitor event and displaying identical output
- S3 download now shows in s3-download-monitor component
- Database restore now shows in database-restore-monitor component

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:19 +01:00
Andras Bacsai
6cb3e4d515 fix: S3 restore button disabled state and security scopes
- Add Alpine.js entangle bindings for s3StorageId and s3Path to enable
  reactive button state without server requests
- Change button disabled binding from PHP :disabled to Alpine x-bind:disabled
  for client-side reactivity using deferred wire:model inputs
- Replace S3Storage::findOrFail with ownedByCurrentTeam()->findOrFail in
  checkS3File() and downloadFromS3() methods
- Remove redundant manual team verification since ownedByCurrentTeam scope
  automatically filters to current team

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-14 10:43:19 +01:00
Andras Bacsai
800396b443 feat: add S3 storage integration for file import
This commit introduces functionality for integrating S3 storage into the import process. It allows users to select S3 storage, check for file existence, and download files directly from S3. This enhancement improves the flexibility of the import feature by enabling users to work with files stored in S3, addressing a common use case for teams that utilize cloud storage solutions.
2025-11-14 10:43:19 +01:00
Andras Bacsai
ec30426a2f feat(ServiceDatabase): add support for TimescaleDB detection and database type identification 2025-11-12 00:36:38 +01:00
Andras Bacsai
6202803db2 fix(CleanupRedis): guard against scan() returning false and use lowercase option keys
- Change Redis scan() option keys from uppercase (MATCH, COUNT) to lowercase (match, count) to comply with PhpRedis requirements
- Add guard to handle scan() returning false and display error message
- Add comprehensive test coverage for scan() error handling scenarios
2025-11-11 21:22:29 +01:00
Andras Bacsai
ad69758c56 refactor(CleanupRedis): remove JSON decode error handling from cleanupStuckJobs method 2025-11-11 20:54:25 +01:00
Andras Bacsai
b79aa1b195 refactor(CleanupRedis): optimize key retrieval in cleanupStuckJobs using Redis scan 2025-11-11 15:41:05 +01:00
Andras Bacsai
a95e92f098 feat(CleanupRedis): add error handling for JSON decode failures in cleanupStuckJobs method 2025-11-11 15:40:11 +01:00
Andras Bacsai
49a3bb0daf refactor(DatabaseBackupJob): remove retry attempts and backoff logic for job execution 2025-11-11 15:39:01 +01:00
Andras Bacsai
644df223dc fix(ScheduledTaskJob): make server property nullable and update logging to handle null values 2025-11-11 15:38:55 +01:00
Andras Bacsai
eb70fe00ff feat(CleanupRedis): add error handling for JSON decode failures in cleanupStuckJobs method 2025-11-11 15:36:34 +01:00
Andras Bacsai
4fa0c581c8 fix(ScheduledTask): change timeout property type to int for consistency in syncData method 2025-11-11 15:30:10 +01:00
Andras Bacsai
334892d1ff feat(BackupNotification): include database name in BackupFailed notification for better context 2025-11-11 15:27:57 +01:00
Andras Bacsai
684a08bf75 feat(CleanupRedis): improve stuck job cleanup logic by prioritizing reserved_at timestamp 2025-11-11 15:27:52 +01:00
Andras Bacsai
133d6a0349 feat(DeploymentException): add custom exception for deployment errors and update handler to exclude from reporting 2025-11-11 15:08:26 +01:00
Andras Bacsai
0d14bc1df7 feat(EmailChannel): enhance error handling with user-friendly messages for Resend API errors 2025-11-11 13:23:45 +01:00
Andras Bacsai
0cfce06869 feat(Cleanup): implement failure marking for stuck scheduled tasks and database backups during startup 2025-11-11 12:32:52 +01:00
Andras Bacsai
64c7d301ce feat(DatabaseBackupJob, ScheduledTaskJob): enforce minimum timeout and add execution ID for timeout handling 2025-11-11 12:07:39 +01:00
Andras Bacsai
104e68a9ac
Merge branch 'next' into improve-scheduled-tasks 2025-11-11 11:38:04 +01:00
Andras Bacsai
e79316c8b5
Update app/Jobs/DeleteResourceJob.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-11 11:35:30 +01:00
Andras Bacsai
75e8605c3d
Merge branch 'next' into port-detection-lol 2025-11-11 11:32:17 +01:00
Andras Bacsai
f9ab2a7ca8
Merge branch 'next' into improve-scheduled-tasks 2025-11-11 11:32:15 +01:00
Andras Bacsai
0039be49b2 fix(DeleteResourceJob): escape deployment UUID and stack name in Docker commands 2025-11-11 11:30:17 +01:00
Andras Bacsai
45ab79f292
Merge branch 'next' into port-detection-lol 2025-11-11 11:21:26 +01:00
Andras Bacsai
a12dd98f64 Merge branch 'next' into fix-deployment-skipped-message 2025-11-10 21:33:10 +01:00
Andras Bacsai
fd50f72889 fix: remove duplicate deployment queue call causing false error messages
Removed duplicate queue_application_deployment() call in Heading.php deploy method that was causing "Deployment already queued for this commit" error to display even though deployment was successfully queued.

Also changed notification type from 'success' to 'error' when deployment is actually skipped for proper user feedback.
2025-11-10 21:31:06 +01:00
Andras Bacsai
f1d80d6776 fix: enhance error handling in initialization and cleanup process 2025-11-10 15:29:26 +01:00
Andras Bacsai
23c165d4d1 fix: wrap database updates in a transaction for consistency in GetContainersStatus 2025-11-10 15:07:44 +01:00
Andras Bacsai
761f177b1e fix: move restart count reset logic to the correct position in the restart method 2025-11-10 14:59:29 +01:00
Andras Bacsai
cefb425492
Update app/Livewire/Project/Application/Heading.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-10 14:58:08 +01:00
Andras Bacsai
18a14037c7 fix: improve logging for PORT environment variable mismatch and ensure .env file is created in the correct directory 2025-11-10 14:56:27 +01:00
Andras Bacsai
0b8d3d395e fix: remove redundant process termination logic from deployment methods 2025-11-10 14:46:02 +01:00
Andras Bacsai
9507f602df fix: ensure service state is refreshed and compose configurations are saved after submission 2025-11-10 14:44:11 +01:00
Andras Bacsai
f5fa09790e refactor: improve command handling and ensure correct working directory for Docker operations 2025-11-10 14:40:03 +01:00
Andras Bacsai
71c89d9ba8
Merge branch 'next' into improve-scheduled-tasks 2025-11-10 14:21:03 +01:00
Andras Bacsai
6decad2e96 refactor: streamline required port retrieval in EditDomain and ServiceApplicationView; add environment_variables method in ServiceApplication 2025-11-10 14:15:53 +01:00
Andras Bacsai
e63a270fea
Enhance container status tracking and improve user notifications (#7182) 2025-11-10 13:58:22 +01:00
Andras Bacsai
194d023f70
Enhance port detection and improve user notifications (#7184) 2025-11-10 13:56:09 +01:00
Andras Bacsai
99e97900a5 feat: add automated PORT environment variable detection and UI warnings
Add detection system for PORT environment variable to help users configure applications correctly:

- Add detectPortFromEnvironment() method to Application model to detect PORT env var
- Add getDetectedPortInfoProperty() computed property in General Livewire component
- Display contextual info banners in UI when PORT is detected:
  - Warning when PORT exists but ports_exposes is empty
  - Warning when PORT doesn't match ports_exposes configuration
  - Info message when PORT matches ports_exposes
- Add deployment logging to warn about PORT/ports_exposes mismatches
- Include comprehensive unit tests for port detection logic

The ports_exposes field remains authoritative for proxy configuration, while
PORT detection provides helpful suggestions to users.
2025-11-10 13:43:27 +01:00
Andras Bacsai
68a9f2ca77 feat: add container restart tracking and crash loop detection
Track container restart counts from Docker and detect crash loops to provide better visibility into application health issues.

- Add restart_count, last_restart_at, and last_restart_type columns to applications table
- Detect restart count increases from Docker inspect data and send notifications
- Show restart count badge in UI with warning icon on Logs navigation
- Distinguish between crash restarts and manual restarts
- Implement 30-second grace period to prevent false "exited" status during crash loops
- Reset restart count on manual stop, restart, and redeploy actions
- Add unit tests for restart count tracking logic

This helps users quickly identify when containers are in crash loops and need attention, even when the container status flickers between states during Docker's restart backoff period.
2025-11-10 13:04:31 +01:00
Andras Bacsai
1580c0d3ad
Update app/Jobs/ScheduledTaskJob.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-10 11:41:50 +01:00
Andras Bacsai
0ea27ce37a
Cancel active deployments when a pull request is closed (#7164) 2025-11-10 11:16:54 +01:00
Andras Bacsai
b22e79caec feat(jobs): improve scheduled tasks with retry logic and queue cleanup
- Add retry configuration to CoolifyTask (3 tries, 600s timeout)
- Add retry configuration to ScheduledTaskJob (3 tries, configurable timeout)
- Add retry configuration to DatabaseBackupJob (2 tries)
- Implement exponential backoff for all jobs (30s, 60s, 120s intervals)
- Add failed() handlers with comprehensive error logging to scheduled-errors channel
- Add execution tracking: started_at, retry_count, duration (decimal), error_details
- Add configurable timeout field to scheduled tasks (60-3600s, default 300s)
- Update UI to include timeout configuration in task creation/editing forms
- Increase ScheduledJobManager lock expiration from 60s to 90s for high-load environments
- Implement safe queue cleanup with restart vs runtime modes
  - Restart mode: aggressive cleanup (marks all processing jobs as failed)
  - Runtime mode: conservative cleanup (only marks jobs >12h as failed, skips deployments)
- Add cleanup:redis --restart flag for system startup
- Integrate cleanup into Dev.php init() for development environment
- Increase scheduled-errors log retention from 7 to 14 days
- Create comprehensive test suite (unit and feature tests)
- Add TESTING_GUIDE.md with manual testing instructions

Fixes issues with jobs failing after single attempt and "attempted too many times" errors
2025-11-10 11:11:18 +01:00
Andras Bacsai
67605d50fc fix(deployment): prevent base deployments from being killed when PRs close (#7113)
- Fix container filtering to properly distinguish base deployments (pullRequestId=0) from PR deployments
- Add deployment cancellation when PR closes via webhook to prevent race conditions
- Prevent CleanupHelperContainersJob from killing active deployment containers
- Enhance error messages with exit codes and actual errors instead of vague "Oops" messages
- Protect status transitions in finally blocks to ensure proper job failure handling
2025-11-09 14:41:35 +01:00
Andras Bacsai
712d60c75b feat: ensure .env file exists for docker compose and auto-inject in payloads 2025-11-07 15:20:10 +01:00
Andras Bacsai
e86575d6f7 fix: guard against null or empty docker compose in saveComposeConfigs method 2025-11-07 14:14:43 +01:00
Andras Bacsai
468d5fe7d7 refactor: improve docker compose validation and transaction handling in StackForm 2025-11-07 14:03:19 +01:00
ShadowArcanist
501a67ac40
Merge branch 'next' into shadow/fix-docker-time-command 2025-11-06 20:17:10 +05:30
Andras Bacsai
4e734492e0 fix: escape shell arguments in syncBunny command execution 2025-11-06 14:57:53 +01:00
Andras Bacsai
24bcce3f9b
Update app/Console/Commands/SyncBunny.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-06 14:36:34 +01:00
Andras Bacsai
bcd225bd22 feat: Implement required port validation for service applications
- Added `requiredPort` property to `ServiceApplicationView` to track the required port for services.
- Introduced modal confirmation for removing required ports, including methods to confirm or cancel the action.
- Enhanced `Service` model with `getRequiredPort` and `requiresPort` methods to retrieve port information from service templates.
- Implemented `extractPortFromUrl` method in `ServiceApplication` to extract port from FQDN URLs.
- Updated frontend views to display warnings when required ports are missing from domains.
- Created unit tests for service port validation and extraction logic, ensuring correct behavior for various scenarios.
- Added feature tests for Livewire component handling of domain submissions with required ports.
2025-11-06 14:32:36 +01:00
Andras Bacsai
d0ee7d0412
Merge branch 'next' into feat-add-dockerfile-from-instruction-par 2025-11-06 09:24:54 +01:00
Andras Bacsai
88aa24057b fix: update environment variable mapping in deployment job 2025-11-06 09:21:41 +01:00
Andras Bacsai
dbf7957795 fix: inserting ARG statements in Dockerfile after FROM instructions 2025-11-06 08:54:35 +01:00
Andras Bacsai
23a3b47011 refactor: rename sync function and improve error handling
The function previously named syncGitHubReleases has been renamed to syncReleasesToGitHubRepo for clarity, as it now focuses on syncing releases directly to the GitHub repository instead of the CDN. Additionally, error handling has been enhanced to provide more informative messages during the cloning, branching, and committing processes. This refactor aims to improve the maintainability of the code and ensure better feedback in case of failures.
2025-11-05 14:54:13 +01:00
Andras Bacsai
0865ecd3db refactor: move RestoreDatabase command to Cloud namespace
This change organizes the command within the appropriate Cloud namespace, improving code structure and maintainability. By grouping related commands together, it enhances clarity for future developers and helps in locating files more efficiently.
2025-11-05 14:42:12 +01:00
Andras Bacsai
2db122c851 fix: remove debugging output from StartPostgresql command handling 2025-11-05 09:10:15 +01:00
Andras Bacsai
5b79844a3a fix: update docker stop command to use --time instead of --timeout 2025-11-05 08:48:10 +01:00
Andras Bacsai
26bbf94d66 fix: update syncData method to use data_get for safer property access 2025-11-04 10:51:46 +01:00
Andras Bacsai
a45e674c39
Update app/Livewire/Project/Application/General.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-11-04 09:57:12 +01:00
Andras Bacsai
7b589abfbe fix: fix SPA toggle nginx regeneration and add confirmation modal
- Fix SPA toggle not triggering nginx configuration regeneration by capturing old value before syncData
- Fix similar issue with is_http_basic_auth_enabled using value comparison instead of isDirty
- Remove redundant application settings save() call
- Add confirmation modal to nginx generation button to prevent accidental overwrites
- Pass correct type parameter (spa/static) to generateNginxConfiguration method
2025-11-04 09:48:59 +01:00
Andras Bacsai
faa62dec57 refactor: Remove SynchronizesModelData trait and implement syncData method for model synchronization 2025-11-04 09:18:05 +01:00
Andras Bacsai
3d9c4954c1 feat: Enhance General component with additional properties and validation rules 2025-11-04 08:51:05 +01:00
Andras Bacsai
fbaa5eb369 feat: Update ApplicationSetting model to include additional boolean casts
- Changed `$cast` to `$casts` in ApplicationSetting model to enable proper boolean casting for new fields.
- Added boolean fields: `is_spa`, `is_build_server_enabled`, `is_preserve_repository_enabled`, `is_container_label_escape_enabled`, `is_container_label_readonly_enabled`, and `use_build_secrets`.

fix: Update Livewire component to reflect new property names

- Updated references in the Livewire component for the new camelCase property names.
- Adjusted bindings and IDs for consistency with the updated model.

test: Add unit tests for ApplicationSetting boolean casting

- Created tests to verify boolean casting for `is_static` and other boolean fields in ApplicationSetting.
- Ensured all boolean fields are correctly defined in the casts array.

test: Implement tests for SynchronizesModelData trait

- Added tests to verify the functionality of the SynchronizesModelData trait, ensuring it correctly syncs properties between the component and the model.
- Included tests for handling non-existent properties gracefully.
2025-11-04 08:43:33 +01:00
Aditya Tripathi
28cb561c04 feat: add database transactions and component-level authorization to shared variables 2025-11-03 20:54:34 +00:00
Andras Bacsai
d291d85311 feat: add RestoreDatabase command for PostgreSQL dump restoration 2025-11-03 13:02:14 +01:00
Andras Bacsai
f315e4bd9c feat: add dev_helper_version to instance settings and update related functionality 2025-11-03 08:38:43 +01:00
Aditya Tripathi
85a1483356 feat: developer view for shared env variables 2025-11-02 22:27:24 +00:00
Andras Bacsai
5fd8cff7c7
Merge pull request #7002 from W8jonas/fix/api-destination-uuid-databases
fix api - set destination_uuid when creating databases
2025-11-01 13:46:47 +01:00
Andras Bacsai
237246acee fix: Remove duplicate custom_labels from config hash calculation
The `custom_labels` attribute was being concatenated twice into the configuration hash calculation within the `isConfigurationChanged` method. This commit removes the redundant inclusion to ensure accurate configuration change detection.
2025-11-01 13:28:56 +01:00
Andras Bacsai
1f158b9b35 fix: Improve custom_network_aliases handling and testing
The `is_array` check for `custom_network_aliases_array` was too strict and could lead to issues when the value was an empty string or null. This commit changes the check to `!empty()` for more robust handling.

Additionally, the unit tests for `custom_network_aliases` have been refactored to directly use the `Application::isConfigurationChanged()` method. This provides a more accurate and integrated test of the configuration change detection logic, rather than relying on a manual hash calculatio
2025-11-01 13:24:05 +01:00
Andras Bacsai
9a664865ee refactor: Improve handling of custom network aliases
The custom_network_aliases attribute in the Application model was being cast to an array directly. This commit refactors the attribute to provide both a string representation (for compatibility with older configurations and hashing) and an array representation for internal use. This ensures that network aliases are correctly parsed and utilized, preventing potential issues during deployment and configuration updates.
2025-11-01 13:13:14 +01:00
Andras Bacsai
ea649d2a85 Add artisan command to update service Docker image versions
This command queries Docker registries (Docker Hub, GHCR, Quay, Codeberg) to find and update Docker image versions in service template files.

Features:
- Automatically updates 'latest' tags to semantic versions using digest matching
- Supports multiple version formats: semantic (1.2.3), date-based (2025.10.20), RELEASE timestamps
- Prefers shorter version tags (1.8 over 1.8.1) when both available
- In-memory caching to avoid duplicate API queries for same images
- Detects and reports services with available major version updates
- Preserves YAML formatting and comments
- Supports dry-run mode for preview

Usage:
  php artisan services:update-versions [--dry-run] [--service=name]

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 08:29:11 +01:00
Andras Bacsai
2a8fbb3f6e feat: add token validation functionality for Hetzner and DigitalOcean providers 2025-10-29 23:21:38 +01:00
Andras Bacsai
c95e297f39 fix: update boarding flow logic to complete onboarding when server is created 2025-10-29 23:06:39 +01:00
ShadowArcanist
97e734e5ea fixed github app deleting private key when it is used by other resources 2025-10-30 01:16:59 +05:30
Andras Bacsai
65c2b917db
Merge pull request #7039 from coollabsio/andrasbacsai/fix-login-rate-limit-bypass
fix: prevent login rate limit bypass via spoofed headers
2025-10-28 12:16:34 +01:00
Andras Bacsai
65e5b2ecdb fix: correct login rate limiter key format to include IP address 2025-10-28 10:32:19 +01:00
Andras Bacsai
f300ba0118 fix: prevent login rate limit bypass via spoofed headers
The login and forgot-password rate limiters were vulnerable to bypass
by manipulating the X-Forwarded-For header. Attackers could rotate
this header value to circumvent the 5 attempts per minute limit.

Changed both rate limiters to use server('REMOTE_ADDR') instead of
ip() to prevent header spoofing. REMOTE_ADDR gives the actual
connecting IP before proxy headers are processed.

Also added comprehensive unit tests to verify the fix.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 09:47:13 +01:00
Andras Bacsai
4c29e8ceb3
Merge pull request #7012 from coollabsio/andrasbacsai/debian-13-docker-support
Add repository-based Docker installation fallbacks for Debian 13 and other major distros
2025-10-28 09:35:24 +01:00
Andras Bacsai
84b0ec1e94
Update app/Actions/Server/InstallDocker.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-28 09:31:32 +01:00
Andras Bacsai
b1a68df65c fix: add null checks and validation to OAuth bulk update method
- Add null check before updating OAuth settings to prevent calling methods on null
- Apply couldBeEnabled() validation for all settings in bulk update (not just instant save)
- Disable OAuth providers that fail validation and collect error messages
- Surface all validation errors to the user instead of silently failing
- Update oauth_settings_map with fresh data after saving each setting

This ensures bulk updates follow the same validation logic as instant-save paths
and prevents bypassing model validation by directly calling update.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 17:04:33 +01:00
Andras Bacsai
8a3dc19d19 Update app/Livewire/SettingsOauth.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-27 17:03:19 +01:00
Andras Bacsai
1ab4b9aa31 refactor: simplify project data retrieval and enhance OAuth settings handling 2025-10-27 17:03:19 +01:00
Andras Bacsai
a3a5694d10
Merge pull request #7029 from coollabsio/andrasbacsai/fix-mongodb-public-proto
fix(database): prevent malformed URLs when server IP is empty
2025-10-27 16:14:48 +01:00
Andras Bacsai
dd002ba85d
Merge pull request #7015 from zackify/feature/fix-booleans
Fix api call booleans not being respected
2025-10-27 15:57:32 +01:00
Andras Bacsai
261dc39f02 fix: Monaco editor empty for docker compose applications
This commit fixes two related issues preventing the Monaco editor from displaying Docker Compose file content:

1. Data Sync Issue:
   - After loadComposeFile() fetches the compose content from Git and updates the database model, the Livewire component properties were never synced
   - Monaco editor binds to component properties via wire:model, so it remained empty
   - Fixed by calling syncFromModel() after refresh() in loadComposeFile() method

2. Script Duplication Issue:
   - Multiple Monaco editors on the same page (compose files, dockerfile, labels) caused race condition
   - Each instance tried to inject the Monaco loader script simultaneously
   - Resulted in "SyntaxError: Identifier '_amdLoaderGlobal' has already been declared"
   - Fixed by adding a global flag to prevent duplicate script injection

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 12:48:20 +01:00
Andras Bacsai
4cc668253e fix(database): prevent malformed URLs when server IP is empty
Add defensive null/empty checks in externalDbUrl() for all standalone database models to prevent "invalid proto:" errors when server IP is not available.

**Problem:**
When `$this->destination->server->getIp` returns null or empty string, database URLs become malformed (e.g., `mongodb://user:pass@:27017` with empty host), causing "invalid proto:" validation errors.

**Solution:**
Added early return with null check in externalDbUrl() method for all 8 database types:
- Check if server IP is empty before building URL
- Return null instead of generating malformed URL
- Maintains graceful degradation - UI handles null URLs appropriately

**Defense in Depth:**
While mount() guard (from commit 74c70b431) prevents most cases, this adds an additional safety layer for edge cases:
- Race conditions during server updates
- State changes between mount and URL access
- Direct model access bypassing Livewire lifecycle

**Affected Models:**
- StandaloneMongodb
- StandalonePostgresql
- StandaloneMysql
- StandaloneMariadb
- StandaloneClickhouse
- StandaloneRedis
- StandaloneKeydb
- StandaloneDragonfly

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 11:46:24 +01:00
Cinzya
bceef418c8 refactor: remove staging URL logic from ServerPatchCheck constructor 2025-10-26 21:52:51 +01:00
Zach Silveira
b72f93faab fix api call booleans not being used 2025-10-26 11:25:44 -04:00
Andras Bacsai
fc49b9284a Add repository-based Docker installation fallbacks for all major Linux distros
This commit adds official Docker repository installation methods as fallbacks
when Rancher and get.docker.com convenience scripts fail, providing more
reliable Docker installation across all supported operating systems.

Changes:
- Add apt repository fallback for Debian-based systems (Ubuntu, Debian, Raspbian)
  - Fixes installation on Debian 13 (Trixie) where get.docker.com fails
  - Uses VERSION_CODENAME for automatic OS version detection
- Add dnf repository fallback for RHEL-based systems (CentOS, Fedora, Rocky, AlmaLinux)
- Add zypper repository fallback for SUSE-based systems (SLES, OpenSUSE)
- Refactor installation methods into dedicated private methods for better maintainability

Installation fallback chain:
1. Rancher install-docker script (preserves version pinning)
2. Docker get.docker.com convenience script
3. Official repository method (new, most reliable)

Benefits:
- Future-proof: Works with new OS releases automatically
- Production-ready: Uses Docker's recommended installation method
- Comprehensive: Covers 95%+ of Linux servers in production
- Maintainable: Clean code structure with single-responsibility methods

Fixes issue where Debian 13 (Trixie) servers fail validation because
get.docker.com script incorrectly uses numeric version "13" instead of
codename "trixie" in repository URLs.
2025-10-26 12:41:50 +01:00
Cinzya
c4bfbad8e7 Merge branch 'next' into hotfix/serverpatch-notification-url 2025-10-26 12:38:26 +01:00
Andras Bacsai
70024f0ca4
Merge pull request #6984 from Cinzya/feature/fix-allowedall-check
fix(settings): prevent false positives in allowed IPs validation
2025-10-26 11:00:15 +01:00
Andras Bacsai
6e74317cb5 refactor: streamline allowed IPs validation and enhance UI warnings for API access 2025-10-26 10:57:24 +01:00
Andras Bacsai
f5b513fdbe
Merge pull request #7005 from coollabsio/fix-github-source-appid-null
fix: GitHub source creation and configuration issues
2025-10-26 09:54:48 +01:00
Andras Bacsai
b75c0fd8ae fix: change app_id and installation_id to integer values in createGithubAppManually method 2025-10-26 09:27:21 +01:00
Andras Bacsai
aeba914bda refactor: remove deprecated next() method
The backward-compatible next() method is no longer needed since all
call sites have been updated to use the clearer method names:
- completeDeployment()
- failDeployment()
- transitionToStatus()

This completes the refactoring to make status transitions more explicit
and maintainable.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 09:20:30 +01:00
Andras Bacsai
42f916dce2 fix: ensure deployment failure notifications are sent reliably
**Problem:**
Deployment failure notifications were not being sent due to two bugs:

1. **Timing Issue in next() function:**
   - When failed() called next(FAILED), the database still had status "in_progress"
   - The notification check looked for ALREADY failed status (not found yet)
   - Status was updated AFTER the check, losing the notification

2. **Direct Status Update:**
   - Healthcheck failures directly updated status to FAILED
   - Bypassed next() entirely, no notification sent

**Solution:**
Refactored status transition logic with clear separation of concerns:

- Moved notification logic AFTER status update (not before)
- Created transitionToStatus() as single source of truth
- Added completeDeployment() and failDeployment() for clarity
- Extracted status-specific side effects into dedicated methods
- Updated healthcheck failure to use failDeployment()

**Benefits:**
-  Notifications sent for ALL failure scenarios
-  Clear, self-documenting method names
-  Single responsibility per method
-  Type-safe using enum instead of strings
-  Harder to bypass notification logic accidentally
-  Backward compatible (old next() preserved)

**Changed:**
- app/Jobs/ApplicationDeploymentJob.php (+101/-21 lines)

Fixes #6911

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 09:06:59 +01:00
Cinzya
e29b517fef fix: server URL generation in ServerPatchCheck notification 2025-10-26 02:50:41 +02:00
Andras Bacsai
06ee7d0132 fix: GitHub source creation and configuration issues
Fixed multiple issues with GitHub App source creation and management:

1. **Fixed null property assignment error on component mount**
   - Changed property types to nullable in Change component (appId, installationId, clientId, etc.)
   - Updated validation rules to allow nullable values
   - Allows mounting component with newly created GitHub Apps that don't have these fields set yet

2. **Fixed Livewire morphing error on manual creation**
   - Modified createGithubAppManually() to redirect after saving
   - Prevents "Cannot read properties of null" error when view structure changes
   - Fields now properly populated after manual creation without requiring page refresh

3. **Fixed is_system_wide not being saved on creation**
   - Removed backwards logic that only saved is_system_wide on cloud instances
   - Added is_system_wide to GithubApp model casts for proper boolean handling
   - System-wide checkbox now works correctly on self-hosted instances

4. **Fixed misleading preview deployment checkbox**
   - Removed instantSave attribute from permission checkboxes in unconfigured state
   - These are configuration options for GitHub App creation, not database fields
   - Prevents "GitHub App updated" success message when nothing was actually saved

5. **Added validation for Refetch Permissions button**
   - Validates App ID and Private Key are set before attempting to fetch
   - Shows clear error messages: "Cannot fetch permissions. Please set the following required fields first: App ID, Private Key"
   - Prevents crash when private key is null or invalid

6. **Better error handling for unsupported private key formats**
   - Detects OpenSSH format keys vs RSA PEM format
   - Shows helpful message: "Please use an RSA private key in PEM format (BEGIN RSA PRIVATE KEY). OpenSSH format keys are not supported."
   - GitHub Apps require RSA PEM format, not OpenSSH format

7. **Made GitHub App view mobile responsive**
   - Updated all flex layouts to stack vertically on mobile (flex-col sm:flex-row)
   - Form fields, buttons, and sections now properly responsive
   - No more cut-off fields on small screens

Added comprehensive test coverage:
- GithubSourceChangeTest.php with 7 tests
- GithubSourceCreateTest.php with 6 tests

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-25 10:49:09 +02:00
Jonas Nascimento
62e1883709
fix api - set destination_uuid when creating databases 2025-10-25 01:09:55 -03:00
Andras Bacsai
7a52fd4506
Merge pull request #6992 from coollabsio/andrasbacsai/service-logos-color
feat: display service logos in original colors with consistent sizing
2025-10-24 14:52:26 +02:00
Andras Bacsai
0138d3b965
Merge pull request #6975 from coollabsio/fix-cron-validation-errors
Fix stale lock issue causing scheduled tasks to stop (#4539)
2025-10-24 13:22:42 +02:00
Andras Bacsai
9f87d499dd
Update app/Console/Commands/CleanupRedis.php
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-10-24 13:20:24 +02:00
Andras Bacsai
9d0d8c6729 Fix loading icon showing during automatic status checks
The loading icon was appearing during automatic background status checks
(every 10 seconds) even when users didn't click anything, which caused
confusion and made it seem like something was running unexpectedly.

Changes:
- Added manualCheckStatus() method to Application, Database, and Service
  Heading components that wraps the checkStatus() call
- Updated status component buttons to call manualCheckStatus() instead
  of checkStatus()
- Added wire:target="manualCheckStatus" to loading directives so the
  loading icon only appears when users explicitly click the refresh button
- Added delay.shortest to prevent flickering on fast operations

The automatic wire:poll.10000ms="checkStatus" now runs silently in the
background without showing the loading icon, while manual refreshes
still provide visual feedback to the user.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 12:58:52 +02:00
Andras Bacsai
b02689a43e feat: display service logos in original colors with consistent sizing
This commit improves the visual presentation of service, application, and database logos on the new resource selection page:

- Remove grayscale filter: Logos now display in their original colors by default instead of being greyed out
- Dark mode support for SVGs: Updated SVG logos to use `fill="currentColor"` and added `text-black dark:text-white` wrapper for proper light/dark theme adaptation
- Consistent aspect ratios: Removed `aspect-square` and added `object-contain` to preserve original logo proportions
- Uniform sizing: Implemented fixed-size container (4.5rem × 4.5rem) with centered logo positioning to ensure all logos appear at consistent sizes regardless of intrinsic dimensions
- Improved mobile UX: Adjusted sticky search bar positioning from `top-10` to `top-20` to prevent navbar overlap

Files modified:
- resources/views/livewire/project/new/select.blade.php
- resources/views/components/resource-view.blade.php
- app/Livewire/Project/New/Select.php
- public/svgs/*.svg (12 SVG files updated with currentColor)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 10:22:33 +02:00
Andras Bacsai
4ef0a50e09 feat: add category filter dropdown to service selection
Add a searchable category dropdown filter on the new resource page to help users filter services by category.

Features:
- Category dropdown positioned next to search input
- Auto-focus on search field when dropdown opens
- Case-insensitive category filtering
- Proper acronym formatting (AI, API, CI, etc. displayed in uppercase)
- Loading/disabled state while categories are being fetched
- Category search/filter within dropdown
- Alphabetical sorting (case-insensitive)

Backend changes:
- Extract unique categories from service templates
- Handle comma-separated categories
- Format common acronyms to uppercase
- Case-insensitive natural sorting

Frontend changes:
- Searchable dropdown component with Alpine.js
- Category filter integration with existing search
- Disabled state placeholder during loading
- Auto-focus behavior for better UX

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 21:02:12 +02:00
Andras Bacsai
188c86ca45 Improve SSH key filtering and datalist component
- Add ownedAndOnlySShKeys() method to filter out git-related keys
- Update Boarding component to use new filtering method
- Enhance datalist component with better multi-select and single-select handling
- Fix Alpine.js reactivity and improve UI interactions

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 16:18:20 +02:00
Andras Bacsai
2e71ef4f11 Fix Hetzner server redirect in onboarding flow
When creating a Hetzner server from the onboarding view, the redirect
to the server details page was not working properly due to modal context.
The standard redirect() call doesn't handle navigation from within modals.

Changes:
- Add from_onboarding flag to ByHetzner component
- Use wire:navigate redirect when in onboarding mode
- Pass from_onboarding=true from boarding view

This ensures proper navigation to the newly created server page instead
of staying on the onboarding view.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 16:17:01 +02:00
Andras Bacsai
c6a2d1fe0a Fix stale lock issue causing scheduled tasks to stop (#4539)
## Problem
Scheduled tasks, backups, and auto-updates stopped working after 1-2 months
with error: MaxAttemptsExceededException: App\Jobs\ScheduledJobManager has
been attempted too many times.

Root cause: ScheduledJobManager used WithoutOverlapping with only
releaseAfter(60), causing locks without expiration (TTL=-1) that persisted
indefinitely when jobs hung or processes crashed.

## Solution

### Part 1: Prevention (Future Locks)
- Added expireAfter(60) to ScheduledJobManager middleware
- Lock now auto-expires after 60 seconds (matches everyMinute schedule)
- Changed from releaseAfter(60) to expireAfter(60)->dontRelease()
- Follows Laravel best practices and matches other Coolify jobs

### Part 2: Recovery (Existing Locks)
- Enhanced cleanup:redis command with --clear-locks flag
- Scans Redis for stale locks (TTL=-1) and removes them
- Called automatically during app:init on startup/upgrade
- Provides immediate recovery for affected instances

## Changes
- app/Jobs/ScheduledJobManager.php: Added expireAfter(60)->dontRelease()
- app/Console/Commands/CleanupRedis.php: Added cleanupCacheLocks() method
- app/Console/Commands/Init.php: Auto-clear locks on startup
- tests/Unit/ScheduledJobManagerLockTest.php: Test to prevent regression
- STALE_LOCK_FIX.md: Complete documentation

## Testing
- Unit tests pass (2 tests, 8 assertions)
- Code formatted with Pint
- Matches pattern used by CleanupInstanceStuffsJob

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:07:33 +02:00
Andras Bacsai
f0fc7af78c
Merge pull request #6961 from YaRissi/fix/hetzner-deprecated
fix: deprecated hetzner servers
2025-10-22 21:42:24 +02:00
Cinzya
b678242780 refactor: remove redundant 2025-10-22 21:02:23 +02:00
Cinzya
e160b5139a refactor: replace allowed IPs validation logic with regex 2025-10-22 20:55:24 +02:00
Andras Bacsai
587517394b Changes auto-committed by Conductor 2025-10-22 13:03:17 +02:00
Andras Bacsai
466772f61a Changes auto-committed by Conductor 2025-10-22 12:41:17 +02:00
Andras Bacsai
51bada1871 Changes auto-committed by Conductor 2025-10-22 08:29:16 +02:00
elmariss
af1374667b fix: filter deprecated server types for Hetzner 2025-10-22 00:13:55 +02:00
Andras Bacsai
d8c89a1abf Changes auto-committed by Conductor 2025-10-21 20:39:39 +02:00
Andras Bacsai
4fc0c946da Changes auto-committed by Conductor 2025-10-21 08:47:38 +02:00
Andras Bacsai
e1fe586397 Changes auto-committed by Conductor 2025-10-20 12:59:57 +02:00
Andras Bacsai
84559a0e7d Changes auto-committed by Conductor 2025-10-20 09:48:37 +02:00
Andras Bacsai
f7427fdea0 Changes auto-committed by Conductor 2025-10-17 23:04:24 +02:00
ShadowArcanist
9620455be0
Merge branch 'next' into shadow/fix-docker-time-command 2025-10-17 18:52:40 +05:30
Andras Bacsai
dab30da63c
Merge pull request #6862 from coollabsio/andrasbacsai/livewire-model-binding
Complete Livewire legacy model binding migration (25+ components)
2025-10-17 09:27:18 +02:00
Andras Bacsai
2b51363b8c Changes auto-committed by Conductor 2025-10-16 17:23:22 +02:00
Andras Bacsai
975d1b8a6b Changes auto-committed by Conductor 2025-10-16 17:13:47 +02:00
Andras Bacsai
e2c254a5a8 Changes auto-committed by Conductor 2025-10-16 17:08:08 +02:00