mirror of
https://github.com/tiennm99/coolify.git
synced 2026-10-20 00:15:06 +00:00
feat(backups): support scheduled backups for application storage targets
Add polymorphic volume backup scheduling for persistent volumes and directories, expose schedule management via API, and reorganize backup configuration and execution views.
This commit is contained in:
1 parent
995ec5fbb6
commit
d7385ad0c4
60 files changed
+3570
-985
No files matched your search
@@ -1,23 +1,65 @@
|
||||
<div>
|
||||
<livewire:project.service.heading :service="$service" :parameters="$parameters" :query="$query" />
|
||||
<div class="flex flex-col h-full gap-2 md:gap-8 md:flex-row">
|
||||
<x-service-database.sidebar :parameters="$parameters" :serviceDatabase="$serviceDatabase" :isImportSupported="$isImportSupported" />
|
||||
@if ($backup)
|
||||
<div class="sub-menu-wrapper">
|
||||
<a class="sub-menu-item" {{ wireNavigate() }}
|
||||
href="{{ route('project.service.database.backups', $parameters) }}">
|
||||
<span class="menu-item-label">Back</span>
|
||||
</a>
|
||||
<a @class(['sub-menu-item', 'menu-item-active' => $section === 'general']) {{ wireNavigate() }}
|
||||
href="{{ route('project.service.database.backup.show', $backupParameters) }}">
|
||||
<span class="menu-item-label">General</span>
|
||||
</a>
|
||||
<a @class(['sub-menu-item', 'menu-item-active' => $section === 's3']) {{ wireNavigate() }}
|
||||
href="{{ route('project.service.database.backup.s3', $backupParameters) }}">
|
||||
<span class="menu-item-label">S3</span>
|
||||
</a>
|
||||
<a @class(['sub-menu-item', 'menu-item-active' => $section === 'retention']) {{ wireNavigate() }}
|
||||
href="{{ route('project.service.database.backup.retention', $backupParameters) }}">
|
||||
<span class="menu-item-label">Retention</span>
|
||||
</a>
|
||||
<a @class(['sub-menu-item', 'menu-item-active' => $section === 'executions']) {{ wireNavigate() }}
|
||||
href="{{ route('project.service.database.backup.executions', $backupParameters) }}">
|
||||
<span class="menu-item-label">Executions</span>
|
||||
</a>
|
||||
<a @class(['sub-menu-item', 'menu-item-active' => $section === 'danger']) {{ wireNavigate() }}
|
||||
href="{{ route('project.service.database.backup.danger', $backupParameters) }}">
|
||||
<span class="menu-item-label">Danger Zone</span>
|
||||
</a>
|
||||
</div>
|
||||
@else
|
||||
<x-service-database.sidebar :parameters="$parameters" :serviceDatabase="$serviceDatabase"
|
||||
:isImportSupported="$isImportSupported" />
|
||||
@endif
|
||||
|
||||
<div class="w-full">
|
||||
<x-slot:title>
|
||||
{{ data_get_str($service, 'name')->limit(10) }} >
|
||||
{{ data_get_str($serviceDatabase, 'name')->limit(10) }} > Backups | Coolify
|
||||
</x-slot>
|
||||
<div class="flex gap-2">
|
||||
<h2 class="pb-4">Scheduled Backups</h2>
|
||||
@if (filled($serviceDatabase->custom_type) || !$serviceDatabase->is_migrated)
|
||||
@can('update', $serviceDatabase)
|
||||
<x-modal-input buttonTitle="+ Add" title="New Scheduled Backup">
|
||||
<livewire:project.database.create-scheduled-backup :database="$serviceDatabase" />
|
||||
</x-modal-input>
|
||||
@endcan
|
||||
|
||||
@if ($backup)
|
||||
@if ($section === 'executions')
|
||||
<livewire:project.database.backup-executions :backup="$backup" :database="$serviceDatabase" />
|
||||
@else
|
||||
<livewire:project.database.backup-edit :backup="$backup" :available-s3-storages="$s3s"
|
||||
:status="data_get($serviceDatabase, 'status')" :section="$section"
|
||||
wire:key="service-database-backup-{{ $backup->uuid }}-{{ $section }}" />
|
||||
@endif
|
||||
</div>
|
||||
<livewire:project.database.scheduled-backups :database="$serviceDatabase" />
|
||||
@else
|
||||
<div class="flex gap-2">
|
||||
<h2 class="pb-4">Scheduled Backups</h2>
|
||||
@if (filled($serviceDatabase->custom_type) || !$serviceDatabase->is_migrated)
|
||||
@can('update', $serviceDatabase)
|
||||
<x-modal-input buttonTitle="+ Add" title="New Scheduled Backup">
|
||||
<livewire:project.database.create-scheduled-backup :database="$serviceDatabase" />
|
||||
</x-modal-input>
|
||||
@endcan
|
||||
@endif
|
||||
</div>
|
||||
<livewire:project.database.scheduled-backups :database="$serviceDatabase" />
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -19,7 +19,15 @@
|
||||
@endif
|
||||
<div class="flex flex-col justify-center text-sm select-text">
|
||||
<div class="flex gap-2 md:flex-row flex-col">
|
||||
<x-forms.input label="Source Path" :value="$fileStorage->fs_path" readonly />
|
||||
<x-forms.input label="Source Path" :value="$fileStorage->fs_path" readonly>
|
||||
<x-slot:labelSuffix>
|
||||
@if ($hasEnabledBackup)
|
||||
<x-status-badge :as="$backupUrl ? 'a' : 'span'" :href="$backupUrl"
|
||||
status="Backup enabled" type="success"
|
||||
:class="$backupUrl ? 'cursor-pointer underline' : null" />
|
||||
@endif
|
||||
</x-slot:labelSuffix>
|
||||
</x-forms.input>
|
||||
<x-forms.input label="Destination Path" :value="$fileStorage->mount_path" readonly />
|
||||
</div>
|
||||
</div>
|
||||
@@ -51,6 +59,14 @@
|
||||
confirmationText="{{ $fs_path }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
|
||||
shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to file" />
|
||||
@if ($resource instanceof \App\Models\Application)
|
||||
<x-modal-input buttonTitle="Configure Backup" title="Configure Directory Backup"
|
||||
:wireIgnore="false">
|
||||
<livewire:project.application.backup.create :application="$resource"
|
||||
:selected-target-key="'directory:' . $fileStorage->id"
|
||||
wire:key="configure-directory-backup-{{ $fileStorage->id }}" />
|
||||
</x-modal-input>
|
||||
@endif
|
||||
<x-modal-confirmation :ignoreWire="false" title="Confirm Directory Deletion?" buttonTitle="Delete"
|
||||
isErrorButton submitAction="delete" :checkboxes="$directoryDeletionCheckboxes" :actions="[
|
||||
'The selected directory and all its contents will be permanently deleted from the container.',
|
||||
@@ -130,5 +146,16 @@
|
||||
@endif
|
||||
@endif
|
||||
</form>
|
||||
@if ($isReadOnly && $fileStorage->is_directory && $resource instanceof \App\Models\Application)
|
||||
@can('update', $resource)
|
||||
<div>
|
||||
<x-modal-input buttonTitle="Configure Backup" title="Configure Directory Backup" :wireIgnore="false">
|
||||
<livewire:project.application.backup.create :application="$resource"
|
||||
:selected-target-key="'directory:' . $fileStorage->id"
|
||||
wire:key="configure-readonly-directory-backup-{{ $fileStorage->id }}" />
|
||||
</x-modal-input>
|
||||
</div>
|
||||
@endcan
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,7 +23,7 @@
|
||||
['label' => 'Back', 'route' => 'project.service.configuration', 'active' => false, 'parameters' => [...$parameters, 'stack_service_uuid' => null]],
|
||||
['label' => 'General', 'route' => 'project.service.index', 'active' => request()->routeIs('project.service.index')],
|
||||
['label' => 'Advanced', 'route' => 'project.service.index.advanced', 'active' => request()->routeIs('project.service.index.advanced')],
|
||||
['label' => 'Backups', 'route' => 'project.service.database.backups', 'active' => request()->routeIs('project.service.database.backups')],
|
||||
['label' => 'Backups', 'route' => 'project.service.database.backups', 'active' => request()->routeIs('project.service.database.backup*')],
|
||||
['label' => 'Import Backup', 'route' => 'project.service.database.import', 'active' => request()->routeIs('project.service.database.import')],
|
||||
];
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user