@@ -99,12 +99,8 @@ class StartClickhouse
|
|||||||
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
||||||
|
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
|
@@ -52,9 +52,8 @@ class StartDatabaseProxy
|
|||||||
}
|
}
|
||||||
|
|
||||||
$configuration_dir = database_proxy_dir($database->uuid);
|
$configuration_dir = database_proxy_dir($database->uuid);
|
||||||
$volume_configuration_dir = $configuration_dir;
|
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
$volume_configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy';
|
$configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy';
|
||||||
}
|
}
|
||||||
$nginxconf = <<<EOF
|
$nginxconf = <<<EOF
|
||||||
user nginx;
|
user nginx;
|
||||||
@@ -87,7 +86,7 @@ class StartDatabaseProxy
|
|||||||
'volumes' => [
|
'volumes' => [
|
||||||
[
|
[
|
||||||
'type' => 'bind',
|
'type' => 'bind',
|
||||||
'source' => "$volume_configuration_dir/nginx.conf",
|
'source' => "$configuration_dir/nginx.conf",
|
||||||
'target' => '/etc/nginx/nginx.conf',
|
'target' => '/etc/nginx/nginx.conf',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
@@ -116,18 +115,8 @@ class StartDatabaseProxy
|
|||||||
instant_remote_process(["docker rm -f $proxyContainerName"], $server, false);
|
instant_remote_process(["docker rm -f $proxyContainerName"], $server, false);
|
||||||
instant_remote_process([
|
instant_remote_process([
|
||||||
"mkdir -p $configuration_dir",
|
"mkdir -p $configuration_dir",
|
||||||
[
|
"echo '{$nginxconf_base64}' | base64 -d | tee $configuration_dir/nginx.conf > /dev/null",
|
||||||
'transfer_file' => [
|
"echo '{$dockercompose_base64}' | base64 -d | tee $configuration_dir/docker-compose.yaml > /dev/null",
|
||||||
'content' => base64_decode($nginxconf_base64),
|
|
||||||
'destination' => "$configuration_dir/nginx.conf",
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'transfer_file' => [
|
|
||||||
'content' => base64_decode($dockercompose_base64),
|
|
||||||
'destination' => "$configuration_dir/docker-compose.yaml",
|
|
||||||
],
|
|
||||||
],
|
|
||||||
"docker compose --project-directory {$configuration_dir} pull",
|
"docker compose --project-directory {$configuration_dir} pull",
|
||||||
"docker compose --project-directory {$configuration_dir} up -d",
|
"docker compose --project-directory {$configuration_dir} up -d",
|
||||||
], $server);
|
], $server);
|
||||||
|
@@ -183,12 +183,8 @@ class StartDragonfly
|
|||||||
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
||||||
|
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
|
@@ -199,12 +199,8 @@ class StartKeydb
|
|||||||
$docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options);
|
$docker_run_options = convertDockerRunToCompose($this->database->custom_docker_run_options);
|
||||||
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
|
@@ -203,12 +203,8 @@ class StartMariadb
|
|||||||
}
|
}
|
||||||
|
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
@@ -288,11 +284,7 @@ class StartMariadb
|
|||||||
}
|
}
|
||||||
$filename = 'custom-config.cnf';
|
$filename = 'custom-config.cnf';
|
||||||
$content = $this->database->mariadb_conf;
|
$content = $this->database->mariadb_conf;
|
||||||
$this->commands[] = [
|
$content_base64 = base64_encode($content);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null";
|
||||||
'content' => $content,
|
|
||||||
'destination' => "$this->configuration_dir/{$filename}",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,9 @@ class StartMongodb
|
|||||||
|
|
||||||
$container_name = $this->database->uuid;
|
$container_name = $this->database->uuid;
|
||||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||||
|
if (isDev()) {
|
||||||
|
$this->configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$container_name;
|
||||||
|
}
|
||||||
|
|
||||||
$this->commands = [
|
$this->commands = [
|
||||||
"echo 'Starting database.'",
|
"echo 'Starting database.'",
|
||||||
@@ -251,12 +254,8 @@ class StartMongodb
|
|||||||
}
|
}
|
||||||
|
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
@@ -333,22 +332,15 @@ class StartMongodb
|
|||||||
}
|
}
|
||||||
$filename = 'mongod.conf';
|
$filename = 'mongod.conf';
|
||||||
$content = $this->database->mongo_conf;
|
$content = $this->database->mongo_conf;
|
||||||
$this->commands[] = [
|
$content_base64 = base64_encode($content);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null";
|
||||||
'content' => $content,
|
|
||||||
'destination' => "$this->configuration_dir/{$filename}",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function add_default_database()
|
private function add_default_database()
|
||||||
{
|
{
|
||||||
$content = "db = db.getSiblingDB(\"{$this->database->mongo_initdb_database}\");db.createCollection('init_collection');db.createUser({user: \"{$this->database->mongo_initdb_root_username}\", pwd: \"{$this->database->mongo_initdb_root_password}\",roles: [{role:\"readWrite\",db:\"{$this->database->mongo_initdb_database}\"}]});";
|
$content = "db = db.getSiblingDB(\"{$this->database->mongo_initdb_database}\");db.createCollection('init_collection');db.createUser({user: \"{$this->database->mongo_initdb_root_username}\", pwd: \"{$this->database->mongo_initdb_root_password}\",roles: [{role:\"readWrite\",db:\"{$this->database->mongo_initdb_database}\"}]});";
|
||||||
$this->commands[] = [
|
$content_base64 = base64_encode($content);
|
||||||
'transfer_file' => [
|
$this->commands[] = "mkdir -p $this->configuration_dir/docker-entrypoint-initdb.d";
|
||||||
'content' => $content,
|
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/docker-entrypoint-initdb.d/01-default-database.js > /dev/null";
|
||||||
'destination' => "$this->configuration_dir/docker-entrypoint-initdb.d/01-default-database.js",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -204,12 +204,8 @@ class StartMysql
|
|||||||
}
|
}
|
||||||
|
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
@@ -291,11 +287,7 @@ class StartMysql
|
|||||||
}
|
}
|
||||||
$filename = 'custom-config.cnf';
|
$filename = 'custom-config.cnf';
|
||||||
$content = $this->database->mysql_conf;
|
$content = $this->database->mysql_conf;
|
||||||
$this->commands[] = [
|
$content_base64 = base64_encode($content);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/{$filename} > /dev/null";
|
||||||
'content' => $content,
|
|
||||||
'destination' => "$this->configuration_dir/{$filename}",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,9 @@ class StartPostgresql
|
|||||||
$this->database = $database;
|
$this->database = $database;
|
||||||
$container_name = $this->database->uuid;
|
$container_name = $this->database->uuid;
|
||||||
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
$this->configuration_dir = database_configuration_dir().'/'.$container_name;
|
||||||
|
if (isDev()) {
|
||||||
|
$this->configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$container_name;
|
||||||
|
}
|
||||||
|
|
||||||
$this->commands = [
|
$this->commands = [
|
||||||
"echo 'Starting database.'",
|
"echo 'Starting database.'",
|
||||||
@@ -214,12 +217,8 @@ class StartPostgresql
|
|||||||
}
|
}
|
||||||
|
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
@@ -305,12 +304,8 @@ class StartPostgresql
|
|||||||
foreach ($this->database->init_scripts as $init_script) {
|
foreach ($this->database->init_scripts as $init_script) {
|
||||||
$filename = data_get($init_script, 'filename');
|
$filename = data_get($init_script, 'filename');
|
||||||
$content = data_get($init_script, 'content');
|
$content = data_get($init_script, 'content');
|
||||||
$this->commands[] = [
|
$content_base64 = base64_encode($content);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $this->configuration_dir/docker-entrypoint-initdb.d/{$filename} > /dev/null";
|
||||||
'content' => $content,
|
|
||||||
'destination' => "$this->configuration_dir/docker-entrypoint-initdb.d/{$filename}",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$this->init_scripts[] = "$this->configuration_dir/docker-entrypoint-initdb.d/{$filename}";
|
$this->init_scripts[] = "$this->configuration_dir/docker-entrypoint-initdb.d/{$filename}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,11 +327,7 @@ class StartPostgresql
|
|||||||
$this->database->postgres_conf = $content;
|
$this->database->postgres_conf = $content;
|
||||||
$this->database->save();
|
$this->database->save();
|
||||||
}
|
}
|
||||||
$this->commands[] = [
|
$content_base64 = base64_encode($content);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$content_base64}' | base64 -d | tee $config_file_path > /dev/null";
|
||||||
'content' => $content,
|
|
||||||
'destination' => $config_file_path,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -196,12 +196,8 @@ class StartRedis
|
|||||||
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
$docker_compose = generateCustomDockerRunOptionsForDatabases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network);
|
||||||
|
|
||||||
$docker_compose = Yaml::dump($docker_compose, 10);
|
$docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->commands[] = [
|
$docker_compose_base64 = base64_encode($docker_compose);
|
||||||
'transfer_file' => [
|
$this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null";
|
||||||
'content' => $docker_compose,
|
|
||||||
'destination' => "$this->configuration_dir/docker-compose.yml",
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$readme = generate_readme_file($this->database->name, now());
|
$readme = generate_readme_file($this->database->name, now());
|
||||||
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
$this->commands[] = "echo '{$readme}' > $this->configuration_dir/README.md";
|
||||||
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
$this->commands[] = "echo 'Pulling {$database->image} image.'";
|
||||||
|
@@ -21,12 +21,7 @@ class SaveProxyConfiguration
|
|||||||
// Transfer the configuration file to the server
|
// Transfer the configuration file to the server
|
||||||
instant_remote_process([
|
instant_remote_process([
|
||||||
"mkdir -p $proxy_path",
|
"mkdir -p $proxy_path",
|
||||||
[
|
"echo '$docker_compose_yml_base64' | base64 -d | tee $proxy_path/docker-compose.yml > /dev/null",
|
||||||
'transfer_file' => [
|
|
||||||
'content' => base64_decode($docker_compose_yml_base64),
|
|
||||||
'destination' => "$proxy_path/docker-compose.yml",
|
|
||||||
],
|
|
||||||
],
|
|
||||||
], $server);
|
], $server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -40,12 +40,7 @@ class ConfigureCloudflared
|
|||||||
$commands = collect([
|
$commands = collect([
|
||||||
'mkdir -p /tmp/cloudflared',
|
'mkdir -p /tmp/cloudflared',
|
||||||
'cd /tmp/cloudflared',
|
'cd /tmp/cloudflared',
|
||||||
[
|
"echo '$docker_compose_yml_base64' | base64 -d | tee docker-compose.yml > /dev/null",
|
||||||
'transfer_file' => [
|
|
||||||
'content' => base64_decode($docker_compose_yml_base64),
|
|
||||||
'destination' => '/tmp/cloudflared/docker-compose.yml',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'echo Pulling latest Cloudflare Tunnel image.',
|
'echo Pulling latest Cloudflare Tunnel image.',
|
||||||
'docker compose pull',
|
'docker compose pull',
|
||||||
'echo Stopping existing Cloudflare Tunnel container.',
|
'echo Stopping existing Cloudflare Tunnel container.',
|
||||||
|
@@ -14,7 +14,6 @@ class InstallDocker
|
|||||||
|
|
||||||
public function handle(Server $server)
|
public function handle(Server $server)
|
||||||
{
|
{
|
||||||
ray('install docker');
|
|
||||||
$dockerVersion = config('constants.docker.minimum_required_version');
|
$dockerVersion = config('constants.docker.minimum_required_version');
|
||||||
$supported_os_type = $server->validateOS();
|
$supported_os_type = $server->validateOS();
|
||||||
if (! $supported_os_type) {
|
if (! $supported_os_type) {
|
||||||
@@ -104,15 +103,8 @@ class InstallDocker
|
|||||||
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$dockerVersion}",
|
"curl https://releases.rancher.com/install-docker/{$dockerVersion}.sh | sh || curl https://get.docker.com | sh -s -- --version {$dockerVersion}",
|
||||||
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
|
"echo 'Configuring Docker Engine (merging existing configuration with the required)...'",
|
||||||
'test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json "/etc/docker/daemon.json.original-$(date +"%Y%m%d-%H%M%S")"',
|
'test -s /etc/docker/daemon.json && cp /etc/docker/daemon.json "/etc/docker/daemon.json.original-$(date +"%Y%m%d-%H%M%S")"',
|
||||||
[
|
"test ! -s /etc/docker/daemon.json && echo '{$config}' | base64 -d | tee /etc/docker/daemon.json > /dev/null",
|
||||||
'transfer_file' => [
|
"echo '{$config}' | base64 -d | tee /etc/docker/daemon.json.coolify > /dev/null",
|
||||||
'content' => base64_decode($config),
|
|
||||||
'destination' => '/tmp/daemon.json.new',
|
|
||||||
],
|
|
||||||
],
|
|
||||||
'test ! -s /etc/docker/daemon.json && cp /tmp/daemon.json.new /etc/docker/daemon.json',
|
|
||||||
'cp /tmp/daemon.json.new /etc/docker/daemon.json.coolify',
|
|
||||||
'rm -f /tmp/daemon.json.new',
|
|
||||||
'jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null',
|
'jq . /etc/docker/daemon.json.coolify | tee /etc/docker/daemon.json.coolify.pretty > /dev/null',
|
||||||
'mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify',
|
'mv /etc/docker/daemon.json.coolify.pretty /etc/docker/daemon.json.coolify',
|
||||||
"jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null",
|
"jq -s '.[0] * .[1]' /etc/docker/daemon.json.coolify /etc/docker/daemon.json | tee /etc/docker/daemon.json.appended > /dev/null",
|
||||||
|
@@ -180,30 +180,10 @@ Files:
|
|||||||
$command = [
|
$command = [
|
||||||
"echo 'Saving configuration'",
|
"echo 'Saving configuration'",
|
||||||
"mkdir -p $config_path",
|
"mkdir -p $config_path",
|
||||||
[
|
"echo '{$parsers}' | base64 -d | tee $parsers_config > /dev/null",
|
||||||
'transfer_file' => [
|
"echo '{$config}' | base64 -d | tee $fluent_bit_config > /dev/null",
|
||||||
'content' => base64_decode($parsers),
|
"echo '{$compose}' | base64 -d | tee $compose_path > /dev/null",
|
||||||
'destination' => $parsers_config,
|
"echo '{$readme}' | base64 -d | tee $readme_path > /dev/null",
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'transfer_file' => [
|
|
||||||
'content' => base64_decode($config),
|
|
||||||
'destination' => $fluent_bit_config,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'transfer_file' => [
|
|
||||||
'content' => base64_decode($compose),
|
|
||||||
'destination' => $compose_path,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'transfer_file' => [
|
|
||||||
'content' => base64_decode($readme),
|
|
||||||
'destination' => $readme_path,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
"test -f $config_path/.env && rm $config_path/.env",
|
"test -f $config_path/.env && rm $config_path/.env",
|
||||||
];
|
];
|
||||||
if ($type === 'newrelic') {
|
if ($type === 'newrelic') {
|
||||||
|
@@ -388,8 +388,11 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
$dockerfile_base64 = base64_encode($this->application->dockerfile);
|
$dockerfile_base64 = base64_encode($this->application->dockerfile);
|
||||||
$this->application_deployment_queue->addLogEntry("Starting deployment of {$this->application->name} to {$this->server->name}.");
|
$this->application_deployment_queue->addLogEntry("Starting deployment of {$this->application->name} to {$this->server->name}.");
|
||||||
$this->prepare_builder_image();
|
$this->prepare_builder_image();
|
||||||
$dockerfile_content = base64_decode($dockerfile_base64);
|
$this->execute_remote_command(
|
||||||
transfer_file_to_container($dockerfile_content, "{$this->workdir}{$this->dockerfile_location}", $this->deployment_uuid, $this->server);
|
[
|
||||||
|
executeInDocker($this->deployment_uuid, "echo '$dockerfile_base64' | base64 -d | tee {$this->workdir}{$this->dockerfile_location} > /dev/null"),
|
||||||
|
],
|
||||||
|
);
|
||||||
$this->generate_image_names();
|
$this->generate_image_names();
|
||||||
$this->generate_compose_file();
|
$this->generate_compose_file();
|
||||||
$this->generate_build_env_variables();
|
$this->generate_build_env_variables();
|
||||||
@@ -479,7 +482,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
if (filled($this->env_filename)) {
|
if (filled($this->env_filename)) {
|
||||||
$services = collect(data_get($composeFile, 'services', []));
|
$services = collect(data_get($composeFile, 'services', []));
|
||||||
$services = $services->map(function ($service, $name) {
|
$services = $services->map(function ($service, $name) {
|
||||||
$service['env_file'] = ["/artifacts/{$this->env_filename}"];
|
$service['env_file'] = [$this->env_filename];
|
||||||
|
|
||||||
return $service;
|
return $service;
|
||||||
});
|
});
|
||||||
@@ -494,7 +497,10 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
$yaml = Yaml::dump(convertToArray($composeFile), 10);
|
$yaml = Yaml::dump(convertToArray($composeFile), 10);
|
||||||
}
|
}
|
||||||
$this->docker_compose_base64 = base64_encode($yaml);
|
$this->docker_compose_base64 = base64_encode($yaml);
|
||||||
transfer_file_to_container($yaml, "{$this->workdir}{$this->docker_compose_location}", $this->deployment_uuid, $this->server);
|
$this->execute_remote_command([
|
||||||
|
executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d | tee {$this->workdir}{$this->docker_compose_location} > /dev/null"),
|
||||||
|
'hidden' => true,
|
||||||
|
]);
|
||||||
// Build new container to limit downtime.
|
// Build new container to limit downtime.
|
||||||
$this->application_deployment_queue->addLogEntry('Pulling & building required images.');
|
$this->application_deployment_queue->addLogEntry('Pulling & building required images.');
|
||||||
|
|
||||||
@@ -505,7 +511,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
} else {
|
} else {
|
||||||
$command = "{$this->coolify_variables} docker compose";
|
$command = "{$this->coolify_variables} docker compose";
|
||||||
if (filled($this->env_filename)) {
|
if (filled($this->env_filename)) {
|
||||||
$command .= " --env-file /artifacts/{$this->env_filename}";
|
$command .= " --env-file {$this->workdir}/{$this->env_filename}";
|
||||||
}
|
}
|
||||||
if ($this->force_rebuild) {
|
if ($this->force_rebuild) {
|
||||||
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull --no-cache";
|
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull --no-cache";
|
||||||
@@ -551,7 +557,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
|
|
||||||
$command = "{$this->coolify_variables} docker compose";
|
$command = "{$this->coolify_variables} docker compose";
|
||||||
if (filled($this->env_filename)) {
|
if (filled($this->env_filename)) {
|
||||||
$command .= " --env-file /artifacts/{$this->env_filename}";
|
$command .= " --env-file {$server_workdir}/{$this->env_filename}";
|
||||||
}
|
}
|
||||||
$command .= " --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d";
|
$command .= " --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d";
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
@@ -568,7 +574,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
$command = "{$this->coolify_variables} docker compose";
|
$command = "{$this->coolify_variables} docker compose";
|
||||||
if ($this->preserveRepository) {
|
if ($this->preserveRepository) {
|
||||||
if (filled($this->env_filename)) {
|
if (filled($this->env_filename)) {
|
||||||
$command .= " --env-file /artifacts/{$this->env_filename}";
|
$command .= " --env-file {$server_workdir}/{$this->env_filename}";
|
||||||
}
|
}
|
||||||
$command .= " --project-name {$this->application->uuid} --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d";
|
$command .= " --project-name {$this->application->uuid} --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d";
|
||||||
$this->write_deployment_configurations();
|
$this->write_deployment_configurations();
|
||||||
@@ -578,7 +584,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (filled($this->env_filename)) {
|
if (filled($this->env_filename)) {
|
||||||
$command .= " --env-file /artifacts/{$this->env_filename}";
|
$command .= " --env-file {$this->workdir}/{$this->env_filename}";
|
||||||
}
|
}
|
||||||
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d";
|
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d";
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
@@ -709,12 +715,13 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
$composeFileName = "$mainDir/".addPreviewDeploymentSuffix('docker-compose', $this->pull_request_id).'.yaml';
|
$composeFileName = "$mainDir/".addPreviewDeploymentSuffix('docker-compose', $this->pull_request_id).'.yaml';
|
||||||
$this->docker_compose_location = '/'.addPreviewDeploymentSuffix('docker-compose', $this->pull_request_id).'.yaml';
|
$this->docker_compose_location = '/'.addPreviewDeploymentSuffix('docker-compose', $this->pull_request_id).'.yaml';
|
||||||
}
|
}
|
||||||
$this->execute_remote_command([
|
|
||||||
"mkdir -p $mainDir",
|
|
||||||
]);
|
|
||||||
$docker_compose_content = base64_decode($this->docker_compose_base64);
|
|
||||||
transfer_file_to_server($docker_compose_content, $composeFileName, $this->server);
|
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"mkdir -p $mainDir",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"echo '{$this->docker_compose_base64}' | base64 -d | tee $composeFileName > /dev/null",
|
||||||
|
],
|
||||||
[
|
[
|
||||||
"echo '{$readme}' > $mainDir/README.md",
|
"echo '{$readme}' > $mainDir/README.md",
|
||||||
]
|
]
|
||||||
@@ -911,24 +918,8 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
});
|
});
|
||||||
if ($this->pull_request_id === 0) {
|
if ($this->pull_request_id === 0) {
|
||||||
$this->env_filename = '.env';
|
$this->env_filename = '.env';
|
||||||
// Filter out buildtime-only variables from runtime environment
|
|
||||||
$runtime_environment_variables = $sorted_environment_variables->filter(function ($env) {
|
|
||||||
return ! $env->is_buildtime_only;
|
|
||||||
});
|
|
||||||
foreach ($runtime_environment_variables as $env) {
|
|
||||||
$envs->push($env->key.'='.$env->real_value);
|
|
||||||
}
|
|
||||||
// Add PORT if not exists, use the first port as default
|
|
||||||
if ($this->build_pack !== 'dockercompose') {
|
|
||||||
if ($this->application->environment_variables->where('key', 'PORT')->isEmpty()) {
|
|
||||||
$envs->push("PORT={$ports[0]}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Add HOST if not exists
|
|
||||||
if ($this->application->environment_variables->where('key', 'HOST')->isEmpty()) {
|
|
||||||
$envs->push('HOST=0.0.0.0');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Generate SERVICE_ variables first for dockercompose
|
||||||
if ($this->build_pack === 'dockercompose') {
|
if ($this->build_pack === 'dockercompose') {
|
||||||
$domains = collect(json_decode($this->application->docker_compose_domains)) ?? collect([]);
|
$domains = collect(json_decode($this->application->docker_compose_domains)) ?? collect([]);
|
||||||
|
|
||||||
@@ -957,26 +948,38 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
$envs->push('SERVICE_NAME_'.str($serviceName)->upper().'='.$serviceName);
|
$envs->push('SERVICE_NAME_'.str($serviceName)->upper().'='.$serviceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$this->env_filename = '.env';
|
// Filter out buildtime-only variables from runtime environment
|
||||||
// Filter out buildtime-only variables from runtime environment for preview
|
$runtime_environment_variables = $sorted_environment_variables->filter(function ($env) {
|
||||||
$runtime_environment_variables_preview = $sorted_environment_variables_preview->filter(function ($env) {
|
|
||||||
return ! $env->is_buildtime_only;
|
return ! $env->is_buildtime_only;
|
||||||
});
|
});
|
||||||
foreach ($runtime_environment_variables_preview as $env) {
|
|
||||||
|
// Sort runtime environment variables: those referencing SERVICE_ variables come after others
|
||||||
|
$runtime_environment_variables = $runtime_environment_variables->sortBy(function ($env) {
|
||||||
|
if (str($env->value)->startsWith('$SERVICE_') || str($env->value)->contains('${SERVICE_')) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($runtime_environment_variables as $env) {
|
||||||
$envs->push($env->key.'='.$env->real_value);
|
$envs->push($env->key.'='.$env->real_value);
|
||||||
}
|
}
|
||||||
// Add PORT if not exists, use the first port as default
|
// Add PORT if not exists, use the first port as default
|
||||||
if ($this->build_pack !== 'dockercompose') {
|
if ($this->build_pack !== 'dockercompose') {
|
||||||
if ($this->application->environment_variables_preview->where('key', 'PORT')->isEmpty()) {
|
if ($this->application->environment_variables->where('key', 'PORT')->isEmpty()) {
|
||||||
$envs->push("PORT={$ports[0]}");
|
$envs->push("PORT={$ports[0]}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add HOST if not exists
|
// Add HOST if not exists
|
||||||
if ($this->application->environment_variables_preview->where('key', 'HOST')->isEmpty()) {
|
if ($this->application->environment_variables->where('key', 'HOST')->isEmpty()) {
|
||||||
$envs->push('HOST=0.0.0.0');
|
$envs->push('HOST=0.0.0.0');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$this->env_filename = '.env';
|
||||||
|
|
||||||
|
// Generate SERVICE_ variables first for dockercompose preview
|
||||||
if ($this->build_pack === 'dockercompose') {
|
if ($this->build_pack === 'dockercompose') {
|
||||||
$domains = collect(json_decode(data_get($this->preview, 'docker_compose_domains'))) ?? collect([]);
|
$domains = collect(json_decode(data_get($this->preview, 'docker_compose_domains'))) ?? collect([]);
|
||||||
|
|
||||||
@@ -1001,6 +1004,34 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
$envs->push('SERVICE_NAME_'.str($rawServiceName)->upper().'='.addPreviewDeploymentSuffix($rawServiceName, $this->pull_request_id));
|
$envs->push('SERVICE_NAME_'.str($rawServiceName)->upper().'='.addPreviewDeploymentSuffix($rawServiceName, $this->pull_request_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter out buildtime-only variables from runtime environment for preview
|
||||||
|
$runtime_environment_variables_preview = $sorted_environment_variables_preview->filter(function ($env) {
|
||||||
|
return ! $env->is_buildtime_only;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort runtime environment variables: those referencing SERVICE_ variables come after others
|
||||||
|
$runtime_environment_variables_preview = $runtime_environment_variables_preview->sortBy(function ($env) {
|
||||||
|
if (str($env->value)->startsWith('$SERVICE_') || str($env->value)->contains('${SERVICE_')) {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach ($runtime_environment_variables_preview as $env) {
|
||||||
|
$envs->push($env->key.'='.$env->real_value);
|
||||||
|
}
|
||||||
|
// Add PORT if not exists, use the first port as default
|
||||||
|
if ($this->build_pack !== 'dockercompose') {
|
||||||
|
if ($this->application->environment_variables_preview->where('key', 'PORT')->isEmpty()) {
|
||||||
|
$envs->push("PORT={$ports[0]}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add HOST if not exists
|
||||||
|
if ($this->application->environment_variables_preview->where('key', 'HOST')->isEmpty()) {
|
||||||
|
$envs->push('HOST=0.0.0.0');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($envs->isEmpty()) {
|
if ($envs->isEmpty()) {
|
||||||
if ($this->env_filename) {
|
if ($this->env_filename) {
|
||||||
@@ -1033,17 +1064,27 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
}
|
}
|
||||||
$this->env_filename = null;
|
$this->env_filename = null;
|
||||||
} else {
|
} else {
|
||||||
$envs_content = $envs->implode("\n");
|
$envs_base64 = base64_encode($envs->implode("\n"));
|
||||||
transfer_file_to_container($envs_content, "/artifacts/{$this->env_filename}", $this->deployment_uuid, $this->server);
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee $this->workdir/{$this->env_filename} > /dev/null"),
|
||||||
|
],
|
||||||
|
|
||||||
// Save the env filename with preview deployment suffix
|
);
|
||||||
$env_filename = addPreviewDeploymentSuffix($this->env_filename, $this->pull_request_id);
|
|
||||||
if ($this->use_build_server) {
|
if ($this->use_build_server) {
|
||||||
$this->server = $this->original_server;
|
$this->server = $this->original_server;
|
||||||
transfer_file_to_server($envs_content, "$this->configuration_dir/{$env_filename}", $this->server);
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"echo '$envs_base64' | base64 -d | tee $this->configuration_dir/{$this->env_filename} > /dev/null",
|
||||||
|
]
|
||||||
|
);
|
||||||
$this->server = $this->build_server;
|
$this->server = $this->build_server;
|
||||||
} else {
|
} else {
|
||||||
transfer_file_to_server($envs_content, "$this->configuration_dir/{$env_filename}", $this->server);
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
"echo '$envs_base64' | base64 -d | tee $this->configuration_dir/{$this->env_filename} > /dev/null",
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->environment_variables = $envs;
|
$this->environment_variables = $envs;
|
||||||
@@ -1436,11 +1477,14 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
}
|
}
|
||||||
$private_key = data_get($this->application, 'private_key.private_key');
|
$private_key = data_get($this->application, 'private_key.private_key');
|
||||||
if ($private_key) {
|
if ($private_key) {
|
||||||
$this->execute_remote_command([
|
$private_key = base64_encode($private_key);
|
||||||
executeInDocker($this->deployment_uuid, 'mkdir -p /root/.ssh'),
|
|
||||||
]);
|
|
||||||
transfer_file_to_container($private_key, '/root/.ssh/id_rsa', $this->deployment_uuid, $this->server);
|
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
|
[
|
||||||
|
executeInDocker($this->deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||||
|
],
|
||||||
|
[
|
||||||
|
executeInDocker($this->deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"),
|
||||||
|
],
|
||||||
[
|
[
|
||||||
executeInDocker($this->deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'),
|
executeInDocker($this->deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'),
|
||||||
],
|
],
|
||||||
@@ -1845,7 +1889,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
if (filled($this->env_filename)) {
|
if (filled($this->env_filename)) {
|
||||||
$docker_compose['services'][$this->container_name]['env_file'] = ["/artifacts/{$this->env_filename}"];
|
$docker_compose['services'][$this->container_name]['env_file'] = [$this->env_filename];
|
||||||
}
|
}
|
||||||
$docker_compose['services'][$this->container_name]['healthcheck'] = [
|
$docker_compose['services'][$this->container_name]['healthcheck'] = [
|
||||||
'test' => [
|
'test' => [
|
||||||
@@ -2002,7 +2046,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
|||||||
|
|
||||||
$this->docker_compose = Yaml::dump($docker_compose, 10);
|
$this->docker_compose = Yaml::dump($docker_compose, 10);
|
||||||
$this->docker_compose_base64 = base64_encode($this->docker_compose);
|
$this->docker_compose_base64 = base64_encode($this->docker_compose);
|
||||||
transfer_file_to_container(base64_decode($this->docker_compose_base64), "{$this->workdir}/docker-compose.yaml", $this->deployment_uuid, $this->server);
|
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->docker_compose_base64}' | base64 -d | tee {$this->workdir}/docker-compose.yaml > /dev/null"), 'hidden' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generate_local_persistent_volumes()
|
private function generate_local_persistent_volumes()
|
||||||
@@ -2130,8 +2174,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
} else {
|
} else {
|
||||||
if ($this->application->build_pack === 'nixpacks') {
|
if ($this->application->build_pack === 'nixpacks') {
|
||||||
$this->nixpacks_plan = base64_encode($this->nixpacks_plan);
|
$this->nixpacks_plan = base64_encode($this->nixpacks_plan);
|
||||||
$nixpacks_content = base64_decode($this->nixpacks_plan);
|
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d | tee /artifacts/thegameplan.json > /dev/null"), 'hidden' => true]);
|
||||||
transfer_file_to_container($nixpacks_content, '/artifacts/thegameplan.json', $this->deployment_uuid, $this->server);
|
|
||||||
if ($this->force_rebuild) {
|
if ($this->force_rebuild) {
|
||||||
$this->execute_remote_command([
|
$this->execute_remote_command([
|
||||||
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->build_image_name} {$this->workdir} -o {$this->workdir}"),
|
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->build_image_name} {$this->workdir} -o {$this->workdir}"),
|
||||||
@@ -2155,7 +2198,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
$base64_build_command = base64_encode($build_command);
|
$base64_build_command = base64_encode($build_command);
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($base64_build_command), '/artifacts/build.sh', $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"),
|
||||||
'hidden' => true,
|
'hidden' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -2178,7 +2221,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
}
|
}
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($base64_build_command), '/artifacts/build.sh', $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"),
|
||||||
'hidden' => true,
|
'hidden' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -2210,13 +2253,13 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
$base64_build_command = base64_encode($build_command);
|
$base64_build_command = base64_encode($build_command);
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($dockerfile), "{$this->workdir}/Dockerfile", $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$dockerfile}' | base64 -d | tee {$this->workdir}/Dockerfile > /dev/null"),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($nginx_config), "{$this->workdir}/nginx.conf", $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d | tee {$this->workdir}/nginx.conf > /dev/null"),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($base64_build_command), '/artifacts/build.sh', $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"),
|
||||||
'hidden' => true,
|
'hidden' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -2239,7 +2282,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
$base64_build_command = base64_encode($build_command);
|
$base64_build_command = base64_encode($build_command);
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($base64_build_command), '/artifacts/build.sh', $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"),
|
||||||
'hidden' => true,
|
'hidden' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -2254,8 +2297,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
} else {
|
} else {
|
||||||
if ($this->application->build_pack === 'nixpacks') {
|
if ($this->application->build_pack === 'nixpacks') {
|
||||||
$this->nixpacks_plan = base64_encode($this->nixpacks_plan);
|
$this->nixpacks_plan = base64_encode($this->nixpacks_plan);
|
||||||
$nixpacks_content = base64_decode($this->nixpacks_plan);
|
$this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d | tee /artifacts/thegameplan.json > /dev/null"), 'hidden' => true]);
|
||||||
transfer_file_to_container($nixpacks_content, '/artifacts/thegameplan.json', $this->deployment_uuid, $this->server);
|
|
||||||
if ($this->force_rebuild) {
|
if ($this->force_rebuild) {
|
||||||
$this->execute_remote_command([
|
$this->execute_remote_command([
|
||||||
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->production_image_name} {$this->workdir} -o {$this->workdir}"),
|
executeInDocker($this->deployment_uuid, "nixpacks build -c /artifacts/thegameplan.json --no-cache --no-error-without-start -n {$this->production_image_name} {$this->workdir} -o {$this->workdir}"),
|
||||||
@@ -2278,7 +2320,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
$base64_build_command = base64_encode($build_command);
|
$base64_build_command = base64_encode($build_command);
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($base64_build_command), '/artifacts/build.sh', $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"),
|
||||||
'hidden' => true,
|
'hidden' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -2301,7 +2343,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
}
|
}
|
||||||
$this->execute_remote_command(
|
$this->execute_remote_command(
|
||||||
[
|
[
|
||||||
transfer_file_to_container(base64_decode($base64_build_command), '/artifacts/build.sh', $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$base64_build_command}' | base64 -d | tee /artifacts/build.sh > /dev/null"),
|
||||||
'hidden' => true,
|
'hidden' => true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -2434,7 +2476,7 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
|||||||
}
|
}
|
||||||
$dockerfile_base64 = base64_encode($dockerfile->implode("\n"));
|
$dockerfile_base64 = base64_encode($dockerfile->implode("\n"));
|
||||||
$this->execute_remote_command([
|
$this->execute_remote_command([
|
||||||
transfer_file_to_container(base64_decode($dockerfile_base64), "{$this->workdir}{$this->dockerfile_location}", $this->deployment_uuid, $this->server),
|
executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d | tee {$this->workdir}{$this->dockerfile_location} > /dev/null"),
|
||||||
'hidden' => true,
|
'hidden' => true,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@@ -232,12 +232,8 @@ EOD;
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->importCommands[] = [
|
$restoreCommandBase64 = base64_encode($restoreCommand);
|
||||||
'transfer_file' => [
|
$this->importCommands[] = "echo \"{$restoreCommandBase64}\" | base64 -d > {$scriptPath}";
|
||||||
'content' => $restoreCommand,
|
|
||||||
'destination' => $scriptPath,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
$this->importCommands[] = "chmod +x {$scriptPath}";
|
$this->importCommands[] = "chmod +x {$scriptPath}";
|
||||||
$this->importCommands[] = "docker cp {$scriptPath} {$this->container}:{$scriptPath}";
|
$this->importCommands[] = "docker cp {$scriptPath} {$this->container}:{$scriptPath}";
|
||||||
|
|
||||||
|
@@ -78,7 +78,10 @@ class NewDynamicConfiguration extends Component
|
|||||||
$yaml = Yaml::dump($yaml, 10, 2);
|
$yaml = Yaml::dump($yaml, 10, 2);
|
||||||
$this->value = $yaml;
|
$this->value = $yaml;
|
||||||
}
|
}
|
||||||
transfer_file_to_server($this->value, $file, $this->server);
|
$base64_value = base64_encode($this->value);
|
||||||
|
instant_remote_process([
|
||||||
|
"echo '{$base64_value}' | base64 -d | tee {$file} > /dev/null",
|
||||||
|
], $this->server);
|
||||||
if ($proxy_type === 'CADDY') {
|
if ($proxy_type === 'CADDY') {
|
||||||
$this->server->reloadCaddy();
|
$this->server->reloadCaddy();
|
||||||
}
|
}
|
||||||
|
@@ -1073,20 +1073,26 @@ class Application extends BaseModel
|
|||||||
if (is_null($private_key)) {
|
if (is_null($private_key)) {
|
||||||
throw new RuntimeException('Private key not found. Please add a private key to the application and try again.');
|
throw new RuntimeException('Private key not found. Please add a private key to the application and try again.');
|
||||||
}
|
}
|
||||||
|
$private_key = base64_encode($private_key);
|
||||||
$base_comamnd = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$base_command} {$customRepository}";
|
$base_comamnd = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$base_command} {$customRepository}";
|
||||||
|
|
||||||
$commands = collect([]);
|
if ($exec_in_docker) {
|
||||||
|
$commands = collect([
|
||||||
|
executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||||
|
executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"),
|
||||||
|
executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'),
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
$commands = collect([
|
||||||
|
'mkdir -p /root/.ssh',
|
||||||
|
"echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null",
|
||||||
|
'chmod 600 /root/.ssh/id_rsa',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
if ($exec_in_docker) {
|
if ($exec_in_docker) {
|
||||||
$commands->push(executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'));
|
|
||||||
// SSH key transfer handled by ApplicationDeploymentJob, assume key is already in container
|
|
||||||
$commands->push(executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'));
|
|
||||||
$commands->push(executeInDocker($deployment_uuid, $base_comamnd));
|
$commands->push(executeInDocker($deployment_uuid, $base_comamnd));
|
||||||
} else {
|
} else {
|
||||||
$server = $this->destination->server;
|
|
||||||
$commands->push('mkdir -p /root/.ssh');
|
|
||||||
transfer_file_to_server($private_key, '/root/.ssh/id_rsa', $server);
|
|
||||||
$commands->push('chmod 600 /root/.ssh/id_rsa');
|
|
||||||
$commands->push($base_comamnd);
|
$commands->push($base_comamnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1212,6 +1218,7 @@ class Application extends BaseModel
|
|||||||
if (is_null($private_key)) {
|
if (is_null($private_key)) {
|
||||||
throw new RuntimeException('Private key not found. Please add a private key to the application and try again.');
|
throw new RuntimeException('Private key not found. Please add a private key to the application and try again.');
|
||||||
}
|
}
|
||||||
|
$private_key = base64_encode($private_key);
|
||||||
$escapedCustomRepository = escapeshellarg($customRepository);
|
$escapedCustomRepository = escapeshellarg($customRepository);
|
||||||
$git_clone_command_base = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}";
|
$git_clone_command_base = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$escapedCustomRepository} {$escapedBaseDir}";
|
||||||
if ($only_checkout) {
|
if ($only_checkout) {
|
||||||
@@ -1219,18 +1226,18 @@ class Application extends BaseModel
|
|||||||
} else {
|
} else {
|
||||||
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base);
|
$git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
$commands = collect([]);
|
|
||||||
|
|
||||||
if ($exec_in_docker) {
|
if ($exec_in_docker) {
|
||||||
$commands->push(executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'));
|
$commands = collect([
|
||||||
// SSH key transfer handled by ApplicationDeploymentJob, assume key is already in container
|
executeInDocker($deployment_uuid, 'mkdir -p /root/.ssh'),
|
||||||
$commands->push(executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'));
|
executeInDocker($deployment_uuid, "echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null"),
|
||||||
|
executeInDocker($deployment_uuid, 'chmod 600 /root/.ssh/id_rsa'),
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
$server = $this->destination->server;
|
$commands = collect([
|
||||||
$commands->push('mkdir -p /root/.ssh');
|
'mkdir -p /root/.ssh',
|
||||||
transfer_file_to_server($private_key, '/root/.ssh/id_rsa', $server);
|
"echo '{$private_key}' | base64 -d | tee /root/.ssh/id_rsa > /dev/null",
|
||||||
$commands->push('chmod 600 /root/.ssh/id_rsa');
|
'chmod 600 /root/.ssh/id_rsa',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
if ($pull_request_id !== 0) {
|
if ($pull_request_id !== 0) {
|
||||||
if ($git_type === 'gitlab') {
|
if ($git_type === 'gitlab') {
|
||||||
@@ -1563,7 +1570,19 @@ class Application extends BaseModel
|
|||||||
if (is_null($this->watch_paths)) {
|
if (is_null($this->watch_paths)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$watch_paths = collect(explode("\n", $this->watch_paths));
|
$watch_paths = collect(explode("\n", $this->watch_paths))
|
||||||
|
->map(function (string $path): string {
|
||||||
|
return trim($path);
|
||||||
|
})
|
||||||
|
->filter(function (string $path): bool {
|
||||||
|
return strlen($path) > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// If no valid patterns after filtering, don't trigger
|
||||||
|
if ($watch_paths->isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$matches = $modified_files->filter(function ($file) use ($watch_paths) {
|
$matches = $modified_files->filter(function ($file) use ($watch_paths) {
|
||||||
return $watch_paths->contains(function ($glob) use ($file) {
|
return $watch_paths->contains(function ($glob) use ($file) {
|
||||||
return fnmatch($glob, $file);
|
return fnmatch($glob, $file);
|
||||||
|
@@ -159,7 +159,8 @@ class LocalFileVolume extends BaseModel
|
|||||||
$chmod = data_get($this, 'chmod');
|
$chmod = data_get($this, 'chmod');
|
||||||
$chown = data_get($this, 'chown');
|
$chown = data_get($this, 'chown');
|
||||||
if ($content) {
|
if ($content) {
|
||||||
transfer_file_to_server($content, $path, $server);
|
$content = base64_encode($content);
|
||||||
|
$commands->push("echo '$content' | base64 -d | tee $path > /dev/null");
|
||||||
} else {
|
} else {
|
||||||
$commands->push("touch $path");
|
$commands->push("touch $path");
|
||||||
}
|
}
|
||||||
@@ -174,10 +175,8 @@ class LocalFileVolume extends BaseModel
|
|||||||
$commands->push("mkdir -p $path > /dev/null 2>&1 || true");
|
$commands->push("mkdir -p $path > /dev/null 2>&1 || true");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($commands->count() > 0) {
|
|
||||||
return instant_remote_process($commands, $server);
|
return instant_remote_process($commands, $server);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Accessor for convenient access
|
// Accessor for convenient access
|
||||||
protected function plainMountPath(): Attribute
|
protected function plainMountPath(): Attribute
|
||||||
|
@@ -309,7 +309,10 @@ class Server extends BaseModel
|
|||||||
$conf = Yaml::dump($dynamic_conf, 12, 2);
|
$conf = Yaml::dump($dynamic_conf, 12, 2);
|
||||||
}
|
}
|
||||||
$conf = $banner.$conf;
|
$conf = $banner.$conf;
|
||||||
transfer_file_to_server($conf, $default_redirect_file, $this);
|
$base64 = base64_encode($conf);
|
||||||
|
instant_remote_process([
|
||||||
|
"echo '$base64' | base64 -d | tee $default_redirect_file > /dev/null",
|
||||||
|
], $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($proxy_type === 'CADDY') {
|
if ($proxy_type === 'CADDY') {
|
||||||
@@ -443,10 +446,11 @@ class Server extends BaseModel
|
|||||||
"# Do not edit it manually (only if you know what are you doing).\n\n".
|
"# Do not edit it manually (only if you know what are you doing).\n\n".
|
||||||
$yaml;
|
$yaml;
|
||||||
|
|
||||||
|
$base64 = base64_encode($yaml);
|
||||||
instant_remote_process([
|
instant_remote_process([
|
||||||
"mkdir -p $dynamic_config_path",
|
"mkdir -p $dynamic_config_path",
|
||||||
|
"echo '$base64' | base64 -d | tee $file > /dev/null",
|
||||||
], $this);
|
], $this);
|
||||||
transfer_file_to_server($yaml, $file, $this);
|
|
||||||
}
|
}
|
||||||
} elseif ($this->proxyType() === 'CADDY') {
|
} elseif ($this->proxyType() === 'CADDY') {
|
||||||
$file = "$dynamic_config_path/coolify.caddy";
|
$file = "$dynamic_config_path/coolify.caddy";
|
||||||
@@ -469,7 +473,10 @@ $schema://$host {
|
|||||||
}
|
}
|
||||||
reverse_proxy coolify:8080
|
reverse_proxy coolify:8080
|
||||||
}";
|
}";
|
||||||
transfer_file_to_server($caddy_file, $file, $this);
|
$base64 = base64_encode($caddy_file);
|
||||||
|
instant_remote_process([
|
||||||
|
"echo '$base64' | base64 -d | tee $file > /dev/null",
|
||||||
|
], $this);
|
||||||
$this->reloadCaddy();
|
$this->reloadCaddy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1075,6 +1082,7 @@ $schema://$host {
|
|||||||
|
|
||||||
public function validateConnection(bool $justCheckingNewKey = false)
|
public function validateConnection(bool $justCheckingNewKey = false)
|
||||||
{
|
{
|
||||||
|
ray('validateConnection', $this->id);
|
||||||
$this->disableSshMux();
|
$this->disableSshMux();
|
||||||
|
|
||||||
if ($this->skipServer()) {
|
if ($this->skipServer()) {
|
||||||
@@ -1312,6 +1320,7 @@ $schema://$host {
|
|||||||
public function generateCaCertificate()
|
public function generateCaCertificate()
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
ray('Generating CA certificate for server', $this->id);
|
||||||
SslHelper::generateSslCertificate(
|
SslHelper::generateSslCertificate(
|
||||||
commonName: 'Coolify CA Certificate',
|
commonName: 'Coolify CA Certificate',
|
||||||
serverId: $this->id,
|
serverId: $this->id,
|
||||||
@@ -1319,6 +1328,7 @@ $schema://$host {
|
|||||||
validityDays: 10 * 365
|
validityDays: 10 * 365
|
||||||
);
|
);
|
||||||
$caCertificate = SslCertificate::where('server_id', $this->id)->where('is_ca_certificate', true)->first();
|
$caCertificate = SslCertificate::where('server_id', $this->id)->where('is_ca_certificate', true)->first();
|
||||||
|
ray('CA certificate generated', $caCertificate);
|
||||||
if ($caCertificate) {
|
if ($caCertificate) {
|
||||||
$certificateContent = $caCertificate->ssl_certificate;
|
$certificateContent = $caCertificate->ssl_certificate;
|
||||||
$caCertPath = config('constants.coolify.base_config_path').'/ssl/';
|
$caCertPath = config('constants.coolify.base_config_path').'/ssl/';
|
||||||
|
@@ -1280,10 +1280,8 @@ class Service extends BaseModel
|
|||||||
if ($envs->count() === 0) {
|
if ($envs->count() === 0) {
|
||||||
$commands[] = 'touch .env';
|
$commands[] = 'touch .env';
|
||||||
} else {
|
} else {
|
||||||
$envs_content = $envs->implode("\n");
|
$envs_base64 = base64_encode($envs->implode("\n"));
|
||||||
transfer_file_to_server($envs_content, $this->workdir().'/.env', $this->server);
|
$commands[] = "echo '$envs_base64' | base64 -d | tee .env > /dev/null";
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
instant_remote_process($commands, $this->server);
|
instant_remote_process($commands, $this->server);
|
||||||
|
@@ -1069,9 +1069,9 @@ function validateComposeFile(string $compose, int $server_id): string|Throwable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$compose_content = Yaml::dump($yaml_compose);
|
$base64_compose = base64_encode(Yaml::dump($yaml_compose));
|
||||||
transfer_file_to_server($compose_content, "/tmp/{$uuid}.yml", $server);
|
|
||||||
instant_remote_process([
|
instant_remote_process([
|
||||||
|
"echo {$base64_compose} | base64 -d | tee /tmp/{$uuid}.yml > /dev/null",
|
||||||
"chmod 600 /tmp/{$uuid}.yml",
|
"chmod 600 /tmp/{$uuid}.yml",
|
||||||
"docker compose -f /tmp/{$uuid}.yml config --no-interpolate --no-path-resolution -q",
|
"docker compose -f /tmp/{$uuid}.yml config --no-interpolate --no-path-resolution -q",
|
||||||
"rm /tmp/{$uuid}.yml",
|
"rm /tmp/{$uuid}.yml",
|
||||||
|
@@ -29,31 +29,11 @@ function remote_process(
|
|||||||
$type = $type ?? ActivityTypes::INLINE->value;
|
$type = $type ?? ActivityTypes::INLINE->value;
|
||||||
$command = $command instanceof Collection ? $command->toArray() : $command;
|
$command = $command instanceof Collection ? $command->toArray() : $command;
|
||||||
|
|
||||||
// Process commands and handle file transfers
|
|
||||||
$processed_commands = [];
|
|
||||||
foreach ($command as $cmd) {
|
|
||||||
if (is_array($cmd) && isset($cmd['transfer_file'])) {
|
|
||||||
// Handle file transfer command
|
|
||||||
$transfer_data = $cmd['transfer_file'];
|
|
||||||
$content = $transfer_data['content'];
|
|
||||||
$destination = $transfer_data['destination'];
|
|
||||||
|
|
||||||
// Execute file transfer immediately
|
|
||||||
transfer_file_to_server($content, $destination, $server, ! $ignore_errors);
|
|
||||||
|
|
||||||
// Add a comment to the command log for visibility
|
|
||||||
$processed_commands[] = "# File transferred via SCP: $destination";
|
|
||||||
} else {
|
|
||||||
// Regular string command
|
|
||||||
$processed_commands[] = $cmd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($server->isNonRoot()) {
|
if ($server->isNonRoot()) {
|
||||||
$processed_commands = parseCommandsByLineForSudo(collect($processed_commands), $server);
|
$command = parseCommandsByLineForSudo(collect($command), $server);
|
||||||
}
|
}
|
||||||
|
|
||||||
$command_string = implode("\n", $processed_commands);
|
$command_string = implode("\n", $command);
|
||||||
|
|
||||||
if (Auth::check()) {
|
if (Auth::check()) {
|
||||||
$teams = Auth::user()->teams->pluck('id');
|
$teams = Auth::user()->teams->pluck('id');
|
||||||
@@ -200,30 +180,10 @@ function instant_remote_process(Collection|array $command, Server $server, bool
|
|||||||
{
|
{
|
||||||
$command = $command instanceof Collection ? $command->toArray() : $command;
|
$command = $command instanceof Collection ? $command->toArray() : $command;
|
||||||
|
|
||||||
// Process commands and handle file transfers
|
|
||||||
$processed_commands = [];
|
|
||||||
foreach ($command as $cmd) {
|
|
||||||
if (is_array($cmd) && isset($cmd['transfer_file'])) {
|
|
||||||
// Handle file transfer command
|
|
||||||
$transfer_data = $cmd['transfer_file'];
|
|
||||||
$content = $transfer_data['content'];
|
|
||||||
$destination = $transfer_data['destination'];
|
|
||||||
|
|
||||||
// Execute file transfer immediately
|
|
||||||
transfer_file_to_server($content, $destination, $server, $throwError);
|
|
||||||
|
|
||||||
// Add a comment to the command log for visibility
|
|
||||||
$processed_commands[] = "# File transferred via SCP: $destination";
|
|
||||||
} else {
|
|
||||||
// Regular string command
|
|
||||||
$processed_commands[] = $cmd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($server->isNonRoot() && ! $no_sudo) {
|
if ($server->isNonRoot() && ! $no_sudo) {
|
||||||
$processed_commands = parseCommandsByLineForSudo(collect($processed_commands), $server);
|
$command = parseCommandsByLineForSudo(collect($command), $server);
|
||||||
}
|
}
|
||||||
$command_string = implode("\n", $processed_commands);
|
$command_string = implode("\n", $command);
|
||||||
|
|
||||||
return \App\Helpers\SshRetryHandler::retry(
|
return \App\Helpers\SshRetryHandler::retry(
|
||||||
function () use ($server, $command_string) {
|
function () use ($server, $command_string) {
|
||||||
|
@@ -69,11 +69,12 @@ function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Appli
|
|||||||
$fileVolume->content = $content;
|
$fileVolume->content = $content;
|
||||||
$fileVolume->is_directory = false;
|
$fileVolume->is_directory = false;
|
||||||
$fileVolume->save();
|
$fileVolume->save();
|
||||||
|
$content = base64_encode($content);
|
||||||
$dir = str($fileLocation)->dirname();
|
$dir = str($fileLocation)->dirname();
|
||||||
instant_remote_process([
|
instant_remote_process([
|
||||||
"mkdir -p $dir",
|
"mkdir -p $dir",
|
||||||
|
"echo '$content' | base64 -d | tee $fileLocation",
|
||||||
], $server);
|
], $server);
|
||||||
transfer_file_to_server($content, $fileLocation, $server);
|
|
||||||
} elseif ($isFile === 'NOK' && $isDir === 'NOK' && $fileVolume->is_directory && $isInit) {
|
} elseif ($isFile === 'NOK' && $isDir === 'NOK' && $fileVolume->is_directory && $isInit) {
|
||||||
// Does not exists (no dir or file), flagged as directory, is init
|
// Does not exists (no dir or file), flagged as directory, is init
|
||||||
$fileVolume->content = null;
|
$fileVolume->content = null;
|
||||||
|
@@ -1125,30 +1125,77 @@ function get_public_ips()
|
|||||||
function isAnyDeploymentInprogress()
|
function isAnyDeploymentInprogress()
|
||||||
{
|
{
|
||||||
$runningJobs = ApplicationDeploymentQueue::where('horizon_job_worker', gethostname())->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value)->get();
|
$runningJobs = ApplicationDeploymentQueue::where('horizon_job_worker', gethostname())->where('status', ApplicationDeploymentStatus::IN_PROGRESS->value)->get();
|
||||||
$basicDetails = $runningJobs->map(function ($job) {
|
|
||||||
return [
|
if ($runningJobs->isEmpty()) {
|
||||||
'id' => $job->id,
|
echo "No deployments in progress.\n";
|
||||||
'created_at' => $job->created_at,
|
exit(0);
|
||||||
'application_id' => $job->application_id,
|
}
|
||||||
'server_id' => $job->server_id,
|
|
||||||
'horizon_job_id' => $job->horizon_job_id,
|
|
||||||
'status' => $job->status,
|
|
||||||
];
|
|
||||||
});
|
|
||||||
echo 'Running jobs: '.json_encode($basicDetails)."\n";
|
|
||||||
$horizonJobIds = [];
|
$horizonJobIds = [];
|
||||||
|
$deploymentDetails = [];
|
||||||
|
|
||||||
foreach ($runningJobs as $runningJob) {
|
foreach ($runningJobs as $runningJob) {
|
||||||
$horizonJobStatus = getJobStatus($runningJob->horizon_job_id);
|
$horizonJobStatus = getJobStatus($runningJob->horizon_job_id);
|
||||||
if ($horizonJobStatus === 'unknown' || $horizonJobStatus === 'reserved') {
|
if ($horizonJobStatus === 'unknown' || $horizonJobStatus === 'reserved') {
|
||||||
$horizonJobIds[] = $runningJob->horizon_job_id;
|
$horizonJobIds[] = $runningJob->horizon_job_id;
|
||||||
|
|
||||||
|
// Get application and team information
|
||||||
|
$application = Application::find($runningJob->application_id);
|
||||||
|
$teamMembers = [];
|
||||||
|
$deploymentUrl = '';
|
||||||
|
|
||||||
|
if ($application) {
|
||||||
|
// Get team members through the application's project
|
||||||
|
$team = $application->team();
|
||||||
|
if ($team) {
|
||||||
|
$teamMembers = $team->members()->pluck('email')->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the full deployment URL
|
||||||
|
if ($runningJob->deployment_url) {
|
||||||
|
$baseUrl = base_url();
|
||||||
|
$deploymentUrl = $baseUrl.$runningJob->deployment_url;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$deploymentDetails[] = [
|
||||||
|
'id' => $runningJob->id,
|
||||||
|
'application_name' => $runningJob->application_name ?? 'Unknown',
|
||||||
|
'server_name' => $runningJob->server_name ?? 'Unknown',
|
||||||
|
'deployment_url' => $deploymentUrl,
|
||||||
|
'team_members' => $teamMembers,
|
||||||
|
'created_at' => $runningJob->created_at->format('Y-m-d H:i:s'),
|
||||||
|
'horizon_job_id' => $runningJob->horizon_job_id,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count($horizonJobIds) === 0) {
|
if (count($horizonJobIds) === 0) {
|
||||||
echo "No deployments in progress.\n";
|
echo "No active deployments in progress (all jobs completed or failed).\n";
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
$horizonJobIds = collect($horizonJobIds)->unique()->toArray();
|
|
||||||
echo 'There are '.count($horizonJobIds)." deployments in progress.\n";
|
// Display enhanced deployment information
|
||||||
|
echo "\n=== Running Deployments ===\n";
|
||||||
|
echo 'Total active deployments: '.count($horizonJobIds)."\n\n";
|
||||||
|
|
||||||
|
foreach ($deploymentDetails as $index => $deployment) {
|
||||||
|
echo 'Deployment #'.($index + 1).":\n";
|
||||||
|
echo ' Application: '.$deployment['application_name']."\n";
|
||||||
|
echo ' Server: '.$deployment['server_name']."\n";
|
||||||
|
echo ' Started: '.$deployment['created_at']."\n";
|
||||||
|
if ($deployment['deployment_url']) {
|
||||||
|
echo ' URL: '.$deployment['deployment_url']."\n";
|
||||||
|
}
|
||||||
|
if (! empty($deployment['team_members'])) {
|
||||||
|
echo ' Team members: '.implode(', ', $deployment['team_members'])."\n";
|
||||||
|
} else {
|
||||||
|
echo " Team members: No team members found\n";
|
||||||
|
}
|
||||||
|
echo ' Horizon Job ID: '.$deployment['horizon_job_id']."\n";
|
||||||
|
echo "\n";
|
||||||
|
}
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'coolify' => [
|
'coolify' => [
|
||||||
'version' => '4.0.0-beta.427',
|
'version' => '4.0.0-beta.428',
|
||||||
'helper_version' => '1.0.10',
|
'helper_version' => '1.0.11',
|
||||||
'realtime_version' => '1.0.10',
|
'realtime_version' => '1.0.10',
|
||||||
'self_hosted' => env('SELF_HOSTED', true),
|
'self_hosted' => env('SELF_HOSTED', true),
|
||||||
'autoupdate' => env('AUTOUPDATE'),
|
'autoupdate' => env('AUTOUPDATE'),
|
||||||
|
10
docker/coolify-realtime/package-lock.json
generated
10
docker/coolify-realtime/package-lock.json
generated
@@ -7,7 +7,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xterm/addon-fit": "0.10.0",
|
"@xterm/addon-fit": "0.10.0",
|
||||||
"@xterm/xterm": "5.5.0",
|
"@xterm/xterm": "5.5.0",
|
||||||
"axios": "1.8.4",
|
"axios": "1.12.0",
|
||||||
"cookie": "1.0.2",
|
"cookie": "1.0.2",
|
||||||
"dotenv": "16.5.0",
|
"dotenv": "16.5.0",
|
||||||
"node-pty": "1.0.0",
|
"node-pty": "1.0.0",
|
||||||
@@ -36,13 +36,13 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.8.4",
|
"version": "1.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz",
|
||||||
"integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
|
"integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.4",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
"@xterm/addon-fit": "0.10.0",
|
"@xterm/addon-fit": "0.10.0",
|
||||||
"@xterm/xterm": "5.5.0",
|
"@xterm/xterm": "5.5.0",
|
||||||
"cookie": "1.0.2",
|
"cookie": "1.0.2",
|
||||||
"axios": "1.8.4",
|
"axios": "1.12.0",
|
||||||
"dotenv": "16.5.0",
|
"dotenv": "16.5.0",
|
||||||
"node-pty": "1.0.0",
|
"node-pty": "1.0.0",
|
||||||
"ws": "8.18.1"
|
"ws": "8.18.1"
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"coolify": {
|
"coolify": {
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.427"
|
|
||||||
},
|
|
||||||
"nightly": {
|
|
||||||
"version": "4.0.0-beta.428"
|
"version": "4.0.0-beta.428"
|
||||||
},
|
},
|
||||||
|
"nightly": {
|
||||||
|
"version": "4.0.0-beta.429"
|
||||||
|
},
|
||||||
"helper": {
|
"helper": {
|
||||||
"version": "1.0.10"
|
"version": "1.0.11"
|
||||||
},
|
},
|
||||||
"realtime": {
|
"realtime": {
|
||||||
"version": "1.0.10"
|
"version": "1.0.10"
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"coolify": {
|
"coolify": {
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.427"
|
|
||||||
},
|
|
||||||
"nightly": {
|
|
||||||
"version": "4.0.0-beta.428"
|
"version": "4.0.0-beta.428"
|
||||||
},
|
},
|
||||||
|
"nightly": {
|
||||||
|
"version": "4.0.0-beta.429"
|
||||||
|
},
|
||||||
"helper": {
|
"helper": {
|
||||||
"version": "1.0.10"
|
"version": "1.0.11"
|
||||||
},
|
},
|
||||||
"realtime": {
|
"realtime": {
|
||||||
"version": "1.0.10"
|
"version": "1.0.10"
|
||||||
|
Reference in New Issue
Block a user