commit
1bfce6716c
@ -6,13 +6,14 @@
|
|||||||
You can ask for guidance anytime on our
|
You can ask for guidance anytime on our
|
||||||
[Discord server](https://coollabs.io/discord) in the `#contribution` channel.
|
[Discord server](https://coollabs.io/discord) in the `#contribution` channel.
|
||||||
|
|
||||||
|
## Code Contribution
|
||||||
|
|
||||||
## 1) Setup your development environment
|
### 1) Setup your development environment
|
||||||
|
|
||||||
- You need to have Docker Engine (or equivalent) [installed](https://docs.docker.com/engine/install/) on your system.
|
- You need to have Docker Engine (or equivalent) [installed](https://docs.docker.com/engine/install/) on your system.
|
||||||
- For better DX, install [Spin](https://serversideup.net/open-source/spin/).
|
- For better DX, install [Spin](https://serversideup.net/open-source/spin/).
|
||||||
|
|
||||||
## 2) Set your environment variables
|
### 2) Set your environment variables
|
||||||
|
|
||||||
- Copy [.env.development.example](./.env.development.example) to .env.
|
- Copy [.env.development.example](./.env.development.example) to .env.
|
||||||
|
|
||||||
@ -23,9 +24,14 @@ You can ask for guidance anytime on our
|
|||||||
|
|
||||||
- Run `./scripts/run setup:dev` - This will generate a secret key for you, delete any existing database layouts, migrate database to the new layout, and seed your database.
|
- Run `./scripts/run setup:dev` - This will generate a secret key for you, delete any existing database layouts, migrate database to the new layout, and seed your database.
|
||||||
|
|
||||||
## 4) Start development
|
### 4) Start development
|
||||||
You can login your Coolify instance at `localhost:8000` with `test@example.com` and `password`.
|
You can login your Coolify instance at `localhost:8000` with `test@example.com` and `password`.
|
||||||
|
|
||||||
Your horizon (Laravel scheduler): `localhost:8000/horizon` - Only reachable if you logged in with root user.
|
Your horizon (Laravel scheduler): `localhost:8000/horizon` - Only reachable if you logged in with root user.
|
||||||
|
|
||||||
Mails are caught by Mailpit: `localhost:8025`
|
Mails are caught by Mailpit: `localhost:8025`
|
||||||
|
|
||||||
|
|
||||||
|
## New Service Contribution
|
||||||
|
Check out the docs [here](https://coolify.io/docs/how-to-add-a-service).
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ Contact us [here](https://coolify.io/docs/contact).
|
|||||||
|
|
||||||
## Recognitions
|
## Recognitions
|
||||||
|
|
||||||
|
<p>
|
||||||
<a href="https://news.ycombinator.com/item?id=26624341">
|
<a href="https://news.ycombinator.com/item?id=26624341">
|
||||||
<img
|
<img
|
||||||
style="width: 250px; height: 54px;" width="250" height="54"
|
style="width: 250px; height: 54px;" width="250" height="54"
|
||||||
@ -47,9 +48,12 @@ Contact us [here](https://coolify.io/docs/contact).
|
|||||||
src="https://hackernews-badge.vercel.app/api?id=26624341"
|
src="https://hackernews-badge.vercel.app/api?id=26624341"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
<a href="https://www.producthunt.com/posts/coolify?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-coolify" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=338273&theme=light" alt="Coolify - An open-source & self-hostable Heroku, Netlify alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
<a href="https://www.producthunt.com/posts/coolify?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-coolify" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=338273&theme=light" alt="Coolify - An open-source & self-hostable Heroku, Netlify alternative | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||||
|
|
||||||
|
<a href="https://trendshift.io/repositories/634" target="_blank"><img src="https://trendshift.io/api/badge/repositories/634" alt="coollabsio%2Fcoolify | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||||
|
|
||||||
## 💰 Financial Contributors
|
## 💰 Financial Contributors
|
||||||
|
|
||||||
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/coollabsio/contribute)]
|
Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/coollabsio/contribute)]
|
||||||
|
@ -19,13 +19,9 @@ class Kernel extends ConsoleKernel
|
|||||||
protected function schedule(Schedule $schedule): void
|
protected function schedule(Schedule $schedule): void
|
||||||
{
|
{
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
// $schedule->job(new ContainerStatusJob(Server::find(0)))->everyTenMinutes()->onOneServer();
|
$schedule->command('horizon:snapshot')->everyMinute();
|
||||||
// $schedule->command('horizon:snapshot')->everyMinute();
|
|
||||||
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer();
|
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer();
|
||||||
// $schedule->job(new CheckResaleLicenseJob)->hourly();
|
$this->check_scheduled_backups($schedule);
|
||||||
// $schedule->job(new DockerCleanupJob)->everyOddHour();
|
|
||||||
// $this->instance_auto_update($schedule);
|
|
||||||
// $this->check_scheduled_backups($schedule);
|
|
||||||
$this->check_resources($schedule);
|
$this->check_resources($schedule);
|
||||||
$this->cleanup_servers($schedule);
|
$this->cleanup_servers($schedule);
|
||||||
$this->check_scheduled_backups($schedule);
|
$this->check_scheduled_backups($schedule);
|
||||||
@ -69,7 +65,6 @@ class Kernel extends ConsoleKernel
|
|||||||
}
|
}
|
||||||
private function check_scheduled_backups($schedule)
|
private function check_scheduled_backups($schedule)
|
||||||
{
|
{
|
||||||
ray('check_scheduled_backups');
|
|
||||||
$scheduled_backups = ScheduledDatabaseBackup::all();
|
$scheduled_backups = ScheduledDatabaseBackup::all();
|
||||||
if ($scheduled_backups->isEmpty()) {
|
if ($scheduled_backups->isEmpty()) {
|
||||||
ray('no scheduled backups');
|
ray('no scheduled backups');
|
||||||
|
@ -17,6 +17,10 @@ class Dashboard extends Component
|
|||||||
$this->servers = Server::ownedByCurrentTeam()->get();
|
$this->servers = Server::ownedByCurrentTeam()->get();
|
||||||
$this->projects = Project::ownedByCurrentTeam()->get();
|
$this->projects = Project::ownedByCurrentTeam()->get();
|
||||||
}
|
}
|
||||||
|
// public function createToken() {
|
||||||
|
// $token = auth()->user()->createToken('test');
|
||||||
|
// ray($token);
|
||||||
|
// }
|
||||||
// public function getIptables()
|
// public function getIptables()
|
||||||
// {
|
// {
|
||||||
// $servers = Server::ownedByCurrentTeam()->get();
|
// $servers = Server::ownedByCurrentTeam()->get();
|
||||||
|
@ -3,12 +3,9 @@
|
|||||||
namespace App\Http\Livewire\Project\Application;
|
namespace App\Http\Livewire\Project\Application;
|
||||||
|
|
||||||
use App\Models\Application;
|
use App\Models\Application;
|
||||||
use App\Models\InstanceSettings;
|
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
use Spatie\Url\Url;
|
|
||||||
use Symfony\Component\Yaml\Yaml;
|
|
||||||
|
|
||||||
class General extends Component
|
class General extends Component
|
||||||
{
|
{
|
||||||
@ -23,6 +20,10 @@ class General extends Component
|
|||||||
public ?string $git_commit_sha = null;
|
public ?string $git_commit_sha = null;
|
||||||
public string $build_pack;
|
public string $build_pack;
|
||||||
|
|
||||||
|
public $customLabels;
|
||||||
|
public bool $labelsChanged = false;
|
||||||
|
public bool $isConfigurationChanged = false;
|
||||||
|
|
||||||
public bool $is_static;
|
public bool $is_static;
|
||||||
public bool $is_git_submodules_enabled;
|
public bool $is_git_submodules_enabled;
|
||||||
public bool $is_git_lfs_enabled;
|
public bool $is_git_lfs_enabled;
|
||||||
@ -52,6 +53,7 @@ class General extends Component
|
|||||||
'application.docker_registry_image_name' => 'nullable',
|
'application.docker_registry_image_name' => 'nullable',
|
||||||
'application.docker_registry_image_tag' => 'nullable',
|
'application.docker_registry_image_tag' => 'nullable',
|
||||||
'application.dockerfile_location' => 'nullable',
|
'application.dockerfile_location' => 'nullable',
|
||||||
|
'application.custom_labels' => 'nullable',
|
||||||
];
|
];
|
||||||
protected $validationAttributes = [
|
protected $validationAttributes = [
|
||||||
'application.name' => 'name',
|
'application.name' => 'name',
|
||||||
@ -73,19 +75,51 @@ class General extends Component
|
|||||||
'application.docker_registry_image_name' => 'Docker registry image name',
|
'application.docker_registry_image_name' => 'Docker registry image name',
|
||||||
'application.docker_registry_image_tag' => 'Docker registry image tag',
|
'application.docker_registry_image_tag' => 'Docker registry image tag',
|
||||||
'application.dockerfile_location' => 'Dockerfile location',
|
'application.dockerfile_location' => 'Dockerfile location',
|
||||||
|
'application.custom_labels' => 'Custom labels',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function updatedApplicationBuildPack(){
|
public function mount()
|
||||||
|
{
|
||||||
|
if (str($this->application->status)->startsWith('running') && is_null($this->application->config_hash)) {
|
||||||
|
$this->application->isConfigurationChanged(true);
|
||||||
|
}
|
||||||
|
$this->isConfigurationChanged = $this->application->isConfigurationChanged();
|
||||||
|
if (is_null(data_get($this->application, 'custom_labels'))) {
|
||||||
|
$this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
|
||||||
|
} else {
|
||||||
|
$this->customLabels = str($this->application->custom_labels)->replace(',', "\n");
|
||||||
|
}
|
||||||
|
if (data_get($this->application, 'settings')) {
|
||||||
|
$this->is_static = $this->application->settings->is_static;
|
||||||
|
$this->is_git_submodules_enabled = $this->application->settings->is_git_submodules_enabled;
|
||||||
|
$this->is_git_lfs_enabled = $this->application->settings->is_git_lfs_enabled;
|
||||||
|
$this->is_debug_enabled = $this->application->settings->is_debug_enabled;
|
||||||
|
$this->is_preview_deployments_enabled = $this->application->settings->is_preview_deployments_enabled;
|
||||||
|
$this->is_auto_deploy_enabled = $this->application->settings->is_auto_deploy_enabled;
|
||||||
|
$this->is_force_https_enabled = $this->application->settings->is_force_https_enabled;
|
||||||
|
}
|
||||||
|
$this->checkLabelUpdates();
|
||||||
|
}
|
||||||
|
public function updatedApplicationBuildPack()
|
||||||
|
{
|
||||||
if ($this->application->build_pack !== 'nixpacks') {
|
if ($this->application->build_pack !== 'nixpacks') {
|
||||||
$this->application->settings->is_static = $this->is_static = false;
|
$this->application->settings->is_static = $this->is_static = false;
|
||||||
$this->application->settings->save();
|
$this->application->settings->save();
|
||||||
}
|
}
|
||||||
$this->submit();
|
$this->submit();
|
||||||
}
|
}
|
||||||
|
public function checkLabelUpdates()
|
||||||
|
{
|
||||||
|
if (md5($this->application->custom_labels) !== md5(implode(",", generateLabelsApplication($this->application)))) {
|
||||||
|
$this->labelsChanged = true;
|
||||||
|
} else {
|
||||||
|
$this->labelsChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
public function instantSave()
|
public function instantSave()
|
||||||
{
|
{
|
||||||
// @TODO: find another way - if possible
|
// @TODO: find another way - if possible
|
||||||
|
$force_https = $this->application->settings->is_force_https_enabled;
|
||||||
$this->application->settings->is_static = $this->is_static;
|
$this->application->settings->is_static = $this->is_static;
|
||||||
if ($this->is_static) {
|
if ($this->is_static) {
|
||||||
$this->application->ports_exposes = 80;
|
$this->application->ports_exposes = 80;
|
||||||
@ -102,33 +136,35 @@ class General extends Component
|
|||||||
$this->application->save();
|
$this->application->save();
|
||||||
$this->application->refresh();
|
$this->application->refresh();
|
||||||
$this->emit('success', 'Application settings updated!');
|
$this->emit('success', 'Application settings updated!');
|
||||||
|
$this->checkLabelUpdates();
|
||||||
|
$this->isConfigurationChanged = $this->application->isConfigurationChanged();
|
||||||
|
if ($force_https !== $this->is_force_https_enabled) {
|
||||||
|
$this->resetDefaultLabels(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getWildcardDomain() {
|
public function getWildcardDomain()
|
||||||
|
{
|
||||||
$server = data_get($this->application, 'destination.server');
|
$server = data_get($this->application, 'destination.server');
|
||||||
if ($server) {
|
if ($server) {
|
||||||
$fqdn = generateFqdn($server, $this->application->uuid);
|
$fqdn = generateFqdn($server, $this->application->uuid);
|
||||||
ray($fqdn);
|
|
||||||
$this->application->fqdn = $fqdn;
|
$this->application->fqdn = $fqdn;
|
||||||
$this->application->save();
|
$this->application->save();
|
||||||
$this->emit('success', 'Application settings updated!');
|
$this->emit('success', 'Application settings updated!');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public function mount()
|
public function resetDefaultLabels($showToaster = true)
|
||||||
{
|
{
|
||||||
if (data_get($this->application,'settings')) {
|
$this->customLabels = str(implode(",", generateLabelsApplication($this->application)))->replace(',', "\n");
|
||||||
$this->is_static = $this->application->settings->is_static;
|
$this->submit($showToaster);
|
||||||
$this->is_git_submodules_enabled = $this->application->settings->is_git_submodules_enabled;
|
|
||||||
$this->is_git_lfs_enabled = $this->application->settings->is_git_lfs_enabled;
|
|
||||||
$this->is_debug_enabled = $this->application->settings->is_debug_enabled;
|
|
||||||
$this->is_preview_deployments_enabled = $this->application->settings->is_preview_deployments_enabled;
|
|
||||||
$this->is_auto_deploy_enabled = $this->application->settings->is_auto_deploy_enabled;
|
|
||||||
$this->is_force_https_enabled = $this->application->settings->is_force_https_enabled;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function submit()
|
public function updatedApplicationFqdn()
|
||||||
|
{
|
||||||
|
$this->resetDefaultLabels(false);
|
||||||
|
$this->emit('success', 'Labels reseted to default!');
|
||||||
|
}
|
||||||
|
public function submit($showToaster = true)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->validate();
|
$this->validate();
|
||||||
@ -156,10 +192,17 @@ class General extends Component
|
|||||||
if ($this->application->publish_directory && $this->application->publish_directory !== '/') {
|
if ($this->application->publish_directory && $this->application->publish_directory !== '/') {
|
||||||
$this->application->publish_directory = rtrim($this->application->publish_directory, '/');
|
$this->application->publish_directory = rtrim($this->application->publish_directory, '/');
|
||||||
}
|
}
|
||||||
|
if (gettype($this->customLabels) === 'string') {
|
||||||
|
$this->customLabels = str($this->customLabels)->replace(',', "\n");
|
||||||
|
}
|
||||||
|
$this->application->custom_labels = $this->customLabels->explode("\n")->implode(',');
|
||||||
$this->application->save();
|
$this->application->save();
|
||||||
$this->emit('success', 'Application settings updated!');
|
$showToaster && $this->emit('success', 'Application settings updated!');
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
return handleError($e, $this);
|
return handleError($e, $this);
|
||||||
|
} finally {
|
||||||
|
$this->checkLabelUpdates();
|
||||||
|
$this->isConfigurationChanged = $this->application->isConfigurationChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
private ApplicationPreview|null $preview = null;
|
private ApplicationPreview|null $preview = null;
|
||||||
|
|
||||||
private string $container_name;
|
private string $container_name;
|
||||||
private string|null $currently_running_container_name = null;
|
private ?string $currently_running_container_name = null;
|
||||||
private string $basedir;
|
private string $basedir;
|
||||||
private string $workdir;
|
private string $workdir;
|
||||||
private ?string $build_pack = null;
|
private ?string $build_pack = null;
|
||||||
@ -75,10 +75,12 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
private string $serverUserHomeDir = '/root';
|
private string $serverUserHomeDir = '/root';
|
||||||
private string $dockerConfigFileExists = 'NOK';
|
private string $dockerConfigFileExists = 'NOK';
|
||||||
|
|
||||||
|
private int $customPort = 22;
|
||||||
|
|
||||||
public $tries = 1;
|
public $tries = 1;
|
||||||
public function __construct(int $application_deployment_queue_id)
|
public function __construct(int $application_deployment_queue_id)
|
||||||
{
|
{
|
||||||
ray()->clearScreen();
|
// ray()->clearScreen();
|
||||||
$this->application_deployment_queue = ApplicationDeploymentQueue::find($application_deployment_queue_id);
|
$this->application_deployment_queue = ApplicationDeploymentQueue::find($application_deployment_queue_id);
|
||||||
$this->log_model = $this->application_deployment_queue;
|
$this->log_model = $this->application_deployment_queue;
|
||||||
$this->application = Application::find($this->application_deployment_queue->application_id);
|
$this->application = Application::find($this->application_deployment_queue->application_id);
|
||||||
@ -166,8 +168,16 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
|
|
||||||
// Get user home directory
|
// Get user home directory
|
||||||
$this->serverUserHomeDir = instant_remote_process(["echo \$HOME"], $this->server);
|
$this->serverUserHomeDir = instant_remote_process(["echo \$HOME"], $this->server);
|
||||||
ray("test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'");
|
|
||||||
$this->dockerConfigFileExists = instant_remote_process(["test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'"], $this->server);
|
$this->dockerConfigFileExists = instant_remote_process(["test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'"], $this->server);
|
||||||
|
|
||||||
|
// Check custom port
|
||||||
|
preg_match('/(?<=:)\d+(?=\/)/', $this->application->git_repository, $matches);
|
||||||
|
if (count($matches) === 1) {
|
||||||
|
$this->customPort = $matches[0];
|
||||||
|
$gitHost = str($this->application->git_repository)->before(':');
|
||||||
|
$gitRepo = str($this->application->git_repository)->after('/');
|
||||||
|
$this->application->git_repository = "$gitHost:$gitRepo";
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
if ($this->application->dockerfile) {
|
if ($this->application->dockerfile) {
|
||||||
$this->deploy_simple_dockerfile();
|
$this->deploy_simple_dockerfile();
|
||||||
@ -186,6 +196,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
dispatch(new ContainerStatusJob($this->server));
|
dispatch(new ContainerStatusJob($this->server));
|
||||||
}
|
}
|
||||||
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
$this->next(ApplicationDeploymentStatus::FINISHED->value);
|
||||||
|
$this->application->isConfigurationChanged(true);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
ray($e);
|
ray($e);
|
||||||
$this->fail($e);
|
$this->fail($e);
|
||||||
@ -354,14 +365,19 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
$this->execute_remote_command([
|
$this->execute_remote_command([
|
||||||
"docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
|
"docker images -q {$this->production_image_name} 2>/dev/null", "hidden" => true, "save" => "local_image_found"
|
||||||
]);
|
]);
|
||||||
if (Str::of($this->saved_outputs->get('local_image_found'))->isNotEmpty()) {
|
if (Str::of($this->saved_outputs->get('local_image_found'))->isNotEmpty() && !$this->application->isConfigurationChanged()) {
|
||||||
$this->execute_remote_command([
|
$this->execute_remote_command([
|
||||||
"echo 'Docker Image found locally with the same Git Commit SHA {$this->application->uuid}:{$this->commit}. Build step skipped...'"
|
"echo 'No configuration changed & Docker Image found locally with the same Git Commit SHA {$this->application->uuid}:{$this->commit}. Build step skipped.'",
|
||||||
]);
|
]);
|
||||||
$this->generate_compose_file();
|
$this->generate_compose_file();
|
||||||
$this->rolling_update();
|
$this->rolling_update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ($this->application->isConfigurationChanged()) {
|
||||||
|
$this->execute_remote_command([
|
||||||
|
"echo 'Configuration changed. Rebuilding image.'",
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$this->cleanup_git();
|
$this->cleanup_git();
|
||||||
$this->generate_nixpacks_confs();
|
$this->generate_nixpacks_confs();
|
||||||
@ -544,13 +560,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->application->deploymentType() === 'deploy_key') {
|
if ($this->application->deploymentType() === 'deploy_key') {
|
||||||
$port = 22;
|
|
||||||
preg_match('/(?<=:)\d+(?=\/)/', $this->application->git_repository, $matches);
|
|
||||||
if (count($matches) === 1) {
|
|
||||||
$port = $matches[0];
|
|
||||||
}
|
|
||||||
$private_key = base64_encode($this->application->private_key->private_key);
|
$private_key = base64_encode($this->application->private_key->private_key);
|
||||||
$git_clone_command = "GIT_SSH_COMMAND=\"ssh -p $port -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$this->application->git_repository} {$this->basedir}";
|
$git_clone_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$this->customPort} -o Port={$this->customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa\" {$git_clone_command} {$this->application->git_repository} {$this->basedir}";
|
||||||
$git_clone_command = $this->set_git_import_settings($git_clone_command);
|
$git_clone_command = $this->set_git_import_settings($git_clone_command);
|
||||||
$commands = collect([
|
$commands = collect([
|
||||||
executeInDocker($this->deployment_uuid, "mkdir -p /root/.ssh"),
|
executeInDocker($this->deployment_uuid, "mkdir -p /root/.ssh"),
|
||||||
@ -650,6 +661,10 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
$volume_names = $this->generate_local_persistent_volumes_only_volume_names();
|
$volume_names = $this->generate_local_persistent_volumes_only_volume_names();
|
||||||
$environment_variables = $this->generate_environment_variables($ports);
|
$environment_variables = $this->generate_environment_variables($ports);
|
||||||
|
|
||||||
|
$labels = generateLabelsApplication($this->application, $this->preview);
|
||||||
|
if (data_get($this->application, 'custom_labels')) {
|
||||||
|
$labels = str($this->application->custom_labels)->explode(',')->toArray();
|
||||||
|
}
|
||||||
$docker_compose = [
|
$docker_compose = [
|
||||||
'version' => '3.8',
|
'version' => '3.8',
|
||||||
'services' => [
|
'services' => [
|
||||||
@ -658,7 +673,7 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
'container_name' => $this->container_name,
|
'container_name' => $this->container_name,
|
||||||
'restart' => RESTART_MODE,
|
'restart' => RESTART_MODE,
|
||||||
'environment' => $environment_variables,
|
'environment' => $environment_variables,
|
||||||
'labels' => generateLabelsApplication($this->application, $this->preview, $ports),
|
'labels' => $labels,
|
||||||
'expose' => $ports,
|
'expose' => $ports,
|
||||||
'networks' => [
|
'networks' => [
|
||||||
$this->destination->network,
|
$this->destination->network,
|
||||||
|
@ -12,7 +12,6 @@ use App\Notifications\Server\Revived;
|
|||||||
use App\Notifications\Server\Unreachable;
|
use App\Notifications\Server\Unreachable;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
@ -25,30 +24,23 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
{
|
{
|
||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
public $tries = 1;
|
|
||||||
public $timeout = 120;
|
|
||||||
|
|
||||||
public function middleware(): array
|
|
||||||
{
|
|
||||||
return [(new WithoutOverlapping($this->server->uuid))->dontRelease()];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function uniqueId(): string
|
|
||||||
{
|
|
||||||
return $this->server->uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __construct(public Server $server)
|
public function __construct(public Server $server)
|
||||||
{
|
{
|
||||||
if (isDev()) {
|
|
||||||
$this->handle();
|
|
||||||
}
|
}
|
||||||
|
public function middleware(): array
|
||||||
|
{
|
||||||
|
return [(new WithoutOverlapping($this->server->id))->dontRelease()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle()
|
public function uniqueId(): int
|
||||||
{
|
{
|
||||||
|
return $this->server->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
ray("checking server status for {$this->server->id}");
|
||||||
try {
|
try {
|
||||||
// ray("checking server status for {$this->server->id}");
|
|
||||||
// ray()->clearAll();
|
// ray()->clearAll();
|
||||||
$serverUptimeCheckNumber = $this->server->unreachable_count;
|
$serverUptimeCheckNumber = $this->server->unreachable_count;
|
||||||
$serverUptimeCheckNumberMax = 3;
|
$serverUptimeCheckNumberMax = 3;
|
||||||
@ -129,7 +121,6 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
ray($e);
|
ray($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
|
$this->server->proxy->status = data_get($foundProxyContainer, 'State.Status');
|
||||||
$this->server->save();
|
$this->server->save();
|
||||||
@ -308,7 +299,7 @@ class ContainerStatusJob implements ShouldQueue, ShouldBeEncrypted
|
|||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
send_internal_notification('ContainerStatusJob failed with: ' . $e->getMessage());
|
send_internal_notification('ContainerStatusJob failed with: ' . $e->getMessage());
|
||||||
ray($e->getMessage());
|
ray($e->getMessage());
|
||||||
return handleError($e);
|
handleError($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,4 +277,31 @@ class Application extends BaseModel
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
public function isConfigurationChanged($save = false)
|
||||||
|
{
|
||||||
|
$newConfigHash = $this->fqdn . $this->git_repository . $this->git_branch . $this->git_commit_sha . $this->build_pack . $this->static_image . $this->install_command . $this->build_command . $this->start_command . $this->port_exposes . $this->port_mappings . $this->base_directory . $this->publish_directory . $this->health_check_path . $this->health_check_port . $this->health_check_host . $this->health_check_method . $this->health_check_return_code . $this->health_check_scheme . $this->health_check_response_text . $this->health_check_interval . $this->health_check_timeout . $this->health_check_retries . $this->health_check_start_period . $this->health_check_enabled . $this->limits_memory . $this->limits_swap . $this->limits_swappiness . $this->limits_reservation . $this->limits_cpus . $this->limits_cpuset . $this->limits_cpu_shares . $this->dockerfile . $this->dockerfile_location . $this->custom_labels;
|
||||||
|
if ($this->pull_request_id === 0) {
|
||||||
|
$newConfigHash .= json_encode($this->environment_variables->all());
|
||||||
|
} else {
|
||||||
|
$newConfigHash .= json_encode($this->environment_variables_preview->all());
|
||||||
|
}
|
||||||
|
$newConfigHash = md5($newConfigHash);
|
||||||
|
$oldConfigHash = data_get($this, 'config_hash');
|
||||||
|
if ($oldConfigHash === null) {
|
||||||
|
if ($save) {
|
||||||
|
$this->config_hash = $newConfigHash;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ($oldConfigHash === $newConfigHash) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if ($save) {
|
||||||
|
$this->config_hash = $newConfigHash;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
15
app/Models/PersonalAccessToken.php
Normal file
15
app/Models/PersonalAccessToken.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;
|
||||||
|
|
||||||
|
class PersonalAccessToken extends SanctumPersonalAccessToken
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'name',
|
||||||
|
'token',
|
||||||
|
'abilities',
|
||||||
|
'expires_at',
|
||||||
|
'team_id',
|
||||||
|
];
|
||||||
|
}
|
@ -50,7 +50,7 @@ class Service extends BaseModel
|
|||||||
|
|
||||||
public function documentation()
|
public function documentation()
|
||||||
{
|
{
|
||||||
$services = Cache::get('services', []);
|
$services = getServiceTemplates();
|
||||||
$service = data_get($services, Str::of($this->name)->beforeLast('-')->value, []);
|
$service = data_get($services, Str::of($this->name)->beforeLast('-')->value, []);
|
||||||
return data_get($service, 'documentation', config('constants.docs.base_url'));
|
return data_get($service, 'documentation', config('constants.docs.base_url'));
|
||||||
}
|
}
|
||||||
@ -538,7 +538,7 @@ class Service extends BaseModel
|
|||||||
$serviceLabels = $serviceLabels->merge($defaultLabels);
|
$serviceLabels = $serviceLabels->merge($defaultLabels);
|
||||||
if (!$isDatabase && $fqdns->count() > 0) {
|
if (!$isDatabase && $fqdns->count() > 0) {
|
||||||
if ($fqdns) {
|
if ($fqdns) {
|
||||||
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($fqdns, true));
|
$serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($this->uuid, $fqdns, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
data_set($service, 'labels', $serviceLabels->toArray());
|
data_set($service, 'labels', $serviceLabels->toArray());
|
||||||
|
@ -4,6 +4,7 @@ namespace App\Models;
|
|||||||
|
|
||||||
use App\Notifications\Channels\SendsEmail;
|
use App\Notifications\Channels\SendsEmail;
|
||||||
use App\Notifications\TransactionalEmails\ResetPassword as TransactionalEmailsResetPassword;
|
use App\Notifications\TransactionalEmails\ResetPassword as TransactionalEmailsResetPassword;
|
||||||
|
use DateTimeInterface;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
use Illuminate\Notifications\Messages\MailMessage;
|
||||||
@ -14,6 +15,8 @@ use Illuminate\Support\Facades\Config;
|
|||||||
use Illuminate\Support\Facades\URL;
|
use Illuminate\Support\Facades\URL;
|
||||||
use Laravel\Fortify\TwoFactorAuthenticatable;
|
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||||
use Laravel\Sanctum\HasApiTokens;
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
|
use Laravel\Sanctum\NewAccessToken;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
class User extends Authenticatable implements SendsEmail
|
class User extends Authenticatable implements SendsEmail
|
||||||
{
|
{
|
||||||
@ -47,7 +50,26 @@ class User extends Authenticatable implements SendsEmail
|
|||||||
$user->teams()->attach($new_team, ['role' => 'owner']);
|
$user->teams()->attach($new_team, ['role' => 'owner']);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
public function createToken(string $name, array $abilities = ['*'], DateTimeInterface $expiresAt = null)
|
||||||
|
{
|
||||||
|
ray('asd');
|
||||||
|
$plainTextToken = sprintf(
|
||||||
|
'%s%s%s',
|
||||||
|
config('sanctum.token_prefix', ''),
|
||||||
|
$tokenEntropy = Str::random(40),
|
||||||
|
hash('crc32b', $tokenEntropy)
|
||||||
|
);
|
||||||
|
|
||||||
|
$token = $this->tokens()->create([
|
||||||
|
'name' => $name,
|
||||||
|
'token' => hash('sha256', $plainTextToken),
|
||||||
|
'abilities' => $abilities,
|
||||||
|
'expires_at' => $expiresAt,
|
||||||
|
'team_id' => session('currentTeam')->id
|
||||||
|
]);
|
||||||
|
|
||||||
|
return new NewAccessToken($token, $token->getKey().'|'.$plainTextToken);
|
||||||
|
}
|
||||||
public function teams()
|
public function teams()
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Team::class)->withPivot('role');
|
return $this->belongsToMany(Team::class)->withPivot('role');
|
||||||
|
@ -30,7 +30,12 @@ class EmailChannel
|
|||||||
);
|
);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
ray($e->getMessage());
|
ray($e->getMessage());
|
||||||
send_internal_notification("EmailChannel error: {$e->getMessage()}. Failed to send email to: " . implode(', ', $recepients) . " with subject: {$mailMessage->subject}");
|
$message = "EmailChannel error: {$e->getMessage()}. Failed to send email to:";
|
||||||
|
if (isset($recepients)) {
|
||||||
|
$message .= implode(', ', $recepients);
|
||||||
|
}
|
||||||
|
$message .= " with subject: {$mailMessage->subject}";
|
||||||
|
send_internal_notification($message);
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ namespace App\Providers;
|
|||||||
|
|
||||||
use Illuminate\Support\Facades\Http;
|
use Illuminate\Support\Facades\Http;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Laravel\Sanctum\Sanctum;
|
||||||
|
use App\Models\PersonalAccessToken;
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
class AppServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
@ -13,6 +15,8 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
|
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
|
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
|
||||||
|
|
||||||
Http::macro('github', function (string $api_url, string|null $github_access_token = null) {
|
Http::macro('github', function (string $api_url, string|null $github_access_token = null) {
|
||||||
if ($github_access_token) {
|
if ($github_access_token) {
|
||||||
return Http::withHeaders([
|
return Http::withHeaders([
|
||||||
|
@ -147,12 +147,11 @@ function defaultLabels($id, $name, $pull_request_id = 0, string $type = 'applica
|
|||||||
}
|
}
|
||||||
return $labels;
|
return $labels;
|
||||||
}
|
}
|
||||||
function fqdnLabelsForTraefik(Collection $domains, bool $is_force_https_enabled, $onlyPort = null)
|
function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled, $onlyPort = null)
|
||||||
{
|
{
|
||||||
$labels = collect([]);
|
$labels = collect([]);
|
||||||
$labels->push('traefik.enable=true');
|
$labels->push('traefik.enable=true');
|
||||||
foreach ($domains as $domain) {
|
foreach ($domains as $loop => $domain) {
|
||||||
$uuid = (string)new Cuid2(7);
|
|
||||||
$url = Url::fromString($domain);
|
$url = Url::fromString($domain);
|
||||||
$host = $url->getHost();
|
$host = $url->getHost();
|
||||||
$path = $url->getPath();
|
$path = $url->getPath();
|
||||||
@ -161,8 +160,8 @@ function fqdnLabelsForTraefik(Collection $domains, bool $is_force_https_enabled,
|
|||||||
if (is_null($port) && !is_null($onlyPort)) {
|
if (is_null($port) && !is_null($onlyPort)) {
|
||||||
$port = $onlyPort;
|
$port = $onlyPort;
|
||||||
}
|
}
|
||||||
$http_label = "{$uuid}-http";
|
$http_label = "{$uuid}-{$loop}-http";
|
||||||
$https_label = "{$uuid}-https";
|
$https_label = "{$uuid}-{$loop}-https";
|
||||||
|
|
||||||
if ($schema === 'https') {
|
if ($schema === 'https') {
|
||||||
// Set labels for https
|
// Set labels for https
|
||||||
@ -205,20 +204,21 @@ function fqdnLabelsForTraefik(Collection $domains, bool $is_force_https_enabled,
|
|||||||
|
|
||||||
return $labels;
|
return $labels;
|
||||||
}
|
}
|
||||||
function generateLabelsApplication(Application $application, ?ApplicationPreview $preview = null, $ports): array
|
function generateLabelsApplication(Application $application, ?ApplicationPreview $preview = null): array
|
||||||
{
|
{
|
||||||
|
$ports = $application->settings->is_static ? [80] : $application->ports_exposes_array;
|
||||||
$onlyPort = null;
|
$onlyPort = null;
|
||||||
if (count($ports) === 1) {
|
if (count($ports) === 1) {
|
||||||
$onlyPort = $ports[0];
|
$onlyPort = $ports[0];
|
||||||
}
|
}
|
||||||
$pull_request_id = data_get($preview, 'pull_request_id', 0);
|
$pull_request_id = data_get($preview, 'pull_request_id', 0);
|
||||||
$container_name = generateApplicationContainerName($application, $pull_request_id);
|
// $container_name = generateApplicationContainerName($application, $pull_request_id);
|
||||||
$appId = $application->id;
|
$appId = $application->id;
|
||||||
if ($pull_request_id !== 0 && $pull_request_id !== null) {
|
if ($pull_request_id !== 0 && $pull_request_id !== null) {
|
||||||
$appId = $appId . '-pr-' . $pull_request_id;
|
$appId = $appId . '-pr-' . $pull_request_id;
|
||||||
}
|
}
|
||||||
$labels = collect([]);
|
$labels = collect([]);
|
||||||
$labels = $labels->merge(defaultLabels($appId, $container_name, $pull_request_id));
|
$labels = $labels->merge(defaultLabels($appId, $application->uuid, $pull_request_id));
|
||||||
if ($application->fqdn) {
|
if ($application->fqdn) {
|
||||||
if ($pull_request_id !== 0) {
|
if ($pull_request_id !== 0) {
|
||||||
$domains = Str::of(data_get($preview, 'fqdn'))->explode(',');
|
$domains = Str::of(data_get($preview, 'fqdn'))->explode(',');
|
||||||
@ -226,7 +226,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview
|
|||||||
$domains = Str::of(data_get($application, 'fqdn'))->explode(',');
|
$domains = Str::of(data_get($application, 'fqdn'))->explode(',');
|
||||||
}
|
}
|
||||||
// Add Traefik labels no matter which proxy is selected
|
// Add Traefik labels no matter which proxy is selected
|
||||||
$labels = $labels->merge(fqdnLabelsForTraefik($domains, $application->settings->is_force_https_enabled,$onlyPort));
|
$labels = $labels->merge(fqdnLabelsForTraefik($application->uuid, $domains, $application->settings->is_force_https_enabled, $onlyPort));
|
||||||
}
|
}
|
||||||
return $labels->all();
|
return $labels->all();
|
||||||
}
|
}
|
||||||
|
@ -210,13 +210,13 @@ return [
|
|||||||
'production' => [
|
'production' => [
|
||||||
's6' => [
|
's6' => [
|
||||||
'autoScalingStrategy' => 'size',
|
'autoScalingStrategy' => 'size',
|
||||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10),
|
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
|
||||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
],
|
],
|
||||||
'long-running' => [
|
'long-running' => [
|
||||||
'autoScalingStrategy' => 'size',
|
'autoScalingStrategy' => 'size',
|
||||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10),
|
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
|
||||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
],
|
],
|
||||||
@ -225,13 +225,13 @@ return [
|
|||||||
'local' => [
|
'local' => [
|
||||||
's6' => [
|
's6' => [
|
||||||
'autoScalingStrategy' => 'size',
|
'autoScalingStrategy' => 'size',
|
||||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10),
|
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
|
||||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
],
|
],
|
||||||
'long-running' => [
|
'long-running' => [
|
||||||
'autoScalingStrategy' => 'size',
|
'autoScalingStrategy' => 'size',
|
||||||
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 10),
|
'maxProcesses' => env('HORIZON_MAX_PROCESSES', 2),
|
||||||
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
'balanceMaxShift' => env('HORIZON_BALANCE_MAX_SHIFT', 1),
|
||||||
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
'balanceCooldown' => env('HORIZON_BALANCE_COOLDOWN', 1),
|
||||||
],
|
],
|
||||||
|
@ -7,7 +7,7 @@ return [
|
|||||||
|
|
||||||
// The release version of your application
|
// The release version of your application
|
||||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||||
'release' => '4.0.0-beta.92',
|
'release' => '4.0.0-beta.97',
|
||||||
// When left empty or `null` the Laravel environment will be used
|
// When left empty or `null` the Laravel environment will be used
|
||||||
'environment' => config('app.env'),
|
'environment' => config('app.env'),
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
return '4.0.0-beta.92';
|
return '4.0.0-beta.97';
|
||||||
|
@ -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('applications', function (Blueprint $table) {
|
||||||
|
$table->text('custom_labels')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('applications', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('custom_labels');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
@ -27,6 +27,7 @@ services:
|
|||||||
- QUEUE_CONNECTION
|
- QUEUE_CONNECTION
|
||||||
- REDIS_HOST
|
- REDIS_HOST
|
||||||
- REDIS_PASSWORD
|
- REDIS_PASSWORD
|
||||||
|
- HORIZON_MAX_PROCESSES
|
||||||
- SSL_MODE=off
|
- SSL_MODE=off
|
||||||
- PHP_PM_CONTROL=dynamic
|
- PHP_PM_CONTROL=dynamic
|
||||||
- PHP_PM_START_SERVERS=1
|
- PHP_PM_START_SERVERS=1
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
services:
|
|
||||||
uptime-kuma:
|
|
||||||
image: louislam/uptime-kuma:1
|
|
||||||
volumes:
|
|
||||||
- uptime-kuma:/app/data
|
|
@ -23,7 +23,7 @@
|
|||||||
@if ($projects->count() === 1)
|
@if ($projects->count() === 1)
|
||||||
<div class="grid grid-cols-1 gap-2">
|
<div class="grid grid-cols-1 gap-2">
|
||||||
@else
|
@else
|
||||||
<div class="grid grid-cols-3 gap-2">
|
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||||
@endif
|
@endif
|
||||||
@foreach ($projects as $project)
|
@foreach ($projects as $project)
|
||||||
<div class="gap-2 border border-transparent cursor-pointer box group" x-data
|
<div class="gap-2 border border-transparent cursor-pointer box group" x-data
|
||||||
@ -62,7 +62,7 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@if ($projects->count() > 0)
|
@if ($projects->count() > 0)
|
||||||
<h3 class="pb-4">Servers</h3>
|
<h3 class="py-4">Servers</h3>
|
||||||
@endif
|
@endif
|
||||||
@if ($servers->count() === 1)
|
@if ($servers->count() === 1)
|
||||||
<div class="grid grid-cols-1 gap-2">
|
<div class="grid grid-cols-1 gap-2">
|
||||||
@ -97,7 +97,9 @@
|
|||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
{{-- <h3 class="py-4">Tokens</h3>
|
||||||
|
{{auth()->user()->tokens}}
|
||||||
|
<x-forms.button wire:click='createToken'>Create Token</x-forms.button> --}}
|
||||||
<script>
|
<script>
|
||||||
function gotoProject(uuid, environment = 'production') {
|
function gotoProject(uuid, environment = 'production') {
|
||||||
window.location.href = '/project/' + uuid + '/' + environment;
|
window.location.href = '/project/' + uuid + '/' + environment;
|
||||||
|
@ -5,8 +5,12 @@
|
|||||||
<x-forms.button type="submit">
|
<x-forms.button type="submit">
|
||||||
Save
|
Save
|
||||||
</x-forms.button>
|
</x-forms.button>
|
||||||
|
@if ($isConfigurationChanged && !is_null($application->config_hash))
|
||||||
|
<div class="font-bold text-warning">Configuration not applied to the running application. You need to
|
||||||
|
redeploy.</div>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="">General configuration for your application.</div>
|
<div>General configuration for your application.</div>
|
||||||
<div class="flex flex-col gap-2 py-4">
|
<div class="flex flex-col gap-2 py-4">
|
||||||
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
<div class="flex flex-col items-end gap-2 xl:flex-row">
|
||||||
<x-forms.input id="application.name" label="Name" required />
|
<x-forms.input id="application.name" label="Name" required />
|
||||||
@ -81,7 +85,6 @@
|
|||||||
@if ($application->dockerfile)
|
@if ($application->dockerfile)
|
||||||
<x-forms.textarea label="Dockerfile" id="application.dockerfile" rows="6"> </x-forms.textarea>
|
<x-forms.textarea label="Dockerfile" id="application.dockerfile" rows="6"> </x-forms.textarea>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<h3>Network</h3>
|
<h3>Network</h3>
|
||||||
<div class="flex flex-col gap-2 xl:flex-row">
|
<div class="flex flex-col gap-2 xl:flex-row">
|
||||||
@if ($application->settings->is_static)
|
@if ($application->settings->is_static)
|
||||||
@ -93,6 +96,12 @@
|
|||||||
<x-forms.input placeholder="3000:3000" id="application.ports_mappings" label="Ports Mappings"
|
<x-forms.input placeholder="3000:3000" id="application.ports_mappings" label="Ports Mappings"
|
||||||
helper="A comma separated list of ports you would like to map to the host system. Useful when you do not want to use domains.<br><br><span class='inline-block font-bold text-warning'>Example:</span><br>3000:3000,3002:3002<br><br>Rolling update is not supported if you have a port mapped to the host." />
|
helper="A comma separated list of ports you would like to map to the host system. Useful when you do not want to use domains.<br><br><span class='inline-block font-bold text-warning'>Example:</span><br>3000:3000,3002:3002<br><br>Rolling update is not supported if you have a port mapped to the host." />
|
||||||
</div>
|
</div>
|
||||||
|
@if ($labelsChanged)
|
||||||
|
<x-forms.textarea label="Custom Labels" rows="15" id="customLabels"></x-forms.textarea>
|
||||||
|
@else
|
||||||
|
<x-forms.textarea label="Coolify Generated Labels" rows="15" id="customLabels"></x-forms.textarea>
|
||||||
|
@endif
|
||||||
|
<x-forms.button wire:click="resetDefaultLabels">Reset to Coolify Generated Labels</x-forms.button>
|
||||||
</div>
|
</div>
|
||||||
<h3>Advanced</h3>
|
<h3>Advanced</h3>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
|
@ -46,9 +46,11 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
@if (Str::of(data_get($application, 'status'))->startsWith('running'))
|
@if (Str::of(data_get($application, 'status'))->startsWith('running'))
|
||||||
<div class="absolute bg-green-400 -top-1 -left-1 badge badge-xs"></div>
|
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||||
@elseif (Str::of(data_get($application, 'status'))->startsWith('exited'))
|
@elseif (Str::of(data_get($application, 'status'))->startsWith('exited'))
|
||||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||||
|
@elseif (Str::of(data_get($application, 'status'))->startsWith('restarting'))
|
||||||
|
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||||
@endif
|
@endif
|
||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -60,9 +62,11 @@
|
|||||||
<div class="text-xs text-gray-400 group-hover:text-white">{{ $database->description }}</div>
|
<div class="text-xs text-gray-400 group-hover:text-white">{{ $database->description }}</div>
|
||||||
</div>
|
</div>
|
||||||
@if (Str::of(data_get($database, 'status'))->startsWith('running'))
|
@if (Str::of(data_get($database, 'status'))->startsWith('running'))
|
||||||
<div class="absolute bg-green-400 -top-1 -left-1 badge badge-xs"></div>
|
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||||
@elseif (Str::of(data_get($database, 'status'))->startsWith('exited'))
|
@elseif (Str::of(data_get($database, 'status'))->startsWith('exited'))
|
||||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||||
|
@elseif (Str::of(data_get($database, 'status'))->startsWith('restaring'))
|
||||||
|
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||||
@endif
|
@endif
|
||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
@ -74,9 +78,9 @@
|
|||||||
<div class="text-xs text-gray-400 group-hover:text-white">{{ $service->description }}</div>
|
<div class="text-xs text-gray-400 group-hover:text-white">{{ $service->description }}</div>
|
||||||
</div>
|
</div>
|
||||||
@if (Str::of(serviceStatus($service))->startsWith('running'))
|
@if (Str::of(serviceStatus($service))->startsWith('running'))
|
||||||
<div class="absolute bg-green-400 -top-1 -left-1 badge badge-xs"></div>
|
<div class="absolute bg-success -top-1 -left-1 badge badge-xs"></div>
|
||||||
@elseif (Str::of(serviceStatus($service))->startsWith('degraded'))
|
@elseif (Str::of(serviceStatus($service))->startsWith('degraded'))
|
||||||
<div class="absolute bg-yellow-400 -top-1 -left-1 badge badge-xs"></div>
|
<div class="absolute bg-warning -top-1 -left-1 badge badge-xs"></div>
|
||||||
@elseif (Str::of(serviceStatus($service))->startsWith('exited'))
|
@elseif (Str::of(serviceStatus($service))->startsWith('exited'))
|
||||||
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
<div class="absolute bg-error -top-1 -left-1 badge badge-xs"></div>
|
||||||
@endif
|
@endif
|
||||||
|
15
templates/compose/appsmith.yaml
Normal file
15
templates/compose/appsmith.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# documentation: https://docs.appsmith.com
|
||||||
|
# slogan: Appsmith is an open-source, self-hosted application development platform that enables you to build powerful web applications with ease.
|
||||||
|
|
||||||
|
services:
|
||||||
|
appsmith:
|
||||||
|
image: index.docker.io/appsmith/appsmith-ce
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN
|
||||||
|
- APPSMITH_MAIL_ENABLED=false
|
||||||
|
- APPSMITH_DISABLE_TELEMETRY=true
|
||||||
|
- APPSMITH_DISABLE_INTERCOM=true
|
||||||
|
- APPSMITH_SENTRY_DSN=
|
||||||
|
- APPSMITH_SMART_LOOK_ID=
|
||||||
|
volumes:
|
||||||
|
- stacks-data:/appsmith-stacks
|
107
templates/compose/appwrite.env
Normal file
107
templates/compose/appwrite.env
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
_APP_ENV=production
|
||||||
|
_APP_LOCALE=en
|
||||||
|
_APP_OPTIONS_ABUSE=enabled
|
||||||
|
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||||
|
_APP_OPENSSL_KEY_V1=
|
||||||
|
_APP_DOMAIN_FUNCTIONS=
|
||||||
|
_APP_CONSOLE_WHITELIST_ROOT=enabled
|
||||||
|
_APP_CONSOLE_WHITELIST_EMAILS=
|
||||||
|
_APP_CONSOLE_WHITELIST_IPS=
|
||||||
|
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
||||||
|
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
|
||||||
|
_APP_SYSTEM_RESPONSE_FORMAT=
|
||||||
|
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=certs@appwrite.io
|
||||||
|
_APP_USAGE_STATS=enabled
|
||||||
|
_APP_LOGGING_PROVIDER=
|
||||||
|
_APP_LOGGING_CONFIG=
|
||||||
|
_APP_USAGE_AGGREGATION_INTERVAL=30
|
||||||
|
_APP_USAGE_TIMESERIES_INTERVAL=30
|
||||||
|
_APP_USAGE_DATABASE_INTERVAL=900
|
||||||
|
_APP_WORKER_PER_CORE=6
|
||||||
|
_APP_REDIS_HOST=redis
|
||||||
|
_APP_REDIS_PORT=6379
|
||||||
|
_APP_REDIS_USER=
|
||||||
|
_APP_REDIS_PASS=
|
||||||
|
_APP_DB_HOST=mariadb
|
||||||
|
_APP_DB_PORT=3306
|
||||||
|
_APP_DB_SCHEMA=appwrite
|
||||||
|
_APP_DB_USER=$SERVICE_USER_MYSQL
|
||||||
|
_APP_DB_PASS=$SERVICE_PASSWORD_MYSQL
|
||||||
|
_APP_DB_ROOT_PASS=$SERVICE_PASSWORD_ROOTMYSQL
|
||||||
|
_APP_INFLUXDB_HOST=influxdb
|
||||||
|
_APP_INFLUXDB_PORT=8086
|
||||||
|
_APP_STATSD_HOST=telegraf
|
||||||
|
_APP_STATSD_PORT=8125
|
||||||
|
_APP_SMTP_HOST=
|
||||||
|
_APP_SMTP_PORT=
|
||||||
|
_APP_SMTP_SECURE=
|
||||||
|
_APP_SMTP_USERNAME=
|
||||||
|
_APP_SMTP_PASSWORD=
|
||||||
|
_APP_SMS_PROVIDER=
|
||||||
|
_APP_SMS_FROM=
|
||||||
|
_APP_STORAGE_LIMIT=30000000
|
||||||
|
_APP_STORAGE_PREVIEW_LIMIT=20000000
|
||||||
|
_APP_STORAGE_ANTIVIRUS=disabled
|
||||||
|
_APP_STORAGE_ANTIVIRUS_HOST=clamav
|
||||||
|
_APP_STORAGE_ANTIVIRUS_PORT=3310
|
||||||
|
_APP_STORAGE_DEVICE=local
|
||||||
|
_APP_STORAGE_S3_ACCESS_KEY=
|
||||||
|
_APP_STORAGE_S3_SECRET=
|
||||||
|
_APP_STORAGE_S3_REGION=us-east-1
|
||||||
|
_APP_STORAGE_S3_BUCKET=
|
||||||
|
_APP_STORAGE_DO_SPACES_ACCESS_KEY=
|
||||||
|
_APP_STORAGE_DO_SPACES_SECRET=
|
||||||
|
_APP_STORAGE_DO_SPACES_REGION=us-east-1
|
||||||
|
_APP_STORAGE_DO_SPACES_BUCKET=
|
||||||
|
_APP_STORAGE_BACKBLAZE_ACCESS_KEY=
|
||||||
|
_APP_STORAGE_BACKBLAZE_SECRET=
|
||||||
|
_APP_STORAGE_BACKBLAZE_REGION=us-west-004
|
||||||
|
_APP_STORAGE_BACKBLAZE_BUCKET=
|
||||||
|
_APP_STORAGE_LINODE_ACCESS_KEY=
|
||||||
|
_APP_STORAGE_LINODE_SECRET=
|
||||||
|
_APP_STORAGE_LINODE_REGION=eu-central-1
|
||||||
|
_APP_STORAGE_LINODE_BUCKET=
|
||||||
|
_APP_STORAGE_WASABI_ACCESS_KEY=
|
||||||
|
_APP_STORAGE_WASABI_SECRET=
|
||||||
|
_APP_STORAGE_WASABI_REGION=eu-central-1
|
||||||
|
_APP_STORAGE_WASABI_BUCKET=
|
||||||
|
_APP_FUNCTIONS_SIZE_LIMIT=30000000
|
||||||
|
_APP_FUNCTIONS_TIMEOUT=900
|
||||||
|
_APP_FUNCTIONS_BUILD_TIMEOUT=900
|
||||||
|
_APP_FUNCTIONS_CONTAINERS=10
|
||||||
|
_APP_FUNCTIONS_CPUS=0
|
||||||
|
_APP_FUNCTIONS_MEMORY=0
|
||||||
|
_APP_FUNCTIONS_MEMORY_SWAP=0
|
||||||
|
_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0
|
||||||
|
_APP_EXECUTOR_SECRET=your-secret-key
|
||||||
|
_APP_EXECUTOR_HOST=http://appwrite-executor/v1
|
||||||
|
_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes
|
||||||
|
_APP_FUNCTIONS_ENVS=node-16.0,php-7.4,python-3.9,ruby-3.0
|
||||||
|
_APP_FUNCTIONS_INACTIVE_THRESHOLD=60
|
||||||
|
DOCKERHUB_PULL_USERNAME=
|
||||||
|
DOCKERHUB_PULL_PASSWORD=
|
||||||
|
DOCKERHUB_PULL_EMAIL=
|
||||||
|
OPEN_RUNTIMES_NETWORK=appwrite_runtimes
|
||||||
|
_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes
|
||||||
|
_APP_DOCKER_HUB_USERNAME=
|
||||||
|
_APP_DOCKER_HUB_PASSWORD=
|
||||||
|
_APP_FUNCTIONS_MAINTENANCE_INTERVAL=3600
|
||||||
|
_APP_VCS_GITHUB_APP_NAME=
|
||||||
|
_APP_VCS_GITHUB_PRIVATE_KEY=
|
||||||
|
_APP_VCS_GITHUB_APP_ID=
|
||||||
|
_APP_VCS_GITHUB_CLIENT_ID=
|
||||||
|
_APP_VCS_GITHUB_CLIENT_SECRET=
|
||||||
|
_APP_VCS_GITHUB_WEBHOOK_SECRET=
|
||||||
|
_APP_MAINTENANCE_INTERVAL=86400
|
||||||
|
_APP_MAINTENANCE_RETENTION_CACHE=2592000
|
||||||
|
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
|
||||||
|
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
|
||||||
|
_APP_MAINTENANCE_RETENTION_ABUSE=86400
|
||||||
|
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
|
||||||
|
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
|
||||||
|
_APP_GRAPHQL_MAX_BATCH_SIZE=10
|
||||||
|
_APP_GRAPHQL_MAX_COMPLEXITY=250
|
||||||
|
_APP_GRAPHQL_MAX_DEPTH=3
|
||||||
|
_APP_MIGRATIONS_FIREBASE_CLIENT_ID=
|
||||||
|
_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=
|
||||||
|
_APP_ASSISTANT_OPENAI_API_KEY=
|
@ -1,20 +1,18 @@
|
|||||||
|
# documentation: https://appwrite.io/docs
|
||||||
|
# slogan: Appwrite is a self-hosted backend-as-a-service platform that simplifies the development of web and mobile applications by providing a range of features and APIs.
|
||||||
|
|
||||||
|
|
||||||
x-logging: &x-logging
|
x-logging: &x-logging
|
||||||
logging:
|
logging:
|
||||||
driver: 'json-file'
|
driver: 'json-file'
|
||||||
options:
|
options:
|
||||||
max-file: '5'
|
max-file: '5'
|
||||||
max-size: '10m'
|
max-size: '10m'
|
||||||
|
|
||||||
x-image: &x-image
|
|
||||||
image: appwrite/appwrite:1.4.3
|
|
||||||
|
|
||||||
x-image-assistant: &x-image-assistant
|
|
||||||
image: appwrite/assistant:0.2.1
|
|
||||||
|
|
||||||
version: '3'
|
version: '3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
appwrite:
|
appwrite:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
container_name: appwrite
|
container_name: appwrite
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
labels:
|
labels:
|
||||||
@ -137,7 +135,7 @@ services:
|
|||||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||||
|
|
||||||
appwrite-realtime:
|
appwrite-realtime:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: realtime
|
entrypoint: realtime
|
||||||
container_name: appwrite-realtime
|
container_name: appwrite-realtime
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
@ -180,7 +178,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-audits:
|
appwrite-worker-audits:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-audits
|
entrypoint: worker-audits
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-audits
|
container_name: appwrite-worker-audits
|
||||||
@ -207,7 +205,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-webhooks:
|
appwrite-worker-webhooks:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-webhooks
|
entrypoint: worker-webhooks
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-webhooks
|
container_name: appwrite-worker-webhooks
|
||||||
@ -230,7 +228,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-deletes:
|
appwrite-worker-deletes:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-deletes
|
entrypoint: worker-deletes
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-deletes
|
container_name: appwrite-worker-deletes
|
||||||
@ -286,7 +284,7 @@ services:
|
|||||||
- _APP_EXECUTOR_HOST
|
- _APP_EXECUTOR_HOST
|
||||||
|
|
||||||
appwrite-worker-databases:
|
appwrite-worker-databases:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-databases
|
entrypoint: worker-databases
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-databases
|
container_name: appwrite-worker-databases
|
||||||
@ -313,7 +311,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-builds:
|
appwrite-worker-builds:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-builds
|
entrypoint: worker-builds
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-builds
|
container_name: appwrite-worker-builds
|
||||||
@ -375,7 +373,7 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_BUCKET
|
- _APP_STORAGE_WASABI_BUCKET
|
||||||
|
|
||||||
appwrite-worker-certificates:
|
appwrite-worker-certificates:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-certificates
|
entrypoint: worker-certificates
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-certificates
|
container_name: appwrite-worker-certificates
|
||||||
@ -409,7 +407,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-functions:
|
appwrite-worker-functions:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-functions
|
entrypoint: worker-functions
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-functions
|
container_name: appwrite-worker-functions
|
||||||
@ -446,7 +444,7 @@ services:
|
|||||||
- _APP_LOGGING_PROVIDER
|
- _APP_LOGGING_PROVIDER
|
||||||
|
|
||||||
appwrite-worker-mails:
|
appwrite-worker-mails:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-mails
|
entrypoint: worker-mails
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-mails
|
container_name: appwrite-worker-mails
|
||||||
@ -474,7 +472,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-messaging:
|
appwrite-worker-messaging:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-messaging
|
container_name: appwrite-worker-messaging
|
||||||
@ -496,7 +494,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-migrations:
|
appwrite-worker-migrations:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: worker-migrations
|
entrypoint: worker-migrations
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-worker-migrations
|
container_name: appwrite-worker-migrations
|
||||||
@ -527,7 +525,7 @@ services:
|
|||||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||||
|
|
||||||
appwrite-maintenance:
|
appwrite-maintenance:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: maintenance
|
entrypoint: maintenance
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
container_name: appwrite-maintenance
|
container_name: appwrite-maintenance
|
||||||
@ -561,7 +559,7 @@ services:
|
|||||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||||
|
|
||||||
appwrite-usage:
|
appwrite-usage:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: usage
|
entrypoint: usage
|
||||||
container_name: appwrite-usage
|
container_name: appwrite-usage
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
@ -592,7 +590,7 @@ services:
|
|||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-schedule:
|
appwrite-schedule:
|
||||||
<<: *x-image
|
image: appwrite/appwrite:1.4.3
|
||||||
entrypoint: schedule
|
entrypoint: schedule
|
||||||
container_name: appwrite-schedule
|
container_name: appwrite-schedule
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
@ -617,7 +615,7 @@ services:
|
|||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
|
|
||||||
appwrite-assistant:
|
appwrite-assistant:
|
||||||
<<: *x-image-assistant
|
image: appwrite/assistant:0.2.1
|
||||||
container_name: appwrite-assistant
|
container_name: appwrite-assistant
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
19
templates/compose/babybuddy.yaml
Normal file
19
templates/compose/babybuddy.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# documentation: https://docs.baby-buddy.net
|
||||||
|
# slogan: Baby Buddy is an open-source web application that helps parents track their baby's daily activities, growth, and health with ease. It's a handy tool for new parents to keep a close eye on their little one's development.
|
||||||
|
|
||||||
|
services:
|
||||||
|
babybuddy:
|
||||||
|
image: lscr.io/linuxserver/babybuddy:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_BABYBUDDY
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Madrid
|
||||||
|
- CSRF_TRUSTED_ORIGINS=$SERVICE_FQDN_BABYBUDDY
|
||||||
|
volumes:
|
||||||
|
- babybuddy-config:/config
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
21
templates/compose/code-server.yaml
Normal file
21
templates/compose/code-server.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# documentation: https://coder.com/docs/code-server/latest/guide
|
||||||
|
# slogan: Code-Server is a self-hosted, web-based code editor that enables remote coding and collaboration from any device, anywhere.
|
||||||
|
|
||||||
|
services:
|
||||||
|
code-server:
|
||||||
|
image: lscr.io/linuxserver/code-server:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_CODESERVER
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Madrid
|
||||||
|
- PASSWORD=$SERVICE_PASSWORD_64_PASSWORDCODESERVER
|
||||||
|
- SUDO_PASSWORD=$SERVICE_PASSWORD_SUDOCODESERVER
|
||||||
|
- DEFAULT_WORKSPACE=/config/workspace
|
||||||
|
volumes:
|
||||||
|
- code-server-config:/config
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8443"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
18
templates/compose/dokuwiki.yaml
Normal file
18
templates/compose/dokuwiki.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# documentation: https://www.dokuwiki.org/faq
|
||||||
|
# slogan: A lightweight and easy-to-use wiki platform for creating and managing documentation and knowledge bases with simplicity and flexibility.
|
||||||
|
|
||||||
|
services:
|
||||||
|
dokuwiki:
|
||||||
|
image: lscr.io/linuxserver/dokuwiki:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_DOKUWIKI
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
- dokuwiki-config:/config
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:80"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
@ -1,10 +1,13 @@
|
|||||||
|
# documentation: https://fider.io/doc
|
||||||
|
# slogan: Fider is an open-source feedback platform for collecting and managing user feedback, helping you prioritize improvements to your products and services.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
fider:
|
fider:
|
||||||
image: getfider/fider:stable
|
image: getfider/fider:stable
|
||||||
environment:
|
environment:
|
||||||
BASE_URL: $SERVICE_FQDN_FIDER
|
BASE_URL: $SERVICE_FQDN_FIDER
|
||||||
DATABASE_URL: postgres://$SERVICE_USER_MYSQL:$SERVICE_PASSWORD_MYSQL@database:5432/fider?sslmode=disable
|
DATABASE_URL: postgres://$SERVICE_USER_MYSQL:$SERVICE_PASSWORD_MYSQL@database:5432/fider?sslmode=disable
|
||||||
JWT_SECRET: $SERVICE_PASSWORD64_FIDER
|
JWT_SECRET: $SERVICE_PASSWORD_64_FIDER
|
||||||
EMAIL_NOREPLY: ${EMAIL_NOREPLY:-noreply@example.com}
|
EMAIL_NOREPLY: ${EMAIL_NOREPLY:-noreply@example.com}
|
||||||
EMAIL_MAILGUN_API: $EMAIL_MAILGUN_API
|
EMAIL_MAILGUN_API: $EMAIL_MAILGUN_API
|
||||||
EMAIL_MAILGUN_DOMAIN: $EMAIL_MAILGUN_DOMAIN
|
EMAIL_MAILGUN_DOMAIN: $EMAIL_MAILGUN_DOMAIN
|
@ -1,3 +1,6 @@
|
|||||||
|
# documentation: https://ghost.org/docs
|
||||||
|
# slogan: Ghost is a popular open-source content management system (CMS) and blogging platform, known for its simplicity and focus on content creation.
|
||||||
|
|
||||||
services:
|
services:
|
||||||
ghost:
|
ghost:
|
||||||
image: ghost:5
|
image: ghost:5
|
18
templates/compose/heimdall.yaml
Normal file
18
templates/compose/heimdall.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# documentation: https://github.com/linuxserver/Heimdall
|
||||||
|
# slogan: Heimdall is a self-hosted dashboard for managing and organizing your server applications, providing a centralized and efficient interface.
|
||||||
|
|
||||||
|
services:
|
||||||
|
heimdall:
|
||||||
|
image: lscr.io/linuxserver/heimdall:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_HEIMDALL
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
- heimdall-config:/config
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:80"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
17
templates/compose/metube.yaml
Normal file
17
templates/compose/metube.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# documentation: https://github.com/alexta69/metube
|
||||||
|
# slogan: A web GUI for youtube-dl with playlist support. It enables you to effortlessly download videos from YouTube and dozens of other sites.
|
||||||
|
|
||||||
|
services:
|
||||||
|
metube:
|
||||||
|
image: ghcr.io/alexta69/metube:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_METUBE
|
||||||
|
- UID=1000
|
||||||
|
- GID=1000
|
||||||
|
volumes:
|
||||||
|
- metube-downloads:/downloads
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8081"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
17
templates/compose/pairdrop.yaml
Normal file
17
templates/compose/pairdrop.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# documentation: https://github.com/schlagmichdoch/PairDrop/blob/master/docs/faq.md
|
||||||
|
# slogan: Pairdrop is a self-hosted file sharing and collaboration platform, offering secure file sharing and collaboration capabilities for efficient teamwork.
|
||||||
|
|
||||||
|
services:
|
||||||
|
pairdrop:
|
||||||
|
image: lscr.io/linuxserver/pairdrop:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_PAIRDROP
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Madrid
|
||||||
|
- DEBUG_MODE=false
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
18
templates/compose/snapdrop.yaml
Normal file
18
templates/compose/snapdrop.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# documentation: https://github.com/RobinLinus/snapdrop/blob/master/docs/faq.md
|
||||||
|
# slogan: A self-hosted file-sharing service for secure and convenient file transfers, whether on a local network or the internet.
|
||||||
|
|
||||||
|
services:
|
||||||
|
snapdrop:
|
||||||
|
image: lscr.io/linuxserver/snapdrop:latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_SNAPDROP
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Europe/Madrid
|
||||||
|
volumes:
|
||||||
|
- snapdrop-config:/config
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:80"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
27
templates/compose/umami.yaml
Normal file
27
templates/compose/umami.yaml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# documentation: https://umami.is/docs/getting-started
|
||||||
|
# slogan: Umami is a lightweight, self-hosted web analytics platform designed to provide website owners with insights into visitor behavior without compromising user privacy.
|
||||||
|
|
||||||
|
services:
|
||||||
|
umami:
|
||||||
|
image: ghcr.io/umami-software/umami:postgresql-latest
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN_UMAMI
|
||||||
|
- DATABASE_URL=postgres://$SERVICE_USER_POSTGRES:$SERVICE_PASSWORD_POSTGRES@postgresql:5432/$POSTGRES_DB
|
||||||
|
- DATABASE_TYPE=postgres
|
||||||
|
- APP_SECRET=$SERVICE_PASSWORD_64_UMAMI
|
||||||
|
depends_on:
|
||||||
|
postgresql:
|
||||||
|
condition: service_healthy
|
||||||
|
postgresql:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
volumes:
|
||||||
|
- postgresql-data:/var/lib/postgresql/data
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=$SERVICE_USER_POSTGRES
|
||||||
|
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||||
|
- POSTGRES_DB=${POSTGRES_DB:-umami}
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
15
templates/compose/uptime-kuma.yaml
Normal file
15
templates/compose/uptime-kuma.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# documentation: https://github.com/louislam/uptime-kuma/wiki
|
||||||
|
# slogan: Uptime Kuma is a free, self-hosted monitoring tool for tracking the status and performance of your web services and applications in real-time.
|
||||||
|
|
||||||
|
services:
|
||||||
|
uptime-kuma:
|
||||||
|
image: louislam/uptime-kuma:1
|
||||||
|
environment:
|
||||||
|
- SERVICE_FQDN
|
||||||
|
volumes:
|
||||||
|
- uptime-kuma:/app/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "extra/healthcheck"]
|
||||||
|
interval: 2s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 15
|
26
templates/compose/wordpress-with-mariadb.yaml
Normal file
26
templates/compose/wordpress-with-mariadb.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# documetaion: https://wordpress.org/documentation/
|
||||||
|
# slogan: "WordPress is open source software you can use to create a beautiful website, blog, or app."
|
||||||
|
|
||||||
|
services:
|
||||||
|
wordpress:
|
||||||
|
image: wordpress:latest
|
||||||
|
volumes:
|
||||||
|
- wordpress-files:/var/www/html
|
||||||
|
environment:
|
||||||
|
SERVICE_FQDN:
|
||||||
|
WORDPRESS_DB_HOST: mariadb
|
||||||
|
WORDPRESS_DB_USER: $SERVICE_USER_WORDPRESS
|
||||||
|
WORDPRESS_DB_PASSWORD: $SERVICE_PASSWORD_WORDPRESS
|
||||||
|
WORDPRESS_DB_NAME: wordpress
|
||||||
|
depends_on:
|
||||||
|
- mariadb
|
||||||
|
|
||||||
|
mariadb:
|
||||||
|
image: mariadb:11
|
||||||
|
volumes:
|
||||||
|
- mariadb-data:/var/lib/mysql
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: $SERVICE_PASSWORD_ROOT
|
||||||
|
MYSQL_DATABASE: wordpress
|
||||||
|
MYSQL_USER: $SERVICE_USER_WORDPRESS
|
||||||
|
MYSQL_PASSWORD: $SERVICE_PASSWORD_WORDPRESS
|
26
templates/compose/wordpress-with-mysql.yaml
Normal file
26
templates/compose/wordpress-with-mysql.yaml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# documetaion: https://wordpress.org/documentation/
|
||||||
|
# slogan: "WordPress is open source software you can use to create a beautiful website, blog, or app."
|
||||||
|
|
||||||
|
services:
|
||||||
|
wordpress:
|
||||||
|
image: wordpress:latest
|
||||||
|
volumes:
|
||||||
|
- wordpress-files:/var/www/html
|
||||||
|
environment:
|
||||||
|
SERVICE_FQDN:
|
||||||
|
WORDPRESS_DB_HOST: mysql
|
||||||
|
WORDPRESS_DB_USER: $SERVICE_USER_WORDPRESS
|
||||||
|
WORDPRESS_DB_PASSWORD: $SERVICE_PASSWORD_WORDPRESS
|
||||||
|
WORDPRESS_DB_NAME: wordpress
|
||||||
|
depends_on:
|
||||||
|
- mysql
|
||||||
|
|
||||||
|
mysql:
|
||||||
|
image: mysql:5.7
|
||||||
|
volumes:
|
||||||
|
- mysql-data:/var/lib/mysql
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: $SERVICE_PASSWORD_ROOT
|
||||||
|
MYSQL_DATABASE: wordpress
|
||||||
|
MYSQL_USER: $SERVICE_USER_WORDPRESS
|
||||||
|
MYSQL_PASSWORD: $SERVICE_PASSWORD_WORDPRESS
|
10
templates/compose/wordpress-without-database.yaml
Normal file
10
templates/compose/wordpress-without-database.yaml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# documetaion: https://wordpress.org/documentation/
|
||||||
|
# slogan: "WordPress is open source software you can use to create a beautiful website, blog, or app."
|
||||||
|
|
||||||
|
services:
|
||||||
|
wordpress:
|
||||||
|
image: wordpress:latest
|
||||||
|
volumes:
|
||||||
|
- wordpress-files:/var/www/html
|
||||||
|
environment:
|
||||||
|
SERVICE_FQDN:
|
@ -4,7 +4,7 @@
|
|||||||
"version": "3.12.36"
|
"version": "3.12.36"
|
||||||
},
|
},
|
||||||
"v4": {
|
"v4": {
|
||||||
"version": "4.0.0-beta.92"
|
"version": "4.0.0-beta.97"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user