Merge branch 'next' into feat-forgejo
This commit is contained in:
@@ -732,8 +732,10 @@ class ApplicationsController extends Controller
|
||||
$application->environment_id = $environment->id;
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
}
|
||||
$application->isConfigurationChanged(true);
|
||||
|
||||
if ($instantDeploy) {
|
||||
@@ -826,8 +828,10 @@ class ApplicationsController extends Controller
|
||||
$application->source_id = $githubApp->id;
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
}
|
||||
$application->isConfigurationChanged(true);
|
||||
|
||||
if ($instantDeploy) {
|
||||
@@ -916,8 +920,10 @@ class ApplicationsController extends Controller
|
||||
$application->environment_id = $environment->id;
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
}
|
||||
$application->isConfigurationChanged(true);
|
||||
|
||||
if ($instantDeploy) {
|
||||
@@ -996,8 +1002,10 @@ class ApplicationsController extends Controller
|
||||
$application->git_branch = 'main';
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
}
|
||||
$application->isConfigurationChanged(true);
|
||||
|
||||
if ($instantDeploy) {
|
||||
@@ -1052,8 +1060,10 @@ class ApplicationsController extends Controller
|
||||
$application->git_branch = 'main';
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
$application->custom_labels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->save();
|
||||
}
|
||||
$application->isConfigurationChanged(true);
|
||||
|
||||
if ($instantDeploy) {
|
||||
@@ -1494,8 +1504,10 @@ class ApplicationsController extends Controller
|
||||
$fqdn = str($fqdn)->replaceEnd(',', '')->trim();
|
||||
$fqdn = str($fqdn)->replaceStart(',', '')->trim();
|
||||
$application->fqdn = $fqdn;
|
||||
$customLabels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->custom_labels = base64_encode($customLabels);
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
$customLabels = str(implode('|coolify|', generateLabelsApplication($application)))->replace('|coolify|', "\n");
|
||||
$application->custom_labels = base64_encode($customLabels);
|
||||
}
|
||||
$request->offsetUnset('domains');
|
||||
}
|
||||
|
||||
|
||||
@@ -462,7 +462,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
if ($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} build";
|
||||
$command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull";
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, $command), 'hidden' => true],
|
||||
);
|
||||
@@ -1523,7 +1523,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$this->application->custom_labels = base64_encode($labels->implode("\n"));
|
||||
$this->application->save();
|
||||
} else {
|
||||
$labels = collect(generateLabelsApplication($this->application, $this->preview));
|
||||
if (! $this->application->settings->is_container_label_readonly_enabled) {
|
||||
$labels = collect(generateLabelsApplication($this->application, $this->preview));
|
||||
}
|
||||
}
|
||||
if ($this->pull_request_id !== 0) {
|
||||
$labels = collect(generateLabelsApplication($this->application, $this->preview));
|
||||
@@ -1624,12 +1626,15 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
],
|
||||
],
|
||||
];
|
||||
if (data_get($this->application, 'swarm_placement_constraints')) {
|
||||
$swarm_placement_constraints = Yaml::parse(base64_decode(data_get($this->application, 'swarm_placement_constraints')));
|
||||
$docker_compose['services'][$this->container_name]['deploy'] = array_merge(
|
||||
$docker_compose['services'][$this->container_name]['deploy'],
|
||||
$swarm_placement_constraints
|
||||
);
|
||||
}
|
||||
if (data_get($this->application, 'settings.is_swarm_only_worker_nodes')) {
|
||||
$docker_compose['services'][$this->container_name]['deploy']['placement'] = [
|
||||
'constraints' => [
|
||||
'node.role == worker',
|
||||
],
|
||||
];
|
||||
$docker_compose['services'][$this->container_name]['deploy']['placement']['constraints'][] = 'node.role == worker';
|
||||
}
|
||||
if ($this->pull_request_id !== 0) {
|
||||
$docker_compose['services'][$this->container_name]['deploy']['replicas'] = 1;
|
||||
@@ -2028,23 +2033,6 @@ COPY ./nginx.conf /etc/nginx/conf.d/default.conf");
|
||||
}
|
||||
}
|
||||
|
||||
private function build_by_compose_file()
|
||||
{
|
||||
$this->application_deployment_queue->addLogEntry('Pulling & building required images.');
|
||||
if ($this->application->build_pack === 'dockerimage') {
|
||||
$this->application_deployment_queue->addLogEntry('Pulling latest images from the registry.');
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} pull"), 'hidden' => true],
|
||||
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} build"), 'hidden' => true],
|
||||
);
|
||||
} else {
|
||||
$this->execute_remote_command(
|
||||
[executeInDocker($this->deployment_uuid, "{$this->coolify_variables} docker compose --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build"), 'hidden' => true],
|
||||
);
|
||||
}
|
||||
$this->application_deployment_queue->addLogEntry('New images built.');
|
||||
}
|
||||
|
||||
private function start_by_compose_file()
|
||||
{
|
||||
if ($this->application->build_pack === 'dockerimage') {
|
||||
|
||||
@@ -84,6 +84,7 @@ class General extends Component
|
||||
'application.settings.is_static' => 'boolean|required',
|
||||
'application.settings.is_build_server_enabled' => 'boolean|required',
|
||||
'application.settings.is_container_label_escape_enabled' => 'boolean|required',
|
||||
'application.settings.is_container_label_readonly_enabled' => 'boolean|required',
|
||||
'application.watch_paths' => 'nullable',
|
||||
'application.redirect' => 'string|required',
|
||||
];
|
||||
@@ -119,6 +120,7 @@ class General extends Component
|
||||
'application.settings.is_static' => 'Is static',
|
||||
'application.settings.is_build_server_enabled' => 'Is build server enabled',
|
||||
'application.settings.is_container_label_escape_enabled' => 'Is container label escape enabled',
|
||||
'application.settings.is_container_label_readonly_enabled' => 'Is container label readonly',
|
||||
'application.watch_paths' => 'Watch paths',
|
||||
'application.redirect' => 'Redirect',
|
||||
];
|
||||
@@ -143,7 +145,7 @@ class General extends Component
|
||||
$this->ports_exposes = $this->application->ports_exposes;
|
||||
$this->is_container_label_escape_enabled = $this->application->settings->is_container_label_escape_enabled;
|
||||
$this->customLabels = $this->application->parseContainerLabels();
|
||||
if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE') {
|
||||
if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE' && ! $this->application->settings->is_container_label_readonly_enabled) {
|
||||
$this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n");
|
||||
$this->application->custom_labels = base64_encode($this->customLabels);
|
||||
$this->application->save();
|
||||
@@ -290,6 +292,9 @@ class General extends Component
|
||||
|
||||
public function resetDefaultLabels()
|
||||
{
|
||||
if ($this->application->settings->is_container_label_readonly_enabled) {
|
||||
return;
|
||||
}
|
||||
$this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n");
|
||||
$this->ports_exposes = $this->application->ports_exposes;
|
||||
$this->is_container_label_escape_enabled = $this->application->settings->is_container_label_escape_enabled;
|
||||
@@ -350,7 +355,7 @@ class General extends Component
|
||||
$this->checkFqdns();
|
||||
|
||||
$this->application->save();
|
||||
if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE') {
|
||||
if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE' && ! $this->application->settings->is_container_label_readonly_enabled) {
|
||||
$this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n");
|
||||
$this->application->custom_labels = base64_encode($this->customLabels);
|
||||
$this->application->save();
|
||||
|
||||
@@ -53,6 +53,12 @@ class GithubPrivateRepository extends Component
|
||||
|
||||
public ?string $publish_directory = null;
|
||||
|
||||
// In case of docker compose
|
||||
public ?string $base_directory = null;
|
||||
|
||||
public ?string $docker_compose_location = '/docker-compose.yaml';
|
||||
// End of docker compose
|
||||
|
||||
protected int $page = 1;
|
||||
|
||||
public $build_pack = 'nixpacks';
|
||||
@@ -68,6 +74,16 @@ class GithubPrivateRepository extends Component
|
||||
$this->github_apps = GithubApp::private();
|
||||
}
|
||||
|
||||
public function updatedBaseDirectory()
|
||||
{
|
||||
if ($this->base_directory) {
|
||||
$this->base_directory = rtrim($this->base_directory, '/');
|
||||
if (! str($this->base_directory)->startsWith('/')) {
|
||||
$this->base_directory = '/'.$this->base_directory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedBuildPack()
|
||||
{
|
||||
if ($this->build_pack === 'nixpacks') {
|
||||
@@ -184,6 +200,10 @@ class GithubPrivateRepository extends Component
|
||||
if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') {
|
||||
$application->health_check_enabled = false;
|
||||
}
|
||||
if ($this->build_pack === 'dockercompose') {
|
||||
$application['docker_compose_location'] = $this->docker_compose_location;
|
||||
$application['base_directory'] = $this->base_directory;
|
||||
}
|
||||
$fqdn = generateFqdn($destination->server, $application->uuid);
|
||||
$application->fqdn = $fqdn;
|
||||
|
||||
|
||||
@@ -33,6 +33,12 @@ class GithubPrivateRepositoryDeployKey extends Component
|
||||
|
||||
public ?string $publish_directory = null;
|
||||
|
||||
// In case of docker compose
|
||||
public ?string $base_directory = null;
|
||||
|
||||
public ?string $docker_compose_location = '/docker-compose.yaml';
|
||||
// End of docker compose
|
||||
|
||||
public string $repository_url;
|
||||
|
||||
public string $branch;
|
||||
@@ -163,6 +169,10 @@ class GithubPrivateRepositoryDeployKey extends Component
|
||||
if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') {
|
||||
$application_init['health_check_enabled'] = false;
|
||||
}
|
||||
if ($this->build_pack === 'dockercompose') {
|
||||
$application_init['docker_compose_location'] = $this->docker_compose_location;
|
||||
$application_init['base_directory'] = $this->base_directory;
|
||||
}
|
||||
$application = Application::create($application_init);
|
||||
$application->settings->is_static = $this->is_static;
|
||||
$application->settings->save();
|
||||
|
||||
@@ -33,6 +33,12 @@ class PublicGitRepository extends Component
|
||||
|
||||
public ?string $publish_directory = null;
|
||||
|
||||
// In case of docker compose
|
||||
public ?string $base_directory = null;
|
||||
|
||||
public ?string $docker_compose_location = '/docker-compose.yaml';
|
||||
// End of docker compose
|
||||
|
||||
public string $git_branch = 'main';
|
||||
|
||||
public int $rate_limit_remaining = 0;
|
||||
@@ -59,6 +65,8 @@ class PublicGitRepository extends Component
|
||||
'is_static' => 'required|boolean',
|
||||
'publish_directory' => 'nullable|string',
|
||||
'build_pack' => 'required|string',
|
||||
'base_directory' => 'nullable|string',
|
||||
'docker_compose_location' => 'nullable|string',
|
||||
];
|
||||
|
||||
protected $validationAttributes = [
|
||||
@@ -67,6 +75,8 @@ class PublicGitRepository extends Component
|
||||
'is_static' => 'static',
|
||||
'publish_directory' => 'publish directory',
|
||||
'build_pack' => 'build pack',
|
||||
'base_directory' => 'base directory',
|
||||
'docker_compose_location' => 'docker compose location',
|
||||
];
|
||||
|
||||
public function mount()
|
||||
@@ -79,6 +89,16 @@ class PublicGitRepository extends Component
|
||||
$this->query = request()->query();
|
||||
}
|
||||
|
||||
public function updatedBaseDirectory()
|
||||
{
|
||||
if ($this->base_directory) {
|
||||
$this->base_directory = rtrim($this->base_directory, '/');
|
||||
if (! str($this->base_directory)->startsWith('/')) {
|
||||
$this->base_directory = '/'.$this->base_directory;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function updatedBuildPack()
|
||||
{
|
||||
if ($this->build_pack === 'nixpacks') {
|
||||
@@ -261,6 +281,10 @@ class PublicGitRepository extends Component
|
||||
if ($this->build_pack === 'dockerfile' || $this->build_pack === 'dockerimage') {
|
||||
$application_init['health_check_enabled'] = false;
|
||||
}
|
||||
if ($this->build_pack === 'dockercompose') {
|
||||
$application_init['docker_compose_location'] = $this->docker_compose_location;
|
||||
$application_init['base_directory'] = $this->base_directory;
|
||||
}
|
||||
$application = Application::create($application_init);
|
||||
|
||||
$application->settings->is_static = $this->is_static;
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Livewire\Project\Shared\Storages;
|
||||
|
||||
use App\Models\LocalPersistentVolume;
|
||||
use Livewire\Component;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
class Show extends Component
|
||||
{
|
||||
@@ -12,8 +11,6 @@ class Show extends Component
|
||||
|
||||
public bool $isReadOnly = false;
|
||||
|
||||
public ?string $modalId = null;
|
||||
|
||||
public bool $isFirst = true;
|
||||
|
||||
public bool $isService = false;
|
||||
@@ -32,11 +29,6 @@ class Show extends Component
|
||||
'host_path' => 'host',
|
||||
];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->modalId = new Cuid2(7);
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Livewire\Tags;
|
||||
|
||||
use App\Http\Controllers\Api\Deploy;
|
||||
use App\Http\Controllers\Api\DeployController;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Attributes\Url;
|
||||
@@ -51,11 +51,11 @@ class Index extends Component
|
||||
{
|
||||
try {
|
||||
$this->applications->each(function ($resource) {
|
||||
$deploy = new Deploy();
|
||||
$deploy = new DeployController();
|
||||
$deploy->deploy_resource($resource);
|
||||
});
|
||||
$this->services->each(function ($resource) {
|
||||
$deploy = new Deploy();
|
||||
$deploy = new DeployController();
|
||||
$deploy->deploy_resource($resource);
|
||||
});
|
||||
$this->dispatch('success', 'Mass deployment started.');
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Livewire\Tags;
|
||||
|
||||
use App\Http\Controllers\Api\Deploy;
|
||||
use App\Http\Controllers\Api\DeployController;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\Tag;
|
||||
use Livewire\Component;
|
||||
@@ -59,11 +59,11 @@ class Show extends Component
|
||||
try {
|
||||
$message = collect([]);
|
||||
$this->applications->each(function ($resource) use ($message) {
|
||||
$deploy = new Deploy();
|
||||
$deploy = new DeployController();
|
||||
$message->push($deploy->deploy_resource($resource));
|
||||
});
|
||||
$this->services->each(function ($resource) use ($message) {
|
||||
$deploy = new Deploy();
|
||||
$deploy = new DeployController();
|
||||
$message->push($deploy->deploy_resource($resource));
|
||||
});
|
||||
$this->dispatch('success', 'Mass deployment started.');
|
||||
|
||||
@@ -1081,45 +1081,55 @@ class Application extends BaseModel
|
||||
'git read-tree -mu HEAD',
|
||||
"cat .$workdir$composeFile",
|
||||
]);
|
||||
$composeFileContent = instant_remote_process($commands, $this->destination->server, false);
|
||||
if (! $composeFileContent) {
|
||||
try {
|
||||
$composeFileContent = instant_remote_process($commands, $this->destination->server);
|
||||
} catch (\Exception $e) {
|
||||
if (str($e->getMessage())->contains('No such file')) {
|
||||
throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
|
||||
}
|
||||
if (str($e->getMessage())->contains('fatal: repository') && str($e->getMessage())->contains('does not exist')) {
|
||||
if ($this->deploymentType() === 'deploy_key') {
|
||||
throw new \RuntimeException('Your deploy key does not have access to the repository. Please check your deploy key and try again.');
|
||||
}
|
||||
throw new \RuntimeException('Repository does not exist. Please check your repository URL and try again.');
|
||||
}
|
||||
throw new \RuntimeException($e->getMessage());
|
||||
} finally {
|
||||
$this->docker_compose_location = $initialDockerComposeLocation;
|
||||
$this->save();
|
||||
$commands = collect([
|
||||
"rm -rf /tmp/{$uuid}",
|
||||
]);
|
||||
instant_remote_process($commands, $this->destination->server, false);
|
||||
throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
|
||||
} else {
|
||||
}
|
||||
if ($composeFileContent) {
|
||||
$this->docker_compose_raw = $composeFileContent;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
$commands = collect([
|
||||
"rm -rf /tmp/{$uuid}",
|
||||
]);
|
||||
instant_remote_process($commands, $this->destination->server, false);
|
||||
$parsedServices = $this->parseCompose();
|
||||
if ($this->docker_compose_domains) {
|
||||
$json = collect(json_decode($this->docker_compose_domains));
|
||||
$names = collect(data_get($parsedServices, 'services'))->keys()->toArray();
|
||||
$jsonNames = $json->keys()->toArray();
|
||||
$diff = array_diff($jsonNames, $names);
|
||||
$json = $json->filter(function ($value, $key) use ($diff) {
|
||||
return ! in_array($key, $diff);
|
||||
});
|
||||
if ($json) {
|
||||
$this->docker_compose_domains = json_encode($json);
|
||||
} else {
|
||||
$this->docker_compose_domains = null;
|
||||
$parsedServices = $this->parseCompose();
|
||||
if ($this->docker_compose_domains) {
|
||||
$json = collect(json_decode($this->docker_compose_domains));
|
||||
$names = collect(data_get($parsedServices, 'services'))->keys()->toArray();
|
||||
$jsonNames = $json->keys()->toArray();
|
||||
$diff = array_diff($jsonNames, $names);
|
||||
$json = $json->filter(function ($value, $key) use ($diff) {
|
||||
return ! in_array($key, $diff);
|
||||
});
|
||||
if ($json) {
|
||||
$this->docker_compose_domains = json_encode($json);
|
||||
} else {
|
||||
$this->docker_compose_domains = null;
|
||||
}
|
||||
$this->save();
|
||||
}
|
||||
$this->save();
|
||||
|
||||
return [
|
||||
'parsedServices' => $parsedServices,
|
||||
'initialDockerComposeLocation' => $this->docker_compose_location,
|
||||
];
|
||||
} else {
|
||||
throw new \RuntimeException("Docker Compose file not found at: $workdir$composeFile<br><br>Check if you used the right extension (.yaml or .yml) in the compose file name.");
|
||||
}
|
||||
|
||||
return [
|
||||
'parsedServices' => $parsedServices,
|
||||
'initialDockerComposeLocation' => $this->docker_compose_location,
|
||||
];
|
||||
}
|
||||
|
||||
public function parseContainerLabels(?ApplicationPreview $preview = null)
|
||||
|
||||
@@ -24,6 +24,7 @@ use Symfony\Component\Yaml\Yaml;
|
||||
'destination_id' => ['type' => 'integer', 'description' => 'The unique identifier of the destination where the service is running.'],
|
||||
'connect_to_docker_network' => ['type' => 'boolean', 'description' => 'The flag to connect the service to the predefined Docker network.'],
|
||||
'is_container_label_escape_enabled' => ['type' => 'boolean', 'description' => 'The flag to enable the container label escape.'],
|
||||
'is_container_label_readonly_enabled' => ['type' => 'boolean', 'description' => 'The flag to enable the container label readonly.'],
|
||||
'config_hash' => ['type' => 'string', 'description' => 'The hash of the service configuration.'],
|
||||
'service_type' => ['type' => 'string', 'description' => 'The type of the service.'],
|
||||
'created_at' => ['type' => 'string', 'description' => 'The date and time when the service was created.'],
|
||||
|
||||
@@ -88,6 +88,9 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
|
||||
try {
|
||||
$name = data_get($resource, 'name');
|
||||
$dockerComposeRaw = data_get($resource, 'service.docker_compose_raw');
|
||||
if (! $dockerComposeRaw) {
|
||||
throw new \Exception('No compose file found or not a valid YAML file.');
|
||||
}
|
||||
$dockerCompose = Yaml::parse($dockerComposeRaw);
|
||||
|
||||
// Switch Image
|
||||
@@ -106,7 +109,7 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
|
||||
if ($resourceFqdns->count() === 1) {
|
||||
$resourceFqdns = $resourceFqdns->first();
|
||||
$variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
|
||||
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
|
||||
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'LIKE', "{$variableName}_%")->first();
|
||||
$fqdn = Url::fromString($resourceFqdns);
|
||||
$port = $fqdn->getPort();
|
||||
$path = $fqdn->getPath();
|
||||
@@ -125,7 +128,7 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
|
||||
}
|
||||
}
|
||||
$variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
|
||||
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
|
||||
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'LIKE', "{$variableName}_%")->first();
|
||||
$url = Url::fromString($fqdn);
|
||||
$port = $url->getPort();
|
||||
$path = $url->getPath();
|
||||
|
||||
@@ -1688,7 +1688,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
$read_only = data_get($volume, 'read_only');
|
||||
if ($source && $target) {
|
||||
$uuid = $resource->uuid;
|
||||
if ((str($source)->startsWith('.') || str($source)->startsWith('~'))) {
|
||||
if ((str($source)->startsWith('.') || str($source)->startsWith('~') || str($source)->startsWith('/'))) {
|
||||
$dir = base_configuration_dir().'/applications/'.$resource->uuid;
|
||||
if (str($source, '.')) {
|
||||
$source = str($source)->replaceFirst('.', $dir);
|
||||
@@ -1696,11 +1696,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
if (str($source, '~')) {
|
||||
$source = str($source)->replaceFirst('~', $dir);
|
||||
}
|
||||
if ($pull_request_id === 0) {
|
||||
$source = $uuid."-$source";
|
||||
} else {
|
||||
$source = $uuid."-$source-pr-$pull_request_id";
|
||||
}
|
||||
if ($read_only) {
|
||||
data_set($volume, 'source', $source.':'.$target.':ro');
|
||||
} else {
|
||||
|
||||
@@ -7,7 +7,7 @@ return [
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.313',
|
||||
'release' => '4.0.0-beta.316',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<?php
|
||||
|
||||
return '4.0.0-beta.313';
|
||||
return '4.0.0-beta.316';
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('application_settings', function (Blueprint $table) {
|
||||
$table->boolean('is_container_label_readonly_enabled')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('application_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('is_container_label_readonly_enabled');
|
||||
});
|
||||
}
|
||||
};
|
||||
BIN
public/svgs/docmost.png
Normal file
BIN
public/svgs/docmost.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
1
public/svgs/drupal.svg
Normal file
1
public/svgs/drupal.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="220.03239mm" height="167.50914mm" viewBox="0 0 623.71387 474.82906"><title>Risorsa 28</title><g id="Livello_2" data-name="Livello 2"><g id="Livello_1-2" data-name="Livello 1"><path d="M292.12129,345.00234h-26.212l.04275,49.04508c0,14.33211-6.14488,25.92692-20.477,25.92692-14.33924,0-20.54117-11.59481-20.54117-25.92692V345.04868H198.78953l-.00713,48.99874c0,28.32213,18.20655,51.27636,46.53223,51.27636,28.31849,0,46.79948-22.95423,46.79948-51.27636Z" style="fill:#009cde"/><rect x="528.48024" y="315.11614" width="26.08367" height="127.67755" style="fill:#009cde"/><polygon points="573.823 319.826 573.823 315.239 594.15 315.239 594.15 319.826 586.715 319.826 586.715 340.043 581.261 340.043 581.261 319.826 573.823 319.826" style="fill:#009cde"/><polygon points="604.673 315.24 610.476 332.295 610.544 332.295 616.029 315.24 623.714 315.24 623.714 340.044 618.606 340.044 618.606 322.465 618.535 322.465 612.458 340.044 608.252 340.044 602.175 322.64 602.103 322.64 602.103 340.044 596.999 340.044 596.999 315.24 604.673 315.24" style="fill:#009cde"/><path d="M177.46784,343.93624c-22.48375-5.18962-36.66617,17.148-37.25785,18.34557-.28871.58814-.2994.93035-1.29384.90533-.82337-.01773-.916-.90533-.916-.90533l-2.79086-17.08726H111.84157v97.51614h26.19419v-52.784c0-4.3128,11.61256-24.993,34.11766-19.67153,11.38088,2.69467,16.21054,7.52436,16.21054,7.52436V348.07087a41.85,41.85,0,0,0-10.89612-4.13463" style="fill:#009cde"/><path d="M353.05258,368.64446a26.13539,26.13539,0,1,1-26.13,26.13,26.13748,26.13748,0,0,1,26.13-26.13M327.664,474.82906V439.74191l.00712.00718.00713-13.14169s.03921-1.05141.98729-1.06218c.84474-.01066,1.03368.549,1.24041,1.06218,1.98529,4.94369,12.90641,23.76689,37.14374,17.86435A51.631,51.631,0,1,0,301.402,394.77446v80.0546Z" style="fill:#009cde"/><path d="M492.37655,394.77479a26.13539,26.13539,0,1,1-26.1336-26.13,26.139,26.139,0,0,1,26.1336,26.13m-.74494,47.9793H517.8935v-47.9793a51.62918,51.62918,0,1,0-65.64764,49.69381c24.23739,5.906,35.15845-12.92066,37.14374-17.86087.20673-.5132.39208-1.07284,1.24041-1.06566.94808.01425.98729,1.06566.98729,1.06566" style="fill:#009cde"/><path d="M36.905,337.16373h-10.529v83.26605l10.81417.278c22.18076,0,36.46656-2.01733,36.46656-41.90208,0-38.24519-12.61057-41.642-36.75172-41.642m-7.1108,105.38619H0V315.0649H31.96836c38.70852,0,68.06785,7.10374,68.06785,63.74083,0,56.09518-31.09872,63.74419-70.24206,63.74419" style="fill:#009cde"/><path d="M336.513,60.04433C316.67656,40.21728,297.75071,21.31654,292.11812,0c-5.63286,21.31654-24.56176,40.21728-44.39487,60.04433-29.74983,29.731-63.47995,63.42669-63.47995,113.96434a107.878,107.878,0,1,0,215.756,0c0-50.53435-33.72736-84.23329-63.48628-113.96434M230.09481,199.146c-6.61462-.22461-31.02654-42.30194,14.26152-87.1038l29.96891,32.73593a2.56174,2.56174,0,0,1-.20005,3.82276c-7.15132,7.33453-37.63207,37.90055-41.42061,48.46955-.782,2.18152-1.92407,2.099-2.60977,2.07556m62.02662,55.45668a37.10175,37.10175,0,0,1-37.102-37.102c0-9.39381,3.73446-17.765,9.24757-24.50685,6.68995-8.18054,27.84947-31.18907,27.84947-31.18907s20.83558,23.34627,27.79953,31.111a36.28369,36.28369,0,0,1,9.30744,24.58494,37.10209,37.10209,0,0,1-37.102,37.102m71.01314-60.16628c-.79965,1.74885-2.61363,4.66848-5.062,4.75761-4.36413.15894-4.83045-2.07721-8.05609-6.8511-7.08179-10.47987-68.88406-75.07043-80.44365-87.56214-10.16779-10.987-1.43181-18.733,2.62052-22.79219,5.084-5.09314,19.92417-19.92418,19.92417-19.92418s44.24974,41.984,62.6825,70.67071,12.08027,53.50972,8.33451,61.70129" style="fill:#009cde"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
6
public/svgs/plane.svg
Normal file
6
public/svgs/plane.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="155" height="155" viewBox="0 0 155 155" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="37" y="64" width="27" height="27" fill="#4075FC"/>
|
||||
<rect x="91" y="64" width="27" height="27" fill="#4075FC"/>
|
||||
<rect x="64" y="91" width="27" height="27" fill="#4075FC"/>
|
||||
<rect x="64" y="36" width="54" height="28" fill="#4075FC"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 346 B |
@@ -239,6 +239,9 @@
|
||||
<x-forms.checkbox label="Escape special characters in labels?"
|
||||
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
||||
id="application.settings.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
|
||||
<x-forms.checkbox label="Readonly Labels"
|
||||
helper="If you know what are you doing, you can enable this to edit the labels directly. Coolify won't update labels automatically. <br><br>Be careful, it could break the proxy configuration after you restart the container."
|
||||
id="application.settings.is_container_label_readonly_enabled" instantSave></x-forms.checkbox>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@@ -264,10 +267,13 @@
|
||||
|
||||
<x-forms.textarea label="Container Labels" rows="15" id="customLabels"
|
||||
monacoEditorLanguage="ini" useMonacoEditor></x-forms.textarea>
|
||||
<div class="w-72">
|
||||
<div class="w-96">
|
||||
<x-forms.checkbox label="Escape special characters in labels?"
|
||||
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
||||
id="application.settings.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
|
||||
<x-forms.checkbox label="Readonly Labels"
|
||||
helper="If you know what are you doing, you can enable this to edit the labels directly. Coolify won't update labels automatically. <br><br>Be careful, it could break the proxy configuration after you restart the container."
|
||||
id="application.settings.is_container_label_readonly_enabled" instantSave></x-forms.checkbox>
|
||||
</div>
|
||||
<x-modal-confirmation buttonFullWidth action="resetDefaultLabels"
|
||||
buttonTitle="Reset to Coolify Generated Labels">
|
||||
|
||||
@@ -62,6 +62,15 @@
|
||||
<x-forms.input id="publish_directory" required label="Publish Directory" />
|
||||
@endif
|
||||
</div>
|
||||
@if ($build_pack === 'dockercompose')
|
||||
<x-forms.input placeholder="/" wire:model.blur="base_directory" label="Base Directory"
|
||||
helper="Directory to use as root. Useful for monorepos." />
|
||||
<x-forms.input placeholder="/docker-compose.yaml" id="docker_compose_location"
|
||||
label="Docker Compose Location"
|
||||
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>" />
|
||||
Compose file location in your repository:<span
|
||||
class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>
|
||||
@endif
|
||||
@if ($show_is_static)
|
||||
<x-forms.input type="number" required id="port" label="Port" :readonly="$is_static || $build_pack === 'static'" />
|
||||
<div class="w-52">
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
@endif
|
||||
</div>
|
||||
<div class="pb-4">Deploy any public or private Git repositories through a GitHub App.</div>
|
||||
|
||||
@if ($github_apps->count() !== 0)
|
||||
<h2 class="pt-4 pb-4">Select a Github App</h2>
|
||||
<div class="flex flex-col gap-2">
|
||||
@@ -92,6 +91,16 @@
|
||||
helper="If there is a build process involved (like Svelte, React, Next, etc..), please specify the output directory for the build assets." />
|
||||
@endif
|
||||
</div>
|
||||
@if ($build_pack === 'dockercompose')
|
||||
<x-forms.input placeholder="/" wire:model.blur="base_directory"
|
||||
label="Base Directory"
|
||||
helper="Directory to use as root. Useful for monorepos." />
|
||||
<x-forms.input placeholder="/docker-compose.yaml" id="docker_compose_location"
|
||||
label="Docker Compose Location"
|
||||
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>" />
|
||||
Compose file location in your repository:<span
|
||||
class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>
|
||||
@endif
|
||||
@if ($show_is_static)
|
||||
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static || $build_pack === 'static'"
|
||||
helper="The port your application listens on." />
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
</div>
|
||||
@if (!$branch_found)
|
||||
<div class="px-2 pt-4">
|
||||
<div class="flex flex-col pb-4">
|
||||
<div>Preselect branch (eg: main):</div>
|
||||
<div class='text-helper'>https://github.com/coollabsio/coolify-examples/tree/main</div>
|
||||
</div>
|
||||
<div>
|
||||
For example application deployments, checkout <a class="underline dark:text-white"
|
||||
href="https://github.com/coollabsio/coolify-examples/" target="_blank">Coolify
|
||||
@@ -51,6 +47,15 @@
|
||||
helper="If there is a build process involved (like Svelte, React, Next, etc..), please specify the output directory for the build assets." />
|
||||
@endif
|
||||
</div>
|
||||
@if ($build_pack === 'dockercompose')
|
||||
<x-forms.input placeholder="/" wire:model.blur="base_directory" label="Base Directory"
|
||||
helper="Directory to use as root. Useful for monorepos." />
|
||||
<x-forms.input placeholder="/docker-compose.yaml" id="docker_compose_location"
|
||||
label="Docker Compose Location"
|
||||
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>" />
|
||||
Compose file location in your repository:<span
|
||||
class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>
|
||||
@endif
|
||||
@if ($show_is_static)
|
||||
<x-forms.input type="number" id="port" label="Port" :readonly="$is_static || $build_pack === 'static'"
|
||||
helper="The port your application listens on." />
|
||||
@@ -59,10 +64,12 @@
|
||||
helper="If your application is a static site or the final build assets should be served as a static site, enable this." />
|
||||
</div>
|
||||
@endif
|
||||
@if ($build_pack === 'dockercompose' && isDev())
|
||||
<div class="dark:text-warning">If you choose Docker Compose based deployments, you cannot change it afterwards.</div>
|
||||
<x-forms.checkbox instantSave label="New Compose Services (only in dev mode)" id="new_compose_services"></x-forms.checkbox>
|
||||
@endif
|
||||
{{-- @if ($build_pack === 'dockercompose' && isDev())
|
||||
<div class="dark:text-warning">If you choose Docker Compose based deployments, you cannot
|
||||
change it afterwards.</div>
|
||||
<x-forms.checkbox instantSave label="New Compose Services (only in dev mode)"
|
||||
id="new_compose_services"></x-forms.checkbox>
|
||||
@endif --}}
|
||||
</div>
|
||||
<x-forms.button wire:click.prevent='submit'>
|
||||
Continue
|
||||
|
||||
@@ -3,11 +3,7 @@
|
||||
prevent
|
||||
name collision. <br>To see the actual volume names, check the Deployable Compose file, or go to Storage
|
||||
menu.</div>
|
||||
<div class="pb-2 w-72">
|
||||
<x-forms.checkbox label="Escape special characters in labels?"
|
||||
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
||||
id="service.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
|
||||
</div>
|
||||
|
||||
<div x-cloak x-show="raw" class="font-mono">
|
||||
<x-forms.textarea allowTab useMonacoEditor monacoEditorLanguage="yaml" rows="20"
|
||||
id="service.docker_compose_raw">
|
||||
@@ -17,6 +13,11 @@
|
||||
<x-forms.textarea rows="20" readonly id="service.docker_compose">
|
||||
</x-forms.textarea>
|
||||
</div>
|
||||
<div class="pt-2 w-72">
|
||||
<x-forms.checkbox label="Escape special characters in labels?"
|
||||
helper="By default, $ (and other chars) is escaped. So if you write $ in the labels, it will be saved as $$.<br><br>If you want to use env variables inside the labels, turn this off."
|
||||
id="service.is_container_label_escape_enabled" instantSave></x-forms.checkbox>
|
||||
</div>
|
||||
<div class="flex justify-end w-full gap-2 pt-4">
|
||||
<div class="flex items-end gap-2">
|
||||
<div x-cloak x-show="raw">
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<x-forms.checkbox id="is_multiline" label="Is Multiline?" />
|
||||
@if (!$shared)
|
||||
<x-forms.checkbox id="is_literal"
|
||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it form another value. In this case, you should set this to true."
|
||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
|
||||
label="Is Literal?" />
|
||||
@endif
|
||||
<x-forms.button type="submit" @click="slideOverOpen=false">
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
@if ($env->is_shared)
|
||||
<x-forms.checkbox instantSave id="env.is_build_time" label="Build Variable?" />
|
||||
<x-forms.checkbox instantSave id="env.is_literal"
|
||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it form another value. In this case, you should set this to true."
|
||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
|
||||
label="Is Literal?" />
|
||||
@else
|
||||
@if ($isSharedVariable)
|
||||
@@ -65,7 +65,7 @@
|
||||
<x-forms.checkbox instantSave id="env.is_multiline" label="Is Multiline?" />
|
||||
@if (!data_get($env, 'is_multiline'))
|
||||
<x-forms.checkbox instantSave id="env.is_literal"
|
||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it form another value. In this case, you should set this to true."
|
||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
|
||||
label="Is Literal?" />
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@@ -15,15 +15,17 @@
|
||||
<x-forms.input id="storage.host_path" readonly helper="Directory on the host system."
|
||||
label="Source Path"
|
||||
helper="Warning: Changing the source path after the initial start could cause problems. Only use it when you know what are you doing." />
|
||||
<x-forms.input id="storage.mount_path" label="Destination Path"
|
||||
helper="Directory inside the container." required readonly />
|
||||
@else
|
||||
<x-forms.input id="storage.host_path" helper="Directory on the host system." label="Source Path"
|
||||
helper="Warning: Changing the source path after the initial start could cause problems. Only use it when you know what are you doing." />
|
||||
<x-forms.input id="storage.mount_path" label="Destination Path"
|
||||
helper="Directory inside the container." required readonly />
|
||||
<x-forms.button type="submit">
|
||||
Update
|
||||
</x-forms.button>
|
||||
@endif
|
||||
<x-forms.input id="storage.mount_path" label="Destination Path" helper="Directory inside the container."
|
||||
required readonly />
|
||||
<x-forms.button type="submit">
|
||||
Update
|
||||
</x-forms.button>
|
||||
@else
|
||||
<x-forms.input id="storage.name" required readonly />
|
||||
<x-forms.input id="storage.host_path" readonly />
|
||||
|
||||
@@ -1,16 +1,45 @@
|
||||
<form wire:submit='createGitHubApp' class="flex flex-col w-full gap-2">
|
||||
<div class="pb-2">This is required, if you would like to get full integration (commit / pull request
|
||||
deployments, etc)
|
||||
with GitHub.</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="name" label="Name" required />
|
||||
<x-forms.input helper="If empty, your GitHub user will be used." id="organization" label="Organization" />
|
||||
<x-forms.input helper="If empty, your GitHub user will be used."
|
||||
placeholder="If empty, your GitHub user will be used." id="organization" label="Organization (on GitHub)" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="html_url" label="HTML Url" required />
|
||||
<x-forms.input id="api_url" label="API Url" required />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="custom_user" label="Custom Git User" required />
|
||||
<x-forms.input id="custom_port" type="number" label="Custom Git Port" required />
|
||||
<div x-data="{
|
||||
activeAccordion: '',
|
||||
setActiveAccordion(id) {
|
||||
this.activeAccordion = (this.activeAccordion == id) ? '' : id
|
||||
}
|
||||
}" class="relative w-full py-2 mx-auto overflow-hidden text-sm font-normal rounded-md">
|
||||
<div x-data="{ id: $id('accordion') }" class="cursor-pointer group">
|
||||
<button @click="setActiveAccordion(id)"
|
||||
class="flex items-center justify-between w-full px-1 py-2 text-left select-none hover:dark:text-white hover:bg-white/5"
|
||||
type="button">
|
||||
<h4>Advanced</h4>
|
||||
<svg class="w-4 h-4 duration-200 ease-out" :class="{ 'rotate-180': activeAccordion == id }"
|
||||
viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor"
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<div x-show="activeAccordion==id" x-collapse x-cloak class="px-2">
|
||||
<div class="py-2">Self-hosted / Enterprise GitHub details.</div>
|
||||
<div class="flex flex-col gap-2 pt-0 opacity-70">
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="html_url" label="HTML Url" required />
|
||||
<x-forms.input id="api_url" label="API Url" required />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="custom_user" label="Custom Git User" required />
|
||||
<x-forms.input id="custom_port" type="number" label="Custom Git Port" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (!isCloud())
|
||||
<x-forms.checkbox id="is_system_wide" label="System Wide" />
|
||||
@endif
|
||||
|
||||
58
templates/compose/docmost.yaml
Normal file
58
templates/compose/docmost.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
# documentation: https://docmost.com/docs/
|
||||
# slogan: Open-source collaborative wiki and documentation software
|
||||
# tags: documentation, opensource, wiki, confluence, knowledge-base, notion, realtime-collaboration, notion-alternative
|
||||
# logo: svgs/docmost.png
|
||||
# port: 3000
|
||||
|
||||
services:
|
||||
docmost:
|
||||
image: "docmost/docmost:latest"
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- SERVICE_FQDN_DOCMOST_3000
|
||||
- APP_SECRET=$SERVICE_BASE64_APPKEY
|
||||
- APP_URL=$SERVICE_FQDN_DOCMOST_3000
|
||||
- DATABASE_URL=postgresql://$SERVICE_USER_POSTGRES:$SERVICE_PASSWORD_POSTGRES@postgresql/docmost?schema=public
|
||||
- REDIS_URL=redis://redis:6379
|
||||
volumes:
|
||||
- "docmost:/app/data/storage"
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- curl
|
||||
- "-f"
|
||||
- "http://127.0.0.1:3000"
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
postgresql:
|
||||
image: "postgres:16-alpine"
|
||||
environment:
|
||||
- POSTGRES_USER=$SERVICE_USER_POSTGRES
|
||||
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
- POSTGRES_DB=docmost
|
||||
volumes:
|
||||
- "postgresql-data:/var/lib/postgresql/data"
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
redis:
|
||||
image: "redis:7.2-alpine"
|
||||
volumes:
|
||||
- "redis-data:/data"
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- redis-cli
|
||||
- PING
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
53
templates/compose/drupal-with-postgresql.yaml
Normal file
53
templates/compose/drupal-with-postgresql.yaml
Normal file
@@ -0,0 +1,53 @@
|
||||
# documentation: https://www.drupal.org/about
|
||||
# slogan: Drupal is a free and open-source web content management system written in PHP and distributed under the GNU General Public License.
|
||||
# tags: cms, blog, content, management, postgresql
|
||||
# logo: svgs/drupal.svg
|
||||
|
||||
services:
|
||||
drupal:
|
||||
image: "drupal:10-apache"
|
||||
environment:
|
||||
- SERVICE_FQDN_DRUPAL
|
||||
- DB_HOST=postgres
|
||||
- DB_NAME=postgres
|
||||
- DB_USER=postgres
|
||||
- DB_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
volumes:
|
||||
- type: volume
|
||||
source: drupal_modules
|
||||
target: /var/www/html/modules
|
||||
is_directory: true
|
||||
- type: volume
|
||||
source: drupal_profiles
|
||||
target: /var/www/html/profiles
|
||||
is_directory: true
|
||||
- type: volume
|
||||
source: drupal_themes
|
||||
target: /var/www/html/themes
|
||||
is_directory: true
|
||||
- type: volume
|
||||
source: drupal_sites
|
||||
target: /var/www/html/sites
|
||||
is_directory: true
|
||||
depends_on:
|
||||
- postgres
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- "curl -f http://localhost:80 || exit 1"
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
postgres:
|
||||
image: "postgres:16"
|
||||
environment:
|
||||
- POSTGRES_DB=postgres
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
@@ -15,7 +15,7 @@ services:
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://127.0.0.1:9000/minio/health/live"]
|
||||
test: ["CMD", "mc", "ready", "local"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
|
||||
190
templates/compose/plane.yaml
Normal file
190
templates/compose/plane.yaml
Normal file
@@ -0,0 +1,190 @@
|
||||
# documentation: https://docs.plane.so/self-hosting/methods/docker-compose
|
||||
# slogan: The open source project management tool
|
||||
# tags: plane,project-management,tool,open,source,api,nextjs,redis,postgresql,django,pm
|
||||
# logo: svgs/plane.svg
|
||||
|
||||
x-app-env: &app-env
|
||||
environment:
|
||||
- WEB_URL=http://localhost
|
||||
- DEBUG=${DEBUG:-0}
|
||||
- CORS_ALLOWED_ORIGINS=http://localhost
|
||||
# Gunicorn Workers
|
||||
- GUNICORN_WORKERS=${GUNICORN_WORKERS:-1}
|
||||
#DB SETTINGS
|
||||
- PGHOST=plane-db
|
||||
- PGDATABASE=plane
|
||||
- POSTGRES_USER=$SERVICE_USER_POSTGRES
|
||||
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
- POSTGRES_DB=plane
|
||||
- POSTGRES_PORT=5432
|
||||
- PGDATA=/var/lib/postgresql/data
|
||||
- DATABASE_URL=postgresql://$SERVICE_USER_POSTGRES:$SERVICE_PASSWORD_POSTGRES@plane-db/plane
|
||||
# REDIS SETTINGS
|
||||
- REDIS_HOST=plane-redis
|
||||
- REDIS_PORT=6379
|
||||
- REDIS_URL=${REDIS_URL:-redis://plane-redis:6379/}
|
||||
# Application secret
|
||||
- SECRET_KEY=$SERVICE_PASSWORD_64_SECRETKEY
|
||||
# DATA STORE SETTINGS
|
||||
- USE_MINIO=${USE_MINIO:-1}
|
||||
- AWS_REGION=${AWS_REGION}
|
||||
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
|
||||
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
|
||||
- AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
|
||||
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
|
||||
- MINIO_ROOT_USER=$SERVICE_USER_MINIO
|
||||
- MINIO_ROOT_PASSWORD=$SERVICE_PASSWORD_MINIO
|
||||
- BUCKET_NAME=${BUCKET_NAME:-uploads}
|
||||
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
|
||||
# Admin and Space URLs
|
||||
- ADMIN_BASE_URL=${ADMIN_BASE_URL}
|
||||
- SPACE_BASE_URL=${SPACE_BASE_URL}
|
||||
- APP_BASE_URL=${APP_BASE_URL}
|
||||
|
||||
services:
|
||||
proxy:
|
||||
environment:
|
||||
- SERVICE_FQDN_PLANE
|
||||
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
|
||||
image: makeplane/plane-proxy:stable
|
||||
depends_on:
|
||||
- web
|
||||
- api
|
||||
- space
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://127.0.0.1:80"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
|
||||
web:
|
||||
<<: *app-env
|
||||
image: makeplane/plane-frontend:stable
|
||||
command: node web/server.js web
|
||||
depends_on:
|
||||
- api
|
||||
- worker
|
||||
healthcheck:
|
||||
test: "wget -qO- http://`hostname`:3000"
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
space:
|
||||
<<: *app-env
|
||||
image: makeplane/plane-space:stable
|
||||
command: node space/server.js space
|
||||
depends_on:
|
||||
- api
|
||||
- worker
|
||||
- web
|
||||
healthcheck:
|
||||
test: ["CMD", "echo", "hey whats up"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
|
||||
admin:
|
||||
<<: *app-env
|
||||
image: makeplane/plane-admin:stable
|
||||
command: node admin/server.js admin
|
||||
depends_on:
|
||||
- api
|
||||
- web
|
||||
healthcheck:
|
||||
test: ["CMD", "echo", "hey whats up"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
|
||||
api:
|
||||
<<: *app-env
|
||||
image: makeplane/plane-backend:stable
|
||||
command: ./bin/docker-entrypoint-api.sh
|
||||
volumes:
|
||||
- logs_api:/code/plane/logs
|
||||
depends_on:
|
||||
- plane-db
|
||||
- plane-redis
|
||||
healthcheck:
|
||||
test: ["CMD", "echo", "hey whats up"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
|
||||
worker:
|
||||
<<: *app-env
|
||||
image: makeplane/plane-backend:stable
|
||||
command: ./bin/docker-entrypoint-worker.sh
|
||||
volumes:
|
||||
- logs_worker:/code/plane/logs
|
||||
depends_on:
|
||||
- api
|
||||
- plane-db
|
||||
- plane-redis
|
||||
healthcheck:
|
||||
test: ["CMD", "echo", "hey whats up"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
|
||||
beat-worker:
|
||||
<<: *app-env
|
||||
image: makeplane/plane-backend:stable
|
||||
command: ./bin/docker-entrypoint-beat.sh
|
||||
volumes:
|
||||
- logs_beat-worker:/code/plane/logs
|
||||
depends_on:
|
||||
- api
|
||||
- plane-db
|
||||
- plane-redis
|
||||
healthcheck:
|
||||
test: ["CMD", "echo", "hey whats up"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
|
||||
migrator:
|
||||
<<: *app-env
|
||||
image: makeplane/plane-backend:stable
|
||||
restart: "no"
|
||||
command: ./bin/docker-entrypoint-migrator.sh
|
||||
volumes:
|
||||
- logs_migrator:/code/plane/logs
|
||||
depends_on:
|
||||
- plane-db
|
||||
- plane-redis
|
||||
|
||||
plane-db:
|
||||
<<: *app-env
|
||||
image: postgres:15.5-alpine
|
||||
command: postgres -c 'max_connections=1000'
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
|
||||
plane-redis:
|
||||
<<: *app-env
|
||||
image: valkey/valkey:7.2.5-alpine
|
||||
volumes:
|
||||
- redisdata:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
|
||||
plane-minio:
|
||||
<<: *app-env
|
||||
image: minio/minio:latest
|
||||
command: server /export --console-address ":9090"
|
||||
volumes:
|
||||
- uploads:/export
|
||||
healthcheck:
|
||||
test: ["CMD", "mc", "ready", "local"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
@@ -53,7 +53,7 @@ services:
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://127.0.0.1:9000/minio/health/live"]
|
||||
test: ["CMD", "mc", "ready", "local"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
|
||||
37
templates/compose/vikunja-with-postgresql.yaml
Normal file
37
templates/compose/vikunja-with-postgresql.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
# documentation: https://vikunja.io
|
||||
# slogan: The open-source, self-hostable to-do app. Organize everything, on all platforms.
|
||||
# tags: productivity,todo
|
||||
# logo: svgs/vikunja.svg
|
||||
# port: 3456
|
||||
|
||||
services:
|
||||
vikunja:
|
||||
image: vikunja/vikunja
|
||||
environment:
|
||||
- SERVICE_FQDN_VIKUNJA
|
||||
- VIKUNJA_SERVICE_PUBLICURL=$SERVICE_FQDN_VIKUNJA
|
||||
- VIKUNJA_SERVICE_JWTSECRET=$SERVICE_PASSWORD_JWTSECRET
|
||||
- VIKUNJA_SERVICE_ENABLEREGISTRATION=true
|
||||
- VIKUNJA_DATABASE_TYPE=postgres
|
||||
- VIKUNJA_DATABASE_HOST=postgresql
|
||||
- VIKUNJA_DATABASE_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL}
|
||||
- VIKUNJA_DATABASE_USER=${SERVICE_USER_POSTGRESQL}
|
||||
- VIKUNJA_DATABASE_DATABASE=${POSTGRESQL_DATABASE}
|
||||
volumes:
|
||||
- vikunja-data:/app/vikunja/
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
postgresql:
|
||||
image: postgres:16-alpine
|
||||
volumes:
|
||||
- vikunja-postgresql-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_USER=${SERVICE_USER_POSTGRESQL}
|
||||
- POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL}
|
||||
- POSTGRES_DB=${POSTGRESQL_DATABASE}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
@@ -12,10 +12,16 @@ services:
|
||||
- VIKUNJA_SERVICE_PUBLICURL=$SERVICE_FQDN_VIKUNJA
|
||||
- VIKUNJA_SERVICE_JWTSECRET=$SERVICE_PASSWORD_JWTSECRET
|
||||
- VIKUNJA_SERVICE_ENABLEREGISTRATION=true
|
||||
- VIKUNJA_DATABASE_PATH=/db/vikunja.db
|
||||
- VIKUNJA_DATABASE_TYPE=sqlite
|
||||
volumes:
|
||||
- vikunja-data:/app/vikunja/
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "http://127.0.0.1:3456"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
- vikunja-sqlite-data:/db
|
||||
depends_on:
|
||||
- init
|
||||
init:
|
||||
image: busybox
|
||||
restart: no
|
||||
volumes:
|
||||
- vikunja-sqlite-data:/db
|
||||
command: ["sh", "-c", "touch /db/vikunja.db && chown -R 1000 /db"]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.313"
|
||||
"version": "4.0.0-beta.316"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user