auto updates
This commit is contained in:
		@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
namespace App\Console;
 | 
			
		||||
 | 
			
		||||
use App\Jobs\AutoUpdateJob;
 | 
			
		||||
use App\Jobs\ContainerStatusJob;
 | 
			
		||||
use App\Jobs\DockerCleanupDanglingImagesJob;
 | 
			
		||||
use App\Jobs\ProxyCheckJob;
 | 
			
		||||
@@ -15,9 +16,9 @@ class Kernel extends ConsoleKernel
 | 
			
		||||
     */
 | 
			
		||||
    protected function schedule(Schedule $schedule): void
 | 
			
		||||
    {
 | 
			
		||||
        $schedule->job(new ContainerStatusJob)->everyMinute();
 | 
			
		||||
        $schedule->job(new DockerCleanupDanglingImagesJob)->everyMinute();
 | 
			
		||||
        // $schedule->job(new ProxyCheckJob)->everyMinute();
 | 
			
		||||
        $schedule->job(new DockerCleanupDanglingImagesJob)->everyFiveMinutes();
 | 
			
		||||
        $schedule->job(new AutoUpdateJob)->everyFifteenMinutes();
 | 
			
		||||
        $schedule->job(new ProxyCheckJob)->everyMinute();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
 | 
			
		||||
namespace App\Http\Livewire\Project\Application;
 | 
			
		||||
 | 
			
		||||
use App\Jobs\ContainerStatusJob;
 | 
			
		||||
use App\Jobs\DeployApplicationJob;
 | 
			
		||||
use App\Models\Application;
 | 
			
		||||
use Illuminate\Support\Facades\Route;
 | 
			
		||||
@@ -26,6 +27,7 @@ class Deploy extends Component
 | 
			
		||||
        $this->parameters = getParameters();
 | 
			
		||||
        $this->application = Application::where('id', $this->applicationId)->first();
 | 
			
		||||
        $this->destination = $this->application->destination->getMorphClass()::where('id', $this->application->destination->id)->first();
 | 
			
		||||
        dispatch(new ContainerStatusJob($this->application->uuid));
 | 
			
		||||
    }
 | 
			
		||||
    protected function setDeploymentUuid()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										93
									
								
								app/Jobs/AutoUpdateJob.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								app/Jobs/AutoUpdateJob.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Jobs;
 | 
			
		||||
 | 
			
		||||
use App\Enums\ActivityTypes;
 | 
			
		||||
use App\Models\InstanceSettings;
 | 
			
		||||
use App\Models\Server;
 | 
			
		||||
use Illuminate\Bus\Queueable;
 | 
			
		||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
 | 
			
		||||
use Illuminate\Contracts\Queue\ShouldQueue;
 | 
			
		||||
use Illuminate\Foundation\Bus\Dispatchable;
 | 
			
		||||
use Illuminate\Queue\InteractsWithQueue;
 | 
			
		||||
use Illuminate\Queue\SerializesModels;
 | 
			
		||||
use Illuminate\Support\Facades\Log;
 | 
			
		||||
 | 
			
		||||
class AutoUpdateJob implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, ShouldBeUnique;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        $instance_settings = InstanceSettings::get();
 | 
			
		||||
        if (!$instance_settings->is_auto_update_enabled) {
 | 
			
		||||
            Log::info('Auto update is disabled');
 | 
			
		||||
            dd('Auto update is disabled');
 | 
			
		||||
            $this->delete();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the job.
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(): void
 | 
			
		||||
    {
 | 
			
		||||
        if (config('app.env') === 'local') {
 | 
			
		||||
            $latest_version = getLatestVersionOfCoolify();
 | 
			
		||||
            $current_version = config('version');
 | 
			
		||||
            if ($latest_version === $current_version) {
 | 
			
		||||
                dd('no update, versions match', $latest_version, $current_version);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (version_compare($latest_version, $current_version, '<')) {
 | 
			
		||||
                dd('no update, latest version is lower than current version');
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $server = Server::where('ip', 'coolify-testing-host')->first();
 | 
			
		||||
            if (!$server) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            instantRemoteProcess([
 | 
			
		||||
                "sleep 2"
 | 
			
		||||
            ], $server);
 | 
			
		||||
            remoteProcess([
 | 
			
		||||
                "sleep 10"
 | 
			
		||||
            ], $server, ActivityTypes::INLINE->value);
 | 
			
		||||
            dd('update done');
 | 
			
		||||
        } else {
 | 
			
		||||
            $latest_version = getLatestVersionOfCoolify();
 | 
			
		||||
            $current_version = config('version');
 | 
			
		||||
            if ($latest_version === $current_version) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (version_compare($latest_version, $current_version, '<')) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $cdn = "https://coolify-cdn.b-cdn.net/files";
 | 
			
		||||
            $server = Server::where('ip', 'host.docker.internal')->first();
 | 
			
		||||
            if (!$server) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            instantRemoteProcess([
 | 
			
		||||
                "curl -fsSL $cdn/docker-compose.yml -o /data/coolify/source/docker-compose.yml",
 | 
			
		||||
                "curl -fsSL $cdn/docker-compose.prod.yml -o /data/coolify/source/docker-compose.prod.yml",
 | 
			
		||||
                "curl -fsSL $cdn/.env.production -o /data/coolify/source/.env.production",
 | 
			
		||||
                "curl -fsSL $cdn/upgrade.sh -o /data/coolify/source/upgrade.sh",
 | 
			
		||||
            ], $server);
 | 
			
		||||
 | 
			
		||||
            instantRemoteProcess([
 | 
			
		||||
                "docker compose -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml pull",
 | 
			
		||||
            ], $server);
 | 
			
		||||
 | 
			
		||||
            remoteProcess([
 | 
			
		||||
                "bash /data/coolify/source/upgrade.sh $latest_version"
 | 
			
		||||
            ], $server, ActivityTypes::INLINE->value);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -52,9 +52,15 @@ class User extends Authenticatable
 | 
			
		||||
            $model->uuid = (string) new Cuid2(7);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    public function isRoot()
 | 
			
		||||
    public function isPartOfRootTeam()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->id == 0;
 | 
			
		||||
        $found_root_team = auth()->user()->teams->filter(function ($team) {
 | 
			
		||||
            if ($team->id == 0) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
        });
 | 
			
		||||
        return $found_root_team->count() > 0;
 | 
			
		||||
    }
 | 
			
		||||
    public function teams()
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,2 @@
 | 
			
		||||
#!/command/execlineb -P
 | 
			
		||||
su - webuser -c "php /var/www/html/artisan queue:listen --timeout=600 --rest=1 --memory=512"
 | 
			
		||||
su - webuser -c "php /var/www/html/artisan queue:listen --timeout=600"
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
                    <button>{{ __('auth.register') }}</button>
 | 
			
		||||
                </a>
 | 
			
		||||
            @else
 | 
			
		||||
                <div>{{ __('auth.registration_disabled') }}</div>
 | 
			
		||||
                <div class="text-sm text-center">{{ __('auth.registration_disabled') }}</div>
 | 
			
		||||
            @endif
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -14,19 +14,18 @@
 | 
			
		||||
                            Dashboard
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </li>
 | 
			
		||||
 | 
			
		||||
                    @if (auth()->user()->isRoot())
 | 
			
		||||
                    @if (auth()->user()->isPartOfRootTeam())
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <a href="/settings">
 | 
			
		||||
                                Settings
 | 
			
		||||
                            </a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                    @endif
 | 
			
		||||
                    <li>
 | 
			
		||||
                    {{-- <li>
 | 
			
		||||
                        <a href="/profile">
 | 
			
		||||
                            Profile
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    </li> --}}
 | 
			
		||||
                    <li>
 | 
			
		||||
                        <a href="/profile/team">
 | 
			
		||||
                            Team
 | 
			
		||||
@@ -37,7 +36,7 @@
 | 
			
		||||
                            Command Center
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    @if (auth()->user()->isRoot())
 | 
			
		||||
                    @if (auth()->user()->isPartOfRootTeam())
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <livewire:force-upgrade />
 | 
			
		||||
                        </li>
 | 
			
		||||
@@ -62,18 +61,18 @@
 | 
			
		||||
                        Dashboard
 | 
			
		||||
                    </a>
 | 
			
		||||
                </li>
 | 
			
		||||
                @if (auth()->user()->isRoot())
 | 
			
		||||
                @if (auth()->user()->isPartOfRootTeam())
 | 
			
		||||
                    <li>
 | 
			
		||||
                        <a href="/settings">
 | 
			
		||||
                            Settings
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                @endif
 | 
			
		||||
                <li>
 | 
			
		||||
                {{-- <li>
 | 
			
		||||
                    <a href="/profile">
 | 
			
		||||
                        Profile
 | 
			
		||||
                    </a>
 | 
			
		||||
                </li>
 | 
			
		||||
                </li> --}}
 | 
			
		||||
                <li>
 | 
			
		||||
                    <a href="/profile/team">
 | 
			
		||||
                        Team
 | 
			
		||||
@@ -84,7 +83,7 @@
 | 
			
		||||
                        Command Center
 | 
			
		||||
                    </a>
 | 
			
		||||
                </li>
 | 
			
		||||
                @if (auth()->user()->isRoot())
 | 
			
		||||
                @if (auth()->user()->isPartOfRootTeam())
 | 
			
		||||
                    <li>
 | 
			
		||||
                        <livewire:force-upgrade />
 | 
			
		||||
                    </li>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
<x-layout>
 | 
			
		||||
    @if ($servers->count() === 0)
 | 
			
		||||
        <div class="flex flex-col items-center justify-center h-full pt-32">
 | 
			
		||||
            <div class="">Without a server, you won't be able to do much</div>
 | 
			
		||||
            <div class="text-2xl">Let's create <a class="underline" href="{{ route('server.new') }}">your
 | 
			
		||||
            <div class="">Without a server, you won't be able to do much...</div>
 | 
			
		||||
            <div>Let's create <a class="underline text-warning" href="{{ route('server.new') }}">your
 | 
			
		||||
                    first</a> one!</div>
 | 
			
		||||
        </div>
 | 
			
		||||
    @else
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,8 @@
 | 
			
		||||
    <form class="flex flex-col gap-2 " wire:submit.prevent='createPrivateKey'>
 | 
			
		||||
        <x-inputs.input id="name" label="Name" required />
 | 
			
		||||
        <x-inputs.input id="description" label="Description" />
 | 
			
		||||
        <x-inputs.input type="textarea" id="value" label="Private Key" required />
 | 
			
		||||
        <x-inputs.textarea id="value" rows="10" placeholder="-----BEGIN OPENSSH PRIVATE KEY-----"
 | 
			
		||||
            label="Private Key" required />
 | 
			
		||||
        <x-inputs.button type="submit" wire.click.prevent>
 | 
			
		||||
            Save
 | 
			
		||||
        </x-inputs.button>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,28 @@
 | 
			
		||||
<div>
 | 
			
		||||
    <form wire:submit.prevent='submit' class="flex flex-col">
 | 
			
		||||
        <div class="flex flex-col gap-2 xl:flex-row">
 | 
			
		||||
            <div class="flex flex-col w-96">
 | 
			
		||||
        <div class="flex items-center gap-2">
 | 
			
		||||
            <h1>Settings</h1>
 | 
			
		||||
            <x-inputs.button type="submit">
 | 
			
		||||
                Save
 | 
			
		||||
            </x-inputs.button>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="flex flex-col gap-2">
 | 
			
		||||
            <div class="flex flex-col gap-2 xl:flex-row">
 | 
			
		||||
                <x-inputs.input id="settings.fqdn" label="Coolify's Domain" />
 | 
			
		||||
                <x-inputs.input id="settings.wildcard_domain" label="Wildcard Domain"
 | 
			
		||||
                    helper="Wildcard domain for your applications. If you set this, you will get a random generated domain for your new applications.<br><br><span class='inline-block font-bold text-warning'>Example</span>https://example.com<br>Your applications will get https://randomthing.example.com" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex flex-col w-96">
 | 
			
		||||
            <div class="flex flex-col gap-2 xl:flex-row">
 | 
			
		||||
                <x-inputs.input type="number" id="settings.public_port_min" label="Public Port Min" />
 | 
			
		||||
                <x-inputs.input type="number" id="settings.public_port_max" label="Public Port Max" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <x-inputs.button class="w-16 mt-4" type="submit">
 | 
			
		||||
            Submit
 | 
			
		||||
        </x-inputs.button>
 | 
			
		||||
    </form>
 | 
			
		||||
 | 
			
		||||
    <h3>Advanced</h3>
 | 
			
		||||
    <div class="flex flex-col pt-4 text-right w-52">
 | 
			
		||||
        <x-inputs.checkbox instantSave id="is_auto_update_enabled" label="Auto Update Coolify" />
 | 
			
		||||
        <x-inputs.checkbox instantSave id="is_registration_enabled" label="Registration Enabled?" />
 | 
			
		||||
        <x-inputs.checkbox instantSave id="is_registration_enabled" label="Registration Allowed" />
 | 
			
		||||
        {{-- <x-inputs.checkbox instantSave id="is_https_forced" label="Force https?" /> --}}
 | 
			
		||||
        <x-inputs.checkbox instantSave id="do_not_track" label="Do Not Track" />
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
<div class="pt-4">
 | 
			
		||||
    <h3>Other Teams</h3>
 | 
			
		||||
    <div class="flex flex-col gap-2">
 | 
			
		||||
        @foreach (auth()->user()->otherTeams() as $team)
 | 
			
		||||
            <x-inputs.button wire:key="{{ $team->id }}" wire:click="switch_to('{{ $team->id }}')">Switch
 | 
			
		||||
                to:
 | 
			
		||||
                {{ $team->name }}</x-inputs.button>
 | 
			
		||||
        @endforeach
 | 
			
		||||
    </div>
 | 
			
		||||
    @if (auth()->user()->otherTeams()->count() > 0)
 | 
			
		||||
        <p>Switch to:</p>
 | 
			
		||||
        <div class="flex gap-2">
 | 
			
		||||
            @foreach (auth()->user()->otherTeams() as $team)
 | 
			
		||||
                <x-inputs.button isHighlighted wire:key="{{ $team->id }}"
 | 
			
		||||
                    wire:click="switch_to('{{ $team->id }}')">
 | 
			
		||||
                    {{ $team->name }}</x-inputs.button>
 | 
			
		||||
            @endforeach
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<x-layout>
 | 
			
		||||
    @if ($private_keys->count() === 0)
 | 
			
		||||
        <h2>Create private key</h2>
 | 
			
		||||
        <h2>Create Private Key</h2>
 | 
			
		||||
        <div>You need to create a private key before you can create a server.</div>
 | 
			
		||||
        <livewire:private-key.create from="server" />
 | 
			
		||||
    @else
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
<x-layout>
 | 
			
		||||
    <h1>Settings</h1>
 | 
			
		||||
    <livewire:settings.form :settings="$settings" />
 | 
			
		||||
</x-layout>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<x-layout>
 | 
			
		||||
    <div>
 | 
			
		||||
        <h3>Current Team</h3>
 | 
			
		||||
        <p>Name: {{ session('currentTeam')->name }}</p>
 | 
			
		||||
        <p>{{ session('currentTeam')->name }}</p>
 | 
			
		||||
        <livewire:switch-team>
 | 
			
		||||
    </div>
 | 
			
		||||
</x-layout>
 | 
			
		||||
 
 | 
			
		||||
@@ -133,7 +133,7 @@ Route::middleware(['auth'])->group(function () {
 | 
			
		||||
    })->name('team');
 | 
			
		||||
 | 
			
		||||
    Route::get('/settings', function () {
 | 
			
		||||
        $isRoot = auth()->user()->isRoot();
 | 
			
		||||
        $isRoot = auth()->user()->isPartOfRootTeam();
 | 
			
		||||
        if ($isRoot) {
 | 
			
		||||
            $settings = InstanceSettings::get();
 | 
			
		||||
            return view('settings', [
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user