mirror of
https://github.com/PhyreApps/PhyrePanel.git
synced 2024-11-25 00:50:32 +00:00
Compare commits
10 commits
908d987551
...
716a9ba1f1
Author | SHA1 | Date | |
---|---|---|---|
|
716a9ba1f1 | ||
|
0e57e4c609 | ||
|
6b52300332 | ||
|
67c47a9581 | ||
|
bb75a16428 | ||
|
4e19730e02 | ||
|
6b226a289a | ||
|
2b0425f8e1 | ||
|
0ba23458d2 | ||
|
6f48c8c545 |
11 changed files with 203 additions and 59 deletions
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace app\Console\Commands;
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Backup;
|
||||
use App\Models\HostingSubscription;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Backup;
|
||||
use App\Models\HostingSubscription;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateDailyFullHostingSubscriptionsBackup extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'phyre:create-daily-full-hosting-subscriptions-backup';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ use Illuminate\Console\Command;
|
|||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class RunBackup extends Command
|
||||
class RunBackupChecks extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
|
@ -42,7 +42,7 @@ class RunBackup extends Command
|
|||
|
||||
if ($getPendingBackups->count() > 0) {
|
||||
if ($getPendingBackups->count() > 1) {
|
||||
$this->info('Multiple backups are pending..');
|
||||
$this->info('Multiple backups are pending...');
|
||||
} else {
|
||||
foreach ($getPendingBackups as $pendingBackup) {
|
||||
$pendingBackup->startBackup();
|
|
@ -10,14 +10,14 @@ use Illuminate\Console\Command;
|
|||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class RunHostingSubscriptionsBackup extends Command
|
||||
class RunHostingSubscriptionsBackupChecks extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'phyre:run-hosting-subscriptions-backup';
|
||||
protected $signature = 'phyre:run-hosting-subscriptions-backup-checks';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
|
@ -37,26 +37,26 @@ class RunHostingSubscriptionsBackup extends Command
|
|||
$backup->delete();
|
||||
}
|
||||
|
||||
// Find Hosting Subscriptions
|
||||
$findHostingSubscriptions = HostingSubscription::all();
|
||||
if ($findHostingSubscriptions->count() > 0) {
|
||||
foreach ($findHostingSubscriptions as $hostingSubscription) {
|
||||
|
||||
$findBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $hostingSubscription->id)
|
||||
->where('backup_type', 'full')
|
||||
->where('created_at', '>=', Carbon::now()->subHours(24))
|
||||
->first();
|
||||
if (! $findBackup) {
|
||||
$backup = new HostingSubscriptionBackup();
|
||||
$backup->hosting_subscription_id = $hostingSubscription->id;
|
||||
$backup->backup_type = 'full';
|
||||
$backup->save();
|
||||
} else {
|
||||
$this->error('Backup already exists for ' . $hostingSubscription->domain);
|
||||
$this->error('Created before: ' . $findBackup->created_at->diffForHumans());
|
||||
}
|
||||
}
|
||||
}
|
||||
// // Find Hosting Subscriptions
|
||||
// $findHostingSubscriptions = HostingSubscription::all();
|
||||
// if ($findHostingSubscriptions->count() > 0) {
|
||||
// foreach ($findHostingSubscriptions as $hostingSubscription) {
|
||||
//
|
||||
// $findBackup = HostingSubscriptionBackup::where('hosting_subscription_id', $hostingSubscription->id)
|
||||
// ->where('backup_type', 'full')
|
||||
// ->where('created_at', '>=', Carbon::now()->subHours(24))
|
||||
// ->first();
|
||||
// if (! $findBackup) {
|
||||
// $backup = new HostingSubscriptionBackup();
|
||||
// $backup->hosting_subscription_id = $hostingSubscription->id;
|
||||
// $backup->backup_type = 'full';
|
||||
// $backup->save();
|
||||
// } else {
|
||||
// $this->error('Backup already exists for ' . $hostingSubscription->domain);
|
||||
// $this->error('Created before: ' . $findBackup->created_at->diffForHumans());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// Check for pending backups
|
||||
|
@ -64,8 +64,8 @@ class RunHostingSubscriptionsBackup extends Command
|
|||
->get();
|
||||
|
||||
if ($getPendingBackups->count() > 0) {
|
||||
if ($getPendingBackups->count() > 3) {
|
||||
$this->info('There are more than 3 pending backups. Please wait for them to finish.');
|
||||
if ($getPendingBackups->count() > 1) {
|
||||
$this->info('Multiple backups are pending...');
|
||||
} else {
|
||||
foreach ($getPendingBackups as $pendingBackup) {
|
||||
$pendingBackup->startBackup();
|
36
web/app/Console/Commands/RunRepair.php
Normal file
36
web/app/Console/Commands/RunRepair.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
namespace app\Console\Commands;
|
||||
|
||||
use App\Models\Backup;
|
||||
use App\Models\HostingSubscription;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class RunRepair extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'phyre:run-repair';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$checkApacheStatus = shell_exec('service apache2 status');
|
||||
}
|
||||
}
|
|
@ -77,9 +77,17 @@ class BackupResource extends Resource
|
|||
Tables\Columns\BadgeColumn::make('status')
|
||||
->badge(),
|
||||
|
||||
Tables\Columns\TextColumn::make('completed_at')
|
||||
Tables\Columns\TextColumn::make('created_at')
|
||||
->state(function (Backup $backup) {
|
||||
return $backup->completed_at ? $backup->completed_at : 'N/A';
|
||||
return $backup->created_at ? $backup->created_at : 'N/A';
|
||||
}),
|
||||
|
||||
Tables\Columns\TextColumn::make('completed_at')
|
||||
->label('Completed time')
|
||||
->state(function (Backup $backup) {
|
||||
$diff = \Carbon\Carbon::parse($backup->completed_at)
|
||||
->diffForHumans($backup->created_at);
|
||||
return $backup->completed_at ? $diff : 'N/A';
|
||||
}),
|
||||
|
||||
Tables\Columns\TextColumn::make('size')
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Filament\Resources\HostingPlanResource\Pages;
|
|||
use App\Models\HostingPlan;
|
||||
use App\Models\RemoteDatabaseServer;
|
||||
use App\SupportedApplicationTypes;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\CheckboxList;
|
||||
use Filament\Forms\Components\Select;
|
||||
|
@ -250,6 +251,7 @@ class HostingPlanResource extends Resource
|
|||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
Tables\Actions\DeleteAction::make()
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
|
|
|
@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Jackiedo\DotenvEditor\Facades\DotenvEditor;
|
||||
|
||||
class Backup extends Model
|
||||
{
|
||||
|
@ -47,12 +48,14 @@ class Backup extends Model
|
|||
});
|
||||
|
||||
static::deleting(function ($model) {
|
||||
ShellApi::safeDelete($model->path,[
|
||||
Storage::path('backups')
|
||||
]);
|
||||
if (Storage::disk('backups')->exists($model->filepath)) {
|
||||
Storage::disk('backups')->delete($model->filepath);
|
||||
}
|
||||
if (is_file($model->filepath)) {
|
||||
// ShellApi::safeDelete($model->path, [
|
||||
// Storage::path('backups')
|
||||
// ]);
|
||||
if (Storage::disk('backups')->exists($model->filepath)) {
|
||||
Storage::disk('backups')->delete($model->filepath);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -96,7 +99,7 @@ class Backup extends Model
|
|||
shell_exec('cd '.$tempValidatePath.' && unzip -o '.Storage::disk('backups')->path($this->filepath));
|
||||
|
||||
$validateDatabaseFile = $tempValidatePath.'/database.sql';
|
||||
$validateEnvFile = $tempValidatePath.'/env.json';
|
||||
$validateEnvFile = $tempValidatePath.'/.env';
|
||||
|
||||
$errorsBag = [];
|
||||
if (! file_exists($validateDatabaseFile)) {
|
||||
|
@ -105,19 +108,19 @@ class Backup extends Model
|
|||
if (! file_exists($validateEnvFile)) {
|
||||
$errorsBag[] = 'Env file not found';
|
||||
}
|
||||
$getEnv = Dotenv::createArrayBacked(base_path())->load();
|
||||
$getEnvFromBackup = json_decode(file_get_contents($validateEnvFile), true);
|
||||
if (empty($getEnvFromBackup)) {
|
||||
$errorsBag[] = 'Env file is empty';
|
||||
} else {
|
||||
foreach ($getEnv as $key => $value) {
|
||||
if (! isset($getEnvFromBackup[$key])) {
|
||||
$errorsBag[] = 'Env key '.$key.' not found';
|
||||
}
|
||||
if ($getEnvFromBackup[$key] != $value) {
|
||||
$errorsBag[] = 'Env key '.$key.' value mismatch';
|
||||
}
|
||||
}
|
||||
if (count($errorsBag) > 0) {
|
||||
$this->status = 'failed';
|
||||
$this->save();
|
||||
return [
|
||||
'status' => 'failed',
|
||||
'message' => 'Backup failed. Database or env file missing.',
|
||||
'errors' => $errorsBag
|
||||
];
|
||||
}
|
||||
$originalEnvContent = file_get_contents(base_path().'/.env');
|
||||
$backupEnvContent = file_get_contents($validateEnvFile);
|
||||
if ($originalEnvContent != $backupEnvContent) {
|
||||
$errorsBag[] = 'Env file content mismatch';
|
||||
}
|
||||
|
||||
if (count($errorsBag) > 0) {
|
||||
|
@ -192,7 +195,7 @@ class Backup extends Model
|
|||
mkdir($backupTempPath);
|
||||
}
|
||||
|
||||
$backupFilename = 'phyre-panel-'.date('Ymd-His').'.zip';
|
||||
$backupFilename = 'phyre-backup-'.date('Ymd-His').'.zip';
|
||||
$backupFilePath = $storagePath.'/' . $backupFilename;
|
||||
|
||||
if ($this->backup_type == 'full') {
|
||||
|
@ -210,12 +213,48 @@ class Backup extends Model
|
|||
// Export Phyre Panel database
|
||||
$shellFileContent .= 'mysqldump -u "'.env('MYSQl_ROOT_USERNAME').'" -p"'.env('MYSQL_ROOT_PASSWORD').'" "'.env('DB_DATABASE').'" > '.$databaseBackupPath . PHP_EOL;
|
||||
|
||||
|
||||
// Export Phyre Panel ENV
|
||||
$getEnv = Dotenv::createArrayBacked(base_path())->load();
|
||||
file_put_contents($backupTempPath.'/env.json', json_encode($getEnv, JSON_PRETTY_PRINT));
|
||||
$backupStructure = [
|
||||
'env'=>$getEnv,
|
||||
];
|
||||
file_put_contents($backupTempPath.'/backup.json', json_encode($backupStructure, JSON_PRETTY_PRINT));
|
||||
$shellFileContent .= 'echo "Backup Phyre Panel ENV"'. PHP_EOL;
|
||||
$shellFileContent .= 'cp '.base_path().'/.env '.$backupTempPath.'/.env'. PHP_EOL;
|
||||
|
||||
$shellFileContent .= 'cd '.$backupTempPath .' && zip -r '.$backupFilePath.' ./* '. PHP_EOL;
|
||||
// Export Phyre Panel Hosting Subscription
|
||||
$findHostingSubscription = HostingSubscription::all();
|
||||
if ($findHostingSubscription->count() > 0) {
|
||||
foreach ($findHostingSubscription as $hostingSubscription) {
|
||||
$hostingSubscriptionPath = $backupTempPath .'/hosting_subscriptions/'.$hostingSubscription->system_username;
|
||||
$shellFileContent .= PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup up hosting subscription: ' . $hostingSubscription->system_username .'" '. PHP_EOL;
|
||||
$shellFileContent .= 'mkdir -p '.$hostingSubscriptionPath.PHP_EOL;
|
||||
$shellFileContent .= 'cp -r /home/'.$hostingSubscription->system_username.'/* .[^.]* ' . $hostingSubscriptionPath .PHP_EOL;
|
||||
|
||||
$shellFileContent .= 'mkdir -p '.$hostingSubscriptionPath.'/databases'.PHP_EOL;
|
||||
|
||||
$getDatabases = Database::where('hosting_subscription_id', $hostingSubscription->id)
|
||||
->where(function ($query) {
|
||||
$query->where('is_remote_database_server', '0')
|
||||
->orWhereNull('is_remote_database_server');
|
||||
})
|
||||
->get();
|
||||
|
||||
if ($getDatabases->count() > 0) {
|
||||
foreach ($getDatabases as $database) {
|
||||
$databaseName = $database->database_name_prefix . $database->database_name;
|
||||
$shellFileContent .= 'echo "Backup up database: ' . $databaseName . '" ' . PHP_EOL;
|
||||
$databaseBackupPath = $hostingSubscriptionPath . '/databases/' . $databaseName . '.sql';
|
||||
$shellFileContent .= 'mysqldump -u "' . env('MYSQl_ROOT_USERNAME') . '" -p"' . env('MYSQL_ROOT_PASSWORD') . '" "' . $databaseName . '" > ' . $databaseBackupPath . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
$shellFileContent .= PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
$shellFileContent .= 'cd '.$backupTempPath .' && zip -r '.$backupFilePath.' ./* .[^.]* '. PHP_EOL;
|
||||
|
||||
$shellFileContent .= 'rm -rf '.$backupTempPath.PHP_EOL;
|
||||
$shellFileContent .= 'echo "Backup complete"' . PHP_EOL;
|
||||
|
|
|
@ -224,6 +224,20 @@ class Domain extends Model
|
|||
shell_exec('chown -R '.$findHostingSubscription->system_username.':'.$webUserGroup.' '.$this->domain_root.'/logs/apache2');
|
||||
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2');
|
||||
|
||||
if (!is_file($this->domain_root.'/logs/apache2/bytes.log')) {
|
||||
shell_exec('touch '.$this->domain_root.'/logs/apache2/bytes.log');
|
||||
}
|
||||
if (!is_file($this->domain_root.'/logs/apache2/access.log')) {
|
||||
shell_exec('touch '.$this->domain_root.'/logs/apache2/access.log');
|
||||
}
|
||||
if (!is_file($this->domain_root.'/logs/apache2/error.log')) {
|
||||
shell_exec('touch '.$this->domain_root.'/logs/apache2/error.log');
|
||||
}
|
||||
|
||||
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2/bytes.log');
|
||||
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2/access.log');
|
||||
shell_exec('chmod -R 775 '.$this->domain_root.'/logs/apache2/error.log');
|
||||
|
||||
$appType = 'php';
|
||||
$appVersion = '8.3';
|
||||
|
||||
|
@ -404,8 +418,10 @@ class Domain extends Model
|
|||
}
|
||||
|
||||
file_put_contents('/etc/apache2/sites-available/'.$this->domain.'-ssl.conf', $apacheBaseConfigWithSSL);
|
||||
shell_exec('ln -s /etc/apache2/sites-available/'.$this->domain.'-ssl.conf /etc/apache2/sites-enabled/'.$this->domain.'-ssl.conf');
|
||||
|
||||
if (!is_link('/etc/apache2/sites-enabled/' . $this->domain . '-ssl.conf')) {
|
||||
shell_exec('ln -s /etc/apache2/sites-available/' . $this->domain . '-ssl.conf /etc/apache2/sites-enabled/' . $this->domain . '-ssl.conf');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ class HostingSubscriptionBackup extends Model
|
|||
|
||||
public function checkCronJob()
|
||||
{
|
||||
$cronJobCommand = 'phyre-php /usr/local/phyre/web/artisan phyre:run-hosting-subscriptions-backup';
|
||||
$cronJobCommand = 'phyre-php /usr/local/phyre/web/artisan phyre:run-hosting-subscriptions-backup-checks';
|
||||
$findCronJob = CronJob::where('command', $cronJobCommand)->first();
|
||||
if (! $findCronJob) {
|
||||
$cronJob = new CronJob();
|
||||
|
@ -73,8 +73,18 @@ class HostingSubscriptionBackup extends Model
|
|||
$cronJob->command = $cronJobCommand;
|
||||
$cronJob->user = 'root';
|
||||
$cronJob->save();
|
||||
return false;
|
||||
}
|
||||
|
||||
$cronJobCommand = 'phyre-php /usr/local/phyre/web/artisan phyre:create-daily-full-hosting-subscriptions-backup';
|
||||
$findCronJob = CronJob::where('command', $cronJobCommand)->first();
|
||||
if (! $findCronJob) {
|
||||
$cronJob = new CronJob();
|
||||
$cronJob->schedule = '0 0 * * *';
|
||||
$cronJob->command = $cronJobCommand;
|
||||
$cronJob->user = 'root';
|
||||
$cronJob->save();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,7 @@
|
|||
LogFormat "%h %l %u %t \"%r\" %>s %b" common
|
||||
|
||||
CustomLog {{$domainRoot}}/logs/apache2/bytes.log bytes
|
||||
CustomLog {{$domainRoot}}/logs/apache2/combined.log combined
|
||||
CustomLog {{$domainRoot}}/logs/apache2/access.log common
|
||||
CustomLog {{$domainRoot}}/logs/apache2/referer.log "%{Referer}i -> %U"
|
||||
CustomLog {{$domainRoot}}/logs/apache2/agent.log "%{User-agent}i"
|
||||
ErrorLog {{$domainRoot}}/logs/apache2/error.log
|
||||
|
||||
@if($appType == 'php')
|
||||
|
|
Loading…
Reference in a new issue