Merge pull request #1066 from coollabsio/patricio-proxy-config-screen
Proxy config screen
This commit is contained in:
commit
c47b0ddcc1
@ -7,6 +7,7 @@ USERID=
|
|||||||
GROUPID=
|
GROUPID=
|
||||||
PROJECT_PATH_ON_HOST=/Users/your-username-here/code/coollabsio/coolify
|
PROJECT_PATH_ON_HOST=/Users/your-username-here/code/coollabsio/coolify
|
||||||
SERVEO_URL=<for receiving webhooks locally https://serveo.net/>
|
SERVEO_URL=<for receiving webhooks locally https://serveo.net/>
|
||||||
|
MUX_ENABLED=false
|
||||||
############################################################################################################
|
############################################################################################################
|
||||||
|
|
||||||
APP_NAME=Coolify
|
APP_NAME=Coolify
|
||||||
|
33
app/Actions/Proxy/CheckProxySettingsInSync.php
Normal file
33
app/Actions/Proxy/CheckProxySettingsInSync.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Proxy;
|
||||||
|
|
||||||
|
use App\Enums\ProxyTypes;
|
||||||
|
use App\Models\Server;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
|
class CheckProxySettingsInSync
|
||||||
|
{
|
||||||
|
public function __invoke(Server $server)
|
||||||
|
{
|
||||||
|
$proxy_path = config('coolify.proxy_config_path');
|
||||||
|
$output = instantRemoteProcess([
|
||||||
|
"cat $proxy_path/docker-compose.yml",
|
||||||
|
], $server, false);
|
||||||
|
if (is_null($output)) {
|
||||||
|
$final_output = Str::of(getProxyConfiguration($server))->trim();
|
||||||
|
} else {
|
||||||
|
$final_output = Str::of($output)->trim();
|
||||||
|
}
|
||||||
|
$docker_compose_yml_base64 = base64_encode($final_output);
|
||||||
|
$server->extra_attributes->last_saved_proxy_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value;
|
||||||
|
$server->save();
|
||||||
|
if (is_null($output)) {
|
||||||
|
instantRemoteProcess([
|
||||||
|
"mkdir -p $proxy_path",
|
||||||
|
"echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml",
|
||||||
|
], $server);
|
||||||
|
}
|
||||||
|
return $final_output;
|
||||||
|
}
|
||||||
|
}
|
@ -3,100 +3,65 @@
|
|||||||
namespace App\Actions\Proxy;
|
namespace App\Actions\Proxy;
|
||||||
|
|
||||||
use App\Enums\ActivityTypes;
|
use App\Enums\ActivityTypes;
|
||||||
|
use App\Enums\ProxyTypes;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Symfony\Component\Yaml\Yaml;
|
use Illuminate\Support\Collection;
|
||||||
|
use Spatie\Activitylog\Models\Activity;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class InstallProxy
|
class InstallProxy
|
||||||
{
|
{
|
||||||
public function __invoke(Server $server)
|
public Collection $networks;
|
||||||
|
|
||||||
|
public function __invoke(Server $server): Activity
|
||||||
{
|
{
|
||||||
$docker_compose_yml_base64 = base64_encode(
|
$proxy_path = config('coolify.proxy_config_path');
|
||||||
$this->getDockerComposeContents()
|
|
||||||
);
|
$networks = collect($server->standaloneDockers)->map(function ($docker) {
|
||||||
|
return $docker['network'];
|
||||||
|
})->unique();
|
||||||
|
if ($networks->count() === 0) {
|
||||||
|
$this->networks = collect(['coolify']);
|
||||||
|
}
|
||||||
|
$create_networks_command = $this->networks->map(function ($network) {
|
||||||
|
return "docker network ls --format '{{.Name}}' | grep '^$network$' >/dev/null 2>&1 || docker network create --attachable $network > /dev/null 2>&1";
|
||||||
|
});
|
||||||
|
|
||||||
|
$configuration = instantRemoteProcess([
|
||||||
|
"cat $proxy_path/docker-compose.yml",
|
||||||
|
], $server, false);
|
||||||
|
if (is_null($configuration)) {
|
||||||
|
$configuration = Str::of(getProxyConfiguration($server))->trim();
|
||||||
|
} else {
|
||||||
|
$configuration = Str::of($configuration)->trim();
|
||||||
|
}
|
||||||
|
$docker_compose_yml_base64 = base64_encode($configuration);
|
||||||
|
$server->extra_attributes->last_applied_proxy_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value;
|
||||||
|
$server->save();
|
||||||
|
|
||||||
$env_file_base64 = base64_encode(
|
$env_file_base64 = base64_encode(
|
||||||
$this->getEnvContents()
|
$this->getEnvContents()
|
||||||
);
|
);
|
||||||
|
|
||||||
$activity = remoteProcess([
|
$activity = remoteProcess([
|
||||||
'mkdir -p projects',
|
...$create_networks_command,
|
||||||
'mkdir -p projects/proxy',
|
"echo 'Docker networks created...'",
|
||||||
'mkdir -p projects/proxy/letsencrypt',
|
"mkdir -p $proxy_path",
|
||||||
'cd projects/proxy',
|
"cd $proxy_path",
|
||||||
"echo '$docker_compose_yml_base64' | base64 -d > docker-compose.yml",
|
"echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml",
|
||||||
"echo '$env_file_base64' | base64 -d > .env",
|
"echo '$env_file_base64' | base64 -d > $proxy_path/.env",
|
||||||
|
"echo 'Docker compose file created...'",
|
||||||
|
"echo 'Pulling docker image...'",
|
||||||
|
'docker compose pull -q',
|
||||||
|
"echo 'Stopping proxy...'",
|
||||||
|
'docker compose down -v --remove-orphans',
|
||||||
|
"echo 'Starting proxy...'",
|
||||||
'docker compose up -d --remove-orphans',
|
'docker compose up -d --remove-orphans',
|
||||||
'docker ps',
|
"echo 'Proxy installed successfully...'"
|
||||||
], $server, ActivityTypes::INLINE->value);
|
], $server, ActivityTypes::INLINE->value);
|
||||||
|
|
||||||
return $activity;
|
return $activity;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDockerComposeContents()
|
|
||||||
{
|
|
||||||
return Yaml::dump($this->getComposeData());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getComposeData(): array
|
|
||||||
{
|
|
||||||
$cwd = config('app.env') === 'local'
|
|
||||||
? config('proxy.project_path_on_host') . '/_testing_hosts/host_2_proxy'
|
|
||||||
: '.';
|
|
||||||
|
|
||||||
ray($cwd);
|
|
||||||
|
|
||||||
return [
|
|
||||||
"version" => "3.7",
|
|
||||||
"networks" => [
|
|
||||||
"coolify" => [
|
|
||||||
"external" => true,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
"services" => [
|
|
||||||
"traefik" => [
|
|
||||||
"container_name" => "coolify-proxy",
|
|
||||||
"image" => "traefik:v2.10",
|
|
||||||
"restart" => "always",
|
|
||||||
"extra_hosts" => [
|
|
||||||
"host.docker.internal:host-gateway",
|
|
||||||
],
|
|
||||||
"networks" => [
|
|
||||||
"coolify",
|
|
||||||
],
|
|
||||||
"ports" => [
|
|
||||||
"80:80",
|
|
||||||
"443:443",
|
|
||||||
"8080:8080",
|
|
||||||
],
|
|
||||||
"volumes" => [
|
|
||||||
"/var/run/docker.sock:/var/run/docker.sock:ro",
|
|
||||||
"{$cwd}/letsencrypt:/letsencrypt",
|
|
||||||
"{$cwd}/traefik.auth:/auth/traefik.auth",
|
|
||||||
],
|
|
||||||
"command" => [
|
|
||||||
"--api.dashboard=true",
|
|
||||||
"--api.insecure=true",
|
|
||||||
"--entrypoints.http.address=:80",
|
|
||||||
"--entrypoints.https.address=:443",
|
|
||||||
"--providers.docker=true",
|
|
||||||
"--providers.docker.exposedbydefault=false",
|
|
||||||
],
|
|
||||||
"labels" => [
|
|
||||||
"traefik.enable=true",
|
|
||||||
"traefik.http.routers.traefik.entrypoints=http",
|
|
||||||
'traefik.http.routers.traefik.rule=Host(`${TRAEFIK_DASHBOARD_HOST}`)',
|
|
||||||
"traefik.http.routers.traefik.service=api@internal",
|
|
||||||
"traefik.http.services.traefik.loadbalancer.server.port=8080",
|
|
||||||
"traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https",
|
|
||||||
],
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getEnvContents()
|
protected function getEnvContents()
|
||||||
{
|
{
|
||||||
$data = [
|
$data = [
|
||||||
|
@ -4,6 +4,7 @@ namespace App\Console;
|
|||||||
|
|
||||||
use App\Jobs\ContainerStatusJob;
|
use App\Jobs\ContainerStatusJob;
|
||||||
use App\Jobs\DockerCleanupDanglingImagesJob;
|
use App\Jobs\DockerCleanupDanglingImagesJob;
|
||||||
|
use App\Jobs\ProxyCheckJob;
|
||||||
use Illuminate\Console\Scheduling\Schedule;
|
use Illuminate\Console\Scheduling\Schedule;
|
||||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||||
|
|
||||||
@ -16,6 +17,7 @@ class Kernel extends ConsoleKernel
|
|||||||
{
|
{
|
||||||
$schedule->job(new ContainerStatusJob)->everyMinute();
|
$schedule->job(new ContainerStatusJob)->everyMinute();
|
||||||
$schedule->job(new DockerCleanupDanglingImagesJob)->everyMinute();
|
$schedule->job(new DockerCleanupDanglingImagesJob)->everyMinute();
|
||||||
|
// $schedule->job(new ProxyCheckJob)->everyMinute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +32,7 @@ class Form extends Component
|
|||||||
|
|
||||||
$this->emit('newMonitorActivity', $activity->id);
|
$this->emit('newMonitorActivity', $activity->id);
|
||||||
}
|
}
|
||||||
public function checkServer()
|
public function validateServer()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->uptime = instantRemoteProcess(['uptime'], $this->server, false);
|
$this->uptime = instantRemoteProcess(['uptime'], $this->server, false);
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
namespace App\Http\Livewire\Server;
|
namespace App\Http\Livewire\Server;
|
||||||
|
|
||||||
|
use App\Actions\Proxy\CheckProxySettingsInSync;
|
||||||
use App\Actions\Proxy\InstallProxy;
|
use App\Actions\Proxy\InstallProxy;
|
||||||
use App\Enums\ActivityTypes;
|
use App\Enums\ProxyTypes;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
@ -11,22 +13,56 @@ class Proxy extends Component
|
|||||||
{
|
{
|
||||||
public Server $server;
|
public Server $server;
|
||||||
|
|
||||||
protected string $selectedProxy = '';
|
public ProxyTypes $selectedProxy = ProxyTypes::TRAEFIK_V2;
|
||||||
|
public $proxy_settings = null;
|
||||||
|
|
||||||
public function mount(Server $server)
|
public function installProxy()
|
||||||
{
|
|
||||||
$this->server = $server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function runInstallProxy()
|
|
||||||
{
|
{
|
||||||
|
$this->saveConfiguration($this->server);
|
||||||
$activity = resolve(InstallProxy::class)($this->server);
|
$activity = resolve(InstallProxy::class)($this->server);
|
||||||
|
|
||||||
$this->emit('newMonitorActivity', $activity->id);
|
$this->emit('newMonitorActivity', $activity->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function render()
|
public function proxyStatus()
|
||||||
{
|
{
|
||||||
return view('livewire.server.proxy');
|
$this->server->extra_attributes->proxy_status = checkContainerStatus(server: $this->server, container_id: 'coolify-proxy');
|
||||||
|
$this->server->save();
|
||||||
|
}
|
||||||
|
public function setProxy()
|
||||||
|
{
|
||||||
|
$this->server->extra_attributes->proxy_type = $this->selectedProxy->value;
|
||||||
|
$this->server->extra_attributes->proxy_status = 'exited';
|
||||||
|
$this->server->save();
|
||||||
|
}
|
||||||
|
public function stopProxy()
|
||||||
|
{
|
||||||
|
instantRemoteProcess([
|
||||||
|
"docker rm -f coolify-proxy",
|
||||||
|
], $this->server);
|
||||||
|
$this->server->extra_attributes->proxy_status = 'exited';
|
||||||
|
$this->server->save();
|
||||||
|
}
|
||||||
|
public function saveConfiguration()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$proxy_path = config('coolify.proxy_config_path');
|
||||||
|
$this->proxy_settings = Str::of($this->proxy_settings)->trim();
|
||||||
|
$docker_compose_yml_base64 = base64_encode($this->proxy_settings);
|
||||||
|
$this->server->extra_attributes->last_saved_proxy_settings = Str::of($docker_compose_yml_base64)->pipe('md5')->value;
|
||||||
|
$this->server->save();
|
||||||
|
instantRemoteProcess([
|
||||||
|
"echo '$docker_compose_yml_base64' | base64 -d > $proxy_path/docker-compose.yml",
|
||||||
|
], $this->server);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return generalErrorHandler($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function checkProxySettingsInSync()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->proxy_settings = resolve(CheckProxySettingsInSync::class)($this->server);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return generalErrorHandler($e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,7 @@ class ContainerStatusJob implements ShouldQueue
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($application->destination->server) {
|
if ($application->destination->server) {
|
||||||
$container = instantRemoteProcess(["docker inspect --format '{{json .State}}' {$this->container_id}"], $application->destination->server);
|
$application->status = checkContainerStatus(server: $application->destination->server, container_id: $this->container_id);
|
||||||
$container = formatDockerCmdOutputToJson($container);
|
|
||||||
$application->status = $container[0]['Status'];
|
|
||||||
$application->save();
|
$application->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,6 @@ class DeployApplicationJob implements ShouldQueue
|
|||||||
protected function stopRunningContainer()
|
protected function stopRunningContainer()
|
||||||
{
|
{
|
||||||
$this->executeNow([
|
$this->executeNow([
|
||||||
|
|
||||||
"echo -n 'Removing old instance... '",
|
"echo -n 'Removing old instance... '",
|
||||||
$this->execute_in_builder("docker rm -f {$this->application->uuid} >/dev/null 2>&1"),
|
$this->execute_in_builder("docker rm -f {$this->application->uuid} >/dev/null 2>&1"),
|
||||||
"echo 'Done.'",
|
"echo 'Done.'",
|
||||||
|
45
app/Jobs/ProxyCheckJob.php
Executable file
45
app/Jobs/ProxyCheckJob.php
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Jobs;
|
||||||
|
|
||||||
|
use App\Actions\Proxy\InstallProxy;
|
||||||
|
use App\Models\Server;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class ProxyCheckJob implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$container_name = 'coolify-proxy';
|
||||||
|
$configuration_path = config('coolify.proxy_config_path');
|
||||||
|
$servers = Server::whereRelation('settings', 'is_validated', true)->get();
|
||||||
|
|
||||||
|
foreach ($servers as $server) {
|
||||||
|
$status = checkContainerStatus(server: $server, container_id: $container_name);
|
||||||
|
if ($status === 'running') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
resolve(InstallProxy::class)($server);
|
||||||
|
}
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
//throw $th;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -40,7 +40,7 @@ if (!function_exists('generalErrorHandler')) {
|
|||||||
'error' => $error->getMessage(),
|
'error' => $error->getMessage(),
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
dump($error);
|
// dump($error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ if (!function_exists('generateSshCommand')) {
|
|||||||
$delimiter = 'EOF-COOLIFY-SSH';
|
$delimiter = 'EOF-COOLIFY-SSH';
|
||||||
Storage::disk('local')->makeDirectory('.ssh');
|
Storage::disk('local')->makeDirectory('.ssh');
|
||||||
$ssh_command = "ssh ";
|
$ssh_command = "ssh ";
|
||||||
if ($isMux) {
|
if ($isMux && config('coolify.mux_enabled')) {
|
||||||
$ssh_command .= '-o ControlMaster=auto -o ControlPersist=1m -o ControlPath=/var/www/html/storage/app/.ssh/ssh_mux_%h_%p_%r ';
|
$ssh_command .= '-o ControlMaster=auto -o ControlPersist=1m -o ControlPath=/var/www/html/storage/app/.ssh/ssh_mux_%h_%p_%r ';
|
||||||
}
|
}
|
||||||
$ssh_command .= "-i {$private_key_location} "
|
$ssh_command .= "-i {$private_key_location} "
|
||||||
@ -165,10 +165,9 @@ if (!function_exists('instantRemoteProcess')) {
|
|||||||
$exitCode = $process->exitCode();
|
$exitCode = $process->exitCode();
|
||||||
if ($exitCode !== 0) {
|
if ($exitCode !== 0) {
|
||||||
if (!$throwError) {
|
if (!$throwError) {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
Log::error($process->errorOutput());
|
throw new \RuntimeException($process->errorOutput());
|
||||||
throw new \RuntimeException('There was an error running the command.');
|
|
||||||
}
|
}
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
@ -196,6 +195,7 @@ use Lcobucci\JWT\Encoding\JoseEncoder;
|
|||||||
use Lcobucci\JWT\Signer\Key\InMemory;
|
use Lcobucci\JWT\Signer\Key\InMemory;
|
||||||
use Lcobucci\JWT\Signer\Rsa\Sha256;
|
use Lcobucci\JWT\Signer\Rsa\Sha256;
|
||||||
use Lcobucci\JWT\Token\Builder;
|
use Lcobucci\JWT\Token\Builder;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
if (!function_exists('generate_github_installation_token')) {
|
if (!function_exists('generate_github_installation_token')) {
|
||||||
function generate_github_installation_token(GithubApp $source)
|
function generate_github_installation_token(GithubApp $source)
|
||||||
@ -244,3 +244,73 @@ if (!function_exists('getParameters')) {
|
|||||||
return Route::current()->parameters();
|
return Route::current()->parameters();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!function_exists('checkContainerStatus')) {
|
||||||
|
function checkContainerStatus(Server $server, string $container_id, bool $throwError = false)
|
||||||
|
{
|
||||||
|
$container = instantRemoteProcess(["docker inspect --format '{{json .State}}' {$container_id}"], $server, $throwError);
|
||||||
|
if (!$container) {
|
||||||
|
return 'exited';
|
||||||
|
}
|
||||||
|
$container = formatDockerCmdOutputToJson($container);
|
||||||
|
return $container[0]['Status'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!function_exists('getProxyConfiguration')) {
|
||||||
|
function getProxyConfiguration(Server $server)
|
||||||
|
{
|
||||||
|
$proxy_config_path = config('coolify.proxy_config_path');
|
||||||
|
$networks = collect($server->standaloneDockers)->map(function ($docker) {
|
||||||
|
return $docker['network'];
|
||||||
|
})->unique();
|
||||||
|
if ($networks->count() === 0) {
|
||||||
|
$networks = collect(['coolify']);
|
||||||
|
}
|
||||||
|
$array_of_networks = collect([]);
|
||||||
|
$networks->map(function ($network) use ($array_of_networks) {
|
||||||
|
$array_of_networks[$network] = [
|
||||||
|
"external" => true,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
return Yaml::dump([
|
||||||
|
"version" => "3.8",
|
||||||
|
"networks" => $array_of_networks->toArray(),
|
||||||
|
"services" => [
|
||||||
|
"traefik" => [
|
||||||
|
"container_name" => "coolify-proxy", # Do not modify this! You will break everything!
|
||||||
|
"image" => "traefik:v2.10",
|
||||||
|
"restart" => "always",
|
||||||
|
"extra_hosts" => [
|
||||||
|
"host.docker.internal:host-gateway",
|
||||||
|
],
|
||||||
|
"networks" => $networks->toArray(), # Do not modify this! You will break everything!
|
||||||
|
"ports" => [
|
||||||
|
"80:80",
|
||||||
|
"443:443",
|
||||||
|
"8080:8080",
|
||||||
|
],
|
||||||
|
"volumes" => [
|
||||||
|
"/var/run/docker.sock:/var/run/docker.sock:ro",
|
||||||
|
"{$proxy_config_path}/letsencrypt:/letsencrypt", # Do not modify this! You will break everything!
|
||||||
|
"{$proxy_config_path}/traefik.auth:/auth/traefik.auth", # Do not modify this! You will break everything!
|
||||||
|
],
|
||||||
|
"command" => [
|
||||||
|
"--api.dashboard=true",
|
||||||
|
"--api.insecure=true",
|
||||||
|
"--entrypoints.http.address=:80",
|
||||||
|
"--entrypoints.https.address=:443",
|
||||||
|
"--providers.docker=true",
|
||||||
|
"--providers.docker.exposedbydefault=false",
|
||||||
|
],
|
||||||
|
"labels" => [
|
||||||
|
"traefik.enable=true", # Do not modify this! You will break everything!
|
||||||
|
"traefik.http.routers.traefik.entrypoints=http",
|
||||||
|
'traefik.http.routers.traefik.rule=Host(`${TRAEFIK_DASHBOARD_HOST}`)',
|
||||||
|
"traefik.http.routers.traefik.service=api@internal",
|
||||||
|
"traefik.http.services.traefik.loadbalancer.server.port=8080",
|
||||||
|
"traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
], 4, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
'mux_enabled' => env('MUX_ENABLED', true),
|
||||||
'dev_webhook' => env('SERVEO_URL'),
|
'dev_webhook' => env('SERVEO_URL'),
|
||||||
|
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
|
||||||
|
'proxy_config_path' => env('BASE_CONFIG_PATH', '/data/coolify') . "/proxy",
|
||||||
];
|
];
|
||||||
|
@ -2,7 +2,6 @@ version: '3.8'
|
|||||||
|
|
||||||
x-testing-host:
|
x-testing-host:
|
||||||
&testing-host-base
|
&testing-host-base
|
||||||
image: coolify-testing-host
|
|
||||||
build:
|
build:
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
context: ./docker/testing-host
|
context: ./docker/testing-host
|
||||||
|
@ -5,4 +5,9 @@ RUN apt-get -y autoremove \
|
|||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*
|
||||||
|
|
||||||
|
RUN echo "alias ll='ls -al'" >> /etc/bash.bashrc
|
||||||
|
RUN echo "alias a='php artisan'" >> /etc/bash.bashrc
|
||||||
|
RUN echo "alias mfs='php artisan migrate:fresh --seed'" >> /etc/bash.bashrc
|
||||||
|
RUN echo "alias cda='composer dump-autoload'" >> /etc/bash.bashrc
|
||||||
|
|
||||||
# COPY --chmod=755 docker/dev-ssu/etc/s6-overlay/ /etc/s6-overlay/
|
# COPY --chmod=755 docker/dev-ssu/etc/s6-overlay/ /etc/s6-overlay/
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
FROM ubuntu:22.04
|
FROM ubuntu:22.04
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
|
|
||||||
# https://download.docker.com/linux/static/stable/
|
# https://download.docker.com/linux/static/stable/
|
||||||
ARG DOCKER_VERSION=20.10.18
|
ARG DOCKER_VERSION=23.0.5
|
||||||
# https://github.com/docker/compose/releases
|
# https://github.com/docker/compose/releases
|
||||||
# Reverted to 2.6.1 because of this https://github.com/docker/compose/issues/9704. 2.9.0 still has a bug.
|
ARG DOCKER_COMPOSE_VERSION=2.17.3
|
||||||
ARG DOCKER_COMPOSE_VERSION=2.6.1
|
# https://github.com/docker/buildx/releases
|
||||||
|
ARG DOCKER_BUILDX_VERSION=0.10.4
|
||||||
# https://github.com/buildpacks/pack/releases
|
# https://github.com/buildpacks/pack/releases
|
||||||
ARG PACK_VERSION=v0.27.0
|
ARG PACK_VERSION=0.29.0
|
||||||
|
# https://github.com/railwayapp/nixpacks/releases
|
||||||
|
ARG NIXPACKS_VERSION=1.6.1
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
ENV TZ=UTC
|
ENV TZ=UTC
|
||||||
@ -17,7 +19,7 @@ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
|||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y gnupg gosu curl ca-certificates zip unzip git git-lfs supervisor \
|
&& apt-get install -y gnupg gosu curl ca-certificates zip unzip git git-lfs supervisor \
|
||||||
sqlite3 libcap2-bin libpng-dev python2 dnsutils openssh-server sudo \
|
sqlite3 libcap2-bin libpng-dev python2 dnsutils openssh-server sudo \
|
||||||
&& apt-get -y autoremove \
|
&& apt-get -y autoremove \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
@ -26,13 +28,14 @@ RUN apt-get update \
|
|||||||
RUN ssh-keygen -A
|
RUN ssh-keygen -A
|
||||||
RUN mkdir -p /run/sshd
|
RUN mkdir -p /run/sshd
|
||||||
|
|
||||||
# Install Docker CLI, Docker Compose, and Pack
|
RUN if [[ ${TARGETPLATFORM} == 'linux/amd64' ]]; then \
|
||||||
RUN mkdir -p ~/.docker/cli-plugins
|
curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx && \
|
||||||
RUN curl -SL https://cdn.coollabs.io/bin/$TARGETPLATFORM/docker-$DOCKER_VERSION -o /usr/bin/docker
|
curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose && \
|
||||||
RUN curl -SL https://cdn.coollabs.io/bin/$TARGETPLATFORM/docker-compose-linux-$DOCKER_COMPOSE_VERSION -o ~/.docker/cli-plugins/docker-compose
|
(curl -sSL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) && \
|
||||||
RUN curl -SL https://cdn.coollabs.io/bin/$TARGETPLATFORM/pack-$PACK_VERSION -o /usr/local/bin/pack
|
(curl -sSL https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux.tgz | tar -C /usr/local/bin/ --no-same-owner -xzv pack) && \
|
||||||
RUN curl -sSL https://nixpacks.com/install.sh | bash
|
curl -sSL https://nixpacks.com/install.sh | bash && \
|
||||||
RUN chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack
|
chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \
|
||||||
|
;fi
|
||||||
RUN groupadd docker
|
RUN groupadd docker
|
||||||
|
|
||||||
# Setup coolify user
|
# Setup coolify user
|
||||||
|
@ -6,8 +6,9 @@ body {
|
|||||||
@apply bg-coolgray-100 text-white font-sans;
|
@apply bg-coolgray-100 text-white font-sans;
|
||||||
}
|
}
|
||||||
|
|
||||||
input, textarea {
|
input,
|
||||||
@apply border-none p-2 bg-coolgray-200 text-white disabled:text-neutral-600 read-only:text-neutral-600 read-only:select-none outline-none ;
|
textarea {
|
||||||
|
@apply border-none p-2 bg-coolgray-200 text-white disabled:text-neutral-600 read-only:text-neutral-600 read-only:select-none outline-none;
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
@apply border-none p-2 bg-coolgray-200 text-white disabled:text-neutral-600 read-only:select-none outline-none;
|
@apply border-none p-2 bg-coolgray-200 text-white disabled:text-neutral-600 read-only:select-none outline-none;
|
||||||
@ -20,11 +21,11 @@ button {
|
|||||||
@apply relative float-left;
|
@apply relative float-left;
|
||||||
}
|
}
|
||||||
.main-menu:after {
|
.main-menu:after {
|
||||||
content: '/';
|
content: "/";
|
||||||
@apply absolute right-0 top-0 text-neutral-400 px-2 pt-[0.3rem];
|
@apply absolute right-0 top-0 text-neutral-400 px-2 pt-[0.3rem];
|
||||||
}
|
}
|
||||||
.magic-input {
|
.magic-input {
|
||||||
@apply w-[25rem] rounded shadow outline-none focus:bg-neutral-700 text-white;
|
@apply w-[25rem] rounded outline-none bg-coolgray-400 focus:bg-neutral-700 text-white;
|
||||||
}
|
}
|
||||||
.magic-items {
|
.magic-items {
|
||||||
@apply absolute top-14 w-[25rem] bg-coolgray-200 border-b-2 border-r-2 border-l-2 border-solid border-coolgray-100 rounded-b;
|
@apply absolute top-14 w-[25rem] bg-coolgray-200 border-b-2 border-r-2 border-l-2 border-solid border-coolgray-100 rounded-b;
|
||||||
@ -41,6 +42,9 @@ h1 {
|
|||||||
h2 {
|
h2 {
|
||||||
@apply text-xl font-bold py-4;
|
@apply text-xl font-bold py-4;
|
||||||
}
|
}
|
||||||
|
h3 {
|
||||||
|
@apply text-lg font-bold py-4;
|
||||||
|
}
|
||||||
.box {
|
.box {
|
||||||
@apply flex items-center justify-center text-sm rounded cursor-pointer h-14 bg-coolgray-200 hover:bg-coollabs p-2;
|
@apply flex items-center justify-center text-sm rounded cursor-pointer h-14 bg-coolgray-200 hover:bg-coollabs p-2;
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
@props([
|
@props([
|
||||||
'isWarning' => null,
|
'isWarning' => null,
|
||||||
|
'isBold' => false,
|
||||||
'disabled' => null,
|
'disabled' => null,
|
||||||
'defaultClass' => 'text-white hover:bg-coollabs h-8 rounded transition-colors',
|
'defaultClass' => 'text-white hover:bg-coollabs h-10 rounded transition-colors',
|
||||||
'defaultWarningClass' => 'text-white bg-red-500 hover:bg-red-600 h-8 rounded',
|
'defaultWarningClass' => 'text-white bg-red-500 hover:bg-red-600 h-10 rounded',
|
||||||
'disabledClass' => 'text-coolgray-200 h-8 rounded',
|
'disabledClass' => 'text-neutral-400 h-10 rounded',
|
||||||
'loadingClass' => 'text-black bg-green-500 h-8 rounded',
|
'loadingClass' => 'text-black bg-green-500 h-10 rounded',
|
||||||
'confirm' => null,
|
'confirm' => null,
|
||||||
'confirmAction' => null,
|
'confirmAction' => null,
|
||||||
])
|
])
|
||||||
<button {{ $attributes }} @class([
|
<button {{ $attributes }} @class([
|
||||||
$defaultClass => !$confirm && !$isWarning && !$disabled,
|
$defaultClass => !$confirm && !$isWarning && !$disabled && !$isBold,
|
||||||
$defaultWarningClass => ($confirm || $isWarning) && !$disabled,
|
$defaultWarningClass => ($confirm || $isWarning) && !$disabled,
|
||||||
$disabledClass => $disabled,
|
$disabledClass => $disabled,
|
||||||
|
$isBold => $isBold
|
||||||
|
? 'bg-coollabs text-white hover:bg-coollabs-100 h-10 rounded transition-colors'
|
||||||
|
: '',
|
||||||
]) @if ($attributes->whereStartsWith('wire:click') && !$disabled)
|
]) @if ($attributes->whereStartsWith('wire:click') && !$disabled)
|
||||||
wire:target="{{ explode('(', $attributes->whereStartsWith('wire:click')->first())[0] }}"
|
wire:target="{{ explode('(', $attributes->whereStartsWith('wire:click')->first())[0] }}"
|
||||||
wire:loading.delay.class="{{ $loadingClass }}" wire:loading.delay.attr="disabled"
|
wire:loading.delay.class="{{ $loadingClass }}" wire:loading.delay.attr="disabled"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<div x-data="magicsearchbar" @slash.window="mainMenu = true" class="pt-2">
|
<div x-data="magicsearchbar" @slash.window="mainMenu = true">
|
||||||
{{-- Main --}}
|
{{-- Main --}}
|
||||||
<template x-cloak x-if="isMainMenu">
|
<template x-cloak x-if="isMainMenu">
|
||||||
<div>
|
<div>
|
||||||
|
@ -1,31 +1,33 @@
|
|||||||
<nav class="flex gap-2">
|
@auth
|
||||||
@auth
|
<nav class="bg-coolgray-200/75">
|
||||||
<div class="fixed flex gap-2 left-2 top-2">
|
<div class="flex px-2 py-1">
|
||||||
<a href="/">
|
<div class="flex gap-2">
|
||||||
<x-inputs.button>Home</x-inputs.button>
|
<a href="/">
|
||||||
</a>
|
<x-inputs.button>Home</x-inputs.button>
|
||||||
<a href="/command-center">
|
|
||||||
<x-inputs.button>Command Center</x-inputs.button>
|
|
||||||
</a>
|
|
||||||
<a href="/profile">
|
|
||||||
<x-inputs.button>Profile</x-inputs.button>
|
|
||||||
</a>
|
|
||||||
@if (auth()->user()->isRoot())
|
|
||||||
<a href="/settings">
|
|
||||||
<x-inputs.button>Settings</x-inputs.button>
|
|
||||||
</a>
|
</a>
|
||||||
@endif
|
<a href="/command-center">
|
||||||
|
<x-inputs.button>Command Center</x-inputs.button>
|
||||||
|
</a>
|
||||||
|
<a href="/profile">
|
||||||
|
<x-inputs.button>Profile</x-inputs.button>
|
||||||
|
</a>
|
||||||
|
@if (auth()->user()->isRoot())
|
||||||
|
<a href="/settings">
|
||||||
|
<x-inputs.button>Settings</x-inputs.button>
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<div class="flex-1"></div>
|
||||||
|
<x-magic-bar />
|
||||||
|
<div class="flex-1"></div>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
{{-- <livewire:check-update /> --}}
|
||||||
|
<livewire:force-upgrade />
|
||||||
|
<form action="/logout" method="POST">
|
||||||
|
@csrf
|
||||||
|
<x-inputs.button type="submit">Logout</x-inputs.button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1"></div>
|
</nav>
|
||||||
<x-magic-bar />
|
@endauth
|
||||||
<div class="flex-1"></div>
|
|
||||||
<div class="fixed flex gap-2 right-2 top-2">
|
|
||||||
{{-- <livewire:check-update /> --}}
|
|
||||||
<livewire:force-upgrade />
|
|
||||||
<form action="/logout" method="POST">
|
|
||||||
@csrf
|
|
||||||
<x-inputs.button type="submit">Logout</x-inputs.button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
@endauth
|
|
||||||
</nav>
|
|
||||||
|
3
resources/views/components/proxy/loading.blade.php
Normal file
3
resources/views/components/proxy/loading.blade.php
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<div>
|
||||||
|
Loading...
|
||||||
|
</div>
|
47
resources/views/components/proxy/options.blade.php
Normal file
47
resources/views/components/proxy/options.blade.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
@props(['proxy_settings'])
|
||||||
|
<div class="mt-4">
|
||||||
|
<label>
|
||||||
|
<div>Edit config file</div>
|
||||||
|
<textarea cols="45" rows="6"></textarea>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<label>
|
||||||
|
Enable dashboard?
|
||||||
|
<input type="checkbox" />
|
||||||
|
(auto-save)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<a href="#">Visit Dashboard</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<label>
|
||||||
|
<div>Setup hostname for Dashboard</div>
|
||||||
|
<div class="mt-2"></div>
|
||||||
|
<label>
|
||||||
|
<div>Hostname <span class="text-xs"> Eg: dashboard.example.com </span></div>
|
||||||
|
<input type="text" />
|
||||||
|
</label>
|
||||||
|
<button>Update</button>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<label>
|
||||||
|
<div>Dashboard credentials</div>
|
||||||
|
<div class="mt-2"></div>
|
||||||
|
<label>
|
||||||
|
Username
|
||||||
|
<input type="text" />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Password
|
||||||
|
<input type="password" />
|
||||||
|
</label>
|
||||||
|
<button>Update</button>
|
||||||
|
</label>
|
||||||
|
</div>
|
@ -1,5 +1,3 @@
|
|||||||
@extends('errors::minimal')
|
<div>
|
||||||
|
You are lost. <a href="{{ route('dashboard') }}">Go home</a>
|
||||||
@section('title', __('Not Found'))
|
</div>
|
||||||
@section('code', '404')
|
|
||||||
@section('message', __('Not Found'))
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<div>
|
<div>
|
||||||
<div
|
@if ($this->activity)
|
||||||
class="flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4">
|
<div
|
||||||
@if ($this->activity)
|
class="flex flex-col-reverse w-full overflow-y-auto border border-solid rounded border-coolgray-300 max-h-[32rem] p-4">
|
||||||
<pre class="whitespace-pre-wrap" @if ($isPollingActive) wire:poll.750ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($this->activity) }}</pre>
|
<pre class="whitespace-pre-wrap" @if ($isPollingActive) wire:poll.750ms="polling" @endif>{{ \App\Actions\CoolifyTask\RunRemoteProcess::decodeOutput($this->activity) }}</pre>
|
||||||
@else
|
{{-- @else
|
||||||
<pre class="whitespace-pre-wrap">Output will be here...</pre>
|
<pre class="whitespace-pre-wrap">Output will be here...</pre> --}}
|
||||||
@endif
|
</div>
|
||||||
</div>
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
<x-inputs.button type="submit">Run</x-inputs.button>
|
<x-inputs.button isBold type="submit">Run</x-inputs.button>
|
||||||
</form>
|
</form>
|
||||||
<div class="container w-full pt-10 mx-auto">
|
<div class="container w-full pt-10 mx-auto">
|
||||||
<livewire:activity-monitor />
|
<livewire:activity-monitor />
|
||||||
|
@ -1,6 +1,23 @@
|
|||||||
<div x-data="{ deleteServer: false }">
|
<div x-data="{ deleteServer: false }">
|
||||||
<x-naked-modal show="deleteServer" message='Are you sure you would like to delete this server?' />
|
<x-naked-modal show="deleteServer" message='Are you sure you would like to delete this server?' />
|
||||||
<form wire:submit.prevent='submit' class="flex flex-col">
|
<form wire:submit.prevent='submit' class="flex flex-col">
|
||||||
|
<div class="flex flex-col pb-4">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div class="text-3xl font-bold">Server</div>
|
||||||
|
<x-inputs.button isBold type="submit">Submit</x-inputs.button>
|
||||||
|
<x-inputs.button isWarning x-on:click.prevent="deleteServer = true">
|
||||||
|
Delete
|
||||||
|
</x-inputs.button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
@if ($server->settings->is_validated)
|
||||||
|
<div class="text-green-400/90">Validated</div>
|
||||||
|
@else
|
||||||
|
<div class="text-red-400/90">Not validated</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
<div class="flex flex-col w-96">
|
<div class="flex flex-col w-96">
|
||||||
<x-inputs.input id="server.name" label="Name" required />
|
<x-inputs.input id="server.name" label="Name" required />
|
||||||
@ -18,15 +35,11 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex gap-2">
|
||||||
<x-inputs.button type="submit">Submit</x-inputs.button>
|
<x-inputs.button isBold wire:click.prevent='validateServer'>Validate Server</x-inputs.button>
|
||||||
<x-inputs.button wire:click.prevent='checkServer'>Check Server</x-inputs.button>
|
<x-inputs.button isBold wire:click.prevent='installDocker'>Install Docker</x-inputs.button>
|
||||||
<x-inputs.button wire:click.prevent='installDocker'>Install Docker</x-inputs.button>
|
|
||||||
<x-inputs.button isWarning x-on:click.prevent="deleteServer = true">
|
|
||||||
Delete
|
|
||||||
</x-inputs.button>
|
|
||||||
</div>
|
</div>
|
||||||
<x-inputs.input class="" disabled type="checkbox" id="server.settings.is_validated" label="Validated" />
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@isset($uptime)
|
@isset($uptime)
|
||||||
|
@ -1,30 +1,52 @@
|
|||||||
<div>
|
<div>
|
||||||
<h2> Proxy </h2>
|
|
||||||
|
|
||||||
@if($this->server->extra_attributes->proxy)
|
@if ($this->server->extra_attributes->proxy_status !== 'running')
|
||||||
<div class="mt-12">
|
|
||||||
<div>
|
|
||||||
Proxy type: {{ $this->server->extra_attributes->proxy }}
|
|
||||||
</div>
|
|
||||||
<div class="mt-12"> Features in W11.</div>
|
|
||||||
<ul>
|
|
||||||
<li>Edit config file</li>
|
|
||||||
<li>Enable dashboard (blocking port by firewall)</li>
|
|
||||||
<li>Dashboard access - login/password</li>
|
|
||||||
<li>Setup host for Traefik Dashboard</li>
|
|
||||||
<li>Visit (nav to traefik dashboard)</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
@else
|
|
||||||
No proxy installed.
|
|
||||||
<select wire:model="selectedProxy">
|
<select wire:model="selectedProxy">
|
||||||
<option value="{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }}">
|
<option value="{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }}">
|
||||||
{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }}
|
{{ \App\Enums\ProxyTypes::TRAEFIK_V2 }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<button wire:click="runInstallProxy">Install Proxy</button>
|
<x-inputs.button isBold wire:click="setProxy">Set Proxy</x-inputs.button>
|
||||||
|
@endif
|
||||||
|
@if ($this->server->extra_attributes->proxy_type)
|
||||||
|
<div wire:poll="proxyStatus">
|
||||||
|
@if (
|
||||||
|
$this->server->extra_attributes->last_applied_proxy_settings &&
|
||||||
|
$this->server->extra_attributes->last_saved_proxy_settings !==
|
||||||
|
$this->server->extra_attributes->last_applied_proxy_settings)
|
||||||
|
<div class="text-red-500">Configuration out of sync.</div>
|
||||||
|
@endif
|
||||||
|
@if ($this->server->extra_attributes->proxy_status !== 'running')
|
||||||
|
<x-inputs.button isBold wire:click="installProxy">
|
||||||
|
Install
|
||||||
|
</x-inputs.button>
|
||||||
|
@endif
|
||||||
|
<x-inputs.button isBold wire:click="stopProxy">Stop</x-inputs.button>
|
||||||
|
<span x-data="{ showConfiguration: false }">
|
||||||
|
<x-inputs.button isBold x-on:click="showConfiguration = !showConfiguration">Show Configuration
|
||||||
|
</x-inputs.button>
|
||||||
|
<div class="pt-4">
|
||||||
|
<livewire:activity-monitor />
|
||||||
|
</div>
|
||||||
|
<template x-if="showConfiguration">
|
||||||
|
<div x-init="$wire.checkProxySettingsInSync">
|
||||||
|
<h3>Configuration</h3>
|
||||||
|
<div wire:loading wire:target="checkProxySettingsInSync">
|
||||||
|
<x-proxy.loading />
|
||||||
|
</div>
|
||||||
|
@isset($this->proxy_settings)
|
||||||
|
<form wire:submit.prevent='saveConfiguration'>
|
||||||
|
<x-inputs.button isBold>Save</x-inputs.button>
|
||||||
|
<x-inputs.button x-on:click="showConfiguration = false" isBold
|
||||||
|
wire:click.prevent="installProxy">
|
||||||
|
Apply
|
||||||
|
</x-inputs.button>
|
||||||
|
<textarea wire:model.defer="proxy_settings" class="w-full" rows="30"></textarea>
|
||||||
|
</form>
|
||||||
|
@endisset
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<livewire:activity-monitor />
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,20 +1,34 @@
|
|||||||
<x-layout>
|
<x-layout>
|
||||||
<h1>Server</h1>
|
|
||||||
<livewire:server.form :server_id="$server->id" />
|
<livewire:server.form :server_id="$server->id" />
|
||||||
<h2>Private Key <a href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}">
|
<div class="flex items-center gap-2">
|
||||||
<x-inputs.button>Change</x-inputs.button>
|
<h2>Private Key</h2>
|
||||||
|
<a href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}">
|
||||||
|
<x-inputs.button isBold>Change</x-inputs.button>
|
||||||
</a>
|
</a>
|
||||||
</h2>
|
</div>
|
||||||
<p>{{ $server->privateKey->name }}</p>
|
<p>{{ $server->privateKey->name }}</p>
|
||||||
<h2>Destinations <a href="{{ route('destination.new', ['server_id' => $server->id]) }}">
|
<div class="flex items-center gap-2">
|
||||||
<x-inputs.button>New</x-inputs.button>
|
<h2>Destinations</h2>
|
||||||
</a></h2>
|
<a href="{{ route('destination.new', ['server_id' => $server->id]) }}">
|
||||||
@if ($server->standaloneDockers)
|
<x-inputs.button isBold>New</x-inputs.button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@if ($server->standaloneDockers->count() > 0)
|
||||||
@foreach ($server->standaloneDockers as $docker)
|
@foreach ($server->standaloneDockers as $docker)
|
||||||
<p>Network: {{ data_get($docker, 'network') }}</p>
|
<p>Network: {{ data_get($docker, 'network') }}</p>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@else
|
||||||
|
<p>No destinations found</p>
|
||||||
|
@endif
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h2>Proxy</h2>
|
||||||
|
@if ($server->settings->is_validated)
|
||||||
|
<div>{{ $server->extra_attributes->proxy_status }}</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@if ($server->settings->is_validated)
|
||||||
|
<livewire:server.proxy :server="$server" />
|
||||||
|
@else
|
||||||
|
<p>Server is not validated. Validate first.</p>
|
||||||
@endif
|
@endif
|
||||||
<h1> {{ $server->name }}</h1>
|
|
||||||
|
|
||||||
<livewire:server.proxy :server="$server"/>
|
|
||||||
</x-layout>
|
</x-layout>
|
||||||
|
@ -34,9 +34,12 @@ function schedule-run {
|
|||||||
function reset-db {
|
function reset-db {
|
||||||
bash vendor/bin/spin exec -u webuser coolify php artisan migrate:fresh --seed
|
bash vendor/bin/spin exec -u webuser coolify php artisan migrate:fresh --seed
|
||||||
}
|
}
|
||||||
|
function mfs {
|
||||||
|
reset-db
|
||||||
|
}
|
||||||
function reset-db-production {
|
function reset-db-production {
|
||||||
bash vendor/bin/spin exec -u webuser coolify php artisan migrate:fresh --force --seed --seeder=ProductionSeeder ||
|
bash vendor/bin/spin exec -u webuser coolify php artisan migrate:fresh --force --seed --seeder=ProductionSeeder ||
|
||||||
php artisan migrate:fresh --force --seed --seeder=ProductionSeeder
|
php artisan migrate:fresh --force --seed --seeder=ProductionSeeder
|
||||||
}
|
}
|
||||||
function coolify {
|
function coolify {
|
||||||
bash vendor/bin/spin exec -u webuser coolify bash
|
bash vendor/bin/spin exec -u webuser coolify bash
|
||||||
|
@ -7,9 +7,9 @@ export default defineConfig({
|
|||||||
host: "0.0.0.0",
|
host: "0.0.0.0",
|
||||||
hmr: process.env.GITPOD_WORKSPACE_URL
|
hmr: process.env.GITPOD_WORKSPACE_URL
|
||||||
? {
|
? {
|
||||||
// Due to port fowarding, we have to replace
|
// Due to port forwarding, we have to replace
|
||||||
// 'https' with the forwarded port, as this
|
// 'https' with the forwarded port, as this
|
||||||
// is the URI created by Gitpod.
|
// is the URI created by GitPod.
|
||||||
host: process.env.GITPOD_WORKSPACE_URL.replace(
|
host: process.env.GITPOD_WORKSPACE_URL.replace(
|
||||||
"https://",
|
"https://",
|
||||||
"5173-"
|
"5173-"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user