diff --git a/.AI_INSTRUCTIONS_SYNC.md b/.AI_INSTRUCTIONS_SYNC.md new file mode 100644 index 0000000000..bbe0a90e1c --- /dev/null +++ b/.AI_INSTRUCTIONS_SYNC.md @@ -0,0 +1,156 @@ +# AI Instructions Synchronization Guide + +This document explains how AI instructions are organized and synchronized across different AI tools used with Coolify. + +## Overview + +Coolify maintains AI instructions in two parallel systems: + +1. **CLAUDE.md** - For Claude Code (claude.ai/code) +2. **.cursor/rules/** - For Cursor IDE and other AI assistants + +Both systems share core principles but are optimized for their respective workflows. + +## Structure + +### CLAUDE.md +- **Purpose**: Condensed, workflow-focused guide for Claude Code +- **Format**: Single markdown file +- **Includes**: + - Quick-reference development commands + - High-level architecture overview + - Core patterns and guidelines + - Embedded Laravel Boost guidelines + - References to detailed .cursor/rules/ documentation + +### .cursor/rules/ +- **Purpose**: Detailed, topic-specific documentation +- **Format**: Multiple .mdc files organized by topic +- **Structure**: + - `README.mdc` - Main index and overview + - `cursor_rules.mdc` - Maintenance guidelines + - Topic-specific files (testing-patterns.mdc, security-patterns.mdc, etc.) +- **Used by**: Cursor IDE, Claude Code (for detailed reference), other AI assistants + +## Cross-References + +Both systems reference each other: + +- **CLAUDE.md** → references `.cursor/rules/` for detailed documentation +- **.cursor/rules/README.mdc** → references `CLAUDE.md` for Claude Code workflow +- **.cursor/rules/cursor_rules.mdc** → notes that changes should sync with CLAUDE.md + +## Maintaining Consistency + +When updating AI instructions, follow these guidelines: + +### 1. Core Principles (MUST be consistent) +- Laravel version (currently Laravel 12) +- PHP version (8.4) +- Testing execution rules (Docker for Feature tests, mocking for Unit tests) +- Security patterns and authorization requirements +- Code style requirements (Pint, PSR-12) + +### 2. Where to Make Changes + +**For workflow changes** (how to run commands, development setup): +- Primary: `CLAUDE.md` +- Secondary: `.cursor/rules/development-workflow.mdc` + +**For architectural patterns** (how code should be structured): +- Primary: `.cursor/rules/` topic files +- Secondary: Reference in `CLAUDE.md` "Additional Documentation" section + +**For testing patterns**: +- Both: Must be synchronized +- `CLAUDE.md` - Contains condensed testing execution rules +- `.cursor/rules/testing-patterns.mdc` - Contains detailed examples and patterns + +### 3. Update Checklist + +When making significant changes: + +- [ ] Identify if change affects core principles (version numbers, critical patterns) +- [ ] Update primary location (CLAUDE.md or .cursor/rules/) +- [ ] Check if update affects cross-referenced content +- [ ] Update secondary location if needed +- [ ] Verify cross-references are still accurate +- [ ] Run: `./vendor/bin/pint CLAUDE.md .cursor/rules/*.mdc` (if applicable) + +### 4. Common Inconsistencies to Watch + +- **Version numbers**: Laravel, PHP, package versions +- **Testing instructions**: Docker execution requirements +- **File paths**: Ensure relative paths work from root +- **Command syntax**: Docker commands, artisan commands +- **Architecture decisions**: Laravel 10 structure vs Laravel 12+ structure + +## File Organization + +``` +/ +├── CLAUDE.md # Claude Code instructions (condensed) +├── .AI_INSTRUCTIONS_SYNC.md # This file +└── .cursor/ + └── rules/ + ├── README.mdc # Index and overview + ├── cursor_rules.mdc # Maintenance guide + ├── testing-patterns.mdc # Testing details + ├── development-workflow.mdc # Dev setup details + ├── security-patterns.mdc # Security details + ├── application-architecture.mdc + ├── deployment-architecture.mdc + ├── database-patterns.mdc + ├── frontend-patterns.mdc + ├── api-and-routing.mdc + ├── form-components.mdc + ├── technology-stack.mdc + ├── project-overview.mdc + └── laravel-boost.mdc # Laravel-specific patterns +``` + +## Recent Updates + +### 2025-10-07 +- ✅ Added cross-references between CLAUDE.md and .cursor/rules/ +- ✅ Synchronized Laravel version (12) across all files +- ✅ Added comprehensive testing execution rules (Docker for Feature tests) +- ✅ Added test design philosophy (prefer mocking over database) +- ✅ Fixed inconsistencies in testing documentation +- ✅ Created this synchronization guide + +## Maintenance Commands + +```bash +# Check for version inconsistencies +grep -r "Laravel [0-9]" CLAUDE.md .cursor/rules/*.mdc + +# Check for PHP version consistency +grep -r "PHP [0-9]" CLAUDE.md .cursor/rules/*.mdc + +# Format all documentation +./vendor/bin/pint CLAUDE.md .cursor/rules/*.mdc + +# Search for specific patterns across all docs +grep -r "pattern_to_check" CLAUDE.md .cursor/rules/ +``` + +## Contributing + +When contributing documentation: + +1. Check both CLAUDE.md and .cursor/rules/ for existing documentation +2. Add to appropriate location(s) based on guidelines above +3. Add cross-references if creating new patterns +4. Update this file if changing organizational structure +5. Verify consistency before submitting PR + +## Questions? + +If unsure about where to document something: + +- **Quick reference / workflow** → CLAUDE.md +- **Detailed patterns / examples** → .cursor/rules/[topic].mdc +- **Both?** → Start with .cursor/rules/, then reference in CLAUDE.md + +When in doubt, prefer detailed documentation in .cursor/rules/ and concise references in CLAUDE.md. diff --git a/.cursor/mcp.json b/.cursor/mcp.json new file mode 100644 index 0000000000..8c6715a151 --- /dev/null +++ b/.cursor/mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "laravel-boost": { + "command": "php", + "args": [ + "artisan", + "boost:mcp" + ] + } + } +} \ No newline at end of file diff --git a/.cursor/rules/README.mdc b/.cursor/rules/README.mdc new file mode 100644 index 0000000000..d0597bb72d --- /dev/null +++ b/.cursor/rules/README.mdc @@ -0,0 +1,297 @@ +--- +description: Complete guide to Coolify Cursor rules and development patterns +globs: .cursor/rules/*.mdc +alwaysApply: false +--- +# Coolify Cursor Rules - Complete Guide + +## Overview + +This comprehensive set of Cursor Rules provides deep insights into **Coolify**, an open-source self-hostable alternative to Heroku/Netlify/Vercel. These rules will help you understand, navigate, and contribute to this complex Laravel-based deployment platform. + +> **Cross-Reference**: This directory is for **detailed, topic-specific rules** used by Cursor IDE and other AI assistants. For Claude Code specifically, also see **[CLAUDE.md](mdc:CLAUDE.md)** which provides a condensed, workflow-focused guide. Both systems share core principles but are optimized for their respective tools. +> +> **Maintaining Rules**: When updating these rules, see **[.AI_INSTRUCTIONS_SYNC.md](mdc:.AI_INSTRUCTIONS_SYNC.md)** for synchronization guidelines to keep CLAUDE.md and .cursor/rules/ consistent. + +## Rule Categories + +### 🏗️ Architecture & Foundation +- **[project-overview.mdc](mdc:.cursor/rules/project-overview.mdc)** - What Coolify is and its core mission +- **[technology-stack.mdc](mdc:.cursor/rules/technology-stack.mdc)** - Complete technology stack and dependencies +- **[application-architecture.mdc](mdc:.cursor/rules/application-architecture.mdc)** - Laravel application structure and patterns + +### 🎨 Frontend Development +- **[frontend-patterns.mdc](mdc:.cursor/rules/frontend-patterns.mdc)** - Livewire + Alpine.js + Tailwind architecture +- **[form-components.mdc](mdc:.cursor/rules/form-components.mdc)** - Enhanced form components with built-in authorization + +### 🗄️ Data & Backend +- **[database-patterns.mdc](mdc:.cursor/rules/database-patterns.mdc)** - Database architecture, models, and data management +- **[deployment-architecture.mdc](mdc:.cursor/rules/deployment-architecture.mdc)** - Docker orchestration and deployment workflows + +### 🌐 API & Communication +- **[api-and-routing.mdc](mdc:.cursor/rules/api-and-routing.mdc)** - RESTful APIs, webhooks, and routing patterns + +### 🧪 Quality Assurance +- **[testing-patterns.mdc](mdc:.cursor/rules/testing-patterns.mdc)** - Testing strategies with Pest PHP and Laravel Dusk + +### 🔧 Development Process +- **[development-workflow.mdc](mdc:.cursor/rules/development-workflow.mdc)** - Development setup, coding standards, and contribution guidelines + +### 🔒 Security +- **[security-patterns.mdc](mdc:.cursor/rules/security-patterns.mdc)** - Security architecture, authentication, and best practices + +## Quick Navigation + +### Core Application Files +- **[app/Models/Application.php](mdc:app/Models/Application.php)** - Main application entity (74KB, highly complex) +- **[app/Models/Server.php](mdc:app/Models/Server.php)** - Server management (46KB, complex) +- **[app/Models/Service.php](mdc:app/Models/Service.php)** - Service definitions (58KB, complex) +- **[app/Models/Team.php](mdc:app/Models/Team.php)** - Multi-tenant structure (8.9KB) + +### Configuration Files +- **[composer.json](mdc:composer.json)** - PHP dependencies and Laravel setup +- **[package.json](mdc:package.json)** - Frontend dependencies and build scripts +- **[vite.config.js](mdc:vite.config.js)** - Frontend build configuration +- **[docker-compose.dev.yml](mdc:docker-compose.dev.yml)** - Development environment + +### API Documentation +- **[openapi.json](mdc:openapi.json)** - Complete API documentation (373KB) +- **[routes/api.php](mdc:routes/api.php)** - API endpoint definitions (13KB) +- **[routes/web.php](mdc:routes/web.php)** - Web application routes (21KB) + +## Key Concepts to Understand + +### 1. Multi-Tenant Architecture +Coolify uses a **team-based multi-tenancy** model where: +- Users belong to multiple teams +- Resources are scoped to teams +- Access control is team-based +- Data isolation is enforced at the database level + +### 2. Deployment Philosophy +- **Docker-first** approach for all deployments +- **Zero-downtime** deployments with health checks +- **Git-based** workflows with webhook integration +- **Multi-server** support with SSH connections + +### 3. Technology Stack +- **Backend**: Laravel 12 + PHP 8.4 +- **Frontend**: Livewire 3.5 + Alpine.js + Tailwind CSS 4.1 +- **Database**: PostgreSQL 15 + Redis 7 +- **Containerization**: Docker + Docker Compose +- **Testing**: Pest PHP 3.8 + Laravel Dusk + +### 4. Security Model +- **Defense-in-depth** security architecture +- **OAuth integration** with multiple providers +- **API token** authentication with Sanctum +- **Encrypted storage** for sensitive data +- **SSH key** management for server access + +## Development Quick Start + +### Local Setup +```bash +# Clone and setup +git clone https://github.com/coollabsio/coolify.git +cd coolify +cp .env.example .env + +# Docker development (recommended) +docker-compose -f docker-compose.dev.yml up -d +docker-compose exec app composer install +docker-compose exec app npm install +docker-compose exec app php artisan migrate +``` + +### Code Quality +```bash +# PHP code style +./vendor/bin/pint + +# Static analysis +./vendor/bin/phpstan analyse + +# Run tests +./vendor/bin/pest +``` + +## Common Patterns + +### Livewire Components +```php +class ApplicationShow extends Component +{ + public Application $application; + + protected $listeners = [ + 'deployment.started' => 'refresh', + 'deployment.completed' => 'refresh', + ]; + + public function deploy(): void + { + $this->authorize('deploy', $this->application); + app(ApplicationDeploymentService::class)->deploy($this->application); + } +} +``` + +### API Controllers +```php +class ApplicationController extends Controller +{ + public function __construct() + { + $this->middleware('auth:sanctum'); + $this->middleware('team.access'); + } + + public function deploy(Application $application): JsonResponse + { + $this->authorize('deploy', $application); + $deployment = app(ApplicationDeploymentService::class)->deploy($application); + return response()->json(['deployment_id' => $deployment->id]); + } +} +``` + +### Queue Jobs +```php +class DeployApplicationJob implements ShouldQueue +{ + public function handle(DockerService $dockerService): void + { + $this->deployment->update(['status' => 'running']); + + try { + $dockerService->deployContainer($this->deployment->application); + $this->deployment->update(['status' => 'success']); + } catch (Exception $e) { + $this->deployment->update(['status' => 'failed']); + throw $e; + } + } +} +``` + +## Testing Patterns + +### Feature Tests +```php +test('user can deploy application via API', function () { + $user = User::factory()->create(); + $application = Application::factory()->create(['team_id' => $user->currentTeam->id]); + + $response = $this->actingAs($user) + ->postJson("/api/v1/applications/{$application->id}/deploy"); + + $response->assertStatus(200); + expect($application->deployments()->count())->toBe(1); +}); +``` + +### Browser Tests +```php +test('user can create application through UI', function () { + $user = User::factory()->create(); + + $this->browse(function (Browser $browser) use ($user) { + $browser->loginAs($user) + ->visit('/applications/create') + ->type('name', 'Test App') + ->press('Create Application') + ->assertSee('Application created successfully'); + }); +}); +``` + +## Security Considerations + +### Authentication +- Multi-provider OAuth support +- API token authentication +- Team-based access control +- Session management + +### Data Protection +- Encrypted environment variables +- Secure SSH key storage +- Input validation and sanitization +- SQL injection prevention + +### Container Security +- Non-root container users +- Minimal capabilities +- Read-only filesystems +- Network isolation + +## Performance Optimization + +### Database +- Eager loading relationships +- Query optimization +- Connection pooling +- Caching strategies + +### Frontend +- Lazy loading components +- Asset optimization +- CDN integration +- Real-time updates via WebSockets + +## Contributing Guidelines + +### Code Standards +- PSR-12 PHP coding standards +- Laravel best practices +- Comprehensive test coverage +- Security-first approach + +### Pull Request Process +1. Fork repository +2. Create feature branch +3. Implement with tests +4. Run quality checks +5. Submit PR with clear description + +## Useful Commands + +### Development +```bash +# Start development environment +docker-compose -f docker-compose.dev.yml up -d + +# Run tests +./vendor/bin/pest + +# Code formatting +./vendor/bin/pint + +# Frontend development +npm run dev +``` + +### Production +```bash +# Install Coolify +curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash + +# Update Coolify +./scripts/upgrade.sh +``` + +## Resources + +### Documentation +- **[README.md](mdc:README.md)** - Project overview and installation +- **[CONTRIBUTING.md](mdc:CONTRIBUTING.md)** - Contribution guidelines +- **[CHANGELOG.md](mdc:CHANGELOG.md)** - Release history +- **[TECH_STACK.md](mdc:TECH_STACK.md)** - Technology overview + +### Configuration +- **[config/](mdc:config)** - Laravel configuration files +- **[database/migrations/](mdc:database/migrations)** - Database schema +- **[tests/](mdc:tests)** - Test suite + +This comprehensive rule set provides everything needed to understand, develop, and contribute to the Coolify project effectively. Each rule focuses on specific aspects while maintaining connections to the broader architecture. diff --git a/.cursor/rules/api-and-routing.mdc b/.cursor/rules/api-and-routing.mdc new file mode 100644 index 0000000000..8321205ac2 --- /dev/null +++ b/.cursor/rules/api-and-routing.mdc @@ -0,0 +1,474 @@ +--- +description: RESTful API design, routing patterns, webhooks, and HTTP communication +globs: routes/*.php, app/Http/Controllers/**/*.php, app/Http/Resources/*.php, app/Http/Requests/*.php +alwaysApply: false +--- +# Coolify API & Routing Architecture + +## Routing Structure + +Coolify implements **multi-layered routing** with web interfaces, RESTful APIs, webhook endpoints, and real-time communication channels. + +## Route Files + +### Core Route Definitions +- **[routes/web.php](mdc:routes/web.php)** - Web application routes (21KB, 362 lines) +- **[routes/api.php](mdc:routes/api.php)** - RESTful API endpoints (13KB, 185 lines) +- **[routes/webhooks.php](mdc:routes/webhooks.php)** - Webhook receivers (815B, 22 lines) +- **[routes/channels.php](mdc:routes/channels.php)** - WebSocket channel definitions (829B, 33 lines) +- **[routes/console.php](mdc:routes/console.php)** - Artisan command routes (592B, 20 lines) + +## Web Application Routing + +### Authentication Routes +```php +// Laravel Fortify authentication +Route::middleware('guest')->group(function () { + Route::get('/login', [AuthController::class, 'login']); + Route::get('/register', [AuthController::class, 'register']); + Route::get('/forgot-password', [AuthController::class, 'forgotPassword']); +}); +``` + +### Dashboard & Core Features +```php +// Main application routes +Route::middleware(['auth', 'verified'])->group(function () { + Route::get('/dashboard', Dashboard::class)->name('dashboard'); + Route::get('/projects', ProjectIndex::class)->name('projects'); + Route::get('/servers', ServerIndex::class)->name('servers'); + Route::get('/teams', TeamIndex::class)->name('teams'); +}); +``` + +### Resource Management Routes +```php +// Server management +Route::prefix('servers')->group(function () { + Route::get('/{server}', ServerShow::class)->name('server.show'); + Route::get('/{server}/edit', ServerEdit::class)->name('server.edit'); + Route::get('/{server}/logs', ServerLogs::class)->name('server.logs'); +}); + +// Application management +Route::prefix('applications')->group(function () { + Route::get('/{application}', ApplicationShow::class)->name('application.show'); + Route::get('/{application}/deployments', ApplicationDeployments::class); + Route::get('/{application}/environment-variables', ApplicationEnvironmentVariables::class); + Route::get('/{application}/logs', ApplicationLogs::class); +}); +``` + +## RESTful API Architecture + +### API Versioning +```php +// API route structure +Route::prefix('v1')->group(function () { + // Application endpoints + Route::apiResource('applications', ApplicationController::class); + Route::apiResource('servers', ServerController::class); + Route::apiResource('teams', TeamController::class); +}); +``` + +### Authentication & Authorization +```php +// Sanctum API authentication +Route::middleware('auth:sanctum')->group(function () { + Route::get('/user', function (Request $request) { + return $request->user(); + }); + + // Team-scoped resources + Route::middleware('team.access')->group(function () { + Route::apiResource('applications', ApplicationController::class); + }); +}); +``` + +### Application Management API +```php +// Application CRUD operations +Route::prefix('applications')->group(function () { + Route::get('/', [ApplicationController::class, 'index']); + Route::post('/', [ApplicationController::class, 'store']); + Route::get('/{application}', [ApplicationController::class, 'show']); + Route::patch('/{application}', [ApplicationController::class, 'update']); + Route::delete('/{application}', [ApplicationController::class, 'destroy']); + + // Deployment operations + Route::post('/{application}/deploy', [ApplicationController::class, 'deploy']); + Route::post('/{application}/restart', [ApplicationController::class, 'restart']); + Route::post('/{application}/stop', [ApplicationController::class, 'stop']); + Route::get('/{application}/logs', [ApplicationController::class, 'logs']); +}); +``` + +### Server Management API +```php +// Server operations +Route::prefix('servers')->group(function () { + Route::get('/', [ServerController::class, 'index']); + Route::post('/', [ServerController::class, 'store']); + Route::get('/{server}', [ServerController::class, 'show']); + Route::patch('/{server}', [ServerController::class, 'update']); + Route::delete('/{server}', [ServerController::class, 'destroy']); + + // Server actions + Route::post('/{server}/validate', [ServerController::class, 'validate']); + Route::get('/{server}/usage', [ServerController::class, 'usage']); + Route::post('/{server}/cleanup', [ServerController::class, 'cleanup']); +}); +``` + +### Database Management API +```php +// Database operations +Route::prefix('databases')->group(function () { + Route::get('/', [DatabaseController::class, 'index']); + Route::post('/', [DatabaseController::class, 'store']); + Route::get('/{database}', [DatabaseController::class, 'show']); + Route::patch('/{database}', [DatabaseController::class, 'update']); + Route::delete('/{database}', [DatabaseController::class, 'destroy']); + + // Database actions + Route::post('/{database}/backup', [DatabaseController::class, 'backup']); + Route::post('/{database}/restore', [DatabaseController::class, 'restore']); + Route::get('/{database}/logs', [DatabaseController::class, 'logs']); +}); +``` + +## Webhook Architecture + +### Git Integration Webhooks +```php +// GitHub webhook endpoints +Route::post('/webhooks/github/{application}', [GitHubWebhookController::class, 'handle']) + ->name('webhooks.github'); + +// GitLab webhook endpoints +Route::post('/webhooks/gitlab/{application}', [GitLabWebhookController::class, 'handle']) + ->name('webhooks.gitlab'); + +// Generic Git webhooks +Route::post('/webhooks/git/{application}', [GitWebhookController::class, 'handle']) + ->name('webhooks.git'); +``` + +### Deployment Webhooks +```php +// Deployment status webhooks +Route::post('/webhooks/deployment/{deployment}/success', [DeploymentWebhookController::class, 'success']); +Route::post('/webhooks/deployment/{deployment}/failure', [DeploymentWebhookController::class, 'failure']); +Route::post('/webhooks/deployment/{deployment}/progress', [DeploymentWebhookController::class, 'progress']); +``` + +### Third-Party Integration Webhooks +```php +// Monitoring webhooks +Route::post('/webhooks/monitoring/{server}', [MonitoringWebhookController::class, 'handle']); + +// Backup status webhooks +Route::post('/webhooks/backup/{backup}', [BackupWebhookController::class, 'handle']); + +// SSL certificate webhooks +Route::post('/webhooks/ssl/{certificate}', [SslWebhookController::class, 'handle']); +``` + +## WebSocket Channel Definitions + +### Real-Time Channels +```php +// Private channels for team members +Broadcast::channel('team.{teamId}', function ($user, $teamId) { + return $user->teams->contains('id', $teamId); +}); + +// Application deployment channels +Broadcast::channel('application.{applicationId}', function ($user, $applicationId) { + return $user->hasAccessToApplication($applicationId); +}); + +// Server monitoring channels +Broadcast::channel('server.{serverId}', function ($user, $serverId) { + return $user->hasAccessToServer($serverId); +}); +``` + +### Presence Channels +```php +// Team collaboration presence +Broadcast::channel('team.{teamId}.presence', function ($user, $teamId) { + if ($user->teams->contains('id', $teamId)) { + return ['id' => $user->id, 'name' => $user->name]; + } +}); +``` + +## API Controllers + +### Location: [app/Http/Controllers/Api/](mdc:app/Http/Controllers) + +#### Resource Controllers +```php +class ApplicationController extends Controller +{ + public function index(Request $request) + { + return ApplicationResource::collection( + $request->user()->currentTeam->applications() + ->with(['server', 'environment']) + ->paginate() + ); + } + + public function store(StoreApplicationRequest $request) + { + $application = $request->user()->currentTeam + ->applications() + ->create($request->validated()); + + return new ApplicationResource($application); + } + + public function deploy(Application $application) + { + $deployment = $application->deploy(); + + return response()->json([ + 'message' => 'Deployment started', + 'deployment_id' => $deployment->id + ]); + } +} +``` + +### API Responses & Resources +```php +// API Resource classes +class ApplicationResource extends JsonResource +{ + public function toArray($request) + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'fqdn' => $this->fqdn, + 'status' => $this->status, + 'git_repository' => $this->git_repository, + 'git_branch' => $this->git_branch, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + 'server' => new ServerResource($this->whenLoaded('server')), + 'environment' => new EnvironmentResource($this->whenLoaded('environment')), + ]; + } +} +``` + +## API Authentication + +### Sanctum Token Authentication +```php +// API token generation +Route::post('/auth/tokens', function (Request $request) { + $request->validate([ + 'name' => 'required|string', + 'abilities' => 'array' + ]); + + $token = $request->user()->createToken( + $request->name, + $request->abilities ?? [] + ); + + return response()->json([ + 'token' => $token->plainTextToken, + 'abilities' => $token->accessToken->abilities + ]); +}); +``` + +### Team-Based Authorization +```php +// Team access middleware +class EnsureTeamAccess +{ + public function handle($request, Closure $next) + { + $teamId = $request->route('team'); + + if (!$request->user()->teams->contains('id', $teamId)) { + abort(403, 'Access denied to team resources'); + } + + return $next($request); + } +} +``` + +## Rate Limiting + +### API Rate Limits +```php +// API throttling configuration +RateLimiter::for('api', function (Request $request) { + return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); +}); + +// Deployment rate limiting +RateLimiter::for('deployments', function (Request $request) { + return Limit::perMinute(10)->by($request->user()->id); +}); +``` + +### Webhook Rate Limiting +```php +// Webhook throttling +RateLimiter::for('webhooks', function (Request $request) { + return Limit::perMinute(100)->by($request->ip()); +}); +``` + +## Route Model Binding + +### Custom Route Bindings +```php +// Custom model binding for applications +Route::bind('application', function ($value) { + return Application::where('uuid', $value) + ->orWhere('id', $value) + ->firstOrFail(); +}); + +// Team-scoped model binding +Route::bind('team_application', function ($value, $route) { + $teamId = $route->parameter('team'); + return Application::whereHas('environment.project', function ($query) use ($teamId) { + $query->where('team_id', $teamId); + })->findOrFail($value); +}); +``` + +## API Documentation + +### OpenAPI Specification +- **[openapi.json](mdc:openapi.json)** - API documentation (373KB, 8316 lines) +- **[openapi.yaml](mdc:openapi.yaml)** - YAML format documentation (184KB, 5579 lines) + +### Documentation Generation +```php +// Swagger/OpenAPI annotations +/** + * @OA\Get( + * path="/api/v1/applications", + * summary="List applications", + * tags={"Applications"}, + * security={{"bearerAuth":{}}}, + * @OA\Response( + * response=200, + * description="List of applications", + * @OA\JsonContent(type="array", @OA\Items(ref="#/components/schemas/Application")) + * ) + * ) + */ +``` + +## Error Handling + +### API Error Responses +```php +// Standardized error response format +class ApiExceptionHandler +{ + public function render($request, Throwable $exception) + { + if ($request->expectsJson()) { + return response()->json([ + 'message' => $exception->getMessage(), + 'error_code' => $this->getErrorCode($exception), + 'timestamp' => now()->toISOString() + ], $this->getStatusCode($exception)); + } + + return parent::render($request, $exception); + } +} +``` + +### Validation Error Handling +```php +// Form request validation +class StoreApplicationRequest extends FormRequest +{ + public function rules() + { + return [ + 'name' => 'required|string|max:255', + 'git_repository' => 'required|url', + 'git_branch' => 'required|string', + 'server_id' => 'required|exists:servers,id', + 'environment_id' => 'required|exists:environments,id' + ]; + } + + public function failedValidation(Validator $validator) + { + throw new HttpResponseException( + response()->json([ + 'message' => 'Validation failed', + 'errors' => $validator->errors() + ], 422) + ); + } +} +``` + +## Real-Time API Integration + +### WebSocket Events +```php +// Broadcasting deployment events +class DeploymentStarted implements ShouldBroadcast +{ + public $application; + public $deployment; + + public function broadcastOn() + { + return [ + new PrivateChannel("application.{$this->application->id}"), + new PrivateChannel("team.{$this->application->team->id}") + ]; + } + + public function broadcastWith() + { + return [ + 'deployment_id' => $this->deployment->id, + 'status' => 'started', + 'timestamp' => now() + ]; + } +} +``` + +### API Event Streaming +```php +// Server-Sent Events for real-time updates +Route::get('/api/v1/applications/{application}/events', function (Application $application) { + return response()->stream(function () use ($application) { + while (true) { + $events = $application->getRecentEvents(); + foreach ($events as $event) { + echo "data: " . json_encode($event) . "\n\n"; + } + usleep(1000000); // 1 second + } + }, 200, [ + 'Content-Type' => 'text/event-stream', + 'Cache-Control' => 'no-cache', + ]); +}); +``` diff --git a/.cursor/rules/application-architecture.mdc b/.cursor/rules/application-architecture.mdc new file mode 100644 index 0000000000..ef8d549ad0 --- /dev/null +++ b/.cursor/rules/application-architecture.mdc @@ -0,0 +1,368 @@ +--- +description: Laravel application structure, patterns, and architectural decisions +globs: app/**/*.php, config/*.php, bootstrap/**/*.php +alwaysApply: false +--- +# Coolify Application Architecture + +## Laravel Project Structure + +### **Core Application Directory** ([app/](mdc:app)) + +``` +app/ +├── Actions/ # Business logic actions (Action pattern) +├── Console/ # Artisan commands +├── Contracts/ # Interface definitions +├── Data/ # Data Transfer Objects (Spatie Laravel Data) +├── Enums/ # Enumeration classes +├── Events/ # Event classes +├── Exceptions/ # Custom exception classes +├── Helpers/ # Utility helper classes +├── Http/ # HTTP layer (Controllers, Middleware, Requests) +├── Jobs/ # Background job classes +├── Listeners/ # Event listeners +├── Livewire/ # Livewire components (Frontend) +├── Models/ # Eloquent models (Domain entities) +├── Notifications/ # Notification classes +├── Policies/ # Authorization policies +├── Providers/ # Service providers +├── Repositories/ # Repository pattern implementations +├── Services/ # Service layer classes +├── Traits/ # Reusable trait classes +└── View/ # View composers and creators +``` + +## Core Domain Models + +### **Infrastructure Management** + +#### **[Server.php](mdc:app/Models/Server.php)** (46KB, 1343 lines) +- **Purpose**: Physical/virtual server management +- **Key Relationships**: + - `hasMany(Application::class)` - Deployed applications + - `hasMany(StandalonePostgresql::class)` - Database instances + - `belongsTo(Team::class)` - Team ownership +- **Key Features**: + - SSH connection management + - Resource monitoring + - Proxy configuration (Traefik/Caddy) + - Docker daemon interaction + +#### **[Application.php](mdc:app/Models/Application.php)** (74KB, 1734 lines) +- **Purpose**: Application deployment and management +- **Key Relationships**: + - `belongsTo(Server::class)` - Deployment target + - `belongsTo(Environment::class)` - Environment context + - `hasMany(ApplicationDeploymentQueue::class)` - Deployment history +- **Key Features**: + - Git repository integration + - Docker build and deployment + - Environment variable management + - SSL certificate handling + +#### **[Service.php](mdc:app/Models/Service.php)** (58KB, 1325 lines) +- **Purpose**: Multi-container service orchestration +- **Key Relationships**: + - `hasMany(ServiceApplication::class)` - Service components + - `hasMany(ServiceDatabase::class)` - Service databases + - `belongsTo(Environment::class)` - Environment context +- **Key Features**: + - Docker Compose generation + - Service dependency management + - Health check configuration + +### **Team & Project Organization** + +#### **[Team.php](mdc:app/Models/Team.php)** (8.9KB, 308 lines) +- **Purpose**: Multi-tenant team management +- **Key Relationships**: + - `hasMany(User::class)` - Team members + - `hasMany(Project::class)` - Team projects + - `hasMany(Server::class)` - Team servers +- **Key Features**: + - Resource limits and quotas + - Team-based access control + - Subscription management + +#### **[Project.php](mdc:app/Models/Project.php)** (4.3KB, 156 lines) +- **Purpose**: Project organization and grouping +- **Key Relationships**: + - `hasMany(Environment::class)` - Project environments + - `belongsTo(Team::class)` - Team ownership +- **Key Features**: + - Environment isolation + - Resource organization + +#### **[Environment.php](mdc:app/Models/Environment.php)** +- **Purpose**: Environment-specific configuration +- **Key Relationships**: + - `hasMany(Application::class)` - Environment applications + - `hasMany(Service::class)` - Environment services + - `belongsTo(Project::class)` - Project context + +### **Database Management Models** + +#### **Standalone Database Models** +- **[StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php)** (11KB, 351 lines) +- **[StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php)** (11KB, 351 lines) +- **[StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php)** (10KB, 337 lines) +- **[StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php)** (12KB, 370 lines) +- **[StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php)** (12KB, 394 lines) +- **[StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php)** (11KB, 347 lines) +- **[StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php)** (11KB, 347 lines) +- **[StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php)** (10KB, 336 lines) + +**Common Features**: +- Database configuration management +- Backup scheduling and execution +- Connection string generation +- Health monitoring + +### **Configuration & Settings** + +#### **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** (7.6KB, 219 lines) +- **Purpose**: Application environment variable management +- **Key Features**: + - Encrypted value storage + - Build-time vs runtime variables + - Shared variable inheritance + +#### **[InstanceSettings.php](mdc:app/Models/InstanceSettings.php)** (3.2KB, 124 lines) +- **Purpose**: Global Coolify instance configuration +- **Key Features**: + - FQDN and port configuration + - Auto-update settings + - Security configurations + +## Architectural Patterns + +### **Action Pattern** ([app/Actions/](mdc:app/Actions)) + +Using [lorisleiva/laravel-actions](mdc:composer.json) for business logic encapsulation: + +```php +// Example Action structure +class DeployApplication extends Action +{ + public function handle(Application $application): void + { + // Business logic for deployment + } + + public function asJob(Application $application): void + { + // Queue job implementation + } +} +``` + +**Key Action Categories**: +- **Application/**: Deployment and management actions +- **Database/**: Database operations +- **Server/**: Server management actions +- **Service/**: Service orchestration actions + +### **Repository Pattern** ([app/Repositories/](mdc:app/Repositories)) + +Data access abstraction layer: +- Encapsulates database queries +- Provides testable data layer +- Abstracts complex query logic + +### **Service Layer** ([app/Services/](mdc:app/Services)) + +Business logic services: +- External API integrations +- Complex business operations +- Cross-cutting concerns + +## Data Flow Architecture + +### **Request Lifecycle** + +1. **HTTP Request** → [routes/web.php](mdc:routes/web.php) +2. **Middleware** → Authentication, authorization +3. **Livewire Component** → [app/Livewire/](mdc:app/Livewire) +4. **Action/Service** → Business logic execution +5. **Model/Repository** → Data persistence +6. **Response** → Livewire reactive update + +### **Background Processing** + +1. **Job Dispatch** → Queue system (Redis) +2. **Job Processing** → [app/Jobs/](mdc:app/Jobs) +3. **Action Execution** → Business logic +4. **Event Broadcasting** → Real-time updates +5. **Notification** → User feedback + +## Security Architecture + +### **Multi-Tenant Isolation** + +```php +// Team-based query scoping +class Application extends Model +{ + public function scopeOwnedByCurrentTeam($query) + { + return $query->whereHas('environment.project.team', function ($q) { + $q->where('id', currentTeam()->id); + }); + } +} +``` + +### **Authorization Layers** + +1. **Team Membership** → User belongs to team +2. **Resource Ownership** → Resource belongs to team +3. **Policy Authorization** → [app/Policies/](mdc:app/Policies) +4. **Environment Isolation** → Project/environment boundaries + +### **Data Protection** + +- **Environment Variables**: Encrypted at rest +- **SSH Keys**: Secure storage and transmission +- **API Tokens**: Sanctum-based authentication +- **Audit Logging**: [spatie/laravel-activitylog](mdc:composer.json) + +## Configuration Hierarchy + +### **Global Configuration** +- **[InstanceSettings](mdc:app/Models/InstanceSettings.php)**: System-wide settings +- **[config/](mdc:config)**: Laravel configuration files + +### **Team Configuration** +- **[Team](mdc:app/Models/Team.php)**: Team-specific settings +- **[ServerSetting](mdc:app/Models/ServerSetting.php)**: Server configurations + +### **Project Configuration** +- **[ProjectSetting](mdc:app/Models/ProjectSetting.php)**: Project settings +- **[Environment](mdc:app/Models/Environment.php)**: Environment variables + +### **Application Configuration** +- **[ApplicationSetting](mdc:app/Models/ApplicationSetting.php)**: App-specific settings +- **[EnvironmentVariable](mdc:app/Models/EnvironmentVariable.php)**: Runtime configuration + +## Event-Driven Architecture + +### **Event Broadcasting** ([app/Events/](mdc:app/Events)) + +Real-time updates using Laravel Echo and WebSockets: + +```php +// Example event structure +class ApplicationDeploymentStarted implements ShouldBroadcast +{ + public function broadcastOn(): array + { + return [ + new PrivateChannel("team.{$this->application->team->id}"), + ]; + } +} +``` + +### **Event Listeners** ([app/Listeners/](mdc:app/Listeners)) + +- Deployment status updates +- Resource monitoring alerts +- Notification dispatching +- Audit log creation + +## Database Design Patterns + +### **Polymorphic Relationships** + +```php +// Environment variables can belong to multiple resource types +class EnvironmentVariable extends Model +{ + public function resource(): MorphTo + { + return $this->morphTo(); + } +} +``` + +### **Team-Based Soft Scoping** + +All major resources include team-based query scoping: + +```php +// Automatic team filtering +$applications = Application::ownedByCurrentTeam()->get(); +$servers = Server::ownedByCurrentTeam()->get(); +``` + +### **Configuration Inheritance** + +Environment variables cascade from: +1. **Shared Variables** → Team-wide defaults +2. **Project Variables** → Project-specific overrides +3. **Application Variables** → Application-specific values + +## Integration Patterns + +### **Git Provider Integration** + +Abstracted git operations supporting: +- **GitHub**: [app/Models/GithubApp.php](mdc:app/Models/GithubApp.php) +- **GitLab**: [app/Models/GitlabApp.php](mdc:app/Models/GitlabApp.php) +- **Bitbucket**: Webhook integration +- **Gitea**: Self-hosted Git support + +### **Docker Integration** + +- **Container Management**: Direct Docker API communication +- **Image Building**: Dockerfile and Buildpack support +- **Network Management**: Custom Docker networks +- **Volume Management**: Persistent storage handling + +### **SSH Communication** + +- **[phpseclib/phpseclib](mdc:composer.json)**: Secure SSH connections +- **Multiplexing**: Connection pooling for efficiency +- **Key Management**: [PrivateKey](mdc:app/Models/PrivateKey.php) model + +## Testing Architecture + +### **Test Structure** ([tests/](mdc:tests)) + +``` +tests/ +├── Feature/ # Integration tests +├── Unit/ # Unit tests +├── Browser/ # Dusk browser tests +├── Traits/ # Test helper traits +├── Pest.php # Pest configuration +└── TestCase.php # Base test case +``` + +### **Testing Patterns** + +- **Feature Tests**: Full request lifecycle testing +- **Unit Tests**: Individual class/method testing +- **Browser Tests**: End-to-end user workflows +- **Database Testing**: Factories and seeders + +## Performance Considerations + +### **Query Optimization** + +- **Eager Loading**: Prevent N+1 queries +- **Query Scoping**: Team-based filtering +- **Database Indexing**: Optimized for common queries + +### **Caching Strategy** + +- **Redis**: Session and cache storage +- **Model Caching**: Frequently accessed data +- **Query Caching**: Expensive query results + +### **Background Processing** + +- **Queue Workers**: Horizon-managed job processing +- **Job Batching**: Related job grouping +- **Failed Job Handling**: Automatic retry logic diff --git a/.cursor/rules/cursor_rules.mdc b/.cursor/rules/cursor_rules.mdc new file mode 100644 index 0000000000..9edccd496f --- /dev/null +++ b/.cursor/rules/cursor_rules.mdc @@ -0,0 +1,59 @@ +--- +description: Guidelines for creating and maintaining Cursor rules to ensure consistency and effectiveness. +globs: .cursor/rules/*.mdc +alwaysApply: true +--- + +# Cursor Rules Maintenance Guide + +> **Important**: These rules in `.cursor/rules/` are shared between Cursor IDE and other AI assistants. Changes here should be reflected in **[CLAUDE.md](mdc:CLAUDE.md)** when they affect core workflows or patterns. +> +> **Synchronization Guide**: See **[.AI_INSTRUCTIONS_SYNC.md](mdc:.AI_INSTRUCTIONS_SYNC.md)** for detailed guidelines on maintaining consistency between CLAUDE.md and .cursor/rules/. + +- **Required Rule Structure:** + ```markdown + --- + description: Clear, one-line description of what the rule enforces + globs: path/to/files/*.ext, other/path/**/* + alwaysApply: boolean + --- + + - **Main Points in Bold** + - Sub-points with details + - Examples and explanations + ``` + +- **File References:** + - Use `[filename](mdc:path/to/file)` ([filename](mdc:filename)) to reference files + - Example: [prisma.mdc](mdc:.cursor/rules/prisma.mdc) for rule references + - Example: [schema.prisma](mdc:prisma/schema.prisma) for code references + +- **Code Examples:** + - Use language-specific code blocks + ```typescript + // ✅ DO: Show good examples + const goodExample = true; + + // ❌ DON'T: Show anti-patterns + const badExample = false; + ``` + +- **Rule Content Guidelines:** + - Start with high-level overview + - Include specific, actionable requirements + - Show examples of correct implementation + - Reference existing code when possible + - Keep rules DRY by referencing other rules + +- **Rule Maintenance:** + - Update rules when new patterns emerge + - Add examples from actual codebase + - Remove outdated patterns + - Cross-reference related rules + +- **Best Practices:** + - Use bullet points for clarity + - Keep descriptions concise + - Include both DO and DON'T examples + - Reference actual code over theoretical examples + - Use consistent formatting across rules \ No newline at end of file diff --git a/.cursor/rules/database-patterns.mdc b/.cursor/rules/database-patterns.mdc new file mode 100644 index 0000000000..ec60a43b39 --- /dev/null +++ b/.cursor/rules/database-patterns.mdc @@ -0,0 +1,329 @@ +--- +description: Database architecture, models, migrations, relationships, and data management patterns +globs: app/Models/*.php, database/migrations/*.php, database/seeders/*.php, app/Actions/Database/*.php +alwaysApply: false +--- +# Coolify Database Architecture & Patterns + +## Database Strategy + +Coolify uses **PostgreSQL 15** as the primary database with **Redis 7** for caching and real-time features. The architecture supports managing multiple external databases across different servers. + +## Primary Database (PostgreSQL) + +### Core Tables & Models + +#### User & Team Management +- **[User.php](mdc:app/Models/User.php)** - User authentication and profiles +- **[Team.php](mdc:app/Models/Team.php)** - Multi-tenant organization structure +- **[TeamInvitation.php](mdc:app/Models/TeamInvitation.php)** - Team collaboration invitations +- **[PersonalAccessToken.php](mdc:app/Models/PersonalAccessToken.php)** - API token management + +#### Infrastructure Management +- **[Server.php](mdc:app/Models/Server.php)** - Physical/virtual server definitions (46KB, complex) +- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - SSH key management +- **[ServerSetting.php](mdc:app/Models/ServerSetting.php)** - Server-specific configurations + +#### Project Organization +- **[Project.php](mdc:app/Models/Project.php)** - Project containers for applications +- **[Environment.php](mdc:app/Models/Environment.php)** - Environment isolation (staging, production, etc.) +- **[ProjectSetting.php](mdc:app/Models/ProjectSetting.php)** - Project-specific settings + +#### Application Deployment +- **[Application.php](mdc:app/Models/Application.php)** - Main application entity (74KB, highly complex) +- **[ApplicationSetting.php](mdc:app/Models/ApplicationSetting.php)** - Application configurations +- **[ApplicationDeploymentQueue.php](mdc:app/Models/ApplicationDeploymentQueue.php)** - Deployment orchestration +- **[ApplicationPreview.php](mdc:app/Models/ApplicationPreview.php)** - Preview environment management + +#### Service Management +- **[Service.php](mdc:app/Models/Service.php)** - Service definitions (58KB, complex) +- **[ServiceApplication.php](mdc:app/Models/ServiceApplication.php)** - Service components +- **[ServiceDatabase.php](mdc:app/Models/ServiceDatabase.php)** - Service-attached databases + +## Database Type Support + +### Standalone Database Models +Each database type has its own dedicated model with specific configurations: + +#### SQL Databases +- **[StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php)** - PostgreSQL instances +- **[StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php)** - MySQL instances +- **[StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php)** - MariaDB instances + +#### NoSQL & Analytics +- **[StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php)** - MongoDB instances +- **[StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php)** - ClickHouse analytics + +#### Caching & In-Memory +- **[StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php)** - Redis instances +- **[StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php)** - KeyDB instances +- **[StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php)** - Dragonfly instances + +## Configuration Management + +### Environment Variables +- **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** - Application-specific environment variables +- **[SharedEnvironmentVariable.php](mdc:app/Models/SharedEnvironmentVariable.php)** - Shared across applications + +### Settings Hierarchy +- **[InstanceSettings.php](mdc:app/Models/InstanceSettings.php)** - Global Coolify instance settings +- **[ServerSetting.php](mdc:app/Models/ServerSetting.php)** - Server-specific settings +- **[ProjectSetting.php](mdc:app/Models/ProjectSetting.php)** - Project-level settings +- **[ApplicationSetting.php](mdc:app/Models/ApplicationSetting.php)** - Application settings + +## Storage & Backup Systems + +### Storage Management +- **[S3Storage.php](mdc:app/Models/S3Storage.php)** - S3-compatible storage configurations +- **[LocalFileVolume.php](mdc:app/Models/LocalFileVolume.php)** - Local filesystem volumes +- **[LocalPersistentVolume.php](mdc:app/Models/LocalPersistentVolume.php)** - Persistent volume management + +### Backup Infrastructure +- **[ScheduledDatabaseBackup.php](mdc:app/Models/ScheduledDatabaseBackup.php)** - Automated backup scheduling +- **[ScheduledDatabaseBackupExecution.php](mdc:app/Models/ScheduledDatabaseBackupExecution.php)** - Backup execution tracking + +### Task Scheduling +- **[ScheduledTask.php](mdc:app/Models/ScheduledTask.php)** - Cron job management +- **[ScheduledTaskExecution.php](mdc:app/Models/ScheduledTaskExecution.php)** - Task execution history + +## Notification & Integration Models + +### Notification Channels +- **[EmailNotificationSettings.php](mdc:app/Models/EmailNotificationSettings.php)** - Email notifications +- **[DiscordNotificationSettings.php](mdc:app/Models/DiscordNotificationSettings.php)** - Discord integration +- **[SlackNotificationSettings.php](mdc:app/Models/SlackNotificationSettings.php)** - Slack integration +- **[TelegramNotificationSettings.php](mdc:app/Models/TelegramNotificationSettings.php)** - Telegram bot +- **[PushoverNotificationSettings.php](mdc:app/Models/PushoverNotificationSettings.php)** - Pushover notifications + +### Source Control Integration +- **[GithubApp.php](mdc:app/Models/GithubApp.php)** - GitHub App integration +- **[GitlabApp.php](mdc:app/Models/GitlabApp.php)** - GitLab integration + +### OAuth & Authentication +- **[OauthSetting.php](mdc:app/Models/OauthSetting.php)** - OAuth provider configurations + +## Docker & Container Management + +### Container Orchestration +- **[StandaloneDocker.php](mdc:app/Models/StandaloneDocker.php)** - Standalone Docker containers +- **[SwarmDocker.php](mdc:app/Models/SwarmDocker.php)** - Docker Swarm management + +### SSL & Security +- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate management + +## Database Migration Strategy + +### Migration Location: [database/migrations/](mdc:database/migrations) + +#### Migration Patterns +```php +// Typical Coolify migration structure +Schema::create('applications', function (Blueprint $table) { + $table->id(); + $table->string('name'); + $table->string('fqdn')->nullable(); + $table->json('environment_variables')->nullable(); + $table->foreignId('destination_id'); + $table->foreignId('source_id'); + $table->timestamps(); +}); +``` + +### Schema Versioning +- **Incremental migrations** for database evolution +- **Data migrations** for complex transformations +- **Rollback support** for deployment safety + +## Eloquent Model Patterns + +### Base Model Structure +- **[BaseModel.php](mdc:app/Models/BaseModel.php)** - Common model functionality +- **UUID primary keys** for distributed systems +- **Soft deletes** for audit trails +- **Activity logging** with Spatie package + +### **CRITICAL: Mass Assignment Protection** +**When adding new database columns, you MUST update the model's `$fillable` array.** Without this, Laravel will silently ignore mass assignment operations like `Model::create()` or `$model->update()`. + +**Checklist for new columns:** +1. ✅ Create migration file +2. ✅ Run migration +3. ✅ **Add column to model's `$fillable` array** +4. ✅ Update any Livewire components that sync this property +5. ✅ Test that the column can be read and written + +**Example:** +```php +class Server extends BaseModel +{ + protected $fillable = [ + 'name', + 'ip', + 'port', + 'is_validating', // ← MUST add new columns here + ]; +} +``` + +### Relationship Patterns +```php +// Typical relationship structure in Application model +class Application extends Model +{ + public function server() + { + return $this->belongsTo(Server::class); + } + + public function environment() + { + return $this->belongsTo(Environment::class); + } + + public function deployments() + { + return $this->hasMany(ApplicationDeploymentQueue::class); + } + + public function environmentVariables() + { + return $this->hasMany(EnvironmentVariable::class); + } +} +``` + +### Model Traits +```php +// Common traits used across models +use SoftDeletes; +use LogsActivity; +use HasFactory; +use HasUuids; +``` + +## Caching Strategy (Redis) + +### Cache Usage Patterns +- **Session storage** - User authentication sessions +- **Queue backend** - Background job processing +- **Model caching** - Expensive query results +- **Real-time data** - WebSocket state management + +### Cache Keys Structure +``` +coolify:session:{session_id} +coolify:server:{server_id}:status +coolify:deployment:{deployment_id}:logs +coolify:user:{user_id}:teams +``` + +## Query Optimization Patterns + +### Eager Loading +```php +// Optimized queries with relationships +$applications = Application::with([ + 'server', + 'environment.project', + 'environmentVariables', + 'deployments' => function ($query) { + $query->latest()->limit(5); + } +])->get(); +``` + +### Chunking for Large Datasets +```php +// Processing large datasets efficiently +Server::chunk(100, function ($servers) { + foreach ($servers as $server) { + // Process server monitoring + } +}); +``` + +### Database Indexes +- **Primary keys** on all tables +- **Foreign key indexes** for relationships +- **Composite indexes** for common queries +- **Unique constraints** for business rules + +## Data Consistency Patterns + +### Database Transactions +```php +// Atomic operations for deployment +DB::transaction(function () { + $application = Application::create($data); + $application->environmentVariables()->createMany($envVars); + $application->deployments()->create(['status' => 'queued']); +}); +``` + +### Model Events +```php +// Automatic cleanup on model deletion +class Application extends Model +{ + protected static function booted() + { + static::deleting(function ($application) { + $application->environmentVariables()->delete(); + $application->deployments()->delete(); + }); + } +} +``` + +## Backup & Recovery + +### Database Backup Strategy +- **Automated PostgreSQL backups** via scheduled tasks +- **Point-in-time recovery** capability +- **Cross-region backup** replication +- **Backup verification** and testing + +### Data Export/Import +- **Application configurations** export/import +- **Environment variable** bulk operations +- **Server configurations** backup and restore + +## Performance Monitoring + +### Query Performance +- **Laravel Telescope** for development debugging +- **Slow query logging** in production +- **Database connection** pooling +- **Read replica** support for scaling + +### Metrics Collection +- **Database size** monitoring +- **Connection count** tracking +- **Query execution time** analysis +- **Cache hit rates** monitoring + +## Multi-Tenancy Pattern + +### Team-Based Isolation +```php +// Global scope for team-based filtering +class Application extends Model +{ + protected static function booted() + { + static::addGlobalScope('team', function (Builder $builder) { + if (auth()->user()) { + $builder->whereHas('environment.project', function ($query) { + $query->where('team_id', auth()->user()->currentTeam->id); + }); + } + }); + } +} +``` + +### Data Separation +- **Team-scoped queries** by default +- **Cross-team access** controls +- **Admin access** patterns +- **Data isolation** guarantees diff --git a/.cursor/rules/deployment-architecture.mdc b/.cursor/rules/deployment-architecture.mdc new file mode 100644 index 0000000000..35ae6699b1 --- /dev/null +++ b/.cursor/rules/deployment-architecture.mdc @@ -0,0 +1,310 @@ +--- +description: Docker orchestration, deployment workflows, and containerization patterns +globs: app/Jobs/*.php, app/Actions/Application/*.php, app/Actions/Server/*.php, docker/*.*, *.yml, *.yaml +alwaysApply: false +--- +# Coolify Deployment Architecture + +## Deployment Philosophy + +Coolify orchestrates **Docker-based deployments** across multiple servers with automated configuration generation, zero-downtime deployments, and comprehensive monitoring. + +## Core Deployment Components + +### Deployment Models +- **[Application.php](mdc:app/Models/Application.php)** - Main application entity with deployment configurations +- **[ApplicationDeploymentQueue.php](mdc:app/Models/ApplicationDeploymentQueue.php)** - Deployment job orchestration +- **[Service.php](mdc:app/Models/Service.php)** - Multi-container service definitions +- **[Server.php](mdc:app/Models/Server.php)** - Target deployment infrastructure + +### Infrastructure Management +- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - SSH key management for secure server access +- **[StandaloneDocker.php](mdc:app/Models/StandaloneDocker.php)** - Single container deployments +- **[SwarmDocker.php](mdc:app/Models/SwarmDocker.php)** - Docker Swarm orchestration + +## Deployment Workflow + +### 1. Source Code Integration +``` +Git Repository → Webhook → Coolify → Build & Deploy +``` + +#### Source Control Models +- **[GithubApp.php](mdc:app/Models/GithubApp.php)** - GitHub integration and webhooks +- **[GitlabApp.php](mdc:app/Models/GitlabApp.php)** - GitLab CI/CD integration + +#### Deployment Triggers +- **Git push** to configured branches +- **Manual deployment** via UI +- **Scheduled deployments** via cron +- **API-triggered** deployments + +### 2. Build Process +``` +Source Code → Docker Build → Image Registry → Deployment +``` + +#### Build Configurations +- **Dockerfile detection** and custom Dockerfile support +- **Buildpack integration** for framework detection +- **Multi-stage builds** for optimization +- **Cache layer** management for faster builds + +### 3. Deployment Orchestration +``` +Queue Job → Configuration Generation → Container Deployment → Health Checks +``` + +## Deployment Actions + +### Location: [app/Actions/](mdc:app/Actions) + +#### Application Deployment Actions +- **Application/** - Core application deployment logic +- **Docker/** - Docker container management +- **Service/** - Multi-container service orchestration +- **Proxy/** - Reverse proxy configuration + +#### Database Actions +- **Database/** - Database deployment and management +- Automated backup scheduling +- Connection management and health checks + +#### Server Management Actions +- **Server/** - Server provisioning and configuration +- SSH connection establishment +- Docker daemon management + +## Configuration Generation + +### Dynamic Configuration +- **[ConfigurationGenerator.php](mdc:app/Services/ConfigurationGenerator.php)** - Generates deployment configurations +- **[ConfigurationRepository.php](mdc:app/Services/ConfigurationRepository.php)** - Configuration management + +### Generated Configurations +#### Docker Compose Files +```yaml +# Generated docker-compose.yml structure +version: '3.8' +services: + app: + image: ${APP_IMAGE} + environment: + - ${ENV_VARIABLES} + labels: + - traefik.enable=true + - traefik.http.routers.app.rule=Host(`${FQDN}`) + volumes: + - ${VOLUME_MAPPINGS} + networks: + - coolify +``` + +#### Nginx Configurations +- **Reverse proxy** setup +- **SSL termination** with automatic certificates +- **Load balancing** for multiple instances +- **Custom headers** and routing rules + +## Container Orchestration + +### Docker Integration +- **[DockerImageParser.php](mdc:app/Services/DockerImageParser.php)** - Parse and validate Docker images +- **Container lifecycle** management +- **Resource allocation** and limits +- **Network isolation** and communication + +### Volume Management +- **[LocalFileVolume.php](mdc:app/Models/LocalFileVolume.php)** - Persistent file storage +- **[LocalPersistentVolume.php](mdc:app/Models/LocalPersistentVolume.php)** - Data persistence +- **Backup integration** for volume data + +### Network Configuration +- **Custom Docker networks** for isolation +- **Service discovery** between containers +- **Port mapping** and exposure +- **SSL/TLS termination** + +## Environment Management + +### Environment Isolation +- **[Environment.php](mdc:app/Models/Environment.php)** - Development, staging, production environments +- **[EnvironmentVariable.php](mdc:app/Models/EnvironmentVariable.php)** - Application-specific variables +- **[SharedEnvironmentVariable.php](mdc:app/Models/SharedEnvironmentVariable.php)** - Cross-application variables + +### Configuration Hierarchy +``` +Instance Settings → Server Settings → Project Settings → Application Settings +``` + +## Preview Environments + +### Git-Based Previews +- **[ApplicationPreview.php](mdc:app/Models/ApplicationPreview.php)** - Preview environment management +- **Automatic PR/MR previews** for feature branches +- **Isolated environments** for testing +- **Automatic cleanup** after merge/close + +### Preview Workflow +``` +Feature Branch → Auto-Deploy → Preview URL → Review → Cleanup +``` + +## SSL & Security + +### Certificate Management +- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate automation +- **Let's Encrypt** integration for free certificates +- **Custom certificate** upload support +- **Automatic renewal** and monitoring + +### Security Patterns +- **Private Docker networks** for container isolation +- **SSH key-based** server authentication +- **Environment variable** encryption +- **Access control** via team permissions + +## Backup & Recovery + +### Database Backups +- **[ScheduledDatabaseBackup.php](mdc:app/Models/ScheduledDatabaseBackup.php)** - Automated database backups +- **[ScheduledDatabaseBackupExecution.php](mdc:app/Models/ScheduledDatabaseBackupExecution.php)** - Backup execution tracking +- **S3-compatible storage** for backup destinations + +### Application Backups +- **Volume snapshots** for persistent data +- **Configuration export** for disaster recovery +- **Cross-region replication** for high availability + +## Monitoring & Logging + +### Real-Time Monitoring +- **[ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php)** - Live deployment monitoring +- **WebSocket-based** log streaming +- **Container health checks** and alerts +- **Resource usage** tracking + +### Deployment Logs +- **Build process** logging +- **Container startup** logs +- **Application runtime** logs +- **Error tracking** and alerting + +## Queue System + +### Background Jobs +Location: [app/Jobs/](mdc:app/Jobs) +- **Deployment jobs** for async processing +- **Server monitoring** jobs +- **Backup scheduling** jobs +- **Notification delivery** jobs + +### Queue Processing +- **Redis-backed** job queues +- **Laravel Horizon** for queue monitoring +- **Failed job** retry mechanisms +- **Queue worker** auto-scaling + +## Multi-Server Deployment + +### Server Types +- **Standalone servers** - Single Docker host +- **Docker Swarm** - Multi-node orchestration +- **Remote servers** - SSH-based deployment +- **Local development** - Docker Desktop integration + +### Load Balancing +- **Traefik integration** for automatic load balancing +- **Health check** based routing +- **Blue-green deployments** for zero downtime +- **Rolling updates** with configurable strategies + +## Deployment Strategies + +### Zero-Downtime Deployment +``` +Old Container → New Container Build → Health Check → Traffic Switch → Old Container Cleanup +``` + +### Blue-Green Deployment +- **Parallel environments** for safe deployments +- **Instant rollback** capability +- **Database migration** handling +- **Configuration synchronization** + +### Rolling Updates +- **Gradual instance** replacement +- **Configurable update** strategy +- **Automatic rollback** on failure +- **Health check** validation + +## API Integration + +### Deployment API +Routes: [routes/api.php](mdc:routes/api.php) +- **RESTful endpoints** for deployment management +- **Webhook receivers** for CI/CD integration +- **Status reporting** endpoints +- **Deployment triggering** via API + +### Authentication +- **Laravel Sanctum** API tokens +- **Team-based** access control +- **Rate limiting** for API calls +- **Audit logging** for API usage + +## Error Handling & Recovery + +### Deployment Failure Recovery +- **Automatic rollback** on deployment failure +- **Health check** failure handling +- **Container crash** recovery +- **Resource exhaustion** protection + +### Monitoring & Alerting +- **Failed deployment** notifications +- **Resource threshold** alerts +- **SSL certificate** expiry warnings +- **Backup failure** notifications + +## Performance Optimization + +### Build Optimization +- **Docker layer** caching +- **Multi-stage builds** for smaller images +- **Build artifact** reuse +- **Parallel build** processing + +### Runtime Optimization +- **Container resource** limits +- **Auto-scaling** based on metrics +- **Connection pooling** for databases +- **CDN integration** for static assets + +## Compliance & Governance + +### Audit Trail +- **Deployment history** tracking +- **Configuration changes** logging +- **User action** auditing +- **Resource access** monitoring + +### Backup Compliance +- **Retention policies** for backups +- **Encryption at rest** for sensitive data +- **Cross-region** backup replication +- **Recovery testing** automation + +## Integration Patterns + +### CI/CD Integration +- **GitHub Actions** compatibility +- **GitLab CI** pipeline integration +- **Custom webhook** endpoints +- **Build status** reporting + +### External Services +- **S3-compatible** storage integration +- **External database** connections +- **Third-party monitoring** tools +- **Custom notification** channels diff --git a/.cursor/rules/dev_workflow.mdc b/.cursor/rules/dev_workflow.mdc new file mode 100644 index 0000000000..003251d8a0 --- /dev/null +++ b/.cursor/rules/dev_workflow.mdc @@ -0,0 +1,219 @@ +--- +description: Guide for using Task Master to manage task-driven development workflows +globs: **/* +alwaysApply: true +--- +# Task Master Development Workflow + +This guide outlines the typical process for using Task Master to manage software development projects. + +## Primary Interaction: MCP Server vs. CLI + +Task Master offers two primary ways to interact: + +1. **MCP Server (Recommended for Integrated Tools)**: + - For AI agents and integrated development environments (like Cursor), interacting via the **MCP server is the preferred method**. + - The MCP server exposes Task Master functionality through a set of tools (e.g., `get_tasks`, `add_subtask`). + - This method offers better performance, structured data exchange, and richer error handling compared to CLI parsing. + - Refer to [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) for details on the MCP architecture and available tools. + - A comprehensive list and description of MCP tools and their corresponding CLI commands can be found in [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc). + - **Restart the MCP server** if core logic in `scripts/modules` or MCP tool/direct function definitions change. + +2. **`task-master` CLI (For Users & Fallback)**: + - The global `task-master` command provides a user-friendly interface for direct terminal interaction. + - It can also serve as a fallback if the MCP server is inaccessible or a specific function isn't exposed via MCP. + - Install globally with `npm install -g task-master-ai` or use locally via `npx task-master-ai ...`. + - The CLI commands often mirror the MCP tools (e.g., `task-master list` corresponds to `get_tasks`). + - Refer to [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc) for a detailed command reference. + +## Standard Development Workflow Process + +- Start new projects by running `initialize_project` tool / `task-master init` or `parse_prd` / `task-master parse-prd --input=''` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to generate initial tasks.json +- Begin coding sessions with `get_tasks` / `task-master list` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to see current tasks, status, and IDs +- Determine the next task to work on using `next_task` / `task-master next` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Analyze task complexity with `analyze_project_complexity` / `task-master analyze-complexity --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) before breaking down tasks +- Review complexity report using `complexity_report` / `task-master complexity-report` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Select tasks based on dependencies (all marked 'done'), priority level, and ID order +- Clarify tasks by checking task files in tasks/ directory or asking for user input +- View specific task details using `get_task` / `task-master show ` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to understand implementation requirements +- Break down complex tasks using `expand_task` / `task-master expand --id= --force --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) with appropriate flags like `--force` (to replace existing subtasks) and `--research`. +- Clear existing subtasks if needed using `clear_subtasks` / `task-master clear-subtasks --id=` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) before regenerating +- Implement code following task details, dependencies, and project standards +- Verify tasks according to test strategies before marking as complete (See [`tests.mdc`](mdc:.cursor/rules/tests.mdc)) +- Mark completed tasks with `set_task_status` / `task-master set-status --id= --status=done` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) +- Update dependent tasks when implementation differs from original plan using `update` / `task-master update --from= --prompt="..."` or `update_task` / `task-master update-task --id= --prompt="..."` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) +- Add new tasks discovered during implementation using `add_task` / `task-master add-task --prompt="..." --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Add new subtasks as needed using `add_subtask` / `task-master add-subtask --parent= --title="..."` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Append notes or details to subtasks using `update_subtask` / `task-master update-subtask --id= --prompt='Add implementation notes here...\nMore details...'` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)). +- Generate task files with `generate` / `task-master generate` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) after updating tasks.json +- Maintain valid dependency structure with `add_dependency`/`remove_dependency` tools or `task-master add-dependency`/`remove-dependency` commands, `validate_dependencies` / `task-master validate-dependencies`, and `fix_dependencies` / `task-master fix-dependencies` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) when needed +- Respect dependency chains and task priorities when selecting work +- Report progress regularly using `get_tasks` / `task-master list` + +## Task Complexity Analysis + +- Run `analyze_project_complexity` / `task-master analyze-complexity --research` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) for comprehensive analysis +- Review complexity report via `complexity_report` / `task-master complexity-report` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) for a formatted, readable version. +- Focus on tasks with highest complexity scores (8-10) for detailed breakdown +- Use analysis results to determine appropriate subtask allocation +- Note that reports are automatically used by the `expand_task` tool/command + +## Task Breakdown Process + +- Use `expand_task` / `task-master expand --id=`. It automatically uses the complexity report if found, otherwise generates default number of subtasks. +- Use `--num=` to specify an explicit number of subtasks, overriding defaults or complexity report recommendations. +- Add `--research` flag to leverage Perplexity AI for research-backed expansion. +- Add `--force` flag to clear existing subtasks before generating new ones (default is to append). +- Use `--prompt=""` to provide additional context when needed. +- Review and adjust generated subtasks as necessary. +- Use `expand_all` tool or `task-master expand --all` to expand multiple pending tasks at once, respecting flags like `--force` and `--research`. +- If subtasks need complete replacement (regardless of the `--force` flag on `expand`), clear them first with `clear_subtasks` / `task-master clear-subtasks --id=`. + +## Implementation Drift Handling + +- When implementation differs significantly from planned approach +- When future tasks need modification due to current implementation choices +- When new dependencies or requirements emerge +- Use `update` / `task-master update --from= --prompt='\nUpdate context...' --research` to update multiple future tasks. +- Use `update_task` / `task-master update-task --id= --prompt='\nUpdate context...' --research` to update a single specific task. + +## Task Status Management + +- Use 'pending' for tasks ready to be worked on +- Use 'done' for completed and verified tasks +- Use 'deferred' for postponed tasks +- Add custom status values as needed for project-specific workflows + +## Task Structure Fields + +- **id**: Unique identifier for the task (Example: `1`, `1.1`) +- **title**: Brief, descriptive title (Example: `"Initialize Repo"`) +- **description**: Concise summary of what the task involves (Example: `"Create a new repository, set up initial structure."`) +- **status**: Current state of the task (Example: `"pending"`, `"done"`, `"deferred"`) +- **dependencies**: IDs of prerequisite tasks (Example: `[1, 2.1]`) + - Dependencies are displayed with status indicators (✅ for completed, ⏱️ for pending) + - This helps quickly identify which prerequisite tasks are blocking work +- **priority**: Importance level (Example: `"high"`, `"medium"`, `"low"`) +- **details**: In-depth implementation instructions (Example: `"Use GitHub client ID/secret, handle callback, set session token."`) +- **testStrategy**: Verification approach (Example: `"Deploy and call endpoint to confirm 'Hello World' response."`) +- **subtasks**: List of smaller, more specific tasks (Example: `[{"id": 1, "title": "Configure OAuth", ...}]`) +- Refer to task structure details (previously linked to `tasks.mdc`). + +## Configuration Management (Updated) + +Taskmaster configuration is managed through two main mechanisms: + +1. **`.taskmasterconfig` File (Primary):** + * Located in the project root directory. + * Stores most configuration settings: AI model selections (main, research, fallback), parameters (max tokens, temperature), logging level, default subtasks/priority, project name, etc. + * **Managed via `task-master models --setup` command.** Do not edit manually unless you know what you are doing. + * **View/Set specific models via `task-master models` command or `models` MCP tool.** + * Created automatically when you run `task-master models --setup` for the first time. + +2. **Environment Variables (`.env` / `mcp.json`):** + * Used **only** for sensitive API keys and specific endpoint URLs. + * Place API keys (one per provider) in a `.env` file in the project root for CLI usage. + * For MCP/Cursor integration, configure these keys in the `env` section of `.cursor/mcp.json`. + * Available keys/variables: See `assets/env.example` or the Configuration section in the command reference (previously linked to `taskmaster.mdc`). + +**Important:** Non-API key settings (like model selections, `MAX_TOKENS`, `TASKMASTER_LOG_LEVEL`) are **no longer configured via environment variables**. Use the `task-master models` command (or `--setup` for interactive configuration) or the `models` MCP tool. +**If AI commands FAIL in MCP** verify that the API key for the selected provider is present in the `env` section of `.cursor/mcp.json`. +**If AI commands FAIL in CLI** verify that the API key for the selected provider is present in the `.env` file in the root of the project. + +## Determining the Next Task + +- Run `next_task` / `task-master next` to show the next task to work on. +- The command identifies tasks with all dependencies satisfied +- Tasks are prioritized by priority level, dependency count, and ID +- The command shows comprehensive task information including: + - Basic task details and description + - Implementation details + - Subtasks (if they exist) + - Contextual suggested actions +- Recommended before starting any new development work +- Respects your project's dependency structure +- Ensures tasks are completed in the appropriate sequence +- Provides ready-to-use commands for common task actions + +## Viewing Specific Task Details + +- Run `get_task` / `task-master show ` to view a specific task. +- Use dot notation for subtasks: `task-master show 1.2` (shows subtask 2 of task 1) +- Displays comprehensive information similar to the next command, but for a specific task +- For parent tasks, shows all subtasks and their current status +- For subtasks, shows parent task information and relationship +- Provides contextual suggested actions appropriate for the specific task +- Useful for examining task details before implementation or checking status + +## Managing Task Dependencies + +- Use `add_dependency` / `task-master add-dependency --id= --depends-on=` to add a dependency. +- Use `remove_dependency` / `task-master remove-dependency --id= --depends-on=` to remove a dependency. +- The system prevents circular dependencies and duplicate dependency entries +- Dependencies are checked for existence before being added or removed +- Task files are automatically regenerated after dependency changes +- Dependencies are visualized with status indicators in task listings and files + +## Iterative Subtask Implementation + +Once a task has been broken down into subtasks using `expand_task` or similar methods, follow this iterative process for implementation: + +1. **Understand the Goal (Preparation):** + * Use `get_task` / `task-master show ` (see [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc)) to thoroughly understand the specific goals and requirements of the subtask. + +2. **Initial Exploration & Planning (Iteration 1):** + * This is the first attempt at creating a concrete implementation plan. + * Explore the codebase to identify the precise files, functions, and even specific lines of code that will need modification. + * Determine the intended code changes (diffs) and their locations. + * Gather *all* relevant details from this exploration phase. + +3. **Log the Plan:** + * Run `update_subtask` / `task-master update-subtask --id= --prompt=''`. + * Provide the *complete and detailed* findings from the exploration phase in the prompt. Include file paths, line numbers, proposed diffs, reasoning, and any potential challenges identified. Do not omit details. The goal is to create a rich, timestamped log within the subtask's `details`. + +4. **Verify the Plan:** + * Run `get_task` / `task-master show ` again to confirm that the detailed implementation plan has been successfully appended to the subtask's details. + +5. **Begin Implementation:** + * Set the subtask status using `set_task_status` / `task-master set-status --id= --status=in-progress`. + * Start coding based on the logged plan. + +6. **Refine and Log Progress (Iteration 2+):** + * As implementation progresses, you will encounter challenges, discover nuances, or confirm successful approaches. + * **Before appending new information**: Briefly review the *existing* details logged in the subtask (using `get_task` or recalling from context) to ensure the update adds fresh insights and avoids redundancy. + * **Regularly** use `update_subtask` / `task-master update-subtask --id= --prompt='\n- What worked...\n- What didn't work...'` to append new findings. + * **Crucially, log:** + * What worked ("fundamental truths" discovered). + * What didn't work and why (to avoid repeating mistakes). + * Specific code snippets or configurations that were successful. + * Decisions made, especially if confirmed with user input. + * Any deviations from the initial plan and the reasoning. + * The objective is to continuously enrich the subtask's details, creating a log of the implementation journey that helps the AI (and human developers) learn, adapt, and avoid repeating errors. + +7. **Review & Update Rules (Post-Implementation):** + * Once the implementation for the subtask is functionally complete, review all code changes and the relevant chat history. + * Identify any new or modified code patterns, conventions, or best practices established during the implementation. + * Create new or update existing rules following internal guidelines (previously linked to `cursor_rules.mdc` and `self_improve.mdc`). + +8. **Mark Task Complete:** + * After verifying the implementation and updating any necessary rules, mark the subtask as completed: `set_task_status` / `task-master set-status --id= --status=done`. + +9. **Commit Changes (If using Git):** + * Stage the relevant code changes and any updated/new rule files (`git add .`). + * Craft a comprehensive Git commit message summarizing the work done for the subtask, including both code implementation and any rule adjustments. + * Execute the commit command directly in the terminal (e.g., `git commit -m 'feat(module): Implement feature X for subtask \n\n- Details about changes...\n- Updated rule Y for pattern Z'`). + * Consider if a Changeset is needed according to internal versioning guidelines (previously linked to `changeset.mdc`). If so, run `npm run changeset`, stage the generated file, and amend the commit or create a new one. + +10. **Proceed to Next Subtask:** + * Identify the next subtask (e.g., using `next_task` / `task-master next`). + +## Code Analysis & Refactoring Techniques + +- **Top-Level Function Search**: + - Useful for understanding module structure or planning refactors. + - Use grep/ripgrep to find exported functions/constants: + `rg "export (async function|function|const) \w+"` or similar patterns. + - Can help compare functions between files during migrations or identify potential naming conflicts. + +--- +*This workflow provides a general guideline. Adapt it based on your specific project needs and team practices.* \ No newline at end of file diff --git a/.cursor/rules/development-workflow.mdc b/.cursor/rules/development-workflow.mdc new file mode 100644 index 0000000000..175b7d85ae --- /dev/null +++ b/.cursor/rules/development-workflow.mdc @@ -0,0 +1,653 @@ +--- +description: Development setup, coding standards, contribution guidelines, and best practices +globs: **/*.php, composer.json, package.json, *.md, .env.example +alwaysApply: false +--- +# Coolify Development Workflow + +## Development Environment Setup + +### Prerequisites +- **PHP 8.4+** - Latest PHP version for modern features +- **Node.js 18+** - For frontend asset compilation +- **Docker & Docker Compose** - Container orchestration +- **PostgreSQL 15** - Primary database +- **Redis 7** - Caching and queues + +### Local Development Setup + +#### Using Docker (Recommended) +```bash +# Clone the repository +git clone https://github.com/coollabsio/coolify.git +cd coolify + +# Copy environment configuration +cp .env.example .env + +# Start development environment +docker-compose -f docker-compose.dev.yml up -d + +# Install PHP dependencies +docker-compose exec app composer install + +# Install Node.js dependencies +docker-compose exec app npm install + +# Generate application key +docker-compose exec app php artisan key:generate + +# Run database migrations +docker-compose exec app php artisan migrate + +# Seed development data +docker-compose exec app php artisan db:seed +``` + +#### Native Development +```bash +# Install PHP dependencies +composer install + +# Install Node.js dependencies +npm install + +# Setup environment +cp .env.example .env +php artisan key:generate + +# Setup database +createdb coolify_dev +php artisan migrate +php artisan db:seed + +# Start development servers +php artisan serve & +npm run dev & +php artisan queue:work & +``` + +## Development Tools & Configuration + +### Code Quality Tools +- **[Laravel Pint](mdc:pint.json)** - PHP code style fixer +- **[Rector](mdc:rector.php)** - PHP automated refactoring (989B, 35 lines) +- **PHPStan** - Static analysis for type safety +- **ESLint** - JavaScript code quality + +### Development Configuration Files +- **[docker-compose.dev.yml](mdc:docker-compose.dev.yml)** - Development Docker setup (3.4KB, 126 lines) +- **[vite.config.js](mdc:vite.config.js)** - Frontend build configuration (1.0KB, 42 lines) +- **[.editorconfig](mdc:.editorconfig)** - Code formatting standards (258B, 19 lines) + +### Git Configuration +- **[.gitignore](mdc:.gitignore)** - Version control exclusions (522B, 40 lines) +- **[.gitattributes](mdc:.gitattributes)** - Git file handling (185B, 11 lines) + +## Development Workflow Process + +### 1. Feature Development +```bash +# Create feature branch +git checkout -b feature/new-deployment-strategy + +# Make changes following coding standards +# Run code quality checks +./vendor/bin/pint +./vendor/bin/rector process --dry-run +./vendor/bin/phpstan analyse + +# Run tests +./vendor/bin/pest +./vendor/bin/pest --coverage + +# Commit changes +git add . +git commit -m "feat: implement blue-green deployment strategy" +``` + +### 2. Code Review Process +```bash +# Push feature branch +git push origin feature/new-deployment-strategy + +# Create pull request with: +# - Clear description of changes +# - Screenshots for UI changes +# - Test coverage information +# - Breaking change documentation +``` + +### 3. Testing Requirements +- **Unit tests** for new models and services +- **Feature tests** for API endpoints +- **Browser tests** for UI changes +- **Integration tests** for deployment workflows + +## Coding Standards & Conventions + +### PHP Coding Standards +```php +// Follow PSR-12 coding standards +class ApplicationDeploymentService +{ + public function __construct( + private readonly DockerService $dockerService, + private readonly ConfigurationGenerator $configGenerator + ) {} + + public function deploy(Application $application): ApplicationDeploymentQueue + { + return DB::transaction(function () use ($application) { + $deployment = $application->deployments()->create([ + 'status' => 'queued', + 'commit_sha' => $application->getLatestCommitSha(), + ]); + + DeployApplicationJob::dispatch($deployment); + + return $deployment; + }); + } +} +``` + +### Laravel Best Practices +```php +// Use Laravel conventions +class Application extends Model +{ + // Mass assignment protection + protected $fillable = [ + 'name', 'git_repository', 'git_branch', 'fqdn' + ]; + + // Type casting + protected $casts = [ + 'environment_variables' => 'array', + 'build_pack' => BuildPack::class, + 'created_at' => 'datetime', + ]; + + // Relationships + public function server(): BelongsTo + { + return $this->belongsTo(Server::class); + } + + public function deployments(): HasMany + { + return $this->hasMany(ApplicationDeploymentQueue::class); + } +} +``` + +### Frontend Standards +```javascript +// Alpine.js component structure +document.addEventListener('alpine:init', () => { + Alpine.data('deploymentMonitor', () => ({ + status: 'idle', + logs: [], + + init() { + this.connectWebSocket(); + }, + + connectWebSocket() { + Echo.private(`application.${this.applicationId}`) + .listen('DeploymentStarted', (e) => { + this.status = 'deploying'; + }) + .listen('DeploymentCompleted', (e) => { + this.status = 'completed'; + }); + } + })); +}); +``` + +### CSS/Tailwind Standards +```html + +
+
+

+ Application Status +

+
+ +
+
+
+``` + +## Database Development + +### Migration Best Practices +```php +// Create descriptive migration files +class CreateApplicationDeploymentQueuesTable extends Migration +{ + public function up(): void + { + Schema::create('application_deployment_queues', function (Blueprint $table) { + $table->id(); + $table->foreignId('application_id')->constrained()->cascadeOnDelete(); + $table->string('status')->default('queued'); + $table->string('commit_sha')->nullable(); + $table->text('build_logs')->nullable(); + $table->text('deployment_logs')->nullable(); + $table->timestamp('started_at')->nullable(); + $table->timestamp('finished_at')->nullable(); + $table->timestamps(); + + $table->index(['application_id', 'status']); + $table->index('created_at'); + }); + } + + public function down(): void + { + Schema::dropIfExists('application_deployment_queues'); + } +} +``` + +### Model Factory Development +```php +// Create comprehensive factories for testing +class ApplicationFactory extends Factory +{ + protected $model = Application::class; + + public function definition(): array + { + return [ + 'name' => $this->faker->words(2, true), + 'fqdn' => $this->faker->domainName, + 'git_repository' => 'https://github.com/' . $this->faker->userName . '/' . $this->faker->word . '.git', + 'git_branch' => 'main', + 'build_pack' => BuildPack::NIXPACKS, + 'server_id' => Server::factory(), + 'environment_id' => Environment::factory(), + ]; + } + + public function withCustomDomain(): static + { + return $this->state(fn (array $attributes) => [ + 'fqdn' => $this->faker->domainName, + ]); + } +} +``` + +## API Development + +### Controller Standards +```php +class ApplicationController extends Controller +{ + public function __construct() + { + $this->middleware('auth:sanctum'); + $this->middleware('team.access'); + } + + public function index(Request $request): AnonymousResourceCollection + { + $applications = $request->user() + ->currentTeam + ->applications() + ->with(['server', 'environment', 'latestDeployment']) + ->paginate(); + + return ApplicationResource::collection($applications); + } + + public function store(StoreApplicationRequest $request): ApplicationResource + { + $application = $request->user() + ->currentTeam + ->applications() + ->create($request->validated()); + + return new ApplicationResource($application); + } + + public function deploy(Application $application): JsonResponse + { + $this->authorize('deploy', $application); + + $deployment = app(ApplicationDeploymentService::class) + ->deploy($application); + + return response()->json([ + 'message' => 'Deployment started successfully', + 'deployment_id' => $deployment->id, + ]); + } +} +``` + +### API Resource Development +```php +class ApplicationResource extends JsonResource +{ + public function toArray($request): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'fqdn' => $this->fqdn, + 'status' => $this->status, + 'git_repository' => $this->git_repository, + 'git_branch' => $this->git_branch, + 'build_pack' => $this->build_pack, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + + // Conditional relationships + 'server' => new ServerResource($this->whenLoaded('server')), + 'environment' => new EnvironmentResource($this->whenLoaded('environment')), + 'latest_deployment' => new DeploymentResource($this->whenLoaded('latestDeployment')), + + // Computed attributes + 'deployment_url' => $this->getDeploymentUrl(), + 'can_deploy' => $this->canDeploy(), + ]; + } +} +``` + +## Livewire Component Development + +### Component Structure +```php +class ApplicationShow extends Component +{ + public Application $application; + public bool $showLogs = false; + + protected $listeners = [ + 'deployment.started' => 'refreshDeploymentStatus', + 'deployment.completed' => 'refreshDeploymentStatus', + ]; + + public function mount(Application $application): void + { + $this->authorize('view', $application); + $this->application = $application; + } + + public function deploy(): void + { + $this->authorize('deploy', $this->application); + + try { + app(ApplicationDeploymentService::class)->deploy($this->application); + + $this->dispatch('deployment.started', [ + 'application_id' => $this->application->id + ]); + + session()->flash('success', 'Deployment started successfully'); + } catch (Exception $e) { + session()->flash('error', 'Failed to start deployment: ' . $e->getMessage()); + } + } + + public function refreshDeploymentStatus(): void + { + $this->application->refresh(); + } + + public function render(): View + { + return view('livewire.application.show', [ + 'deployments' => $this->application + ->deployments() + ->latest() + ->limit(10) + ->get() + ]); + } +} +``` + +## Queue Job Development + +### Job Structure +```php +class DeployApplicationJob implements ShouldQueue +{ + use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + + public int $tries = 3; + public int $maxExceptions = 1; + + public function __construct( + public ApplicationDeploymentQueue $deployment + ) {} + + public function handle( + DockerService $dockerService, + ConfigurationGenerator $configGenerator + ): void { + $this->deployment->update(['status' => 'running', 'started_at' => now()]); + + try { + // Generate configuration + $config = $configGenerator->generateDockerCompose($this->deployment->application); + + // Build and deploy + $imageTag = $dockerService->buildImage($this->deployment->application); + $dockerService->deployContainer($this->deployment->application, $imageTag); + + $this->deployment->update([ + 'status' => 'success', + 'finished_at' => now() + ]); + + // Broadcast success + broadcast(new DeploymentCompleted($this->deployment)); + + } catch (Exception $e) { + $this->deployment->update([ + 'status' => 'failed', + 'error_message' => $e->getMessage(), + 'finished_at' => now() + ]); + + broadcast(new DeploymentFailed($this->deployment)); + + throw $e; + } + } + + public function backoff(): array + { + return [1, 5, 10]; + } + + public function failed(Throwable $exception): void + { + $this->deployment->update([ + 'status' => 'failed', + 'error_message' => $exception->getMessage(), + 'finished_at' => now() + ]); + } +} +``` + +## Testing Development + +### Test Structure +```php +// Feature test example +test('user can deploy application via API', function () { + $user = User::factory()->create(); + $application = Application::factory()->create([ + 'team_id' => $user->currentTeam->id + ]); + + // Mock external services + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('app:latest'); + $mock->shouldReceive('deployContainer')->andReturn(true); + }); + + $response = $this->actingAs($user) + ->postJson("/api/v1/applications/{$application->id}/deploy"); + + $response->assertStatus(200) + ->assertJson([ + 'message' => 'Deployment started successfully' + ]); + + expect($application->deployments()->count())->toBe(1); + expect($application->deployments()->first()->status)->toBe('queued'); +}); +``` + +## Documentation Standards + +### Code Documentation +```php +/** + * Deploy an application to the specified server. + * + * This method creates a new deployment queue entry and dispatches + * a background job to handle the actual deployment process. + * + * @param Application $application The application to deploy + * @param array $options Additional deployment options + * @return ApplicationDeploymentQueue The created deployment queue entry + * + * @throws DeploymentException When deployment cannot be started + * @throws ServerConnectionException When server is unreachable + */ +public function deploy(Application $application, array $options = []): ApplicationDeploymentQueue +{ + // Implementation +} +``` + +### API Documentation +```php +/** + * @OA\Post( + * path="/api/v1/applications/{application}/deploy", + * summary="Deploy an application", + * description="Triggers a new deployment for the specified application", + * operationId="deployApplication", + * tags={"Applications"}, + * security={{"bearerAuth":{}}}, + * @OA\Parameter( + * name="application", + * in="path", + * required=true, + * @OA\Schema(type="integer"), + * description="Application ID" + * ), + * @OA\Response( + * response=200, + * description="Deployment started successfully", + * @OA\JsonContent( + * @OA\Property(property="message", type="string"), + * @OA\Property(property="deployment_id", type="integer") + * ) + * ) + * ) + */ +``` + +## Performance Optimization + +### Database Optimization +```php +// Use eager loading to prevent N+1 queries +$applications = Application::with([ + 'server:id,name,ip', + 'environment:id,name', + 'latestDeployment:id,application_id,status,created_at' +])->get(); + +// Use database transactions for consistency +DB::transaction(function () use ($application) { + $deployment = $application->deployments()->create(['status' => 'queued']); + $application->update(['last_deployment_at' => now()]); + DeployApplicationJob::dispatch($deployment); +}); +``` + +### Caching Strategies +```php +// Cache expensive operations +public function getServerMetrics(Server $server): array +{ + return Cache::remember( + "server.{$server->id}.metrics", + now()->addMinutes(5), + fn () => $this->fetchServerMetrics($server) + ); +} +``` + +## Deployment & Release Process + +### Version Management +- **[versions.json](mdc:versions.json)** - Version tracking (355B, 19 lines) +- **[CHANGELOG.md](mdc:CHANGELOG.md)** - Release notes (187KB, 7411 lines) +- **[cliff.toml](mdc:cliff.toml)** - Changelog generation (3.2KB, 85 lines) + +### Release Workflow +```bash +# Create release branch +git checkout -b release/v4.1.0 + +# Update version numbers +# Update CHANGELOG.md +# Run full test suite +./vendor/bin/pest +npm run test + +# Create release commit +git commit -m "chore: release v4.1.0" + +# Create and push tag +git tag v4.1.0 +git push origin v4.1.0 + +# Merge to main +git checkout main +git merge release/v4.1.0 +``` + +## Contributing Guidelines + +### Pull Request Process +1. **Fork** the repository +2. **Create** feature branch from `main` +3. **Implement** changes with tests +4. **Run** code quality checks +5. **Submit** pull request with clear description +6. **Address** review feedback +7. **Merge** after approval + +### Code Review Checklist +- [ ] Code follows project standards +- [ ] Tests cover new functionality +- [ ] Documentation is updated +- [ ] No breaking changes without migration +- [ ] Performance impact considered +- [ ] Security implications reviewed + +### Issue Reporting +- Use issue templates +- Provide reproduction steps +- Include environment details +- Add relevant logs/screenshots +- Label appropriately diff --git a/.cursor/rules/form-components.mdc b/.cursor/rules/form-components.mdc new file mode 100644 index 0000000000..665ccfd983 --- /dev/null +++ b/.cursor/rules/form-components.mdc @@ -0,0 +1,452 @@ +--- +description: Enhanced form components with built-in authorization system +globs: resources/views/**/*.blade.php, app/View/Components/Forms/*.php +alwaysApply: true +--- + +# Enhanced Form Components with Authorization + +## Overview + +Coolify's form components now feature **built-in authorization** that automatically handles permission-based UI control, dramatically reducing code duplication and improving security consistency. + +## Enhanced Components + +All form components now support the `canGate` authorization system: + +- **[Input.php](mdc:app/View/Components/Forms/Input.php)** - Text, password, and other input fields +- **[Select.php](mdc:app/View/Components/Forms/Select.php)** - Dropdown selection components +- **[Textarea.php](mdc:app/View/Components/Forms/Textarea.php)** - Multi-line text areas +- **[Checkbox.php](mdc:app/View/Components/Forms/Checkbox.php)** - Boolean toggle components +- **[Button.php](mdc:app/View/Components/Forms/Button.php)** - Action buttons + +## Authorization Parameters + +### Core Parameters +```php +public ?string $canGate = null; // Gate name: 'update', 'view', 'deploy', 'delete' +public mixed $canResource = null; // Resource model instance to check against +public bool $autoDisable = true; // Automatically disable if no permission +``` + +### How It Works +```php +// Automatic authorization logic in each component +if ($this->canGate && $this->canResource && $this->autoDisable) { + $hasPermission = Gate::allows($this->canGate, $this->canResource); + + if (! $hasPermission) { + $this->disabled = true; + // For Checkbox: also sets $this->instantSave = false; + } +} +``` + +## Usage Patterns + +### ✅ Recommended: Single Line Pattern + +**Before (Verbose, 6+ lines per element):** +```html +@can('update', $application) + + + Save +@else + + +@endcan +``` + +**After (Clean, 1 line per element):** +```html + + +Save +``` + +**Result: 90% code reduction!** + +### Component-Specific Examples + +#### Input Fields +```html + + + + + + + + +``` + +#### Select Dropdowns +```html + + + + + + + + + + @foreach($servers as $server) + + @endforeach + +``` + +#### Checkboxes with InstantSave +```html + + + + + + + + +``` + +#### Textareas +```html + + + + + +``` + +#### Buttons +```html + + + Save Configuration + + + + + Deploy Application + + + + + Delete Application + +``` + +## Advanced Usage + +### Custom Authorization Logic +```html + + +``` + +### Multiple Permission Checks +```html + + +``` + +### Conditional Resources +```html + + + {{ $isEditing ? 'Save Changes' : 'View Details' }} + +``` + +## Supported Gates + +### Resource-Level Gates +- `view` - Read access to resource details +- `update` - Modify resource configuration and settings +- `deploy` - Deploy, restart, or manage resource state +- `delete` - Remove or destroy resource +- `clone` - Duplicate resource to another location + +### Global Gates +- `createAnyResource` - Create new resources of any type +- `manageTeam` - Team administration permissions +- `accessServer` - Server-level access permissions + +## Supported Resources + +### Primary Resources +- `$application` - Application instances and configurations +- `$service` - Docker Compose services and components +- `$database` - Database instances (PostgreSQL, MySQL, etc.) +- `$server` - Physical or virtual server instances + +### Container Resources +- `$project` - Project containers and environments +- `$environment` - Environment-specific configurations +- `$team` - Team and organization contexts + +### Infrastructure Resources +- `$privateKey` - SSH private keys and certificates +- `$source` - Git sources and repositories +- `$destination` - Deployment destinations and targets + +## Component Behavior + +### Input Components (Input, Select, Textarea) +When authorization fails: +- **disabled = true** - Field becomes non-editable +- **Visual styling** - Opacity reduction and disabled cursor +- **Form submission** - Values are ignored in forms +- **User feedback** - Clear visual indication of restricted access + +### Checkbox Components +When authorization fails: +- **disabled = true** - Checkbox becomes non-clickable +- **instantSave = false** - Automatic saving is disabled +- **State preservation** - Current value is maintained but read-only +- **Visual styling** - Disabled appearance with reduced opacity + +### Button Components +When authorization fails: +- **disabled = true** - Button becomes non-clickable +- **Event blocking** - Click handlers are ignored +- **Visual styling** - Disabled appearance and cursor +- **Loading states** - Loading indicators are disabled + +## Migration Guide + +### Converting Existing Forms + +**Old Pattern:** +```html +
+ @can('update', $application) + + ... + + Save + @else + + ... + + @endcan + +``` + +**New Pattern:** +```html +
+ + ... + + Save + +``` + +### Gradual Migration Strategy + +1. **Start with new forms** - Use the new pattern for all new components +2. **Convert high-traffic areas** - Migrate frequently used forms first +3. **Batch convert similar forms** - Group similar authorization patterns +4. **Test thoroughly** - Verify authorization behavior matches expectations +5. **Remove old patterns** - Clean up legacy @can/@else blocks + +## Testing Patterns + +### Component Authorization Tests +```php +// Test authorization integration in components +test('input component respects authorization', function () { + $user = User::factory()->member()->create(); + $application = Application::factory()->create(); + + // Member should see disabled input + $component = Livewire::actingAs($user) + ->test(TestComponent::class, [ + 'canGate' => 'update', + 'canResource' => $application + ]); + + expect($component->get('disabled'))->toBeTrue(); +}); + +test('checkbox disables instantSave for unauthorized users', function () { + $user = User::factory()->member()->create(); + $application = Application::factory()->create(); + + $component = Livewire::actingAs($user) + ->test(CheckboxComponent::class, [ + 'instantSave' => true, + 'canGate' => 'update', + 'canResource' => $application + ]); + + expect($component->get('disabled'))->toBeTrue(); + expect($component->get('instantSave'))->toBeFalse(); +}); +``` + +### Integration Tests +```php +// Test full form authorization behavior +test('application form respects member permissions', function () { + $member = User::factory()->member()->create(); + $application = Application::factory()->create(); + + $this->actingAs($member) + ->get(route('application.edit', $application)) + ->assertSee('disabled') + ->assertDontSee('Save Configuration'); +}); +``` + +## Best Practices + +### Consistent Gate Usage +- Use `update` for configuration changes +- Use `deploy` for operational actions +- Use `view` for read-only access +- Use `delete` for destructive actions + +### Resource Context +- Always pass the specific resource being acted upon +- Use team context for creation permissions +- Consider nested resource relationships + +### Error Handling +- Provide clear feedback for disabled components +- Use helper text to explain permission requirements +- Consider tooltips for disabled buttons + +### Performance +- Authorization checks are cached per request +- Use eager loading for resource relationships +- Consider query optimization for complex permissions + +## Common Patterns + +### Application Configuration Forms +```html + + +... + +Save +``` + +### Service Configuration Forms +```html + + + + +Save + + + + + +@can('update', $service) + +@endcan +``` + +### Server Management Forms +```html + + +... +Delete Server +``` + +### Resource Creation Forms +```html + + +... +Create Application +``` \ No newline at end of file diff --git a/.cursor/rules/frontend-patterns.mdc b/.cursor/rules/frontend-patterns.mdc new file mode 100644 index 0000000000..4730160b2e --- /dev/null +++ b/.cursor/rules/frontend-patterns.mdc @@ -0,0 +1,701 @@ +--- +description: Livewire components, Alpine.js patterns, Tailwind CSS, and enhanced form components +globs: app/Livewire/**/*.php, resources/views/**/*.blade.php, resources/js/**/*.js, resources/css/**/*.css +alwaysApply: false +--- +# Coolify Frontend Architecture & Patterns + +## Frontend Philosophy + +Coolify uses a **server-side first** approach with minimal JavaScript, leveraging Livewire for reactivity and Alpine.js for lightweight client-side interactions. + +## Core Frontend Stack + +### Livewire 3.5+ (Primary Framework) +- **Server-side rendering** with reactive components +- **Real-time updates** without page refreshes +- **State management** handled on the server +- **WebSocket integration** for live updates + +### Alpine.js (Client-Side Interactivity) +- **Lightweight JavaScript** for DOM manipulation +- **Declarative directives** in HTML +- **Component-like behavior** without build steps +- **Perfect companion** to Livewire + +### Tailwind CSS 4.1+ (Styling) +- **Utility-first** CSS framework +- **Custom design system** for deployment platform +- **Responsive design** built-in +- **Dark mode support** + +## Livewire Component Structure + +### Location: [app/Livewire/](mdc:app/Livewire) + +#### Core Application Components +- **[Dashboard.php](mdc:app/Livewire/Dashboard.php)** - Main dashboard interface +- **[ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php)** - Real-time activity tracking +- **[MonacoEditor.php](mdc:app/Livewire/MonacoEditor.php)** - Code editor component + +#### Server Management +- **Server/** directory - Server configuration and monitoring +- Real-time server status updates +- SSH connection management +- Resource monitoring + +#### Project & Application Management +- **Project/** directory - Project organization +- Application deployment interfaces +- Environment variable management +- Service configuration + +#### Settings & Configuration +- **Settings/** directory - System configuration +- **[SettingsEmail.php](mdc:app/Livewire/SettingsEmail.php)** - Email notification setup +- **[SettingsOauth.php](mdc:app/Livewire/SettingsOauth.php)** - OAuth provider configuration +- **[SettingsBackup.php](mdc:app/Livewire/SettingsBackup.php)** - Backup configuration + +#### User & Team Management +- **Team/** directory - Team collaboration features +- **Profile/** directory - User profile management +- **Security/** directory - Security settings + +## Blade Template Organization + +### Location: [resources/views/](mdc:resources/views) + +#### Layout Structure +- **layouts/** - Base layout templates +- **components/** - Reusable UI components +- **livewire/** - Livewire component views + +#### Feature-Specific Views +- **server/** - Server management interfaces +- **auth/** - Authentication pages +- **emails/** - Email templates +- **errors/** - Error pages + +## Interactive Components + +### Monaco Editor Integration +- **Code editing** for configuration files +- **Syntax highlighting** for multiple languages +- **Live validation** and error detection +- **Integration** with deployment process + +### Terminal Emulation (XTerm.js) +- **Real-time terminal** access to servers +- **WebSocket-based** communication +- **Multi-session** support +- **Secure connection** through SSH + +### Real-Time Updates +- **WebSocket connections** via Laravel Echo +- **Live deployment logs** streaming +- **Server monitoring** with live metrics +- **Activity notifications** in real-time + +## Alpine.js Patterns + +### Common Directives Used +```html + +
+ + + +``` + +## Tailwind CSS Patterns + +### Design System +- **Consistent spacing** using Tailwind scale +- **Color palette** optimized for deployment platform +- **Typography** hierarchy for technical content +- **Component classes** for reusable elements + +### Responsive Design +```html + +
+ +
+``` + +### Dark Mode Support +```html + +
+ +
+``` + +## Build Process + +### Vite Configuration ([vite.config.js](mdc:vite.config.js)) +- **Fast development** with hot module replacement +- **Optimized production** builds +- **Asset versioning** for cache busting +- **CSS processing** with PostCSS + +### Asset Compilation +```bash +# Development +npm run dev + +# Production build +npm run build +``` + +## State Management Patterns + +### Server-Side State (Livewire) +- **Component properties** for persistent state +- **Session storage** for user preferences +- **Database models** for application state +- **Cache layer** for performance + +### Client-Side State (Alpine.js) +- **Local component state** for UI interactions +- **Form validation** and user feedback +- **Modal and dropdown** state management +- **Temporary UI states** (loading, hover, etc.) + +## Real-Time Features + +### WebSocket Integration +```php +// Livewire component with real-time updates +class ActivityMonitor extends Component +{ + public function getListeners() + { + return [ + 'deployment.started' => 'refresh', + 'deployment.finished' => 'refresh', + 'server.status.changed' => 'updateServerStatus', + ]; + } +} +``` + +### Event Broadcasting +- **Laravel Echo** for client-side WebSocket handling +- **Pusher protocol** for real-time communication +- **Private channels** for user-specific events +- **Presence channels** for collaborative features + +## Performance Patterns + +### Lazy Loading +```php +// Livewire lazy loading +class ServerList extends Component +{ + public function placeholder() + { + return view('components.loading-skeleton'); + } +} +``` + +### Caching Strategies +- **Fragment caching** for expensive operations +- **Image optimization** with lazy loading +- **Asset bundling** and compression +- **CDN integration** for static assets + +## Enhanced Form Components + +### Built-in Authorization System +Coolify features **enhanced form components** with automatic authorization handling: + +```html + + + +Save + + +@can('update', $application) + +@else + +@endcan +``` + +### Authorization Parameters +```php +// Available on all form components (Input, Select, Textarea, Checkbox, Button) +public ?string $canGate = null; // Gate name: 'update', 'view', 'deploy', 'delete' +public mixed $canResource = null; // Resource model instance to check against +public bool $autoDisable = true; // Automatically disable if no permission (default: true) +``` + +### Benefits +- **90% code reduction** for authorization-protected forms +- **Consistent security** across all form components +- **Automatic disabling** for unauthorized users +- **Smart behavior** (disables instantSave on checkboxes for unauthorized users) + +For complete documentation, see **[form-components.mdc](mdc:.cursor/rules/form-components.mdc)** + +## Form Handling Patterns + +### Livewire Component Data Synchronization Pattern + +**IMPORTANT**: All Livewire components must use the **manual `syncData()` pattern** for synchronizing component properties with Eloquent models. + +#### Property Naming Convention +- **Component properties**: Use camelCase (e.g., `$gitRepository`, `$isStatic`) +- **Database columns**: Use snake_case (e.g., `git_repository`, `is_static`) +- **View bindings**: Use camelCase matching component properties (e.g., `id="gitRepository"`) + +#### The syncData() Method Pattern + +```php +use Livewire\Attributes\Validate; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; + +class MyComponent extends Component +{ + use AuthorizesRequests; + + public Application $application; + + // Properties with validation attributes + #[Validate(['required'])] + public string $name; + + #[Validate(['string', 'nullable'])] + public ?string $description = null; + + #[Validate(['boolean', 'required'])] + public bool $isStatic = false; + + public function mount() + { + $this->authorize('view', $this->application); + $this->syncData(); // Load from model + } + + public function syncData(bool $toModel = false): void + { + if ($toModel) { + $this->validate(); + + // Sync TO model (camelCase → snake_case) + $this->application->name = $this->name; + $this->application->description = $this->description; + $this->application->is_static = $this->isStatic; + + $this->application->save(); + } else { + // Sync FROM model (snake_case → camelCase) + $this->name = $this->application->name; + $this->description = $this->application->description; + $this->isStatic = $this->application->is_static; + } + } + + public function submit() + { + $this->authorize('update', $this->application); + $this->syncData(toModel: true); // Save to model + $this->dispatch('success', 'Saved successfully.'); + } +} +``` + +#### Validation with #[Validate] Attributes + +All component properties should have `#[Validate]` attributes: + +```php +// Boolean properties +#[Validate(['boolean'])] +public bool $isEnabled = false; + +// Required strings +#[Validate(['string', 'required'])] +public string $name; + +// Nullable strings +#[Validate(['string', 'nullable'])] +public ?string $description = null; + +// With constraints +#[Validate(['integer', 'min:1'])] +public int $timeout; +``` + +#### Benefits of syncData() Pattern + +- **Explicit Control**: Clear visibility of what's being synchronized +- **Type Safety**: #[Validate] attributes provide compile-time validation info +- **Easy Debugging**: Single method to check for data flow issues +- **Maintainability**: All sync logic in one place +- **Flexibility**: Can add custom logic (encoding, transformations, etc.) + +#### Creating New Form Components with syncData() + +#### Step-by-Step Component Creation Guide + +**Step 1: Define properties in camelCase with #[Validate] attributes** +```php +use Livewire\Attributes\Validate; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; +use Livewire\Component; + +class MyFormComponent extends Component +{ + use AuthorizesRequests; + + // The model we're syncing with + public Application $application; + + // Component properties in camelCase with validation + #[Validate(['string', 'required'])] + public string $name; + + #[Validate(['string', 'nullable'])] + public ?string $gitRepository = null; + + #[Validate(['string', 'nullable'])] + public ?string $installCommand = null; + + #[Validate(['boolean'])] + public bool $isStatic = false; +} +``` + +**Step 2: Implement syncData() method** +```php +public function syncData(bool $toModel = false): void +{ + if ($toModel) { + $this->validate(); + + // Sync TO model (component camelCase → database snake_case) + $this->application->name = $this->name; + $this->application->git_repository = $this->gitRepository; + $this->application->install_command = $this->installCommand; + $this->application->is_static = $this->isStatic; + + $this->application->save(); + } else { + // Sync FROM model (database snake_case → component camelCase) + $this->name = $this->application->name; + $this->gitRepository = $this->application->git_repository; + $this->installCommand = $this->application->install_command; + $this->isStatic = $this->application->is_static; + } +} +``` + +**Step 3: Implement mount() to load initial data** +```php +public function mount() +{ + $this->authorize('view', $this->application); + $this->syncData(); // Load data from model to component properties +} +``` + +**Step 4: Implement action methods with authorization** +```php +public function instantSave() +{ + try { + $this->authorize('update', $this->application); + $this->syncData(toModel: true); // Save component properties to model + $this->dispatch('success', 'Settings saved.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } +} + +public function submit() +{ + try { + $this->authorize('update', $this->application); + $this->syncData(toModel: true); // Save component properties to model + $this->dispatch('success', 'Changes saved successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } +} +``` + +**Step 5: Create Blade view with camelCase bindings** +```blade +
+
+ + + + + + + + + + Save Changes + + +
+``` + +**Key Points**: +- Use `wire:model="camelCase"` and `id="camelCase"` in Blade views +- Component properties are camelCase, database columns are snake_case +- Always include authorization checks (`authorize()`, `canGate`, `canResource`) +- Use `instantSave` for checkboxes that save immediately without form submission + +#### Special Patterns + +**Pattern 1: Related Models (e.g., Application → Settings)** +```php +public function syncData(bool $toModel = false): void +{ + if ($toModel) { + $this->validate(); + + // Sync main model + $this->application->name = $this->name; + $this->application->save(); + + // Sync related model + $this->application->settings->is_static = $this->isStatic; + $this->application->settings->save(); + } else { + // From main model + $this->name = $this->application->name; + + // From related model + $this->isStatic = $this->application->settings->is_static; + } +} +``` + +**Pattern 2: Custom Encoding/Decoding** +```php +public function syncData(bool $toModel = false): void +{ + if ($toModel) { + $this->validate(); + + // Encode before saving + $this->application->custom_labels = base64_encode($this->customLabels); + $this->application->save(); + } else { + // Decode when loading + $this->customLabels = $this->application->parseContainerLabels(); + } +} +``` + +**Pattern 3: Error Rollback** +```php +public function submit() +{ + $this->authorize('update', $this->resource); + $original = $this->model->getOriginal(); + + try { + $this->syncData(toModel: true); + $this->dispatch('success', 'Saved successfully.'); + } catch (\Throwable $e) { + // Rollback on error + $this->model->setRawAttributes($original); + $this->model->save(); + $this->syncData(); // Reload from model + return handleError($e, $this); + } +} +``` + +#### Property Type Patterns + +**Required Strings** +```php +#[Validate(['string', 'required'])] +public string $name; // No ?, no default, always has value +``` + +**Nullable Strings** +```php +#[Validate(['string', 'nullable'])] +public ?string $description = null; // ?, = null, can be empty +``` + +**Booleans** +```php +#[Validate(['boolean'])] +public bool $isEnabled = false; // Always has default value +``` + +**Integers with Constraints** +```php +#[Validate(['integer', 'min:1'])] +public int $timeout; // Required + +#[Validate(['integer', 'min:1', 'nullable'])] +public ?int $port = null; // Nullable +``` + +#### Testing Checklist + +After creating a new component with syncData(), verify: + +- [ ] All checkboxes save correctly (especially `instantSave` ones) +- [ ] All form inputs persist to database +- [ ] Custom encoded fields (like labels) display correctly if applicable +- [ ] Form validation works for all fields +- [ ] No console errors in browser +- [ ] Authorization checks work (`@can` directives and `authorize()` calls) +- [ ] Error rollback works if exceptions occur +- [ ] Related models save correctly if applicable (e.g., Application + ApplicationSetting) + +#### Common Pitfalls to Avoid + +1. **snake_case in component properties**: Always use camelCase for component properties (e.g., `$gitRepository` not `$git_repository`) +2. **Missing #[Validate] attributes**: Every property should have validation attributes for type safety +3. **Forgetting to call syncData()**: Must call `syncData()` in `mount()` to load initial data +4. **Missing authorization**: Always use `authorize()` in methods and `canGate`/`canResource` in views +5. **View binding mismatch**: Use camelCase in Blade (e.g., `id="gitRepository"` not `id="git_repository"`) +6. **wire:model vs wire:model.live**: Use `.live` for `instantSave` checkboxes to avoid timing issues +7. **Validation sync**: If using `rules()` method, keep it in sync with `#[Validate]` attributes +8. **Related models**: Don't forget to save both main and related models in syncData() method + +### Livewire Forms +```php +class ServerCreateForm extends Component +{ + public $name; + public $ip; + + protected $rules = [ + 'name' => 'required|min:3', + 'ip' => 'required|ip', + ]; + + public function save() + { + $this->validate(); + // Save logic + } +} +``` + +### Real-Time Validation +- **Live validation** as user types +- **Server-side validation** rules +- **Error message** display +- **Success feedback** patterns + +## Component Communication + +### Parent-Child Communication +```php +// Parent component +$this->emit('serverCreated', $server->id); + +// Child component +protected $listeners = ['serverCreated' => 'refresh']; +``` + +### Cross-Component Events +- **Global events** for application-wide updates +- **Scoped events** for feature-specific communication +- **Browser events** for JavaScript integration + +## Error Handling & UX + +### Loading States +- **Skeleton screens** during data loading +- **Progress indicators** for long operations +- **Optimistic updates** with rollback capability + +### Error Display +- **Toast notifications** for user feedback +- **Inline validation** errors +- **Global error** handling +- **Retry mechanisms** for failed operations + +## Accessibility Patterns + +### ARIA Labels and Roles +```html + +``` + +### Keyboard Navigation +- **Tab order** management +- **Keyboard shortcuts** for power users +- **Focus management** in modals and forms +- **Screen reader** compatibility + +## Mobile Optimization + +### Touch-Friendly Interface +- **Larger tap targets** for mobile devices +- **Swipe gestures** where appropriate +- **Mobile-optimized** forms and navigation + +### Progressive Enhancement +- **Core functionality** works without JavaScript +- **Enhanced experience** with JavaScript enabled +- **Offline capabilities** where possible diff --git a/.cursor/rules/laravel-boost.mdc b/.cursor/rules/laravel-boost.mdc new file mode 100644 index 0000000000..c409a46472 --- /dev/null +++ b/.cursor/rules/laravel-boost.mdc @@ -0,0 +1,405 @@ +--- +alwaysApply: true +--- + +=== foundation rules === + +# Laravel Boost Guidelines + +The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications. + +## Foundational Context +This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions. + +- php - 8.4.7 +- laravel/fortify (FORTIFY) - v1 +- laravel/framework (LARAVEL) - v12 +- laravel/horizon (HORIZON) - v5 +- laravel/prompts (PROMPTS) - v0 +- laravel/sanctum (SANCTUM) - v4 +- laravel/socialite (SOCIALITE) - v5 +- livewire/livewire (LIVEWIRE) - v3 +- laravel/dusk (DUSK) - v8 +- laravel/pint (PINT) - v1 +- laravel/telescope (TELESCOPE) - v5 +- pestphp/pest (PEST) - v3 +- phpunit/phpunit (PHPUNIT) - v11 +- rector/rector (RECTOR) - v2 +- laravel-echo (ECHO) - v2 +- tailwindcss (TAILWINDCSS) - v4 +- vue (VUE) - v3 + + +## Conventions +- You must follow all existing code conventions used in this application. When creating or editing a file, check sibling files for the correct structure, approach, naming. +- Use descriptive names for variables and methods. For example, `isRegisteredForDiscounts`, not `discount()`. +- Check for existing components to reuse before writing a new one. + +## Verification Scripts +- Do not create verification scripts or tinker when tests cover that functionality and prove it works. Unit and feature tests are more important. + +## Application Structure & Architecture +- Stick to existing directory structure - don't create new base folders without approval. +- Do not change the application's dependencies without approval. + +## Frontend Bundling +- If the user doesn't see a frontend change reflected in the UI, it could mean they need to run `npm run build`, `npm run dev`, or `composer run dev`. Ask them. + +## Replies +- Be concise in your explanations - focus on what's important rather than explaining obvious details. + +## Documentation Files +- You must only create documentation files if explicitly requested by the user. + + +=== boost rules === + +## Laravel Boost +- Laravel Boost is an MCP server that comes with powerful tools designed specifically for this application. Use them. + +## Artisan +- Use the `list-artisan-commands` tool when you need to call an Artisan command to double check the available parameters. + +## URLs +- Whenever you share a project URL with the user you should use the `get-absolute-url` tool to ensure you're using the correct scheme, domain / IP, and port. + +## Tinker / Debugging +- You should use the `tinker` tool when you need to execute PHP to debug code or query Eloquent models directly. +- Use the `database-query` tool when you only need to read from the database. + +## Reading Browser Logs With the `browser-logs` Tool +- You can read browser logs, errors, and exceptions using the `browser-logs` tool from Boost. +- Only recent browser logs will be useful - ignore old logs. + +## Searching Documentation (Critically Important) +- Boost comes with a powerful `search-docs` tool you should use before any other approaches. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation specific for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages. +- The 'search-docs' tool is perfect for all Laravel related packages, including Laravel, Inertia, Livewire, Filament, Tailwind, Pest, Nova, Nightwatch, etc. +- You must use this tool to search for Laravel-ecosystem documentation before falling back to other approaches. +- Search the documentation before making code changes to ensure we are taking the correct approach. +- Use multiple, broad, simple, topic based queries to start. For example: `['rate limiting', 'routing rate limiting', 'routing']`. +- Do not add package names to queries - package information is already shared. For example, use `test resource table`, not `filament 4 test resource table`. + +### Available Search Syntax +- You can and should pass multiple queries at once. The most relevant results will be returned first. + +1. Simple Word Searches with auto-stemming - query=authentication - finds 'authenticate' and 'auth' +2. Multiple Words (AND Logic) - query=rate limit - finds knowledge containing both "rate" AND "limit" +3. Quoted Phrases (Exact Position) - query="infinite scroll" - Words must be adjacent and in that order +4. Mixed Queries - query=middleware "rate limit" - "middleware" AND exact phrase "rate limit" +5. Multiple Queries - queries=["authentication", "middleware"] - ANY of these terms + + +=== php rules === + +## PHP + +- Always use curly braces for control structures, even if it has one line. + +### Constructors +- Use PHP 8 constructor property promotion in `__construct()`. + - public function __construct(public GitHub $github) { } +- Do not allow empty `__construct()` methods with zero parameters. + +### Type Declarations +- Always use explicit return type declarations for methods and functions. +- Use appropriate PHP type hints for method parameters. + + +protected function isAccessible(User $user, ?string $path = null): bool +{ + ... +} + + +## Comments +- Prefer PHPDoc blocks over comments. Never use comments within the code itself unless there is something _very_ complex going on. + +## PHPDoc Blocks +- Add useful array shape type definitions for arrays when appropriate. + +## Enums +- Typically, keys in an Enum should be TitleCase. For example: `FavoritePerson`, `BestLake`, `Monthly`. + + +=== laravel/core rules === + +## Do Things the Laravel Way + +- Use `php artisan make:` commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the `list-artisan-commands` tool. +- If you're creating a generic PHP class, use `artisan make:class`. +- Pass `--no-interaction` to all Artisan commands to ensure they work without user input. You should also pass the correct `--options` to ensure correct behavior. + +### Database +- Always use proper Eloquent relationship methods with return type hints. Prefer relationship methods over raw queries or manual joins. +- Use Eloquent models and relationships before suggesting raw database queries +- Avoid `DB::`; prefer `Model::query()`. Generate code that leverages Laravel's ORM capabilities rather than bypassing them. +- Generate code that prevents N+1 query problems by using eager loading. +- Use Laravel's query builder for very complex database operations. + +### Model Creation +- When creating new models, create useful factories and seeders for them too. Ask the user if they need any other things, using `list-artisan-commands` to check the available options to `php artisan make:model`. + +### APIs & Eloquent Resources +- For APIs, default to using Eloquent API Resources and API versioning unless existing API routes do not, then you should follow existing application convention. + +### Controllers & Validation +- Always create Form Request classes for validation rather than inline validation in controllers. Include both validation rules and custom error messages. +- Check sibling Form Requests to see if the application uses array or string based validation rules. + +### Queues +- Use queued jobs for time-consuming operations with the `ShouldQueue` interface. + +### Authentication & Authorization +- Use Laravel's built-in authentication and authorization features (gates, policies, Sanctum, etc.). + +### URL Generation +- When generating links to other pages, prefer named routes and the `route()` function. + +### Configuration +- Use environment variables only in configuration files - never use the `env()` function directly outside of config files. Always use `config('app.name')`, not `env('APP_NAME')`. + +### Testing +- When creating models for tests, use the factories for the models. Check if the factory has custom states that can be used before manually setting up the model. +- Faker: Use methods such as `$this->faker->word()` or `fake()->randomDigit()`. Follow existing conventions whether to use `$this->faker` or `fake()`. +- When creating tests, make use of `php artisan make:test [options] ` to create a feature test, and pass `--unit` to create a unit test. Most tests should be feature tests. + +### Vite Error +- If you receive an "Illuminate\Foundation\ViteException: Unable to locate file in Vite manifest" error, you can run `npm run build` or ask the user to run `npm run dev` or `composer run dev`. + + +=== laravel/v12 rules === + +## Laravel 12 + +- Use the `search-docs` tool to get version specific documentation. +- This project upgraded from Laravel 10 without migrating to the new streamlined Laravel file structure. +- This is **perfectly fine** and recommended by Laravel. Follow the existing structure from Laravel 10. We do not to need migrate to the new Laravel structure unless the user explicitly requests that. + +### Laravel 10 Structure +- Middleware typically lives in `app/Http/Middleware/` and service providers in `app/Providers/`. +- There is no `bootstrap/app.php` application configuration in a Laravel 10 structure: + - Middleware registration happens in `app/Http/Kernel.php` + - Exception handling is in `app/Exceptions/Handler.php` + - Console commands and schedule register in `app/Console/Kernel.php` + - Rate limits likely exist in `RouteServiceProvider` or `app/Http/Kernel.php` + +### Database +- When modifying a column, the migration must include all of the attributes that were previously defined on the column. Otherwise, they will be dropped and lost. +- Laravel 12 allows limiting eagerly loaded records natively, without external packages: `$query->latest()->limit(10);`. + +### Models +- Casts can and likely should be set in a `casts()` method on a model rather than the `$casts` property. Follow existing conventions from other models. + + +=== livewire/core rules === + +## Livewire Core +- Use the `search-docs` tool to find exact version specific documentation for how to write Livewire & Livewire tests. +- Use the `php artisan make:livewire [Posts\\CreatePost]` artisan command to create new components +- State should live on the server, with the UI reflecting it. +- All Livewire requests hit the Laravel backend, they're like regular HTTP requests. Always validate form data, and run authorization checks in Livewire actions. + +## Livewire Best Practices +- Livewire components require a single root element. +- Use `wire:loading` and `wire:dirty` for delightful loading states. +- Add `wire:key` in loops: + + ```blade + @foreach ($items as $item) +
+ {{ $item->name }} +
+ @endforeach + ``` + +- Prefer lifecycle hooks like `mount()`, `updatedFoo()`) for initialization and reactive side effects: + + + public function mount(User $user) { $this->user = $user; } + public function updatedSearch() { $this->resetPage(); } + + + +## Testing Livewire + + + Livewire::test(Counter::class) + ->assertSet('count', 0) + ->call('increment') + ->assertSet('count', 1) + ->assertSee(1) + ->assertStatus(200); + + + + + $this->get('/posts/create') + ->assertSeeLivewire(CreatePost::class); + + + +=== livewire/v3 rules === + +## Livewire 3 + +### Key Changes From Livewire 2 +- These things changed in Livewire 2, but may not have been updated in this application. Verify this application's setup to ensure you conform with application conventions. + - Use `wire:model.live` for real-time updates, `wire:model` is now deferred by default. + - Components now use the `App\Livewire` namespace (not `App\Http\Livewire`). + - Use `$this->dispatch()` to dispatch events (not `emit` or `dispatchBrowserEvent`). + - Use the `components.layouts.app` view as the typical layout path (not `layouts.app`). + +### New Directives +- `wire:show`, `wire:transition`, `wire:cloak`, `wire:offline`, `wire:target` are available for use. Use the documentation to find usage examples. + +### Alpine +- Alpine is now included with Livewire, don't manually include Alpine.js. +- Plugins included with Alpine: persist, intersect, collapse, and focus. + +### Lifecycle Hooks +- You can listen for `livewire:init` to hook into Livewire initialization, and `fail.status === 419` for the page expiring: + + +document.addEventListener('livewire:init', function () { + Livewire.hook('request', ({ fail }) => { + if (fail && fail.status === 419) { + alert('Your session expired'); + } + }); + + Livewire.hook('message.failed', (message, component) => { + console.error(message); + }); +}); + + + +=== pint/core rules === + +## Laravel Pint Code Formatter + +- You must run `vendor/bin/pint --dirty` before finalizing changes to ensure your code matches the project's expected style. +- Do not run `vendor/bin/pint --test`, simply run `vendor/bin/pint` to fix any formatting issues. + + +=== pest/core rules === + +## Pest + +### Testing +- If you need to verify a feature is working, write or update a Unit / Feature test. + +### Pest Tests +- All tests must be written using Pest. Use `php artisan make:test --pest `. +- You must not remove any tests or test files from the tests directory without approval. These are not temporary or helper files - these are core to the application. +- Tests should test all of the happy paths, failure paths, and weird paths. +- Tests live in the `tests/Feature` and `tests/Unit` directories. +- Pest tests look and behave like this: + +it('is true', function () { + expect(true)->toBeTrue(); +}); + + +### Running Tests +- Run the minimal number of tests using an appropriate filter before finalizing code edits. +- To run all tests: `php artisan test`. +- To run all tests in a file: `php artisan test tests/Feature/ExampleTest.php`. +- To filter on a particular test name: `php artisan test --filter=testName` (recommended after making a change to a related file). +- When the tests relating to your changes are passing, ask the user if they would like to run the entire test suite to ensure everything is still passing. + +### Pest Assertions +- When asserting status codes on a response, use the specific method like `assertForbidden` and `assertNotFound` instead of using `assertStatus(403)` or similar, e.g.: + +it('returns all', function () { + $response = $this->postJson('/api/docs', []); + + $response->assertSuccessful(); +}); + + +### Mocking +- Mocking can be very helpful when appropriate. +- When mocking, you can use the `Pest\Laravel\mock` Pest function, but always import it via `use function Pest\Laravel\mock;` before using it. Alternatively, you can use `$this->mock()` if existing tests do. +- You can also create partial mocks using the same import or self method. + +### Datasets +- Use datasets in Pest to simplify tests which have a lot of duplicated data. This is often the case when testing validation rules, so consider going with this solution when writing tests for validation rules. + + +it('has emails', function (string $email) { + expect($email)->not->toBeEmpty(); +})->with([ + 'james' => 'james@laravel.com', + 'taylor' => 'taylor@laravel.com', +]); + + + +=== tailwindcss/core rules === + +## Tailwind Core + +- Use Tailwind CSS classes to style HTML, check and use existing tailwind conventions within the project before writing your own. +- Offer to extract repeated patterns into components that match the project's conventions (i.e. Blade, JSX, Vue, etc..) +- Think through class placement, order, priority, and defaults - remove redundant classes, add classes to parent or child carefully to limit repetition, group elements logically +- You can use the `search-docs` tool to get exact examples from the official documentation when needed. + +### Spacing +- When listing items, use gap utilities for spacing, don't use margins. + + +
+
Superior
+
Michigan
+
Erie
+
+
+ + +### Dark Mode +- If existing pages and components support dark mode, new pages and components must support dark mode in a similar way, typically using `dark:`. + + +=== tailwindcss/v4 rules === + +## Tailwind 4 + +- Always use Tailwind CSS v4 - do not use the deprecated utilities. +- `corePlugins` is not supported in Tailwind v4. +- In Tailwind v4, you import Tailwind using a regular CSS `@import` statement, not using the `@tailwind` directives used in v3: + + + + +### Replaced Utilities +- Tailwind v4 removed deprecated utilities. Do not use the deprecated option - use the replacement. +- Opacity values are still numeric. + +| Deprecated | Replacement | +|------------+--------------| +| bg-opacity-* | bg-black/* | +| text-opacity-* | text-black/* | +| border-opacity-* | border-black/* | +| divide-opacity-* | divide-black/* | +| ring-opacity-* | ring-black/* | +| placeholder-opacity-* | placeholder-black/* | +| flex-shrink-* | shrink-* | +| flex-grow-* | grow-* | +| overflow-ellipsis | text-ellipsis | +| decoration-slice | box-decoration-slice | +| decoration-clone | box-decoration-clone | + + +=== tests rules === + +## Test Enforcement + +- Every change must be programmatically tested. Write a new test or update an existing test, then run the affected tests to make sure they pass. +- Run the minimum number of tests needed to ensure code quality and speed. Use `php artisan test` with a specific filename or filter. +
\ No newline at end of file diff --git a/.cursor/rules/project-overview.mdc b/.cursor/rules/project-overview.mdc new file mode 100644 index 0000000000..b615a5d3ee --- /dev/null +++ b/.cursor/rules/project-overview.mdc @@ -0,0 +1,161 @@ +--- +description: High-level project mission, core concepts, and architectural overview +globs: README.md, CONTRIBUTING.md, CHANGELOG.md, *.md +alwaysApply: false +--- +# Coolify Project Overview + +## What is Coolify? + +Coolify is an **open-source & self-hostable alternative to Heroku / Netlify / Vercel**. It's a comprehensive deployment platform that helps you manage servers, applications, and databases on your own hardware with just an SSH connection. + +## Core Mission + +**"Imagine having the ease of a cloud but with your own servers. That is Coolify."** + +- **No vendor lock-in** - All configurations saved to your servers +- **Self-hosted** - Complete control over your infrastructure +- **SSH-only requirement** - Works with VPS, Bare Metal, Raspberry PIs, anything +- **Docker-first** - Container-based deployment architecture + +## Key Features + +### 🚀 **Application Deployment** +- Git-based deployments (GitHub, GitLab, Bitbucket, Gitea) +- Docker & Docker Compose support +- Preview deployments for pull requests +- Zero-downtime deployments +- Build cache optimization + +### 🖥️ **Server Management** +- Multi-server orchestration +- Real-time monitoring and logs +- SSH key management +- Proxy configuration (Traefik/Caddy) +- Resource usage tracking + +### 🗄️ **Database Management** +- PostgreSQL, MySQL, MariaDB, MongoDB +- Redis, KeyDB, Dragonfly, ClickHouse +- Automated backups with S3 integration +- Database clustering support + +### 🔧 **Infrastructure as Code** +- Docker Compose generation +- Environment variable management +- SSL certificate automation +- Custom domain configuration + +### 👥 **Team Collaboration** +- Multi-tenant team organization +- Role-based access control +- Project and environment isolation +- Team-wide resource sharing + +### 📊 **Monitoring & Observability** +- Real-time application logs +- Server resource monitoring +- Deployment status tracking +- Webhook integrations +- Notification systems (Email, Discord, Slack, Telegram) + +## Target Users + +### **DevOps Engineers** +- Infrastructure automation +- Multi-environment management +- CI/CD pipeline integration + +### **Developers** +- Easy application deployment +- Development environment provisioning +- Preview deployments for testing + +### **Small to Medium Businesses** +- Cost-effective Heroku alternative +- Self-hosted control and privacy +- Scalable infrastructure management + +### **Agencies & Consultants** +- Client project isolation +- Multi-tenant management +- White-label deployment solutions + +## Business Model + +### **Open Source (Free)** +- Complete feature set +- Self-hosted deployment +- Community support +- No feature restrictions + +### **Cloud Version (Paid)** +- Managed Coolify instance +- High availability +- Premium support +- Email notifications included +- Same price as self-hosted server (~$4-5/month) + +## Architecture Philosophy + +### **Server-Side First** +- Laravel backend with Livewire frontend +- Minimal JavaScript footprint +- Real-time updates via WebSockets +- Progressive enhancement approach + +### **Docker-Native** +- Container-first deployment strategy +- Docker Compose orchestration +- Image building and registry integration +- Volume and network management + +### **Security-Focused** +- SSH-based server communication +- Environment variable encryption +- Team-based access isolation +- Audit logging and activity tracking + +## Project Structure + +``` +coolify/ +├── app/ # Laravel application core +│ ├── Models/ # Domain models (Application, Server, Service) +│ ├── Livewire/ # Frontend components +│ ├── Actions/ # Business logic actions +│ └── Jobs/ # Background job processing +├── resources/ # Frontend assets and views +├── database/ # Migrations and seeders +├── docker/ # Docker configuration +├── scripts/ # Installation and utility scripts +└── tests/ # Test suites (Pest, Dusk) +``` + +## Key Differentiators + +### **vs. Heroku** +- ✅ Self-hosted (no vendor lock-in) +- ✅ Multi-server support +- ✅ No usage-based pricing +- ✅ Full infrastructure control + +### **vs. Vercel/Netlify** +- ✅ Backend application support +- ✅ Database management included +- ✅ Multi-environment workflows +- ✅ Custom server infrastructure + +### **vs. Docker Swarm/Kubernetes** +- ✅ User-friendly web interface +- ✅ Git-based deployment workflows +- ✅ Integrated monitoring and logging +- ✅ No complex YAML configuration + +## Development Principles + +- **Simplicity over complexity** +- **Convention over configuration** +- **Security by default** +- **Developer experience focused** +- **Community-driven development** diff --git a/.cursor/rules/security-patterns.mdc b/.cursor/rules/security-patterns.mdc new file mode 100644 index 0000000000..a7ab2ad691 --- /dev/null +++ b/.cursor/rules/security-patterns.mdc @@ -0,0 +1,1105 @@ +--- +description: Security architecture, authentication, authorization patterns, and enhanced form component security +globs: app/Policies/*.php, app/View/Components/Forms/*.php, app/Http/Middleware/*.php, resources/views/**/*.blade.php +alwaysApply: true +--- +# Coolify Security Architecture & Patterns + +## Security Philosophy + +Coolify implements **defense-in-depth security** with multiple layers of protection including authentication, authorization, encryption, network isolation, and secure deployment practices. + +## Authentication Architecture + +### Multi-Provider Authentication +- **[Laravel Fortify](mdc:config/fortify.php)** - Core authentication scaffolding (4.9KB, 149 lines) +- **[Laravel Sanctum](mdc:config/sanctum.php)** - API token authentication (2.4KB, 69 lines) +- **[Laravel Socialite](mdc:config/services.php)** - OAuth provider integration + +### OAuth Integration +- **[OauthSetting.php](mdc:app/Models/OauthSetting.php)** - OAuth provider configurations +- **Supported Providers**: + - Google OAuth + - Microsoft Azure AD + - Clerk + - Authentik + - Discord + - GitHub (via GitHub Apps) + - GitLab + +### Authentication Models +```php +// User authentication with team-based access +class User extends Authenticatable +{ + use HasApiTokens, HasFactory, Notifiable; + + protected $fillable = [ + 'name', 'email', 'password' + ]; + + protected $hidden = [ + 'password', 'remember_token' + ]; + + protected $casts = [ + 'email_verified_at' => 'datetime', + 'password' => 'hashed', + ]; + + public function teams(): BelongsToMany + { + return $this->belongsToMany(Team::class) + ->withPivot('role') + ->withTimestamps(); + } + + public function currentTeam(): BelongsTo + { + return $this->belongsTo(Team::class, 'current_team_id'); + } +} +``` + +## Authorization & Access Control + +### Enhanced Form Component Authorization System + +Coolify now features a **centralized authorization system** built into all form components (`Input`, `Select`, `Textarea`, `Checkbox`, `Button`) that automatically handles permission-based UI control. + +#### Component Authorization Parameters +```php +// Available on all form components +public ?string $canGate = null; // Gate name (e.g., 'update', 'view', 'delete') +public mixed $canResource = null; // Resource to check against (model instance) +public bool $autoDisable = true; // Auto-disable if no permission (default: true) +``` + +#### Smart Authorization Logic +```php +// Automatic authorization handling in component constructor +if ($this->canGate && $this->canResource && $this->autoDisable) { + $hasPermission = Gate::allows($this->canGate, $this->canResource); + + if (! $hasPermission) { + $this->disabled = true; + // For Checkbox: also disables instantSave + } +} +``` + +#### Usage Examples + +**✅ Recommended Pattern (Single Line):** +```html + + + + + + + + + + + + + + + Save Configuration + +``` + +**❌ Old Pattern (Verbose, Deprecated):** +```html + +@can('update', $application) + + Save +@else + +@endcan +``` + +#### Advanced Usage with Custom Control + +**Custom Authorization Logic:** +```html + + +``` + +**Multiple Permission Checks:** +```html + + +``` + +#### Supported Gates and Resources + +**Common Gates:** +- `view` - Read access to resource +- `update` - Modify resource configuration +- `deploy` - Deploy/restart resource +- `delete` - Remove resource +- `createAnyResource` - Create new resources + +**Resource Types:** +- `Application` - Application instances +- `Service` - Docker Compose services +- `Server` - Server instances +- `Project` - Project containers +- `Environment` - Environment contexts +- `Database` - Database instances + +#### Benefits + +**🔥 Massive Code Reduction:** +- **90% less code** for authorization-protected forms +- **Single line** instead of 6-12 lines per form element +- **No more @can/@else blocks** cluttering templates + +**🛡️ Consistent Security:** +- **Unified authorization logic** across all form components +- **Automatic disabling** for unauthorized users +- **Smart behavior** (like disabling instantSave on checkboxes) + +**🎨 Better UX:** +- **Consistent disabled styling** across all components +- **Proper visual feedback** for restricted access +- **Clean, professional interface** + +#### Implementation Details + +**Component Enhancement:** +```php +// Enhanced in all form components +use Illuminate\Support\Facades\Gate; + +public function __construct( + // ... existing parameters + public ?string $canGate = null, + public mixed $canResource = null, + public bool $autoDisable = true, +) { + // Handle authorization-based disabling + if ($this->canGate && $this->canResource && $this->autoDisable) { + $hasPermission = Gate::allows($this->canGate, $this->canResource); + + if (! $hasPermission) { + $this->disabled = true; + // For Checkbox: $this->instantSave = false; + } + } +} +``` + +**Backward Compatibility:** +- All existing form components continue to work unchanged +- New authorization parameters are optional +- Legacy @can/@else patterns still function but are discouraged + +### Custom Component Authorization Patterns + +When dealing with **custom Alpine.js components** or complex UI elements that don't use the standard `x-forms.*` components, manual authorization protection is required since the automatic `canGate` system only applies to enhanced form components. + +#### Common Custom Components Requiring Manual Protection + +**⚠️ Custom Components That Need Manual Authorization:** +- Custom dropdowns/selects with Alpine.js +- Complex form widgets with JavaScript interactions +- Multi-step wizards or dynamic forms +- Third-party component integrations +- Custom date/time pickers +- File upload components with drag-and-drop + +#### Manual Authorization Pattern + +**✅ Proper Manual Authorization:** +```html + +
+
+ + +
+ @can('update', $resource) + +
+ +
+ + +
+
+ @else + +
+ + + + +
+ @endcan +
+``` + +#### Implementation Checklist + +When implementing authorization for custom components: + +**🔍 1. Identify Custom Components:** +- Look for Alpine.js `x-data` declarations +- Find components not using `x-forms.*` prefix +- Check for JavaScript-heavy interactions +- Review complex form widgets + +**🛡️ 2. Wrap with Authorization:** +- Use `@can('gate', $resource)` / `@else` / `@endcan` structure +- Provide full functionality in the `@can` block +- Create disabled/readonly version in the `@else` block + +**🎨 3. Design Disabled State:** +- Apply `readonly disabled` attributes to inputs +- Add `opacity-50 cursor-not-allowed` classes for visual feedback +- Remove interactive JavaScript behaviors +- Show current value or appropriate placeholder + +**🔒 4. Backend Protection:** +- Ensure corresponding Livewire methods check authorization +- Add `$this->authorize('gate', $resource)` in relevant methods +- Validate permissions before processing any changes + +#### Real-World Examples + +**Custom Date Range Picker:** +```html +@can('update', $application) +
+ +
+@else +
+ + +
+@endcan +``` + +**Multi-Select Component:** +```html +@can('update', $server) +
+ +
+@else +
+ @foreach($selectedValues as $value) +
+ {{ $value }} +
+ @endforeach +
+@endcan +``` + +**File Upload Widget:** +```html +@can('update', $application) +
+ +
+@else +
+

File upload restricted

+ @if($currentFile) +

Current: {{ $currentFile }}

+ @endif +
+@endcan +``` + +#### Key Principles + +**🎯 Consistency:** +- Maintain similar visual styling between enabled/disabled states +- Use consistent disabled patterns across the application +- Apply the same opacity and cursor styling + +**🔐 Security First:** +- Always implement backend authorization checks +- Never rely solely on frontend hiding/disabling +- Validate permissions on every server action + +**💡 User Experience:** +- Show current values in disabled state when appropriate +- Provide clear visual feedback about restricted access +- Maintain layout stability between states + +**🚀 Performance:** +- Minimize Alpine.js initialization for disabled components +- Avoid loading unnecessary JavaScript for unauthorized users +- Use simple HTML structures for read-only states + +### Team-Based Multi-Tenancy +- **[Team.php](mdc:app/Models/Team.php)** - Multi-tenant organization structure (8.9KB, 308 lines) +- **[TeamInvitation.php](mdc:app/Models/TeamInvitation.php)** - Secure team collaboration +- **Role-based permissions** within teams +- **Resource isolation** by team ownership + +### Authorization Patterns +```php +// Team-scoped authorization middleware +class EnsureTeamAccess +{ + public function handle(Request $request, Closure $next): Response + { + $user = $request->user(); + $teamId = $request->route('team'); + + if (!$user->teams->contains('id', $teamId)) { + abort(403, 'Access denied to team resources'); + } + + // Set current team context + $user->switchTeam($teamId); + + return $next($request); + } +} + +// Resource-level authorization policies +class ApplicationPolicy +{ + public function view(User $user, Application $application): bool + { + return $user->teams->contains('id', $application->team_id); + } + + public function deploy(User $user, Application $application): bool + { + return $this->view($user, $application) && + $user->hasTeamPermission($application->team_id, 'deploy'); + } + + public function delete(User $user, Application $application): bool + { + return $this->view($user, $application) && + $user->hasTeamRole($application->team_id, 'admin'); + } +} +``` + +### Global Scopes for Data Isolation +```php +// Automatic team-based filtering +class Application extends Model +{ + protected static function booted(): void + { + static::addGlobalScope('team', function (Builder $builder) { + if (auth()->check() && auth()->user()->currentTeam) { + $builder->whereHas('environment.project', function ($query) { + $query->where('team_id', auth()->user()->currentTeam->id); + }); + } + }); + } +} +``` + +## API Security + +### Token-Based Authentication +```php +// Sanctum API token management +class PersonalAccessToken extends Model +{ + protected $fillable = [ + 'name', 'token', 'abilities', 'expires_at' + ]; + + protected $casts = [ + 'abilities' => 'array', + 'expires_at' => 'datetime', + 'last_used_at' => 'datetime', + ]; + + public function tokenable(): MorphTo + { + return $this->morphTo(); + } + + public function hasAbility(string $ability): bool + { + return in_array('*', $this->abilities) || + in_array($ability, $this->abilities); + } +} +``` + +### API Rate Limiting +```php +// Rate limiting configuration +RateLimiter::for('api', function (Request $request) { + return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip()); +}); + +RateLimiter::for('deployments', function (Request $request) { + return Limit::perMinute(10)->by($request->user()->id); +}); + +RateLimiter::for('webhooks', function (Request $request) { + return Limit::perMinute(100)->by($request->ip()); +}); +``` + +### API Input Validation +```php +// Comprehensive input validation +class StoreApplicationRequest extends FormRequest +{ + public function authorize(): bool + { + return $this->user()->can('create', Application::class); + } + + public function rules(): array + { + return [ + 'name' => 'required|string|max:255|regex:/^[a-zA-Z0-9\-_]+$/', + 'git_repository' => 'required|url|starts_with:https://', + 'git_branch' => 'required|string|max:100|regex:/^[a-zA-Z0-9\-_\/]+$/', + 'server_id' => 'required|exists:servers,id', + 'environment_id' => 'required|exists:environments,id', + 'environment_variables' => 'array', + 'environment_variables.*' => 'string|max:1000', + ]; + } + + public function prepareForValidation(): void + { + $this->merge([ + 'name' => strip_tags($this->name), + 'git_repository' => filter_var($this->git_repository, FILTER_SANITIZE_URL), + ]); + } +} +``` + +## SSH Security + +### Private Key Management +- **[PrivateKey.php](mdc:app/Models/PrivateKey.php)** - Secure SSH key storage (6.5KB, 247 lines) +- **Encrypted key storage** in database +- **Key rotation** capabilities +- **Access logging** for key usage + +### SSH Connection Security +```php +class SshConnection +{ + private string $host; + private int $port; + private string $username; + private PrivateKey $privateKey; + + public function __construct(Server $server) + { + $this->host = $server->ip; + $this->port = $server->port; + $this->username = $server->user; + $this->privateKey = $server->privateKey; + } + + public function connect(): bool + { + $connection = ssh2_connect($this->host, $this->port); + + if (!$connection) { + throw new SshConnectionException('Failed to connect to server'); + } + + // Use private key authentication + $privateKeyContent = decrypt($this->privateKey->private_key); + $publicKeyContent = decrypt($this->privateKey->public_key); + + if (!ssh2_auth_pubkey_file($connection, $this->username, $publicKeyContent, $privateKeyContent)) { + throw new SshAuthenticationException('SSH authentication failed'); + } + + return true; + } + + public function execute(string $command): string + { + // Sanitize command to prevent injection + $command = escapeshellcmd($command); + + $stream = ssh2_exec($this->connection, $command); + + if (!$stream) { + throw new SshExecutionException('Failed to execute command'); + } + + return stream_get_contents($stream); + } +} +``` + +## Container Security + +### Docker Security Patterns +```php +class DockerSecurityService +{ + public function createSecureContainer(Application $application): array + { + return [ + 'image' => $this->validateImageName($application->docker_image), + 'user' => '1000:1000', // Non-root user + 'read_only' => true, + 'no_new_privileges' => true, + 'security_opt' => [ + 'no-new-privileges:true', + 'apparmor:docker-default' + ], + 'cap_drop' => ['ALL'], + 'cap_add' => ['CHOWN', 'SETUID', 'SETGID'], // Minimal capabilities + 'tmpfs' => [ + '/tmp' => 'rw,noexec,nosuid,size=100m', + '/var/tmp' => 'rw,noexec,nosuid,size=50m' + ], + 'ulimits' => [ + 'nproc' => 1024, + 'nofile' => 1024 + ] + ]; + } + + private function validateImageName(string $image): string + { + // Validate image name against allowed registries + $allowedRegistries = ['docker.io', 'ghcr.io', 'quay.io']; + + $parser = new DockerImageParser(); + $parsed = $parser->parse($image); + + if (!in_array($parsed['registry'], $allowedRegistries)) { + throw new SecurityException('Image registry not allowed'); + } + + return $image; + } +} +``` + +### Network Isolation +```yaml +# Docker Compose security configuration +version: '3.8' +services: + app: + image: ${APP_IMAGE} + networks: + - app-network + security_opt: + - no-new-privileges:true + - apparmor:docker-default + read_only: true + tmpfs: + - /tmp:rw,noexec,nosuid,size=100m + cap_drop: + - ALL + cap_add: + - CHOWN + - SETUID + - SETGID + +networks: + app-network: + driver: bridge + internal: true + ipam: + config: + - subnet: 172.20.0.0/16 +``` + +## SSL/TLS Security + +### Certificate Management +- **[SslCertificate.php](mdc:app/Models/SslCertificate.php)** - SSL certificate automation +- **Let's Encrypt** integration for free certificates +- **Automatic renewal** and monitoring +- **Custom certificate** upload support + +### SSL Configuration +```php +class SslCertificateService +{ + public function generateCertificate(Application $application): SslCertificate + { + $domains = $this->validateDomains($application->getAllDomains()); + + $certificate = SslCertificate::create([ + 'application_id' => $application->id, + 'domains' => $domains, + 'provider' => 'letsencrypt', + 'status' => 'pending' + ]); + + // Generate certificate using ACME protocol + $acmeClient = new AcmeClient(); + $certData = $acmeClient->generateCertificate($domains); + + $certificate->update([ + 'certificate' => encrypt($certData['certificate']), + 'private_key' => encrypt($certData['private_key']), + 'chain' => encrypt($certData['chain']), + 'expires_at' => $certData['expires_at'], + 'status' => 'active' + ]); + + return $certificate; + } + + private function validateDomains(array $domains): array + { + foreach ($domains as $domain) { + if (!filter_var($domain, FILTER_VALIDATE_DOMAIN)) { + throw new InvalidDomainException("Invalid domain: {$domain}"); + } + + // Check domain ownership + if (!$this->verifyDomainOwnership($domain)) { + throw new DomainOwnershipException("Domain ownership verification failed: {$domain}"); + } + } + + return $domains; + } +} +``` + +## Environment Variable Security + +### Secure Configuration Management +```php +class EnvironmentVariable extends Model +{ + protected $fillable = [ + 'key', 'value', 'is_secret', 'application_id' + ]; + + protected $casts = [ + 'is_secret' => 'boolean', + 'value' => 'encrypted' // Automatic encryption for sensitive values + ]; + + public function setValueAttribute($value): void + { + // Automatically encrypt sensitive environment variables + if ($this->isSensitiveKey($this->key)) { + $this->attributes['value'] = encrypt($value); + $this->attributes['is_secret'] = true; + } else { + $this->attributes['value'] = $value; + } + } + + public function getValueAttribute($value): string + { + if ($this->is_secret) { + return decrypt($value); + } + + return $value; + } + + private function isSensitiveKey(string $key): bool + { + $sensitivePatterns = [ + 'PASSWORD', 'SECRET', 'KEY', 'TOKEN', 'API_KEY', + 'DATABASE_URL', 'REDIS_URL', 'PRIVATE', 'CREDENTIAL', + 'AUTH', 'CERTIFICATE', 'ENCRYPTION', 'SALT', 'HASH', + 'OAUTH', 'JWT', 'BEARER', 'ACCESS', 'REFRESH' + ]; + + foreach ($sensitivePatterns as $pattern) { + if (str_contains(strtoupper($key), $pattern)) { + return true; + } + } + + return false; + } +} +``` + +## Webhook Security + +### Webhook Signature Verification +```php +class WebhookSecurityService +{ + public function verifyGitHubSignature(Request $request, string $secret): bool + { + $signature = $request->header('X-Hub-Signature-256'); + + if (!$signature) { + return false; + } + + $expectedSignature = 'sha256=' . hash_hmac('sha256', $request->getContent(), $secret); + + return hash_equals($expectedSignature, $signature); + } + + public function verifyGitLabSignature(Request $request, string $secret): bool + { + $signature = $request->header('X-Gitlab-Token'); + + return hash_equals($secret, $signature); + } + + public function validateWebhookPayload(array $payload): array + { + // Sanitize and validate webhook payload + $validator = Validator::make($payload, [ + 'repository.clone_url' => 'required|url|starts_with:https://', + 'ref' => 'required|string|max:255', + 'head_commit.id' => 'required|string|size:40', // Git SHA + 'head_commit.message' => 'required|string|max:1000' + ]); + + if ($validator->fails()) { + throw new InvalidWebhookPayloadException('Invalid webhook payload'); + } + + return $validator->validated(); + } +} +``` + +## Input Sanitization & Validation + +### XSS Prevention +```php +class SecurityMiddleware +{ + public function handle(Request $request, Closure $next): Response + { + // Sanitize input data + $input = $request->all(); + $sanitized = $this->sanitizeInput($input); + $request->merge($sanitized); + + return $next($request); + } + + private function sanitizeInput(array $input): array + { + foreach ($input as $key => $value) { + if (is_string($value)) { + // Remove potentially dangerous HTML tags + $input[$key] = strip_tags($value, '


'); + + // Escape special characters + $input[$key] = htmlspecialchars($input[$key], ENT_QUOTES, 'UTF-8'); + } elseif (is_array($value)) { + $input[$key] = $this->sanitizeInput($value); + } + } + + return $input; + } +} +``` + +### SQL Injection Prevention +```php +// Always use parameterized queries and Eloquent ORM +class ApplicationRepository +{ + public function findByName(string $name): ?Application + { + // Safe: Uses parameter binding + return Application::where('name', $name)->first(); + } + + public function searchApplications(string $query): Collection + { + // Safe: Eloquent handles escaping + return Application::where('name', 'LIKE', "%{$query}%") + ->orWhere('description', 'LIKE', "%{$query}%") + ->get(); + } + + // NEVER do this - vulnerable to SQL injection + // public function unsafeSearch(string $query): Collection + // { + // return DB::select("SELECT * FROM applications WHERE name LIKE '%{$query}%'"); + // } +} +``` + +## Audit Logging & Monitoring + +### Activity Logging +```php +// Using Spatie Activity Log package +class Application extends Model +{ + use LogsActivity; + + protected static $logAttributes = [ + 'name', 'git_repository', 'git_branch', 'fqdn' + ]; + + protected static $logOnlyDirty = true; + + public function getDescriptionForEvent(string $eventName): string + { + return "Application {$this->name} was {$eventName}"; + } +} + +// Custom security events +class SecurityEventLogger +{ + public function logFailedLogin(string $email, string $ip): void + { + activity('security') + ->withProperties([ + 'email' => $email, + 'ip' => $ip, + 'user_agent' => request()->userAgent() + ]) + ->log('Failed login attempt'); + } + + public function logSuspiciousActivity(User $user, string $activity): void + { + activity('security') + ->causedBy($user) + ->withProperties([ + 'activity' => $activity, + 'ip' => request()->ip(), + 'timestamp' => now() + ]) + ->log('Suspicious activity detected'); + } +} +``` + +### Security Monitoring +```php +class SecurityMonitoringService +{ + public function detectAnomalousActivity(User $user): bool + { + // Check for unusual login patterns + $recentLogins = $user->activities() + ->where('description', 'like', '%login%') + ->where('created_at', '>=', now()->subHours(24)) + ->get(); + + // Multiple failed attempts + $failedAttempts = $recentLogins->where('description', 'Failed login attempt')->count(); + if ($failedAttempts > 5) { + $this->triggerSecurityAlert($user, 'Multiple failed login attempts'); + return true; + } + + // Login from new location + $uniqueIps = $recentLogins->pluck('properties.ip')->unique(); + if ($uniqueIps->count() > 3) { + $this->triggerSecurityAlert($user, 'Login from multiple IP addresses'); + return true; + } + + return false; + } + + private function triggerSecurityAlert(User $user, string $reason): void + { + // Send security notification + $user->notify(new SecurityAlertNotification($reason)); + + // Log security event + activity('security') + ->causedBy($user) + ->withProperties(['reason' => $reason]) + ->log('Security alert triggered'); + } +} +``` + +## Backup Security + +### Encrypted Backups +```php +class SecureBackupService +{ + public function createEncryptedBackup(ScheduledDatabaseBackup $backup): void + { + $database = $backup->database; + $dumpPath = $this->createDatabaseDump($database); + + // Encrypt backup file + $encryptedPath = $this->encryptFile($dumpPath, $backup->encryption_key); + + // Upload to secure storage + $this->uploadToSecureStorage($encryptedPath, $backup->s3Storage); + + // Clean up local files + unlink($dumpPath); + unlink($encryptedPath); + } + + private function encryptFile(string $filePath, string $key): string + { + $data = file_get_contents($filePath); + $encryptedData = encrypt($data, $key); + + $encryptedPath = $filePath . '.encrypted'; + file_put_contents($encryptedPath, $encryptedData); + + return $encryptedPath; + } +} +``` + +## Security Headers & CORS + +### Security Headers Configuration +```php +// Security headers middleware +class SecurityHeadersMiddleware +{ + public function handle(Request $request, Closure $next): Response + { + $response = $next($request); + + $response->headers->set('X-Content-Type-Options', 'nosniff'); + $response->headers->set('X-Frame-Options', 'DENY'); + $response->headers->set('X-XSS-Protection', '1; mode=block'); + $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin'); + $response->headers->set('Permissions-Policy', 'geolocation=(), microphone=(), camera=()'); + + if ($request->secure()) { + $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); + } + + return $response; + } +} +``` + +### CORS Configuration +```php +// CORS configuration for API endpoints +return [ + 'paths' => ['api/*', 'webhooks/*'], + 'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], + 'allowed_origins' => [ + 'https://app.coolify.io', + 'https://*.coolify.io' + ], + 'allowed_origins_patterns' => [], + 'allowed_headers' => ['*'], + 'exposed_headers' => [], + 'max_age' => 0, + 'supports_credentials' => true, +]; +``` + +## Security Testing + +### Security Test Patterns +```php +// Security-focused tests +test('prevents SQL injection in search', function () { + $user = User::factory()->create(); + $maliciousInput = "'; DROP TABLE applications; --"; + + $response = $this->actingAs($user) + ->getJson("/api/v1/applications?search={$maliciousInput}"); + + $response->assertStatus(200); + + // Verify applications table still exists + expect(Schema::hasTable('applications'))->toBeTrue(); +}); + +test('prevents XSS in application names', function () { + $user = User::factory()->create(); + $xssPayload = ''; + + $response = $this->actingAs($user) + ->postJson('/api/v1/applications', [ + 'name' => $xssPayload, + 'git_repository' => 'https://github.com/user/repo.git', + 'server_id' => Server::factory()->create()->id + ]); + + $response->assertStatus(422); +}); + +test('enforces team isolation', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + + $team1 = Team::factory()->create(); + $team2 = Team::factory()->create(); + + $user1->teams()->attach($team1); + $user2->teams()->attach($team2); + + $application = Application::factory()->create(['team_id' => $team1->id]); + + $response = $this->actingAs($user2) + ->getJson("/api/v1/applications/{$application->id}"); + + $response->assertStatus(403); +}); +``` diff --git a/.cursor/rules/self_improve.mdc b/.cursor/rules/self_improve.mdc new file mode 100644 index 0000000000..2bebaec759 --- /dev/null +++ b/.cursor/rules/self_improve.mdc @@ -0,0 +1,59 @@ +--- +description: Guidelines for continuously improving Cursor rules based on emerging code patterns and best practices. +globs: **/* +alwaysApply: true +--- + +- **Rule Improvement Triggers:** + - New code patterns not covered by existing rules + - Repeated similar implementations across files + - Common error patterns that could be prevented + - New libraries or tools being used consistently + - Emerging best practices in the codebase + +- **Analysis Process:** + - Compare new code with existing rules + - Identify patterns that should be standardized + - Look for references to external documentation + - Check for consistent error handling patterns + - Monitor test patterns and coverage + +- **Rule Updates:** + - **Add New Rules When:** + - A new technology/pattern is used in 3+ files + - Common bugs could be prevented by a rule + - Code reviews repeatedly mention the same feedback + - New security or performance patterns emerge + + - **Modify Existing Rules When:** + - Better examples exist in the codebase + - Additional edge cases are discovered + - Related rules have been updated + - Implementation details have changed + + +- **Rule Quality Checks:** + - Rules should be actionable and specific + - Examples should come from actual code + - References should be up to date + - Patterns should be consistently enforced + +- **Continuous Improvement:** + - Monitor code review comments + - Track common development questions + - Update rules after major refactors + - Add links to relevant documentation + - Cross-reference related rules + +- **Rule Deprecation:** + - Mark outdated patterns as deprecated + - Remove rules that no longer apply + - Update references to deprecated rules + - Document migration paths for old patterns + +- **Documentation Updates:** + - Keep examples synchronized with code + - Update references to external docs + - Maintain links between related rules + - Document breaking changes +Follow [cursor_rules.mdc](mdc:.cursor/rules/cursor_rules.mdc) for proper rule formatting and structure. diff --git a/.cursor/rules/technology-stack.mdc b/.cursor/rules/technology-stack.mdc new file mode 100644 index 0000000000..2119a2ff1d --- /dev/null +++ b/.cursor/rules/technology-stack.mdc @@ -0,0 +1,250 @@ +--- +description: Complete technology stack, dependencies, and infrastructure components +globs: composer.json, package.json, docker-compose*.yml, config/*.php +alwaysApply: false +--- +# Coolify Technology Stack + +## Backend Framework + +### **Laravel 12.4.1** (PHP Framework) +- **Location**: [composer.json](mdc:composer.json) +- **Purpose**: Core application framework +- **Key Features**: + - Eloquent ORM for database interactions + - Artisan CLI for development tasks + - Queue system for background jobs + - Event-driven architecture + +### **PHP 8.4** +- **Requirement**: `^8.4` in [composer.json](mdc:composer.json) +- **Features Used**: + - Typed properties and return types + - Attributes for validation and configuration + - Match expressions + - Constructor property promotion + +## Frontend Stack + +### **Livewire 3.5.20** (Primary Frontend Framework) +- **Purpose**: Server-side rendering with reactive components +- **Location**: [app/Livewire/](mdc:app/Livewire/) +- **Key Components**: + - [Dashboard.php](mdc:app/Livewire/Dashboard.php) - Main interface + - [ActivityMonitor.php](mdc:app/Livewire/ActivityMonitor.php) - Real-time monitoring + - [MonacoEditor.php](mdc:app/Livewire/MonacoEditor.php) - Code editor + +### **Alpine.js** (Client-Side Interactivity) +- **Purpose**: Lightweight JavaScript for DOM manipulation +- **Integration**: Works seamlessly with Livewire components +- **Usage**: Declarative directives in Blade templates + +### **Tailwind CSS 4.1.4** (Styling Framework) +- **Location**: [package.json](mdc:package.json) +- **Configuration**: [postcss.config.cjs](mdc:postcss.config.cjs) +- **Extensions**: + - `@tailwindcss/forms` - Form styling + - `@tailwindcss/typography` - Content typography + - `tailwind-scrollbar` - Custom scrollbars + +### **Vue.js 3.5.13** (Component Framework) +- **Purpose**: Enhanced interactive components +- **Integration**: Used alongside Livewire for complex UI +- **Build Tool**: Vite with Vue plugin + +## Database & Caching + +### **PostgreSQL 15** (Primary Database) +- **Purpose**: Main application data storage +- **Features**: JSONB support, advanced indexing +- **Models**: [app/Models/](mdc:app/Models/) + +### **Redis 7** (Caching & Real-time) +- **Purpose**: + - Session storage + - Queue backend + - Real-time data caching + - WebSocket session management + +### **Supported Databases** (For User Applications) +- **PostgreSQL**: [StandalonePostgresql.php](mdc:app/Models/StandalonePostgresql.php) +- **MySQL**: [StandaloneMysql.php](mdc:app/Models/StandaloneMysql.php) +- **MariaDB**: [StandaloneMariadb.php](mdc:app/Models/StandaloneMariadb.php) +- **MongoDB**: [StandaloneMongodb.php](mdc:app/Models/StandaloneMongodb.php) +- **Redis**: [StandaloneRedis.php](mdc:app/Models/StandaloneRedis.php) +- **KeyDB**: [StandaloneKeydb.php](mdc:app/Models/StandaloneKeydb.php) +- **Dragonfly**: [StandaloneDragonfly.php](mdc:app/Models/StandaloneDragonfly.php) +- **ClickHouse**: [StandaloneClickhouse.php](mdc:app/Models/StandaloneClickhouse.php) + +## Authentication & Security + +### **Laravel Sanctum 4.0.8** +- **Purpose**: API token authentication +- **Usage**: Secure API access for external integrations + +### **Laravel Fortify 1.25.4** +- **Purpose**: Authentication scaffolding +- **Features**: Login, registration, password reset + +### **Laravel Socialite 5.18.0** +- **Purpose**: OAuth provider integration +- **Providers**: + - GitHub, GitLab, Google + - Microsoft Azure, Authentik, Discord, Clerk + - Custom OAuth implementations + +## Background Processing + +### **Laravel Horizon 5.30.3** +- **Purpose**: Queue monitoring and management +- **Features**: Real-time queue metrics, failed job handling + +### **Queue System** +- **Backend**: Redis-based queues +- **Jobs**: [app/Jobs/](mdc:app/Jobs/) +- **Processing**: Background deployment and monitoring tasks + +## Development Tools + +### **Build Tools** +- **Vite 6.2.6**: Modern build tool and dev server +- **Laravel Vite Plugin**: Laravel integration +- **PostCSS**: CSS processing pipeline + +### **Code Quality** +- **Laravel Pint**: PHP code style fixer +- **Rector**: PHP automated refactoring +- **PHPStan**: Static analysis tool + +### **Testing Framework** +- **Pest 3.8.0**: Modern PHP testing framework +- **Laravel Dusk**: Browser automation testing +- **PHPUnit**: Unit testing foundation + +## External Integrations + +### **Git Providers** +- **GitHub**: Repository integration and webhooks +- **GitLab**: Self-hosted and cloud GitLab support +- **Bitbucket**: Atlassian integration +- **Gitea**: Self-hosted Git service + +### **Cloud Storage** +- **AWS S3**: [league/flysystem-aws-s3-v3](mdc:composer.json) +- **SFTP**: [league/flysystem-sftp-v3](mdc:composer.json) +- **Local Storage**: File system integration + +### **Notification Services** +- **Email**: [resend/resend-laravel](mdc:composer.json) +- **Discord**: Custom webhook integration +- **Slack**: Webhook notifications +- **Telegram**: Bot API integration +- **Pushover**: Push notifications + +### **Monitoring & Logging** +- **Sentry**: [sentry/sentry-laravel](mdc:composer.json) - Error tracking +- **Laravel Ray**: [spatie/laravel-ray](mdc:composer.json) - Debug tool +- **Activity Log**: [spatie/laravel-activitylog](mdc:composer.json) + +## DevOps & Infrastructure + +### **Docker & Containerization** +- **Docker**: Container runtime +- **Docker Compose**: Multi-container orchestration +- **Docker Swarm**: Container clustering (optional) + +### **Web Servers & Proxies** +- **Nginx**: Primary web server +- **Traefik**: Reverse proxy and load balancer +- **Caddy**: Alternative reverse proxy + +### **Process Management** +- **S6 Overlay**: Process supervisor +- **Supervisor**: Alternative process manager + +### **SSL/TLS** +- **Let's Encrypt**: Automatic SSL certificates +- **Custom Certificates**: Manual SSL management + +## Terminal & Code Editing + +### **XTerm.js 5.5.0** +- **Purpose**: Web-based terminal emulator +- **Features**: SSH session management, real-time command execution +- **Addons**: Fit addon for responsive terminals + +### **Monaco Editor** +- **Purpose**: Code editor component +- **Features**: Syntax highlighting, auto-completion +- **Integration**: Environment variable editing, configuration files + +## API & Documentation + +### **OpenAPI/Swagger** +- **Documentation**: [openapi.json](mdc:openapi.json) (373KB) +- **Generator**: [zircote/swagger-php](mdc:composer.json) +- **API Routes**: [routes/api.php](mdc:routes/api.php) + +### **WebSocket Communication** +- **Laravel Echo**: Real-time event broadcasting +- **Pusher**: WebSocket service integration +- **Soketi**: Self-hosted WebSocket server + +## Package Management + +### **PHP Dependencies** ([composer.json](mdc:composer.json)) +```json +{ + "require": { + "php": "^8.4", + "laravel/framework": "12.4.1", + "livewire/livewire": "^3.5.20", + "spatie/laravel-data": "^4.13.1", + "lorisleiva/laravel-actions": "^2.8.6" + } +} +``` + +### **JavaScript Dependencies** ([package.json](mdc:package.json)) +```json +{ + "devDependencies": { + "vite": "^6.2.6", + "tailwindcss": "^4.1.4", + "@vitejs/plugin-vue": "5.2.3" + }, + "dependencies": { + "@xterm/xterm": "^5.5.0", + "ioredis": "5.6.0" + } +} +``` + +## Configuration Files + +### **Build Configuration** +- **[vite.config.js](mdc:vite.config.js)**: Frontend build setup +- **[postcss.config.cjs](mdc:postcss.config.cjs)**: CSS processing +- **[rector.php](mdc:rector.php)**: PHP refactoring rules +- **[pint.json](mdc:pint.json)**: Code style configuration + +### **Testing Configuration** +- **[phpunit.xml](mdc:phpunit.xml)**: Unit test configuration +- **[phpunit.dusk.xml](mdc:phpunit.dusk.xml)**: Browser test configuration +- **[tests/Pest.php](mdc:tests/Pest.php)**: Pest testing setup + +## Version Requirements + +### **Minimum Requirements** +- **PHP**: 8.4+ +- **Node.js**: 18+ (for build tools) +- **PostgreSQL**: 15+ +- **Redis**: 7+ +- **Docker**: 20.10+ +- **Docker Compose**: 2.0+ + +### **Recommended Versions** +- **Ubuntu**: 22.04 LTS or 24.04 LTS +- **Memory**: 2GB+ RAM +- **Storage**: 20GB+ available space +- **Network**: Stable internet connection for deployments diff --git a/.cursor/rules/testing-patterns.mdc b/.cursor/rules/testing-patterns.mdc new file mode 100644 index 0000000000..8d250b56a1 --- /dev/null +++ b/.cursor/rules/testing-patterns.mdc @@ -0,0 +1,653 @@ +--- +description: Testing strategies with Pest PHP, Laravel Dusk, and quality assurance patterns +globs: tests/**/*.php, database/factories/*.php +alwaysApply: false +--- +# Coolify Testing Architecture & Patterns + +> **Cross-Reference**: These detailed testing patterns align with the testing guidelines in **[CLAUDE.md](mdc:CLAUDE.md)**. Both documents share the same core principles about Docker execution and mocking preferences. + +## Testing Philosophy + +Coolify employs **comprehensive testing strategies** using modern PHP testing frameworks to ensure reliability of deployment operations, infrastructure management, and user interactions. + +### Test Execution Rules + +**CRITICAL**: Tests are categorized by database dependency: + +#### Unit Tests (`tests/Unit/`) +- **MUST NOT** use database connections +- **MUST** use mocking for models and external dependencies +- **CAN** run outside Docker: `./vendor/bin/pest tests/Unit` +- Purpose: Test isolated logic, helper functions, and business rules + +#### Feature Tests (`tests/Feature/`) +- **MAY** use database connections (factories, migrations, models) +- **MUST** run inside Docker container: `docker exec coolify php artisan test` +- **MUST** use `RefreshDatabase` trait if touching database +- Purpose: Test API endpoints, workflows, and integration scenarios + +**Rule of thumb**: If your test needs `Server::factory()->create()` or any database operation, it's a Feature test and MUST run in Docker. + +### Prefer Mocking Over Database + +When writing tests, always prefer mocking over real database operations: + +```php +// ❌ BAD: Unit test using database +it('extracts custom commands', function () { + $server = Server::factory()->create(['ip' => '1.2.3.4']); + $commands = extract_custom_proxy_commands($server, $yaml); + expect($commands)->toBeArray(); +}); + +// ✅ GOOD: Unit test using mocking +it('extracts custom commands', function () { + $server = Mockery::mock('App\Models\Server'); + $server->shouldReceive('proxyType')->andReturn('traefik'); + $commands = extract_custom_proxy_commands($server, $yaml); + expect($commands)->toBeArray(); +}); +``` + +**Design principles for testable code:** +- Use dependency injection instead of global state +- Create interfaces for external dependencies (SSH, Docker, etc.) +- Separate business logic from data persistence +- Make functions accept interfaces instead of concrete models when possible + +## Testing Framework Stack + +### Core Testing Tools +- **Pest PHP 3.8+** - Primary testing framework with expressive syntax +- **Laravel Dusk** - Browser automation and end-to-end testing +- **PHPUnit** - Underlying unit testing framework +- **Mockery** - Mocking and stubbing for isolated tests + +### Testing Configuration +- **[tests/Pest.php](mdc:tests/Pest.php)** - Pest configuration and global setup (1.5KB, 45 lines) +- **[tests/TestCase.php](mdc:tests/TestCase.php)** - Base test case class (163B, 11 lines) +- **[tests/CreatesApplication.php](mdc:tests/CreatesApplication.php)** - Application factory trait (375B, 22 lines) +- **[tests/DuskTestCase.php](mdc:tests/DuskTestCase.php)** - Browser testing setup (1.4KB, 58 lines) + +## Test Directory Structure + +### Test Organization +- **[tests/Feature/](mdc:tests/Feature)** - Feature and integration tests +- **[tests/Unit/](mdc:tests/Unit)** - Unit tests for isolated components +- **[tests/Browser/](mdc:tests/Browser)** - Laravel Dusk browser tests +- **[tests/Traits/](mdc:tests/Traits)** - Shared testing utilities + +## Unit Testing Patterns + +### Model Testing +```php +// Testing Eloquent models +test('application model has correct relationships', function () { + $application = Application::factory()->create(); + + expect($application->server)->toBeInstanceOf(Server::class); + expect($application->environment)->toBeInstanceOf(Environment::class); + expect($application->deployments)->toBeInstanceOf(Collection::class); +}); + +test('application can generate deployment configuration', function () { + $application = Application::factory()->create([ + 'name' => 'test-app', + 'git_repository' => 'https://github.com/user/repo.git' + ]); + + $config = $application->generateDockerCompose(); + + expect($config)->toContain('test-app'); + expect($config)->toContain('image:'); + expect($config)->toContain('networks:'); +}); +``` + +### Service Layer Testing +```php +// Testing service classes +test('configuration generator creates valid docker compose', function () { + $generator = new ConfigurationGenerator(); + $application = Application::factory()->create(); + + $compose = $generator->generateDockerCompose($application); + + expect($compose)->toBeString(); + expect(yaml_parse($compose))->toBeArray(); + expect($compose)->toContain('version: "3.8"'); +}); + +test('docker image parser validates image names', function () { + $parser = new DockerImageParser(); + + expect($parser->isValid('nginx:latest'))->toBeTrue(); + expect($parser->isValid('invalid-image-name'))->toBeFalse(); + expect($parser->parse('nginx:1.21'))->toEqual([ + 'registry' => 'docker.io', + 'namespace' => 'library', + 'repository' => 'nginx', + 'tag' => '1.21' + ]); +}); +``` + +### Action Testing +```php +// Testing Laravel Actions +test('deploy application action creates deployment queue', function () { + $application = Application::factory()->create(); + $action = new DeployApplicationAction(); + + $deployment = $action->handle($application); + + expect($deployment)->toBeInstanceOf(ApplicationDeploymentQueue::class); + expect($deployment->status)->toBe('queued'); + expect($deployment->application_id)->toBe($application->id); +}); + +test('server validation action checks ssh connectivity', function () { + $server = Server::factory()->create([ + 'ip' => '192.168.1.100', + 'port' => 22 + ]); + + $action = new ValidateServerAction(); + + // Mock SSH connection + $this->mock(SshConnection::class, function ($mock) { + $mock->shouldReceive('connect')->andReturn(true); + $mock->shouldReceive('execute')->with('docker --version')->andReturn('Docker version 20.10.0'); + }); + + $result = $action->handle($server); + + expect($result['ssh_connection'])->toBeTrue(); + expect($result['docker_installed'])->toBeTrue(); +}); +``` + +## Feature Testing Patterns + +### API Testing +```php +// Testing API endpoints +test('authenticated user can list applications', function () { + $user = User::factory()->create(); + $team = Team::factory()->create(); + $user->teams()->attach($team); + + $applications = Application::factory(3)->create([ + 'team_id' => $team->id + ]); + + $response = $this->actingAs($user) + ->getJson('/api/v1/applications'); + + $response->assertStatus(200) + ->assertJsonCount(3, 'data') + ->assertJsonStructure([ + 'data' => [ + '*' => ['id', 'name', 'fqdn', 'status', 'created_at'] + ] + ]); +}); + +test('user cannot access applications from other teams', function () { + $user = User::factory()->create(); + $otherTeam = Team::factory()->create(); + + $application = Application::factory()->create([ + 'team_id' => $otherTeam->id + ]); + + $response = $this->actingAs($user) + ->getJson("/api/v1/applications/{$application->id}"); + + $response->assertStatus(403); +}); +``` + +### Deployment Testing +```php +// Testing deployment workflows +test('application deployment creates docker containers', function () { + $application = Application::factory()->create([ + 'git_repository' => 'https://github.com/laravel/laravel.git', + 'git_branch' => 'main' + ]); + + // Mock Docker operations + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('app:latest'); + $mock->shouldReceive('createContainer')->andReturn('container_id'); + $mock->shouldReceive('startContainer')->andReturn(true); + }); + + $deployment = $application->deploy(); + + expect($deployment->status)->toBe('queued'); + + // Process the deployment job + $this->artisan('queue:work --once'); + + $deployment->refresh(); + expect($deployment->status)->toBe('success'); +}); + +test('failed deployment triggers rollback', function () { + $application = Application::factory()->create(); + + // Mock failed deployment + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andThrow(new DeploymentException('Build failed')); + }); + + $deployment = $application->deploy(); + + $this->artisan('queue:work --once'); + + $deployment->refresh(); + expect($deployment->status)->toBe('failed'); + expect($deployment->error_message)->toContain('Build failed'); +}); +``` + +### Webhook Testing +```php +// Testing webhook endpoints +test('github webhook triggers deployment', function () { + $application = Application::factory()->create([ + 'git_repository' => 'https://github.com/user/repo.git', + 'git_branch' => 'main' + ]); + + $payload = [ + 'ref' => 'refs/heads/main', + 'repository' => [ + 'clone_url' => 'https://github.com/user/repo.git' + ], + 'head_commit' => [ + 'id' => 'abc123', + 'message' => 'Update application' + ] + ]; + + $response = $this->postJson("/webhooks/github/{$application->id}", $payload); + + $response->assertStatus(200); + + expect($application->deployments()->count())->toBe(1); + expect($application->deployments()->first()->commit_sha)->toBe('abc123'); +}); + +test('webhook validates payload signature', function () { + $application = Application::factory()->create(); + + $payload = ['invalid' => 'payload']; + + $response = $this->postJson("/webhooks/github/{$application->id}", $payload); + + $response->assertStatus(400); +}); +``` + +## Browser Testing (Laravel Dusk) + +### End-to-End Testing +```php +// Testing complete user workflows +test('user can create and deploy application', function () { + $user = User::factory()->create(); + $server = Server::factory()->create(['team_id' => $user->currentTeam->id]); + + $this->browse(function (Browser $browser) use ($user, $server) { + $browser->loginAs($user) + ->visit('/applications/create') + ->type('name', 'Test Application') + ->type('git_repository', 'https://github.com/laravel/laravel.git') + ->type('git_branch', 'main') + ->select('server_id', $server->id) + ->press('Create Application') + ->assertPathIs('/applications/*') + ->assertSee('Test Application') + ->press('Deploy') + ->waitForText('Deployment started', 10) + ->assertSee('Deployment started'); + }); +}); + +test('user can monitor deployment logs in real-time', function () { + $user = User::factory()->create(); + $application = Application::factory()->create(['team_id' => $user->currentTeam->id]); + + $this->browse(function (Browser $browser) use ($user, $application) { + $browser->loginAs($user) + ->visit("/applications/{$application->id}") + ->press('Deploy') + ->waitForText('Deployment started') + ->click('@logs-tab') + ->waitFor('@deployment-logs') + ->assertSee('Building Docker image') + ->waitForText('Deployment completed', 30); + }); +}); +``` + +### UI Component Testing +```php +// Testing Livewire components +test('server status component updates in real-time', function () { + $user = User::factory()->create(); + $server = Server::factory()->create(['team_id' => $user->currentTeam->id]); + + $this->browse(function (Browser $browser) use ($user, $server) { + $browser->loginAs($user) + ->visit("/servers/{$server->id}") + ->assertSee('Status: Online') + ->waitFor('@server-metrics') + ->assertSee('CPU Usage') + ->assertSee('Memory Usage') + ->assertSee('Disk Usage'); + + // Simulate server going offline + $server->update(['status' => 'offline']); + + $browser->waitForText('Status: Offline', 5) + ->assertSee('Status: Offline'); + }); +}); +``` + +## Database Testing Patterns + +### Migration Testing +```php +// Testing database migrations +test('applications table has correct structure', function () { + expect(Schema::hasTable('applications'))->toBeTrue(); + expect(Schema::hasColumns('applications', [ + 'id', 'name', 'fqdn', 'git_repository', 'git_branch', + 'server_id', 'environment_id', 'created_at', 'updated_at' + ]))->toBeTrue(); +}); + +test('foreign key constraints are properly set', function () { + $application = Application::factory()->create(); + + expect($application->server)->toBeInstanceOf(Server::class); + expect($application->environment)->toBeInstanceOf(Environment::class); + + // Test cascade deletion + $application->server->delete(); + expect(Application::find($application->id))->toBeNull(); +}); +``` + +### Factory Testing +```php +// Testing model factories +test('application factory creates valid models', function () { + $application = Application::factory()->create(); + + expect($application->name)->toBeString(); + expect($application->git_repository)->toStartWith('https://'); + expect($application->server_id)->toBeInt(); + expect($application->environment_id)->toBeInt(); +}); + +test('application factory can create with custom attributes', function () { + $application = Application::factory()->create([ + 'name' => 'Custom App', + 'git_branch' => 'develop' + ]); + + expect($application->name)->toBe('Custom App'); + expect($application->git_branch)->toBe('develop'); +}); +``` + +## Queue Testing + +### Job Testing +```php +// Testing background jobs +test('deploy application job processes successfully', function () { + $application = Application::factory()->create(); + $deployment = ApplicationDeploymentQueue::factory()->create([ + 'application_id' => $application->id, + 'status' => 'queued' + ]); + + $job = new DeployApplicationJob($deployment); + + // Mock external dependencies + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('app:latest'); + $mock->shouldReceive('deployContainer')->andReturn(true); + }); + + $job->handle(); + + $deployment->refresh(); + expect($deployment->status)->toBe('success'); +}); + +test('failed job is retried with exponential backoff', function () { + $application = Application::factory()->create(); + $deployment = ApplicationDeploymentQueue::factory()->create([ + 'application_id' => $application->id + ]); + + $job = new DeployApplicationJob($deployment); + + // Mock failure + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andThrow(new Exception('Network error')); + }); + + expect(fn() => $job->handle())->toThrow(Exception::class); + + // Job should be retried + expect($job->tries)->toBe(3); + expect($job->backoff())->toBe([1, 5, 10]); +}); +``` + +## Security Testing + +### Authentication Testing +```php +// Testing authentication and authorization +test('unauthenticated users cannot access protected routes', function () { + $response = $this->get('/dashboard'); + $response->assertRedirect('/login'); +}); + +test('users can only access their team resources', function () { + $user1 = User::factory()->create(); + $user2 = User::factory()->create(); + + $team1 = Team::factory()->create(); + $team2 = Team::factory()->create(); + + $user1->teams()->attach($team1); + $user2->teams()->attach($team2); + + $application = Application::factory()->create(['team_id' => $team1->id]); + + $response = $this->actingAs($user2) + ->get("/applications/{$application->id}"); + + $response->assertStatus(403); +}); +``` + +### Input Validation Testing +```php +// Testing input validation and sanitization +test('application creation validates required fields', function () { + $user = User::factory()->create(); + + $response = $this->actingAs($user) + ->postJson('/api/v1/applications', []); + + $response->assertStatus(422) + ->assertJsonValidationErrors(['name', 'git_repository', 'server_id']); +}); + +test('malicious input is properly sanitized', function () { + $user = User::factory()->create(); + + $response = $this->actingAs($user) + ->postJson('/api/v1/applications', [ + 'name' => '', + 'git_repository' => 'javascript:alert("xss")', + 'server_id' => 'invalid' + ]); + + $response->assertStatus(422); +}); +``` + +## Performance Testing + +### Load Testing +```php +// Testing application performance under load +test('application list endpoint handles concurrent requests', function () { + $user = User::factory()->create(); + $applications = Application::factory(100)->create(['team_id' => $user->currentTeam->id]); + + $startTime = microtime(true); + + $response = $this->actingAs($user) + ->getJson('/api/v1/applications'); + + $endTime = microtime(true); + $responseTime = ($endTime - $startTime) * 1000; // Convert to milliseconds + + $response->assertStatus(200); + expect($responseTime)->toBeLessThan(500); // Should respond within 500ms +}); +``` + +### Memory Usage Testing +```php +// Testing memory efficiency +test('deployment process does not exceed memory limits', function () { + $initialMemory = memory_get_usage(); + + $application = Application::factory()->create(); + $deployment = $application->deploy(); + + // Process deployment + $this->artisan('queue:work --once'); + + $finalMemory = memory_get_usage(); + $memoryIncrease = $finalMemory - $initialMemory; + + expect($memoryIncrease)->toBeLessThan(50 * 1024 * 1024); // Less than 50MB +}); +``` + +## Test Utilities and Helpers + +### Custom Assertions +```php +// Custom test assertions +expect()->extend('toBeValidDockerCompose', function () { + $yaml = yaml_parse($this->value); + + return $yaml !== false && + isset($yaml['version']) && + isset($yaml['services']) && + is_array($yaml['services']); +}); + +expect()->extend('toHaveValidSshConnection', function () { + $server = $this->value; + + try { + $connection = new SshConnection($server); + return $connection->test(); + } catch (Exception $e) { + return false; + } +}); +``` + +### Test Traits +```php +// Shared testing functionality +trait CreatesTestServers +{ + protected function createTestServer(array $attributes = []): Server + { + return Server::factory()->create(array_merge([ + 'name' => 'Test Server', + 'ip' => '127.0.0.1', + 'port' => 22, + 'team_id' => $this->user->currentTeam->id + ], $attributes)); + } +} + +trait MocksDockerOperations +{ + protected function mockDockerService(): void + { + $this->mock(DockerService::class, function ($mock) { + $mock->shouldReceive('buildImage')->andReturn('test:latest'); + $mock->shouldReceive('createContainer')->andReturn('container_123'); + $mock->shouldReceive('startContainer')->andReturn(true); + $mock->shouldReceive('stopContainer')->andReturn(true); + }); + } +} +``` + +## Continuous Integration Testing + +### GitHub Actions Integration +```yaml +# .github/workflows/tests.yml +name: Tests +on: [push, pull_request] +jobs: + test: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_PASSWORD: password + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + steps: + - uses: actions/checkout@v3 + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.4 + - name: Install dependencies + run: composer install + - name: Run tests + run: ./vendor/bin/pest +``` + +### Test Coverage +```php +// Generate test coverage reports +test('application has adequate test coverage', function () { + $coverage = $this->getCoverageData(); + + expect($coverage['application'])->toBeGreaterThan(80); + expect($coverage['models'])->toBeGreaterThan(90); + expect($coverage['actions'])->toBeGreaterThan(85); +}); +``` diff --git a/.dockerignore b/.dockerignore index 3a0ec49f78..6f3c903f0f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,7 +3,6 @@ /public/build /public/hot /public/storage -/storage/*.key /vendor .env .env.backup @@ -23,3 +22,17 @@ yarn-error.log .rnd /.ssh .ignition.json +.env.dusk.local +docker/coolify-realtime/node_modules + +/storage/*.key +/storage/app/backups +/storage/app/ssh/keys +/storage/app/ssh/mux +/storage/app/tmp +/storage/app/debugbar +/storage/logs +/storage/pail + + + diff --git a/.env.dusk.ci b/.env.dusk.ci new file mode 100644 index 0000000000..9660de7b48 --- /dev/null +++ b/.env.dusk.ci @@ -0,0 +1,15 @@ +APP_ENV=production +APP_NAME="Coolify Staging" +APP_ID=development +APP_KEY= +APP_URL=http://localhost +APP_PORT=8000 +SSH_MUX_ENABLED=true + +# PostgreSQL Database Configuration +DB_DATABASE=coolify +DB_USERNAME=coolify +DB_PASSWORD=password +DB_HOST=localhost +DB_PORT=5432 + diff --git a/.env.production b/.env.production index 099ec7c250..fe3c8370e2 100644 --- a/.env.production +++ b/.env.production @@ -1,16 +1,18 @@ -# Coolify Configuration APP_ID= APP_NAME=Coolify APP_KEY= -# PostgreSQL Database Configuration DB_USERNAME=coolify DB_PASSWORD= -# Redis Configuration REDIS_PASSWORD= -# Pusher Configuration PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= + +ROOT_USERNAME= +ROOT_USER_EMAIL= +ROOT_USER_PASSWORD= + +REGISTRY_URL=ghcr.io diff --git a/.env.windows-docker-desktop.example b/.env.windows-docker-desktop.example index 02a5a41742..b067b4c5c0 100644 --- a/.env.windows-docker-desktop.example +++ b/.env.windows-docker-desktop.example @@ -4,6 +4,7 @@ APP_ID=coolify-windows-docker-desktop APP_NAME=Coolify APP_KEY=base64:ssTlCmrIE/q7whnKMvT6DwURikg69COzGsAwFVROm80= +DB_USERNAME=coolify DB_PASSWORD=coolify REDIS_PASSWORD=coolify diff --git a/.gitattributes b/.gitattributes index fcb21d396d..c48a5898bc 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,4 +8,4 @@ /.github export-ignore CHANGELOG.md export-ignore -.styleci.yml export-ignore +.styleci.yml export-ignore \ No newline at end of file diff --git a/.github/workflows/lock-closed-issues-discussions-and-prs.yml b/.github/workflows/chore-lock-closed-issues-discussions-and-prs.yml similarity index 84% rename from .github/workflows/lock-closed-issues-discussions-and-prs.yml rename to .github/workflows/chore-lock-closed-issues-discussions-and-prs.yml index d008539647..3658422544 100644 --- a/.github/workflows/lock-closed-issues-discussions-and-prs.yml +++ b/.github/workflows/chore-lock-closed-issues-discussions-and-prs.yml @@ -4,6 +4,11 @@ on: schedule: - cron: '0 1 * * *' +permissions: + issues: write + discussions: write + pull-requests: write + jobs: lock-threads: runs-on: ubuntu-latest @@ -13,5 +18,5 @@ jobs: with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-inactive-days: '30' - pr-inactive-days: '30' discussion-inactive-days: '30' + pr-inactive-days: '30' diff --git a/.github/workflows/manage-stale-issues-and-prs.yml b/.github/workflows/chore-manage-stale-issues-and-prs.yml similarity index 57% rename from .github/workflows/manage-stale-issues-and-prs.yml rename to .github/workflows/chore-manage-stale-issues-and-prs.yml index 2afc996cb5..d610055497 100644 --- a/.github/workflows/manage-stale-issues-and-prs.yml +++ b/.github/workflows/chore-manage-stale-issues-and-prs.yml @@ -4,6 +4,10 @@ on: schedule: - cron: '0 2 * * *' +permissions: + issues: write + pull-requests: write + jobs: manage-stale: runs-on: ubuntu-latest @@ -13,16 +17,16 @@ jobs: id: stale with: stale-issue-message: 'This issue will be automatically closed in a few days if no response is received. Please provide an update with the requested information.' - stale-pr-message: 'This pull request will be automatically closed in a few days if no response is received. Please update your PR or comment if you would like to continue working on it.' + stale-pr-message: 'This pull request requires attention. If no changes or response is received within the next few days, it will be automatically closed. Please update your PR or leave a comment with the requested information.' close-issue-message: 'This issue has been automatically closed due to inactivity.' - close-pr-message: 'This pull request has been automatically closed due to inactivity.' + close-pr-message: 'Thank you for your contribution. Due to inactivity, this PR was automatically closed. If you would like to continue working on this change in the future, feel free to reopen this PR or submit a new one.' days-before-stale: 14 days-before-close: 7 stale-issue-label: '⏱︎ Stale' stale-pr-label: '⏱︎ Stale' - only-labels: '💤 Waiting for feedback' + only-labels: '💤 Waiting for feedback, 💤 Waiting for changes' remove-stale-when-updated: true operations-per-run: 100 - labels-to-remove-when-unstale: '⏱︎ Stale, 💤 Waiting for feedback' + labels-to-remove-when-unstale: '⏱︎ Stale, 💤 Waiting for feedback, 💤 Waiting for changes' close-issue-reason: 'not_planned' exempt-all-milestones: false diff --git a/.github/workflows/chore-pr-comments.yml b/.github/workflows/chore-pr-comments.yml new file mode 100644 index 0000000000..1d94bec813 --- /dev/null +++ b/.github/workflows/chore-pr-comments.yml @@ -0,0 +1,49 @@ +name: Add comment based on label +on: + pull_request_target: + types: + - labeled + +permissions: + pull-requests: write + +jobs: + add-comment: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - label: "⚙️ Service" + body: | + Hi @${{ github.event.pull_request.user.login }}! 👋 + + It appears to us that you are either adding a new service or making changes to an existing one. + We kindly ask you to also review and update the **Coolify Documentation** to include this new service or it's new configuration needs. + This will help ensure that our documentation remains accurate and up-to-date for all users. + + Coolify Docs Repository: https://github.com/coollabsio/coolify-docs + How to Contribute a new Service to the Docs: https://coolify.io/docs/get-started/contribute/service#adding-a-new-service-template-to-the-coolify-documentation + - label: "🛠️ Feature" + body: | + Hi @${{ github.event.pull_request.user.login }}! 👋 + + It appears to us that you are adding a new feature to Coolify. + We kindly ask you to also update the **Coolify Documentation** to include information about this new feature. + This will help ensure that our documentation remains accurate and up-to-date for all users. + + Coolify Docs Repository: https://github.com/coollabsio/coolify-docs + How to Contribute to the Docs: https://coolify.io/docs/get-started/contribute/documentation + # - label: "✨ Enhancement" + # body: | + # It appears to us that you are making an enhancement to Coolify. + # We kindly ask you to also review and update the Coolify Documentation to include information about this enhancement if applicable. + # This will help ensure that our documentation remains accurate and up-to-date for all users. + steps: + - name: Add comment + if: github.event.label.name == matrix.label + run: gh pr comment "$NUMBER" --body "$BODY" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.pull_request.number }} + BODY: ${{ matrix.body }} diff --git a/.github/workflows/remove-labels-and-assignees-on-close.yml b/.github/workflows/chore-remove-labels-and-assignees-on-close.yml similarity index 80% rename from .github/workflows/remove-labels-and-assignees-on-close.yml rename to .github/workflows/chore-remove-labels-and-assignees-on-close.yml index ea097e328c..8ac199a089 100644 --- a/.github/workflows/remove-labels-and-assignees-on-close.yml +++ b/.github/workflows/chore-remove-labels-and-assignees-on-close.yml @@ -8,6 +8,10 @@ on: pull_request_target: types: [closed] +permissions: + issues: write + pull-requests: write + jobs: remove-labels-and-assignees: runs-on: ubuntu-latest @@ -19,8 +23,12 @@ jobs: script: | const { owner, repo } = context.repo; - async function processIssue(issueNumber) { + async function processIssue(issueNumber, isFromPR = false, prBaseBranch = null) { try { + if (isFromPR && prBaseBranch !== 'v4.x') { + return; + } + const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({ owner, repo, @@ -59,19 +67,19 @@ jobs: } } - if (context.eventName === 'issues' || context.eventName === 'pull_request' || context.eventName === 'pull_request_target') { - const issue = context.payload.issue || context.payload.pull_request; - await processIssue(issue.number); + if (context.eventName === 'issues') { + await processIssue(context.payload.issue.number); } if (context.eventName === 'pull_request' || context.eventName === 'pull_request_target') { const pr = context.payload.pull_request; - if (pr.body) { + await processIssue(pr.number); + if (pr.merged && pr.base.ref === 'v4.x' && pr.body) { const issueReferences = pr.body.match(/#(\d+)/g); if (issueReferences) { for (const reference of issueReferences) { const issueNumber = parseInt(reference.substring(1)); - await processIssue(issueNumber); + await processIssue(issueNumber, true, pr.base.ref); } } } diff --git a/.github/workflows/cleanup-ghcr-untagged.yml b/.github/workflows/cleanup-ghcr-untagged.yml new file mode 100644 index 0000000000..a86cedcb03 --- /dev/null +++ b/.github/workflows/cleanup-ghcr-untagged.yml @@ -0,0 +1,22 @@ +name: Cleanup Untagged GHCR Images + +on: + workflow_dispatch: + +permissions: + packages: write + +jobs: + cleanup-all-packages: + runs-on: ubuntu-latest + strategy: + matrix: + package: ['coolify', 'coolify-helper', 'coolify-realtime', 'coolify-testing-host'] + steps: + - name: Delete untagged ${{ matrix.package }} images + uses: actions/delete-package-versions@v5 + with: + package-name: ${{ matrix.package }} + package-type: 'container' + min-versions-to-keep: 0 + delete-only-untagged-versions: 'true' diff --git a/.github/workflows/coolify-helper-next.yml b/.github/workflows/coolify-helper-next.yml index 4add8516ee..fec54d54aa 100644 --- a/.github/workflows/coolify-helper-next.yml +++ b/.github/workflows/coolify-helper-next.yml @@ -1,4 +1,4 @@ -name: Coolify Helper Image Development (v4) +name: Coolify Helper Image Development on: push: @@ -7,93 +7,109 @@ on: - .github/workflows/coolify-helper-next.yml - docker/coolify-helper/Dockerfile +permissions: + contents: read + packages: write + env: - REGISTRY: ghcr.io + GITHUB_REGISTRY: ghcr.io + DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-helper" jobs: - amd64: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write + build-push: + strategy: + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: aarch64 + platform: linux/aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Get Version - id: version - run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - no-cache: true - context: . - file: docker/coolify-helper/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next - labels: | - coolify.managed=true - aarch64: - runs-on: [ self-hosted, arm64 ] - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + + - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Build and Push Image (${{ matrix.arch }}) + uses: docker/build-push-action@v6 with: - no-cache: true context: . file: docker/coolify-helper/Dockerfile - platforms: linux/aarch64 + platforms: ${{ matrix.platform }} push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} labels: | coolify.managed=true + merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [ amd64, aarch64 ] + runs-on: ubuntu-24.04 + needs: build-push steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Create & publish manifest + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next + docker buildx imagetools create \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:next + + - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:next + - uses: sarisia/actions-status-discord@v1 if: always() with: diff --git a/.github/workflows/coolify-helper.yml b/.github/workflows/coolify-helper.yml index a9e8a5dd0d..0c9996ec86 100644 --- a/.github/workflows/coolify-helper.yml +++ b/.github/workflows/coolify-helper.yml @@ -1,99 +1,114 @@ -name: Coolify Helper Image (v4) +name: Coolify Helper Image on: push: - branches: [ "main" ] + branches: [ "v4.x" ] paths: - .github/workflows/coolify-helper.yml - docker/coolify-helper/Dockerfile +permissions: + contents: read + packages: write + env: - REGISTRY: ghcr.io + GITHUB_REGISTRY: ghcr.io + DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-helper" jobs: - amd64: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write + build-push: + strategy: + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: aarch64 + platform: linux/aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Get Version - id: version - run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - no-cache: true - context: . - file: docker/coolify-helper/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} - labels: | - coolify.managed=true - aarch64: - runs-on: [ self-hosted, arm64 ] - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + + - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Build and Push Image (${{ matrix.arch }}) + uses: docker/build-push-action@v6 with: - no-cache: true context: . file: docker/coolify-helper/Dockerfile - platforms: linux/aarch64 + platforms: ${{ matrix.platform }} push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} labels: | coolify.managed=true merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [ amd64, aarch64 ] + runs-on: ubuntu-24.04 + needs: build-push steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Create & publish manifest + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + docker buildx imagetools create \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + + - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + - uses: sarisia/actions-status-discord@v1 if: always() with: diff --git a/.github/workflows/coolify-production-build.yml b/.github/workflows/coolify-production-build.yml new file mode 100644 index 0000000000..21871b103d --- /dev/null +++ b/.github/workflows/coolify-production-build.yml @@ -0,0 +1,121 @@ +name: Production Build (v4) + +on: + push: + branches: ["v4.x"] + paths-ignore: + - .github/workflows/coolify-helper.yml + - .github/workflows/coolify-helper-next.yml + - .github/workflows/coolify-realtime.yml + - .github/workflows/coolify-realtime-next.yml + - docker/coolify-helper/Dockerfile + - docker/coolify-realtime/Dockerfile + - docker/testing-host/Dockerfile + - templates/** + - CHANGELOG.md + +permissions: + contents: read + packages: write + +env: + GITHUB_REGISTRY: ghcr.io + DOCKER_REGISTRY: docker.io + IMAGE_NAME: "coollabsio/coolify" + +jobs: + build-push: + strategy: + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: aarch64 + platform: linux/aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Login to ${{ env.GITHUB_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.GITHUB_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Get Version + id: version + run: | + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Build and Push Image (${{ matrix.arch }}) + uses: docker/build-push-action@v6 + with: + context: . + file: docker/production/Dockerfile + platforms: ${{ matrix.platform }} + push: true + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} + + merge-manifest: + runs-on: ubuntu-24.04 + needs: build-push + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.GITHUB_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Get Version + id: version + run: | + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + + - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + + - uses: sarisia/actions-status-discord@v1 + if: always() + with: + webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }} diff --git a/.github/workflows/coolify-realtime-next.yml b/.github/workflows/coolify-realtime-next.yml index 33e048627d..7ab4dcc427 100644 --- a/.github/workflows/coolify-realtime-next.yml +++ b/.github/workflows/coolify-realtime-next.yml @@ -1,103 +1,120 @@ -name: Coolify Realtime Development (v4) +name: Coolify Realtime Development on: push: branches: [ "next" ] paths: - - .github/workflows/coolify-realtime.yml + - .github/workflows/coolify-realtime-next.yml - docker/coolify-realtime/Dockerfile - docker/coolify-realtime/terminal-server.js - docker/coolify-realtime/package.json + - docker/coolify-realtime/package-lock.json - docker/coolify-realtime/soketi-entrypoint.sh +permissions: + contents: read + packages: write + env: - REGISTRY: ghcr.io + GITHUB_REGISTRY: ghcr.io + DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-realtime" jobs: - amd64: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write + build-push: + strategy: + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: aarch64 + platform: linux/aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Get Version - id: version - run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - no-cache: true - context: . - file: docker/coolify-realtime/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next - labels: | - coolify.managed=true - aarch64: - runs-on: [ self-hosted, arm64 ] - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + + - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Build and Push Image (${{ matrix.arch }}) + uses: docker/build-push-action@v6 with: - no-cache: true context: . file: docker/coolify-realtime/Dockerfile - platforms: linux/aarch64 + platforms: ${{ matrix.platform }} push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }} labels: | coolify.managed=true + merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [ amd64, aarch64 ] + runs-on: ubuntu-24.04 + needs: build-push steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Create & publish manifest + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next + docker buildx imagetools create \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:next + + - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:next + - uses: sarisia/actions-status-discord@v1 if: always() with: - webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }} + webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} diff --git a/.github/workflows/coolify-realtime.yml b/.github/workflows/coolify-realtime.yml index 30910ae0bd..5efe445c5e 100644 --- a/.github/workflows/coolify-realtime.yml +++ b/.github/workflows/coolify-realtime.yml @@ -1,102 +1,119 @@ -name: Coolify Realtime (v4) +name: Coolify Realtime on: push: - branches: [ "main" ] + branches: [ "v4.x" ] paths: - .github/workflows/coolify-realtime.yml - docker/coolify-realtime/Dockerfile - docker/coolify-realtime/terminal-server.js - docker/coolify-realtime/package.json + - docker/coolify-realtime/package-lock.json - docker/coolify-realtime/soketi-entrypoint.sh +permissions: + contents: read + packages: write + env: - REGISTRY: ghcr.io + GITHUB_REGISTRY: ghcr.io + DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-realtime" jobs: - amd64: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write + build-push: + strategy: + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: aarch64 + platform: linux/aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Get Version - id: version - run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - no-cache: true - context: . - file: docker/coolify-realtime/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} - labels: | - coolify.managed=true - aarch64: - runs-on: [ self-hosted, arm64 ] - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + + - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Build and Push Image (${{ matrix.arch }}) + uses: docker/build-push-action@v6 with: - no-cache: true context: . file: docker/coolify-realtime/Dockerfile - platforms: linux/aarch64 + platforms: ${{ matrix.platform }} push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }} labels: | coolify.managed=true + merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [ amd64, aarch64 ] + runs-on: ubuntu-24.04 + needs: build-push steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + - name: Get Version id: version run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT - - name: Create & publish manifest + echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT + + - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + docker buildx imagetools create \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + + - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + - uses: sarisia/actions-status-discord@v1 if: always() with: diff --git a/.github/workflows/coolify-staging-build.yml b/.github/workflows/coolify-staging-build.yml new file mode 100644 index 0000000000..67b7b03e82 --- /dev/null +++ b/.github/workflows/coolify-staging-build.yml @@ -0,0 +1,133 @@ +name: Staging Build + +on: + push: + branches-ignore: + - v4.x + - v3.x + - '**v5.x**' + paths-ignore: + - .github/workflows/coolify-helper.yml + - .github/workflows/coolify-helper-next.yml + - .github/workflows/coolify-realtime.yml + - .github/workflows/coolify-realtime-next.yml + - docker/coolify-helper/Dockerfile + - docker/coolify-realtime/Dockerfile + - docker/testing-host/Dockerfile + - templates/** + - CHANGELOG.md + +permissions: + contents: read + packages: write + +env: + GITHUB_REGISTRY: ghcr.io + DOCKER_REGISTRY: docker.io + IMAGE_NAME: "coollabsio/coolify" + +jobs: + build-push: + strategy: + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: aarch64 + platform: linux/aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Sanitize branch name for Docker tag + id: sanitize + run: | + # Replace slashes and other invalid characters with dashes + SANITIZED_NAME=$(echo "${{ github.ref_name }}" | sed 's/[\/]/-/g') + echo "tag=${SANITIZED_NAME}" >> $GITHUB_OUTPUT + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.GITHUB_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Build and Push Image (${{ matrix.arch }}) + uses: docker/build-push-action@v6 + with: + context: . + file: docker/production/Dockerfile + platforms: ${{ matrix.platform }} + push: true + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-${{ matrix.arch }} + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-${{ matrix.arch }} + cache-from: | + type=gha,scope=build-${{ matrix.arch }} + type=registry,ref=${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.arch }} + cache-to: type=gha,mode=max,scope=build-${{ matrix.arch }} + + merge-manifest: + runs-on: ubuntu-24.04 + needs: build-push + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Sanitize branch name for Docker tag + id: sanitize + run: | + # Replace slashes and other invalid characters with dashes + SANITIZED_NAME=$(echo "${{ github.ref_name }}" | sed 's/[\/]/-/g') + echo "tag=${SANITIZED_NAME}" >> $GITHUB_OUTPUT + + - uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.GITHUB_REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-amd64 \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-aarch64 \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }} + + - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-amd64 \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-aarch64 \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }} + + - uses: sarisia/actions-status-discord@v1 + if: always() + with: + webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} diff --git a/.github/workflows/coolify-testing-host.yml b/.github/workflows/coolify-testing-host.yml index 5fdc329914..24133887a5 100644 --- a/.github/workflows/coolify-testing-host.yml +++ b/.github/workflows/coolify-testing-host.yml @@ -1,83 +1,103 @@ -name: Coolify Testing Host (v4-non-prod) +name: Coolify Testing Host on: push: - branches: [ "main", "next" ] + branches: [ "next" ] paths: - .github/workflows/coolify-testing-host.yml - docker/testing-host/Dockerfile +permissions: + contents: read + packages: write + env: - REGISTRY: ghcr.io + GITHUB_REGISTRY: ghcr.io + DOCKER_REGISTRY: docker.io IMAGE_NAME: "coollabsio/coolify-testing-host" jobs: - amd64: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write + build-push: + strategy: + matrix: + include: + - arch: amd64 + platform: linux/amd64 + runner: ubuntu-24.04 + - arch: aarch64 + platform: linux/aarch64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - no-cache: true - context: . - file: docker/testing-host/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - aarch64: - runs-on: [ self-hosted, arm64 ] - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io + + - name: Login to ${{ env.DOCKER_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image and push to registry - uses: docker/build-push-action@v5 + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Build and Push Image (${{ matrix.arch }}) + uses: docker/build-push-action@v6 with: - no-cache: true context: . file: docker/testing-host/Dockerfile - platforms: linux/aarch64 + platforms: ${{ matrix.platform }} push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 + tags: | + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-${{ matrix.arch }} + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-${{ matrix.arch }} + labels: | + coolify.managed=true + merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [ amd64, aarch64 ] + runs-on: ubuntu-24.04 + needs: build-push steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Login to ghcr.io + - uses: actions/checkout@v5 + with: + persist-credentials: false + + - uses: docker/setup-buildx-action@v3 + + - name: Login to ${{ env.GITHUB_REGISTRY }} uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} + registry: ${{ env.GITHUB_REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Create & publish manifest + + - name: Login to ${{ env.DOCKER_REGISTRY }} + uses: docker/login-action@v3 + with: + registry: ${{ env.DOCKER_REGISTRY }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }} run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + docker buildx imagetools create \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64 \ + ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 \ + --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + + - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }} + run: | + docker buildx imagetools create \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64 \ + ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 \ + --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest + - uses: sarisia/actions-status-discord@v1 if: always() with: diff --git a/.github/workflows/development-build.yml b/.github/workflows/development-build.yml deleted file mode 100644 index 268b885aca..0000000000 --- a/.github/workflows/development-build.yml +++ /dev/null @@ -1,79 +0,0 @@ -name: Development Build (v4) - -on: - push: - branches-ignore: ["main", "v3"] - paths-ignore: - - .github/workflows/coolify-helper.yml - - docker/coolify-helper/Dockerfile - -env: - REGISTRY: ghcr.io - IMAGE_NAME: "coollabsio/coolify" - -jobs: - amd64: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - context: . - file: docker/prod/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }} - aarch64: - runs-on: [self-hosted, arm64] - permissions: - contents: read - packages: write - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - context: . - file: docker/prod/Dockerfile - platforms: linux/aarch64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64 - merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [amd64, aarch64] - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Create & publish manifest - run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }} - - uses: sarisia/actions-status-discord@v1 - if: always() - with: - webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} diff --git a/.github/workflows/generate-changelog.yml b/.github/workflows/generate-changelog.yml new file mode 100644 index 0000000000..935a887211 --- /dev/null +++ b/.github/workflows/generate-changelog.yml @@ -0,0 +1,36 @@ +name: Generate Changelog + +on: + push: + branches: [ v4.x ] + workflow_dispatch: + +permissions: + contents: write + +jobs: + changelog: + name: Generate changelog + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate changelog + uses: orhun/git-cliff-action@v4 + with: + config: cliff.toml + args: --verbose + env: + OUTPUT: CHANGELOG.md + GITHUB_REPO: ${{ github.repository }} + + - name: Commit + run: | + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git add CHANGELOG.md + git commit -m "docs: update changelog" + git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git v4.x diff --git a/.github/workflows/production-build.yml b/.github/workflows/production-build.yml deleted file mode 100644 index c78c865bfe..0000000000 --- a/.github/workflows/production-build.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: Production Build (v4) - -on: - push: - branches: ["main"] - paths-ignore: - - .github/workflows/coolify-helper.yml - - docker/coolify-helper/Dockerfile - - templates/service-templates.json - -env: - REGISTRY: ghcr.io - IMAGE_NAME: "coollabsio/coolify" - -jobs: - amd64: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Get Version - id: version - run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - context: . - file: docker/prod/Dockerfile - platforms: linux/amd64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} - aarch64: - runs-on: [self-hosted, arm64] - steps: - - uses: actions/checkout@v4 - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Get Version - id: version - run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT - - name: Build image and push to registry - uses: docker/build-push-action@v5 - with: - context: . - file: docker/prod/Dockerfile - platforms: linux/aarch64 - push: true - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 - merge-manifest: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - needs: [amd64, aarch64] - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: Login to ghcr.io - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Get Version - id: version - run: | - echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT - - name: Create & publish manifest - run: | - docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - - uses: sarisia/actions-status-discord@v1 - if: always() - with: - webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }} diff --git a/.gitignore b/.gitignore index 09504afeeb..935ea548e8 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,8 @@ _ide_helper_models.php /.ssh scripts/load-test/* .ignition.json +.env.dusk.local +docker/coolify-realtime/node_modules +.DS_Store +CHANGELOG.md +/.workspaces diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 6fd6797b54..0000000000 --- a/.gitpod.yml +++ /dev/null @@ -1,65 +0,0 @@ -tasks: - - name: Setup Spin environment and Composer dependencies - # Fix because of https://github.com/gitpod-io/gitpod/issues/16614 - before: sudo curl -o /usr/local/bin/docker-compose -fsSL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-$(uname -m) - init: | - cp .env.development.example .env && - sed -i "s#APP_URL=http://localhost#APP_URL=$(gp url 8000)#g" .env - sed -i "s#USERID=#USERID=33333#g" .env - sed -i "s#GROUPID=#GROUPID=33333#g" .env - composer install --ignore-platform-reqs - ./vendor/bin/spin up -d - ./vendor/bin/spin exec -u webuser coolify php artisan key:generate - ./vendor/bin/spin exec -u webuser coolify php artisan storage:link - ./vendor/bin/spin exec -u webuser coolify php artisan migrate:fresh --seed - cat .coolify-logo - gp sync-done spin-is-ready - - - name: Install Node dependencies and run Vite - command: | - echo "Waiting for Sail environment to boot up." - gp sync-await spin-is-ready - ./vendor/bin/spin exec vite npm install - ./vendor/bin/spin exec vite npm run dev -- --host - - - name: Laravel Queue Worker, listening to code changes - command: | - echo "Waiting for Sail environment to boot up." - gp sync-await spin-is-ready - ./vendor/bin/spin exec -u webuser coolify php artisan queue:listen - -ports: - - port: 5432 - onOpen: ignore - name: PostgreSQL - visibility: public - - port: 5173 - onOpen: ignore - visibility: public - name: Node Server for Vite - - port: 8000 - onOpen: ignore - visibility: public - name: Coolify - -# Configure vscode -vscode: - extensions: - - bmewburn.vscode-intelephense-client - - ikappas.composer - - ms-azuretools.vscode-docker - - ecmel.vscode-html-css - - MehediDracula.php-namespace-resolver - - wmaurer.change-case - - Equinusocio.vsc-community-material-theme - - EditorConfig.EditorConfig - - streetsidesoftware.code-spell-checker - - rangav.vscode-thunder-client - - PKief.material-icon-theme - - cierra.livewire-vscode - - lennardv.livewire-goto-updated - - bradlc.vscode-tailwindcss - - heybourn.headwind - - adrianwilczynski.alpine-js-intellisense - - amiralizadeh9480.laravel-extra-intellisense - - shufo.vscode-blade-formatter diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000000..8c6715a151 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "laravel-boost": { + "command": "php", + "args": [ + "artisan", + "boost:mcp" + ] + } + } +} \ No newline at end of file diff --git a/.phpactor.json b/.phpactor.json new file mode 100644 index 0000000000..4d42bbbc5a --- /dev/null +++ b/.phpactor.json @@ -0,0 +1,4 @@ +{ + "$schema": "/phpactor.schema.json", + "language_server_phpstan.enabled": true +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..2980c74012 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9076 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [unreleased] + +### 🐛 Bug Fixes + +- Update syncData method to use data_get for safer property access +- Update version numbers to 4.0.0-beta.441 and 4.0.0-beta.442 +- Enhance menu item styles and update theme color meta tag +- Clean up input attributes for PostgreSQL settings in general.blade.php +- Update docker stop command to use --time instead of --timeout +- Clean up utility classes and improve readability in Blade templates +- Enhance styling for page width component in Blade template +- Remove debugging output from StartPostgresql command handling + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.440] - 2025-11-04 + +### 🐛 Bug Fixes + +- Fix SPA toggle nginx regeneration and add confirmation modal + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.439] - 2025-11-03 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.438] - 2025-10-29 + +### 🚀 Features + +- Display service logos in original colors with consistent sizing +- Add warnings for system-wide GitHub Apps +- Show message when no resources use GitHub App +- Add dynamic viewport-based height for compose editor +- Add funding information for Coollabs including sponsorship plans and channels +- Update Evolution API slogan to better reflect its capabilities +- *(templates)* Update plane compose to v1.0.0 +- Add token validation functionality for Hetzner and DigitalOcean providers +- Add dev_helper_version to instance settings and update related functionality +- Add RestoreDatabase command for PostgreSQL dump restoration +- Update ApplicationSetting model to include additional boolean casts +- Enhance General component with additional properties and validation rules +- Update version numbers to 4.0.0-beta.440 and 4.0.0-beta.441 + +### 🐛 Bug Fixes + +- Handle redis_password in API database creation +- Make modals scrollable on small screens +- Resolve Livewire wire:model binding error in domains input +- Make environment variable forms responsive +- Make proxy logs page responsive +- Improve proxy logs form layout for better responsive behavior +- Prevent horizontal overflow in log text +- Use break-all to force line wrapping in logs +- Ensure deployment failure notifications are sent reliably +- GitHub source creation and configuration issues +- Make system-wide warning reactive in Create view +- Prevent system-wide warning callout from making modal too wide +- Constrain callout width with max-w-2xl and wrap text properly +- Center system-wide warning callout in modal +- Left-align callout on regular view, keep centered in modal +- Allow callout to take full width in regular view +- Change app_id and installation_id to integer values in createGithubAppManually method +- Use x-cloak instead of inline style to prevent FOUC +- Clarify warning message for allowed IPs configuration +- Server URL generation in ServerPatchCheck notification +- Monaco editor empty for docker compose applications +- Update sponsor link from Darweb to Dade2 in README +- *(database)* Prevent malformed URLs when server IP is empty +- Optimize caching in Dockerfile and GitHub Actions workflow +- Remove wire:ignore from modal and add wire:key to EditCompose component +- Add wire:ignore directive to modal component for improved functionality +- Clean up formatting and remove unnecessary key binding in stack form component +- Add null checks and validation to OAuth bulk update method +- *(docs)* Update documentation URL to version 2 in evolution-api.yaml +- *(templates)* Remove volumes from Plane's compose +- *(templates)* Add redis env to live service in Plane +- *(templates)* Update minio image to use coollabsio fork in Plane +- Prevent login rate limit bypass via spoofed headers +- Correct login rate limiter key format to include IP address +- Change SMTP port input type to number for better validation +- Remove unnecessary step attribute from maximum storage input fields +- Update boarding flow logic to complete onboarding when server is created +- Convert network aliases to string for display +- Improve custom_network_aliases handling and testing +- Remove duplicate custom_labels from config hash calculation +- Improve run script and enhance sticky header style + +### 💼 Other + +- *(deps-dev)* Bump vite from 6.3.6 to 6.4.1 + +### 🚜 Refactor + +- Remove deprecated next() method +- Replace allowed IPs validation logic with regex +- Remove redundant +- Streamline allowed IPs validation and enhance UI warnings for API access +- Remove staging URL logic from ServerPatchCheck constructor +- Streamline Docker build process with matrix strategy for multi-architecture support +- Simplify project data retrieval and enhance OAuth settings handling +- Improve handling of custom network aliases +- Remove unused submodules +- Update subproject commit hashes +- Remove SynchronizesModelData trait and implement syncData method for model synchronization + +### 📚 Documentation + +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Add service & database deployment logging plan + +### 🧪 Testing + +- Add unit tests for ServerPatchCheck notification URL generation +- Fix ServerPatchCheckNotification tests to avoid global state pollution + +### ⚙️ Miscellaneous Tasks + +- Add category field to siyuan.yaml +- Update siyuan category in service templates +- Add spacing and format callout text in modal +- Update version numbers to 4.0.0-beta.439 and 4.0.0-beta.440 +- Add .workspaces to .gitignore + +## [4.0.0-beta.437] - 2025-10-21 + +### 🚀 Features + +- *(templates)* Add sparkyfitness compose template and logo +- *(servide)* Add siyuan template +- Add onboarding guide link to global search no results state +- Add category filter dropdown to service selection + +### 🐛 Bug Fixes + +- *(service)* Update image version & healthcheck start period +- Filter deprecated server types for Hetzner +- Eliminate dark mode white screen flicker on page transitions + +### 💼 Other + +- Preserve clean docker_compose_raw without Coolify additions + +### 📚 Documentation + +- Update changelog +- Update changelog + +## [4.0.0-beta.435] - 2025-10-15 + +### 🚀 Features + +- *(docker)* Enhance Docker image handling with new validation and parsing logic +- *(docker)* Improve Docker image submission logic with enhanced parsing +- *(docker)* Refine Docker image processing in application creation +- Add Ente Photos service template +- *(storage)* Add read-only volume handling and UI notifications +- *(service)* Add Elasticsearch password handling in extraFields method +- *(application)* Add default NIXPACKS_NODE_VERSION environment variable for Nixpacks applications +- *(proxy)* Enhance proxy configuration regeneration by extracting custom commands +- *(backup)* Enhance backup job with S3 upload handling and notifications +- *(storage)* Implement transaction handling in storage settings submission +- *(project)* Enhance project index with resource creation capabilities +- *(dashboard)* Enhance project and server sections with modal input for resource creation +- *(global-search)* Enhance resource creation functionality in search modal +- *(global-search)* Add navigation routes and enhance search functionality +- *(conductor)* Add setup script and configuration file +- *(conductor)* Add run script and update runScriptMode configuration +- *(docker-compose)* Add image specifications for coolify, soketi, and testing-host services +- *(cleanup)* Add force deletion of stuck servers and orphaned SSL certificates +- *(deployment)* Save build-time .env file before build and enhance logging for Dockerfile +- Implement Hetzner deletion failure notification system with email and messaging support +- Enhance proxy status notifications with detailed messages for various states +- Add retry functionality for server validation process +- Add retry mechanism with rate limit handling to API requests in HetznerService +- Implement ValidHostname validation rule and integrate it into server creation process +- Add support for selecting additional SSH keys from Hetzner in server creation form +- Enhance datalist component with unified input container and improved option handling +- Add modal support for creating private keys in server creation form and enhance UI for private key selection +- Add IPv4/IPv6 network configuration for Hetzner server creation +- Add pricing display to Hetzner server creation button +- Add cloud-init script support for Hetzner server creation +- Add cloud-init scripts management UI in Security section +- Add cloud-init scripts to global search +- Add artisan command to clear global search cache +- Add YAML validation for cloud-init scripts +- Add clear button for cloud-init script dropdown +- Add custom webhook notification support +- Add webhook placeholder to Test notification +- Add WebhookChannel placeholder implementation +- Implement actual webhook delivery +- Implement actual webhook delivery with Ray debugging +- Improve webhook URL field UI +- Add UUIDs and URLs to webhook notifications +- *(onboarding)* Redesign user onboarding flow with modern UI/UX +- Replace terminal dropdown with searchable datalist component +- *(onboarding)* Add Hetzner integration and fix navigation issues +- Use new homarr image +- *(templates)* Actually use the new image now +- *(templates)* Pin homarr image version to v1.40.0 +- *(template)* Added newapi +- Add mail environment variables to docmost.yaml +- Add Email Envs, Install more required packages by pdsadmin +- Make an empty pds.env file to trick pdsadmin into working correctly +- Not many know how to setup this without reading pds docs +- Make the other email env also required +- *(templates)* Added Lobe Chat service +- *(service)* Add Gramps Web template +- *(campfire)* Add Docker Compose configuration for Once Campfire service +- Add Hetzner affiliate link to token form +- Update Hetzner affiliate link text and URL +- Add CPU vendor information to server types in Hetzner integration +- Implement TrustHosts middleware to handle FQDN and IP address trust logic +- Implement TrustHosts middleware to handle FQDN and IP address trust logic +- Allow safe environment variable defaults in array-format volumes +- Add signoz template +- *(signoz)* Replace png icon by svg icon +- *(signoz)* Remove explicit 'networks' setting +- *(signoz)* Add predefined environment variables to configure Telemetry, SMTP and email sending for Alert Manager +- *(signoz)* Generate URLs for `otel-collector` service +- *(signoz)* Update documentation link +- *(signoz)* Add healthcheck to otel-collector service +- *(signoz)* Use latest tag instead of hardcoded versions +- *(signoz)* Remove redundant users.xml volume from clickhouse container +- *(signoz)* Replace clickhouse' config.xml volume with simpler configuration +- *(signoz)* Remove deprecated parameters of signoz container +- *(signoz)* Remove volumes from signoz.yaml +- *(signoz)* Assume there is a single zookeeper container +- *(signoz)* Update Clickhouse config to include all settings required by Signoz +- *(signoz)* Update config.xml and users.xml to ensure clickhouse boots correctly +- *(signoz)* Update otel-collector configuration to match upstream +- *(signoz)* Fix otel-collector config for version v0.128.0 +- *(signoz)* Remove unecessary port mapping for otel-collector +- *(signoz)* Add SIGNOZ_JWT_SECRET env var generation +- *(signoz)* Upgrade clickhouse image to 25.5.6 +- *(signoz)* Use latest tag for signoz/zookeeper +- *(signoz)* Update variables for SMTP configuration +- *(signoz)* Replace deprecated `TELEMETRY_ENABLED` by `SIGNOZ_STATSREPORTER_ENABLED` +- *(signoz)* Pin service image tags and `exclude_from_hc` flag to services excluded from health checks +- *(templates)* Add SMTP configuration to ente-photos compose templates +- *(templates)* Add SMTP encryption configuration to ente-photos compose templates + +### 🐛 Bug Fixes + +- Region env variable +- Ente photos +- *(elasticsearch)* Update Elasticsearch and Kibana configuration for enhanced security and setup +- *(ui)* Make the deployments indicator toast in the bottom-left above the sidebar +- *(environment)* Clear computed property cache after adding environment variables +- *(backup)* Update backup job to use backup_log_uuid for container naming +- *(core)* Set default base_directory and include in submit method +- *(deployment)* Add warning for NIXPACKS_NODE_VERSION in node configurations +- *(deployment)* Save runtime environment variables when skipping build +- *(job)* Correct build logs URL structure in ApplicationPullRequestUpdateJob +- *(tests)* Update Docker command for running feature tests without `-it` flag +- On team creation, redirect to the new team instantly +- *(project)* Update redirect logic after resource creation to include environment UUID +- *(dashboard)* Add cursor pointer to modal input buttons for better UX +- *(modal-confirmation)* Refine escape key handling to ensure modal closes only when open +- *(conductor-setup)* Update script permissions for execution +- *(conductor)* Update run script command to 'spin up' +- *(conductor)* Update run script to include 'spin down' command +- *(docker-compose)* Set pull_policy to 'never' for coolify, soketi, and testing-host services +- *(migration)* Disable transaction for concurrent index creation +- Properly handle transaction for concurrent index operations +- Use correct property declaration for withinTransaction +- *(api-tokens)* Update settings link for API enablement message +- *(css)* Update success color to match design specifications +- *(css)* Update focus styles for input and button utilities to improve accessibility +- *(css)* Remove unnecessary tracking classes from status components for consistency +- *(css)* Update focus styles for Checkbox and modal input components to enhance accessibility +- Refresh server data before showing notification to ensure accurate proxy status +- Update Hetzner server status handling to prevent unnecessary database updates and improve UI responsiveness +- Improve error logging and handling in ServerConnectionCheckJob for Hetzner server status +- Correct dispatch logic for Hetzner server status refresh in checkHetznerServerStatus method +- Streamline proxy status handling in StartProxy and Navbar components +- Improve placeholder text for token name input in cloud provider token form +- Update cloud provider token form with improved placeholder and guidance for API token creation +- *(ci)* Sanitize branch names for Docker tag compatibility +- Set cloud-init script dropdown to empty by default +- Reset cloud-init fields when closing server creation modal +- Improve cloud-init scripts UI styling and behavior +- Allow typing in global search while data loads +- Hide 'No results found' message while data is loading +- Populate webhook notification settings for existing teams +- Register WebhookNotificationSettings with NotificationPolicy +- Add missing server_patch_webhook_notifications field +- Move POST badge before input field +- Use btn-primary for POST badge background +- *(onboarding)* Auto-select first SSH key for better UX +- Prevent container name conflict when updating database port mappings +- Missing 422 error code in openapi spec +- Allow all environment variable fields in API endpoints +- Fixed version +- Fix documentation url +- Bluesky PDS template +- Bluesky PDS template finally works normally +- Add back template info +- Now it automatically generates the JWT secret and the PLC rotation key +- Syntax error on vars +- Remove the SERVICE_EMAIL_ADMIN and make it normal +- Both email envs are needed in order for the PDS to start, so set the other one as required +- Add back template info +- Healthcheck doesn’t need to be 5s +- Make email envs not required +- Domain on coolify +- *(templates)* Update Lobe-chat openai base_url env + required envs +- *(templates)* Lobechat environnement variable +- *(lobe-chat)* Update Docker image tag to a specific version 1.135.5 +- Enable docker network connection for pgadmin service +- *(template/filebrowser)* Correct routing and healthcheck for Filebrowser +- *(template/filebrowser)* Correct healthcheck for Filebrowser +- *(campfire)* Update port configuration from 80 to 3000 in Docker Compose file +- *(campfire)* Correct port comment from 3000 to 80 in Docker Compose file +- *(campfire)* Update service definition to use image instead of build in Docker Compose file +- *(templates)* Remove mattermost healthcheck command according to lack of shell in new version +- Prevent duplicate services on image change and enable real-time UI refresh +- Enhance run script to remove existing containers before starting +- Prevent TypeError in database General components with null server +- Add authorization checks to database Livewire components +- Add missing save_runtime_environment_variables() in deploy_simple_dockerfile +- *(git)* Handle Git redirects and improve URL parsing for tangled.sh and other Git hosts +- Improve logging and add shell escaping for git ls-remote +- Update run script to use bun for development +- Restore original run script functionality in conductor.json +- Use computed imageTag variable for digest-based Docker images +- Improve Docker image digest handling and add auto-parse feature +- 'new image' quick action not progressing to resource selection +- Use wasChanged() instead of isDirty() in updated hooks +- Prevent command injection in git ls-remote operations +- Handle null environment variable values in bash escaping +- Critical privilege escalation in team invitation system +- Add authentication context to TeamPolicyTest +- Ensure negative cache results are stored in TrustHosts middleware +- Use wasChanged() instead of isDirty() in updated hook +- Prevent command injection in Docker Compose parsing - add pre-save validation +- Use canonical parser for Windows path validation +- Correct variable name typo in generateGitLsRemoteCommands method +- Update version numbers to 4.0.0-beta.436 and 4.0.0-beta.437 +- Ensure authorization checks are in place for viewing and updating the application +- Ensure authorization check is performed during component mount +- *(signoz)* Remove example secrets to avoid triggering GitGuardian +- *(signoz)* Remove hardcoded container names +- *(signoz)* Remove HTTP collector FQDN in otel-collector +- *(n8n)* Add DB_SQLITE_POOL_SIZE environment variable for configuration +- *(template)* Remove default values for environment variables +- Update metamcp image version and clean up environment variable syntax + +### 💼 Other + +- Ente config +- Cofig variables +- Lean Config +- Env +- Services & Env variables +- Product hunt Ente Logo +- Remove volumes +- Add ray logging for Hetzner createServer API request/response +- Escape all shell directory paths in Git deployment commands +- Remove content from docker_compose_raw to prevent file overwrites +- *(templates)* Metamcp app + +### 🚜 Refactor + +- *(environment-variables)* Adjust ordering logic for environment variables +- Update ente photos configuration for improved service management +- *(deployment)* Streamline environment variable generation in ApplicationDeploymentJob +- *(deployment)* Enhance deployment data retrieval and relationships +- *(deployment)* Standardize environment variable handling in ApplicationDeploymentJob +- *(deployment)* Update environment variable handling for Docker builds +- *(navbar, app)* Improve layout and styling for better responsiveness +- *(switch-team)* Remove label from team selection component for cleaner UI +- *(global-search, environment)* Streamline environment retrieval with new query method +- *(backup)* Make backup_log_uuid initialization lazy +- *(checkbox, utilities, global-search)* Enhance focus styles for better accessibility +- *(forms)* Simplify wire:dirty class bindings for input, select, and textarea components +- Replace direct SslCertificate queries with server relationship methods for consistency +- *(ui)* Improve cloud-init script save checkbox visibility and styling +- Enable cloud-init save checkbox at all times with backend validation +- Improve cloud-init script UX and remove description field +- Improve cloud-init script management UI and cache control +- Remove debug sleep from global search modal +- Reduce cloud-init label width for better layout +- Remove SendsWebhook interface +- Reposition POST badge as button +- Migrate database components from legacy model binding to explicit properties +- Volumes set back to ./pds-data:/pds +- *(campfire)* Streamline environment variable definitions in Docker Compose file +- Improve validation error handling and coding standards +- Preserve exception chain in validation error handling +- Harden and deduplicate validateShellSafePath +- Replace random ID generation with Cuid2 for unique HTML IDs in form components + +### 📚 Documentation + +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- *(tests)* Update testing guidelines for unit and feature tests +- *(sync)* Create AI Instructions Synchronization Guide and update CLAUDE.md references +- *(database-patterns)* Add critical note on mass assignment protection for new columns +- Clarify cloud-init script compatibility +- Update changelog +- Update changelog + +### 🎨 Styling + +- *(campfire)* Format environment variables for better readability in Docker Compose file +- *(campfire)* Update comment for DISABLE_SSL environment variable for clarity + +### 🧪 Testing + +- Improve Git ls-remote parsing tests with uppercase SHA and negative cases +- Add coverage for newline and tab rejection in volume strings + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update Coolify version numbers to 4.0.0-beta.435 and 4.0.0-beta.436 +- Update package-lock.json +- *(service)* Update convex template and image +- *(signoz)* Remove unused ports +- *(signoz)* Bump version to 0.77.0 +- *(signoz)* Bump version to 0.78.1 + +## [4.0.0-beta.434] - 2025-10-03 + +### 🚀 Features + +- *(deployments)* Enhance Docker build argument handling for multiline variables +- *(deployments)* Add log copying functionality to clipboard in dev +- *(deployments)* Generate SERVICE_NAME environment variables from Docker Compose services + +### 🐛 Bug Fixes + +- *(deployments)* Enhance builder container management and environment variable handling + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update version numbers for Coolify releases +- *(versions)* Bump Coolify stable version to 4.0.0-beta.434 + +## [4.0.0-beta.433] - 2025-10-01 + +### 🚀 Features + +- *(user-deletion)* Implement file locking to prevent concurrent user deletions and enhance error handling +- *(ui)* Enhance resource operations interface with dynamic selection for cloning and moving resources +- *(global-search)* Integrate projects and environments into global search functionality +- *(storage)* Consolidate storage management into a single component with enhanced UI +- *(deployments)* Add support for Coolify variables in Dockerfile + +### 🐛 Bug Fixes + +- *(workflows)* Update CLAUDE API key reference in GitHub Actions workflow +- *(ui)* Update docker registry image helper text for clarity +- *(ui)* Correct HTML structure and improve clarity in Docker cleanup options +- *(workflows)* Update CLAUDE API key reference in GitHub Actions workflow +- *(api)* Correct OpenAPI schema annotations for array items +- *(ui)* Improve queued deployment status readability in dark mode +- *(git)* Handle additional repository URL cases for 'tangled' and improve branch assignment logic +- *(git)* Enhance error handling for missing branch information during deployment +- *(git)* Trim whitespace from repository, branch, and commit SHA fields +- *(deployments)* Order deployments by ID for consistent retrieval + +### 💼 Other + +- *(storage)* Enhance file storage management with new properties and UI improvements +- *(core)* Update projects property type and enhance UI styling +- *(components)* Adjust SVG icon sizes for consistency across applications and services +- *(components)* Auto-focus first input in modal on open +- *(styles)* Enhance focus styles for buttons and links +- *(components)* Enhance close button accessibility in modal + +### 🚜 Refactor + +- *(global-search)* Change event listener to window level for global search modal +- *(dashboard)* Remove deployment loading logic and introduce DeploymentsIndicator component for better UI management +- *(dashboard)* Replace project navigation method with direct link in UI +- *(global-search)* Improve event handling and cleanup in global search component + +### 📚 Documentation + +- Update changelog +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.433 and nightly version to 4.0.0-beta.434 in configuration files + +## [4.0.0-beta.432] - 2025-09-29 + +### 🚀 Features + +- *(application)* Implement order-based pattern matching for watch paths with negation support +- *(github)* Enhance Docker Compose input fields for better user experience +- *(dev-seeders)* Add PersonalAccessTokenSeeder to create development API tokens +- *(application)* Add conditional .env file creation for Symfony apps during PHP deployment +- *(application)* Enhance watch path parsing to support negation syntax +- *(application)* Add normalizeWatchPaths method to improve watch path handling +- *(validation)* Enhance ValidGitRepositoryUrl to support additional safe characters and add comprehensive unit tests for various Git repository URL formats +- *(deployment)* Implement detection for Laravel/Symfony frameworks and configure NIXPACKS PHP environment variables accordingly + +### 🐛 Bug Fixes + +- *(application)* Restrict GitHub-based application settings to non-public repositories +- *(traits)* Update saved_outputs handling in ExecuteRemoteCommand to use collection methods for better performance +- *(application)* Enhance domain handling by replacing both dots and dashes with underscores for HTML form binding +- *(constants)* Reduce command timeout from 7200 to 3600 seconds for improved performance +- *(github)* Update repository URL to point to the v4.x branch for development +- *(models)* Update sorting of scheduled database backups to order by creation date instead of name +- *(socialite)* Add custom base URL support for GitLab provider in OAuth settings +- *(configuration-checker)* Update message to clarify redeployment requirement for configuration changes +- *(application)* Reduce docker stop timeout from 30 to 10 seconds for improved application shutdown efficiency +- *(application)* Increase docker stop timeout from 10 to 30 seconds for better application shutdown handling +- *(validation)* Update git:// URL validation to support port numbers and tilde characters in paths +- Resolve scroll lock issue after closing quick search modal with escape key +- Prevent quick search modal duplication from keyboard shortcuts + +### 🚜 Refactor + +- *(tests)* Simplify matchWatchPaths tests and update implementation for better clarity +- *(deployment)* Improve environment variable handling in ApplicationDeploymentJob +- *(deployment)* Remove commented-out code and streamline environment variable handling in ApplicationDeploymentJob +- *(application)* Improve handling of docker compose domains by normalizing keys and ensuring valid JSON structure +- *(forms)* Update wire:model bindings to use 'blur' instead of 'blur-sm' for input fields across multiple views + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(application)* Remove debugging statement from loadComposeFile method +- *(workflows)* Update Claude GitHub Action configuration to support new event types and improve permissions + +## [4.0.0-beta.431] - 2025-09-24 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.430] - 2025-09-24 + +### 🚀 Features + +- *(add-watch-paths-for-services)* Show watch paths field for docker compose applications + +### 🐛 Bug Fixes + +- *(PreviewCompose)* Adds port to preview urls +- *(deployment-job)* Enhance build time variable analysis +- *(docker)* Adjust openssh-client installation in Dockerfile to avoid version bug +- *(docker)* Streamline openssh-client installation in Dockerfile +- *(team)* Normalize email case in invite link generation +- *(README)* Update Juxtdigital description to reflect current services +- *(environment-variable-warning)* Enhance warning logic to check for problematic variable values +- *(install)* Ensure proper quoting of environment file paths to prevent issues with spaces +- *(security)* Implement authorization checks for terminal access management +- *(ui)* Improve mobile sidebar close behavior + +### 🚜 Refactor + +- *(installer)* Improve install script +- *(upgrade)* Improve upgrade script +- *(installer, upgrade)* Enhance environment variable management +- *(upgrade)* Enhance logging and quoting in upgrade scripts +- *(upgrade)* Replace warning div with a callout component for better UI consistency +- *(ui)* Replace warning and error divs with callout components for improved consistency and readability +- *(ui)* Improve styling and consistency in environment variable warning and docker cleanup components +- *(security)* Streamline update check functionality and improve UI button interactions in patches view + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Increment coolify version numbers to 4.0.0-beta.431 and 4.0.0-beta.432 in configuration files +- *(versions)* Update coolify version numbers to 4.0.0-beta.432 and 4.0.0-beta.433 in configuration files +- Remove unused files +- Adjust wording +- *(workflow)* Update pull request trigger to pull_request_target and refine permissions for enhanced security + +## [4.0.0-beta.429] - 2025-09-23 + +### 🚀 Features + +- *(environment)* Replace is_buildtime_only with is_runtime and is_buildtime flags for environment variables, updating related logic and views +- *(deployment)* Handle buildtime and runtime variables during deployment +- *(search)* Implement global search functionality with caching and modal interface +- *(search)* Enable query logging for global search caching +- *(environment)* Add dynamic checkbox options for environment variable settings based on user permissions and variable types +- *(redaction)* Implement sensitive information redaction in logs and commands +- Improve detection of special network modes +- *(api)* Add endpoint to update backup configuration by UUID and backup ID; modify response to include backup id +- *(databases)* Enhance backup management API with new endpoints and improved data handling +- *(github)* Add GitHub app management endpoints +- *(github)* Add update and delete endpoints for GitHub apps +- *(databases)* Enhance backup update and deletion logic with validation +- *(environment-variables)* Implement environment variable analysis for build-time issues +- *(databases)* Implement unique UUID generation for backup execution +- *(cloud-check)* Enhance subscription reporting in CloudCheckSubscription command +- *(cloud-check)* Enhance CloudCheckSubscription command with fix options +- *(stripe)* Enhance subscription handling and verification process +- *(private-key-refresh)* Add refresh dispatch on private key update and connection check +- *(comments)* Add automated comments for labeled pull requests to guide documentation updates +- *(comments)* Ping PR author + +### 🐛 Bug Fixes + +- *(docker)* Enhance container status aggregation to include restarting and exited states +- *(environment)* Correct grammatical errors in helper text for environment variable sorting checkbox +- *(ui)* Change order and fix ui on small screens +- Order for git deploy types +- *(deployment)* Enhance Dockerfile modification for build-time variables and secrets during deployment in case of docker compose buildpack +- Hide sensitive email change fields in team member responses +- *(domains)* Trim whitespace from domains before validation +- *(databases)* Update backup retrieval logic to include team context +- *(environment-variables)* Update affected services in environment variable analysis +- *(team)* Clear stripe_subscription_id on subscription end +- *(github)* Update authentication method for GitHub app operations +- *(databases)* Restrict database updates to allowed fields only +- *(cache)* Add Model import to ClearsGlobalSearchCache trait for improved functionality +- *(environment-variables)* Correct method call syntax in analyzeBuildVariable function +- *(clears-global-search-cache)* Refine team retrieval logic in getTeamIdForCache method +- *(subscription-job)* Enhance retry logic for VerifyStripeSubscriptionStatusJob +- *(environment-variable)* Update checkbox visibility and helper text for build and runtime options +- *(deployment-job)* Escape single quotes in build arguments for Docker Compose command + +### 🚜 Refactor + +- *(environment)* Conditionally render Docker Build Secrets checkbox based on build pack type +- *(search)* Optimize cache clearing logic to only trigger on searchable field changes +- *(environment)* Streamline rendering of Docker Build Secrets checkbox and adjust layout for environment variable settings +- *(proxy)* Streamline proxy configuration form layout and improve button placements +- *(remoteProcess)* Remove redundant file transfer functions for improved clarity +- *(github)* Enhance API request handling and validation +- *(databases)* Remove deprecated backup parameters from API documentation +- *(databases)* Streamline backup queries to use team context +- *(databases)* Update backup queries to use team-specific method +- *(server)* Update dispatch messages and streamline data synchronization +- *(cache)* Update team retrieval method in ClearsGlobalSearchCache trait +- *(database-backup)* Move unique UUID generation for backup execution to database loop +- *(cloud-commands)* Consolidate and enhance subscription management commands +- *(toast-component)* Improve layout and icon handling in toast notifications +- *(private-key-update)* Implement transaction for private key association and connection validation + +### 📚 Documentation + +- Update changelog +- Update changelog +- *(claude)* Update testing guidelines and add note on Application::team relationship + +### 🎨 Styling + +- *(environment-variable)* Adjust SVG icon margin for improved layout in locked state +- *(proxy)* Adjust padding in proxy configuration form for better visual alignment + +### ⚙️ Miscellaneous Tasks + +- Change order of runtime and buildtime +- *(docker-compose)* Update soketi image version to 1.0.10 in production and Windows configurations +- *(versions)* Update coolify version numbers to 4.0.0-beta.430 and 4.0.0-beta.431 in configuration files + +## [4.0.0-beta.428] - 2025-09-15 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.427] - 2025-09-15 + +### 🚀 Features + +- Add Ente Photos service template +- *(command)* Add option to sync GitHub releases to BunnyCDN and refactor sync logic +- *(ui)* Display current version in settings dropdown and update UI accordingly +- *(settings)* Add option to restrict PR deployments to repository members and contributors +- *(command)* Implement SSH command retry logic with exponential backoff and logging for better error handling +- *(ssh)* Add Sentry tracking for SSH retry events to enhance error monitoring +- *(exceptions)* Introduce NonReportableException to handle known errors and update Handler for selective reporting +- *(sudo-helper)* Add helper functions for command parsing and ownership management with sudo +- *(dev-command)* Dispatch CheckHelperImageJob during instance initialization to enhance setup process +- *(ssh-multiplexing)* Enhance multiplexed connection management with health checks and metadata caching +- *(ssh-multiplexing)* Add connection age metadata handling to improve multiplexed connection management +- *(database-backup)* Enhance error handling and output management in DatabaseBackupJob +- *(application)* Display parsing version in development mode and clean up domain conflict modal markup +- *(deployment)* Add SERVICE_NAME variables for service discovery +- *(storages)* Add method to retrieve the first storage ID for improved stability in storage display +- *(environment)* Add 'is_literal' attribute to environment variable for enhanced configuration options +- *(pre-commit)* Automate generation of service templates and OpenAPI documentation during pre-commit hook +- *(execute-container)* Enhance container command form with auto-connect feature for single container scenarios +- *(environment)* Introduce 'is_buildtime_only' attribute to environment variables for improved build-time configuration +- *(templates)* Add n8n service with PostgreSQL and worker support for enhanced workflow automation +- *(user-management)* Implement user deletion command with phased resource and subscription cancellation, including dry run option +- *(sentinel)* Add support for custom Docker images in StartSentinel and related methods +- *(sentinel)* Add slide-over for viewing Sentinel logs and custom Docker image input for development +- *(executions)* Add 'Load All' button to view all logs and implement loadAllLogs method for complete log retrieval +- *(auth)* Enhance user login flow to handle team invitations, attaching users to invited teams upon first login and maintaining personal team logic for regular logins +- *(laravel-boost)* Add Laravel Boost guidelines and MCP server configuration to enhance development experience +- *(deployment)* Enhance deployment status reporting with detailed information on active deployments and team members +- *(deployment)* Implement cancellation checks during deployment process to enhance user control and prevent unnecessary execution +- *(deployment)* Introduce 'use_build_secrets' setting for enhanced security during Docker builds and update related logic in deployment process + +### 🐛 Bug Fixes + +- *(ui)* Transactional email settings link on members page (#6491) +- *(api)* Add custom labels generation for applications with readonly container label setting enabled +- *(ui)* Add cursor pointer to upgrade button for better user interaction +- *(templates)* Update SECRET_KEY environment variable in getoutline.yaml to use SERVICE_HEX_32_OUTLINE +- *(command)* Enhance database deletion command to support multiple database types +- *(command)* Enhance cleanup process for stuck application previews by adding force delete for trashed records +- *(user)* Ensure email attributes are stored in lowercase for consistency and prevent case-related issues +- *(webhook)* Replace delete with forceDelete for application previews to ensure immediate removal +- *(ssh)* Introduce SshRetryHandler and SshRetryable trait for enhanced SSH command retry logic with exponential backoff and error handling +- Appwrite template - 500 errors, missing env vars etc. +- *(LocalFileVolume)* Add missing directory creation command for workdir in saveStorageOnServer method +- *(ScheduledTaskJob)* Replace generic Exception with NonReportableException for better error handling +- *(web-routes)* Enhance backup response messages to clarify local and S3 availability +- *(proxy)* Replace CheckConfiguration with GetProxyConfiguration and SaveConfiguration with SaveProxyConfiguration for improved clarity and consistency in proxy management +- *(private-key)* Implement transaction handling and error verification for private key storage operations +- *(deployment)* Add COOLIFY_* environment variables to Nixpacks build context for enhanced deployment configuration +- *(application)* Add functionality to stop and remove Docker containers on server +- *(templates)* Update 'compose' configuration for Appwrite service to enhance compatibility and streamline deployment +- *(security)* Update contact email for reporting vulnerabilities to enhance privacy +- *(feedback)* Update feedback email address to improve communication with users +- *(security)* Update contact email for vulnerability reports to improve security communication +- *(navbar)* Restrict subscription link visibility to admin users in cloud environment +- *(docker)* Enhance container status aggregation for multi-container applications, including exclusion handling based on docker-compose configuration +- *(application)* Improve watch paths handling by trimming and filtering empty paths to prevent unnecessary triggers +- *(server)* Update server usability check to reflect actual Docker availability status +- *(server)* Add build server check to disable Sentinel and update related logic +- *(server)* Implement refreshServer method and update navbar event listener for improved server state management +- *(deployment)* Prevent removal of running containers for pull request deployments in case of failure +- *(docker)* Redirect stderr to stdout for container log retrieval to capture error messages +- *(clone)* Update destinations method call to ensure correct retrieval of selected destination + +### 🚜 Refactor + +- *(jobs)* Pull github changelogs from cdn instead of github +- *(command)* Streamline database deletion process to handle multiple database types and improve user experience +- *(command)* Improve database collection logic for deletion command by using unique identifiers and enhancing user experience +- *(command)* Remove InitChangelog command as it is no longer needed +- *(command)* Streamline Init command by removing unnecessary options and enhancing error handling for various operations +- *(webhook)* Replace direct forceDelete calls with DeleteResourceJob dispatch for application previews +- *(command)* Replace forceDelete calls with DeleteResourceJob dispatch for all stuck resources in cleanup process +- *(command)* Simplify SSH command retry logic by removing unnecessary logging and improving delay calculation +- *(ssh)* Enhance error handling in SSH command execution and improve connection validation logging +- *(backlog)* Remove outdated guidelines and project manager agent files to streamline task management documentation +- *(error-handling)* Remove ray debugging statements from CheckUpdates and shared helper functions to clean up error reporting +- *(file-transfer)* Replace base64 encoding with direct file transfer method across multiple database actions for improved clarity and efficiency +- *(remoteProcess)* Remove debugging statement from transfer_file_to_server function to clean up code +- *(dns-validation)* Rename DNS validation functions for consistency and clarity, and remove unused code +- *(file-transfer)* Replace base64 encoding with direct file transfer method in various components for improved clarity and efficiency +- *(private-key)* Remove debugging statement from storeInFileSystem method for cleaner code +- *(github-webhook)* Restructure application processing by grouping applications by server for improved deployment handling +- *(deployment)* Enhance queuing logic to support concurrent deployments by including pull request ID in checks +- *(remoteProcess)* Remove debugging statement from transfer_file_to_container function for cleaner code +- *(deployment)* Streamline next deployment queuing logic by repositioning queue_next_deployment call +- *(deployment)* Add validation for pull request existence in deployment process to enhance error handling +- *(database)* Remove volume_configuration_dir and streamline configuration directory usage in MongoDB and PostgreSQL handlers +- *(application-source)* Improve layout and accessibility of Git repository links in the application source view +- *(models)* Remove 'is_readonly' attribute from multiple database models for consistency +- *(webhook)* Remove Webhook model and related logic; add migrations to drop webhooks and kubernetes tables +- *(clone)* Consolidate application cloning logic into a dedicated function for improved maintainability and readability +- *(clone)* Integrate preview cloning logic directly into application cloning function for improved clarity and maintainability +- *(application)* Enhance environment variable retrieval in configuration change check for improved accuracy +- *(clone)* Enhance application cloning by separating production and preview environment variable handling +- *(deployment)* Add environment variable copying logic to Docker build commands for pull requests +- *(environment)* Standardize service name formatting by replacing '-' and '.' with '_' in environment variable keys +- *(deployment)* Update environment file handling in Docker commands to use '/artifacts/' path and streamline variable management +- *(openapi)* Remove 'is_build_time' attribute from environment variable definitions to streamline configuration +- *(environment)* Remove 'is_build_time' attribute from environment variable handling across the application to simplify configuration +- *(environment)* Streamline environment variable handling by replacing sorting methods with direct property access and enhancing query ordering for improved performance +- *(stripe-jobs)* Comment out internal notification calls and add subscription status verification before sending failure notifications +- *(deployment)* Streamline environment variable handling for dockercompose and improve sorting of runtime variables +- *(remoteProcess)* Remove command log comments for file transfers to simplify code +- *(remoteProcess)* Remove file transfer handling from remote_process and instant_remote_process functions to simplify code +- *(deployment)* Update environment file paths in docker compose commands to use working directory for improved consistency +- *(server)* Remove debugging ray call from validateConnection method for cleaner code +- *(deployment)* Conditionally cleanup build secrets based on Docker BuildKit support and remove redundant calls for improved efficiency +- *(deployment)* Remove redundant environment variable documentation from Dockerfile comments to streamline the deployment process +- *(deployment)* Streamline Docker BuildKit detection and environment variable handling for enhanced security during application deployment +- *(deployment)* Optimize BuildKit capabilities detection and remove unnecessary comments for cleaner deployment logic +- *(deployment)* Rename method for modifying Dockerfile to improve clarity and streamline build secrets integration + +### 📚 Documentation + +- Update changelog +- *(testing-patterns)* Add important note to always run tests inside the `coolify` container for clarity + +### ⚙️ Miscellaneous Tasks + +- Update coolify version to 4.0.0-beta.427 and nightly version to 4.0.0-beta.428 +- Use main value then fallback to service_ values +- Remove webhooks table cleanup +- *(cleanup)* Remove deprecated ServerCheck and related job classes to streamline codebase +- *(versions)* Update sentinel version from 0.0.15 to 0.0.16 in versions.json files +- *(constants)* Update realtime_version from 1.0.10 to 1.0.11 +- *(versions)* Increment coolify version to 4.0.0-beta.428 and update realtime_version to 1.0.10 +- *(docker)* Add a blank line for improved readability in Dockerfile +- *(versions)* Bump coolify version to 4.0.0-beta.429 and nightly version to 4.0.0-beta.430 + +## [4.0.0-beta.426] - 2025-08-28 + +### 🚜 Refactor + +- *(policy)* Simplify ServiceDatabasePolicy methods to always return true and add manageBackups method + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Update coolify version to 4.0.0-beta.426 and nightly version to 4.0.0-beta.427 + +## [4.0.0-beta.425] - 2025-08-28 + +### 🚀 Features + +- *(domains)* Implement domain conflict detection and user confirmation modal across application components +- *(domains)* Add force_domain_override option and enhance domain conflict detection responses + +### 🐛 Bug Fixes + +- *(previews)* Simplify FQDN generation logic by removing unnecessary empty check +- *(templates)* Update Matrix service compose configuration for improved compatibility and clarity + +### 🚜 Refactor + +- *(urls)* Replace generateFqdn with generateUrl for consistent URL generation across applications +- *(domains)* Rename check_domain_usage to checkDomainUsage and update references across the application +- *(auth)* Simplify access control logic in CanAccessTerminal and ServerPolicy by allowing all users to perform actions + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Update coolify version to 4.0.0-beta.425 and nightly version to 4.0.0-beta.426 + +## [4.0.0-beta.424] - 2025-08-27 + +### 💼 Other + +- Allow deploy from container image hash + +### 📚 Documentation + +- Update changelog +- Update changelog + +## [4.0.0-beta.423] - 2025-08-27 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.422] - 2025-08-27 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.421] - 2025-08-26 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.420.9] - 2025-08-26 + +### 🚀 Features + +- *(policies)* Add EnvironmentVariablePolicy for managing environment variables ( it was missing ) + +### 🐛 Bug Fixes + +- *(backups)* S3 backup upload is failing +- *(backups)* Rollback helper update for now +- *(parsers)* Replace hyphens with underscores in service names for consistency. this allows to properly parse custom domains in docker compose based applications +- *(parsers)* Implement parseDockerVolumeString function to handle various Docker volume formats and modes, including environment variables and Windows paths. Add unit tests for comprehensive coverage. +- *(git)* Submodule update command uses an unsupported option (#6454) +- *(service)* Swap URL for FQDN on matrix template (#6466) +- *(parsers)* Enhance volume string handling by preserving mode in application and service parsers. Update related unit tests for validation. +- *(docker)* Update parser version in FQDN generation for service-specific URLs +- *(parsers)* Do not modify service names, only for getting fqdns and related envs +- *(compose)* Temporary allow to edit volumes in apps (compose based) and services + +### 🚜 Refactor + +- *(git)* Improve submodule cloning +- *(parsers)* Remove unnecessary hyphen-to-underscore replacement for service names in serviceParser function + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(core)* Update version +- *(core)* Update version +- *(versions)* Update coolify version to 4.0.0-beta.421 and nightly version to 4.0.0-beta.422 +- Update version +- Update development node version +- Update coolify version to 4.0.0-beta.423 and nightly version to 4.0.0-beta.424 +- Update coolify version to 4.0.0-beta.424 and nightly version to 4.0.0-beta.425 + +## [4.0.0-beta.420.8] - 2025-08-26 + +### 🚜 Refactor + +- *(policies)* Remove Response type hint from update methods in ApplicationPreviewPolicy and DatabasePolicy for improved flexibility + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.420.7] - 2025-08-26 + +### 🚀 Features + +- *(service)* Add TriliumNext service (#5970) +- *(service)* Add Matrix service (#6029) +- *(service)* Add GitHub Action runner service (#6209) +- *(terminal)* Dispatch focus event for terminal after connection and enhance focus handling in JavaScript +- *(lang)* Add Polish language & improve forgot_password translation (#6306) +- *(service)* Update Authentik template (#6264) +- *(service)* Add sequin template (#6105) +- *(service)* Add pi-hole template (#6020) +- *(services)* Add Chroma service (#6201) +- *(service)* Add OpenPanel template (#5310) +- *(service)* Add librechat template (#5654) +- *(service)* Add Homebox service (#6116) +- *(service)* Add pterodactyl & wings services (#5537) +- *(service)* Add Bluesky PDS template (#6302) +- *(input)* Add autofocus attribute to input component for improved accessibility +- *(core)* Finally fqdn is fqdn and url is url. haha +- *(user)* Add changelog read tracking and unread count method +- *(templates)* Add new service templates and update existing compose files for various applications +- *(changelog)* Implement automated changelog fetching from GitHub and enhance changelog read tracking +- *(drizzle-gateway)* Add new drizzle-gateway service with configuration and logo +- *(drizzle-gateway)* Enhance service configuration by adding Master Password field and updating compose file path +- *(templates)* Add new service templates for Homebox, LibreChat, Pterodactyl, and Wings with corresponding configurations and logos +- *(templates)* Add Bluesky PDS service template and update compose file with new environment variable +- *(readme)* Add CubePath as a big sponsor and include new small sponsors with logos +- *(api)* Add create_environment endpoint to ProjectController for environment creation in projects +- *(api)* Add endpoints for managing environments in projects, including listing, creating, and deleting environments +- *(backup)* Add disable local backup option and related logic for S3 uploads +- *(dev patches)* Add functionality to send test email with patch data in development mode +- *(templates)* Added category per service +- *(email)* Implement email change request and verification process +- Generate category for services +- *(service)* Add elasticsearch template (#6300) +- *(sanitization)* Integrate DOMPurify for HTML sanitization across components +- *(cleanup)* Add command for sanitizing name fields across models +- *(sanitization)* Enhance HTML sanitization with improved DOMPurify configuration +- *(validation)* Centralize validation patterns for names and descriptions +- *(git-settings)* Add support for shallow cloning in application settings +- *(auth)* Implement authorization checks for server updates across multiple components +- *(auth)* Implement authorization for PrivateKey management +- *(auth)* Implement authorization for Docker and server management +- *(validation)* Add custom validation rules for Git repository URLs and branches +- *(security)* Add authorization checks for package updates in Livewire components +- *(auth)* Implement authorization checks for application management +- *(auth)* Enhance API error handling for authorization exceptions +- *(auth)* Add comprehensive authorization checks for all kind of resource creations +- *(auth)* Implement authorization checks for database management +- *(auth)* Refine authorization checks for S3 storage and service management +- *(auth)* Implement comprehensive authorization checks across API controllers +- *(auth)* Introduce resource creation authorization middleware and policies for enhanced access control +- *(auth)* Add middleware for resource creation authorization +- *(auth)* Enhance authorization checks in Livewire components for resource management +- *(validation)* Add ValidIpOrCidr rule for validating IP addresses and CIDR notations; update API access settings UI and add comprehensive tests +- *(docs)* Update architecture and development guidelines; enhance form components with built-in authorization system and improve routing documentation +- *(docs)* Expand authorization documentation for custom Alpine.js components; include manual protection patterns and implementation guidelines +- *(sentinel)* Implement SentinelRestarted event and update Livewire components to handle server restart notifications +- *(api)* Enhance IP access control in middleware and settings; support CIDR notation and special case for 0.0.0.0 to allow all IPs +- *(acl)* Change views/backend code to able to use proper ACL's later on. Currently it is not enabled. +- *(docs)* Add Backlog.md guidelines and project manager backlog agent; enhance CLAUDE.md with new links for task management +- *(docs)* Add tasks for implementing Docker build caching and optimizing staging builds; include detailed acceptance criteria and implementation plans +- *(docker)* Implement Docker cleanup processing in ScheduledJobManager; refactor server task scheduling to streamline cleanup job dispatching +- *(docs)* Expand Backlog.md guidelines with comprehensive usage instructions, CLI commands, and best practices for task management to enhance project organization and collaboration + +### 🐛 Bug Fixes + +- *(service)* Triliumnext platform and link +- *(application)* Update service environment variables when generating domain for Docker Compose +- *(application)* Add option to suppress toast notifications when loading compose file +- *(git)* Tracking issue due to case sensitivity +- *(git)* Tracking issue due to case sensitivity +- *(git)* Tracking issue due to case sensitivity +- *(ui)* Delete button width on small screens (#6308) +- *(service)* Matrix entrypoint +- *(ui)* Add flex-wrap to prevent overflow on small screens (#6307) +- *(docker)* Volumes get delete when stopping a service if `Delete Unused Volumes` is activated (#6317) +- *(docker)* Cleanup always running on deletion +- *(proxy)* Remove hardcoded port 80/443 checks (#6275) +- *(service)* Update healthcheck of penpot backend container (#6272) +- *(api)* Duplicated logs in application endpoint (#6292) +- *(service)* Documenso signees always pending (#6334) +- *(api)* Update service upsert to retain name and description values if not set +- *(database)* Custom postgres configs with SSL (#6352) +- *(policy)* Update delete method to check for admin status in S3StoragePolicy +- *(container)* Sort containers alphabetically by name in ExecuteContainerCommand and update filtering in Terminal Index +- *(application)* Streamline environment variable updates for Docker Compose services and enhance FQDN generation logic +- *(constants)* Update 'Change Log' to 'Changelog' in settings dropdown +- *(constants)* Update coolify version to 4.0.0-beta.420.7 +- *(parsers)* Clarify comments and update variable checks for FQDN and URL handling +- *(terminal)* Update text color for terminal availability message and improve readability +- *(drizzle-gateway)* Remove healthcheck from drizzle-gateway compose file and update service template +- *(templates)* Should generate old SERVICE_FQDN service templates as well +- *(constants)* Update official service template URL to point to the v4.x branch for accuracy +- *(git)* Use exact refspec in ls-remote to avoid matching similarly named branches (e.g., changeset-release/main). Use refs/heads/ or provider-specific PR refs. +- *(ApplicationPreview)* Change null check to empty check for fqdn in generate_preview_fqdn method +- *(email notifications)* Enhance EmailChannel to validate team membership for recipients and handle errors gracefully +- *(service api)* Separate create and update service functionalities +- *(templates)* Added a category tag for the docs service filter +- *(application)* Clear Docker Compose specific data when switching away from dockercompose +- *(database)* Conditionally set started_at only if the database is running +- *(ui)* Handle null values in postgres metrics (#6388) +- Disable env sorting by default +- *(proxy)* Filter host network from default proxy (#6383) +- *(modal)* Enhance confirmation text handling +- *(notification)* Update unread count display and improve HTML rendering +- *(select)* Remove unnecessary sanitization for logo rendering +- *(tags)* Update tag display to limit name length and adjust styling +- *(init)* Improve error handling for deployment and template pulling processes +- *(settings-dropdown)* Adjust unread count badge size and display logic for better consistency +- *(sanitization)* Enhance DOMPurify hook to remove Alpine.js directives for improved XSS protection +- *(servercheck)* Properly check server statuses with and without Sentinel +- *(errors)* Update error pages to provide navigation options +- *(github-deploy-key)* Update background color for selected private keys in deployment key selection UI +- *(auth)* Enhance authorization checks in application management + +### 💼 Other + +- *(settings-dropdown)* Add icons to buttons for improved UI in settings dropdown +- *(ui)* Introduce task for simplifying resource operations UI by replacing boxes with dropdown selections to enhance user experience and streamline interactions + +### 🚜 Refactor + +- *(jobs)* Remove logging for ScheduledJobManager and ServerResourceManager start and completion +- *(services)* Update validation rules to be optional +- *(service)* Improve langfuse +- *(service)* Improve openpanel template +- *(service)* Improve librechat +- *(public-git-repository)* Enhance form structure and add autofocus to repository URL input +- *(public-git-repository)* Remove commented-out code for cleaner template +- *(templates)* Update service template file handling to use dynamic file name from constants +- *(parsers)* Streamline domain handling in applicationParser and improve DNS validation logic +- *(templates)* Replace SERVICE_FQDN variables with SERVICE_URL in compose files for consistency +- *(links)* Replace inline SVGs with reusable external link component for consistency and improved maintainability +- *(previews)* Improve layout and add deployment/application logs links for previews +- *(docker compose)* Remove deprecated newParser function and associated test file to streamline codebase +- *(shared helpers)* Remove unused parseServiceVolumes function to clean up codebase +- *(parsers)* Update volume parsing logic to use beforeLast and afterLast for improved accuracy +- *(validation)* Implement centralized validation patterns across components +- *(jobs)* Rename job classes to indicate deprecation status +- Update check frequency logic for cloud and self-hosted environments; streamline server task scheduling and timezone handling +- *(policies)* Remove Response type hint from update methods in ApplicationPreviewPolicy and DatabasePolicy for improved flexibility + +### 📚 Documentation + +- *(claude)* Clarify that artisan commands should only be run inside the "coolify" container during development +- Add AGENTS.md for project guidance and development instructions +- Update changelog +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(service)* Improve matrix service +- *(service)* Format runner service +- *(service)* Improve sequin +- *(service)* Add `NOT_SECURED` env to Postiz (#6243) +- *(service)* Improve evolution-api environment variables (#6283) +- *(service)* Update Langfuse template to v3 (#6301) +- *(core)* Remove unused argument +- *(deletion)* Rename isDeleteOperation to deleteConnectedNetworks +- *(docker)* Remove unused arguments on StopService +- *(service)* Homebox formatting +- Clarify usage of custom redis configuration (#6321) +- *(changelogs)* Add .gitignore for changelogs directory and remove outdated changelog files for May, June, and July 2025 +- *(service)* Change affine images (#6366) +- Elasticsearch URL, fromatting and add category +- Update service-templates json files +- *(docs)* Remove AGENTS.md file; enhance CLAUDE.md with detailed form authorization patterns and service configuration examples +- *(cleanup)* Remove unused GitLab view files for change, new, and show pages +- *(workflows)* Add backlog directory to build triggers for production and staging workflows +- *(config)* Disable auto_commit in backlog configuration to prevent automatic commits +- *(versions)* Update coolify version to 4.0.0-beta.420.8 and nightly version to 4.0.0-beta.420.9 in versions.json and constants.php +- *(docker)* Update soketi image version to 1.0.10 in production and Windows configurations + +### ◀️ Revert + +- *(parser)* Enhance FQDN generation logic for services and applications + +## [4.0.0-beta.420.6] - 2025-07-18 + +### 🚀 Features + +- *(service)* Enable password protection for the Wireguard Ul +- *(queues)* Improve Horizon config to reduce CPU and RAM usage (#6212) +- *(service)* Add Gowa service (#6164) +- *(container)* Add updatedSelectedContainer method to connect to non-default containers and update wire:model for improved reactivity +- *(application)* Implement environment variable updates for Docker Compose applications, including creation, updating, and deletion of SERVICE_FQDN and SERVICE_URL variables + +### 🐛 Bug Fixes + +- *(installer)* Public IPv4 link does not work +- *(composer)* Version constraint of prompts +- *(service)* Budibase secret keys (#6205) +- *(service)* Wg-easy host should be just the FQDN +- *(ui)* Search box overlaps the sidebar navigation (#6176) +- *(webhooks)* Exclude webhook routes from CSRF protection (#6200) +- *(services)* Update environment variable naming convention to use underscores instead of dashes for SERVICE_FQDN and SERVICE_URL + +### 🚜 Refactor + +- *(service)* Improve gowa +- *(previews)* Streamline preview domain generation logic in ApplicationDeploymentJob for improved clarity and maintainability +- *(services)* Simplify environment variable updates by using updateOrCreate and add cleanup for removed FQDNs + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(service)* Update Nitropage template (#6181) +- *(versions)* Update all version +- *(bump)* Update composer deps +- *(version)* Bump Coolify version to 4.0.0-beta.420.6 + +## [4.0.0-beta.420.4] - 2025-07-08 + +### 🚀 Features + +- *(scheduling)* Add command to manually run scheduled database backups and tasks with options for chunking, delays, and dry runs +- *(scheduling)* Add frequency filter option for manual execution of scheduled jobs +- *(logging)* Implement scheduled logs command and enhance backup/task scheduling with cron checks +- *(logging)* Add frequency filters for scheduled logs command to support hourly, daily, weekly, and monthly job views +- *(scheduling)* Introduce ScheduledJobManager and ServerResourceManager for enhanced job scheduling and resource management +- *(previews)* Implement soft delete and cleanup for ApplicationPreview, enhancing resource management in DeleteResourceJob + +### 🐛 Bug Fixes + +- *(service)* Update Postiz compose configuration for improved server availability +- *(install.sh)* Use IPV4_PUBLIC_IP variable in output instead of repeated curl +- *(env)* Generate literal env variables better +- *(deployment)* Update x-data initialization in deployment view for improved functionality +- *(deployment)* Enhance COOLIFY_URL and COOLIFY_FQDN variable generation for better compatibility +- *(deployment)* Improve docker-compose domain handling and environment variable generation +- *(deployment)* Refactor domain parsing and environment variable generation using Spatie URL library +- *(deployment)* Update COOLIFY_URL and COOLIFY_FQDN generation to use Spatie URL library for improved accuracy +- *(scheduling)* Change redis cleanup command frequency from hourly to weekly for better resource management +- *(versions)* Update coolify version numbers in versions.json and constants.php to 4.0.0-beta.420.5 and 4.0.0-beta.420.6 +- *(database)* Ensure internal port defaults correctly for unsupported database types in StartDatabaseProxy +- *(versions)* Update coolify version numbers in versions.json and constants.php to 4.0.0-beta.420.6 and 4.0.0-beta.420.7 +- *(scheduling)* Remove unnecessary padding from scheduled task form layout for improved UI consistency +- *(horizon)* Update queue configuration to use environment variable for dynamic queue management +- *(horizon)* Add silenced jobs +- *(application)* Sanitize service names for HTML form binding and ensure original names are stored in docker compose domains +- *(previews)* Adjust padding for rate limit message in application previews +- *(previews)* Order application previews by pull request ID in descending order +- *(previews)* Add unique wire keys for preview containers and services based on pull request ID +- *(previews)* Enhance domain generation logic for application previews, ensuring unique domains are created when none are set +- *(previews)* Refine preview domain generation for Docker Compose applications, ensuring correct method usage based on build pack type +- *(ui)* Typo on proxy request handler tooltip (#6192) +- *(backups)* Large database backups are not working (#6217) +- *(backups)* Error message if there is no exception + +### 🚜 Refactor + +- *(previews)* Streamline preview URL generation by utilizing application method +- *(application)* Adjust layout and spacing in general application view for improved UI +- *(postgresql)* Improve layout and spacing in SSL and Proxy configuration sections for better UI consistency +- *(scheduling)* Replace deprecated job checks with ScheduledJobManager and ServerResourceManager for improved scheduling efficiency +- *(previews)* Move preview domain generation logic to ApplicationPreview model for better encapsulation and consistency across webhook handlers + +### 📚 Documentation + +- Update changelog +- Update changelog + +## [4.0.0-beta.420.3] - 2025-07-03 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.420.2] - 2025-07-03 + +### 🚀 Features + +- *(template)* Added excalidraw (#6095) +- *(template)* Add excalidraw service configuration with documentation and tags + +### 🐛 Bug Fixes + +- *(terminal)* Ensure shell execution only uses valid shell if available in terminal command +- *(ui)* Improve destination selection description for clarity in resource segregation +- *(jobs)* Update middleware to use expireAfter for WithoutOverlapping in multiple job classes +- Removing eager loading (#6071) +- *(template)* Adjust health check interval and retries for excalidraw service +- *(ui)* Env variable settings wrong order +- *(service)* Ensure configuration changes are properly tracked and dispatched + +### 🚜 Refactor + +- *(ui)* Enhance project cloning interface with improved table layout for server and resource selection +- *(terminal)* Simplify command construction for SSH execution +- *(settings)* Streamline instance admin checks and initialization of settings in Livewire components +- *(policy)* Optimize team membership checks in S3StoragePolicy +- *(popup)* Improve styling and structure of the small popup component +- *(shared)* Enhance FQDN generation logic for services in newParser function +- *(redis)* Enhance CleanupRedis command with dry-run option and improved key deletion logic +- *(init)* Standardize method naming conventions and improve command structure in Init.php +- *(shared)* Improve error handling in getTopLevelNetworks function to return network name on invalid docker-compose.yml +- *(database)* Improve error handling for unsupported database types in StartDatabaseProxy + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Bump coolify and nightly versions to 4.0.0-beta.420.3 and 4.0.0-beta.420.4 respectively +- *(versions)* Update coolify and nightly versions to 4.0.0-beta.420.4 and 4.0.0-beta.420.5 respectively + +## [4.0.0-beta.420.1] - 2025-06-26 + +### 🐛 Bug Fixes + +- *(server)* Prepend 'mux_' to UUID in muxFilename method for consistent naming +- *(ui)* Enhance terminal access messaging to clarify server functionality and terminal status +- *(database)* Proxy ssl port if ssl is enabled + +### 🚜 Refactor + +- *(ui)* Separate views for instance settings to separate paths to make it cleaner +- *(ui)* Remove unnecessary step3ButtonText attributes from modal confirmation components for cleaner code + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update Coolify versions to 4.0.0-beta.420.2 and 4.0.0-beta.420.3 in multiple files + +## [4.0.0-beta.420] - 2025-06-26 + +### 🚀 Features + +- *(service)* Add Miniflux service (#5843) +- *(service)* Add Pingvin Share service (#5969) +- *(auth)* Add Discord OAuth Provider (#5552) +- *(auth)* Add Clerk OAuth Provider (#5553) +- *(auth)* Add Zitadel OAuth Provider (#5490) +- *(core)* Set custom API rate limit (#5984) +- *(service)* Enhance service status handling and UI updates +- *(cleanup)* Add functionality to delete teams with no members or servers in CleanupStuckedResources command +- *(ui)* Add heart icon and enhance popup messaging for sponsorship support +- *(settings)* Add sponsorship popup toggle and corresponding database migration +- *(migrations)* Add optimized indexes to activity_log for improved query performance + +### 🐛 Bug Fixes + +- *(service)* Audiobookshelf healthcheck command (#5993) +- *(service)* Downgrade Evolution API phone version (#5977) +- *(service)* Pingvinshare-with-clamav +- *(ssh)* Scp requires square brackets for ipv6 (#6001) +- *(github)* Changing github app breaks the webhook. it does not anymore +- *(parser)* Improve FQDN generation and update environment variable handling +- *(ui)* Enhance status refresh buttons with loading indicators +- *(ui)* Update confirmation button text for stopping database and service +- *(routes)* Update middleware for deploy route to use 'api.ability:deploy' +- *(ui)* Refine API token creation form and update helper text for clarity +- *(ui)* Adjust layout of deployments section for improved alignment +- *(ui)* Adjust project grid layout and refine server border styling for better visibility +- *(ui)* Update border styling for consistency across components and enhance loading indicators +- *(ui)* Add padding to section headers in settings views for improved spacing +- *(ui)* Reduce gap between input fields in email settings for better alignment +- *(docker)* Conditionally enable gzip compression in Traefik labels based on configuration +- *(parser)* Enable gzip compression conditionally for Pocketbase images and streamline service creation logic +- *(ui)* Update padding for trademarks policy and enhance spacing in advanced settings section +- *(ui)* Correct closing tag for sponsorship link in layout popups +- *(ui)* Refine wording in sponsorship donation prompt in layout popups +- *(ui)* Update navbar icon color and enhance popup layout for sponsorship support +- *(ui)* Add target="_blank" to sponsorship links in layout popups for improved user experience +- *(models)* Refine comment wording in User model for clarity on user deletion criteria +- *(models)* Improve user deletion logic in User model to handle team member roles and prevent deletion if user is alone in root team +- *(ui)* Update wording in sponsorship prompt for clarity and engagement +- *(shared)* Refactor gzip handling for Pocketbase in newParser function for improved clarity + +### 🚜 Refactor + +- *(service)* Update Hoarder to their new name karakeep (#5964) +- *(service)* Karakeep naming and formatting +- *(service)* Improve miniflux +- *(core)* Rename API rate limit ENV +- *(ui)* Simplify container selection form in execute-container-command view +- *(email)* Streamline SMTP and resend settings logic for improved clarity +- *(invitation)* Rename methods for consistency and enhance invitation deletion logic +- *(user)* Streamline user deletion process and enhance team management logic + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(service)* Update Evolution API image to the official one (#6031) +- *(versions)* Bump coolify versions to v4.0.0-beta.420 and v4.0.0-beta.421 +- *(dependencies)* Update composer dependencies to latest versions including resend-laravel to ^0.19.0 and aws-sdk-php to 3.347.0 +- *(versions)* Update Coolify version to 4.0.0-beta.420.1 and add new services (karakeep, miniflux, pingvinshare) to service templates + +## [4.0.0-beta.419] - 2025-06-17 + +### 🚀 Features + +- *(core)* Add 'postmarketos' to supported OS list +- *(service)* Add memos service template (#5032) +- *(ui)* Upgrade to Tailwind v4 (#5710) +- *(service)* Add Navidrome service template (#5022) +- *(service)* Add Passbolt service (#5769) +- *(service)* Add Vert service (#5663) +- *(service)* Add Ryot service (#5232) +- *(service)* Add Marimo service (#5559) +- *(service)* Add Diun service (#5113) +- *(service)* Add Observium service (#5613) +- *(service)* Add Leantime service (#5792) +- *(service)* Add Limesurvey service (#5751) +- *(service)* Add Paymenter service (#5809) +- *(service)* Add CodiMD service (#4867) +- *(modal)* Add dispatchAction property to confirmation modal +- *(security)* Implement server patching functionality +- *(service)* Add Typesense service (#5643) +- *(service)* Add Yamtrack service (#5845) +- *(service)* Add PG Back Web service (#5079) +- *(service)* Update Maybe service and adjust it for the new release (#5795) +- *(oauth)* Set redirect uri as optional and add default value (#5760) +- *(service)* Add apache superset service (#4891) +- *(service)* Add One Time Secret service (#5650) +- *(service)* Add Seafile service (#5817) +- *(service)* Add Netbird-Client service (#5873) +- *(service)* Add OrangeHRM and Grist services (#5212) +- *(rules)* Add comprehensive documentation for Coolify architecture and development practices for AI tools, especially for cursor +- *(server)* Implement server patch check notifications +- *(api)* Add latest query param to Service restart API (#5881) +- *(api)* Add connect_to_docker_network setting to App creation API (#5691) +- *(routes)* Restrict backup download access to team admins and owners +- *(destination)* Update confirmation modal text and add persistent storage warning for server deployment +- *(terminal-access)* Implement terminal access control for servers and containers, including UI updates and backend logic +- *(ca-certificate)* Add CA certificate management functionality with UI integration and routing +- *(security-patches)* Add update check initialization and enhance notification messaging in UI +- *(previews)* Add force deploy without cache functionality and update deploy method to accept force rebuild parameter +- *(security-patterns)* Expand sensitive patterns list to include additional security-related variables +- *(database-backup)* Add MongoDB credential extraction and backup handling to DatabaseBackupJob +- *(activity-monitor)* Implement auto-scrolling functionality and dynamic content observation for improved user experience +- *(utf8-handling)* Implement UTF-8 sanitization for command outputs and enhance error handling in logs processing +- *(navbar)* Add Traefik dashboard availability check and server IP handling; refactor dynamic configurations loading +- *(proxy-dashboard)* Implement ProxyDashboardCacheService to manage Traefik dashboard cache; clear cache on configuration changes and proxy actions +- *(terminal-connection)* Enhance terminal connection handling with auto-connect feature and improved status messaging +- *(terminal)* Implement resize handling with ResizeObserver for improved terminal responsiveness +- *(migration)* Add is_sentinel_enabled column to server_settings with default true +- *(seeder)* Dispatch StartProxy action for each server in ProductionSeeder +- *(seeder)* Add CheckAndStartSentinelJob dispatch for each server in ProductionSeeder +- *(seeder)* Conditionally dispatch StartProxy action based on proxy check result +- *(service)* Update Changedetection template (#5937) + +### 🐛 Bug Fixes + +- *(constants)* Adding 'fedora-asahi-remix' as a supported OS (#5646) +- *(authentik)* Update docker-compose configuration for authentik service +- *(api)* Allow nullable destination_uuid (#5683) +- *(service)* Fix documenso startup and mail (#5737) +- *(docker)* Fix production dockerfile +- *(service)* Navidrome service +- *(service)* Passbolt +- *(service)* Add missing ENVs to NTFY service (#5629) +- *(service)* NTFY is behind a proxy +- *(service)* Vert logo and ENVs +- *(service)* Add platform to Observium service +- *(ActivityMonitor)* Prevent multiple event dispatches during polling +- *(service)* Convex ENVs and update image versions (#5827) +- *(service)* Paymenter +- *(ApplicationDeploymentJob)* Ensure correct COOLIFY_FQDN/COOLIFY_URL values (#4719) +- *(service)* Snapdrop no matching manifest error (#5849) +- *(service)* Use the same volume between chatwoot and sidekiq (#5851) +- *(api)* Validate docker_compose_raw input in ApplicationsController +- *(api)* Enhance validation for docker_compose_raw in ApplicationsController +- *(select)* Update PostgreSQL versions and titles in resource selection +- *(database)* Include DatabaseStatusChanged event in activityMonitor dispatch +- *(css)* Tailwind v5 things +- *(service)* Diun ENV for consistency +- *(service)* Memos service name +- *(css)* 8+ issue with new tailwind v4 +- *(css)* `bg-coollabs-gradient` not working anymore +- *(ui)* Add back missing service navbar components +- *(deploy)* Update resource timestamp handling in deploy_resource method +- *(patches)* DNF reboot logic is flipped +- *(deployment)* Correct syntax for else statement in docker compose build command +- *(shared)* Remove unused relation from queryDatabaseByUuidWithinTeam function +- *(deployment)* Correct COOLIFY_URL and COOLIFY_FQDN assignments based on parsing version in preview deployments +- *(docker)* Ensure correct parsing of environment variables by limiting explode to 2 parts +- *(project)* Update selected environment handling to use environment name instead of UUID +- *(ui)* Update server status display and improve server addition layout +- *(service)* Neon WS Proxy service not working on ARM64 (#5887) +- *(server)* Enhance error handling in server patch check notifications +- *(PushServerUpdateJob)* Add null checks before updating application and database statuses +- *(environment-variables)* Update label text for build variable checkboxes to improve clarity +- *(service-management)* Update service stop and restart messages for improved clarity and formatting +- *(preview-form)* Update helper text formatting in preview URL template input for better readability +- *(application-management)* Improve stop messages for application, database, and service to enhance clarity and formatting +- *(application-configuration)* Prevent access to preview deployments for deploy_key applications and update menu visibility accordingly +- *(select-component)* Handle exceptions during parameter retrieval and environment selection in the mount method +- *(previews)* Escape container names in stopContainers method to prevent shell injection vulnerabilities +- *(docker)* Add protection against empty container queries in GetContainersStatus to prevent unnecessary updates +- *(modal-confirmation)* Decode HTML entities in confirmation text to ensure proper display +- *(select-component)* Enhance user interaction by adding cursor styles and disabling selection during processing +- *(deployment-show)* Remove unnecessary fixed positioning for button container to improve layout responsiveness +- *(email-notifications)* Change notify method to notifyNow for immediate test email delivery +- *(service-templates)* Update Convex service configuration to use FQDN variables +- *(database-heading)* Simplify stop database message for clarity +- *(navbar)* Remove unnecessary x-init directive for loading proxy configuration +- *(patches)* Add padding to loading message for better visibility during update checks +- *(terminal-connection)* Improve error handling and stability for auto-connection; enhance component readiness checks and retry logic +- *(terminal)* Add unique wire:key to terminal component for improved reactivity and state management +- *(css)* Adjust utility classes in utilities.css for consistent application of Tailwind directives +- *(css)* Refine utility classes in utilities.css for proper Tailwind directive application +- *(install)* Update Docker installation script to use dynamic OS_TYPE and correct installation URL +- *(cloudflare)* Add error handling to automated Cloudflare configuration script +- *(navbar)* Add error handling for proxy status check to improve user feedback +- *(web)* Update user team retrieval method for consistent authentication handling +- *(cloudflare)* Update refresh method to correctly set Cloudflare tunnel status and improve user notification on IP address update +- *(service)* Update service template for affine and add migration service for improved deployment process +- *(supabase)* Update Supabase service images and healthcheck methods for improved reliability +- *(terminal)* Now it should work +- *(degraded-status)* Remove unnecessary whitespace in badge element for cleaner HTML +- *(routes)* Add name to security route for improved route management +- *(migration)* Update default value handling for is_sentinel_enabled column in server_settings +- *(seeder)* Conditionally dispatch CheckAndStartSentinelJob based on server's sentinel status +- *(service)* Disable healthcheck logging for Gotenberg (#6005) +- *(service)* Joplin volume name (#5930) +- *(server)* Update sentinelUpdatedAt assignment to use server's sentinel_updated_at property + +### 💼 Other + +- Add support for postmarketOS (#5608) +- *(core)* Simplify events for app/db/service status changes + +### 🚜 Refactor + +- *(service)* Observium +- *(service)* Improve leantime +- *(service)* Imporve limesurvey +- *(service)* Improve CodiMD +- *(service)* Typsense +- *(services)* Improve yamtrack +- *(service)* Improve paymenter +- *(service)* Consolidate configuration change dispatch logic and remove unused navbar component +- *(sidebar)* Simplify server patching link by removing button element +- *(slide-over)* Streamline button element and improve code readability +- *(service)* Enhance modal confirmation component with event dispatching for service stop actions +- *(slide-over)* Enhance class merging for improved component styling +- *(core)* Use property promotion +- *(service)* Improve maybe +- *(applications)* Remove unused docker compose raw decoding +- *(service)* Make TYPESENSE_API_KEY required +- *(ui)* Show toast when server does not work and on stop +- *(service)* Improve superset +- *(service)* Improve Onetimesecret +- *(service)* Improve Seafile +- *(service)* Improve orangehrm +- *(service)* Improve grist +- *(application)* Enhance application stopping logic to support multiple servers +- *(pricing-plans)* Improve label class binding for payment frequency selection +- *(error-handling)* Replace generic Exception with RuntimeException for improved error specificity +- *(error-handling)* Change Exception to RuntimeException for clearer error reporting +- *(service)* Remove informational dispatch during service stop for cleaner execution +- *(server-ui)* Improve layout and messaging in advanced settings and charts views +- *(terminal-access)* Streamline resource retrieval and enhance terminal access messaging in UI +- *(terminal)* Enhance terminal connection management and error handling, including improved reconnection logic and cleanup procedures +- *(application-deployment)* Separate handling of FAILED and CANCELLED_BY_USER statuses for clearer logic and notification +- *(jobs)* Update middleware to include job-specific identifiers for WithoutOverlapping +- *(jobs)* Modify middleware to use job-specific identifier for WithoutOverlapping +- *(environment-variables)* Remove debug logging from bulk submit handling for cleaner code +- *(environment-variables)* Simplify application build pack check in environment variable handling +- *(logs)* Adjust padding in logs view for improved layout consistency +- *(application-deployment)* Streamline post-deployment process by always dispatching container status check +- *(service-management)* Enhance container stopping logic by implementing parallel processing and removing deprecated methods +- *(activity-monitor)* Change activity property visibility and update view references for consistency +- *(activity-monitor)* Enhance layout responsiveness by adjusting class bindings and structure for better display +- *(service-management)* Update stopContainersInParallel method to enforce Server type hint for improved type safety +- *(service-management)* Rearrange docker cleanup logic in StopService to improve readability +- *(database-management)* Simplify docker cleanup logic in StopDatabase to enhance readability +- *(activity-monitor)* Consolidate activity monitoring logic and remove deprecated NewActivityMonitor component +- *(activity-monitor)* Update dispatch method to use activityMonitor instead of deprecated newActivityMonitor +- *(push-server-update)* Enhance application preview handling by incorporating pull request IDs and adding status update protections +- *(docker-compose)* Replace hardcoded Docker Compose configuration with external YAML template for improved database detection testing +- *(test-database-detection)* Rename services for clarity, add new database configurations, and update application service dependencies +- *(database-detection)* Enhance isDatabaseImage function to utilize service configuration for improved detection accuracy +- *(install-scripts)* Update Docker installation process to include manual installation fallback and improve error handling +- *(logs-view)* Update logs display for service containers with improved headings and dynamic key binding +- *(logs)* Enhance container loading logic and improve UI for logs display across various resource types +- *(cloudflare-tunnel)* Enhance layout and structure of Cloudflare Tunnel documentation and confirmation modal +- *(terminal-connection)* Streamline auto-connection logic and improve component readiness checks +- *(logs)* Remove unused methods and debug functionality from Logs.php for cleaner code +- *(remoteProcess)* Update sanitize_utf8_text function to accept nullable string parameter for improved type safety +- *(events)* Remove ProxyStarted event and associated ProxyStartedNotification listener for code cleanup +- *(navbar)* Remove unnecessary parameters from server navbar component for cleaner implementation +- *(proxy)* Remove commented-out listener and method for cleaner code structure +- *(events)* Update ProxyStatusChangedUI constructor to accept nullable teamId for improved flexibility +- *(cloudflare)* Update server retrieval method for improved query efficiency +- *(navbar)* Remove unused PHP use statement for cleaner code +- *(proxy)* Streamline proxy status handling and improve dashboard availability checks +- *(navbar)* Simplify proxy status handling and enhance loading indicators for better user experience +- *(resource-operations)* Filter out build servers from the server list and clean up commented-out code in the resource operations view +- *(execute-container-command)* Simplify connection logic and improve terminal availability checks +- *(navigation)* Remove wire:navigate directive from configuration links for cleaner HTML structure +- *(proxy)* Update StartProxy calls to use named parameter for async option +- *(clone-project)* Enhance server retrieval by including destinations and filtering out build servers +- *(ui)* Terminal +- *(ui)* Remove terminal header from execute-container-command view +- *(ui)* Remove unnecessary padding from deployment, backup, and logs sections + +### 📚 Documentation + +- Update changelog +- *(service)* Add new docs link for zipline (#5912) +- Update changelog +- Update changelog +- Update changelog + +### 🎨 Styling + +- *(css)* Update padding utility for password input and add newline in app.css +- *(css)* Refine badge utility styles in utilities.css +- *(css)* Enhance badge utility styles in utilities.css + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.419 and nightly version to 4.0.0-beta.420 in configuration files +- *(service)* Rename hoarder server to karakeep (#5607) +- *(service)* Update Supabase services (#5708) +- *(service)* Remove unused documenso env +- *(service)* Formatting and cleanup of ryot +- *(docs)* Remove changelog and add it to gitignore +- *(versions)* Update version to 4.0.0-beta.419 +- *(service)* Diun formatting +- *(docs)* Update CHANGELOG.md +- *(service)* Switch convex vars +- *(service)* Pgbackweb formatting and naming update +- *(service)* Remove typesense default API key +- *(service)* Format yamtrack healthcheck +- *(core)* Remove unused function +- *(ui)* Remove unused stopEvent code +- *(service)* Remove unused env +- *(tests)* Update test environment database name and add new feature test for converting container environment variables to array +- *(service)* Update Immich service (#5886) +- *(service)* Remove unused logo +- *(api)* Update API docs +- *(dependencies)* Update package versions in composer.json and composer.lock for improved compatibility and performance +- *(dependencies)* Update package versions in package.json and package-lock.json for improved stability and features +- *(version)* Update coolify-realtime to version 1.0.9 in docker-compose and versions files +- *(version)* Update coolify version to 4.0.0-beta.420 and nightly version to 4.0.0-beta.421 +- *(service)* Changedetection remove unused code + +## [4.0.0-beta.417] - 2025-05-07 + +### 🐛 Bug Fixes + +- *(select)* Update fallback logo path to use absolute URL for improved reliability + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.418 + +## [4.0.0-beta.416] - 2025-05-05 + +### 🚀 Features + +- *(migration)* Add 'is_migrated' and 'custom_type' columns to service_applications and service_databases tables +- *(backup)* Implement custom database type selection and enhance scheduled backups management +- *(README)* Add Gozunga and Macarne to sponsors list +- *(redis)* Add scheduled cleanup command for Redis keys and enhance cleanup logic + +### 🐛 Bug Fixes + +- *(service)* Graceful shutdown of old container (#5731) +- *(ServerCheck)* Enhance proxy container check to ensure it is running before proceeding +- *(applications)* Include pull_request_id in deployment queue check to prevent duplicate deployments +- *(database)* Update label for image input field to improve clarity +- *(ServerCheck)* Set default proxy status to 'exited' to handle missing container state +- *(database)* Reduce container stop timeout from 300 to 30 seconds for improved responsiveness +- *(ui)* System theming for charts (#5740) +- *(dev)* Mount points?! +- *(dev)* Proxy mount point +- *(ui)* Allow adding scheduled backups for non-migrated databases +- *(DatabaseBackupJob)* Escape PostgreSQL password in backup command (#5759) +- *(ui)* Correct closing div tag in service index view + +### 🚜 Refactor + +- *(Database)* Streamline container shutdown process and reduce timeout duration +- *(core)* Streamline container stopping process and reduce timeout duration; update related methods for consistency +- *(database)* Update DB facade usage for consistency across service files +- *(database)* Enhance application conversion logic and add existence checks for databases and applications +- *(actions)* Standardize method naming for network and configuration deletion across application and service classes +- *(logdrain)* Consolidate log drain stopping logic to reduce redundancy +- *(StandaloneMariadb)* Add type hint for destination method to improve code clarity +- *(DeleteResourceJob)* Streamline resource deletion logic and improve conditional checks for database types +- *(jobs)* Update middleware to prevent job release after expiration for CleanupInstanceStuffsJob, RestartProxyJob, and ServerCheckJob +- *(jobs)* Unify middleware configuration to prevent job release after expiration for DockerCleanupJob and PushServerUpdateJob + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(seeder)* Update git branch from 'main' to 'v4.x' for multiple examples in ApplicationSeeder +- *(versions)* Update coolify version to 4.0.0-beta.417 and nightly version to 4.0.0-beta.418 + +## [4.0.0-beta.415] - 2025-04-29 + +### 🐛 Bug Fixes + +- *(ui)* Remove required attribute from image input in service application view +- *(ui)* Change application image validation to be nullable in service application view +- *(Server)* Correct proxy path formatting for Traefik proxy type + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.416 and nightly version to 4.0.0-beta.417 in configuration files; fix links in deployment view + +## [4.0.0-beta.414] - 2025-04-28 + +### 🐛 Bug Fixes + +- *(ui)* Disable livewire navigate feature (causing spam of setInterval()) + +## [4.0.0-beta.413] - 2025-04-28 + +### 💼 Other + +- Adjust Workflows for v5 (#5689) + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(workflows)* Adjust workflow for announcement + +## [4.0.0-beta.411] - 2025-04-23 + +### 🚀 Features + +- *(deployment)* Add repository_project_id handling for private GitHub apps and clean up unused Caddy label logic +- *(api)* Enhance OpenAPI specifications with token variable and additional key attributes +- *(docker)* Add HTTP Basic Authentication support and enhance hostname parsing in Docker run conversion +- *(api)* Add HTTP Basic Authentication fields to OpenAPI specifications and enhance PrivateKey model descriptions +- *(README)* Add InterviewPal sponsorship link and corresponding SVG icon + +### 🐛 Bug Fixes + +- *(backup-edit)* Conditionally enable S3 checkbox based on available validated S3 storage +- *(source)* Update no sources found message for clarity +- *(api)* Correct middleware for service update route to ensure proper permissions +- *(api)* Handle JSON response in service creation and update methods for improved error handling +- Add 201 json code to servers validate api response +- *(docker)* Ensure password hashing only occurs when HTTP Basic Authentication is enabled +- *(docker)* Enhance hostname and GPU option validation in Docker run to compose conversion +- *(terminal)* Enhance WebSocket client verification with authorized IPs in terminal server +- *(ApplicationDeploymentJob)* Ensure source is an object before checking GitHub app properties + +### 🚜 Refactor + +- *(jobs)* Comment out unused Caddy label handling in ApplicationDeploymentJob and simplify proxy path logic in Server model +- *(database)* Simplify database type checks in ServiceDatabase and enhance image validation in Docker helper +- *(shared)* Remove unused ray debugging statement from newParser function +- *(applications)* Remove redundant error response in create_env method +- *(api)* Restructure routes to include versioning and maintain existing feedback endpoint +- *(api)* Remove token variable from OpenAPI specifications for clarity +- *(environment-variables)* Remove protected variable checks from delete methods for cleaner logic +- *(http-basic-auth)* Rename 'http_basic_auth_enable' to 'http_basic_auth_enabled' across application files for consistency +- *(docker)* Remove debug statement and enhance hostname handling in Docker run conversion +- *(server)* Simplify proxy path logic and remove unnecessary conditions + +### 📚 Documentation + +- Update changelog +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.411 and nightly version to 4.0.0-beta.412 in configuration files +- *(versions)* Update coolify version to 4.0.0-beta.412 and nightly version to 4.0.0-beta.413 in configuration files +- *(versions)* Update coolify version to 4.0.0-beta.413 and nightly version to 4.0.0-beta.414 in configuration files +- *(versions)* Update realtime version to 1.0.8 in versions.json +- *(versions)* Update realtime version to 1.0.8 in versions.json +- *(docker)* Update soketi image version to 1.0.8 in production configuration files +- *(versions)* Update coolify version to 4.0.0-beta.414 and nightly version to 4.0.0-beta.415 in configuration files + +## [4.0.0-beta.410] - 2025-04-18 + +### 🚀 Features + +- Add HTTP Basic Authentication +- *(readme)* Add new sponsors Supadata AI and WZ-IT to the README +- *(core)* Enable magic env variables for compose based applications + +### 🐛 Bug Fixes + +- *(application)* Append base directory to git branch URLs for improved path handling +- *(templates)* Correct casing of "denokv" to "denoKV" in service templates JSON +- *(navbar)* Update error message link to use route for environment variables navigation +- Unsend template +- Replace ports with expose +- *(templates)* Update Unsend compose configuration for improved service integration + +### 🚜 Refactor + +- *(jobs)* Update WithoutOverlapping middleware to use expireAfter for better queue management + +### 📚 Documentation + +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Bump coolify version to 4.0.0-beta.410 and update nightly version to 4.0.0-beta.411 in configuration files +- *(templates)* Update plausible and clickhouse images to latest versions and remove mail service + +## [4.0.0-beta.409] - 2025-04-16 + +### 🐛 Bug Fixes + +- *(parser)* Transform associative array labels into key=value format for better compatibility +- *(redis)* Update username and password input handling to clarify database sync requirements +- *(source)* Update connected source display to handle cases with no source connected + +### 🚜 Refactor + +- *(source)* Conditionally display connected source and change source options based on private key presence + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Bump coolify version to 4.0.0-beta.409 in configuration files + +## [4.0.0-beta.408] - 2025-04-14 + +### 🚀 Features + +- *(OpenApi)* Enhance OpenAPI specifications by adding UUID parameters for application, project, and service updates; improve deployment listing with pagination parameters; update command signature for OpenApi generation +- *(subscription)* Enhance subscription management with loading states and Stripe status checks + +### 🐛 Bug Fixes + +- *(pre-commit)* Correct input redirection for /dev/tty and add OpenAPI generation command +- *(pricing-plans)* Adjust grid class for improved layout consistency in subscription pricing plans +- *(migrations)* Make stripe_comment field nullable in subscriptions table +- *(mongodb)* Also apply custom config when SSL is enabled +- *(templates)* Correct casing of denoKV references in service templates and YAML files +- *(deployment)* Handle missing destination in deployment process to prevent errors + +### 💼 Other + +- Add missing openapi items to PrivateKey + +### 🚜 Refactor + +- *(commands)* Reorganize OpenAPI and Services generation commands into a new namespace for better structure; remove old command files +- *(Dockerfile)* Remove service generation command from the build process to streamline Dockerfile and improve build efficiency +- *(navbar-delete-team)* Simplify modal confirmation layout and enhance button styling for better user experience +- *(Server)* Remove debug logging from isReachableChanged method to clean up code and improve performance + +### 📚 Documentation + +- Update changelog +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update nightly version to 4.0.0-beta.410 +- *(pre-commit)* Remove OpenAPI generation command from pre-commit hook +- *(versions)* Update realtime version to 1.0.7 and bump dependencies in package.json + +## [4.0.0-beta.407] - 2025-04-09 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.406] - 2025-04-05 + +### 🚀 Features + +- *(Deploy)* Add info dispatch for proxy check initiation +- *(EnvironmentVariable)* Add handling for Redis credentials in the environment variable component +- *(EnvironmentVariable)* Implement protection for critical environment variables and enhance deletion logic +- *(Application)* Add networkAliases attribute for handling network aliases as JSON or comma-separated values +- *(GithubApp)* Update default events to include 'pull_request' and streamline event handling +- *(CleanupDocker)* Add support for realtime image management in Docker cleanup process +- *(Deployment)* Enhance queue_application_deployment to handle existing deployments and return appropriate status messages +- *(SourceManagement)* Add functionality to change Git source and display current source in the application settings + +### 🐛 Bug Fixes + +- *(CheckProxy)* Update port conflict check to ensure accurate grep matching +- *(CheckProxy)* Refine port conflict detection with improved grep patterns +- *(CheckProxy)* Enhance port conflict detection by adjusting ss command for better output +- *(api)* Add back validateDataApplications (#5539) +- *(CheckProxy, Status)* Prevent proxy checks when force_stop is active; remove debug statement in General +- *(Status)* Conditionally check proxy status and refresh button based on force_stop state +- *(General)* Change redis_password property to nullable string +- *(DeployController)* Update request handling to use input method and enhance OpenAPI description for deployment endpoint + +### 💼 Other + +- Add missing UUID to openapi spec + +### 🚜 Refactor + +- *(Server)* Use data_get for safer access to settings properties in isFunctional method +- *(Application)* Rename network_aliases to custom_network_aliases across the application for clarity and consistency +- *(ApplicationDeploymentJob)* Streamline environment variable handling by introducing generate_coolify_env_variables method and consolidating logic for pull request and main branch scenarios +- *(ApplicationDeploymentJob, ApplicationDeploymentQueue)* Improve deployment status handling and log entry management with transaction support +- *(SourceManagement)* Sort sources by name and improve UI for changing Git source with better error handling +- *(Email)* Streamline SMTP and resend settings handling in copyFromInstanceSettings method +- *(Email)* Enhance error handling in SMTP and resend methods by passing context to handleError function +- *(DynamicConfigurations)* Improve handling of dynamic configuration content by ensuring fallback to empty string when content is null +- *(ServicesGenerate)* Update command signature from 'services:generate' to 'generate:services' for consistency; update Dockerfile to run service generation during build; update Odoo image version to 18 and add extra addons volume in compose configuration +- *(Dockerfile)* Streamline RUN commands for improved readability and maintainability by adding line continuations +- *(Dockerfile)* Reintroduce service generation command in the build process for consistency and ensure proper asset compilation + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Bump version to 406 +- *(versions)* Bump version to 407 and 408 for coolify and nightly +- *(versions)* Bump version to 408 for coolify and 409 for nightly + +## [4.0.0-beta.405] - 2025-04-04 + +### 🚀 Features + +- *(api)* Update OpenAPI spec for services (#5448) +- *(proxy)* Enhance proxy handling and port conflict detection + +### 🐛 Bug Fixes + +- *(api)* Used ssh keys can be deleted +- *(email)* Transactional emails not sending + +### 🚜 Refactor + +- *(CheckProxy)* Replace 'which' with 'command -v' for command availability checks + +### 📚 Documentation + +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Bump version to 406 +- *(versions)* Bump version to 407 + +## [4.0.0-beta.404] - 2025-04-03 + +### 🚀 Features + +- *(lang)* Added Azerbaijani language updated turkish language. (#5497) +- *(lang)* Added Portuguese from Brazil language (#5500) +- *(lang)* Add Indonesian language translations (#5513) + +### 🐛 Bug Fixes + +- *(docs)* Comment out execute for now +- *(installation)* Mount the docker config +- *(installation)* Path to config file for docker login +- *(service)* Add health check to Bugsink service (#5512) +- *(email)* Emails are not sent in multiple cases +- *(deployments)* Use graceful shutdown instead of `rm` +- *(docs)* Contribute service url (#5517) +- *(proxy)* Proxy restart does not work on domain +- *(ui)* Only show copy button on https +- *(database)* Custom config for MongoDB (#5471) + +### 📚 Documentation + +- Update changelog +- Update changelog +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(service)* Remove unused code in Bugsink service +- *(versions)* Update version to 404 +- *(versions)* Bump version to 403 (#5520) +- *(versions)* Bump version to 404 + +## [4.0.0-beta.402] - 2025-04-01 + +### 🚀 Features + +- *(deployments)* Add list application deployments api route +- *(deploy)* Add pull request ID parameter to deploy endpoint +- *(api)* Add pull request ID parameter to applications endpoint +- *(api)* Add endpoints for retrieving application logs and deployments +- *(lang)* Added Norwegian language (#5280) +- *(dep)* Bump all dependencies + +### 🐛 Bug Fixes + +- Only get apps for the current team +- *(DeployController)* Cast 'pr' query parameter to integer +- *(deploy)* Validate team ID before deployment +- *(wakapi)* Typo in env variables and add some useful variables to wakapi.yaml (#5424) +- *(ui)* Instance Backup settings + +### 🚜 Refactor + +- *(dev)* Remove OpenAPI generation functionality +- *(migration)* Enhance local file volumes migration with logging + +### ⚙️ Miscellaneous Tasks + +- *(service)* Update minecraft service ENVs +- *(service)* Add more vars to infisical.yaml (#5418) +- *(service)* Add google variables to plausible.yaml (#5429) +- *(service)* Update authentik.yaml versions (#5373) +- *(core)* Remove redocs +- *(versions)* Update coolify version numbers to 4.0.0-beta.403 and 4.0.0-beta.404 + +## [4.0.0-beta.401] - 2025-03-28 + +### 📚 Documentation + +- Update changelog +- Update changelog + +## [4.0.0-beta.400] - 2025-03-27 + +### 🚀 Features + +- *(database)* Disable MongoDB SSL by default in migration +- *(database)* Add CA certificate generation for database servers +- *(application)* Add SPA configuration and update Nginx generation logic + +### 🐛 Bug Fixes + +- *(file-storage)* Double save on compose volumes +- *(parser)* Add logging support for applications in services + +### 🚜 Refactor + +- *(proxy)* Improve port availability checks with multiple methods +- *(database)* Update MongoDB SSL configuration for improved security +- *(database)* Enhance SSL configuration handling for various databases +- *(notifications)* Update Telegram button URL for staging environment +- *(models)* Remove unnecessary cloud check in isEnabled method +- *(database)* Streamline event listeners in Redis General component +- *(database)* Remove redundant database status display in MongoDB view +- *(database)* Update import statements for Auth in database components +- *(database)* Require PEM key file for SSL certificate regeneration +- *(database)* Change MySQL daemon command to MariaDB daemon +- *(nightly)* Update version numbers and enhance upgrade script +- *(versions)* Update version numbers for coolify and nightly +- *(email)* Validate team membership for email recipients +- *(shared)* Simplify deployment status check logic +- *(shared)* Add logging for running deployment jobs +- *(shared)* Enhance job status check to include 'reserved' +- *(email)* Improve error handling by passing context to handleError +- *(email)* Streamline email sending logic and improve configuration handling +- *(email)* Remove unnecessary whitespace in email sending logic +- *(email)* Allow custom email recipients in email sending logic +- *(email)* Enhance sender information formatting in email logic +- *(proxy)* Remove redundant stop call in restart method +- *(file-storage)* Add loadStorageOnServer method for improved error handling +- *(docker)* Parse and sanitize YAML compose file before encoding +- *(file-storage)* Improve layout and structure of input fields +- *(email)* Update label for test email recipient input +- *(database-backup)* Remove existing Docker container before backup upload +- *(database)* Improve decryption and deduplication of local file volumes +- *(database)* Remove debug output from volume update process + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update version numbers for coolify and nightly + +### ◀️ Revert + +- Encrypting mount and fs_path + +## [4.0.0-beta.399] - 2025-03-25 + +### 🚀 Features + +- *(service)* Neon +- *(migration)* Add `ssl_certificates` table and model +- *(migration)* Add ssl setting to `standalone_postgresqls` table +- *(ui)* Add ssl settings to Postgres ui +- *(db)* Add ssl mode to Postgres URLs +- *(db)* Setup ssl during Postgres start +- *(migration)* Encrypt local file volumes content and paths +- *(ssl)* Ssl generation helper +- *(ssl)* Migrate to `ECC`certificates using `secp521r1` +- *(ssl)* Improve SSL helper +- *(ssl)* Add a Coolify CA Certificate to all servers +- *(seeder)* Call CA SSL seeder in prod and dev +- *(ssl)* Add Coolify CA Certificate when adding a new server +- *(installer)* Create CA folder during installation +- *(ssl)* Improve SSL helper +- *(ssl)* Use new improved helper for SSL generation +- *(ui)* Add CA cert UI +- *(ui)* New copy button component +- *(ui)* Use new copy button component everywhere +- *(ui)* Improve server advanced view +- *(migration)* Add CN and alternative names to DB +- *(databases)* Add CA SSL crt location to Postgres URLs +- *(ssl)* Improve ssl generation +- *(ssl)* Regenerate SSL certs job +- *(ssl)* Regenerate certificate and valid until UI +- *(ssl)* Regenerate CA cert and all other certs logic +- *(ssl)* Add full MySQL SSL Support +- *(ssl)* Add full MariaDB SSL support +- *(ssl)* Add `openssl.conf` to configure SSL extension properly +- *(ssl)* Improve SSL generation and security a lot +- *(ssl)* Check for SSL renewal twice daily +- *(ssl)* Add SSL relationships to all DBs +- Add full SSL support to MongoDB +- *(ssl)* Fix some issues and improve ssl generation helper +- *(ssl)* Ability to create `.pem` certs and add `clientAuth` to `extendedKeyUsage` +- *(ssl)* New modes for MongoDB and get `caCert` and `mountPath` correctly +- *(ssl)* Full SSL support for Redis +- New mode implementation for MongoDB +- *(ssl)* Improve Redis and remove modes +- Full SSL support for DrangonflyDB +- SSL notification +- *(github-source)* Enhance GitHub App configuration with manual and private key support +- *(ui)* Improve GitHub repository selection and styling +- *(database)* Implement two-step confirmation for database deletion +- *(assets)* Add new SVG logo for Coolify +- *(install)* Enhance Docker address pool configuration and validation +- *(install)* Improve Docker address pool management and service restart logic +- *(install)* Add missing env variable to install script +- *(LocalFileVolume)* Add binary file detection and update UI logic +- *(templates)* Change glance for v0.7 +- *(templates)* Add Freescout service template +- *(service)* Add Evolution API template +- *(service)* Add evolution-api and neon-ws-proxy templates +- *(svg)* Add coolify and evolution-api SVG logos +- *(api)* Add api to create custom services +- *(api)* Separate create and one-click routes +- *(api)* Update Services api routes and handlers +- *(api)* Unify service creation endpoint and enhance validation +- *(notifications)* Add discord ping functionality and settings +- *(user)* Implement session deletion on password reset +- *(github)* Enhance repository loading and validation in applications + +### 🐛 Bug Fixes + +- *(api)* Docker compose based apps creationg through api +- *(database)* Improve database type detection for Supabase Postgres images +- *(ssl)* Permission of ssl crt and key inside the container +- *(ui)* Make sure file mounts do not showing the encrypted values +- *(ssl)* Make default ssl mode require not verify-full as it does not need a ca cert +- *(ui)* Select component should not always uses title case +- *(db)* SSL certificates table and model +- *(migration)* Ssl certificates table +- *(databases)* Fix database name users new `uuid` instead of DB one +- *(database)* Fix volume and file mounts and naming +- *(migration)* Store subjectAlternativeNames as a json array in the db +- *(ssl)* Make sure the subjectAlternativeNames are unique and stored correctly +- *(ui)* Certificate expiration data is null before starting the DB +- *(deletion)* Fix DB deletion +- *(ssl)* Improve SSL cert file mounts +- *(ssl)* Always create ca crt on disk even if it is already there +- *(ssl)* Use mountPath parameter not a hardcoded path +- *(ssl)* Use 1 instead of on for mysql +- *(ssl)* Do not remove SSL directory +- *(ssl)* Wrong ssl cert is loaded to the server and UI error when regenerating SSL +- *(ssl)* Make sure when regenerating the CA cert it is not overwritten with a server cert +- *(ssl)* Regenerating certs for a specific DB +- *(ssl)* Fix MariaDB and MySQL need CA cert +- *(ssl)* Add mount path to DB to fix regeneration of certs +- *(ssl)* Fix SSL regeneration to sign with CA cert and use mount path +- *(ssl)* Get caCert correctly +- *(ssl)* Remove caCert even if it is a folder by accident +- *(ssl)* Ger caCert and `mountPath` correctly +- *(ui)* Only show Regenerate SSL Certificates button when there is a cert +- *(ssl)* Server id +- *(ssl)* When regenerating SSL certs the cert is not singed with the new CN +- *(ssl)* Adjust ca paths for MySQL +- *(ssl)* Remove mode selection for MariaDB as it is not supported +- *(ssl)* Permission issue with MariDB cert and key and paths +- *(ssl)* Rename Redis mode to verify-ca as it is not verify-full +- *(ui)* Remove unused mode for MongoDB +- *(ssl)* KeyDB port and caCert args are missing +- *(ui)* Enable SSL is not working correctly for KeyDB +- *(ssl)* Add `--tls` arg to DrangflyDB +- *(notification)* Always send SSL notifications +- *(database)* Change default value of enable_ssl to false for multiple tables +- *(ui)* Correct grammatical error in 404 page +- *(seeder)* Update GitHub app name in GithubAppSeeder +- *(plane)* Update APP_RELEASE to v0.25.2 in environment configuration +- *(domain)* Dispatch refreshStatus event after successful domain update +- *(database)* Correct container name generation for service databases +- *(database)* Limit container name length for database proxy +- *(database)* Handle unsupported database types in StartDatabaseProxy +- *(database)* Simplify container name generation in StartDatabaseProxy +- *(install)* Handle potential errors in Docker address pool configuration +- *(backups)* Retention settings +- *(redis)* Set default redis_username for new instances +- *(core)* Improve instantSave logic and error handling +- *(general)* Correct link to framework specific documentation +- *(core)* Redirect healthcheck route for dockercompose applications +- *(api)* Use name from request payload +- *(issue#4746)* Do not use setGitImportSettings inside of generateGitLsRemoteCommands +- Correct some spellings +- *(service)* Replace deprecated credentials env variables on keycloak service +- *(keycloak)* Update keycloak image version to 26.1 +- *(console)* Handle missing root user in password reset command +- *(ssl)* Handle missing CA certificate in SSL regeneration job +- *(copy-button)* Ensure text is safely passed to clipboard + +### 💼 Other + +- Bump Coolify to 4.0.0-beta.400 +- *(migration)* Add SSL fields to database tables +- SSL Support for KeyDB + +### 🚜 Refactor + +- *(ui)* Unhide log toggle in application settings +- *(nginx)* Streamline default Nginx configuration and improve error handling +- *(install)* Clean up install script and enhance Docker installation logic +- *(ScheduledTask)* Clean up code formatting and remove unused import +- *(app)* Remove unused MagicBar component and related code +- *(database)* Streamline SSL configuration handling across database types +- *(application)* Streamline healthcheck parsing from Dockerfile +- *(notifications)* Standardize getRecipients method signatures +- *(configuration)* Centralize configuration management in ConfigurationRepository +- *(docker)* Update image references to use centralized registry URL +- *(env)* Add centralized registry URL to environment configuration +- *(storage)* Simplify file storage iteration in Blade template +- *(models)* Add is_directory attribute to LocalFileVolume model +- *(modal)* Add ignoreWire attribute to modal-confirmation component +- *(invite-link)* Adjust layout for better responsiveness in form +- *(invite-link)* Enhance form layout for improved responsiveness +- *(network)* Enhance docker network creation with ipv6 fallback +- *(network)* Check for existing coolify network before creation +- *(database)* Enhance encryption process for local file volumes + +### 📚 Documentation + +- Update changelog +- Update changelog +- *(CONTRIBUTING)* Add note about Laravel Horizon accessibility +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(migration)* Remove unused columns +- *(ssl)* Improve code in ssl helper +- *(migration)* Ssl cert and key should not be nullable +- *(ssl)* Rename CA cert to `coolify-ca.crt` because of conflicts +- Rename ca crt folder to ssl +- *(ui)* Improve valid until handling +- Improve code quality suggested by code rabbit +- *(supabase)* Update Supabase service template and Postgres image version +- *(versions)* Update version numbers for coolify and nightly + +## [4.0.0-beta.398] - 2025-03-01 + +### 🚀 Features + +- *(billing)* Add Stripe past due subscription status tracking +- *(ui)* Add past due subscription warning banner + +### 🐛 Bug Fixes + +- *(billing)* Restrict Stripe subscription status update to 'active' only + +### 💼 Other + +- Bump Coolify to 4.0.0-beta.398 + +### 🚜 Refactor + +- *(billing)* Enhance Stripe subscription status handling and notifications + +## [4.0.0-beta.397] - 2025-02-28 + +### 🐛 Bug Fixes + +- *(billing)* Handle 'past_due' subscription status in Stripe processing +- *(revert)* Label parsing +- *(helpers)* Initialize command variable in parseCommandFromMagicEnvVariable + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.396] - 2025-02-28 + +### 🚀 Features + +- *(ui)* Add wire:key to two-step confirmation settings +- *(database)* Add index to scheduled task executions for improved query performance +- *(database)* Add index to scheduled database backup executions + +### 🐛 Bug Fixes + +- *(core)* Production dockerfile +- *(ui)* Update storage configuration guidance link +- *(ui)* Set default SMTP encryption to starttls +- *(notifications)* Correct environment URL path in application notifications +- *(config)* Update default PostgreSQL host to coolify-db instead of postgres +- *(docker)* Improve Docker compose file validation process +- *(ui)* Restrict service retrieval to current team +- *(core)* Only validate custom compose files +- *(mail)* Set default mailer to array when not specified +- *(ui)* Correct redirect routes after task deletion +- *(core)* Adding a new server should not try to make the default docker network +- *(core)* Clean up unnecessary files during application image build +- *(core)* Improve label generation and merging for applications and services + +### 💼 Other + +- Bump all dependencies (#5216) + +### 🚜 Refactor + +- *(ui)* Simplify file storage modal confirmations +- *(notifications)* Improve transactional email settings handling +- *(scheduled-tasks)* Improve scheduled task creation and management + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Bump helper and realtime version + +## [4.0.0-beta.395] - 2025-02-22 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.394] - 2025-02-17 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.393] - 2025-02-15 + +### 📚 Documentation + +- Update changelog + +## [4.0.0-beta.392] - 2025-02-13 + +### 🚀 Features + +- *(ui)* Add top padding to pricing plans view +- *(core)* Add error logging and cron parsing to docker/server schedules +- *(core)* Prevent using servers with existing resources as build servers +- *(ui)* Add textarea switching option in service compose editor + +### 🐛 Bug Fixes + +- Pull latest image from registry when using build server +- *(deployment)* Improve server selection for deployment cancellation +- *(deployment)* Improve log line rendering and formatting +- *(s3-storage)* Optimize team admin notification query +- *(core)* Improve connection testing with dynamic disk configuration for s3 backups +- *(core)* Update service status refresh event handling +- *(ui)* Adjust polling intervals for database and service status checks +- *(service)* Update Fider service template healthcheck command +- *(core)* Improve server selection error handling in Docker component +- *(core)* Add server functionality check before dispatching container status +- *(ui)* Disable sticky scroll in Monaco editor +- *(ui)* Add literal and multiline env support to services. +- *(services)* Owncloud docs link +- *(template)* Remove db-migration step from `infisical.yaml` (#5209) +- *(service)* Penpot (#5047) + +### 🚜 Refactor + +- Use pull flag on docker compose up + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- Rollback Coolify version to 4.0.0-beta.392 +- Bump Coolify version to 4.0.0-beta.393 +- Bump Coolify version to 4.0.0-beta.394 +- Bump Coolify version to 4.0.0-beta.395 +- Bump Coolify version to 4.0.0-beta.396 +- *(services)* Update zipline to use new Database env var. (#5210) +- *(service)* Upgrade authentik service +- *(service)* Remove unused env from zipline + +## [4.0.0-beta.391] - 2025-02-04 + +### 🚀 Features + +- Add application api route +- Container logs +- Remove ansi color from log +- Add lines query parameter +- *(changelog)* Add git cliff for automatic changelog generation +- *(workflows)* Improve changelog generation and workflows +- *(ui)* Add periodic status checking for services +- *(deployment)* Ensure private key is stored in filesystem before deployment +- *(slack)* Show message title in notification previews (#5063) +- *(i18n)* Add Arabic translations (#4991) +- *(i18n)* Add French translations (#4992) +- *(services)* Update `service-templates.json` + +### 🐛 Bug Fixes + +- *(core)* Improve deployment failure Slack notification formatting +- *(core)* Update Slack notification formatting to use bold correctly +- *(core)* Enhance Slack deployment success notification formatting +- *(ui)* Simplify service templates loading logic +- *(ui)* Align title and add button vertically in various views +- Handle pullrequest:updated for reliable preview deployments +- *(ui)* Fix typo on team page (#5105) +- Cal.com documentation link give 404 (#5070) +- *(slack)* Notification settings URL in `HighDiskUsage` message (#5071) +- *(ui)* Correct typo in Storage delete dialog (#5061) +- *(lang)* Add missing italian translations (#5057) +- *(service)* Improve duplicati.yaml (#4971) +- *(service)* Links in homepage service (#5002) +- *(service)* Added SMTP credentials to getoutline yaml template file (#5011) +- *(service)* Added `KEY` Variable to Beszel Template (#5021) +- *(cloudflare-tunnels)* Dead links to docs (#5104) +- System-wide GitHub apps (#5114) + +### 🚜 Refactor + +- Simplify service start and restart workflows + +### 📚 Documentation + +- *(services)* Reword nitropage url and slogan +- *(readme)* Add Convex to special sponsors section +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(config)* Increase default PHP memory limit to 256M +- Add openapi response +- *(workflows)* Make naming more clear and remove unused code +- Bump Coolify version to 4.0.0-beta.392/393 +- *(ci)* Update changelog generation workflow to target 'next' branch +- *(ci)* Update changelog generation workflow to target main branch + +## [4.0.0-beta.390] - 2025-01-28 + +### 🚀 Features + +- *(template)* Add Open Web UI +- *(templates)* Add Open Web UI service template +- *(ui)* Update GitHub source creation advanced section label +- *(core)* Add dynamic label reset for application settings +- *(ui)* Conditionally enable advanced application settings based on label readonly status +- *(env)* Added COOLIFY_RESOURCE_UUID environment variable +- *(vite)* Add Cloudflare async script and style tag attributes +- *(meta)* Add comprehensive SEO and social media meta tags +- *(core)* Add name to default proxy configuration + +### 🐛 Bug Fixes + +- *(ui)* Update database control UI to check server functionality before displaying actions +- *(ui)* Typo in upgrade message +- *(ui)* Cloudflare tunnel configuration should be an info, not a warning +- *(s3)* DigitalOcean storage buckets do not work +- *(ui)* Correct typo in container label helper text +- Disable certain parts if readonly label is turned off +- Cleanup old scheduled_task_executions +- Validate cron expression in Scheduled Task update +- *(core)* Check cron expression on save +- *(database)* Detect more postgres database image types +- *(templates)* Update service templates +- Remove quotes in COOLIFY_CONTAINER_NAME +- *(templates)* Update Trigger.dev service templates with v3 configuration +- *(database)* Adjust MongoDB restore command and import view styling +- *(core)* Improve public repository URL parsing for branch and base directory +- *(core)* Increase HTTP/2 max concurrent streams to 250 (default) +- *(ui)* Update docker compose file helper text to clarify repository modification +- *(ui)* Skip SERVICE_FQDN and SERVICE_URL variables during update +- *(core)* Stopping database is not disabling db proxy +- *(core)* Remove --remove-orphans flag from proxy startup command to prevent other proxy deletions (db) +- *(api)* Domain check when updating domain +- *(ui)* Always redirect to dashboard after team switch +- *(backup)* Escape special characters in database backup commands + +### 💼 Other + +- Trigger.dev templates - wrong key length issue +- Trigger.dev template - missing ports and wrong env usage +- Trigger.dev template - fixed otel config +- Trigger.dev template - fixed otel config +- Trigger.dev template - fixed port config + +### 🚜 Refactor + +- *(s3)* Improve S3 bucket endpoint formatting +- *(vite)* Improve environment variable handling in Vite configuration +- *(ui)* Simplify GitHub App registration UI and layout + +### ⚙️ Miscellaneous Tasks + +- *(version)* Bump Coolify version to 4.0.0-beta.391 + +### ◀️ Revert + +- Remove Cloudflare async tag attributes + +## [4.0.0-beta.389] - 2025-01-23 + +### 🚀 Features + +- *(docs)* Update tech stack +- *(terminal)* Show terminal unavailable if the container does not have a shell on the global terminal UI +- *(ui)* Improve deployment UI + +### 🐛 Bug Fixes + +- *(service)* Infinite loading and lag with invoiceninja service (#4876) +- *(service)* Invoiceninja service +- *(workflows)* `Waiting for changes` label should also be considered and improved messages +- *(workflows)* Remove tags only if the PR has been merged into the main branch +- *(terminal)* Terminal shows that it is not available, even though it is +- *(labels)* Docker labels do not generated correctly +- *(helper)* Downgrade Nixpacks to v1.29.0 +- *(labels)* Generate labels when they are empty not when they are already generated +- *(storage)* Hetzner storage buckets not working + +### 📚 Documentation + +- Add TECH_STACK.md (#4883) + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify versions to v4.0.0-beta.389 +- *(core)* EnvironmentVariable Model now extends BaseModel to remove duplicated code +- *(versions)* Update coolify versions to v4.0.0-beta.3909 + +## [4.0.0-beta.388] - 2025-01-22 + +### 🚀 Features + +- *(core)* Add SOURCE_COMMIT variable to build environment in ApplicationDeploymentJob +- *(service)* Update affine.yaml with AI environment variables (#4918) +- *(service)* Add new service Flipt (#4875) + +### 🐛 Bug Fixes + +- *(core)* Update environment variable generation logic in ApplicationDeploymentJob to handle different build packs +- *(env)* Shared variables can not be updated +- *(ui)* Metrics stuck in loading state +- *(ui)* Use `wire:navigate` to navigate to the server settings page +- *(service)* Plunk API & health check endpoint (#4925) + +## [4.0.0-beta.386] - 2025-01-22 + +### 🐛 Bug Fixes + +- *(redis)* Update environment variable keys from standalone_redis_id to resourceable_id +- *(routes)* Local API docs not available on domain or IP +- *(routes)* Local API docs not available on domain or IP +- *(core)* Update application_id references to resourable_id and resourable_type for Nixpacks configuration +- *(core)* Correct spelling of 'resourable' to 'resourceable' in Nixpacks configuration for ApplicationDeploymentJob +- *(ui)* Traefik dashboard url not working +- *(ui)* Proxy status badge flashing during navigation + +### 🚜 Refactor + +- *(workflows)* Replace jq with PHP script for version retrieval in workflows + +### ⚙️ Miscellaneous Tasks + +- *(dep)* Bump helper version to 1.0.5 +- *(docker)* Add blank line for readability in Dockerfile +- *(versions)* Update coolify versions to v4.0.0-beta.388 +- *(versions)* Update coolify versions to v4.0.0-beta.389 and add helper version retrieval script + +## [4.0.0-beta.385] - 2025-01-21 + +### 🚀 Features + +- *(core)* Wip version of coolify.json + +### 🐛 Bug Fixes + +- *(email)* Transactional email sending +- *(ui)* Add missing save button for new Docker Cleanup page +- *(ui)* Show preview deployment environment variables +- *(ui)* Show error on terminal if container has no shell (bash/sh) +- *(parser)* Resource URL should only be parsed if there is one +- *(core)* Compose parsing for apps + +### ⚙️ Miscellaneous Tasks + +- *(dep)* Bump nixpacks version +- *(dep)* Version++ + +## [4.0.0-beta.384] - 2025-01-21 + +### 🐛 Bug Fixes + +- *(ui)* Backups link should not redirected to general +- Envs with special chars during build +- *(db)* `finished_at` timestamps are not set for existing deployments +- Load service templates on cloud + +## [4.0.0-beta.383] - 2025-01-20 + +### 🐛 Bug Fixes + +- *(service)* Add healthcheck to Cloudflared service (#4859) +- Remove wire:navigate from import backups + +## [4.0.0-beta.382] - 2025-01-17 + +### 🚀 Features + +- Add log file check message in upgrade script for better troubleshooting +- Add root user details to install script + +### 🐛 Bug Fixes + +- Create the private key before the server in the prod seeder +- Update ProductionSeeder to check for private key instead of server's private key +- *(ui)* Missing underline for docs link in the Swarm section (#4860) +- *(service)* Change chatwoot service postgres image from `postgres:12` to `pgvector/pgvector:pg12` +- Docker image parser +- Add public key attribute to privatekey model +- Correct service update logic in Docker Compose parser +- Update CDN URL in install script to point to nightly version + +### 🚜 Refactor + +- Comment out RootUserSeeder call in ProductionSeeder for clarity +- Streamline ProductionSeeder by removing debug logs and unnecessary checks, while ensuring essential seeding operations remain intact +- Remove debug echo statements from Init command to clean up output and improve readability + +## [4.0.0-beta.381] - 2025-01-17 + +### 🚀 Features + +- Able to import full db backups for pg/mysql/mariadb +- Restore backup from server file +- Docker volume data cloning +- Move volume data cloning to a Job +- Volume cloning for ResourceOperations +- Remote server volume cloning +- Add horizon server details to queue +- Enhance horizon:manage command with worker restart check +- Add is_coolify_host to the server api responses +- DB migration for Backup retention +- UI for backup retention settings +- New global s3 and local backup deletion function +- Use new backup deletion functions +- Add calibre-web service +- Add actual-budget service +- Add rallly service +- Template for Gotenberg, a Docker-powered stateless API for PDF files +- Enhance import command options with additional guidance and improved checkbox label +- Purify for better sanitization +- Move docker cleanup to its own tab +- DB and Model for docker cleanup executions +- DockerCleanupExecutions relationship +- DockerCleanupDone event +- Get command and output for logs from CleanupDocker +- New sidebar menu and order +- Docker cleanup executions UI +- Add execution log to dockerCleanupJob +- Improve deployment UI +- Root user envs and seeding +- Email, username and password validation when they are set via envs +- Improved error handling and log output +- Add root user configuration variables to production environment + +### 🐛 Bug Fixes + +- Compose envs +- Scheduled tasks and backups are executed by server timezone. +- Show backup timezone on the UI +- Disappearing UI after livewire event received +- Add default vector db for anythingllm +- We need XSRF-TOKEN for terminal +- Prevent default link behavior for resource and settings actions in dashboard +- Increase default php memory limit +- Show if only build servers are added to your team +- Update Livewire button click method to use camelCase +- Local dropzonejs +- Import backups due to js stuff should not be navigated +- Install inetutils on Arch Linux +- Use ip in place of hostname from inetutils in arch +- Update import command to append file redirection for database restoration +- Ui bug on pw confirmation +- Exclude system and computed fields from model replication +- Service cloning on a separate server +- Application cloning +- `Undefined variable $fs_path` for databases +- Service and database cloning and label generation +- Labels and URL generation when cloning +- Clone naming for different database data volumes +- Implement all the cloneMe changes for ResourceOperations as well +- Volume and fileStorages cloning +- View text and helpers +- Teable +- Trigger with external db +- Set `EXPERIMENTAL_FEATURES` to false for labelstudio +- Monaco editor disabled state +- Edge case where executions could be null +- Create destination properly +- Getcontainer status should timeout after 30s +- Enable response for temporary unavailability in sentinel push endpoint +- Use timeout in cleanup resources +- Add timeout to sentinel process checks for improved reliability +- Horizon job checker +- Update response message for sentinel push route +- Add own servers on cloud +- Application deployment +- Service update statsu +- If $SERVICE found in the service specific configuration, then search for it in the db +- Instance wide GitHub apps are not available on other teams then the source team +- Function calls +- UI +- Deletion of single backup +- Backup job deletion - delete all backups from s3 and local +- Use new removeOldBackups function +- Retention functions and folder deletion for local backups +- Storage retention setting +- Db without s3 should still backup +- Wording +- `Undefined variable $service` when creating a new service +- Nodebb service +- Calibre-web service +- Rallly and actualbudget service +- Removed container_name +- Added healthcheck for gotenberg template +- Gotenberg +- *(template)* Gotenberg healthcheck, use /health instead of /version +- Use wire:navigate on sidebar +- Use wire:navigate on dashboard +- Use wire:navigate on projects page +- More wire:navigate +- Even more wire:navigate +- Service navigation +- Logs icons everywhere + terminal +- Redis DB should use the new resourceable columns +- Joomla service +- Add back letters to prod password requirement +- Check System and GitHub time and throw and error if it is over 50s out of sync +- Error message and server time getting +- Error rendering +- Render html correctly now +- Indent +- Potential fix for permissions update +- Expiration time claim ('exp') must be a numeric value +- Sanitize html error messages +- Production password rule and cleanup code +- Use json as it is just better than string for huge amount of logs +- Use `wire:navigate` on server sidebar +- Use finished_at for the end time instead of created_at +- Cancelled deployments should not show end and duration time +- Redirect to server index instead of show on error in Advanced and DockerCleanup components +- Disable registration after creating the root user +- RootUserSeeder +- Regex username validation +- Add spacing around echo outputs +- Success message +- Silent return if envs are empty or not set. + +### 💼 Other + +- Arrrrr +- Dep +- Docker dep + +### 🚜 Refactor + +- Rename parameter in DatabaseBackupJob for clarity +- Improve checkbox component accessibility and styling +- Remove unused tags method from ApplicationDeploymentJob +- Improve deployment status check in isAnyDeploymentInprogress function +- Extend HorizonServiceProvider from HorizonApplicationServiceProvider +- Streamline job status retrieval and clean up repository interface +- Enhance ApplicationDeploymentJob and HorizonServiceProvider for improved job handling +- Remove commented-out unsubscribe route from API +- Update redirect calls to use a consistent navigation method in deployment functions +- AppServiceProvider +- Github.php +- Improve data formatting and UI + +### ⚙️ Miscellaneous Tasks + +- Improve Penpot healthchecks +- Switch up readonly lables to make more sense +- Remove unused computed fields +- Use the new job dispatch +- Disable volume data cloning for now +- Improve code +- Lowcoder service naming +- Use new functions +- Improve error styling +- Css +- More css as it still looks like shit +- Final css touches +- Ajust time to 50s (tests done) +- Remove debug log, finally found it +- Remove more logging +- Remove limit on commit message +- Remove dayjs +- Remove unused code and fix import + +## [4.0.0-beta.380] - 2024-12-27 + +### 🚀 Features + +- New ServerReachabilityChanged event +- Use new ServerReachabilityChanged event instead of isDirty +- Add infomaniak oauth +- Add server disk usage check frequency +- Add environment_uuid support and update API documentation +- Add service/resource/project labels +- Add coolify.environment label +- Add database subtype +- Migrate to new encryption options +- New encryption options + +### 🐛 Bug Fixes + +- Render html on error page correctly +- Invalid API response on missing project +- Applications API response code + schema +- Applications API writing to unavailable models +- If an init script is renamed the old version is still on the server +- Oauthseeder +- Compose loading seq +- Resource clone name + volume name generation +- Update Dockerfile entrypoint path to /etc/entrypoint.d +- Debug mode +- Unreachable notifications +- Remove duplicated ServerCheckJob call +- Few fixes and use new ServerReachabilityChanged event +- Use serverStatus not just status +- Oauth seeder +- Service ui structure +- Check port 8080 and fallback to 80 +- Refactor database view +- Always use docker cleanup frequency +- Advanced server UI +- Html css +- Fix domain being override when update application +- Use nixpacks predefined build variables, but still could update the default values from Coolify +- Use local monaco-editor instead of Cloudflare +- N8n timezone +- Smtp encryption +- Bind() to 0.0.0.0:80 failed +- Oauth seeder +- Unreachable notifications +- Instance settings migration +- Only encrypt instance email settings if there are any +- Error message +- Update healthcheck and port configurations to use port 8080 + +### 🚜 Refactor + +- Rename `coolify.environment` to `coolify.environmentName` + +### ⚙️ Miscellaneous Tasks + +- Regenerate API spec, removing notification fields +- Remove ray debugging +- Version ++ + +## [4.0.0-beta.378] - 2024-12-13 + +### 🐛 Bug Fixes + +- Monaco editor light and dark mode switching +- Service status indicator + oauth saving +- Socialite for azure and authentik +- Saving oauth +- Fallback for copy button +- Copy the right text +- Maybe fallback is now working +- Only show copy button on secure context + +## [4.0.0-beta.377] - 2024-12-13 + +### 🚀 Features + +- Add deploy-only token permission +- Able to deploy without cache on every commit +- Update private key nam with new slug as well +- Allow disabling default redirect, set status to 503 +- Add TLS configuration for default redirect in Server model +- Slack notifications +- Introduce root permission +- Able to download schedule task logs +- Migrate old email notification settings from the teams table +- Migrate old discord notification settings from the teams table +- Migrate old telegram notification settings from the teams table +- Add slack notifications to a new table +- Enable success messages again +- Use new notification stuff inside team model +- Some more notification settings and better defaults +- New email notification settings +- New shared function name `is_transactional_emails_enabled()` +- New shared notifications functions +- Email Notification Settings Model +- Telegram notification settings Model +- Discord notification settings Model +- Slack notification settings Model +- New Discord notification UI +- New Slack notification UI +- New telegram UI +- Use new notification event names +- Always sent notifications +- Scheduled task success notification +- Notification trait +- Get discord Webhook form new table +- Get Slack Webhook form new table +- Use new table or instance settings for email +- Use new place for settings and topic IDs for telegram +- Encrypt instance email settings +- Use encryption in instance settings model +- Scheduled task success and failure notifications +- Add docker cleanup success and failure notification settings columns +- UI for docker cleanup success and failure notification +- Docker cleanup email views +- Docker cleanup success and failure notification files +- Scheduled task success email +- Send new docker cleanup notifications +- :passport_control: integrate Authentik authentication with Coolify +- *(notification)* Add Pushover +- Add seeder command and configuration for database seeding +- Add new password magic env with symbols +- Add documenso service + +### 🐛 Bug Fixes + +- Resolve undefined searchInput reference in Alpine.js component +- URL and sync new app name +- Typos and naming +- Client and webhook secret disappear after sync +- Missing `mysql_password` API property +- Incorrect MongoDB init API property +- Old git versions does not have --cone implemented properly +- Don't allow editing traefik config +- Restart proxy +- Dev mode +- Ui +- Display actual values for disk space checks in installer script +- Proxy change behaviour +- Add warning color +- Import NotificationSlack correctly +- Add middleware to new abilities, better ux for selecting permissions, etc. +- Root + read:sensive could read senstive data with a middlewarew +- Always have download logs button on scheduled tasks +- Missing css +- Development image +- Dockerignore +- DB migration error +- Drop all unused smtp columns +- Backward compatibility +- Email notification channel enabled function +- Instance email settins +- Make sure resend is false if SMTP is true and vice versa +- Email Notification saving +- Slack and discord url now uses text filed because encryption makes the url very long +- Notification trait +- Encryption fixes +- Docker cleanup email template +- Add missing deployment notifications to telegram +- New docker cleanup settings are now saved to the DB correctly +- Ui + migrations +- Docker cleanup email notifications +- General notifications does not go through email channel +- Test notifications to only send it to the right channel +- Remove resale_license from db as well +- Nexus service +- Fileflows volume names +- --cone +- Provider error +- Database migration +- Seeder +- Migration call +- Slack helper +- Telegram helper +- Discord helper +- Telegram topic IDs +- Make pushover settings more clear +- Typo in pushover user key +- Use Livewire refresh method and lock properties +- Create pushover settings for existing teams +- Update token permission check from 'write' to 'root' +- Pushover +- Oauth seeder +- Correct heading display for OAuth settings in settings-oauth.blade.php +- Adjust spacing in login form for improved layout +- Services env values should be sensitive +- Documenso +- Dolibarr +- Typo +- Update OauthSettingSeeder to handle new provider definitions and ensure authentik is recreated if missing +- Improve OauthSettingSeeder to correctly delete non-existent providers and ensure proper handling of provider definitions +- Encrypt resend API key in instance settings +- Resend api key is already a text column + +### 💼 Other + +- Test rename GitHub app +- Checkmate service and fix prowlar slogan (too long) + +### 🚜 Refactor + +- Update Traefik configuration for improved security and logging +- Improve proxy configuration and code consistency in Server model +- Rename name method to sanitizedName in BaseModel for clarity +- Improve migration command and enhance application model with global scope and status checks +- Unify notification icon +- Remove unused Azure and Authentik service configurations from services.php +- Change email column types in instance_settings migration from string to text +- Change OauthSetting creation to updateOrCreate for better handling of existing records + +### ⚙️ Miscellaneous Tasks + +- Regenerate openapi spec +- Composer dep bump +- Dep bump +- Upgrade cloudflared and minio +- Remove comments and improve DB column naming +- Remove unused seeder +- Remove unused waitlist stuff +- Remove wired.php (not used anymore) +- Remove unused resale license job +- Remove commented out internal notification +- Remove more waitlist stuff +- Remove commented out notification +- Remove more waitlist stuff +- Remove unused code +- Fix typo +- Remove comment out code +- Some reordering +- Remove resale license reference +- Remove functions from shared.php +- Public settings for email notification +- Remove waitlist redirect +- Remove log +- Use new notification trait +- Remove unused route +- Remove unused email component +- Comment status changes as it is disabled for now +- Bump dep +- Reorder navbar +- Rename topicID to threadId like in the telegram API response +- Update PHP configuration to set memory limit using environment variable + +## [4.0.0-beta.376] - 2024-12-07 + +### 🐛 Bug Fixes + +- Api endpoint + +## [4.0.0-beta.374] - 2024-12-03 + +### 🐛 Bug Fixes + +- Application view loading +- Postiz service +- Only able to select the right keys +- Test email should not be required +- A few inputs + +### 🧪 Testing + +- Setup database for upcoming tests + +## [4.0.0-beta.372] - 2024-11-26 + +### 🚀 Features + +- Add MacOS template +- Add Windows template +- *(service)* :sparkles: add mealie +- Add hex magic env var + +### 🐛 Bug Fixes + +- Service generate includes yml files as well (haha) +- ServercheckJob should run every 5 minutes on cloud +- New resource icons +- Search should be more visible on scroll on new resource +- Logdrain settings +- Ui +- Email should be retried with backoff +- Alpine in body layout + +### 💼 Other + +- Caddy docker labels do not honor "strip prefix" option + +## [4.0.0-beta.371] - 2024-11-22 + +### 🐛 Bug Fixes + +- Improve helper text for metrics input fields +- Refine helper text for metrics input fields +- If mux conn fails, still use it without mux + save priv key with better logic +- Migration +- Always validate ssh key +- Make sure important jobs/actions are running on high prio queue +- Do not send internal notification for backups and status jobs +- Validateconnection +- View issue +- Heading +- Remove mux cleanup +- Db backup for services +- Version should come from constants + fix stripe webhook error reporting +- Undefined variable +- Remove version.php as everything is coming from constants.php +- Sentry error +- Websocket connections autoreconnect +- Sentry error +- Sentry +- Empty server API response +- Incorrect server API patch response +- Missing `uuid` parameter on server API patch +- Missing `settings` property on servers API +- Move servers API `delete_unused_*` properties +- Servers API returning `port` as a string -> integer +- Only return server uuid on server update + +## [4.0.0-beta.370] - 2024-11-15 + +### 🐛 Bug Fixes + +- Modal (+ add) on dynamic config was not opening, removed x-cloak +- AUTOUPDATE + checkbox opacity + +## [4.0.0-beta.369] - 2024-11-15 + +### 🐛 Bug Fixes + +- Modal-input + +## [4.0.0-beta.368] - 2024-11-15 + +### 🚀 Features + +- Check local horizon scheduler deployments +- Add internal api docs to /docs/api with auth +- Add proxy type change to create/update apis + +### 🐛 Bug Fixes + +- Show proper error message on invalid Git source +- Convert HTTP to SSH source when using deploy key on GitHub +- Cloud + stripe related +- Terminal view loading in async +- Cool 500 error (thanks hugodos) +- Update schema in code decorator +- Openapi docs +- Add tests for git url converts +- Minio / logto url generation +- Admin view +- Min docker version 26 +- Pull latest service-templates.json on init +- Workflow files for coolify build +- Autocompletes +- Timezone settings validation +- Invalid tz should not prevent other jobs to be executed +- Testing-host should be built locally +- Poll with modal issue +- Terminal opening issue +- If service img not found, use github as a source +- Fallback to local coolify.png +- Gather private ips +- Cf tunnel menu should be visible when server is not validated +- Deployment optimizations +- Init script + optimize laravel +- Default docker engine version + fix install script +- Pull helper image on init +- SPA static site default nginx conf + +### 💼 Other + +- Https://github.com/coollabsio/coolify/issues/4186 +- Separate resources by type in projects view +- Improve s3 add view + +### ⚙️ Miscellaneous Tasks + +- Update dep + +## [4.0.0-beta.365] - 2024-11-11 + +### 🚀 Features + +- Custom nginx configuration for static deployments + fix 404 redirects in nginx conf + +### 🐛 Bug Fixes + +- Trigger.dev db host & sslmode=disable +- Manual update should be executed only once + better UX +- Upgrade.sh +- Missing privateKey + +## [4.0.0-beta.364] - 2024-11-08 + +### 🐛 Bug Fixes + +- Define separate volumes for mattermost service template +- Github app name is too long +- ServerTimezone update + +### ⚙️ Miscellaneous Tasks + +- Edit www helper + +## [4.0.0-beta.363] - 2024-11-08 + +### 🚀 Features + +- Add Firefox template +- Add template for Wiki.js +- Add upgrade logs to /data/coolify/source + +### 🐛 Bug Fixes + +- Saving resend api key +- Wildcard domain save +- Disable cloudflare tunnel on "localhost" + +## [4.0.0-beta.362] - 2024-11-08 + +### 🐛 Bug Fixes + +- Notifications ui +- Disable wire:navigate +- Confirmation Settings css for light mode +- Server wildcard + +## [4.0.0-beta.361] - 2024-11-08 + +### 🚀 Features + +- Add Transmission template +- Add transmission healhcheck +- Add zipline template +- Dify template +- Required envs +- Add EdgeDB +- Show warning if people would like to use sslip with https +- Add is shared to env variables +- Variabel sync and support shared vars +- Add notification settings to server_disk_usage +- Add coder service tamplate and logo +- Debug mode for sentinel +- Add jitsi template +- Add --gpu support for custom docker command + +### 🐛 Bug Fixes + +- Make sure caddy is not removed by cleanup +- Libretranslate +- Do not allow to change number of lines when streaming logs +- Plunk +- No manual timezones +- Helper push +- Format +- Add port metadata and Coolify magic to generate the domain +- Sentinel +- Metrics +- Generate sentinel url +- Only enable Sentinel for new servers +- Is_static through API +- Allow setting standalone redis variables via ENVs (team variables...) +- Check for username separately form password +- Encrypt all existing redis passwords +- Pull helper image on helper_version change +- Redis database user and password +- Able to update ipv4 / ipv6 instance settings +- Metrics for dbs +- Sentinel start fixed +- Validate sentinel custom URL when enabling sentinel +- Should be able to reset labels in read-only mode with manual click +- No sentinel for swarm yet +- Charts ui +- Volume +- Sentinel config changes restarts sentinel +- Disable sentinel for now +- Disable Sentinel temporarily +- Disable Sentinel temporarily for non-dev environments +- Access team's github apps only +- Admins should now invite owner +- Add experimental flag +- GenerateSentinelUrl method +- NumberOfLines could be null +- Login / register view +- Restart sentinel once a day +- Changing private key manually won't trigger a notification +- Grammar for helper +- Fix my own grammar +- Add telescope only in dev mode +- New way to update container statuses +- Only run server storage every 10 mins if sentinel is not active +- Cloud admin view +- Queries in kernel.php +- Lower case emails only +- Change emails to lowercase on init +- Do not error on update email +- Always authenticate with lowercase emails +- Dashboard refactor +- Add min/max length to input/texarea +- Remove livewire legacy from help view +- Remove unnecessary endpoints (magic) +- Transactional email livewire +- Destinations livewire refactor +- Refactor destination/docker view +- Logdrains validation +- Reworded +- Use Auth(), add new db proxy stop event refactor clickhouse view +- Add user/pw to db view +- Sort servers by name +- Keydb view +- Refactor tags view / remove obsolete one +- Send discord/telegram notifications on high job queue +- Server view refresh on validation +- ShowBoarding +- Show docker installation logs & ubuntu 24.10 notification +- Do not overlap servercheckjob +- Server limit check +- Server validation +- Clear route / view +- Only skip docker installation on 24.10 if its not installed +- For --gpus device support +- Db/service start should be on high queue +- Do not stop sentinel on Coolify restart +- Run resourceCheck after new serviceCheckJob +- Mongodb in dev +- Better invitation errors +- Loading indicator for db proxies +- Do not execute gh workflow on template changes +- Only use sentry in cloud +- Update packagejson of coolify-realtime + add lock file +- Update last online with old function +- Seeder should not start sentinel +- Start sentinel on seeder + +### 💼 Other + +- Add peppermint +- Loggy +- Add UI for redis password and username +- Wireguard-easy template + +### 📚 Documentation + +- Update link to deploy api docs + +### ⚙️ Miscellaneous Tasks + +- Add transmission template desc +- Update transmission docs link +- Update version numbers to 4.0.0-beta.360 in configuration files +- Update AWS environment variable names in unsend.yaml +- Update AWS environment variable names in unsend.yaml +- Update livewire/livewire dependency to version 3.4.9 +- Update version to 4.0.0-beta.361 +- Update Docker build and push actions to v6 +- Update Docker build and push actions to v6 +- Update Docker build and push actions to v6 +- Sync coolify-helper to dockerhub as well +- Push realtime to dockerhub +- Sync coolify-realtime to dockerhub +- Rename workflows +- Rename development to staging build +- Sync coolify-testing-host to dockerhbu +- Sync coolify prod image to dockerhub as well +- Update Docker version to 26.0 +- Update project resource index page +- Update project service configuration view + +## [4.0.0-beta.360] - 2024-10-11 + +### ⚙️ Miscellaneous Tasks + +- Update livewire/livewire dependency to version 3.4.9 + +## [4.0.0-beta.359] - 2024-10-11 + +### 🐛 Bug Fixes + +- Use correct env variable for invoice ninja password + +### ⚙️ Miscellaneous Tasks + +- Update laravel/horizon dependency to version 5.29.1 +- Update service extra fields to use dynamic keys + +## [4.0.0-beta.358] - 2024-10-10 + +### 🚀 Features + +- Add customHelper to stack-form +- Add cloudbeaver template +- Add ntfy template +- Add qbittorrent template +- Add Homebox template +- Add owncloud service and logo +- Add immich service +- Auto generate url +- Refactored to work with coolify auto env vars +- Affine service template and logo +- Add LibreTranslate template +- Open version in a new tab + +### 🐛 Bug Fixes + +- Signup +- Application domains should be http and https only +- Validate and sanitize application domains +- Sanitize and validate application domains + +### 💼 Other + +- Other DB options for freshrss +- Nextcloud MariaDB and MySQL versions + +### ⚙️ Miscellaneous Tasks + +- Fix form submission and keydown event handling in modal-confirmation.blade.php +- Update version numbers to 4.0.0-beta.359 in configuration files +- Disable adding default environment variables in shared.php + +## [4.0.0-beta.357] - 2024-10-08 + +### 🚀 Features + +- Add Mautic 4 and 5 to service templates +- Add keycloak template +- Add onedev template +- Improve search functionality in project selection + +### 🐛 Bug Fixes + +- Update mattermost image tag and add default port +- Remove env, change timezone +- Postgres healthcheck +- Azimutt template - still not working haha +- New parser with SERVICE_URL_ envs +- Improve service template readability +- Update password variables in Service model +- Scheduled database server +- Select server view + +### 💼 Other + +- Keycloak + +### ⚙️ Miscellaneous Tasks + +- Add mattermost logo as svg +- Add mattermost svg to compose +- Update version to 4.0.0-beta.357 + +## [4.0.0-beta.356] - 2024-10-07 + +### 🚀 Features + +- Add Argilla service configuration to Service model +- Add Invoice Ninja service configuration to Service model +- Project search on frontend +- Add ollama service with open webui and logo +- Update setType method to use slug value for type +- Refactor setType method to use slug value for type +- Refactor setType method to use slug value for type +- Add Supertokens template +- Add easyappointments service template +- Add dozzle template +- Adds forgejo service with runners + +### 🐛 Bug Fixes + +- Reset description and subject fields after submitting feedback +- Tag mass redeployments +- Service env orders, application env orders +- Proxy conf in dev +- One-click services +- Use local service-templates in dev +- New services +- Remove not used extra host +- Chatwoot service +- Directus +- Database descriptions +- Update services +- Soketi +- Select server view + +### 💼 Other + +- Update helper version +- Outline +- Directus +- Supertokens +- Supertokens json +- Rabbitmq +- Easyappointments +- Soketi +- Dozzle +- Windmill +- Coolify.json + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.356 +- Remove commented code for shared variable type validation +- Update MariaDB image to version 11 and fix service environment variable orders +- Update anythingllm.yaml volumes configuration +- Update proxy configuration paths for Caddy and Nginx in dev +- Update password form submission in modal-confirmation component +- Update project query to order by name in uppercase +- Update project query to order by name in lowercase +- Update select.blade.php with improved search functionality +- Add Nitropage service template and logo +- Bump coolify-helper version to 1.0.2 +- Refactor loadServices2 method and remove unused code +- Update version to 4.0.0-beta.357 +- Update service names and volumes in windmill.yaml +- Update version to 4.0.0-beta.358 +- Ignore .ignition.json files in Docker and Git + +## [4.0.0-beta.355] - 2024-10-03 + +### 🐛 Bug Fixes + +- Scheduled backup for services view +- Parser, espacing container labels + +### ⚙️ Miscellaneous Tasks + +- Update homarr service template and remove unnecessary code +- Update version to 4.0.0-beta.355 + +## [4.0.0-beta.354] - 2024-10-03 + +### 🚀 Features + +- Add it-tools service template and logo +- Add homarr service tamplate and logo + +### 🐛 Bug Fixes + +- Parse proxy config and check the set ports usage +- Update FQDN + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.354 +- Remove debug statement in Service model +- Remove commented code in Server model +- Fix application deployment queue filter logic +- Refactor modal-confirmation component +- Update it-tools service template and port configuration +- Update homarr service template and remove unnecessary code + +## [4.0.0-beta.353] - 2024-10-03 + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.353 +- Update service application view + +## [4.0.0-beta.352] - 2024-10-03 + +### 🐛 Bug Fixes + +- Service application view +- Add new supported database images + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.352 +- Refactor DatabaseBackupJob to handle missing team + +## [4.0.0-beta.351] - 2024-10-03 + +### 🚀 Features + +- Add strapi template + +### 🐛 Bug Fixes + +- Able to support more database dynamically from Coolify's UI +- Strapi template +- Bitcoin core template +- Api useBuildServer + +## [4.0.0-beta.349] - 2024-10-01 + +### 🚀 Features + +- Add command to check application deployment queue +- Support Hetzner S3 +- Handle HTTPS domain in ConfigureCloudflareTunnels +- Backup all databases for mysql,mariadb,postgresql +- Restart service without pulling the latest image + +### 🐛 Bug Fixes + +- Remove autofocuses +- Ipv6 scp should use -6 flag +- Cleanup stucked applicationdeploymentqueue +- Realtime watch in development mode +- Able to select root permission easier + +### 💼 Other + +- Show backup button on supported db service stacks + +### 🚜 Refactor + +- Remove deployment queue when deleting an application +- Improve SSH command generation in Terminal.php and terminal-server.js +- Fix indentation in modal-confirmation.blade.php +- Improve parsing of commands for sudo in parseCommandsByLineForSudo +- Improve popup component styling and button behavior +- Encode delimiter in SshMultiplexingHelper +- Remove inactivity timer in terminal-server.js +- Improve socket reconnection interval in terminal.js +- Remove unnecessary watch command from soketi service entrypoint + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.350 in configuration files +- Update command signature and description for cleanup application deployment queue +- Add missing import for Attribute class in ApplicationDeploymentQueue model +- Update modal input in server form to prevent closing on outside click +- Remove unnecessary command from SshMultiplexingHelper +- Remove commented out code for uploading to S3 in DatabaseBackupJob +- Update soketi service image to version 1.0.3 + +## [4.0.0-beta.348] - 2024-10-01 + +### 🚀 Features + +- Update resource deletion job to allow configurable options through API +- Add query parameters for deleting configurations, volumes, docker cleanup, and connected networks + +### 🐛 Bug Fixes + +- In dev mode do not ask confirmation on delete +- Mixpost +- Handle deletion of 'hello' in confirmation modal for dev environment + +### 💼 Other + +- Server storage check + +### 🚜 Refactor + +- Update search input placeholder in resource index view + +### ⚙️ Miscellaneous Tasks + +- Fix docs link in running state +- Update Coolify Realtime workflow to only trigger on the main branch +- Refactor instanceSettings() function to improve code readability +- Update Coolify Realtime image to version 1.0.2 +- Remove unnecessary code in DatabaseBackupJob.php +- Add "Not Usable" indicator for storage items +- Refactor instanceSettings() function and improve code readability +- Update version numbers to 4.0.0-beta.349 and 4.0.0-beta.350 + +## [4.0.0-beta.347] - 2024-09-28 + +### 🚀 Features + +- Allow specify use_build_server when creating/updating an application +- Add support for `use_build_server` in API endpoints for creating/updating applications +- Add Mixpost template + +### 🐛 Bug Fixes + +- Filebrowser template +- Edit is_build_server_enabled upon creating application on other application type +- Save settings after assigning value + +### 💼 Other + +- Remove memlock as it caused problems for some users + +### ⚙️ Miscellaneous Tasks + +- Update Mailpit logo to use SVG format + +## [4.0.0-beta.346] - 2024-09-27 + +### 🚀 Features + +- Add ContainerStatusTypes enum for managing container status + +### 🐛 Bug Fixes + +- Proxy fixes +- Proxy +- *(templates)* Filebrowser FQDN env variable +- Handle edge case when build variables and env variables are in different format +- Compose based terminal + +### 💼 Other + +- Manual cleanup button and unused volumes and network deletion +- Force helper image removal +- Use the new confirmation flow +- Typo +- Typo in install script +- If API is disabeled do not show API token creation stuff +- Disable API by default +- Add debug bar + +### 🚜 Refactor + +- Update environment variable name for uptime-kuma service +- Improve start proxy script to handle existing containers gracefully +- Update delete server confirmation modal buttons +- Remove unnecessary code + +### ⚙️ Miscellaneous Tasks + +- Add autocomplete attribute to input fields +- Refactor API Tokens component to use isApiEnabled flag +- Update versions.json file +- Remove unused .env.development.example file +- Update API Tokens view to include link to Settings menu +- Update web.php to cast server port as integer +- Update backup deletion labels to use language files +- Update database startup heading title +- Update database startup heading title +- Custom vite envs +- Update version numbers to 4.0.0-beta.348 +- Refactor code to improve SSH key handling and storage + +## [4.0.0-beta.343] - 2024-09-25 + +### 🐛 Bug Fixes + +- Parser +- Exited services statuses +- Make sure to reload window if app status changes +- Deploy key based deployments + +### 🚜 Refactor + +- Remove commented out code and improve environment variable handling in newParser function +- Improve label positioning in input and checkbox components +- Group and sort fields in StackForm by service name and password status +- Improve layout and add checkbox for task enablement in scheduled task form +- Update checkbox component to support full width option +- Update confirmation label in danger.blade.php template +- Fix typo in execute-container-command.blade.php +- Update OS_TYPE for Asahi Linux in install.sh script +- Add localhost as Server if it doesn't exist and not in cloud environment +- Add localhost as Server if it doesn't exist and not in cloud environment +- Update ProductionSeeder to fix issue with coolify_key assignment +- Improve modal confirmation titles and button labels +- Update install.sh script to remove redirection of upgrade output to /dev/null +- Fix modal input closeOutside prop in configuration.blade.php +- Add support for IPv6 addresses in sslip function + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.343 +- Update version numbers to 4.0.0-beta.344 +- Update version numbers to 4.0.0-beta.345 +- Update version numbers to 4.0.0-beta.346 + +## [4.0.0-beta.342] - 2024-09-24 + +### 🚀 Features + +- Add nullable constraint to 'fingerprint' column in private_keys table +- *(api)* Add an endpoint to execute a command +- *(api)* Add endpoint to execute a command + +### 🐛 Bug Fixes + +- Proxy status +- Coolify-db should not be in the managed resources +- Store original root key in the original location +- Logto service +- Cloudflared service +- Migrations +- Cloudflare tunnel configuration, ui, etc + +### 💼 Other + +- Volumes on development environment +- Clean new volume name for dev volumes +- Persist DBs, services and so on stored in data/coolify +- Add SSH Key fingerprint to DB +- Add a fingerprint to every private key on save, create... +- Make sure invalid private keys can not be added +- Encrypt private SSH keys in the DB +- Add is_sftp and is_server_ssh_key coloums +- New ssh key file name on disk +- Store all keys on disk by default +- Populate SSH key folder +- Populate SSH keys in dev +- Use new function names and logic everywhere +- Create a Multiplexing Helper +- SSH multiplexing +- Remove unused code form multiplexing +- SSH Key cleanup job +- Private key with ID 2 on dev +- Move more functions to the PrivateKey Model +- Add ssh key fingerprint and generate one for existing keys +- ID issues on dev seeders +- Server ID 0 +- Make sure in use private keys are not deleted +- Do not delete SSH Key from disk during server validation error +- UI bug, do not write ssh key to disk in server dialog +- SSH Multiplexing for Jobs +- SSH algorhytm text +- Few multiplexing things +- Clear mux directory +- Multiplexing do not write file manually +- Integrate tow step process in the modal component WIP +- Ability to hide labels +- DB start, stop confirm +- Del init script +- General confirm +- Preview deployments and typos +- Service confirmation +- Confirm file storage +- Stop service confirm +- DB image cleanup +- Confirm ressource operation +- Environment variabel deletion +- Confirm scheduled tasks +- Confirm API token +- Confirm private key +- Confirm server deletion +- Confirm server settings +- Proxy stop and restart confirmation +- GH app deletion confirmation +- Redeploy all confirmation +- User deletion confirmation +- Team deletion confirmation +- Backup job confirmation +- Delete volume confirmation +- More conformations and fixes +- Delete unused private keys button +- Ray error because port is not uncommented +- #3322 deploy DB alterations before updating +- Css issue with advanced settings and remove cf tunnel in onboarding +- New cf tunnel install flow +- Made help text more clear +- Cloudflare tunnel +- Make helper text more clean to use a FQDN and not an URL + +### 🚜 Refactor + +- Update Docker cleanup label in Heading.php and Navbar.php +- Remove commented out code in Navbar.php +- Remove CleanupSshKeysJob from schedule in Kernel.php +- Update getAJoke function to exclude offensive jokes +- Update getAJoke function to use HTTPS for API request +- Update CleanupHelperContainersJob to use more efficient Docker command +- Update PrivateKey model to improve code readability and maintainability +- Remove unnecessary code in PrivateKey model +- Update PrivateKey model to use ownedByCurrentTeam() scope for cleanupUnusedKeys() +- Update install.sh script to check if coolify-db volume exists before generating SSH key +- Update ServerSeeder and PopulateSshKeysDirectorySeeder +- Improve attribute sanitization in Server model +- Update confirmation button text for deletion actions +- Remove unnecessary code in shared.php file +- Update environment variables for services in compose files +- Update select.blade.php to improve trademarks policy display +- Update select.blade.php to improve trademarks policy display +- Fix typo in subscription URLs +- Add Postiz service to compose file (disabled for now) +- Update shared.php to include predefined ports for services +- Simplify SSH key synchronization logic +- Remove unused code in DatabaseBackupStatusJob and PopulateSshKeysDirectorySeeder + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.342 +- Update remove-labels-and-assignees-on-close.yml +- Add SSH key for localhost in ProductionSeeder +- Update SSH key generation in install.sh script +- Update ProductionSeeder to call OauthSettingSeeder and PopulateSshKeysDirectorySeeder +- Update install.sh to support Asahi Linux +- Update install.sh version to 1.6 +- Remove unused middleware and uniqueId method in DockerCleanupJob +- Refactor DockerCleanupJob to remove unused middleware and uniqueId method +- Remove unused migration file for populating SSH keys and clearing mux directory +- Add modified files to the commit +- Refactor pre-commit hook to improve performance and readability +- Update CONTRIBUTING.md with troubleshooting note about database migrations +- Refactor pre-commit hook to improve performance and readability +- Update cleanup command to use Redis instead of queue +- Update Docker commands to start proxy + +## [4.0.0-beta.341] - 2024-09-18 + +### 🚀 Features + +- Add buddy logo + +## [4.0.0-beta.336] - 2024-09-16 + +### 🚀 Features + +- Make coolify full width by default +- Fully functional terminal for command center +- Custom terminal host + +### 🐛 Bug Fixes + +- Keep-alive ws connections +- Add build.sh to debug logs +- Update Coolify installer +- Terminal +- Generate https for minio +- Install script +- Handle WebSocket connection close in terminal.blade.php +- Able to open terminal to any containers +- Refactor run-command +- If you exit a container manually, it should close the underlying tty as well +- Move terminal to separate view on services +- Only update helper image in DB +- Generated fqdn for SERVICE_FQDN_APP_3000 magic envs + +### 💼 Other + +- Remove labels and assignees on issue close +- Make sure this action is also triggered on PR issue close + +### 🚜 Refactor + +- Remove unnecessary code in ExecuteContainerCommand.php +- Improve Docker network connection command in StartService.php +- Terminal / run command +- Add authorization check in ExecuteContainerCommand mount method +- Remove unnecessary code in Terminal.php +- Remove unnecessary code in Terminal.blade.php +- Update WebSocket connection initialization in terminal.blade.php +- Remove unnecessary console.log statements in terminal.blade.php + +### ⚙️ Miscellaneous Tasks + +- Update release version to 4.0.0-beta.336 +- Update coolify environment variable assignment with double quotes +- Update shared.php to fix issues with source and network variables +- Update terminal styling for better readability +- Update button text for container connection form +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Remove unused entrypoint script and update volume mapping +- Update .env file and docker-compose configuration +- Update APP_NAME environment variable in docker-compose.prod.yml +- Update WebSocket URL in terminal.blade.php +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Rename Command Center to Terminal in code and views +- Update branch restriction for push event in coolify-helper.yml +- Update terminal button text and layout in application heading view +- Refactor terminal component and select form layout +- Update coolify nightly version to 4.0.0-beta.335 +- Update helper version to 1.0.1 +- Fix syntax error in versions.json +- Update version numbers to 4.0.0-beta.337 +- Update Coolify installer and scripts to include a function for fetching programming jokes +- Update docker network connection command in ApplicationDeploymentJob.php +- Add validation to prevent selecting 'default' server or container in RunCommand.php +- Update versions.json to reflect latest version of realtime container +- Update soketi image to version 1.0.1 +- Nightly - Update soketi image to version 1.0.1 and versions.json to reflect latest version of realtime container +- Update version numbers to 4.0.0-beta.339 +- Update version numbers to 4.0.0-beta.340 +- Update version numbers to 4.0.0-beta.341 + +### ◀️ Revert + +- Databasebackup + +## [4.0.0-beta.335] - 2024-09-12 + +### 🐛 Bug Fixes + +- Cloudflare tunnel with new multiplexing feature + +### 💼 Other + +- SSH Multiplexing on docker desktop on Windows + +### ⚙️ Miscellaneous Tasks + +- Update release version to 4.0.0-beta.335 +- Update constants.ssh.mux_enabled in remoteProcess.php +- Update listeners and proxy settings in server form and new server components +- Remove unnecessary null check for proxy_type in generate_default_proxy_configuration +- Remove unnecessary SSH command execution time logging + +## [4.0.0-beta.334] - 2024-09-12 + +### ⚙️ Miscellaneous Tasks + +- Remove itsgoingd/clockwork from require-dev in composer.json +- Update 'key' value of gitlab in Service.php to use environment variable + +## [4.0.0-beta.333] - 2024-09-11 + +### 🐛 Bug Fixes + +- Disable mux_enabled during server validation +- Move mc command to coolify image from helper +- Keydb. add `:` delimiter for connection string + +### 💼 Other + +- Remote servers with port and user +- Do not change localhost server name on revalidation +- Release.md file + +### 🚜 Refactor + +- Improve handling of environment variable merging in upgrade script + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.333 +- Copy .env file to .env-{DATE} if it exists +- Update .env file with new values +- Update server check job middleware to use server ID instead of UUID +- Add reminder to backup .env file before running install script again +- Copy .env file to backup location during installation script +- Add reminder to backup .env file during installation script +- Update permissions in pr-build.yml and version numbers +- Add minio/mc command to Dockerfile + +## [4.0.0-beta.332] - 2024-09-10 + +### 🚀 Features + +- Expose project description in API response +- Add elixir finetunes to the deployment job + +### 🐛 Bug Fixes + +- Reenable overlapping servercheckjob +- Appwrite template + parser +- Don't add `networks` key if `network_mode` is used +- Remove debug statement in shared.php +- Scp through cloudflare +- Delete older versions of the helper image other than the latest one +- Update remoteProcess.php to handle null values in logItem properties + +### 💼 Other + +- Set a default server timezone +- Implement SSH Multiplexing +- Enabel mux +- Cleanup stale multiplexing connections + +### 🚜 Refactor + +- Improve environment variable handling in shared.php + +### ⚙️ Miscellaneous Tasks + +- Set timeout for ServerCheckJob to 60 seconds +- Update appwrite.yaml to include OpenSSL key variable assignment + +## [4.0.0-beta.330] - 2024-09-06 + +### 🐛 Bug Fixes + +- Parser +- Plunk NEXT_PUBLIC_API_URI + +### 💼 Other + +- Pull helper image if not available otherwise s3 backup upload fails + +### 🚜 Refactor + +- Improve handling of server timezones in scheduled backups and tasks +- Improve handling of server timezones in scheduled backups and tasks +- Improve handling of server timezones in scheduled backups and tasks +- Update cleanup schedule to run daily at midnight +- Skip returning volume if driver type is cifs or nfs + +### ⚙️ Miscellaneous Tasks + +- Update coolify-helper.yml to get version from versions.json +- Disable Ray by default +- Enable Ray by default and update Dockerfile with latest versions of PACK and NIXPACKS +- Update Ray configuration and Dockerfile +- Add middleware for updating environment variables by UUID in `api.php` routes +- Expose port 3000 in browserless.yaml template +- Update Ray configuration and Dockerfile +- Update coolify version to 4.0.0-beta.331 +- Update versions.json and sentry.php to 4.0.0-beta.332 +- Update version to 4.0.0-beta.332 +- Update DATABASE_URL in plunk.yaml to use plunk database +- Add coolify.managed=true label to Docker image builds +- Update docker image pruning command to exclude managed images +- Update docker cleanup schedule to run daily at midnight +- Update versions.json to version 1.0.1 +- Update coolify-helper.yml to include "next" branch in push trigger + +## [4.0.0-beta.326] - 2024-09-03 + +### 🚀 Features + +- Update server_settings table to force docker cleanup +- Update Docker Compose file with DB_URL environment variable +- Refactor shared.php to improve environment variable handling + +### 🐛 Bug Fixes + +- Wrong executions order +- Handle project not found error in environment_details API endpoint +- Deployment running for - without "ago" +- Update helper image pulling logic to only pull if the version is newer + +### 💼 Other + +- Plunk svg + +### 📚 Documentation + +- Update Plunk documentation link in compose/plunk.yaml + +### ⚙️ Miscellaneous Tasks + +- Update UI for displaying no executions found in scheduled task list +- Update UI for displaying deployment status in deployment list +- Update UI for displaying deployment status in deployment list +- Ignore unnecessary files in production build workflow +- Update server form layout and settings +- Update Dockerfile with latest versions of PACK and NIXPACKS + +## [4.0.0-beta.324] - 2024-09-02 + +### 🚀 Features + +- Preserve git repository with advanced file storages +- Added Windmill template +- Added Budibase template +- Add shm-size for custom docker commands +- Add custom docker container options to all databases +- Able to select different postgres database +- Add new logos for jobscollider and hostinger +- Order scheduled task executions +- Add Code Server environment variables to Service model +- Add coolify build env variables to building phase +- Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid +- Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid + +### 🐛 Bug Fixes + +- Timezone not updated when systemd is missing +- If volumes + file mounts are defined, should merge them together in the compose file +- All mongo v4 backups should use the different backup command +- Database custom environment variables +- Connect compose apps to the right predefined network +- Docker compose destination network +- Server status when there are multiple servers +- Sync fqdn change on the UI +- Pr build names in case custom name is used +- Application patch request instant_deploy +- Canceling deployment on build server +- Backup of password protected postgresql database +- Docker cleanup job +- Storages with preserved git repository +- Parser parser parser +- New parser only in dev +- Parser parser +- Numberoflines should be number +- Docker cleanup job +- Fix directory and file mount headings in file-storage.blade.php +- Preview fqdn generation +- Revert a few lines +- Service ui sync bug +- Setup script doesn't work on rhel based images with some curl variant already installed +- Let's wait for healthy container during installation and wait an extra 20 seconds (for migrations) +- Infra files +- Log drain only for Applications +- Copy large compose files through scp (not ssh) +- Check if array is associative or not +- Openapi endpoint urls +- Convert environment variables to one format in shared.php +- Logical volumes could be overwritten with new path +- Env variable in value parsed +- Pull coolify image only when the app needs to be updated + +### 💼 Other + +- Actually update timezone on the server +- Cron jobs are executed based on the server timezone +- Server timezone seeder +- Recent backups UI +- Use apt-get instead of apt +- Typo +- Only pull helper image if the version is newer than the one + +### 🚜 Refactor + +- Update event listeners in Show components +- Refresh application to get latest database changes +- Update RabbitMQ configuration to use environment variable for port +- Remove debug statement in parseDockerComposeFile function +- ParseServiceVolumes +- Update OpenApi command to generate documentation +- Remove unnecessary server status check in destination view +- Remove unnecessary admin user email and password in budibase.yaml +- Improve saving of custom internal name in Advanced.php +- Add conditional check for volumes in generate_compose_file() +- Improve storage mount forms in add.blade.php +- Load environment variables based on resource type in sortEnvironmentVariables() +- Remove unnecessary network cleanup in Init.php +- Remove unnecessary environment variable checks in parseDockerComposeFile() +- Add null check for docker_compose_raw in parseCompose() +- Update dockerComposeParser to use YAML data from $yaml instead of $compose +- Convert service variables to key-value pairs in parseDockerComposeFile function +- Update database service name from mariadb to mysql +- Remove unnecessary code in DatabaseBackupJob and BackupExecutions +- Update Docker Compose parsing function to convert service variables to key-value pairs +- Update Docker Compose parsing function to convert service variables to key-value pairs +- Remove unused server timezone seeder and related code +- Remove unused server timezone seeder and related code +- Remove unused PullCoolifyImageJob from schedule +- Update parse method in Advanced, All, ApplicationPreview, General, and ApplicationDeploymentJob classes +- Remove commented out code for getIptables() in Dashboard.php +- Update .env file path in install.sh script +- Update SELF_HOSTED environment variable in docker-compose.prod.yml +- Remove unnecessary code for creating coolify network in upgrade.sh +- Update environment variable handling in StartClickhouse.php and ApplicationDeploymentJob.php +- Improve handling of COOLIFY_URL in shared.php +- Update build_args property type in ApplicationDeploymentJob +- Update background color of sponsor section in README.md +- Update Docker Compose location handling in PublicGitRepository +- Upgrade process of Coolify + +### 🧪 Testing + +- More tests + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.324 +- New compose parser with tests +- Update version to 1.3.4 in install.sh and 1.0.6 in upgrade.sh +- Update memory limit to 64MB in horizon configuration +- Update php packages +- Update axios npm dependency to version 1.7.5 +- Update Coolify version to 4.0.0-beta.324 and fix file paths in upgrade script +- Update Coolify version to 4.0.0-beta.324 +- Update Coolify version to 4.0.0-beta.325 +- Update Coolify version to 4.0.0-beta.326 +- Add cd command to change directory before removing .env file +- Update Coolify version to 4.0.0-beta.327 +- Update Coolify version to 4.0.0-beta.328 +- Update sponsor links in README.md +- Update version.json to versions.json in GitHub workflow +- Cleanup stucked resources and scheduled backups +- Update GitHub workflow to use versions.json instead of version.json +- Update GitHub workflow to use versions.json instead of version.json +- Update GitHub workflow to use versions.json instead of version.json +- Update GitHub workflow to use jq container for version extraction +- Update GitHub workflow to use jq container for version extraction + +## [4.0.0-beta.323] - 2024-08-08 + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.323 + +## [4.0.0-beta.322] - 2024-08-08 + +### 🐛 Bug Fixes + +- Manual update process + +### 🚜 Refactor + +- Update Server model getContainers method to use collect() for containers and containerReplicates +- Import ProxyTypes enum and use TRAEFIK instead of TRAEFIK_V2 + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.322 + +## [4.0.0-beta.321] - 2024-08-08 + +### 🐛 Bug Fixes + +- Scheduledbackup not found + +### 🚜 Refactor + +- Update StandalonePostgresql database initialization and backup handling +- Update cron expressions and add helper text for scheduled tasks + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.321 + +## [4.0.0-beta.320] - 2024-08-08 + +### 🚀 Features + +- Delete team in cloud without subscription +- Coolify init should cleanup stuck networks in proxy +- Add manual update check functionality to settings page +- Update auto update and update check frequencies in settings +- Update Upgrade component to check for latest version of Coolify +- Improve homepage service template +- Support map fields in Directus +- Labels by proxy type +- Able to generate only the required labels for resources + +### 🐛 Bug Fixes + +- Only append docker network if service/app is running +- Remove lazy load from scheduled tasks +- Plausible template +- Service_url should not have a trailing slash +- If usagebefore cannot be determined, cleanup docker with force +- Async remote command +- Only run logdrain if necessary +- Remove network if it is only connected to coolify proxy itself +- Dir mounts should have proper dirs +- File storages (dir/file mount) handled properly +- Do not use port exposes on docker compose buildpacks +- Minecraft server template fixed +- Graceful shutdown +- Stop resources gracefully +- Handle null and empty disk usage in DockerCleanupJob +- Show latest version on manual update view +- Empty string content should be saved as a file +- Update Traefik labels on init +- Add missing middleware for server check job + +### 🚜 Refactor + +- Update CleanupDatabase.php to adjust keep_days based on environment +- Adjust keep_days in CleanupDatabase.php based on environment +- Remove commented out code for cleaning up networks in CleanupDocker.php +- Update livewire polling interval in heading.blade.php +- Remove unused code for checking server status in Heading.php +- Simplify log drain installation in ServerCheckJob +- Remove unnecessary debug statement in ServerCheckJob +- Simplify log drain installation and stop log drain if necessary +- Cleanup unnecessary dynamic proxy configuration in Init command +- Remove unnecessary debug statement in ApplicationDeploymentJob +- Update timeout for graceful_shutdown_container in ApplicationDeploymentJob +- Remove unused code and optimize CheckForUpdatesJob +- Update ProxyTypes enum values to use TRAEFIK instead of TRAEFIK_V2 +- Update Traefik labels on init and cleanup unnecessary dynamic proxy configuration + +### 🎨 Styling + +- Linting + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.320 +- Add pull_request image builds to GH actions +- Add comment explaining the purpose of disconnecting the network in cleanup_unused_network_from_coolify_proxy() +- Update formbricks template +- Update registration view to display a notice for first user that it will be an admin +- Update server form to use password input for IP Address/Domain field +- Update navbar to include service status check +- Update navbar and configuration to improve service status check functionality +- Update workflows to include PR build and merge manifest steps +- Update UpdateCoolifyJob timeout to 10 minutes +- Update UpdateCoolifyJob to dispatch CheckForUpdatesJob synchronously + +## [4.0.0-beta.319] - 2024-07-26 + +### 🐛 Bug Fixes + +- Parse docker composer +- Service env parsing +- Service env variables +- Activity type invalid +- Update env on ui + +### 💼 Other + +- Service env parsing + +### ⚙️ Miscellaneous Tasks + +- Collect/create/update volumes in parseDockerComposeFile function + +## [4.0.0-beta.318] - 2024-07-24 + +### 🚀 Features + +- Create/delete project endpoints +- Add patch request to projects +- Add server api endpoints +- Add branddev logo to README.md +- Update API endpoint summaries +- Update Caddy button label in proxy.blade.php +- Check custom internal name through server's applications. +- New server check job + +### 🐛 Bug Fixes + +- Preview deployments should be stopped properly via gh webhook +- Deleting application should delete preview deployments +- Plane service images +- Fix issue with deployment start command in ApplicationDeploymentJob +- Directory will be created by default for compose host mounts +- Restart proxy does not work + status indicator on the UI +- Uuid in api docs type +- Raw compose deployment .env not found +- Api -> application patch endpoint +- Remove pull always when uploading backup to s3 +- Handle array env vars +- Link in task failed job notifications +- Random generated uuid will be full length (not 7 characters) +- Gitlab service +- Gitlab logo +- Bitbucket repository url +- By default volumes that we cannot determine if they are directories or files are treated as directories +- Domain update on services on the UI +- Update SERVICE_FQDN/URL env variables when you change the domain +- Several shared environment variables in one value, parsed correctly +- Members of root team should not see instance admin stuff + +### 💼 Other + +- Formbricks template add required CRON_SECRET +- Add required CRON_SECRET to Formbricks template + +### ⚙️ Miscellaneous Tasks + +- Update APP_BASE_URL to use SERVICE_FQDN_PLANE +- Update resource-limits.blade.php with improved input field helpers +- Update version numbers to 4.0.0-beta.319 +- Remove commented out code for docker image pruning + +## [4.0.0-beta.314] - 2024-07-15 + +### 🚀 Features + +- Improve error handling in loadComposeFile method +- Add readonly labels +- Preserve git repository +- Force cleanup server + +### 🐛 Bug Fixes + +- Typo in is_literal helper +- Env is_literal helper text typo +- Update docker compose pull command with --policy always +- Plane service template +- Vikunja +- Docmost template +- Drupal +- Improve github source creation +- Tag deployments +- New docker compose parsing +- Handle / in preselecting branches +- Handle custom_internal_name check in ApplicationDeploymentJob.php +- If git limit reached, ignore it and continue with a default selection +- Backup downloads +- Missing input for api endpoint +- Volume detection (dir or file) is fixed +- Supabase +- Create file storage even if content is empty + +### 💼 Other + +- Add basedir + compose file in new compose based apps + +### 🚜 Refactor + +- Remove unused code and fix storage form layout +- Update Docker Compose build command to include --pull flag +- Update DockerCleanupJob to handle nullable usageBefore property +- Server status job and docker cleanup job +- Update DockerCleanupJob to use server settings for force cleanup +- Update DockerCleanupJob to use server settings for force cleanup +- Disable health check for Rust applications during deployment + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.315 +- Update version to 4.0.0-beta.316 +- Update bug report template +- Update repository form with simplified URL input field +- Update width of container in general.blade.php +- Update checkbox labels in general.blade.php +- Update general page of apps +- Handle JSON parsing errors in format_docker_command_output_to_json +- Update Traefik image version to v2.11 +- Update version to 4.0.0-beta.317 +- Update version to 4.0.0-beta.318 +- Update helper message with link to documentation +- Disable health check by default +- Remove commented out code for sending internal notification + +### ◀️ Revert + +- Pull policy +- Advanced dropdown + +## [4.0.0-beta.308] - 2024-07-11 + +### 🚀 Features + +- Cleanup unused docker networks from proxy +- Compose parser v2 +- Display time interval for rollback images +- Add security and storage access key env to twenty template +- Add new logo for Latitude +- Enable legacy model binding in Livewire configuration + +### 🐛 Bug Fixes + +- Do not overwrite hardcoded variables if they rely on another variable +- Remove networks when deleting a docker compose based app +- Api +- Always set project name during app deployments +- Remove volumes as well +- Gitea pr previews +- Prevent instance fqdn persisting to other servers dynamic proxy configs +- Better volume cleanups +- Cleanup parameter +- Update redirect URL in unauthenticated exception handler +- Respect top-level configs and secrets +- Service status changed event +- Disable sentinel until a few bugs are fixed +- Service domains and envs are properly updated +- *(reactive-resume)* New healthcheck command for MinIO +- *(MinIO)* New command healthcheck +- Update minio hc in services +- Add validation for missing docker compose file + +### 🚜 Refactor + +- Add force parameter to StartProxy handle method +- Comment out unused code for network cleanup +- Reset default labels when docker_compose_domains is modified +- Webhooks view +- Tags view +- Only get instanceSettings once from db +- Update Dockerfile to set CI environment variable to true +- Remove unnecessary code in AppServiceProvider.php +- Update Livewire configuration views +- Update Webhooks.php to use nullable type for webhook URLs +- Add lazy loading to tags in Livewire configuration view +- Update metrics.blade.php to improve alert message clarity +- Update version numbers to 4.0.0-beta.312 +- Update version numbers to 4.0.0-beta.314 + +### ⚙️ Miscellaneous Tasks + +- Update Plausible docker compose template to Plausible 2.1.0 +- Update Plausible docker compose template to Plausible 2.1.0 +- Update livewire/livewire dependency to version 3.4.9 +- Refactor checkIfDomainIsAlreadyUsed function +- Update storage.blade.php view for livewire project service +- Update version to 4.0.0-beta.310 +- Update composer dependencies +- Add new logo for Latitude +- Bump version to 4.0.0-beta.311 + +### ◀️ Revert + +- Instancesettings + +## [4.0.0-beta.301] - 2024-06-24 + +### 🚀 Features + +- Local fonts +- More API endpoints +- Bulk env update api endpoint +- Update server settings metrics history days to 7 +- New app API endpoint +- Private gh deployments through api +- Lots of api endpoints +- Api api api api api api +- Rename CloudCleanupSubs to CloudCleanupSubscriptions +- Early fraud warning webhook +- Improve internal notification message for early fraud warning webhook +- Add schema for uuid property in app update response + +### 🐛 Bug Fixes + +- Run user commands on high prio queue +- Load js locally +- Remove lemon + paddle things +- Run container commands on high priority +- Image logo +- Remove both option for api endpoints. it just makes things complicated +- Cleanup subs in cloud +- Show keydbs/dragonflies/clickhouses +- Only run cloud clean on cloud + remove root team +- Force cleanup on busy servers +- Check domain on new app via api +- Custom container name will be the container name, not just internal network name +- Api updates +- Yaml everywhere +- Add newline character to private key before saving +- Add validation for webhook endpoint selection +- Database input validators +- Remove own app from domain checks +- Return data of app update + +### 💼 Other + +- Update process +- Glances service +- Glances +- Able to update application + +### 🚜 Refactor + +- Update Service model's saveComposeConfigs method +- Add default environment to Service model's saveComposeConfigs method +- Improve handling of default environment in Service model's saveComposeConfigs method +- Remove commented out code in Service model's saveComposeConfigs method +- Update stack-form.blade.php to include wire:target attribute for submit button +- Update code to use str() instead of Str::of() for string manipulation +- Improve formatting and readability of source.blade.php +- Add is_build_time property to nixpacks_php_fallback_path and nixpacks_php_root_dir +- Simplify code for retrieving subscription in Stripe webhook + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.302 +- Update version to 4.0.0-beta.303 +- Update version to 4.0.0-beta.305 +- Update version to 4.0.0-beta.306 +- Add log1x/laravel-webfonts package +- Update version to 4.0.0-beta.307 +- Refactor ServerStatusJob constructor formatting +- Update Monaco Editor for Docker Compose and Proxy Configuration +- More details +- Refactor shared.php helper functions + +## [4.0.0-beta.298] - 2024-06-24 + +### 🚀 Features + +- Spanish translation +- Cancelling a deployment will check if new could be started. +- Add supaguide logo to donations section +- Nixpacks now could reach local dbs internally +- Add Tigris logo to other/logos directory +- COOLIFY_CONTAINER_NAME predefined variable +- Charts +- Sentinel + charts +- Container metrics +- Add high priority queue +- Add metrics warning for servers without Sentinel enabled +- Add blacksmith logo to donations section +- Preselect server and destination if only one found +- More api endpoints +- Add API endpoint to update application by UUID +- Update statusnook logo filename in compose template + +### 🐛 Bug Fixes + +- Stripprefix middleware correctly labeled to http +- Bitbucket link +- Compose generator +- Do no truncate repositories wtih domain (git) in it +- In services should edit compose file for volumes and envs +- Handle laravel deployment better +- Db proxy status shown better in the UI +- Show commit message on webhooks + prs +- Metrics parsing +- Charts +- Application custom labels reset after saving +- Static build with new nixpacks build process +- Make server charts one livewire component with one interval selector +- You can now add env variable from ui to services +- Update compose environment with UI defined variables +- Refresh deployable compose without reload +- Remove cloud stripe notifications +- App deployment should be in high queue +- Remove zoom from modals +- Get envs before sortby +- MB is % lol +- Projects with 0 envs + +### 💼 Other + +- Unnecessary notification + +### 🚜 Refactor + +- Update text color for stderr output in deployment show view +- Update text color for stderr output in deployment show view +- Remove debug code for saving environment variables +- Update Docker build commands for better performance and flexibility +- Update image sizes and add new logos to README.md +- Update README.md with new logos and fix styling +- Update shared.php to use correct key for retrieving sentinel version +- Update container name assignment in Application model +- Remove commented code for docker container removal +- Update Application model to include getDomainsByUuid method +- Update Project/Show component to sort environments by created_at +- Update profile index view to display 2FA QR code in a centered container +- Update dashboard.blade.php to use project's default environment for redirection +- Update gitCommitLink method to handle null values in source.html_url +- Update docker-compose generation to use multi-line literal block + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.298 +- Switch to database sessions from redis +- Update dependencies and remove unused code +- Update tailwindcss and vue versions in package.json +- Update service template URL in constants.php +- Update sentinel version to 0.0.8 +- Update chart styling and loading text +- Update sentinel version to 0.0.9 +- Update Spanish translation for failed authentication messages +- Add portuguese traslation +- Add Turkish translations +- Add Vietnamese translate +- Add Treive logo to donations section +- Update README.md with latest release version badge +- Update latest release version badge in README.md +- Update version to 4.0.0-beta.299 +- Move server delete component to the bottom of the page +- Update version to 4.0.0-beta.301 + +## [4.0.0-beta.297] - 2024-06-11 + +### 🚀 Features + +- Easily redirect between www-and-non-www domains +- Add logos for new sponsors +- Add homepage template +- Update homepage.yaml with environment variables and volumes + +### 🐛 Bug Fixes + +- Multiline build args +- Setup script doesnt link to the correct source code file +- Install.sh do not reinstall packages on arch +- Just restart + +### 🚜 Refactor + +- Replaces duplications in code with a single function + +### ⚙️ Miscellaneous Tasks + +- Update page title in resource index view +- Update logo file path in logto.yaml +- Update logo file path in logto.yaml +- Remove commented out code for docker container removal +- Add isAnyDeploymentInprogress function to check if any deployments are in progress +- Add ApplicationDeploymentJob and pint.json + +## [4.0.0-beta.295] - 2024-06-10 + +### 🚀 Features + +- Able to change database passwords on the UI. It won't sync to the database. +- Able to add several domains to compose based previews +- Add bounty program link to bug report template +- Add titles +- Db proxy logs + +### 🐛 Bug Fixes + +- Custom docker compose commands, add project dir if needed +- Autoupdate process +- Backup executions view +- Handle previously defined compose previews +- Sort backup executions +- Supabase service, newest versions +- Set default name for Docker volumes if it is null +- Multiline variable should be literal + should be multiline in bash with \ +- Gitlab merge request should close PR + +### 💼 Other + +- Rocketchat +- New services based git apps + +### 🚜 Refactor + +- Append utm_source parameter to documentation URL +- Update save_environment_variables method to use application's environment_variables instead of environment_variables_preview +- Update deployment previews heading to "Deployments" +- Remove unused variables and improve code readability +- Initialize null properties in Github Change component +- Improve pre and post deployment command inputs +- Improve handling of Docker volumes in parseDockerComposeFile function + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.295 +- Update supported OS list with almalinux +- Update install.sh to support PopOS +- Update install.sh script to version 1.3.2 and handle Linux Mint as Ubuntu + +## [4.0.0-beta.294] - 2024-06-04 + +### ⚙️ Miscellaneous Tasks + +- Update Dockerfile with latest versions of Docker, Docker Compose, Docker Buildx, Pack, and Nixpacks + +## [4.0.0-beta.289] - 2024-05-29 + +### 🚀 Features + +- Add PHP memory limit environment variable to docker-compose.prod.yml +- Add manual update option to UpdateCoolify handle method +- Add port configuration for Vaultwarden service + +### 🐛 Bug Fixes + +- Sync upgrade process +- Publish horizon +- Add missing team model +- Test new upgrade process? +- Throw exception +- Build server dirs not created on main server +- Compose load with non-root user +- Able to redeploy dockerfile based apps without cache +- Compose previews does have env variables +- Fine-tune cdn pulls +- Spamming :D +- Parse docker version better +- Compose issues +- SERVICE_FQDN has source port in it +- Logto service +- Allow invitations via email +- Sort by defined order + fixed typo +- Only ignore volumes with driver_opts +- Check env in args for compose based apps + +### 🚜 Refactor + +- Update destination.blade.php to add group class for better styling +- Applicationdeploymentjob +- Improve code structure in ApplicationDeploymentJob.php +- Remove unnecessary debug statement in ApplicationDeploymentJob.php +- Remove unnecessary debug statements and improve code structure in RunRemoteProcess.php and ApplicationDeploymentJob.php +- Remove unnecessary logging statements from UpdateCoolify +- Update storage form inputs in show.blade.php +- Improve Docker Compose parsing for services +- Remove unnecessary port appending in updateCompose function +- Remove unnecessary form class in profile index.blade.php +- Update form layout in invite-link.blade.php +- Add log entry when starting new application deployment +- Improve Docker Compose parsing for services +- Update Docker Compose parsing for services +- Update slogan in shlink.yaml +- Improve display of deployment time in index.blade.php +- Remove commented out code for clearing Ray logs +- Update save_environment_variables method to use application's environment_variables instead of environment_variables_preview + +### ⚙️ Miscellaneous Tasks + +- Update for version 289 +- Fix formatting issue in deployment index.blade.php file +- Remove unnecessary wire:navigate attribute in breadcrumbs.blade.php +- Rename docker dirs +- Update laravel/socialite to version v5.14.0 and livewire/livewire to version 3.4.9 +- Update modal styles for better user experience +- Update deployment index.blade.php script for better performance +- Update version numbers to 4.0.0-beta.290 +- Update version numbers to 4.0.0-beta.291 +- Update version numbers to 4.0.0-beta.292 +- Update version numbers to 4.0.0-beta.293 +- Add upgrade guide link to upgrade.blade.php +- Improve upgrade.blade.php with clearer instructions and formatting +- Update version numbers to 4.0.0-beta.294 +- Add Lightspeed.run as a sponsor +- Update Dockerfile to install vim + +## [4.0.0-beta.288] - 2024-05-28 + +### 🐛 Bug Fixes + +- Do not allow service storage mount point modifications +- Volume adding + +### ⚙️ Miscellaneous Tasks + +- Update Sentry release version to 4.0.0-beta.288 + +## [4.0.0-beta.287] - 2024-05-27 + +### 🚀 Features + +- Handle incomplete expired subscriptions in Stripe webhook +- Add more persistent storage types + +### 🐛 Bug Fixes + +- Force load services from cdn on reload list + +### ⚙️ Miscellaneous Tasks + +- Update Sentry release version to 4.0.0-beta.287 +- Add Thompson Edolo as a sponsor +- Add null checks for team in Stripe webhook + +## [4.0.0-beta.286] - 2024-05-27 + +### 🚀 Features + +- If the time seems too long it remains at 0s +- Improve Docker Engine start logic in ServerStatusJob +- If proxy stopped manually, it won't start back again +- Exclude_from_hc magic +- Gitea manual webhooks +- Add container logs in case the container does not start healthy + +### 🐛 Bug Fixes + +- Wrong time during a failed deployment +- Removal of the failed deployment condition, addition of since started instead of finished time +- Use local versions + service templates and query them every 10 minutes +- Check proxy functionality before removing unnecessary coolify.yaml file and checking Docker Engine +- Show first 20 users only in admin view +- Add subpath for services +- Ghost subdir +- Do not pull templates in dev +- Templates +- Update error message for invalid token to mention invalid signature +- Disable containerStopped job for now +- Disable unreachable/revived notifications for now +- JSON_UNESCAPED_UNICODE +- Add wget to nixpacks builds +- Pre and post deployment commands +- Bitbucket commits link +- Better way to add curl/wget to nixpacks +- Root team able to download backups +- Build server should not have a proxy +- Improve build server functionalities +- Sentry issue +- Sentry +- Sentry error + livewire downgrade +- Sentry +- Sentry +- Sentry error +- Sentry + +### 🚜 Refactor + +- Update edit-domain form in project service view +- Add Huly services to compose file +- Remove redundant heading in backup settings page +- Add isBuildServer method to Server model +- Update docker network creation in ApplicationDeploymentJob + +### ⚙️ Miscellaneous Tasks + +- Change pre and post deployment command length in applications table +- Refactor container name logic in GetContainersStatus.php and ForcePasswordReset.php +- Remove unnecessary content from Docker Compose file + +## [4.0.0-beta.285] - 2024-05-21 + +### 🚀 Features + +- Add SerpAPI as a Github Sponsor +- Admin view for deleting users +- Scheduled task failed notification + +### 🐛 Bug Fixes + +- Optimize new resource creation +- Show it docker compose has syntax errors + +### 💼 Other + +- Responsive here and there + +## [4.0.0-beta.284] - 2024-05-19 + +### 🚀 Features + +- Add hc logs to healthchecks + +### ◀️ Revert + +- Hc return code check + +## [4.0.0-beta.283] - 2024-05-17 + +### 🚀 Features + +- Update healthcheck test in StartMongodb action +- Add pull_request_id filter to get_last_successful_deployment method in Application model + +### 🐛 Bug Fixes + +- PR deployments have good predefined envs + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.283 + +## [4.0.0-beta.281] - 2024-05-17 + +### 🚀 Features + +- Shows the latest deployment commit + message on status +- New manual update process + remove next_channel +- Add lastDeploymentInfo and lastDeploymentLink props to breadcrumbs and status components +- Sort envs alphabetically and creation date +- Improve sorting of environment variables in the All component + +### 🐛 Bug Fixes + +- Hc from localhost to 127.0.0.1 +- Use rc in hc +- Telegram group chat notifications + +## [4.0.0-beta.280] - 2024-05-16 + +### 🐛 Bug Fixes + +- Commit message length + +## [4.0.0-beta.279] - 2024-05-16 + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.279 +- Limit commit message length to 50 characters in ApplicationDeploymentJob + +## [4.0.0-beta.278] - 2024-05-16 + +### 🚀 Features + +- Adding new COOLIFY_ variables +- Save commit message and better view on deployments +- Toggle label escaping mechanism + +### 🐛 Bug Fixes + +- Use commit hash on webhooks + +### ⚙️ Miscellaneous Tasks + +- Refactor Service.php to handle missing admin user in extraFields() method +- Update twenty CRM template with environment variables and dependencies +- Refactor applications.php to remove unused imports and improve code readability +- Refactor deployment index.blade.php for improved readability and rollback handling +- Refactor GitHub app selection UI in project creation form +- Update ServerLimitCheckJob.php to handle missing serverLimit value +- Remove unnecessary code for saving commit message +- Update DOCKER_VERSION to 26.0 in install.sh script +- Update Docker and Docker Compose versions in Dockerfiles + +## [4.0.0-beta.277] - 2024-05-10 + +### 🚀 Features + +- Add AdminRemoveUser command to remove users from the database + +### 🐛 Bug Fixes + +- Color for resource operation server and project name +- Only show realtime error on non-cloud instances +- Only allow push and mr gitlab events +- Improve scheduled task adding/removing +- Docker compose dependencies for pr previews +- Properly populating dependencies + +### 💼 Other + +- Fix a few boxes here and there + +### ⚙️ Miscellaneous Tasks + +- Update version numbers to 4.0.0-beta.278 +- Update hover behavior and cursor style in scheduled task executions view +- Refactor scheduled task view to improve code readability and maintainability +- Skip scheduled tasks if application or service is not running +- Remove debug logging statements in Kernel.php +- Handle invalid cron strings in Kernel.php + +## [4.0.0-beta.275] - 2024-05-06 + +### 🚀 Features + +- Add container name to network aliases in ApplicationDeploymentJob +- Add lazy loading for images in General.php and improve Docker Compose file handling in Application.php +- Experimental sentinel +- Start Sentinel on servers. +- Pull new sentinel image and restart container +- Init metrics + +### 🐛 Bug Fixes + +- Typo in tags.blade.php +- Install.sh error +- Env file +- Comment out internal notification in email_verify method +- Confirmation for custom labels +- Change permissions on newly created dirs + +### 💼 Other + +- Fix tag view + +### 🚜 Refactor + +- Add SCHEDULER environment variable to StartSentinel.php + +### ⚙️ Miscellaneous Tasks + +- Dark mode should be the default +- Improve menu item styling and spacing in service configuration and index views +- Improve menu item styling and spacing in service configuration and index views +- Improve menu item styling and spacing in project index and show views +- Remove docker compose versions +- Add Listmonk service template and logo +- Refactor GetContainersStatus.php for improved readability and maintainability +- Refactor ApplicationDeploymentJob.php for improved readability and maintainability +- Add metrics and logs directories to installation script +- Update sentinel version to 0.0.2 in versions.json +- Update permissions on metrics and logs directories +- Comment out server sentinel check in ServerStatusJob + +## [4.0.0-beta.273] - 2024-05-03 + +### 🐛 Bug Fixes + +- Formbricks image origin +- Add port even if traefik is used + +### ⚙️ Miscellaneous Tasks + +- Update version to 4.0.0-beta.275 +- Update DNS server validation helper text + +## [4.0.0-beta.267] - 2024-04-26 + +### 🚀 Features + +- Initial datalist +- Update service contribution docs URL +- The final pricing plan, pay-as-you-go + +### 🐛 Bug Fixes + +- Move s3 storages to separate view +- Mongo db backup +- Backups +- Autoupdate +- Respect start period and chekc interval for hc +- Parse HEALTHCHECK from dockerfile +- Make s3 name and endpoint required +- Able to update source path for predefined volumes +- Get logs with non-root user +- Mongo 4.0 db backup + +### 💼 Other + +- Update resource operations view + +### ◀️ Revert + +- Variable parsing + +## [4.0.0-beta.266] - 2024-04-24 + +### 🐛 Bug Fixes + +- Refresh public ips on start + +## [4.0.0-beta.259] - 2024-04-17 + +### 🚀 Features + +- Literal env variables +- Lazy load stuffs + tell user if compose based deployments have missing envs +- Can edit file/dir volumes from ui in compose based apps +- Upgrade Appwrite service template to 1.5 +- Upgrade Appwrite service template to 1.5 +- Add db name to backup notifications + +### 🐛 Bug Fixes + +- Helper image only pulled if required, not every 10 mins +- Make sure that confs when checking if it is changed sorted +- Respect .env file (for default values) +- Remove temporary cloudflared config +- Remove lazy loading until bug figured out +- Rollback feature +- Base64 encode .env +- $ in labels escaped +- .env saved to deployment server, not to build server +- Do no able to delete gh app without deleting resources +- 500 error on edge case +- Able to select server when creating new destination +- N8n template + +### 💼 Other + +- Non-root user for remote servers +- Non-root + +## [4.0.0-beta.258] - 2024-04-12 + +### 🚀 Features + +- Dynamic mux time + +### 🐛 Bug Fixes + +- Check each required binaries one-by-one + +## [4.0.0-beta.256] - 2024-04-12 + +### 🚀 Features + +- Upload large backups +- Edit domains easier for compose +- Able to delete configuration from server +- Configuration checker for all resources +- Allow tab in textarea + +### 🐛 Bug Fixes + +- Service config hash update +- Redeploy if image not found in restart only mode + +### 💼 Other + +- New pricing +- Fix allowTab logic +- Use 2 space instead of tab + +## [4.0.0-beta.252] - 2024-04-09 + +### 🚀 Features + +- Add amazon linux 2023 + +### 🐛 Bug Fixes + +- Git submodule update +- Unintended left padding on sidebar +- Hashed random delimeter in ssh commands + make sure to remove the delimeter from the command + +## [4.0.0-beta.250] - 2024-04-05 + +### 🚀 Features + +- *(application)* Update submodules after git checkout + +## [4.0.0-beta.249] - 2024-04-03 + +### 🚀 Features + +- Able to make rsa/ed ssh keys + +### 🐛 Bug Fixes + +- Warning if you use multiple domains for a service +- New github app creation +- Always rebuild Dockerfile / dockerimage buildpacks +- Do not rebuild dockerfile based apps twice +- Make sure if envs are changed, rebuild is needed +- Members cannot manage subscriptions +- IsMember +- Storage layout +- How to update docker-compose, environment variables and fqdns + +### 💼 Other + +- Light buttons +- Multiple server view + +## [4.0.0-beta.242] - 2024-03-25 + +### 🚀 Features + +- Change page width +- Watch paths + +### 🐛 Bug Fixes + +- Compose env has SERVICE, but not defined for Coolify +- Public service database +- Make sure service db proxy restarted +- Restart service db proxies +- Two factor +- Ui for tags +- Update resources view +- Realtime connection check +- Multline env in dev mode +- Scheduled backup for other service databases (supabase) +- PR deployments should not be distributed to 2 servers +- Name/from address required for resend +- Autoupdater +- Async service loads +- Disabled inputs are not trucated +- Duplicated generated fqdns are now working +- Uis +- Ui for cftunnels +- Search services +- Trial users subscription page +- Async public key loading +- Unfunctional server should see resources + +### 💼 Other + +- Run cleanup every day +- Fix +- Fix log outputs +- Automatic cloudflare tunnels +- Backup executions + +## [4.0.0-beta.241] - 2024-03-20 + +### 🚀 Features + +- Able to run scheduler/horizon programatically + +### 🐛 Bug Fixes + +- Volumes for prs +- Shared env variable parsing + +### 💼 Other + +- Redesign +- Redesign + +## [4.0.0-beta.240] - 2024-03-18 + +### 🐛 Bug Fixes + +- Empty get logs number of lines +- Only escape envs after v239+ +- 0 in env value +- Consistent container name +- Custom ip address should turn off rolling update +- Multiline input +- Raw compose deployment +- Dashboard view if no project found + +## [4.0.0-beta.239] - 2024-03-14 + +### 🐛 Bug Fixes + +- Duplicate dockerfile +- Multiline env variables +- Server stopped, service page not reachable + +## [4.0.0-beta.237] - 2024-03-14 + +### 🚀 Features + +- Domains api endpoint +- Resources api endpoint +- Team api endpoint +- Add deployment details to deploy endpoint +- Add deployments api +- Experimental caddy support +- Dynamic configuration for caddy +- Reset password +- Show resources on source page + +### 🐛 Bug Fixes + +- Deploy api messages +- Fqdn null in case docker compose bp +- Reload caddy issue +- /realtime endpoint +- Proxy switch +- Service ports for services + caddy +- Failed deployments should send failed email/notification +- Consider custom healthchecks in dockerfile +- Create initial files async +- Docker compose validation + +## [4.0.0-beta.235] - 2024-03-05 + +### 🐛 Bug Fixes + +- Should note delete personal teams +- Make sure to show some buttons +- Sort repositories by name + +## [4.0.0-beta.224] - 2024-02-23 + +### 🚀 Features + +- Custom server limit +- Delay container/server jobs +- Add static ipv4 ipv6 support +- Server disabled by overflow +- Preview deployment logs +- Collect webhooks during maintenance +- Logs and execute commands with several servers + +### 🐛 Bug Fixes + +- Subscription / plan switch, etc +- Firefly service +- Force enable/disable server in case ultimate package quantity decreases +- Server disabled +- Custom dockerfile location always checked +- Import to mysql and mariadb +- Resource tab not loading if server is not reachable +- Load unmanaged async +- Do not show n/a networsk +- Service container status updates +- Public prs should not be commented +- Pull request deployments + build servers +- Env value generation +- Sentry error +- Service status updated + +### 💼 Other + +- Change + icon to hamburger. + +## [4.0.0-beta.222] - 2024-02-22 + +### 🚀 Features + +- Able to add dynamic configurations from proxy dashboard + +### 🐛 Bug Fixes + +- Connections being stuck and not processed until proxy restarts +- Use latest image if nothing is specified +- No coolify.yaml found +- Server validation +- Statuses +- Unknown image of service until it is uploaded + +## [4.0.0-beta.220] - 2024-02-19 + +### 🚀 Features + +- Save github app permission locally +- Minversion for services + +### 🐛 Bug Fixes + +- Add openbsd ssh server check +- Resources +- Empty build variables +- *(server)* Revalidate server button not showing in server's page +- Fluent bit ident level +- Submodule cloning +- Database status +- Permission change updates from webhook +- Server validation + +### 💼 Other + +- Updates + +## [4.0.0-beta.213] - 2024-02-12 + +### 🚀 Features + +- Magic for traefik redirectregex in services +- Revalidate server +- Disable gzip compression on service applications + +### 🐛 Bug Fixes + +- Cleanup scheduled tasks +- Padding left on input boxes +- Use ls / command instead ls +- Do not add the same server twice +- Only show redeployment required if status is not exited + +## [4.0.0-beta.212] - 2024-02-08 + +### 🚀 Features + +- Cleanup queue + +### 🐛 Bug Fixes + +- New menu on navbar +- Make sure resources are deleted in async mode +- Go to prod env from dashboard if there is no other envs defined +- User proper image_tag, if set +- New menu ui +- Lock logdrain configuration when one of them are enabled +- Add docker compose check during server validation +- Get service stack as uuid, not name +- Menu +- Flex wrap deployment previews +- Boolean docker options +- Only add 'networks' key if 'network_mode' is absent + +## [4.0.0-beta.206] - 2024-02-05 + +### 🚀 Features + +- Clone to env +- Multi deployments + +### 🐛 Bug Fixes + +- Wrap tags and avoid horizontal overflow +- Stripe webhooks +- Feedback from self-hosted envs to discord + +### 💼 Other + +- Specific about newrelic logdrains + +## [4.0.0-beta.201] - 2024-01-29 + +### 🚀 Features + +- Added manual webhook support for bitbucket +- Add initial support for custom docker run commands +- Cleanup unreachable servers +- Tags and tag deploy webhooks + +### 🐛 Bug Fixes + +- Bitbucket manual deployments +- Webhooks for multiple apps +- Unhealthy deployments should be failed +- Add env variables for wordpress template without database +- Service deletion function +- Service deletion fix +- Dns validation + duplicated fqdns +- Validate server navbar upated +- Regenerate labels on application clone +- Service deletion +- Not able to use other shared envs +- Sentry fix +- Sentry +- Sentry error +- Sentry +- Sentry error +- Create dynamic directory +- Migrate to new modal +- Duplicate domain check +- Tags + +### 💼 Other + +- New modal component + +## [4.0.0-beta.188] - 2024-01-11 + +### 🚀 Features + +- Search between resources +- Move resources between projects / environments +- Clone any resource +- Shared environments +- Concurrent builds / server +- Able to deploy multiple resources with webhook +- Add PR comments +- Dashboard live deployment view + +### 🐛 Bug Fixes + +- Preview deployments with nixpacks +- Cleanup docker stuffs before upgrading +- Service deletion command +- Cpuset limits was determined in a way that apps only used 1 CPU max, ehh, sorry. +- Service stack view +- Change proxy view +- Checkbox click +- Git pull command for deploy key based previews +- Server status job +- Service deletion bug! +- Links +- Redis custom conf +- Sentry error +- Restrict concurrent deployments per server +- Queue +- Change env variable length + +### 💼 Other + +- Send notification email if payment + +### 🚜 Refactor + +- Compose file and install script + +## [4.0.0-beta.186] - 2024-01-11 + +### 🚀 Features + +- Import backups + +### 🐛 Bug Fixes + +- Do not include thegameplan.json into build image +- Submit error on postgresql +- Email verification / forgot password +- Escape build envs properly for nixpacks + docker build +- Undead endpoint +- Upload limit on ui +- Save cmd output propely (merge) +- Load profile on remote commands +- Load profile and set envs on remote cmd +- Restart should not update config hash + +## [4.0.0-beta.184] - 2024-01-09 + +### 🐛 Bug Fixes + +- Healthy status +- Show framework based notification in build logs +- Traefik labels +- Use ip for sslip in dev if remote server is used +- Service labels without ports (unknown ports) +- Sort and rename (unique part) of labels +- Settings menu +- Remove traefik debug in dev mode +- Php pgsql to 8.2 +- Static buildpack should set port 80 +- Update navbar on build_pack change + +## [4.0.0-beta.183] - 2024-01-06 + +### 🚀 Features + +- Add www-non-www redirects to traefik + +### 🐛 Bug Fixes + +- Database env variables + +## [4.0.0-beta.182] - 2024-01-04 + +### 🐛 Bug Fixes + +- File storage save + +## [4.0.0-beta.181] - 2024-01-03 + +### 🐛 Bug Fixes + +- Nixpacks buildpack + +## [4.0.0-beta.180] - 2024-01-03 + +### 🐛 Bug Fixes + +- Nixpacks cache +- Only add restart policy if its empty (compose) + +## [4.0.0-beta.179] - 2024-01-02 + +### 🐛 Bug Fixes + +- Set deployment failed if new container is not healthy + +## [4.0.0-beta.177] - 2024-01-02 + +### 🚀 Features + +- Raw docker compose deployments + +### 🐛 Bug Fixes + +- Duplicate compose variable + +## [4.0.0-beta.176] - 2023-12-31 + +### 🐛 Bug Fixes + +- Horizon + +## [4.0.0-beta.175] - 2023-12-30 + +### 🚀 Features + +- Add environment description + able to change name + +### 🐛 Bug Fixes + +- Sub +- Wrong env variable parsing +- Deploy key + docker compose + +## [4.0.0-beta.174] - 2023-12-27 + +### 🐛 Bug Fixes + +- Restore falsely deleted coolify-db-backup + +## [4.0.0-beta.173] - 2023-12-27 + +### 🐛 Bug Fixes + +- Cpu limit to float from int +- Add source commit to final envs +- Routing, switch back to old one +- Deploy instead of restart in case swarm is used +- Button title + +## [4.0.0-beta.163] - 2023-12-15 + +### 🚀 Features + +- Custom docker compose commands + +### 🐛 Bug Fixes + +- Domains for compose bp +- No action in webhooks +- Add debug output to gitlab webhooks +- Do not push dockerimage +- Add alpha to swarm +- Server not found +- Do not autovalidate server on mount +- Server update schedule +- Swarm support ui +- Server ready +- Get swarm service logs +- Docker compose apps env rewritten +- Storage error on dbs +- Why?! +- Stay tuned + +### 💼 Other + +- Swarm +- Swarm + +## [4.0.0-beta.155] - 2023-12-11 + +### 🚀 Features + +- Autoupdate env during seed +- Disable autoupdate +- Randomly sleep between executions +- Pull latest images for services + +### 🐛 Bug Fixes + +- Do not send telegram noti on intent payment failed +- Database ui is realtime based +- Live mode for github webhooks +- Ui +- Realtime connection popup could be disabled +- Realtime check +- Add new destination +- Proxy logs +- Db status check +- Pusher host +- Add ipv6 +- Realtime connection?! +- Websocket +- Better handling of errors with install script +- Install script parse version +- Only allow to modify in .env file if AUTOUPDATE is set +- Is autoupdate not null +- Run init command after production seeder +- Init +- Comma in traefik custom labels +- Ignore if dynamic config could not be set +- Service env variable ovewritten if it has a default value +- Labelling +- Non-ascii chars in labels +- Labels +- Init script echos +- Update Coolify script +- Null notify +- Check queued deployments as well +- Copy invitation +- Password reset / invitation link requests +- Add catch all route +- Revert random container job delay +- Backup executions view +- Only check server status in container status job +- Improve server status check times +- Handle other types of generated values +- Server checking status +- Ui for adding new destination +- Reset domains on compose file change + +### 💼 Other + +- Fix for comma in labels +- Add image name to service stack + better options visibility + +### 🚜 Refactor + +- Service logs are now on one page +- Application status changed realtime +- Custom labels +- Clone project + +## [4.0.0-beta.154] - 2023-12-07 + +### 🚀 Features + +- Execute command in container + +### 🐛 Bug Fixes + +- Container selection +- Service navbar using new realtime events +- Do not create duplicated networks +- Live event +- Service start + event +- Service deletion job +- Double ws connection +- Boarding view + +### 💼 Other + +- Env vars +- Migrate to livewire 3 + +## [4.0.0-beta.124] - 2023-11-13 + +### 🚀 Features + +- Log drain (wip) +- Enable/disable log drain by service +- Log drainer container check +- Add docker engine support install script to rhel based systems +- Save timestamp configuration for logs +- Custom log drain endpoints +- Auto-restart tcp proxies for databases + +### 🐛 Bug Fixes + +- *(fider template)* Use the correct docs url +- Fqdn for minio +- Generate service fields +- Mariadb backups +- When to pull image +- Do not allow to enter local ip addresses +- Reset password +- Only report nonruntime errors +- Handle different label formats in services +- Server adding process +- Show defined resources in server tab, so you will know what you need to delete before you can delete the server. +- Lots of regarding git + docker compose deployments +- Pull request build variables +- Double default password length +- Do not remove deployment in case compose based failed +- No container servers +- Sentry issue +- Dockercompose save ./ volumes under /data/coolify +- Server view for link() +- Default value do not overwrite existing env value +- Use official install script with rancher (one will work for sure) +- Add cf tunnel to boarding server view +- Prevent autorefresh of proxy status +- Missing docker image thing +- Add hc for soketi +- Deploy the right compose file +- Bind volumes for compose bp +- Use hc port 80 in case of static build +- Switching to static build + +### 💼 Other + +- New deployment jobs +- Compose based apps +- Swarm +- Swarm +- Swarm +- Swarm +- Disable trial +- Meilisearch +- Broadcast +- 🌮 + +### 🚜 Refactor + +- Env variable generator + +### ◀️ Revert + +- Wip + +## [4.0.0-beta.109] - 2023-11-06 + +### 🚀 Features + +- Deployment logs fullscreen +- Service database backups +- Make service databases public + +### 🐛 Bug Fixes + +- Missing environment variables prevewi on service +- Invoice.paid should sleep for 5 seconds +- Local dev repo +- Deployments ui +- Dockerfile build pack fix +- Set labels on generate domain +- Network service parse +- Notification url in containerstatusjob +- Gh webhook response 200 to installation_repositories +- Delete destination +- No id found +- Missing $mailMessage +- Set default from/sender names +- No environments +- Telegram text +- Private key not found error +- UI +- Resourcesdelete command +- Port number should be int +- Separate delete with validation of server +- Add nixpacks info +- Remove filter +- Container logs are now followable in full-screen and sorted by timestamp +- Ui for labels +- Ui +- Deletions +- Build_image not found +- Github source view +- Github source view +- Dockercleanupjob should be released back +- Ui +- Local ip address +- Revert workdir to basedir +- Container status jobs for old pr deployments +- Service updates + +## [4.0.0-beta.99] - 2023-10-24 + +### 🚀 Features + +- Improve deployment time by a lot + +### 🐛 Bug Fixes + +- Space in build args +- Lock SERVICE_FQDN envs +- If user is invited, that means its email is verified +- Force password reset on invited accounts +- Add ssh options to git ls-remote +- Git ls-remote +- Remove coolify labels from ui + +### 💼 Other + +- Fix subs + +## [4.0.0-beta.97] - 2023-10-20 + +### 🚀 Features + +- Standalone mongodb +- Cloning project +- Api tokens + deploy webhook +- Start all kinds of things +- Simple search functionality +- Mysql, mariadb +- Lock environment variables +- Download local backups + +### 🐛 Bug Fixes + +- Service docs links +- Add PGUSER to prevent HC warning +- Preselect s3 storage if available +- Port exposes change, shoud regenerate label +- Boarding +- Clone to with the same environment name +- Cleanup stucked resources on start +- Do not allow to delete env if a resource is defined +- Service template generator + appwrite +- Mongodb backup +- Make sure coolfiy network exists on install +- Syncbunny command +- Encrypt mongodb password +- Mongodb healtcheck command +- Rate limit for api + add mariadb + mysql +- Server settings guarded + +### 💼 Other + +- Generate services +- Mongodb backup +- Mongodb backup +- Updates + +## [4.0.0-beta.93] - 2023-10-18 + +### 🚀 Features + +- Able to customize docker labels on applications +- Show if config is not applied + +### 🐛 Bug Fixes + +- Setup:dev script & contribution guide +- Do not show configuration changed if config_hash is null +- Add config_hash if its null (old deployments) +- Label generation +- Labels +- Email channel no recepients +- Limit horizon processes to 2 by default +- Add custom port as ssh option to deploy_key based commands +- Remove custom port from git repo url +- ContainerStatus job + +### 💼 Other + +- PAT by team + +## [4.0.0-beta.92] - 2023-10-17 + +### 🐛 Bug Fixes + +- Proxy start process + +## [4.0.0-beta.91] - 2023-10-17 + +### 🐛 Bug Fixes + +- Always start proxy if not NONE is selected + +### 💼 Other + +- Add helper to service domains + +## [4.0.0-beta.90] - 2023-10-17 + +### 🐛 Bug Fixes + +- Only include config.json if its exists and a file + +### 💼 Other + +- Wordpress + +## [4.0.0-beta.89] - 2023-10-17 + +### 🐛 Bug Fixes + +- Noindex meta tag +- Show docker build logs + +## [4.0.0-beta.88] - 2023-10-17 + +### 🚀 Features + +- Use docker login credentials from server + +## [4.0.0-beta.87] - 2023-10-17 + +### 🐛 Bug Fixes + +- Service status check is a bit better +- Generate fqdn if you deleted a service app, but it requires fqdn +- Cancel any deployments + queue next +- Add internal domain names during build process + +## [4.0.0-beta.86] - 2023-10-15 + +### 🐛 Bug Fixes + +- Build image before starting dockerfile buildpacks + +## [4.0.0-beta.85] - 2023-10-14 + +### 🐛 Bug Fixes + +- Redis URL generated + +## [4.0.0-beta.83] - 2023-10-13 + +### 🐛 Bug Fixes + +- Docker hub URL + +## [4.0.0-beta.70] - 2023-10-09 + +### 🚀 Features + +- Add email verification for cloud +- Able to deploy docker images +- Add dockerfile location +- Proxy logs on the ui +- Add custom redis conf + +### 🐛 Bug Fixes + +- Server validation process +- Fqdn could be null +- Small +- Server unreachable count +- Do not reset unreachable count +- Contact docs +- Check connection +- Server saving +- No env goto envs from dashboard +- Goto +- Tcp proxy for dbs +- Database backups +- Only send email if transactional email set +- Backupfailed notification is forced +- Use port exposed for reverse proxy +- Contact link +- Use only ip addresses for servers +- Deleted team and it is the current one +- Add new team button +- Transactional email link +- Dashboard goto link +- Only require registry image in case of dockerimage bp +- Instant save build pack change +- Public git +- Cannot remove localhost +- Check localhost connection +- Send unreachable/revived notifications +- Boarding + verification +- Make sure proxy wont start in NONE mode +- Service check status 10 sec +- IsCloud in production seeder +- Make sure to use IP address +- Dockerfile location feature +- Server ip could be hostname in self-hosted +- Urls should be password fields +- No backup for redis +- Show database logs in case of its not healthy and running +- Proxy check for ports, do not kill anything listening on port 80/443 +- Traefik dashboard ip +- Db labels +- Docker cleanup jobs +- Timeout for instant remote processes +- Dev containerjobs +- Backup database one-by-one. +- Turn off static deployment if you switch buildpacks + +### 💼 Other + +- Dockerimage +- Updated dashboard +- Fix +- Fix +- Coolify proxy access logs exposed in dev +- Able to select environment on new resource +- Delete server +- Redis + +## [4.0.0-beta.58] - 2023-10-02 + +### 🚀 Features + +- Reset root password +- Attach Coolify defined networks to services +- Delete resource command +- Multiselect removable resources +- Disable service, required version +- Basedir / monorepo initial support +- Init version of any git deployment +- Deploy private repo with ssh key + +### 🐛 Bug Fixes + +- If waitlist is disabled, redirect to register +- Add destination to new services +- Predefined content for files +- Move /data to ./_data in dev +- UI +- Show all storages in one place for services +- Ui +- Add _data to vite ignore +- Only use _ in volume names for services +- Volume names in services +- Volume names +- Service logs visible if the whole service stack is not running +- Ui +- Compose magic +- Compose parser updated +- Dev compose files +- Traefik labels for multiport deployments +- Visible version number +- Remove SERVICE_ from deployable compose +- Delete event to deleting +- Move dev data to volumes to prevent permission issues +- Traefik labelling in case of several http and https domain added +- PR deployments use the first fqdn as base +- Email notifications subscription fixed +- Services - do not remove unnecessary things for now +- Decrease max horizon processes to get lower memory usage +- Test emails only available for user owned smtp/resend +- Ui for self-hosted email settings +- Set smtp notifications on by default +- Select branch on other git +- Private repository +- Contribution guide +- Public repository names +- *(create)* Flex wrap on server & network selection +- Better unreachable/revived server statuses +- Able to set base dir for Dockerfile build pack + +### 💼 Other + +- Uptime kume hc updated +- Switch back to /data (volume errors) +- Notifications +- Add shared email option to everyone + +## [4.0.0-beta.57] - 2023-10-02 + +### 🚀 Features + +- Container logs + +### 🐛 Bug Fixes + +- Always pull helper image in dev +- Only show last 1000 lines +- Service status + +## [4.0.0-beta.47] - 2023-09-28 + +### 🐛 Bug Fixes + +- Next helper image +- Service templates +- Sync:bunny +- Update process if server has been renamed +- Reporting handler +- Localhost privatekey update +- Remove private key in case you removed a github app +- Only show manually added private keys on server view +- Show source on all type of applications +- Docker cleanup should be a job by server +- File/dir based volumes are now read from the server +- Respect server fqdn +- If public repository does not have a main branch +- Preselect branc on private repos +- Deploykey branch +- Backups are now working again +- Not found base_branch in git webhooks +- Coolify db backup +- Preview deployments name, status etc +- Services should have destination as well +- Dockerfile expose is not overwritten +- If app settings is not saved to db +- Do not show subscription cancelled noti +- Show real volume names +- Only parse expose in dockerfiles if ports_exposes is empty +- Add uuid to volume names +- New volumes for services should have - instead of _ + +### 💼 Other + +- Fix previews to preview + +## [4.0.0-beta.46] - 2023-09-28 + +### 🐛 Bug Fixes + +- Containerstatusjob +- Aaaaaaaaaaaaaaaaa +- Services view +- Services +- Manually create network for services +- Disable early updates +- Sslip for localhost +- ContainerStatusJob +- Cannot delete env with available services +- Sync command +- Install script drops an error +- Prevent sync version (it needs an option) +- Instance fqdn setting +- Sentry 4510197209 +- Sentry 4504136641 +- Sentry 4502634789 + +## [4.0.0-beta.45] - 2023-09-24 + +### 🚀 Features + +- Services +- Image tag for services + +### 🐛 Bug Fixes + +- Applications with port mappins do a normal update (not rolling update) +- Put back build pack chooser +- Proxy configuration + starter +- Show real storage name on services +- New service template layout + +### 💼 Other + +- Fixed z-index for version link. +- Add source button +- Fixed z-index for magicbar +- A bit better error +- More visible feedback button +- Update help modal +- Help +- Marketing emails + +## [4.0.0-beta.28] - 2023-09-08 + +### 🚀 Features + +- Telegram topics separation +- Developer view for env variables +- Cache team settings +- Generate public key from private keys +- Able to invite more people at once +- Trial +- Dynamic trial period +- Ssh-agent instead of filesystem based ssh keys +- New container status checks +- Generate ssh key +- Sentry add email for better support +- Healthcheck for apps +- Add cloudflare tunnel support + +### 🐛 Bug Fixes + +- Db backup job +- Sentry 4459819517 +- Sentry 4451028626 +- Ui +- Retry notifications +- Instance email settings +- Ui +- Test email on for admins or custom smtp +- Coolify already exists should not throw error +- Delete database related things when delete database +- Remove -q from docker compose +- Errors in views +- Only send internal notifcations to enabled channels +- Recovery code +- Email sending error +- Sentry 4469575117 +- Old docker version error +- Errors +- Proxy check, reduce jobs, etc +- Queue after commit +- Remove nixpkgarchive +- Remove nixpkgarchive from ui +- Webhooks should not run if server is not functional +- Server is functional check +- Confirm email before sending +- Help should send cc on email +- Sub type +- Show help modal everywhere +- Forgot password +- Disable dockerfile based healtcheck for now +- Add timeout for ssh commands +- Prevent weird ui bug for validateServer +- Lowercase email in forgot password +- Lower case email on waitlist +- Encrypt jobs +- ProcessWithEnv()->run +- Plus boarding step about Coolify +- SaveConfigurationSync +- Help uri +- Sub for root +- Redirect on server not found +- Ip check +- Uniqueips +- Simply reply to help messages +- Help +- Rate limit +- Collect billing address +- Invitation +- Smtp view +- Ssh-agent revert +- Restarting container state on ui +- Generate new key +- Missing upgrade js +- Team error +- 4.0.0-beta.37 +- Localhost +- Proxy start (if not proxy defined, use Traefik) +- Do not remove localhost in boarding +- Allow non ip address (DNS) +- InstallDocker id not found +- Boarding +- Errors +- Proxy container status +- Proxy configuration saving +- Convert startProxy to action +- Stop/start UI on apps and dbs +- Improve localhost boarding process +- Try to use old docker-compose +- Boarding again +- Send internal notifications of email errors +- Add github app change on new app view +- Delete environment variables on app/db delete +- Save proxy configuration +- Add proxy to network with periodic check +- Proxy connections +- Delete persistent storages on resource deletion +- Prevent overwrite already existing env variables in services +- Mappings +- Sentry issue 4478125289 +- Make sure proxy path created +- StartProxy +- Server validation with cf tunnels +- Only show traefik dashboard if its available +- Services +- Database schema +- Report livewire errors +- Links with path +- Add traefik labels no matter if traefik is selected or not +- Add expose port for containers +- Also check docker socks permission on validation + +### 💼 Other + +- User should know that the public key +- Services are not availble yet +- Show registered users on waitlist page +- Nixpacksarchive +- Add Plausible analytics +- Global env variables +- Fix +- Trial emails +- Server check instead of app check +- Show trial instead of sub +- Server lost connection +- Services +- Services +- Services +- Ui for services +- Services +- Services +- Services +- Fixes +- Fix typo + +## [4.0.0-beta.27] - 2023-09-08 + +### 🐛 Bug Fixes + +- Bug + +## [4.0.0-beta.26] - 2023-09-08 + +### 🚀 Features + +- Public database + +## [4.0.0-beta.25] - 2023-09-07 + +### 🐛 Bug Fixes + +- SaveModel email settings + +## [4.0.0-beta.24] - 2023-09-06 + +### 🚀 Features + +- Send request in cloud +- Add discord notifications + +### 🐛 Bug Fixes + +- Form address +- Show hosted email service, just disable for non pro subs +- Add navbar for source + keys +- Add docker network to build process +- Overlapping apps +- Do not show system wide git on cloud +- Lowercase image names +- Typo + +### 💼 Other + +- Backup existing database + +## [4.0.0-beta.23] - 2023-09-01 + +### 🐛 Bug Fixes + +- Sentry bug +- Button loading animation + +## [4.0.0-beta.22] - 2023-09-01 + +### 🚀 Features + +- Add resend as transactional emails + +### 🐛 Bug Fixes + +- DockerCleanupjob +- Validation +- Webhook endpoint in cloud and no system wide gh app +- Subscriptions +- Password confirmation +- Proxy start job +- Dockerimage jobs are not overlapping + +## [4.0.0-beta.21] - 2023-08-27 + +### 🚀 Features + +- Invite by email from waitlist +- Rolling update + +### 🐛 Bug Fixes + +- Limits & server creation page +- Fqdn on apps + +### 💼 Other + +- Boarding + +## [4.0.0-beta.20] - 2023-08-17 + +### 🚀 Features + +- Send internal notification to discord +- Monitor server connection + +### 🐛 Bug Fixes + +- Make coolify-db backups unique dir + +## [4.0.0-beta.19] - 2023-08-15 + +### 🚀 Features + +- Pricing plans ans subs +- Add s3 storages +- Init postgresql database +- Add backup notifications +- Dockerfile build pack +- Cloud +- Force password reset + waitlist + +### 🐛 Bug Fixes + +- Remove buggregator from dev +- Able to change localhost's private key +- Readonly input box +- Notifications +- Licensing +- Subscription link +- Migrate db schema for smtp + discord +- Text field +- Null fqdn notifications +- Remove old modal +- Proxy stop/start ui +- Proxy UI +- Empty description +- Input and textarea +- Postgres_username name to not name, lol +- DatabaseBackupJob.php +- No storage +- Backup now button +- Ui + subscription +- Self-hosted + +### 💼 Other + +- Scheduled backups + +## [4.0.0-beta.18] - 2023-07-14 + +### 🚀 Features + +- Able to control multiplexing +- Add runRemoteCommandSync +- Github repo with deployment key +- Add persistent volumes +- Debuggable executeNow commands +- Add private gh repos +- Delete gh app +- Installation/update github apps +- Auto-deploy +- Deploy key based deployments +- Resource limits +- Long running queue with 1 hour of timeout +- Add arm build to dev +- Disk cleanup threshold by server +- Notify user of disk cleanup init + +### 🐛 Bug Fixes + +- Logo of CCCareers +- Typo +- Ssh +- Nullable name on deploy_keys +- Enviroments +- Remove dd - oops +- Add inprogress activity +- Application view +- Only set status in case the last command block is finished +- Poll activity +- Small typo +- Show activity on load +- Deployment should fail on error +- Tests +- Version +- Status not needed +- No project redirect +- Gh actions +- Set status +- Seeders +- Do not modify localhost +- Deployment_uuid -> type_uuid +- Read env from config, bc of cache +- Private key change view +- New destination +- Do not update next channel all the time +- Cancel deployment button +- Public repo limit shown + branch should be preselected. +- Better status on ui for apps +- Arm coolify version +- Formatting +- Gh actions +- Show github app secrets +- Do not force next version updates +- Debug log button +- Deployment key based works +- Deployment cancel/debug buttons +- Upgrade button +- Changing static build changes port +- Overwrite default nginx configuration +- Do not overlap docker image names +- Oops +- Found image name +- Name length +- Semicolons encoding by traefik +- Base_dir wip & outputs +- Cleanup docker images +- Nginx try_files +- Master is the default, not main +- No ms in rate limit resets +- Loading after button text +- Default value +- Localhost is usable +- Update docker-compose prod +- Cloud/checkoutid/lms +- Type of license code +- More verbose error +- Version lol +- Update prod compose +- Version + +### 💼 Other + +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Persisting data + +## [3.12.28] - 2023-03-16 + +### 🐛 Bug Fixes + +- Revert from dockerhub if ghcr.io does not exists + +## [3.12.27] - 2023-03-07 + +### 🐛 Bug Fixes + +- Show ip address as host in public dbs + +## [3.12.24] - 2023-03-04 + +### 🐛 Bug Fixes + +- Nestjs buildpack + +## [3.12.22] - 2023-03-03 + +### 🚀 Features + +- Add host path to any container + +### 🐛 Bug Fixes + +- Set PACK_VERSION to 0.27.0 +- PublishDirectory +- Host volumes +- Replace . & .. & $PWD with ~ +- Handle log format volumes + +## [3.12.19] - 2023-02-20 + +### 🚀 Features + +- Github raw icon url +- Remove svg support + +### 🐛 Bug Fixes + +- Typos in docs +- Url +- Network in compose files +- Escape new line chars in wp custom configs +- Applications cannot be deleted +- Arm servics +- Base directory not found +- Cannot delete resource when you are not on root team +- Empty port in docker compose + +## [3.12.18] - 2023-01-24 + +### 🐛 Bug Fixes + +- CleanupStuckedContainers +- CleanupStuckedContainers + +## [3.12.16] - 2023-01-20 + +### 🐛 Bug Fixes + +- Stucked containers + +## [3.12.15] - 2023-01-20 + +### 🐛 Bug Fixes + +- Cleanup function +- Cleanup stucked containers +- Deletion + cleanupStuckedContainers + +## [3.12.14] - 2023-01-19 + +### 🐛 Bug Fixes + +- Www redirect + +## [3.12.13] - 2023-01-18 + +### 🐛 Bug Fixes + +- Secrets + +## [3.12.12] - 2023-01-17 + +### 🚀 Features + +- Init h2c (http2/grpc) support +- Http + h2c paralel + +### 🐛 Bug Fixes + +- Build args docker compose +- Grpc + +## [3.12.11] - 2023-01-16 + +### 🐛 Bug Fixes + +- Compose file location +- Docker log sequence +- Delete apps with previews +- Do not cleanup compose applications as unconfigured +- Build env variables with docker compose +- Public gh repo reload compose + +### 💼 Other + +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc + +## [3.12.10] - 2023-01-11 + +### 💼 Other + +- Add missing variables + +## [3.12.9] - 2023-01-11 + +### 🚀 Features + +- Add Openblocks icon +- Adding icon for whoogle +- *(ui)* Add libretranslate service icon +- Handle invite_only plausible analytics + +### 🐛 Bug Fixes + +- Custom gitlab git user +- Add documentation link again +- Remove prefetches +- Doc link +- Temporary disable dns check with dns servers +- Local images for reverting +- Secrets + +## [3.12.8] - 2022-12-27 + +### 🐛 Bug Fixes + +- Parsing secrets +- Read-only permission +- Read-only iam +- $ sign in secrets + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.12.5] - 2022-12-26 + +### 🐛 Bug Fixes + +- Remove unused imports + +### 💼 Other + +- Conditional on environment + +## [3.12.2] - 2022-12-19 + +### 🐛 Bug Fixes + +- Appwrite tmp volume +- Do not replace secret +- Root user for dbs on arm +- Escape secrets +- Escape env vars +- Envs +- Docker buildpack env +- Secrets with newline +- Secrets +- Add default node_env variable +- Add default node_env variable +- Secrets +- Secrets +- Gh actions +- Duplicate env variables +- Cleanupstorage + +### 💼 Other + +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.12.1] - 2022-12-13 + +### 🐛 Bug Fixes + +- Build commands +- Migration file +- Adding missing appwrite volume + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.12.0] - 2022-12-09 + +### 🚀 Features + +- Use registry for building +- Docker registries working +- Custom docker compose file location in repo +- Save doNotTrackData to db +- Add default sentry +- Do not track in settings +- System wide git out of beta +- Custom previewseparator +- Sentry frontend +- Able to host static/php sites on arm +- Save application data before deploying +- SimpleDockerfile deployment +- Able to push image to docker registry +- Revert to remote image +- *(api)* Name label + +### 🐛 Bug Fixes + +- 0 destinations redirect after creation +- Seed +- Sentry dsn update +- Dnt +- Ui +- Only visible with publicrepo +- Migrations +- Prevent webhook errors to be logged +- Login error +- Remove beta from systemwide git +- Git checkout +- Remove sentry before migration +- Webhook previewseparator +- Apache on arm +- Update PR/MRs with new previewSeparator +- Static for arm +- Failed builds should not push images +- Turn off autodeploy for simpledockerfiles +- Security hole +- Rde +- Delete resource on dashboard +- Wrong port in case of docker compose +- Public db icon on dashboard +- Cleanup + +### 💼 Other + +- Pocketbase release + +## [3.11.10] - 2022-11-16 + +### 🚀 Features + +- Only show expose if no proxy conf defined in template +- Custom/private docker registries + +### 🐛 Bug Fixes + +- Local dev api/ws urls +- Wrong template/type +- Gitea icon is svg +- Gh actions +- Gh actions +- Replace $$generate vars +- Webhook traefik +- Exposed ports +- Wrong icons on dashboard +- Escape % in secrets +- Move debug log settings to build logs +- Storage for compose bp + debug on +- Hasura admin secret +- Logs +- Mounts +- Load logs after build failed +- Accept logged and not logged user in /base +- Remote haproxy password/etc +- Remove hardcoded sentry dsn +- Nope in database strings + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ +- Version++ +- Version++ + +## [3.11.9] - 2022-11-15 + +### 🐛 Bug Fixes + +- IsBot issue + +## [3.11.8] - 2022-11-14 + +### 🐛 Bug Fixes + +- Default icon for new services + +## [3.11.1] - 2022-11-08 + +### 🚀 Features + +- Rollback coolify + +### 🐛 Bug Fixes + +- Remove contribution docs +- Umami template +- Compose webhooks fixed +- Variable replacements +- Doc links +- For rollback +- N8n and weblate icon +- Expose ports for services +- Wp + mysql on arm +- Show rollback button loading +- No tags error +- Update on mobile +- Dashboard error +- GetTemplates +- Docker compose persistent volumes +- Application persistent storage things +- Volume names for undefined volume names in compose +- Empty secrets on UI +- Ports for services + +### 💼 Other + +- Secrets on apps +- Fix +- Fixes +- Reload compose loading + +### 🚜 Refactor + +- Code + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Add jda icon for lavalink service +- Version++ + +### ◀️ Revert + +- Revert: revert + +## [3.11.0] - 2022-11-07 + +### 🚀 Features + +- Initial support for specific git commit +- Add default to latest commit and support for gitlab +- Redirect catch-all rule + +### 🐛 Bug Fixes + +- Secret errors +- Service logs +- Heroku bp +- Expose port is readonly on the wrong condition +- Toast +- Traefik proxy q 10s +- App logs view +- Tooltip +- Toast, rde, webhooks +- Pathprefix +- Load public repos +- Webhook simplified +- Remote webhooks +- Previews wbh +- Webhooks +- Websecure redirect +- Wb for previews +- Pr stopps main deployment +- Preview wbh +- Wh catchall for all +- Remove old minio proxies +- Template files +- Compose icon +- Templates +- Confirm restart service +- Template +- Templates +- Templates +- Plausible analytics things +- Appwrite webhook +- Coolify instance proxy +- Migrate template +- Preview webhooks +- Simplify webhooks +- Remove ghost-mariadb from the list +- More simplified webhooks +- Umami + ghost issues + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.10.16] - 2022-10-12 + +### 🐛 Bug Fixes + +- Single container logs and usage with compose + +### 💼 Other + +- New resource label + +## [3.10.15] - 2022-10-12 + +### 🚀 Features + +- Monitoring by container + +### 🐛 Bug Fixes + +- Do not show nope as ip address for dbs +- Add git sha to build args +- Smart search for new services +- Logs for not running containers +- Update docker binaries +- Gh release +- Dev container +- Gitlab auth and compose reload +- Check compose domains in general +- Port required if fqdn is set +- Appwrite v1 missing containers +- Dockerfile +- Pull does not work remotely on huge compose file + +### ⚙️ Miscellaneous Tasks + +- Update staging release + +## [3.10.14] - 2022-10-05 + +### 🚀 Features + +- Docker compose support +- Docker compose +- Docker compose + +### 🐛 Bug Fixes + +- Do not use npx +- Pure docker based development + +### 💼 Other + +- Docker-compose support +- Docker compose +- Remove worker jobs +- One less worker thread + +### 🧪 Testing + +- Remove prisma + +## [3.10.5] - 2022-09-26 + +### 🚀 Features + +- Add migration button to appwrite +- Custom certificate +- Ssl cert on traefik config +- Refresh resource status on dashboard +- Ssl certificate sets custom ssl for applications +- System-wide github apps +- Cleanup unconfigured applications +- Cleanup unconfigured services and databases + +### 🐛 Bug Fixes + +- Ui +- Tooltip +- Dropdown +- Ssl certificate distribution +- Db migration +- Multiplex ssh connections +- Able to search with id +- Not found redirect +- Settings db requests +- Error during saving logs +- Consider base directory in heroku bp +- Basedirectory should be empty if null +- Allow basedirectory for heroku +- Stream logs for heroku bp +- Debug log for bp +- Scp without host verification & cert copy +- Base directory & docker bp +- Laravel php chooser +- Multiplex ssh and ssl copy +- Seed new preview secret types +- Error notification +- Empty preview value +- Error notification +- Seed +- Service logs +- Appwrite function network is not the default +- Logs in docker bp +- Able to delete apps in unconfigured state +- Disable development low disk space +- Only log things to console in dev mode +- Do not get status of more than 10 resources defined by category +- BaseDirectory +- Dashboard statuses +- Default buildImage and baseBuildImage +- Initial deploy status +- Show logs better +- Do not start tcp proxy without main container +- Cleanup stucked tcp proxies +- Default 0 pending invitations +- Handle forked repositories +- Typo +- Pr branches +- Fork pr previews +- Remove unnecessary things +- Meilisearch data dir +- Verify and configure remote docker engines +- Add buildkit features +- Nope if you are not logged in + +### 💼 Other + +- Responsive! +- Fixes +- Fix git icon +- Dropdown as infobox +- Small logs on mobile +- Improvements +- Fix destination view +- Settings view +- More UI improvements +- Fixes +- Fixes +- Fix +- Fixes +- Beta features +- Fix button +- Service fixes +- Fix basedirectory meaning +- Resource button fix +- Main resource search +- Dev logs +- Loading button +- Fix gitlab importer view +- Small fix +- Beta flag +- Hasura console notification +- Fix +- Fix +- Fixes +- Inprogress version of iam +- Fix indicato +- Iam & settings update +- Send 200 for ping and installation wh +- Settings icon + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ + +### ◀️ Revert + +- Show usage everytime + +## [3.10.2] - 2022-09-11 + +### 🚀 Features + +- Add queue reset button +- Previewapplications init +- PreviewApplications finalized +- Fluentbit +- Show remote servers +- *(layout)* Added drawer when user is in mobile +- Re-apply ui improves +- *(ui)* Improve header of pages +- *(styles)* Make header css component +- *(routes)* Improve ui for apps, databases and services logs + +### 🐛 Bug Fixes + +- Changing umami image URL to get latest version +- Gitlab importer for public repos +- Show error logs +- Umami init sql +- Plausible analytics actions +- Login +- Dev url +- UpdateMany build logs +- Fallback to db logs +- Fluentbit configuration +- Coolify update +- Fluentbit and logs +- Canceling build +- Logging +- Load more +- Build logs +- Versions of appwrite +- Appwrite?! +- Get building status +- Await +- Await #2 +- Update PR building status +- Appwrite default version 1.0 +- Undead endpoint does not require JWT +- *(routes)* Improve design of application page +- *(routes)* Improve design of git sources page +- *(routes)* Ui from destinations page +- *(routes)* Ui from databases page +- *(routes)* Ui from databases page +- *(routes)* Ui from databases page +- *(routes)* Ui from services page +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* Ui from settings page +- *(routes)* Duplicates classes in services page +- *(routes)* Searchbar ui +- Github conflicts +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- Ui with headers +- *(routes)* Header of settings page in databases +- *(routes)* Ui from secrets table + +### 💼 Other + +- Fix plausible +- Fix cleanup button +- Fix buttons + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Minor changes +- Minor changes +- Minor changes +- Whoops + +## [3.10.1] - 2022-09-10 + +### 🐛 Bug Fixes + +- Show restarting apps +- Show restarting application & logs +- Remove unnecessary gitlab group name +- Secrets for PR +- Volumes for services +- Build secrets for apps +- Delete resource use window location + +### 💼 Other + +- Fix button +- Fix follow button +- Arm should be on next all the time + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.10.0] - 2022-09-08 + +### 🚀 Features + +- New servers view + +### 🐛 Bug Fixes + +- Change to execa from utils +- Save search input +- Ispublic status on databases +- Port checkers +- Ui variables +- Glitchtip env to pyhton boolean +- Autoupdater + +### 💼 Other + +- Dashboard updates +- Fix tooltip + +## [3.9.4] - 2022-09-07 + +### 🐛 Bug Fixes + +- DnsServer formatting +- Settings for service + +## [3.9.3] - 2022-09-07 + +### 🐛 Bug Fixes + +- Pr previews + +## [3.9.2] - 2022-09-07 + +### 🚀 Features + +- Add traefik acme json to coolify container +- Database secrets + +### 🐛 Bug Fixes + +- Gitlab webhook +- Use ip address instead of window location +- Use ip instead of window location host +- Service state update +- Add initial DNS servers +- Revert last change with domain check +- Service volume generation +- Minio default env variables +- Add php 8.1/8.2 +- Edgedb ui +- Edgedb stuff +- Edgedb + +### 💼 Other + +- Fix login/register page +- Update devcontainer +- Add debug log +- Fix initial loading icon bg +- Fix loading start/stop db/services +- Dashboard updates and a lot more + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ + +## [3.9.0] - 2022-09-06 + +### 🐛 Bug Fixes + +- Debug api logging + gh actions +- Workdir +- Move restart button to settings + +## [3.9.1-rc.1] - 2022-09-06 + +### 🚀 Features + +- *(routes)* Rework ui from login and register page + +### 🐛 Bug Fixes + +- Ssh pid agent name +- Repository link trim +- Fqdn or expose port required +- Service deploymentEnabled +- Expose port is not required +- Remote verification +- Dockerfile + +### 💼 Other + +- Database_branches +- Login page + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ + +## [3.9.0-rc.1] - 2022-09-02 + +### 🚀 Features + +- New service - weblate +- Restart application +- Show elapsed time on running builds +- Github allow fual branches +- Gitlab dual branch +- Taiga + +### 🐛 Bug Fixes + +- Glitchtip things +- Loading state on start +- Ui +- Submodule +- Gitlab webhooks +- UI + refactor +- Exposedport on save +- Appwrite letsencrypt +- Traefik appwrite +- Traefik +- Finally works! :) +- Rename components + remove PR/MR deployment from public repos +- Settings missing id +- Explainer component +- Database name on logs view +- Taiga + +### 💼 Other + +- Fixes +- Change tooltips and info boxes +- Added rc release + +### 🧪 Testing + +- Native binary target +- Dockerfile + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.8.9] - 2022-08-30 + +### 🐛 Bug Fixes + +- Oh god Prisma + +## [3.8.8] - 2022-08-30 + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.8.6] - 2022-08-30 + +### 🐛 Bug Fixes + +- Pr deployment +- CompareVersions +- Include +- Include +- Gitlab apps + +### 💼 Other + +- Fixes +- Route to the correct path when creating destination from db config + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.8.5] - 2022-08-27 + +### 🐛 Bug Fixes + +- Copy all files during install process +- Typo +- Process +- White labeled icon on navbar +- Whitelabeled icon +- Next/nuxt deployment type +- Again + +## [3.8.4] - 2022-08-27 + +### 🐛 Bug Fixes + +- UI thinkgs +- Delete team while it is active +- Team switching +- Queue cleanup +- Decrypt secrets +- Cleanup build cache as well +- Pr deployments + remove public gits + +### 💼 Other + +- Dashbord fixes +- Fixes + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.8.3] - 2022-08-26 + +### 🐛 Bug Fixes + +- Secrets decryption + +## [3.8.2] - 2022-08-26 + +### 🚀 Features + +- *(ui)* Rework home UI and with responsive design + +### 🐛 Bug Fixes + +- Never stop deplyo queue +- Build queue system +- High cpu usage +- Worker +- Better worker system + +### 💼 Other + +- Dashboard fine-tunes +- Fine-tune +- Fixes +- Fix + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.8.1] - 2022-08-24 + +### 🐛 Bug Fixes + +- Ui buttons +- Clear queue on cancelling jobs +- Cancelling jobs +- Dashboard for admins + +## [3.8.0] - 2022-08-23 + +### 🚀 Features + +- Searxng service + +### 🐛 Bug Fixes + +- Port checker +- Cancel build after 5 seconds +- ExposedPort checker +- Batch secret = +- Dashboard for non-root users +- Stream build logs +- Show build log start/end + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.7.0] - 2022-08-19 + +### 🚀 Features + +- Add GlitchTip service + +### 🐛 Bug Fixes + +- Missing commas +- ExposedPort is just optional + +### ⚙️ Miscellaneous Tasks + +- Add .pnpm-store in .gitignore +- Version++ + +## [3.6.0] - 2022-08-18 + +### 🚀 Features + +- Import public repos (wip) +- Public repo deployment +- Force rebuild + env.PORT for port + public repo build + +### 🐛 Bug Fixes + +- Bots without exposed ports + +### 💼 Other + +- Fixes here and there + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.5.2] - 2022-08-17 + +### 🐛 Bug Fixes + +- Restart containers on-failure instead of always +- Show that Ghost values could be changed + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.5.1] - 2022-08-17 + +### 🐛 Bug Fixes + +- Revert docker compose version to 2.6.1 +- Trim secrets + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.5.0] - 2022-08-17 + +### 🚀 Features + +- Deploy bots (no domains) +- Custom dns servers + +### 🐛 Bug Fixes + +- Dns button ui +- Bot deployments +- Bots +- AutoUpdater & cleanupStorage jobs + +### 💼 Other + +- Typing + +## [3.4.0] - 2022-08-16 + +### 🚀 Features + +- Appwrite service +- Heroku deployments + +### 🐛 Bug Fixes + +- Replace docker compose with docker-compose on CSB +- Dashboard ui +- Create coolify-infra, if it does not exists +- Gitpod conf and heroku buildpacks +- Appwrite +- Autoimport + readme +- Services import +- Heroku icon +- Heroku icon + +## [3.3.4] - 2022-08-15 + +### 🐛 Bug Fixes + +- Make it public button +- Loading indicator + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.3.3] - 2022-08-14 + +### 🐛 Bug Fixes + +- Decryption errors +- Postgresql on ARM + +## [3.3.2] - 2022-08-12 + +### 🐛 Bug Fixes + +- Debounce dashboard status requests + +### 💼 Other + +- Fider + +## [3.3.1] - 2022-08-12 + +### 🐛 Bug Fixes + +- Empty buildpack icons + +## [3.2.3] - 2022-08-12 + +### 🚀 Features + +- Databases on ARM +- Mongodb arm support +- New dashboard + +### 🐛 Bug Fixes + +- Cleanup stucked prisma-engines +- Toast +- Secrets +- Cleanup prisma engine if there is more than 1 +- !isARM to isARM +- Enterprise GH link + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.2.2] - 2022-08-11 + +### 🐛 Bug Fixes + +- Coolify-network on verification + +## [3.2.1] - 2022-08-11 + +### 🚀 Features + +- Init heroku buildpacks + +### 🐛 Bug Fixes + +- Follow/cancel buttons +- Only remove coolify managed containers +- White-labeled env +- Schema + +### 💼 Other + +- Fix + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.2.0] - 2022-08-11 + +### 🚀 Features + +- Persistent storage for all services +- Cleanup clickhouse db + +### 🐛 Bug Fixes + +- Rde local ports +- Empty remote destinations could be removed +- Tips +- Lowercase issues fider +- Tooltip colors +- Update clickhouse configuration +- Cleanup command +- Enterprise Github instance endpoint + +### 💼 Other + +- Local ssh port +- Redesign a lot +- Fixes +- Loading indicator for plausible buttons + +## [3.1.4] - 2022-08-01 + +### 🚀 Features + +- Moodle init +- Remote docker engine init +- Working on remote docker engine +- Rde +- Remote docker engine +- Ipv4 and ipv6 +- Contributors +- Add arch to database +- Stop preview deployment + +### 🐛 Bug Fixes + +- Settings from api +- Selectable destinations +- Gitpod hardcodes +- Typo +- Typo +- Expose port checker +- States and exposed ports +- CleanupStorage +- Remote traefik webhook +- Remote engine ip address +- RemoteipAddress +- Explanation for remote engine url +- Tcp proxy +- Lol +- Webhook +- Dns check for rde +- Gitpod +- Revert last commit +- Dns check +- Dns checker +- Webhook +- Df and more debug +- Webhooks +- Load previews async +- Destination icon +- Pr webhook +- Cache image +- No ssh key found +- Prisma migration + update of docker and stuffs +- Ui +- Ui +- Only 1 ssh-agent is needed +- Reuse ssh connection +- Ssh tunnel +- Dns checking +- Fider BASE_URL set correctly + +### 💼 Other + +- Error message https://github.com/coollabsio/coolify/issues/502 +- Changes +- Settings +- For removing app + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.1.3] - 2022-07-18 + +### 🚀 Features + +- Init moodle and separate stuffs to shared package + +### 🐛 Bug Fixes + +- More types for API +- More types +- Do not rebuild in case image exists and sha not changed +- Gitpod urls +- Remove new service start process +- Remove shared dir, deployment does not work +- Gitlab custom url +- Location url for services and apps + +## [3.1.2] - 2022-07-14 + +### 🐛 Bug Fixes + +- Admin password reset should not timeout +- Message for double branches +- Turn off autodeploy if double branch is configured + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.1.1] - 2022-07-13 + +### 🚀 Features + +- Gitpod integration + +### 🐛 Bug Fixes + +- Cleanup less often and can do it manually + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ + +## [3.1.0] - 2022-07-12 + +### 🚀 Features + +- Ability to change deployment type for nextjs +- Ability to change deployment type for nuxtjs +- Gitpod ready code(almost) +- Add Docker buildpack exposed port setting +- Custom port for git instances + +### 🐛 Bug Fixes + +- GitLab pagination load data +- Service domain checker +- Wp missing ftp solution +- Ftp WP issues +- Ftp?! +- Gitpod updates +- Gitpod +- Gitpod +- Wordpress FTP permission issues +- GitLab search fields +- GitHub App button +- GitLab loop on misconfigured source +- Gitpod + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [3.0.3] - 2022-07-06 + +### 🐛 Bug Fixes + +- Domain check +- Domain check +- TrustProxy for Fastify +- Hostname issue + +## [3.0.2] - 2022-07-06 + +### 🐛 Bug Fixes + +- New destination can be created +- Include post +- New destinations + +## [3.0.1] - 2022-07-06 + +### 🐛 Bug Fixes + +- Seeding +- Forgot that the version bump changed 😅 + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.11] - 2022-06-20 + +### 🐛 Bug Fixes + +- Be able to change database + service versions +- Lock file + +## [2.9.10] - 2022-06-17 + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.9] - 2022-06-10 + +### 🐛 Bug Fixes + +- Host and reload for uvicorn +- Remove package-lock + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.8] - 2022-06-10 + +### 🐛 Bug Fixes + +- Persistent nocodb +- Nocodb persistency + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.7] - 2022-06-09 + +### 🐛 Bug Fixes + +- Plausible custom script +- Plausible script and middlewares +- Remove console log +- Remove comments +- Traefik middleware + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.6] - 2022-06-02 + +### 🐛 Bug Fixes + +- Fider changed an env variable name +- Pnpm command + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.5] - 2022-06-02 + +### 🐛 Bug Fixes + +- Proxy stop missing argument + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.4] - 2022-06-01 + +### 🐛 Bug Fixes + +- Demo version forms +- Typo +- Revert gh and gl cloning + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.3] - 2022-05-31 + +### 🐛 Bug Fixes + +- Recurisve clone instead of submodule +- Versions +- Only reconfigure coolify proxy if its missconfigured + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.2] - 2022-05-31 + +### 🐛 Bug Fixes + +- TrustProxy +- Force restart proxy +- Only restart coolify proxy in case of version prior to 2.9.2 +- Force restart proxy on seeding +- Add GIT ENV variable for submodules + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.1] - 2022-05-31 + +### 🐛 Bug Fixes + +- GitHub fixes + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.9.0] - 2022-05-31 + +### 🚀 Features + +- PageLoader +- Database + service usage + +### 🐛 Bug Fixes + +- Service checks +- Remove console.log +- Traefik +- Remove debug things +- WIP Traefik +- Proxy for http +- PR deployments view +- Minio urls + domain checks +- Remove gh token on git source changes +- Do not fetch app state in case of missconfiguration +- Demo instance save domain instantly +- Instant save on demo instance +- New source canceled view +- Lint errors in database services +- Otherfqdns +- Host key verification +- Ftp connection + +### 💼 Other + +- Appwrite +- Testing WS +- Traefik?! +- Traefik +- Traefik +- Traefik migration +- Traefik +- Traefik +- Traefik +- Notifications and application usage +- *(fix)* Traefik +- Css + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.8.2] - 2022-05-16 + +### 🐛 Bug Fixes + +- Gastby buildpack + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.8.1] - 2022-05-10 + +### 🐛 Bug Fixes + +- WP custom db +- UI + +## [2.6.1] - 2022-05-03 + +### 🚀 Features + +- Basic server usage on dashboard +- Show usage trends +- Usage on dashboard +- Custom script path for Plausible +- WP could have custom db +- Python image selection + +### 🐛 Bug Fixes + +- ExposedPorts +- Logos for dbs +- Do not run SSL renew in development +- Check domain for coolify before saving +- Remove debug info +- Cancel jobs +- Cancel old builds in database +- Better DNS check to prevent errors +- Check DNS in prod only +- DNS check +- Disable sentry for now +- Cancel +- Sentry +- No image for Docker buildpack +- Default packagemanager +- Server usage only shown for root team +- Expose ports for services +- UI +- Navbar UI +- UI +- UI +- Remove RC python +- UI +- UI +- UI +- Default Python package + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ +- Version++ +- Version++ + +## [2.6.0] - 2022-05-02 + +### 🚀 Features + +- Hasura as a service +- Gzip compression +- Laravel buildpack is working! +- Laravel +- Fider service +- Database and services logs +- DNS check settings for SSL generation +- Cancel builds! + +### 🐛 Bug Fixes + +- Unami svg size +- Team switching moved to IAM menu +- Always use IP address for webhooks +- Remove unnecessary test endpoint +- UI +- Migration +- Fider envs +- Checking low disk space +- Build image +- Update autoupdate env variable +- Renew certificates +- Webhook build images +- Missing node versions + +### 💼 Other + +- Laravel + +## [2.4.11] - 2022-04-20 + +### 🚀 Features + +- Deno DB migration +- Show exited containers on UI & better UX +- Query container state periodically +- Install svelte-18n and init setup +- Umami service +- Coolify auto-updater +- Autoupdater +- Select base image for buildpacks + +### 🐛 Bug Fixes + +- Deno configurations +- Text on deno buildpack +- Correct branch shown in build logs +- Vscode permission fix +- I18n +- Locales +- Application logs is not reversed and queried better +- Do not activate i18n for now +- GitHub token cleanup on team switch +- No logs found +- Code cleanups +- Reactivate posgtres password +- Contribution guide +- Simplify list services +- Contribution +- Contribution guide +- Contribution guide +- Packagemanager finder + +### 💼 Other + +- Umami service +- Base image selector + +### 📚 Documentation + +- How to add new services +- Update +- Update + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ +- Version++ + +## [2.4.10] - 2022-04-17 + +### 🚀 Features + +- Add persistent storage for services +- Multiply dockerfile locations for docker buildpack +- Testing fluentd logging driver +- Fluentbit investigation +- Initial deno support + +### 🐛 Bug Fixes + +- Switch from bitnami/redis to normal redis +- Use redis-alpine +- Wordpress extra config +- Stop sFTP connection on wp stop +- Change user's id in sftp wp instance +- Use arm based certbot on arm +- Buildlog line number is not string +- Application logs paginated +- Switch to stream on applications logs +- Scroll to top for logs +- Pull new images for services all the time it's started. +- White-labeled custom logo +- Application logs + +### 💼 Other + +- Show extraconfig if wp is running + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ + +## [2.4.9] - 2022-04-14 + +### 🐛 Bug Fixes + +- Postgres root pw is pw field +- Teams view +- Improved tcp proxy monitoring for databases/ftp +- Add HTTP proxy checks +- Loading of new destinations +- Better performance for cleanup images +- Remove proxy container in case of dependent container is down +- Restart local docker coolify proxy in case of something happens to it +- Id of service container + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.8] - 2022-04-13 + +### 🐛 Bug Fixes + +- Register should happen if coolify proxy cannot be started +- GitLab typo +- Remove system wide pw reset + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.7] - 2022-04-13 + +### 🐛 Bug Fixes + +- Destinations to HAProxy + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.6] - 2022-04-13 + +### 🐛 Bug Fixes + +- Cleanup images older than a day +- Meilisearch service +- Load all branches, not just the first 30 +- ProjectID for Github +- DNS check before creating SSL cert +- Try catch me +- Restart policy for resources +- No permission on first registration +- Reverting postgres password for now + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.5] - 2022-04-12 + +### 🐛 Bug Fixes + +- Types +- Invitations +- Timeout values + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.4] - 2022-04-12 + +### 🐛 Bug Fixes + +- Haproxy build stuffs +- Proxy + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.3] - 2022-04-12 + +### 🐛 Bug Fixes + +- Remove unnecessary save button haha +- Update dockerfile + +### ⚙️ Miscellaneous Tasks + +- Update packages +- Version++ +- Update build scripts +- Update build packages + +## [2.4.2] - 2022-04-09 + +### 🐛 Bug Fixes + +- Missing install repositories GitHub +- Return own and other sources better +- Show config missing on sources + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.1] - 2022-04-09 + +### 🐛 Bug Fixes + +- Enable https for Ghost +- Postgres root passwor shown and set +- Able to change postgres user password from ui +- DB Connecting string generator + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.4.0] - 2022-04-08 + +### 🚀 Features + +- Wordpress on-demand SFTP +- Finalize on-demand sftp for wp +- PHP Composer support +- Working on-demand sftp to wp data +- Admin team sees everything +- Able to change service version/tag +- Basic white labeled version +- Able to modify database passwords + +### 🐛 Bug Fixes + +- Add openssl to image +- Permission issues +- On-demand sFTP for wp +- Fix for fix haha +- Do not pull latest image +- Updated db versions +- Only show proxy for admin team +- Team view for root team +- Do not trigger >1 webhooks on GitLab +- Possible fix for spikes in CPU usage +- Last commit +- Www or not-www, that's the question +- Fix for the fix that fixes the fix +- Ton of updates for users/teams +- Small typo +- Unique storage paths +- Self-hosted GitLab URL +- No line during buildLog +- Html/apiUrls cannot end with / +- Typo +- Missing buildpack + +### 💼 Other + +- Fix +- Better layout for root team +- Fix +- Fixes +- Fix +- Fix +- Fix +- Fix +- Fix +- Fix +- Fix +- Insane amount +- Fix +- Fixes +- Fixes +- Fix +- Fixes +- Fixes + +### 📚 Documentation + +- Contribution guide + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.3.3] - 2022-04-05 + +### 🐛 Bug Fixes + +- Add git lfs while deploying +- Try to update build status several times +- Update stucked builds +- Update stucked builds on startup +- Revert seed +- Lame fixing +- Remove asyncUntil + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.3.2] - 2022-04-04 + +### 🐛 Bug Fixes + +- *(php)* If .htaccess file found use apache +- Add default webhook domain for n8n + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.3.1] - 2022-04-04 + +### 🐛 Bug Fixes + +- Secrets build/runtime coudl be changed after save +- Default configuration + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.3.0] - 2022-04-04 + +### 🚀 Features + +- Initial python support +- Add loading on register button +- *(dev)* Allow windows users to use pnpm dev +- MeiliSearch service +- Add abilitry to paste env files + +### 🐛 Bug Fixes + +- Ignore coolify proxy error for now +- Python no wsgi +- If user not found +- Rename envs to secrets +- Infinite loop on www domains +- No need to paste clear text env for previews +- Build log fix attempt #1 +- Small UI fix on logs +- Lets await! +- Async progress +- Remove console.log +- Build log +- UI +- Gitlab & Github urls + +### 💼 Other + +- Improvements + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ +- Lock file + fix packages + +## [2.2.7] - 2022-04-01 + +### 🐛 Bug Fixes + +- Haproxy errors +- Build variables +- Use NodeJS for sveltekit for now + +## [2.2.6] - 2022-03-31 + +### 🐛 Bug Fixes + +- Add PROTO headers + +## [2.2.5] - 2022-03-31 + +### 🐛 Bug Fixes + +- Registration enabled/disabled + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.2.4] - 2022-03-31 + +### 🐛 Bug Fixes + +- Gitlab repo url +- No need to dashify anymore + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.2.3] - 2022-03-31 + +### 🐛 Bug Fixes + +- List ghost services +- Reload window on settings saved +- Persistent storage on webhooks +- Add license +- Space in repo names + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ +- Version++ +- Fixed typo on New Git Source view + +## [2.2.0] - 2022-03-27 + +### 🚀 Features + +- Add n8n.io service +- Add update kuma service +- Ghost service + +### 🐛 Bug Fixes + +- Ghost logo size +- Ghost icon, remove console.log + +### 💼 Other + +- Colors on svelte-select + +### ⚙️ Miscellaneous Tasks + +- Version ++ + +## [2.1.1] - 2022-03-25 + +### 🐛 Bug Fixes + +- Cleanup only 2 hours+ old images + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.1.0] - 2022-03-23 + +### 🚀 Features + +- Use compose instead of normal docker cmd +- Be able to redeploy PRs + +### 🐛 Bug Fixes + +- Skip ssl cert in case of error +- Volumes + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.31] - 2022-03-20 + +### 🚀 Features + +- Add PHP modules + +### 🐛 Bug Fixes + +- Cleanup old builds +- Only cleanup same app +- Add nginx + htaccess files + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.30] - 2022-03-19 + +### 🐛 Bug Fixes + +- No cookie found +- Missing session data +- No error if GitSource is missing +- No webhook secret found? +- Basedir for dockerfiles +- Better queue system + more support on monorepos +- Remove build logs in case of app removed + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.29] - 2022-03-11 + +### 🚀 Features + +- Webhooks inititate all applications with the correct branch +- Check ssl for new apps/services first +- Autodeploy pause +- Install pnpm into docker image if pnpm lock file is used + +### 🐛 Bug Fixes + +- Personal Gitlab repos +- Autodeploy true by default for GH repos + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.28] - 2022-03-04 + +### 🚀 Features + +- Service secrets + +### 🐛 Bug Fixes + +- Do not error if proxy is not running + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.27] - 2022-03-02 + +### 🚀 Features + +- Send version with update request + +### 🐛 Bug Fixes + +- Check when a container is running +- Reload haproxy if new cert is added +- Cleanup coolify images +- Application state in UI + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.26] - 2022-03-02 + +### 🐛 Bug Fixes + +- Update process + +## [2.0.25] - 2022-03-02 + +### 🚀 Features + +- Languagetool service + +### 🐛 Bug Fixes + +- Reload proxy on ssl cert +- Volume name + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.24] - 2022-03-02 + +### 🐛 Bug Fixes + +- Better proxy check +- Ssl + sslrenew +- Null proxyhash on restart +- Reconfigure proxy on restart +- Update process + +## [2.0.23] - 2022-02-28 + +### 🐛 Bug Fixes + +- Be sure .env exists +- Missing fqdn for services +- Default npm command +- Add coolify-image label for build images +- Cleanup old images, > 3 days + +### 💼 Other + +- Colorful states +- Application start + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.22] - 2022-02-27 + +### 🐛 Bug Fixes + +- Coolify image pulls +- Remove wrong/stuck proxy configurations +- Always use a buildpack +- Add icons for eleventy + astro +- Fix proxy every 10 secs +- Do not remove coolify proxy +- Update version + +### 💼 Other + +- Remote docker engine + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.21] - 2022-02-24 + +### 🚀 Features + +- Random subdomain for demo +- Random domain for services +- Astro buildpack +- 11ty buildpack +- Registration page + +### 🐛 Bug Fixes + +- Http for demo, oops +- Docker scanner +- Improvement on image pulls + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.20] - 2022-02-23 + +### 🐛 Bug Fixes + +- Revert default network + +### 💼 Other + +- Dns check + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.19] - 2022-02-23 + +### 🐛 Bug Fixes + +- Random network name for demo +- Settings fqdn grr + +## [2.0.18] - 2022-02-22 + +### 🚀 Features + +- Ports range + +### 🐛 Bug Fixes + +- Email is lowercased in login +- Lowercase email everywhere +- Use normal docker-compose in dev + +### 💼 Other + +- Make copy/password visible + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.17] - 2022-02-21 + +### 🐛 Bug Fixes + +- Move tokens from session to cookie/store + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.14] - 2022-02-18 + +### 🚀 Features + +- Basic password reset form +- Scan for lock files and set right commands +- Public port range (WIP) + +### 🐛 Bug Fixes + +- SSL app off +- Local docker host +- Typo +- Lets encrypt +- Remove SSL with stop +- SSL off for services +- Grr +- Running state css +- Minor fixes +- Remove force SSL when doing let's encrypt request +- GhToken in session now +- Random port for certbot +- Follow icon +- Plausible volume fixed +- Database connection strings +- Gitlab webhooks fixed +- If DNS not found, do not redirect +- Github token + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version ++ + +## [2.0.13] - 2022-02-17 + +### 🐛 Bug Fixes + +- Login issues + +## [2.0.11] - 2022-02-15 + +### 🚀 Features + +- Follow logs +- Generate www & non-www SSL certs + +### 🐛 Bug Fixes + +- Window error in SSR +- GitHub sync PR's +- Load more button +- Small fixes +- Typo +- Error with follow logs +- IsDomainConfigured +- TransactionIds +- Coolify image cleanup +- Cleanup every 10 mins +- Cleanup images +- Add no user redis to uri +- Secure cookie disabled by default +- Buggy svelte-kit-cookie-session + +### 💼 Other + +- Only allow cleanup in production + +### ⚙️ Miscellaneous Tasks + +- Version++ +- Version++ + +## [2.0.10] - 2022-02-15 + +### 🐛 Bug Fixes + +- Typo +- Error handling +- Stopping service without proxy +- Coolify proxy start + +### ⚙️ Miscellaneous Tasks + +- Version++ + +## [2.0.8] - 2022-02-14 + +### 🐛 Bug Fixes + +- Validate secrets +- Truncate git clone errors +- Branch used does not throw error + +## [2.0.7] - 2022-02-13 + +### 🚀 Features + +- Www <-> non-www redirection for apps +- Www <-> non-www redirection + +### 🐛 Bug Fixes + +- Package.json +- Build secrets should be visible in runtime +- New secret should have default values + +## [2.0.5] - 2022-02-11 + +### 🚀 Features + +- VaultWarden service + +### 🐛 Bug Fixes + +- PreventDefault on a button, thats all +- Haproxy check should not throw error +- Delete all build files +- Cleanup images +- More error handling in proxy configuration + cleanups +- Local static assets +- Check sentry +- Typo + +### ⚙️ Miscellaneous Tasks + +- Version +- Version + +## [2.0.4] - 2022-02-11 + +### 🚀 Features + +- Use tags in update +- New update process (#115) + +### 🐛 Bug Fixes + +- Docker Engine bug related to live-restore and IPs +- Version + +## [2.0.3] - 2022-02-10 + +### 🐛 Bug Fixes + +- Capture non-error as error +- Only delete id.rsa in case of it exists +- Status is not available yet + +### ⚙️ Miscellaneous Tasks + +- Version bump + +## [2.0.2] - 2022-02-10 + +### 🐛 Bug Fixes + +- Secrets join +- ENV variables set differently + +## [1.0.0] - 2021-03-24 + + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..6434ef8775 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,709 @@ +# CLAUDE.md + +This file provides guidance to **Claude Code** (claude.ai/code) when working with code in this repository. + +> **Note for AI Assistants**: This file is specifically for Claude Code. If you're using Cursor IDE, refer to the `.cursor/rules/` directory for detailed rule files. Both systems share core principles but are optimized for their respective workflows. +> +> **Maintaining Instructions**: When updating AI instructions, see [.AI_INSTRUCTIONS_SYNC.md](.AI_INSTRUCTIONS_SYNC.md) for synchronization guidelines between CLAUDE.md and .cursor/rules/. + +## Project Overview + +Coolify is an open-source, self-hostable platform for deploying applications and managing servers - an alternative to Heroku/Netlify/Vercel. It's built with Laravel (PHP) and uses Docker for containerization. + +## Development Commands + +### Frontend Development +- `npm run dev` - Start Vite development server for frontend assets +- `npm run build` - Build frontend assets for production + +### Backend Development +Only run artisan commands inside "coolify" container when in development. +- `php artisan serve` - Start Laravel development server +- `php artisan migrate` - Run database migrations +- `php artisan queue:work` - Start queue worker for background jobs +- `php artisan horizon` - Start Laravel Horizon for queue monitoring +- `php artisan tinker` - Start interactive PHP REPL + +### Code Quality +- `./vendor/bin/pint` - Run Laravel Pint for code formatting +- `./vendor/bin/phpstan` - Run PHPStan for static analysis +- `./vendor/bin/pest` - Run Pest tests (unit tests only, without database) + +### Running Tests +**IMPORTANT**: Tests that require database connections MUST be run inside the Docker container: +- **Inside Docker**: `docker exec coolify php artisan test` (for feature tests requiring database) +- **Outside Docker**: `./vendor/bin/pest tests/Unit` (for pure unit tests without database dependencies) +- Unit tests should use mocking and avoid database connections +- Feature tests that require database must be run in the `coolify` container + +## Architecture Overview + +### Technology Stack +- **Backend**: Laravel 12 (PHP 8.4) +- **Frontend**: Livewire 3.5+ with Alpine.js and Tailwind CSS 4.1+ +- **Database**: PostgreSQL 15 (primary), Redis 7 (cache/queues) +- **Real-time**: Soketi (WebSocket server) +- **Containerization**: Docker & Docker Compose +- **Queue Management**: Laravel Horizon + +### Key Components + +#### Core Models +- `Application` - Deployed applications with Git integration (74KB, highly complex) +- `Server` - Remote servers managed by Coolify (46KB, complex) +- `Service` - Docker Compose services (58KB, complex) +- `Database` - Standalone database instances (PostgreSQL, MySQL, MongoDB, Redis, etc.) +- `Team` - Multi-tenancy support +- `Project` - Grouping of environments and resources +- `Environment` - Environment isolation (staging, production, etc.) + +#### Job System +- Uses Laravel Horizon for queue management +- Key jobs: `ApplicationDeploymentJob`, `ServerCheckJob`, `DatabaseBackupJob` +- `ServerManagerJob` and `ServerConnectionCheckJob` handle job scheduling + +#### Deployment Flow +1. Git webhook triggers deployment +2. `ApplicationDeploymentJob` handles build and deployment +3. Docker containers are managed on target servers +4. Proxy configuration (Nginx/Traefik) is updated + +#### Server Management +- SSH-based server communication via `ExecuteRemoteCommand` trait +- Docker installation and management +- Proxy configuration generation +- Resource monitoring and cleanup + +### Directory Structure +- `app/Actions/` - Domain-specific actions (Application, Database, Server, etc.) +- `app/Jobs/` - Background queue jobs +- `app/Livewire/` - Frontend components (full-stack with Livewire) +- `app/Models/` - Eloquent models +- `app/Rules/` - Custom validation rules +- `app/Http/Middleware/` - HTTP middleware +- `bootstrap/helpers/` - Helper functions for various domains +- `database/migrations/` - Database schema evolution +- `routes/` - Application routing (web.php, api.php, webhooks.php, channels.php) +- `resources/views/livewire/` - Livewire component views +- `tests/` - Pest tests (Feature and Unit) + +## Development Guidelines + +### Frontend Philosophy +Coolify uses a **server-side first** approach with minimal JavaScript: +- **Livewire** for server-side rendering with reactive components +- **Alpine.js** for lightweight client-side interactions +- **Tailwind CSS** for utility-first styling with dark mode support +- **Enhanced Form Components** with built-in authorization system +- Real-time updates via WebSocket without page refreshes + +### Form Authorization Pattern +**IMPORTANT**: When creating or editing forms, ALWAYS include authorization: + +#### For Form Components (Input, Select, Textarea, Checkbox, Button): +Use `canGate` and `canResource` attributes for automatic authorization: +```html + +... + +Save +``` + +#### For Modal Components: +Wrap with `@can` directives: +```html +@can('update', $resource) + ... + ... +@endcan +``` + +#### In Livewire Components: +Always add the `AuthorizesRequests` trait and check permissions: +```php +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; + +class MyComponent extends Component +{ + use AuthorizesRequests; + + public function mount() + { + $this->authorize('view', $this->resource); + } + + public function update() + { + $this->authorize('update', $this->resource); + // ... update logic + } +} +``` + +### Livewire Component Structure +- Components located in `app/Livewire/` +- Views in `resources/views/livewire/` +- State management handled on the server +- Use wire:model for two-way data binding +- Dispatch events for component communication +- **CRITICAL**: Livewire component views **MUST** have exactly ONE root element. ALL content must be contained within this single root element. Placing ANY elements (` diff --git a/resources/js/terminal.js b/resources/js/terminal.js index 59c9a79a8d..b49aad9cf2 100644 --- a/resources/js/terminal.js +++ b/resources/js/terminal.js @@ -17,16 +17,47 @@ export function initializeTerminalComponent() { MAX_PENDING_WRITES: 5, keepAliveInterval: null, reconnectInterval: null, + // Enhanced connection management + connectionState: 'disconnected', // 'connecting', 'connected', 'disconnected', 'reconnecting' + reconnectAttempts: 0, + maxReconnectAttempts: 10, + baseReconnectDelay: 1000, + maxReconnectDelay: 30000, + connectionTimeout: 10000, + connectionTimeoutId: null, + lastPingTime: null, + pingTimeout: 35000, // 5 seconds longer than ping interval + pingTimeoutId: null, + heartbeatMissed: 0, + maxHeartbeatMisses: 3, + // Resize handling + resizeObserver: null, + resizeTimeout: null, init() { this.setupTerminal(); - this.initializeWebSocket(); + + // Add a small delay for initial connection to ensure everything is ready + setTimeout(() => { + this.initializeWebSocket(); + }, 100); + this.setupTerminalEventListeners(); this.$wire.on('send-back-command', (command) => { - this.socket.send(JSON.stringify({ - command: command - })); + this.sendCommandWhenReady({ command: command }); + }); + + this.$wire.on('terminal-should-focus', () => { + // Wait for terminal to be ready, then focus + const focusWhenReady = () => { + if (this.terminalActive && this.term) { + this.term.focus(); + } else { + setTimeout(focusWhenReady, 100); + } + }; + focusWhenReady(); }); this.keepAliveInterval = setInterval(this.keepAlive.bind(this), 30000); @@ -39,19 +70,25 @@ export function initializeTerminalComponent() { if (active) { this.$refs.terminalWrapper.style.display = 'block'; this.resizeTerminal(); + + // Start observing terminal wrapper for resize changes + if (this.resizeObserver && this.$refs.terminalWrapper) { + this.resizeObserver.observe(this.$refs.terminalWrapper); + } } else { this.$refs.terminalWrapper.style.display = 'none'; + + // Stop observing when terminal is inactive + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + } } }); }); ['livewire:navigated', 'beforeunload'].forEach((event) => { document.addEventListener(event, () => { - this.checkIfProcessIsRunningAndKillIt(); - clearInterval(this.keepAliveInterval); - if (this.reconnectInterval) { - clearInterval(this.reconnectInterval); - } + this.cleanup(); }, { once: true }); }); @@ -59,6 +96,66 @@ export function initializeTerminalComponent() { this.resizeTerminal() }; + // Set up ResizeObserver for more reliable terminal resizing + if (window.ResizeObserver) { + this.resizeObserver = new ResizeObserver(() => { + // Debounce resize calls to avoid performance issues + clearTimeout(this.resizeTimeout); + this.resizeTimeout = setTimeout(() => { + this.resizeTerminal(); + }, 50); + }); + } + }, + + cleanup() { + this.checkIfProcessIsRunningAndKillIt(); + this.clearAllTimers(); + this.connectionState = 'disconnected'; + if (this.socket) { + this.socket.close(1000, 'Client cleanup'); + } + + // Clean up resize observer + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + this.resizeObserver = null; + } + + // Clear resize timeout + if (this.resizeTimeout) { + clearTimeout(this.resizeTimeout); + } + }, + + clearAllTimers() { + [this.keepAliveInterval, this.reconnectInterval, this.connectionTimeoutId, this.pingTimeoutId, this.resizeTimeout] + .forEach(timer => timer && clearInterval(timer)); + this.keepAliveInterval = null; + this.reconnectInterval = null; + this.connectionTimeoutId = null; + this.pingTimeoutId = null; + this.resizeTimeout = null; + }, + + resetTerminal() { + if (this.term) { + this.$wire.dispatch('error', 'Terminal websocket connection lost.'); + this.term.reset(); + this.term.clear(); + this.pendingWrites = 0; + this.paused = false; + this.commandBuffer = ''; + + // Notify parent component that terminal disconnected + this.$wire.dispatch('terminalDisconnected'); + + // Force a refresh + this.$nextTick(() => { + this.resizeTerminal(); + this.term.focus(); + }); + } }, setupTerminal() { @@ -69,67 +166,186 @@ export function initializeTerminalComponent() { rows: 30, fontFamily: '"Fira Code", courier-new, courier, monospace, "Powerline Extra Symbols"', cursorBlink: true, + rendererType: 'canvas', + convertEol: true, + disableStdin: false }); this.fitAddon = new FitAddon(); this.term.loadAddon(this.fitAddon); + this.$nextTick(() => { + this.resizeTerminal(); + }); } }, initializeWebSocket() { - if (!this.socket || this.socket.readyState === WebSocket.CLOSED) { - const predefined = window.terminalConfig - const connectionString = { - protocol: window.location.protocol === 'https:' ? 'wss' : 'ws', - host: window.location.hostname, - port: ":6002", - path: '/terminal/ws' - } - if (!window.location.port) { - connectionString.port = '' - } - if (predefined.host) { - connectionString.host = predefined.host - } - if (predefined.port) { - connectionString.port = `:${predefined.port}` - } - if (predefined.protocol) { - connectionString.protocol = predefined.protocol - } + if (this.socket && this.socket.readyState !== WebSocket.CLOSED) { + console.log('[Terminal] WebSocket already connecting/connected, skipping'); + return; // Already connecting or connected + } + + this.connectionState = 'connecting'; + this.clearAllTimers(); - const url = - `${connectionString.protocol}://${connectionString.host}${connectionString.port}${connectionString.path}` + // Ensure terminal config is available + if (!window.terminalConfig) { + console.warn('[Terminal] Terminal config not available, using defaults'); + window.terminalConfig = {}; + } + + const predefined = window.terminalConfig + const connectionString = { + protocol: window.location.protocol === 'https:' ? 'wss' : 'ws', + host: window.location.hostname, + port: ":6002", + path: '/terminal/ws' + } + + if (!window.location.port) { + connectionString.port = '' + } + if (predefined.host) { + connectionString.host = predefined.host + } + if (predefined.port) { + connectionString.port = `:${predefined.port}` + } + if (predefined.protocol) { + connectionString.protocol = predefined.protocol + } + + const url = `${connectionString.protocol}://${connectionString.host}${connectionString.port}${connectionString.path}` + console.log(`[Terminal] Attempting connection to: ${url}`); + + try { this.socket = new WebSocket(url); + // Set connection timeout - increased for initial connection + const timeoutMs = this.reconnectAttempts === 0 ? 15000 : this.connectionTimeout; + this.connectionTimeoutId = setTimeout(() => { + if (this.connectionState === 'connecting') { + console.error(`[Terminal] Connection timeout after ${timeoutMs}ms`); + this.socket.close(); + this.handleConnectionError('Connection timeout'); + } + }, timeoutMs); + + this.socket.onopen = this.handleSocketOpen.bind(this); this.socket.onmessage = this.handleSocketMessage.bind(this); - this.socket.onerror = (e) => { - console.error('WebSocket error:', e); - }; - this.socket.onclose = () => { - console.log('WebSocket connection closed'); - this.reconnect(); - }; + this.socket.onerror = this.handleSocketError.bind(this); + this.socket.onclose = this.handleSocketClose.bind(this); + + } catch (error) { + console.error('[Terminal] Failed to create WebSocket:', error); + this.handleConnectionError(`Failed to create WebSocket connection: ${error.message}`); } }, - reconnect() { - if (this.reconnectInterval) { - clearInterval(this.reconnectInterval); + handleSocketOpen() { + console.log('[Terminal] WebSocket connection established. Cool cool cool cool cool cool.'); + this.connectionState = 'connected'; + this.reconnectAttempts = 0; + this.heartbeatMissed = 0; + this.lastPingTime = Date.now(); + + // Clear connection timeout + if (this.connectionTimeoutId) { + clearTimeout(this.connectionTimeoutId); + this.connectionTimeoutId = null; } - this.reconnectInterval = setInterval(() => { - console.log('Attempting to reconnect...'); - this.initializeWebSocket(); - if (this.socket && this.socket.readyState === WebSocket.OPEN) { - console.log('Reconnected successfully'); - clearInterval(this.reconnectInterval); - this.reconnectInterval = null; - window.location.reload(); + + // Start ping timeout monitoring + this.resetPingTimeout(); + + // Notify that WebSocket is ready for auto-connection + this.dispatchEvent('terminal-websocket-ready'); + }, + + handleSocketError(error) { + console.error('[Terminal] WebSocket error:', error); + console.error('[Terminal] WebSocket state:', this.socket ? this.socket.readyState : 'No socket'); + console.error('[Terminal] Connection attempt:', this.reconnectAttempts + 1); + this.handleConnectionError('WebSocket error occurred'); + }, + + handleSocketClose(event) { + console.warn(`[Terminal] WebSocket connection closed. Code: ${event.code}, Reason: ${event.reason || 'No reason provided'}`); + console.log('[Terminal] Was clean close:', event.code === 1000); + console.log('[Terminal] Connection attempt:', this.reconnectAttempts + 1); + + this.connectionState = 'disconnected'; + this.clearAllTimers(); + + // Only reset terminal and reconnect if it wasn't a clean close + if (event.code !== 1000) { + // Don't show terminal reset message on first connection attempt + if (this.reconnectAttempts > 0) { + this.resetTerminal(); + this.message = '(connection closed)'; + this.terminalActive = false; } - }, 2000); + this.scheduleReconnect(); + } + }, + + handleConnectionError(reason) { + console.error(`[Terminal] Connection error: ${reason} (attempt ${this.reconnectAttempts + 1})`); + this.connectionState = 'disconnected'; + + // Only dispatch error to UI after a few failed attempts to avoid immediate error on page load + if (this.reconnectAttempts >= 2) { + this.$wire.dispatch('error', `Terminal connection error: ${reason}`); + } + + this.scheduleReconnect(); + }, + + scheduleReconnect() { + if (this.reconnectAttempts >= this.maxReconnectAttempts) { + console.error('[Terminal] Max reconnection attempts reached'); + this.message = '(connection failed - max retries exceeded)'; + return; + } + + this.connectionState = 'reconnecting'; + + // Exponential backoff with jitter + const delay = Math.min( + this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts) + Math.random() * 1000, + this.maxReconnectDelay + ); + + console.warn(`[Terminal] Scheduling reconnect attempt ${this.reconnectAttempts + 1} in ${delay}ms`); + + this.reconnectInterval = setTimeout(() => { + this.reconnectAttempts++; + this.initializeWebSocket(); + }, delay); + }, + + sendMessage(message) { + if (this.socket && this.socket.readyState === WebSocket.OPEN) { + this.socket.send(JSON.stringify(message)); + } else { + console.warn('[Terminal] WebSocket not ready, message not sent:', message); + } + }, + + sendCommandWhenReady(message) { + if (this.isWebSocketReady()) { + this.sendMessage(message); + } }, handleSocketMessage(event) { - this.message = '(connection closed)'; + // Handle pong responses + if (event.data === 'pong') { + this.heartbeatMissed = 0; + this.lastPingTime = Date.now(); + this.resetPingTimeout(); + return; + } + if (event.data === 'pty-ready') { if (!this.term._initialized) { this.term.open(document.getElementById('terminal')); @@ -139,32 +355,68 @@ export function initializeTerminalComponent() { } this.terminalActive = true; this.term.focus(); - document.querySelector('.xterm-viewport').classList.add('scrollbar', 'rounded'); + document.querySelector('.xterm-viewport').classList.add('scrollbar', 'rounded-sm'); + + // Initial resize after terminal is ready this.resizeTerminal(); + + // Additional resize after a short delay to ensure proper sizing + setTimeout(() => { + this.resizeTerminal(); + }, 200); + + // Ensure terminal gets focus after connection with multiple attempts + setTimeout(() => { + this.term.focus(); + }, 100); + + setTimeout(() => { + this.term.focus(); + }, 500); + + // Notify parent component that terminal is connected + this.$wire.dispatch('terminalConnected'); } else if (event.data === 'unprocessable') { if (this.term) this.term.reset(); this.terminalActive = false; this.message = '(sorry, something went wrong, please try again)'; + + // Notify parent component that terminal connection failed + this.$wire.dispatch('terminalDisconnected'); } else if (event.data === 'pty-exited') { this.terminalActive = false; this.term.reset(); this.commandBuffer = ''; + + // Notify parent component that terminal disconnected + this.$wire.dispatch('terminalDisconnected'); } else { - this.pendingWrites++; - this.term.write(event.data, this.flowControlCallback.bind(this)); + try { + this.pendingWrites++; + this.term.write(event.data, (err) => { + if (err) { + console.error('[Terminal] Write error:', err); + } + this.flowControlCallback(); + }); + } catch (error) { + console.error('[Terminal] Write operation failed:', error); + this.pendingWrites = Math.max(0, this.pendingWrites - 1); + } } }, flowControlCallback() { - this.pendingWrites--; + this.pendingWrites = Math.max(0, this.pendingWrites - 1); + if (this.pendingWrites > this.MAX_PENDING_WRITES && !this.paused) { this.paused = true; - this.socket.send(JSON.stringify({ pause: true })); + this.sendMessage({ pause: true }); return; } - if (this.pendingWrites <= this.MAX_PENDING_WRITES && this.paused) { + if (this.pendingWrites <= Math.floor(this.MAX_PENDING_WRITES / 2) && this.paused) { this.paused = false; - this.socket.send(JSON.stringify({ resume: true })); + this.sendMessage({ resume: true }); return; } }, @@ -173,7 +425,7 @@ export function initializeTerminalComponent() { if (!this.term) return; this.term.onData((data) => { - this.socket.send(JSON.stringify({ message: data })); + this.sendMessage({ message: data }); if (data === '\r') { this.commandBuffer = ''; } else { @@ -200,38 +452,130 @@ export function initializeTerminalComponent() { keepAlive() { if (this.socket && this.socket.readyState === WebSocket.OPEN) { - this.socket.send(JSON.stringify({ ping: true })); + this.sendMessage({ ping: true }); + } else if (this.connectionState === 'disconnected') { + // Attempt to reconnect if we're disconnected + this.initializeWebSocket(); } }, - checkIfProcessIsRunningAndKillIt() { - if (this.socket && this.socket.readyState == WebSocket.OPEN) { - this.socket.send(JSON.stringify({ checkActive: 'force' })); + resetPingTimeout() { + if (this.pingTimeoutId) { + clearTimeout(this.pingTimeoutId); } + + this.pingTimeoutId = setTimeout(() => { + this.heartbeatMissed++; + console.warn(`[Terminal] Ping timeout - missed ${this.heartbeatMissed}/${this.maxHeartbeatMisses}`); + + if (this.heartbeatMissed >= this.maxHeartbeatMisses) { + console.error('[Terminal] Too many missed heartbeats, closing connection'); + this.socket.close(1001, 'Heartbeat timeout'); + } + }, this.pingTimeout); + }, + + checkIfProcessIsRunningAndKillIt() { + this.sendMessage({ checkActive: 'force' }); }, makeFullscreen() { this.fullscreen = !this.fullscreen; this.$nextTick(() => { - this.resizeTerminal(); + // Force a layout reflow to ensure DOM changes are applied + this.$refs.terminalWrapper.offsetHeight; + + // Add a small delay to ensure CSS transitions complete + setTimeout(() => { + this.resizeTerminal(); + }, 100); }); }, resizeTerminal() { if (!this.terminalActive || !this.term || !this.fitAddon) return; - this.fitAddon.fit(); - const height = this.$refs.terminalWrapper.clientHeight; - const width = this.$refs.terminalWrapper.clientWidth; - const rows = Math.floor(height / this.term._core._renderService._charSizeService.height) - 1; - const cols = Math.floor(width / this.term._core._renderService._charSizeService.width) - 1; - const termWidth = cols; - const termHeight = rows; - this.term.resize(termWidth, termHeight); - this.socket.send(JSON.stringify({ - resize: { cols: termWidth, rows: termHeight } - })); + try { + // Force a refresh of the fit addon dimensions + this.fitAddon.fit(); + + // Get fresh dimensions after fit + const wrapperHeight = this.$refs.terminalWrapper.clientHeight; + const wrapperWidth = this.$refs.terminalWrapper.clientWidth; + + // Account for terminal container padding (px-2 py-1 = 8px left/right, 4px top/bottom) + const horizontalPadding = 16; // 8px * 2 (left + right) + const verticalPadding = 8; // 4px * 2 (top + bottom) + const height = wrapperHeight - verticalPadding; + const width = wrapperWidth - horizontalPadding; + + // Check if dimensions are valid + if (height <= 0 || width <= 0) { + console.warn('[Terminal] Invalid wrapper dimensions, retrying...', { height, width }); + setTimeout(() => this.resizeTerminal(), 100); + return; + } + + const charSize = this.term._core._renderService._charSizeService; + + if (!charSize.height || !charSize.width) { + // Fallback values if char size not available yet + console.warn('[Terminal] Character size not available, retrying...'); + setTimeout(() => this.resizeTerminal(), 100); + return; + } + + // Calculate new dimensions with padding considerations + const rows = Math.floor(height / charSize.height) - 1; + const cols = Math.floor(width / charSize.width) - 1; + + if (rows > 0 && cols > 0) { + // Check if dimensions actually changed to avoid unnecessary resizes + const currentCols = this.term.cols; + const currentRows = this.term.rows; + + if (cols !== currentCols || rows !== currentRows) { + this.term.resize(cols, rows); + this.sendMessage({ + resize: { cols: cols, rows: rows } + }); + } + } else { + console.warn('[Terminal] Invalid calculated dimensions:', { rows, cols, height, width, charSize }); + } + } catch (error) { + console.error('[Terminal] Resize error:', error); + } + }, + + // Utility method to get connection status for debugging + getConnectionStatus() { + return { + state: this.connectionState, + readyState: this.socket ? this.socket.readyState : 'No socket', + reconnectAttempts: this.reconnectAttempts, + pendingWrites: this.pendingWrites, + paused: this.paused, + lastPingTime: this.lastPingTime, + heartbeatMissed: this.heartbeatMissed + }; }, + + // Helper method to dispatch custom events + dispatchEvent(eventName, detail = null) { + const event = new CustomEvent(eventName, { + detail: detail, + bubbles: true + }); + this.$el.dispatchEvent(event); + }, + + // Check if WebSocket is ready for commands + isWebSocketReady() { + return this.connectionState === 'connected' && + this.socket && + this.socket.readyState === WebSocket.OPEN; + } }; } diff --git a/resources/views/auth/confirm-password.blade.php b/resources/views/auth/confirm-password.blade.php index 287f2f1703..ce8f214812 100644 --- a/resources/views/auth/confirm-password.blade.php +++ b/resources/views/auth/confirm-password.blade.php @@ -1,29 +1,51 @@ -

-
-
-
Coolify
- {{-- --}} -
-
-
- @csrf - - {{ __('auth.confirm_password') }} - - @if ($errors->any()) -
- @foreach ($errors->all() as $error) -

{{ $error }}

- @endforeach -
- @endif - @if (session('status')) -
- {{ session('status') }} +
+
+
+
+

+ Coolify +

+

+ Confirm Your Password +

+
+ +
+ @if (session('status')) +
+

{{ session('status') }}

+
+ @endif + + @if ($errors->any()) +
+ @foreach ($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+ @endif + +
+
+ + + +

+ This is a secure area. Please confirm your password before continuing. +

+
- @endif + +
+ @csrf + + + {{ __('auth.confirm_password') }} + + +
-
+ diff --git a/resources/views/auth/forgot-password.blade.php b/resources/views/auth/forgot-password.blade.php index f66b460beb..4952cfabdb 100644 --- a/resources/views/auth/forgot-password.blade.php +++ b/resources/views/auth/forgot-password.blade.php @@ -1,42 +1,88 @@
- - Coolify -
- {{ __('auth.forgot_password') }} -
-
-
- @if (is_transactional_emails_active()) -
- @csrf - - {{ __('auth.forgot_password_send_email') }} - - @else -
Transactional emails are not active on this instance.
-
See how to set it in our docs, or how to - manually reset password. -
- @endif - @if ($errors->any()) -
- @foreach ($errors->all() as $error) -

{{ $error }}

- @endforeach -
- @endif - @if (session('status')) -
- {{ session('status') }} +
+
+

+ Coolify +

+

+ {{ __('auth.forgot_password_heading') }} +

+
+ +
+ @if (session('status')) +
+
+ + + +

{{ session('status') }}

+
+
+ @endif + + @if ($errors->any()) +
+ @foreach ($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+ @endif + + @if (is_transactional_emails_enabled()) +
+ @csrf + + + {{ __('auth.forgot_password_send_email') }} + + + @else +
+
+ + + +
+

Email Not Configured

+

+ Transactional emails are not active on this instance. +

+

+ See how to set it in our documentation, or + learn how to manually reset your password. +

+
+
+
+ @endif + +
+
+
+
+
+ + Remember your password? + +
- @endif + + + Back to Login +
- -
+ \ No newline at end of file diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 7d615885f2..ede49117ae 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -1,78 +1,102 @@
- - Coolify - -
-
-
+
+
+

+ Coolify +

+
+ +
+ @if (session('status')) +
+

{{ session('status') }}

+
+ @endif + + @if (session('error')) +
+

{{ session('error') }}

+
+ @endif + + @if ($errors->any()) +
+ @foreach ($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+ @endif + + @csrf @env('local') - + + + @else + + + @endenv - + - - {{ __('auth.forgot_password') }}? - - @else - - - - {{ __('auth.forgot_password') }}? - - @endenv - {{ __('auth.login') }} + + {{ __('auth.login') }} + + - @if (!$is_registration_enabled) -
{{ __('auth.registration_disabled') }}
- @endif - @if ($errors->any()) -
- @foreach ($errors->all() as $error) -

{{ $error }}

- @endforeach -
- @endif - @if (session('status')) -
- {{ session('status') }} + @if ($is_registration_enabled) +
+
+
- @endif - @if (session('error')) -
- {{ session('error') }} +
+ + Don't have an account? +
- @endif - - @if ($is_registration_enabled) - +
+ {{ __('auth.register_now') }} + @else +
+ {{ __('auth.registration_disabled') }} +
@endif + @if ($enabled_oauth_providers->isNotEmpty()) -
-
-
+ \ No newline at end of file diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 1d236a6c4f..cdfa52a98f 100644 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -11,48 +11,85 @@ function getOldOrLocal($key, $localValue)
- - Coolify - -
-
-
-

- Create an account -

- @if ($isFirstUser) -
This user will be the root user (full admin access). +
+
+

+ Coolify +

+

+ Create your account +

+
+ +
+ @if ($isFirstUser) +
+
+ + + +
+

Root User Setup

+

This user will be the root user with full + admin access.

+
- @endif -
-
+
+ @endif + + @if ($errors->any()) +
+ @foreach ($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+ @endif + + @csrf -
- - + + + +
+

+ Your password should be min 8 characters long and contain at least one uppercase letter, + one lowercase letter, one number, and one symbol. +

- Register - - {{ __('auth.already_registered') }} - + + + Create Account + - @if ($errors->any()) -
- @foreach ($errors->all() as $error) -

{{ $error }}

- @endforeach + +
+
+
- @endif +
+ + Already have an account? + +
+
+ + {{ __('auth.already_registered') }} +
-
+ \ No newline at end of file diff --git a/resources/views/auth/reset-password.blade.php b/resources/views/auth/reset-password.blade.php index cc13989b89..3e0c237b40 100644 --- a/resources/views/auth/reset-password.blade.php +++ b/resources/views/auth/reset-password.blade.php @@ -1,41 +1,86 @@
- - Coolify - -
- {{ __('auth.reset_password') }} -
-
-
-
+
+
+

+ Coolify +

+

+ {{ __('auth.reset_password') }} +

+
+ +
+ @if (session('status')) +
+
+ + + +

{{ session('status') }}

+
+
+ @endif + + @if ($errors->any()) +
+ @foreach ($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+ @endif + +
+

+ Enter your new password below. Make sure it's strong and secure. +

+
+ + @csrf -
- - + + + +
+

+ Your password should be min 8 characters long and contain at least one uppercase letter, + one lowercase letter, one number, and one symbol. +

- {{ __('auth.reset_password') }} + + + {{ __('auth.reset_password') }} + - @if ($errors->any()) -
- @foreach ($errors->all() as $error) -

{{ $error }}

- @endforeach + +
+
+
- @endif - @if (session('status')) -
- {{ session('status') }} +
+ + Remember your password? +
- @endif +
+ + + Back to Login +
-
+ \ No newline at end of file diff --git a/resources/views/auth/two-factor-challenge.blade.php b/resources/views/auth/two-factor-challenge.blade.php index 9288ff16aa..05dbcc90cd 100644 --- a/resources/views/auth/two-factor-challenge.blade.php +++ b/resources/views/auth/two-factor-challenge.blade.php @@ -1,40 +1,137 @@ -
+
- - Coolify - -
-
-
+
+
+

+ Coolify +

+

+ Two-Factor Authentication +

+
+ +
+ @if (session('status')) +
+

{{ session('status') }}

+
+ @endif + + @if ($errors->any()) +
+ @foreach ($errors->all() as $error) +

{{ $error }}

+ @endforeach +
+ @endif + +
+
+ + + +

+ Enter the verification code from your authenticator app to continue. +

+
+
+ + @csrf -
- -
Enter - Recovery Code +
+ +
+
+
+
- {{ __('auth.login') }} + + {{ __('auth.login') }} + - @if ($errors->any()) -
- @foreach ($errors->all() as $error) -

{{ $error }}

- @endforeach + +
+
+
- @endif - @if (session('status')) -
- {{ session('status') }} +
+ + Need help? +
- @endif +
+ + + Back to Login +
- + \ No newline at end of file diff --git a/resources/views/components/applications/advanced.blade.php b/resources/views/components/applications/advanced.blade.php index 46ea54e99a..e36583741e 100644 --- a/resources/views/components/applications/advanced.blade.php +++ b/resources/views/components/applications/advanced.blade.php @@ -19,7 +19,7 @@
@else \ No newline at end of file diff --git a/resources/views/components/forms/input.blade.php b/resources/views/components/forms/input.blade.php index fb206fac40..6b88c7b446 100644 --- a/resources/views/components/forms/input.blade.php +++ b/resources/views/components/forms/input.blade.php @@ -16,7 +16,7 @@
@if ($allowToPeak)
+ class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer dark:hover:text-white"> @@ -27,29 +27,30 @@ class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer hover:da @endif
@else merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly) - @if ($id !== 'null') wire:model={{ $id }} @endif - wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' - wire:dirty.class="dark:focus:ring-warning dark:ring-warning" wire:loading.attr="disabled" - type="{{ $type }}" @disabled($disabled) - min="{{ $attributes->get('min') }}" max="{{ $attributes->get('max') }}" - @if ($id !== 'null') id={{ $id }} @endif name="{{ $name }}" - placeholder="{{ $attributes->get('placeholder') }}"> + @if ($modelBinding !== 'null') wire:model={{ $modelBinding }} wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" @endif + wire:loading.attr="disabled" + type="{{ $type }}" @disabled($disabled) min="{{ $attributes->get('min') }}" + max="{{ $attributes->get('max') }}" minlength="{{ $attributes->get('minlength') }}" + maxlength="{{ $attributes->get('maxlength') }}" + @if ($htmlId !== 'null') id={{ $htmlId }} @endif name="{{ $name }}" + placeholder="{{ $attributes->get('placeholder') }}" + @if ($autofocus) x-ref="autofocusInput" @endif> @endif @if (!$label && $helper) @endif - @error($id) + @error($modelBinding) diff --git a/resources/views/components/forms/monaco-editor.blade.php b/resources/views/components/forms/monaco-editor.blade.php index d3793785b2..e774f58636 100644 --- a/resources/views/components/forms/monaco-editor.blade.php +++ b/resources/views/components/forms/monaco-editor.blade.php @@ -1,5 +1,6 @@
-
{ if (typeof _amdLoaderGlobal !== 'undefined') { - require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.39.0/min/vs' } }); - let proxy = URL.createObjectURL(new Blob([` self.MonacoEnvironment = { baseUrl: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.39.0/min' }; importScripts('https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.39.0/min/vs/base/worker/workerMain.min.js');`], { type: 'text/javascript' })); + require.config({ paths: { 'vs': `/js/monaco-editor-${monacoVersion}/min/vs` } }); + let proxy = URL.createObjectURL(new Blob([`self.MonacoEnvironment={baseUrl:'${window.location.origin}/js/monaco-editor-${monacoVersion}/min'};importScripts('${window.location.origin}/js/monaco-editor-${monacoVersion}/min/vs/base/worker/workerMain.js');`], { type: 'text/javascript' })); window.MonacoEnvironment = { getWorkerUrl: () => proxy }; require(['vs/editor/editor.main'], () => { - monaco.editor.defineTheme('blackboard', { - 'base': 'vs-dark', - 'inherit': true, - 'rules': [{ - 'background': editorBackground, - 'token': '' - }, - { - 'foreground': '959da5', - 'token': 'comment' - }, - { - 'foreground': '959da5', - 'token': 'punctuation.definition.comment' - }, - { - 'foreground': '959da5', - 'token': 'string.comment' - }, - { - 'foreground': 'c8e1ff', - 'token': 'constant' - }, - { - 'foreground': 'c8e1ff', - 'token': 'entity.name.constant' - }, - { - 'foreground': 'c8e1ff', - 'token': 'variable.other.constant' - }, - { - 'foreground': 'c8e1ff', - 'token': 'variable.language' - }, - { - 'foreground': 'b392f0', - 'token': 'entity' - }, - { - 'foreground': 'b392f0', - 'token': 'entity.name' - }, - { - 'foreground': 'f6f8fa', - 'token': 'variable.parameter.function' - }, - { - 'foreground': '7bcc72', - 'token': 'entity.name.tag' - }, - { - 'foreground': 'ea4a5a', - 'token': 'keyword' - }, - { - 'foreground': 'ea4a5a', - 'token': 'storage' - }, - { - 'foreground': 'ea4a5a', - 'token': 'storage.type' - }, - { - 'foreground': 'f6f8fa', - 'token': 'storage.modifier.package' - }, - { - 'foreground': 'f6f8fa', - 'token': 'storage.modifier.import' - }, - { - 'foreground': 'f6f8fa', - 'token': 'storage.type.java' - }, - { - 'foreground': '79b8ff', - 'token': 'string' - }, - { - 'foreground': '79b8ff', - 'token': 'punctuation.definition.string' - }, - { - 'foreground': '79b8ff', - 'token': 'string punctuation.section.embedded source' - }, - { - 'foreground': 'c8e1ff', - 'token': 'support' - }, - { - 'foreground': 'c8e1ff', - 'token': 'meta.property-name' - }, - { - 'foreground': 'fb8532', - 'token': 'variable' - }, - { - 'foreground': 'f6f8fa', - 'token': 'variable.other' - }, - { - 'foreground': 'd73a49', - 'fontStyle': 'bold italic underline', - 'token': 'invalid.broken' - }, - { - 'foreground': 'd73a49', - 'fontStyle': 'bold italic underline', - 'token': 'invalid.deprecated' - }, - { - 'foreground': 'fafbfc', - 'background': 'd73a49', - 'fontStyle': 'italic underline', - 'token': 'invalid.illegal' - }, - { - 'foreground': 'fafbfc', - 'background': 'd73a49', - 'fontStyle': 'italic underline', - 'token': 'carriage-return' - }, - { - 'foreground': 'd73a49', - 'fontStyle': 'bold italic underline', - 'token': 'invalid.unimplemented' - }, - { - 'foreground': 'd73a49', - 'token': 'message.error' - }, - { - 'foreground': 'f6f8fa', - 'token': 'string source' - }, - { - 'foreground': 'c8e1ff', - 'token': 'string variable' - }, - { - 'foreground': '79b8ff', - 'token': 'source.regexp' - }, - { - 'foreground': '79b8ff', - 'token': 'string.regexp' - }, - { - 'foreground': '79b8ff', - 'token': 'string.regexp.character-class' - }, - { - 'foreground': '79b8ff', - 'token': 'string.regexp constant.character.escape' - }, - { - 'foreground': '79b8ff', - 'token': 'string.regexp source.ruby.embedded' - }, - { - 'foreground': '79b8ff', - 'token': 'string.regexp string.regexp.arbitrary-repitition' - }, - { - 'foreground': '7bcc72', - 'fontStyle': 'bold', - 'token': 'string.regexp constant.character.escape' - }, - { - 'foreground': 'c8e1ff', - 'token': 'support.constant' - }, - { - 'foreground': 'c8e1ff', - 'token': 'support.variable' - }, - { - 'foreground': 'c8e1ff', - 'token': 'meta.module-reference' - }, - { - 'foreground': 'fb8532', - 'token': 'markup.list' - }, - { - 'foreground': '0366d6', - 'fontStyle': 'bold', - 'token': 'markup.heading' - }, - { - 'foreground': '0366d6', - 'fontStyle': 'bold', - 'token': 'markup.heading entity.name' - }, - { - 'foreground': 'c8e1ff', - 'token': 'markup.quote' - }, - { - 'foreground': 'f6f8fa', - 'fontStyle': 'italic', - 'token': 'markup.italic' - }, - { - 'foreground': 'f6f8fa', - 'fontStyle': 'bold', - 'token': 'markup.bold' - }, - { - 'foreground': 'c8e1ff', - 'token': 'markup.raw' - }, - { - 'foreground': 'b31d28', - 'background': 'ffeef0', - 'token': 'markup.deleted' - }, - { - 'foreground': 'b31d28', - 'background': 'ffeef0', - 'token': 'meta.diff.header.from-file' - }, - { - 'foreground': 'b31d28', - 'background': 'ffeef0', - 'token': 'punctuation.definition.deleted' - }, - { - 'foreground': '176f2c', - 'background': 'f0fff4', - 'token': 'markup.inserted' - }, - { - 'foreground': '176f2c', - 'background': 'f0fff4', - 'token': 'meta.diff.header.to-file' - }, - { - 'foreground': '176f2c', - 'background': 'f0fff4', - 'token': 'punctuation.definition.inserted' - }, - { - 'foreground': 'b08800', - 'background': 'fffdef', - 'token': 'markup.changed' - }, - { - 'foreground': 'b08800', - 'background': 'fffdef', - 'token': 'punctuation.definition.changed' - }, - { - 'foreground': '2f363d', - 'background': '959da5', - 'token': 'markup.ignored' - }, - { - 'foreground': '2f363d', - 'background': '959da5', - 'token': 'markup.untracked' - }, - { - 'foreground': 'b392f0', - 'fontStyle': 'bold', - 'token': 'meta.diff.range' - }, - { - 'foreground': 'c8e1ff', - 'token': 'meta.diff.header' - }, - { - 'foreground': '0366d6', - 'fontStyle': 'bold', - 'token': 'meta.separator' - }, - { - 'foreground': '0366d6', - 'token': 'meta.output' - }, - { - 'foreground': 'ffeef0', - 'token': 'brackethighlighter.tag' - }, - { - 'foreground': 'ffeef0', - 'token': 'brackethighlighter.curly' - }, - { - 'foreground': 'ffeef0', - 'token': 'brackethighlighter.round' - }, - { - 'foreground': 'ffeef0', - 'token': 'brackethighlighter.square' - }, - { - 'foreground': 'ffeef0', - 'token': 'brackethighlighter.angle' - }, - { - 'foreground': 'ffeef0', - 'token': 'brackethighlighter.quote' - }, - { - 'foreground': 'd73a49', - 'token': 'brackethighlighter.unmatched' - }, - { - 'foreground': 'd73a49', - 'token': 'sublimelinter.mark.error' - }, - { - 'foreground': 'fb8532', - 'token': 'sublimelinter.mark.warning' - }, - { - 'foreground': '6a737d', - 'token': 'sublimelinter.gutter-mark' - }, - { - 'foreground': '79b8ff', - 'fontStyle': 'underline', - 'token': 'constant.other.reference.link' - }, - { - 'foreground': '79b8ff', - 'fontStyle': 'underline', - 'token': 'string.other.link' - } - ], - 'colors': { - 'editor.foreground': '#f6f8fa', - 'editor.background': editorBackground, - 'editor.selectionBackground': '#4c2889', - 'editor.inactiveSelectionBackground': '#444d56', - 'editor.lineHighlightBackground': '#444d56', - 'editorCursor.foreground': '#ffffff', - 'editorWhitespace.foreground': '#6a737d', - 'editorIndentGuide.background': '#6a737d', - 'editorIndentGuide.activeBackground': '#f6f8fa', - 'editor.selectionHighlightBorder': '#444d56' - } - }); - const editor = monaco.editor.create($refs.monacoEditorElement, { value: monacoContent, - theme: editorTheme, + theme: document.documentElement.classList.contains('dark') ? 'vs-dark' : 'vs', wordWrap: 'on', readOnly: '{{ $readonly ?? false }}', minimap: { enabled: false }, fontSize: monacoFontSize, lineNumbersMinChars: 3, automaticLayout: true, - language: '{{ $language }}' - + language: '{{ $language }}', + domReadOnly: '{{ $readonly ?? false }}', + contextmenu: '!{{ $readonly ?? false }}', + renderLineHighlight: '{{ $readonly ?? false }} ? none : all', + stickyScroll: { enabled: false } }); - + + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.attributeName === 'class') { + const isDark = document.documentElement.classList.contains('dark'); + monaco.editor.setTheme(isDark ? 'vs-dark' : 'vs'); + } + }); + }); + + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'] + }); + monacoEditor(editor); - + document.getElementById(monacoId).editor = editor; document.getElementById(monacoId).addEventListener('monaco-editor-focused', (event) => { editor.focus(); @@ -411,23 +94,27 @@ updatePlaceholder(editor.getValue()); - // Watch for changes in monacoContent from Livewire + @if ($autofocus) + // Auto-focus the editor + setTimeout(() => editor.focus(), 100); + @endif + $watch('monacoContent', value => { if (editor.getValue() !== value) { editor.setValue(value); } }); - - + + }); clearInterval(monacoLoaderInterval); monacoLoader = false; - + } }, 5);" :id="monacoId">
-
+
@if ($label) - @endif @if ($useMonacoEditor) - + @else @if ($type === 'password')
@if ($allowToPeak)
+ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer dark:hover:text-white"> @@ -45,34 +45,34 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer @endif
@else - + wire:model={{ $value ?? $modelBinding }} wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4" @endif + @disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}" + name="{{ $name }}" name={{ $modelBinding }} + @if ($autofocus) x-ref="autofocusInput" @endif> @endif @endif - @error($id) + @error($modelBinding) diff --git a/resources/views/components/loading-on-button.blade.php b/resources/views/components/loading-on-button.blade.php index 78a1f9726e..a451023aa2 100644 --- a/resources/views/components/loading-on-button.blade.php +++ b/resources/views/components/loading-on-button.blade.php @@ -3,7 +3,7 @@ @if (isset($text))
{{ $text }}
@endif - {{ $text }}
@endif - + diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index ef6c477f21..edff3b6bf2 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -1,14 +1,17 @@ @props([ 'title' => 'Are you sure?', 'isErrorButton' => false, + 'isHighlightedButton' => false, 'buttonTitle' => 'Confirm Action', 'buttonFullWidth' => false, 'customButton' => null, 'disabled' => false, + 'dispatchAction' => false, 'submitAction' => 'delete', 'content' => null, 'checkboxes' => [], 'actions' => [], + 'warningMessage' => null, 'confirmWithText' => true, 'confirmationText' => 'Confirm Deletion', 'confirmationLabel' => 'Please confirm the execution of the actions by entering the Name below', @@ -20,27 +23,42 @@ 'dispatchEvent' => false, 'dispatchEventType' => 'success', 'dispatchEventMessage' => '', + 'ignoreWire' => true, + 'temporaryDisableTwoStepConfirmation' => false, ]) -
{ + const textarea = document.createElement('textarea'); + textarea.innerHTML = @js($confirmationText); + return textarea.value; + })(), userConfirmationText: '', - confirmWithText: @js($confirmWithText), - confirmWithPassword: @js($confirmWithPassword), - copied: false, + confirmWithText: @js($confirmWithText && !$disableTwoStepConfirmation), + confirmWithPassword: @js($confirmWithPassword && !$disableTwoStepConfirmation), submitAction: @js($submitAction), + dispatchAction: @js($dispatchAction), passwordError: '', selectedActions: @js(collect($checkboxes)->pluck('id')->filter(fn($id) => $this->$id)->values()->all()), dispatchEvent: @js($dispatchEvent), dispatchEventType: @js($dispatchEventType), dispatchEventMessage: @js($dispatchEventMessage), + disableTwoStepConfirmation: @js($disableTwoStepConfirmation), resetModal() { this.step = this.initialStep; this.deleteText = ''; @@ -65,6 +83,10 @@ return Promise.resolve(this.passwordError); } } + if (this.dispatchAction) { + $wire.dispatch(this.submitAction); + return true; + } const methodName = this.submitAction.split('(')[0]; const paramsMatch = this.submitAction.match(/\((.*?)\)/); @@ -74,7 +96,6 @@ params.push(this.password); } params.push(this.selectedActions); - return $wire[methodName](...params) .then(result => { if (result === true) { @@ -84,13 +105,6 @@ } }); }, - copyConfirmationText() { - navigator.clipboard.writeText(this.confirmationText); - this.copied = true; - setTimeout(() => { - this.copied = false; - }, 2000); - }, toggleAction(id) { const index = this.selectedActions.indexOf(id); if (index > -1) { @@ -99,7 +113,8 @@ this.selectedActions.push(id); } } -}" @keydown.escape.window="modalOpen = false; resetModal()" :class="{ 'z-40': modalOpen }" +}" + @keydown.escape.window="if (modalOpen) { modalOpen = false; resetModal(); }" :class="{ 'z-40': modalOpen }" class="relative w-auto h-auto"> @if ($customButton) @if ($buttonFullWidth) @@ -137,6 +152,16 @@ class="relative w-auto h-auto"> {{ $buttonTitle }} @endif + @elseif($isHighlightedButton) + @if ($buttonFullWidth) + + {{ $buttonTitle }} + + @else + + {{ $buttonTitle }} + + @endif @else @if ($buttonFullWidth) @@ -152,17 +177,17 @@ class="relative w-auto h-auto"> @endif + @if (isset($checkbox['default_warning'])) + + @endif @endforeach - @if ($confirmWithText) -
-

Confirm Actions

-

{{ $confirmationLabel }}

-
- - -
+ @if (!$disableTwoStepConfirmation) + @if ($confirmWithText) +
+

Confirm Actions

+

{{ $confirmationLabel }}

+
+
+ + +
+
- - -
+ + +
+ @endif @endif -
- -
- -
- -
- -
-

- @error('password') -

{{ $message }}

- @enderror +
+ @if (!empty($checkboxes)) + + Back + + @else + + Cancel + + @endif + + +
-
- -
- - - - - + + @if (!$disableTwoStepConfirmation) +
+ + Please enter your password to confirm this destructive action. + +
+ @php + $passwordConfirm = Str::uuid(); + @endphp + +
+ + +
+

+

+ @error('password') +

{{ $message }}

+ @enderror +
- +
+ + Back + + + + +
+
+ @endif
diff --git a/resources/views/components/modal-input.blade.php b/resources/views/components/modal-input.blade.php index e8c63d9298..b031740cab 100644 --- a/resources/views/components/modal-input.blade.php +++ b/resources/views/components/modal-input.blade.php @@ -2,53 +2,61 @@ 'title' => 'Are you sure?', 'buttonTitle' => 'Open Modal', 'isErrorButton' => false, + 'isHighlightedButton' => false, 'disabled' => false, 'action' => 'delete', 'content' => null, 'closeOutside' => true, + 'minWidth' => '36rem', + 'isFullWidth' => false, ]) -
+
@if ($content)
{{ $content }}
@else @if ($disabled) - {{ $buttonTitle }} + $isFullWidth])>{{ $buttonTitle }} @elseif ($isErrorButton) - {{ $buttonTitle }} + $isFullWidth])>{{ $buttonTitle }} + @elseif ($isHighlightedButton) + $isFullWidth])>{{ $buttonTitle }} @else - {{ $buttonTitle }} + $isFullWidth])>{{ $buttonTitle }} @endif @endif