Merge branch 'feature' into feature/oauth
This commit is contained in:
@@ -5,3 +5,7 @@ function get_team_id_from_token()
|
||||
$token = auth()->user()->currentAccessToken();
|
||||
return data_get($token, 'team_id');
|
||||
}
|
||||
function invalid_token()
|
||||
{
|
||||
return response()->json(['error' => 'Invalid token.', 'docs' => 'https://coolify.io/docs/api/authentication'], 400);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\ProxyTypes;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\Server;
|
||||
@@ -215,6 +216,45 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource,
|
||||
}
|
||||
return $payload;
|
||||
}
|
||||
function fqdnLabelsForCaddy(string $network, string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null)
|
||||
{
|
||||
$labels = collect([]);
|
||||
if ($serviceLabels) {
|
||||
$labels->push("caddy_ingress_network={$uuid}");
|
||||
} else {
|
||||
$labels->push("caddy_ingress_network={$network}");
|
||||
}
|
||||
foreach ($domains as $loop => $domain) {
|
||||
$loop = $loop;
|
||||
$url = Url::fromString($domain);
|
||||
$host = $url->getHost();
|
||||
$path = $url->getPath();
|
||||
// $stripped_path = str($path)->replaceEnd('/', '');
|
||||
|
||||
$schema = $url->getScheme();
|
||||
$port = $url->getPort();
|
||||
if (is_null($port) && !is_null($onlyPort)) {
|
||||
$port = $onlyPort;
|
||||
}
|
||||
$labels->push("caddy_{$loop}={$schema}://{$host}");
|
||||
$labels->push("caddy_{$loop}.header=-Server");
|
||||
$labels->push("caddy_{$loop}.try_files={path} /index.html /index.php");
|
||||
|
||||
if ($port) {
|
||||
$labels->push("caddy_{$loop}.handle_path.{$loop}_reverse_proxy={{upstreams $port}}");
|
||||
} else {
|
||||
$labels->push("caddy_{$loop}.handle_path.{$loop}_reverse_proxy={{upstreams}}");
|
||||
}
|
||||
$labels->push("caddy_{$loop}.handle_path={$path}*");
|
||||
if ($is_gzip_enabled) {
|
||||
$labels->push("caddy_{$loop}.encode=zstd gzip");
|
||||
}
|
||||
if (isDev()) {
|
||||
// $labels->push("caddy_{$loop}.tls=internal");
|
||||
}
|
||||
}
|
||||
return $labels->sort();
|
||||
}
|
||||
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null)
|
||||
{
|
||||
$labels = collect([]);
|
||||
@@ -395,7 +435,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
||||
} else {
|
||||
$domains = Str::of(data_get($application, 'fqdn'))->explode(',');
|
||||
}
|
||||
// Add Traefik labels no matter which proxy is selected
|
||||
// Add Traefik labels
|
||||
$labels = $labels->merge(fqdnLabelsForTraefik(
|
||||
uuid: $appUuid,
|
||||
domains: $domains,
|
||||
@@ -404,6 +444,16 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
||||
));
|
||||
// Add Caddy labels
|
||||
$labels = $labels->merge(fqdnLabelsForCaddy(
|
||||
network: $application->destination->network,
|
||||
uuid: $appUuid,
|
||||
domains: $domains,
|
||||
onlyPort: $onlyPort,
|
||||
is_force_https_enabled: $application->isForceHttpsEnabled(),
|
||||
is_gzip_enabled: $application->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $application->isStripprefixEnabled()
|
||||
));
|
||||
}
|
||||
return $labels->all();
|
||||
}
|
||||
@@ -506,3 +556,33 @@ function convert_docker_run_to_compose(?string $custom_docker_run_options = null
|
||||
}
|
||||
return $compose_options->toArray();
|
||||
}
|
||||
|
||||
function validateComposeFile(string $compose, int $server_id): string|Throwable
|
||||
{
|
||||
return 'OK';
|
||||
try {
|
||||
$uuid = Str::random(10);
|
||||
$server = Server::findOrFail($server_id);
|
||||
$base64_compose = base64_encode($compose);
|
||||
$output = instant_remote_process([
|
||||
"echo {$base64_compose} | base64 -d > /tmp/{$uuid}.yml",
|
||||
"docker compose -f /tmp/{$uuid}.yml config",
|
||||
], $server);
|
||||
ray($output);
|
||||
return 'OK';
|
||||
} catch (\Throwable $e) {
|
||||
ray($e);
|
||||
return $e->getMessage();
|
||||
} finally {
|
||||
instant_remote_process([
|
||||
"rm /tmp/{$uuid}.yml",
|
||||
], $server);
|
||||
}
|
||||
}
|
||||
|
||||
function escapeEnvVariables($value)
|
||||
{
|
||||
$search = array("\\", "\r", "\t", "\x0", '"', "'", "$");
|
||||
$replace = array("\\\\", "\\r", "\\t", "\\0", '\"', "\'", "$$");
|
||||
return str_replace($search, $replace, $value);
|
||||
}
|
||||
|
||||
@@ -7,12 +7,7 @@ use App\Models\Server;
|
||||
use Spatie\Url\Url;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
function get_proxy_path()
|
||||
{
|
||||
$base_path = config('coolify.base_config_path');
|
||||
$proxy_path = "$base_path/proxy";
|
||||
return $proxy_path;
|
||||
}
|
||||
|
||||
function connectProxyToNetworks(Server $server)
|
||||
{
|
||||
if ($server->isSwarm()) {
|
||||
@@ -75,7 +70,9 @@ function connectProxyToNetworks(Server $server)
|
||||
}
|
||||
function generate_default_proxy_configuration(Server $server)
|
||||
{
|
||||
$proxy_path = get_proxy_path();
|
||||
$proxy_path = $server->proxyPath();
|
||||
$proxy_type = $server->proxyType();
|
||||
|
||||
if ($server->isSwarm()) {
|
||||
$networks = collect($server->swarmDockers)->map(function ($docker) {
|
||||
return $docker['network'];
|
||||
@@ -98,287 +95,126 @@ function generate_default_proxy_configuration(Server $server)
|
||||
"external" => true,
|
||||
];
|
||||
});
|
||||
$labels = [
|
||||
"traefik.enable=true",
|
||||
"traefik.http.routers.traefik.entrypoints=http",
|
||||
"traefik.http.routers.traefik.service=api@internal",
|
||||
"traefik.http.services.traefik.loadbalancer.server.port=8080",
|
||||
"coolify.managed=true",
|
||||
];
|
||||
$config = [
|
||||
"version" => "3.8",
|
||||
"networks" => $array_of_networks->toArray(),
|
||||
"services" => [
|
||||
"traefik" => [
|
||||
"container_name" => "coolify-proxy",
|
||||
"image" => "traefik:v2.10",
|
||||
"restart" => RESTART_MODE,
|
||||
"extra_hosts" => [
|
||||
"host.docker.internal:host-gateway",
|
||||
if ($proxy_type === 'TRAEFIK_V2') {
|
||||
$labels = [
|
||||
"traefik.enable=true",
|
||||
"traefik.http.routers.traefik.entrypoints=http",
|
||||
"traefik.http.routers.traefik.service=api@internal",
|
||||
"traefik.http.services.traefik.loadbalancer.server.port=8080",
|
||||
"coolify.managed=true",
|
||||
];
|
||||
$config = [
|
||||
"version" => "3.8",
|
||||
"networks" => $array_of_networks->toArray(),
|
||||
"services" => [
|
||||
"traefik" => [
|
||||
"container_name" => "coolify-proxy",
|
||||
"image" => "traefik:v2.10",
|
||||
"restart" => RESTART_MODE,
|
||||
"extra_hosts" => [
|
||||
"host.docker.internal:host-gateway",
|
||||
],
|
||||
"networks" => $networks->toArray(),
|
||||
"ports" => [
|
||||
"80:80",
|
||||
"443:443",
|
||||
"8080:8080",
|
||||
],
|
||||
"healthcheck" => [
|
||||
"test" => "wget -qO- http://localhost:80/ping || exit 1",
|
||||
"interval" => "4s",
|
||||
"timeout" => "2s",
|
||||
"retries" => 5,
|
||||
],
|
||||
"volumes" => [
|
||||
"/var/run/docker.sock:/var/run/docker.sock:ro",
|
||||
"{$proxy_path}:/traefik",
|
||||
],
|
||||
"command" => [
|
||||
"--ping=true",
|
||||
"--ping.entrypoint=http",
|
||||
"--api.dashboard=true",
|
||||
"--api.insecure=false",
|
||||
"--entrypoints.http.address=:80",
|
||||
"--entrypoints.https.address=:443",
|
||||
"--entrypoints.http.http.encodequerysemicolons=true",
|
||||
"--entryPoints.http.http2.maxConcurrentStreams=50",
|
||||
"--entrypoints.https.http.encodequerysemicolons=true",
|
||||
"--entryPoints.https.http2.maxConcurrentStreams=50",
|
||||
"--providers.docker.exposedbydefault=false",
|
||||
"--providers.file.directory=/traefik/dynamic/",
|
||||
"--providers.file.watch=true",
|
||||
"--certificatesresolvers.letsencrypt.acme.httpchallenge=true",
|
||||
"--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json",
|
||||
"--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http",
|
||||
],
|
||||
"labels" => $labels,
|
||||
],
|
||||
"networks" => $networks->toArray(),
|
||||
"ports" => [
|
||||
"80:80",
|
||||
"443:443",
|
||||
"8080:8080",
|
||||
],
|
||||
"healthcheck" => [
|
||||
"test" => "wget -qO- http://localhost:80/ping || exit 1",
|
||||
"interval" => "4s",
|
||||
"timeout" => "2s",
|
||||
"retries" => 5,
|
||||
],
|
||||
"volumes" => [
|
||||
"/var/run/docker.sock:/var/run/docker.sock:ro",
|
||||
"{$proxy_path}:/traefik",
|
||||
],
|
||||
"command" => [
|
||||
"--ping=true",
|
||||
"--ping.entrypoint=http",
|
||||
"--api.dashboard=true",
|
||||
"--api.insecure=false",
|
||||
"--entrypoints.http.address=:80",
|
||||
"--entrypoints.https.address=:443",
|
||||
"--entrypoints.http.http.encodequerysemicolons=true",
|
||||
"--entryPoints.http.http2.maxConcurrentStreams=50",
|
||||
"--entrypoints.https.http.encodequerysemicolons=true",
|
||||
"--entryPoints.https.http2.maxConcurrentStreams=50",
|
||||
"--providers.docker.exposedbydefault=false",
|
||||
"--providers.file.directory=/traefik/dynamic/",
|
||||
"--providers.file.watch=true",
|
||||
"--certificatesresolvers.letsencrypt.acme.httpchallenge=true",
|
||||
"--certificatesresolvers.letsencrypt.acme.storage=/traefik/acme.json",
|
||||
"--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=http",
|
||||
],
|
||||
"labels" => $labels,
|
||||
],
|
||||
],
|
||||
];
|
||||
if (isDev()) {
|
||||
// $config['services']['traefik']['command'][] = "--log.level=debug";
|
||||
$config['services']['traefik']['command'][] = "--accesslog.filepath=/traefik/access.log";
|
||||
$config['services']['traefik']['command'][] = "--accesslog.bufferingsize=100";
|
||||
}
|
||||
if ($server->isSwarm()) {
|
||||
data_forget($config, 'services.traefik.container_name');
|
||||
data_forget($config, 'services.traefik.restart');
|
||||
data_forget($config, 'services.traefik.labels');
|
||||
];
|
||||
if (isDev()) {
|
||||
// $config['services']['traefik']['command'][] = "--log.level=debug";
|
||||
$config['services']['traefik']['command'][] = "--accesslog.filepath=/traefik/access.log";
|
||||
$config['services']['traefik']['command'][] = "--accesslog.bufferingsize=100";
|
||||
}
|
||||
if ($server->isSwarm()) {
|
||||
data_forget($config, 'services.traefik.container_name');
|
||||
data_forget($config, 'services.traefik.restart');
|
||||
data_forget($config, 'services.traefik.labels');
|
||||
|
||||
$config['services']['traefik']['command'][] = "--providers.docker.swarmMode=true";
|
||||
$config['services']['traefik']['deploy'] = [
|
||||
"labels" => $labels,
|
||||
"placement" => [
|
||||
"constraints" => [
|
||||
"node.role==manager",
|
||||
$config['services']['traefik']['command'][] = "--providers.docker.swarmMode=true";
|
||||
$config['services']['traefik']['deploy'] = [
|
||||
"labels" => $labels,
|
||||
"placement" => [
|
||||
"constraints" => [
|
||||
"node.role==manager",
|
||||
],
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$config['services']['traefik']['command'][] = "--providers.docker=true";
|
||||
}
|
||||
} else if ($proxy_type === 'CADDY') {
|
||||
$config = [
|
||||
"version" => "3.8",
|
||||
"networks" => $array_of_networks->toArray(),
|
||||
"services" => [
|
||||
"caddy" => [
|
||||
"container_name" => "coolify-proxy",
|
||||
"image" => "lucaslorentz/caddy-docker-proxy:2.8-alpine",
|
||||
"restart" => RESTART_MODE,
|
||||
"extra_hosts" => [
|
||||
"host.docker.internal:host-gateway",
|
||||
],
|
||||
"environment" => [
|
||||
"CADDY_DOCKER_POLLING_INTERVAL=5s",
|
||||
"CADDY_DOCKER_CADDYFILE_PATH=/dynamic/Caddyfile",
|
||||
],
|
||||
"networks" => $networks->toArray(),
|
||||
"ports" => [
|
||||
"80:80",
|
||||
"443:443",
|
||||
],
|
||||
// "healthcheck" => [
|
||||
// "test" => "wget -qO- http://localhost:80|| exit 1",
|
||||
// "interval" => "4s",
|
||||
// "timeout" => "2s",
|
||||
// "retries" => 5,
|
||||
// ],
|
||||
"volumes" => [
|
||||
"/var/run/docker.sock:/var/run/docker.sock:ro",
|
||||
"{$proxy_path}/dynamic:/dynamic",
|
||||
"{$proxy_path}/config:/config",
|
||||
"{$proxy_path}/data:/data",
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$config['services']['traefik']['command'][] = "--providers.docker=true";
|
||||
return null;
|
||||
}
|
||||
|
||||
$config = Yaml::dump($config, 12, 2);
|
||||
SaveConfiguration::run($server, $config);
|
||||
return $config;
|
||||
}
|
||||
function setup_dynamic_configuration()
|
||||
{
|
||||
$dynamic_config_path = get_proxy_path() . "/dynamic";
|
||||
$settings = InstanceSettings::get();
|
||||
$server = Server::find(0);
|
||||
if ($server) {
|
||||
$file = "$dynamic_config_path/coolify.yaml";
|
||||
if (empty($settings->fqdn)) {
|
||||
instant_remote_process([
|
||||
"rm -f $file",
|
||||
], $server);
|
||||
} else {
|
||||
$url = Url::fromString($settings->fqdn);
|
||||
$host = $url->getHost();
|
||||
$schema = $url->getScheme();
|
||||
$traefik_dynamic_conf = [
|
||||
'http' =>
|
||||
[
|
||||
'middlewares' => [
|
||||
'redirect-to-https' => [
|
||||
'redirectscheme' => [
|
||||
'scheme' => 'https',
|
||||
],
|
||||
],
|
||||
'gzip' => [
|
||||
'compress' => true,
|
||||
],
|
||||
],
|
||||
'routers' =>
|
||||
[
|
||||
'coolify-http' =>
|
||||
[
|
||||
'middlewares' => [
|
||||
0 => 'gzip',
|
||||
],
|
||||
'entryPoints' => [
|
||||
0 => 'http',
|
||||
],
|
||||
'service' => 'coolify',
|
||||
'rule' => "Host(`{$host}`)",
|
||||
],
|
||||
'coolify-realtime-ws' =>
|
||||
[
|
||||
'entryPoints' => [
|
||||
0 => 'http',
|
||||
],
|
||||
'service' => 'coolify-realtime',
|
||||
'rule' => "Host(`{$host}`) && PathPrefix(`/app`)",
|
||||
],
|
||||
],
|
||||
'services' =>
|
||||
[
|
||||
'coolify' =>
|
||||
[
|
||||
'loadBalancer' =>
|
||||
[
|
||||
'servers' =>
|
||||
[
|
||||
0 =>
|
||||
[
|
||||
'url' => 'http://coolify:80',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'coolify-realtime' =>
|
||||
[
|
||||
'loadBalancer' =>
|
||||
[
|
||||
'servers' =>
|
||||
[
|
||||
0 =>
|
||||
[
|
||||
'url' => 'http://coolify-realtime:6001',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
if ($schema === 'https') {
|
||||
$traefik_dynamic_conf['http']['routers']['coolify-http']['middlewares'] = [
|
||||
0 => 'redirect-to-https',
|
||||
];
|
||||
|
||||
$traefik_dynamic_conf['http']['routers']['coolify-https'] = [
|
||||
'entryPoints' => [
|
||||
0 => 'https',
|
||||
],
|
||||
'service' => 'coolify',
|
||||
'rule' => "Host(`{$host}`)",
|
||||
'tls' => [
|
||||
'certresolver' => 'letsencrypt',
|
||||
],
|
||||
];
|
||||
$traefik_dynamic_conf['http']['routers']['coolify-realtime-wss'] = [
|
||||
'entryPoints' => [
|
||||
0 => 'https',
|
||||
],
|
||||
'service' => 'coolify-realtime',
|
||||
'rule' => "Host(`{$host}`) && PathPrefix(`/app`)",
|
||||
'tls' => [
|
||||
'certresolver' => 'letsencrypt',
|
||||
],
|
||||
];
|
||||
}
|
||||
$yaml = Yaml::dump($traefik_dynamic_conf, 12, 2);
|
||||
$yaml =
|
||||
"# This file is automatically generated by Coolify.\n" .
|
||||
"# Do not edit it manually (only if you know what are you doing).\n\n" .
|
||||
$yaml;
|
||||
|
||||
$base64 = base64_encode($yaml);
|
||||
instant_remote_process([
|
||||
"mkdir -p $dynamic_config_path",
|
||||
"echo '$base64' | base64 -d > $file",
|
||||
], $server);
|
||||
|
||||
if (config('app.env') == 'local') {
|
||||
// ray($yaml);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function setup_default_redirect_404(string|null $redirect_url, Server $server)
|
||||
{
|
||||
$traefik_dynamic_conf_path = get_proxy_path() . "/dynamic";
|
||||
$traefik_default_redirect_file = "$traefik_dynamic_conf_path/default_redirect_404.yaml";
|
||||
if (empty($redirect_url)) {
|
||||
instant_remote_process([
|
||||
"mkdir -p $traefik_dynamic_conf_path",
|
||||
"rm -f $traefik_default_redirect_file",
|
||||
], $server);
|
||||
} else {
|
||||
$traefik_dynamic_conf = [
|
||||
'http' =>
|
||||
[
|
||||
'routers' =>
|
||||
[
|
||||
'catchall' =>
|
||||
[
|
||||
'entryPoints' => [
|
||||
0 => 'http',
|
||||
1 => 'https',
|
||||
],
|
||||
'service' => 'noop',
|
||||
'rule' => "HostRegexp(`{catchall:.*}`)",
|
||||
'priority' => 1,
|
||||
'middlewares' => [
|
||||
0 => 'redirect-regexp@file',
|
||||
],
|
||||
],
|
||||
],
|
||||
'services' =>
|
||||
[
|
||||
'noop' =>
|
||||
[
|
||||
'loadBalancer' =>
|
||||
[
|
||||
'servers' =>
|
||||
[
|
||||
0 =>
|
||||
[
|
||||
'url' => '',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'middlewares' =>
|
||||
[
|
||||
'redirect-regexp' =>
|
||||
[
|
||||
'redirectRegex' =>
|
||||
[
|
||||
'regex' => '(.*)',
|
||||
'replacement' => $redirect_url,
|
||||
'permanent' => false,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
$yaml = Yaml::dump($traefik_dynamic_conf, 12, 2);
|
||||
$yaml =
|
||||
"# This file is automatically generated by Coolify.\n" .
|
||||
"# Do not edit it manually (only if you know what are you doing).\n\n" .
|
||||
$yaml;
|
||||
|
||||
$base64 = base64_encode($yaml);
|
||||
instant_remote_process([
|
||||
"mkdir -p $traefik_dynamic_conf_path",
|
||||
"echo '$base64' | base64 -d > $traefik_default_redirect_file",
|
||||
], $server);
|
||||
|
||||
if (config('app.env') == 'local') {
|
||||
ray($yaml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ function remote_process(
|
||||
?string $type_uuid = null,
|
||||
?Model $model = null,
|
||||
bool $ignore_errors = false,
|
||||
$callEventOnFinish = null
|
||||
$callEventOnFinish = null,
|
||||
$callEventData = null
|
||||
): Activity {
|
||||
if (is_null($type)) {
|
||||
$type = ActivityTypes::INLINE->value;
|
||||
@@ -50,6 +51,7 @@ function remote_process(
|
||||
model: $model,
|
||||
ignore_errors: $ignore_errors,
|
||||
call_event_on_finish: $callEventOnFinish,
|
||||
call_event_data: $callEventData,
|
||||
),
|
||||
])();
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase $oneS
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
function updateCompose($resource)
|
||||
function updateCompose(ServiceApplication|ServiceDatabase $resource)
|
||||
{
|
||||
try {
|
||||
$name = data_get($resource, 'name');
|
||||
@@ -90,6 +90,9 @@ function updateCompose($resource)
|
||||
// Switch Image
|
||||
$image = data_get($resource, 'image');
|
||||
data_set($dockerCompose, "services.{$name}.image", $image);
|
||||
$dockerComposeRaw = Yaml::dump($dockerCompose, 10, 2);
|
||||
$resource->service->docker_compose_raw = $dockerComposeRaw;
|
||||
$resource->service->save();
|
||||
|
||||
if (!str($resource->fqdn)->contains(',')) {
|
||||
// Update FQDN
|
||||
@@ -105,7 +108,6 @@ function updateCompose($resource)
|
||||
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
|
||||
$url = Url::fromString($resource->fqdn);
|
||||
$url = $url->getHost();
|
||||
ray($url);
|
||||
if ($generatedEnv) {
|
||||
$url = Str::of($resource->fqdn)->after('://');
|
||||
$generatedEnv->value = $url;
|
||||
@@ -113,9 +115,6 @@ function updateCompose($resource)
|
||||
}
|
||||
}
|
||||
|
||||
$dockerComposeRaw = Yaml::dump($dockerCompose, 10, 2);
|
||||
$resource->service->docker_compose_raw = $dockerComposeRaw;
|
||||
$resource->service->save();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Jobs\ServerFilesFromServerJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\EnvironmentVariable;
|
||||
@@ -615,7 +616,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception($e->getMessage());
|
||||
}
|
||||
|
||||
$allServices = getServiceTemplates();
|
||||
$topLevelVolumes = collect(data_get($yaml, 'volumes', []));
|
||||
$topLevelNetworks = collect(data_get($yaml, 'networks', []));
|
||||
$dockerComposeVersion = data_get($yaml, 'version') ?? '3.8';
|
||||
@@ -630,7 +631,22 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
}
|
||||
}
|
||||
$definedNetwork = collect([$resource->uuid]);
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource) {
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $resource, $allServices) {
|
||||
// Workarounds for beta users.
|
||||
if ($serviceName === 'registry') {
|
||||
$tempServiceName = "docker-registry";
|
||||
} else {
|
||||
$tempServiceName = $serviceName;
|
||||
}
|
||||
if (str(data_get($service, 'image'))->contains('glitchtip')) {
|
||||
$tempServiceName = 'glitchtip';
|
||||
}
|
||||
$serviceDefinition = data_get($allServices, $tempServiceName);
|
||||
$predefinedPort = data_get($serviceDefinition, 'port');
|
||||
if ($serviceName === 'plausible') {
|
||||
$predefinedPort = '8000';
|
||||
}
|
||||
// End of workarounds for beta users.
|
||||
$serviceVolumes = collect(data_get($service, 'volumes', []));
|
||||
$servicePorts = collect(data_get($service, 'ports', []));
|
||||
$serviceNetworks = collect(data_get($service, 'networks', []));
|
||||
@@ -802,7 +818,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
$isDirectory = (bool) data_get($volume, 'isDirectory', false) || (bool) data_get($volume, 'is_directory', false);
|
||||
}
|
||||
}
|
||||
if ($type->value() === 'bind') {
|
||||
if ($type?->value() === 'bind') {
|
||||
if ($source->value() === "/var/run/docker.sock") {
|
||||
return $volume;
|
||||
}
|
||||
@@ -852,7 +868,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
]
|
||||
);
|
||||
}
|
||||
$savedService->getFilesFromServer(isInit: true);
|
||||
dispatch(new ServerFilesFromServerJob($savedService));
|
||||
return $volume;
|
||||
});
|
||||
data_set($service, 'volumes', $serviceVolumes->toArray());
|
||||
@@ -898,17 +914,24 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
// SERVICE_FQDN_UMAMI_1000
|
||||
$port = $key->afterLast('_');
|
||||
} else {
|
||||
// SERVICE_FQDN_UMAMI
|
||||
$port = null;
|
||||
$last = $key->afterLast('_');
|
||||
if (is_numeric($last->value())) {
|
||||
// SERVICE_FQDN_3001
|
||||
$port = $last;
|
||||
} else {
|
||||
// SERVICE_FQDN_UMAMI
|
||||
$port = null;
|
||||
}
|
||||
}
|
||||
if ($port) {
|
||||
$fqdn = "$fqdn:$port";
|
||||
}
|
||||
if (substr_count($key->value(), '_') >= 2) {
|
||||
if (is_null($value)) {
|
||||
$value = Str::of('/');
|
||||
if ($value) {
|
||||
$path = $value->value();
|
||||
} else {
|
||||
$path = null;
|
||||
}
|
||||
$path = $value->value();
|
||||
if ($generatedServiceFQDNS->count() > 0) {
|
||||
$alreadyGenerated = $generatedServiceFQDNS->has($key->value());
|
||||
if ($alreadyGenerated) {
|
||||
@@ -939,6 +962,25 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
'is_preview' => false,
|
||||
]);
|
||||
}
|
||||
// Caddy needs exact port in some cases.
|
||||
|
||||
if ($predefinedPort && !$key->endsWith("_{$predefinedPort}")) {
|
||||
if ($resource->server->proxyType() === 'CADDY') {
|
||||
$env = EnvironmentVariable::where([
|
||||
'key' => $key,
|
||||
'service_id' => $resource->id,
|
||||
])->first();
|
||||
if ($env) {
|
||||
$env_url = Url::fromString($savedService->fqdn);
|
||||
$env_port = $env_url->getPort();
|
||||
if ($env_port !== $predefinedPort) {
|
||||
$env_url = $env_url->withPort($predefinedPort);
|
||||
$savedService->fqdn = $env_url->__toString();
|
||||
$savedService->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// data_forget($service, "environment.$variableName");
|
||||
// $yaml = data_forget($yaml, "services.$serviceName.environment.$variableName");
|
||||
// if (count(data_get($yaml, 'services.' . $serviceName . '.environment')) === 0) {
|
||||
@@ -987,6 +1029,22 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
$savedService->fqdn = $fqdn;
|
||||
$savedService->save();
|
||||
}
|
||||
// Caddy needs exact port in some cases.
|
||||
if ($predefinedPort && !$key->endsWith("_{$predefinedPort}") && $command?->value() === 'FQDN' && $resource->server->proxyType() === 'CADDY') {
|
||||
$env = EnvironmentVariable::where([
|
||||
'key' => $key,
|
||||
'service_id' => $resource->id,
|
||||
])->first();
|
||||
if ($env) {
|
||||
$env_url = Url::fromString($env->value);
|
||||
$env_port = $env_url->getPort();
|
||||
if ($env_port !== $predefinedPort) {
|
||||
$env_url = $env_url->withPort($predefinedPort);
|
||||
$savedService->fqdn = $env_url->__toString();
|
||||
$savedService->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$generatedValue = generateEnvValue($command, $resource);
|
||||
@@ -1056,6 +1114,16 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
is_stripprefix_enabled: $savedService->isStripprefixEnabled(),
|
||||
service_name: $serviceName
|
||||
));
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy(
|
||||
network: $resource->destination->network,
|
||||
uuid: $resource->uuid,
|
||||
domains: $fqdns,
|
||||
is_force_https_enabled: true,
|
||||
serviceLabels: $serviceLabels,
|
||||
is_gzip_enabled: $savedService->isGzipEnabled(),
|
||||
is_stripprefix_enabled: $savedService->isStripprefixEnabled(),
|
||||
service_name: $serviceName
|
||||
));
|
||||
}
|
||||
}
|
||||
if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) {
|
||||
@@ -1354,10 +1422,11 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
$fqdn = "$fqdn:$port";
|
||||
}
|
||||
if (substr_count($key->value(), '_') >= 2) {
|
||||
if (is_null($value)) {
|
||||
$value = Str::of('/');
|
||||
if ($value) {
|
||||
$path = $value->value();
|
||||
} else {
|
||||
$path = null;
|
||||
}
|
||||
$path = $value->value();
|
||||
if ($generatedServiceFQDNS->count() > 0) {
|
||||
$alreadyGenerated = $generatedServiceFQDNS->has($key->value());
|
||||
if ($alreadyGenerated) {
|
||||
@@ -1495,7 +1564,17 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
return $preview_fqdn;
|
||||
});
|
||||
}
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($uuid, $fqdns, serviceLabels: $serviceLabels));
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik(
|
||||
uuid: $uuid,
|
||||
domains: $fqdns,
|
||||
serviceLabels: $serviceLabels
|
||||
));
|
||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy(
|
||||
network: $resource->destination->network,
|
||||
uuid: $uuid,
|
||||
domains: $fqdns,
|
||||
serviceLabels: $serviceLabels
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ function allowedPathsForBoardingAccounts()
|
||||
{
|
||||
return [
|
||||
...allowedPathsForUnsubscribedAccounts(),
|
||||
'boarding',
|
||||
'onboarding',
|
||||
'livewire/update'
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user