mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-31 12:34:03 +00:00
Compare commits
136 Commits
v4.0.0-bet
...
v4.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bae9ea79de | ||
|
|
d57c9d8aa0 | ||
|
|
c7c2924990 | ||
|
|
aa30e83f4a | ||
|
|
77455cd444 | ||
|
|
2777fbc0ec | ||
|
|
2c929b300a | ||
|
|
27ad4441ee | ||
|
|
63729c7bbf | ||
|
|
1e68444f10 | ||
|
|
f8dfe643f4 | ||
|
|
66cf6df4b3 | ||
|
|
29acc4ee25 | ||
|
|
f73983e3dd | ||
|
|
44d417c07e | ||
|
|
1d72f76072 | ||
|
|
c2f7e85022 | ||
|
|
9e6486fa66 | ||
|
|
28bcd0023c | ||
|
|
84093afaf6 | ||
|
|
40347744e0 | ||
|
|
060988d923 | ||
|
|
b093c9757c | ||
|
|
4f9e1a3e5e | ||
|
|
c8218e6901 | ||
|
|
cc10d08a7c | ||
|
|
e5a980d544 | ||
|
|
59c7f2cb56 | ||
|
|
d2a306dab9 | ||
|
|
681a745fc7 | ||
|
|
abb6655fef | ||
|
|
aa586a5677 | ||
|
|
87ee3c511c | ||
|
|
a17daf96be | ||
|
|
a419496066 | ||
|
|
c668d2d1ff | ||
|
|
4611332a8f | ||
|
|
8b3eed5895 | ||
|
|
9861ad4045 | ||
|
|
5fb560dbbf | ||
|
|
435c0baa87 | ||
|
|
bb1454d255 | ||
|
|
a882d3c713 | ||
|
|
6010b3209d | ||
|
|
504133232a | ||
|
|
d816863d31 | ||
|
|
3eb909d3bc | ||
|
|
a102e812cf | ||
|
|
254611dda8 | ||
|
|
d8f9e5910f | ||
|
|
68d4a30eb0 | ||
|
|
5c05ea4463 | ||
|
|
a2dac9394a | ||
|
|
7fabeec08d | ||
|
|
a9228b110e | ||
|
|
148c7d212c | ||
|
|
98154549cf | ||
|
|
3d4f02afde | ||
|
|
b57e2960f2 | ||
|
|
110fac944d | ||
|
|
518ba3502d | ||
|
|
676cee9e3e | ||
|
|
ec7b18556e | ||
|
|
8d2b280b03 | ||
|
|
ba0e29aaf4 | ||
|
|
fccd31009c | ||
|
|
34e213202a | ||
|
|
e7ab43c018 | ||
|
|
0c87a8f4ec | ||
|
|
54e69de2af | ||
|
|
545613b554 | ||
|
|
5c7b9473f8 | ||
|
|
a32e53c5a3 | ||
|
|
b44f4e49e8 | ||
|
|
321b8559e0 | ||
|
|
69794f4ca8 | ||
|
|
4e1663e9db | ||
|
|
2e5ed5969d | ||
|
|
ab055e0692 | ||
|
|
6c2717ad08 | ||
|
|
3ac52af673 | ||
|
|
22d99dec52 | ||
|
|
6a654e31bd | ||
|
|
d07cf59460 | ||
|
|
90e435d392 | ||
|
|
dfadadda10 | ||
|
|
0a7c7036f1 | ||
|
|
9215054d72 | ||
|
|
22de8a7d2b | ||
|
|
6f5b92d322 | ||
|
|
9ef44f9ffb | ||
|
|
5a604b2fc4 | ||
|
|
65b8d3c6d4 | ||
|
|
e05e0da058 | ||
|
|
e4854aaa1b | ||
|
|
2531574a9a | ||
|
|
3aa31f3da6 | ||
|
|
645337b09c | ||
|
|
bd3220ad73 | ||
|
|
6528bc5766 | ||
|
|
93af54ef84 | ||
|
|
08b9c79298 | ||
|
|
22bd305e8f | ||
|
|
dbad08f4dd | ||
|
|
b5232f3d32 | ||
|
|
58234ef65e | ||
|
|
d211362ab3 | ||
|
|
629316d68a | ||
|
|
05084cb69c | ||
|
|
401c410adb | ||
|
|
4888f4c405 | ||
|
|
b241f17eee | ||
|
|
bc22ec63e6 | ||
|
|
458a461388 | ||
|
|
a725ff0a75 | ||
|
|
a8fd7db9a8 | ||
|
|
fbb7568786 | ||
|
|
fae175039a | ||
|
|
9196571737 | ||
|
|
0dad77af33 | ||
|
|
f43298a610 | ||
|
|
02f950edc7 | ||
|
|
817a72e753 | ||
|
|
9c2f4ec04e | ||
|
|
3b533c7d06 | ||
|
|
b0039885eb | ||
|
|
cadb12986c | ||
|
|
63a07e7649 | ||
|
|
08a80876f9 | ||
|
|
ae4c889fa2 | ||
|
|
f072823f00 | ||
|
|
bf475e538c | ||
|
|
fe477ba325 | ||
|
|
a26bc65137 | ||
|
|
b73db2d725 | ||
|
|
8168b564ea |
@@ -21,7 +21,10 @@ DB_PASSWORD=password
|
||||
DB_HOST=host.docker.internal
|
||||
DB_PORT=5432
|
||||
|
||||
#Set custom ray port
|
||||
# Ray Configuration
|
||||
# Set to true to enable Ray
|
||||
RAY_ENABLED=false
|
||||
# Set custom ray port
|
||||
RAY_PORT=
|
||||
|
||||
# Special Keys for Andras
|
||||
|
||||
23
.github/workflows/coolify-helper-next.yml
vendored
23
.github/workflows/coolify-helper-next.yml
vendored
@@ -25,6 +25,10 @@ jobs:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT
|
||||
- name: Build image and push to registry
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
@@ -33,7 +37,9 @@ jobs:
|
||||
file: docker/coolify-helper/Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next
|
||||
labels: |
|
||||
coolify.managed=true
|
||||
aarch64:
|
||||
runs-on: [ self-hosted, arm64 ]
|
||||
permissions:
|
||||
@@ -47,6 +53,10 @@ jobs:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT
|
||||
- name: Build image and push to registry
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
@@ -55,7 +65,9 @@ jobs:
|
||||
file: docker/coolify-helper/Dockerfile
|
||||
platforms: linux/aarch64
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next-aarch64
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64
|
||||
labels: |
|
||||
coolify.managed=true
|
||||
merge-manifest:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@@ -75,10 +87,15 @@ jobs:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT
|
||||
- name: Create & publish manifest
|
||||
run: |
|
||||
docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next
|
||||
docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next
|
||||
- uses: sarisia/actions-status-discord@v1
|
||||
if: always()
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}
|
||||
|
||||
|
||||
24
.github/workflows/coolify-helper.yml
vendored
24
.github/workflows/coolify-helper.yml
vendored
@@ -2,7 +2,7 @@ name: Coolify Helper Image (v4)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
branches: [ "main", "next" ]
|
||||
paths:
|
||||
- .github/workflows/coolify-helper.yml
|
||||
- docker/coolify-helper/Dockerfile
|
||||
@@ -25,6 +25,10 @@ jobs:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT
|
||||
- name: Build image and push to registry
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
@@ -33,7 +37,9 @@ jobs:
|
||||
file: docker/coolify-helper/Dockerfile
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
|
||||
labels: |
|
||||
coolify.managed=true
|
||||
aarch64:
|
||||
runs-on: [ self-hosted, arm64 ]
|
||||
permissions:
|
||||
@@ -47,6 +53,10 @@ jobs:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT
|
||||
- name: Build image and push to registry
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
@@ -55,7 +65,9 @@ jobs:
|
||||
file: docker/coolify-helper/Dockerfile
|
||||
platforms: linux/aarch64
|
||||
push: true
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64
|
||||
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
|
||||
labels: |
|
||||
coolify.managed=true
|
||||
merge-manifest:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
@@ -75,9 +87,13 @@ jobs:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.helper.version' versions.json)"|xargs >> $GITHUB_OUTPUT
|
||||
- name: Create & publish manifest
|
||||
run: |
|
||||
docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
- uses: sarisia/actions-status-discord@v1
|
||||
if: always()
|
||||
with:
|
||||
|
||||
2
.github/workflows/production-build.yml
vendored
2
.github/workflows/production-build.yml
vendored
@@ -4,6 +4,8 @@ on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths-ignore:
|
||||
- .github/workflows/coolify-helper.yml
|
||||
- docker/coolify-helper/Dockerfile
|
||||
- templates/service-templates.json
|
||||
|
||||
env:
|
||||
|
||||
42
README.md
42
README.md
@@ -39,27 +39,27 @@ Special thanks to our biggest sponsors!
|
||||
|
||||

|
||||
|
||||
* [CCCareers](https://cccareers.org/) - A career development platform for coding bootcamp graduates.
|
||||
* [Hetzner](http://htznr.li/CoolifyXHetzner) - A German web hosting company offering dedicated servers and cloud services.
|
||||
* [Logto](https://logto.io/?ref=coolify) - An open-source authentication and authorization platform.
|
||||
* [BC Direct](https://bc.direct/?ref=coolify.io) - A digital marketing agency specializing in e-commerce solutions.
|
||||
* [QuantCDN](https://www.quantcdn.io/?ref=coolify.io) - A content delivery network (CDN) for fast content delivery.
|
||||
* [Arcjet](https://arcjet.com/?ref=coolify.io) - A cloud-based platform for data analytics and visualization.
|
||||
* [SupaGuide](https://supa.guide/?ref=coolify.io) - A platform offering guides and resources for web development and design.
|
||||
* [Tigris](https://tigrisdata.com/?ref=coolify.io) - A data integration platform for connecting and managing data sources.
|
||||
* [Fractal Networks](https://fractalnetworks.co/?ref=coolify.io) - A decentralized network infrastructure for secure data exchange.
|
||||
* [Advin](https://coolify.ad.vin/?ref=coolify.io) - A digital advertising agency specializing in programmatic advertising.
|
||||
* [Treive](https://trieve.ai/?ref=coolify.io) - An AI-powered data analytics platform for business insights.
|
||||
* [Blacksmith](https://blacksmith.sh/?ref=coolify.io) - A cloud-based platform for automating DevOps and infrastructure management.
|
||||
* [Latitude](https://latitude.sh/?ref=coolify.io) - A platform offering location-based services and geospatial data.
|
||||
* [Brand Dev](https://brand.dev/?ref=coolify.io) - A web development agency specializing in brand identity and digital presence.
|
||||
* [Jobscollider](https://jobscollider.com/remote-jobs?ref=coolify.io) - A job search platform specializing in remote and flexible work opportunities.
|
||||
* [Hostinger](https://hostinger.com?ref=coolify.io) - A web hosting company offering shared, VPS, and cloud hosting services.
|
||||
* [Glueops](https://www.glueops.dev/?ref=coolify.io) - A DevOps and cloud consulting company offering infrastructure automation services.
|
||||
* [Ubicloud](https://ubicloud.com/?ref=coolify.io) - A cloud-based platform for IoT device management and data analytics.
|
||||
* [Juxtdigital](https://juxtdigital.dev/?ref=coolify.io) - A digital agency offering web development, design, and marketing services.
|
||||
* [Saasykit](https://saasykit.com/?ref=coolify.io) - SaaSykit is a Laravel-based boilerplate with everything you need to build an awesome SaaS.
|
||||
* [Massivegrid](https://massivegrid.com/?ref=coolify.io) - A cloud-based platform for data storage and processing.
|
||||
* [CCCareers](https://cccareers.org/) - A career development platform connecting coding bootcamp graduates with job opportunities in the tech industry.
|
||||
* [Hetzner](http://htznr.li/CoolifyXHetzner) - A German web hosting company offering affordable dedicated servers, cloud services, and web hosting solutions.
|
||||
* [Logto](https://logto.io/?ref=coolify) - An open-source authentication and authorization solution for building secure login systems and managing user identities.
|
||||
* [BC Direct](https://bc.direct/?ref=coolify.io) - A digital marketing agency specializing in e-commerce solutions and online business growth strategies.
|
||||
* [QuantCDN](https://www.quantcdn.io/?ref=coolify.io) - A content delivery network (CDN) optimizing website performance through global content distribution.
|
||||
* [Arcjet](https://arcjet.com/?ref=coolify.io) - A cloud-based platform providing real-time protection against API abuse and bot attacks.
|
||||
* [SupaGuide](https://supa.guide/?ref=coolify.io) - A comprehensive resource hub offering guides and tutorials for web development using Supabase.
|
||||
* [Tigris](https://tigrisdata.com/?ref=coolify.io) - A fully managed serverless object storage service compatible with Amazon S3 API. Offers high performance, scalability, and built-in search capabilities for efficient data management.
|
||||
* [Fractal Networks](https://fractalnetworks.co/?ref=coolify.io) - A decentralized network infrastructure company focusing on secure and private communication solutions.
|
||||
* [Advin](https://coolify.ad.vin/?ref=coolify.io) - A digital advertising agency specializing in programmatic advertising and data-driven marketing strategies.
|
||||
* [Treive](https://trieve.ai/?ref=coolify.io) - An AI-powered search and discovery platform for enhancing information retrieval in large datasets.
|
||||
* [Blacksmith](https://blacksmith.sh/?ref=coolify.io) - A cloud-native platform for automating infrastructure provisioning and management across multiple cloud providers.
|
||||
* [Latitude](https://latitude.sh/?ref=coolify.io) - A cloud computing platform offering bare metal servers and cloud instances for developers and businesses.
|
||||
* [Brand Dev](https://brand.dev/?ref=coolify.io) - A web development agency specializing in creating custom digital experiences and brand identities.
|
||||
* [Jobscollider](https://jobscollider.com/remote-jobs?ref=coolify.io) - A job search platform connecting professionals with remote work opportunities across various industries.
|
||||
* [Hostinger](https://hostinger.com?ref=coolify.io) - A web hosting provider offering affordable hosting solutions, domain registration, and website building tools.
|
||||
* [Glueops](https://www.glueops.dev/?ref=coolify.io) - A DevOps consulting company providing infrastructure automation and cloud optimization services.
|
||||
* [Ubicloud](https://ubicloud.com/?ref=coolify.io) - An open-source alternative to hyperscale cloud providers, offering high-performance cloud computing services.
|
||||
* [Juxtdigital](https://juxtdigital.dev/?ref=coolify.io) - A digital agency offering web development, design, and digital marketing services for businesses.
|
||||
* [Saasykit](https://saasykit.com/?ref=coolify.io) - A Laravel-based boilerplate providing essential components and features for building SaaS applications quickly.
|
||||
* [Massivegrid](https://massivegrid.com/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
|
||||
|
||||
|
||||
## Github Sponsors ($40+)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Actions\Server;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
@@ -21,10 +22,16 @@ class CleanupDocker
|
||||
|
||||
private function getCommands(): array
|
||||
{
|
||||
$settings = InstanceSettings::get();
|
||||
$helperImageVersion = data_get($settings, 'helper_version');
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$helperImageWithVersion = config('coolify.helper_image').':'.$helperImageVersion;
|
||||
|
||||
$commonCommands = [
|
||||
'docker container prune -f --filter "label=coolify.managed=true"',
|
||||
'docker image prune -af',
|
||||
'docker image prune -af --filter "label!=coolify.managed=true"',
|
||||
'docker builder prune -af',
|
||||
"docker images --filter before=$helperImageWithVersion --filter reference=$helperImage | grep $helperImage | awk '{print $3}' | xargs -r docker rmi",
|
||||
];
|
||||
|
||||
return $commonCommands;
|
||||
|
||||
@@ -4,8 +4,6 @@ namespace App\Actions\Server;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class UpdateCoolify
|
||||
@@ -27,11 +25,6 @@ class UpdateCoolify
|
||||
return;
|
||||
}
|
||||
CleanupDocker::dispatch($this->server)->onQueue('high');
|
||||
$response = Http::retry(3, 1000)->get('https://cdn.coollabs.io/coolify/versions.json');
|
||||
if ($response->successful()) {
|
||||
$versions = $response->json();
|
||||
File::put(base_path('versions.json'), json_encode($versions, JSON_PRETTY_PRINT));
|
||||
}
|
||||
$this->latestVersion = get_latest_version_of_coolify();
|
||||
$this->currentVersion = config('version');
|
||||
if (! $manual_update) {
|
||||
@@ -62,10 +55,11 @@ class UpdateCoolify
|
||||
|
||||
return;
|
||||
}
|
||||
instant_remote_process(["docker pull -q ghcr.io/coollabsio/coolify:{$this->latestVersion}"], $this->server, false);
|
||||
|
||||
remote_process([
|
||||
'curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh -o /data/coolify/source/upgrade.sh',
|
||||
"bash /data/coolify/source/upgrade.sh $this->latestVersion",
|
||||
], $this->server);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,10 @@ class StartService
|
||||
$service->saveComposeConfigs();
|
||||
$commands[] = 'cd '.$service->workdir();
|
||||
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
|
||||
$commands[] = "echo 'Creating Docker network.'";
|
||||
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid";
|
||||
if($service->networks()->count() > 0){
|
||||
$commands[] = "echo 'Creating Docker network.'";
|
||||
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid";
|
||||
}
|
||||
$commands[] = 'echo Starting service.';
|
||||
$commands[] = "echo 'Pulling images.'";
|
||||
$commands[] = 'docker compose pull';
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Models\ScheduledTask;
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
@@ -165,6 +166,18 @@ class CleanupStuckedResources extends Command
|
||||
echo "Error in cleaning stuck scheduledtasks: {$e->getMessage()}\n";
|
||||
}
|
||||
|
||||
try {
|
||||
$scheduled_backups = ScheduledDatabaseBackup::all();
|
||||
foreach ($scheduled_backups as $scheduled_backup) {
|
||||
if (! $scheduled_backup->server()) {
|
||||
echo "Deleting stuck scheduledbackup: {$scheduled_backup->name}\n";
|
||||
$scheduled_backup->delete();
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stuck scheduledbackups: {$e->getMessage()}\n";
|
||||
}
|
||||
|
||||
// Cleanup any resources that are not attached to any environment or destination or server
|
||||
try {
|
||||
$applications = Application::all();
|
||||
|
||||
@@ -4,9 +4,9 @@ namespace App\Console;
|
||||
|
||||
use App\Jobs\CheckForUpdatesJob;
|
||||
use App\Jobs\CleanupInstanceStuffsJob;
|
||||
use App\Jobs\CleanupStaleMultiplexedConnections;
|
||||
use App\Jobs\DatabaseBackupJob;
|
||||
use App\Jobs\DockerCleanupJob;
|
||||
use App\Jobs\PullCoolifyImageJob;
|
||||
use App\Jobs\PullHelperImageJob;
|
||||
use App\Jobs\PullSentinelImageJob;
|
||||
use App\Jobs\PullTemplatesFromCDN;
|
||||
@@ -30,7 +30,8 @@ class Kernel extends ConsoleKernel
|
||||
$this->all_servers = Server::all();
|
||||
$settings = InstanceSettings::get();
|
||||
|
||||
$schedule->command('telescope:prune')->daily();
|
||||
$schedule->job(new CleanupStaleMultiplexedConnections)->hourly();
|
||||
|
||||
if (isDev()) {
|
||||
// Instance Jobs
|
||||
$schedule->command('horizon:snapshot')->everyMinute();
|
||||
@@ -40,11 +41,12 @@ class Kernel extends ConsoleKernel
|
||||
$this->check_resources($schedule);
|
||||
$this->check_scheduled_tasks($schedule);
|
||||
$schedule->command('uploads:clear')->everyTwoMinutes();
|
||||
|
||||
$schedule->command('telescope:prune')->daily();
|
||||
} else {
|
||||
// Instance Jobs
|
||||
$schedule->command('horizon:snapshot')->everyFiveMinutes();
|
||||
$schedule->command('cleanup:unreachable-servers')->daily()->onOneServer();
|
||||
$schedule->job(new PullCoolifyImageJob)->cron($settings->update_check_frequency)->timezone($settings->instance_timezone)->onOneServer();
|
||||
$schedule->job(new PullTemplatesFromCDN)->cron($settings->update_check_frequency)->timezone($settings->instance_timezone)->onOneServer();
|
||||
$schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer();
|
||||
$this->schedule_updates($schedule);
|
||||
@@ -139,6 +141,10 @@ class Kernel extends ConsoleKernel
|
||||
}
|
||||
|
||||
$server = $scheduled_backup->server();
|
||||
|
||||
if (! $server) {
|
||||
continue;
|
||||
}
|
||||
$serverTimezone = $server->settings->server_timezone;
|
||||
|
||||
if (isset(VALID_CRON_STRINGS[$scheduled_backup->frequency])) {
|
||||
@@ -181,6 +187,9 @@ class Kernel extends ConsoleKernel
|
||||
}
|
||||
|
||||
$server = $scheduled_task->server();
|
||||
if (! $server) {
|
||||
continue;
|
||||
}
|
||||
$serverTimezone = $server->settings->server_timezone ?: config('app.timezone');
|
||||
|
||||
if (isset(VALID_CRON_STRINGS[$scheduled_task->frequency])) {
|
||||
|
||||
@@ -86,7 +86,7 @@ class DeployController extends Controller
|
||||
],
|
||||
tags: ['Deployments'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Deployment Uuid', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Deployment UUID', schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
@@ -150,7 +150,7 @@ class DeployController extends Controller
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Get deployment(s) Uuid\'s',
|
||||
description: 'Get deployment(s) UUID\'s',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
|
||||
@@ -11,7 +11,7 @@ class ProjectController extends Controller
|
||||
{
|
||||
#[OA\Get(
|
||||
summary: 'List',
|
||||
description: 'list projects.',
|
||||
description: 'List projects.',
|
||||
path: '/projects',
|
||||
operationId: 'list-projects',
|
||||
security: [
|
||||
@@ -47,7 +47,7 @@ class ProjectController extends Controller
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$projects = Project::whereTeamId($teamId)->select('id', 'name', 'uuid')->get();
|
||||
$projects = Project::whereTeamId($teamId)->select('id', 'name', 'description', 'uuid')->get();
|
||||
|
||||
return response()->json(serializeApiResponse($projects),
|
||||
);
|
||||
@@ -55,7 +55,7 @@ class ProjectController extends Controller
|
||||
|
||||
#[OA\Get(
|
||||
summary: 'Get',
|
||||
description: 'Get project by Uuid.',
|
||||
description: 'Get project by UUID.',
|
||||
path: '/projects/{uuid}',
|
||||
operationId: 'get-project-by-uuid',
|
||||
security: [
|
||||
@@ -139,12 +139,15 @@ class ProjectController extends Controller
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
if (! $request->uuid) {
|
||||
return response()->json(['message' => 'Uuid is required.'], 422);
|
||||
return response()->json(['message' => 'UUID is required.'], 422);
|
||||
}
|
||||
if (! $request->environment_name) {
|
||||
return response()->json(['message' => 'Environment name is required.'], 422);
|
||||
}
|
||||
$project = Project::whereTeamId($teamId)->whereUuid($request->uuid)->first();
|
||||
if (! $project) {
|
||||
return response()->json(['message' => 'Project not found.'], 404);
|
||||
}
|
||||
$environment = $project->environments()->whereName($request->environment_name)->first();
|
||||
if (! $environment) {
|
||||
return response()->json(['message' => 'Environment not found.'], 404);
|
||||
@@ -171,7 +174,7 @@ class ProjectController extends Controller
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'uuid' => ['type' => 'string', 'description' => 'The name of the project.'],
|
||||
'name' => ['type' => 'string', 'description' => 'The name of the project.'],
|
||||
'description' => ['type' => 'string', 'description' => 'The description of the project.'],
|
||||
],
|
||||
),
|
||||
@@ -338,7 +341,7 @@ class ProjectController extends Controller
|
||||
}
|
||||
$uuid = $request->uuid;
|
||||
if (! $uuid) {
|
||||
return response()->json(['message' => 'Uuid is required.'], 422);
|
||||
return response()->json(['message' => 'UUID is required.'], 422);
|
||||
}
|
||||
|
||||
$project = Project::whereTeamId($teamId)->whereUuid($uuid)->first();
|
||||
@@ -414,7 +417,7 @@ class ProjectController extends Controller
|
||||
}
|
||||
|
||||
if (! $request->uuid) {
|
||||
return response()->json(['message' => 'Uuid is required.'], 422);
|
||||
return response()->json(['message' => 'UUID is required.'], 422);
|
||||
}
|
||||
$project = Project::whereTeamId($teamId)->whereUuid($request->uuid)->first();
|
||||
if (! $project) {
|
||||
|
||||
@@ -75,7 +75,7 @@ class SecurityController extends Controller
|
||||
],
|
||||
tags: ['Private Keys'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key Uuid', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key UUID', schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
@@ -323,7 +323,7 @@ class SecurityController extends Controller
|
||||
],
|
||||
tags: ['Private Keys'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key Uuid', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Private Key UUID', schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
|
||||
@@ -107,7 +107,7 @@ class ServersController extends Controller
|
||||
],
|
||||
tags: ['Servers'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s UUID', schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
@@ -185,7 +185,7 @@ class ServersController extends Controller
|
||||
],
|
||||
tags: ['Servers'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s UUID', schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
@@ -263,7 +263,7 @@ class ServersController extends Controller
|
||||
],
|
||||
tags: ['Servers'],
|
||||
parameters: [
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s Uuid', schema: new OA\Schema(type: 'string')),
|
||||
new OA\Parameter(name: 'uuid', in: 'path', required: true, description: 'Server\'s UUID', schema: new OA\Schema(type: 'string')),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
|
||||
@@ -378,7 +378,7 @@ class ServicesController extends Controller
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Get a service by Uuid.',
|
||||
description: 'Get a service by UUID.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
@@ -436,7 +436,7 @@ class ServicesController extends Controller
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Delete a service by Uuid',
|
||||
description: 'Delete a service by UUID',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
@@ -483,6 +483,516 @@ class ServicesController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
summary: 'List Envs',
|
||||
description: 'List all envs by service UUID.',
|
||||
path: '/services/{uuid}/envs',
|
||||
operationId: 'list-envs-by-service-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Services'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the service.',
|
||||
required: true,
|
||||
schema: new OA\Schema(
|
||||
type: 'string',
|
||||
format: 'uuid',
|
||||
)
|
||||
),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'All environment variables by service UUID.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'array',
|
||||
items: new OA\Items(ref: '#/components/schemas/EnvironmentVariable')
|
||||
)
|
||||
),
|
||||
]),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 400,
|
||||
ref: '#/components/responses/400',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 404,
|
||||
ref: '#/components/responses/404',
|
||||
),
|
||||
]
|
||||
)]
|
||||
public function envs(Request $request)
|
||||
{
|
||||
$teamId = getTeamIdFromToken();
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
||||
$envs = $service->environment_variables->map(function ($env) {
|
||||
$env->makeHidden([
|
||||
'application_id',
|
||||
'standalone_clickhouse_id',
|
||||
'standalone_dragonfly_id',
|
||||
'standalone_keydb_id',
|
||||
'standalone_mariadb_id',
|
||||
'standalone_mongodb_id',
|
||||
'standalone_mysql_id',
|
||||
'standalone_postgresql_id',
|
||||
'standalone_redis_id',
|
||||
]);
|
||||
$env = $this->removeSensitiveData($env);
|
||||
|
||||
return $env;
|
||||
});
|
||||
|
||||
return response()->json($envs);
|
||||
}
|
||||
|
||||
#[OA\Patch(
|
||||
summary: 'Update Env',
|
||||
description: 'Update env by service UUID.',
|
||||
path: '/services/{uuid}/envs',
|
||||
operationId: 'update-env-by-service-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Services'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the service.',
|
||||
required: true,
|
||||
schema: new OA\Schema(
|
||||
type: 'string',
|
||||
format: 'uuid',
|
||||
)
|
||||
),
|
||||
],
|
||||
requestBody: new OA\RequestBody(
|
||||
description: 'Env updated.',
|
||||
required: true,
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
required: ['key', 'value'],
|
||||
properties: [
|
||||
'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'],
|
||||
'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'],
|
||||
'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'],
|
||||
'is_build_time' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in build time.'],
|
||||
'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'],
|
||||
'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'],
|
||||
'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'],
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 201,
|
||||
description: 'Environment variable updated.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'message' => ['type' => 'string', 'example' => 'Environment variable updated.'],
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 400,
|
||||
ref: '#/components/responses/400',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 404,
|
||||
ref: '#/components/responses/404',
|
||||
),
|
||||
]
|
||||
)]
|
||||
public function update_env_by_uuid(Request $request)
|
||||
{
|
||||
$teamId = getTeamIdFromToken();
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'key' => 'string|required',
|
||||
'value' => 'string|nullable',
|
||||
'is_build_time' => 'boolean',
|
||||
'is_literal' => 'boolean',
|
||||
'is_multiline' => 'boolean',
|
||||
'is_shown_once' => 'boolean',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => $validator->errors(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$env = $service->environment_variables()->where('key', $request->key)->first();
|
||||
if (! $env) {
|
||||
return response()->json(['message' => 'Environment variable not found.'], 404);
|
||||
}
|
||||
|
||||
$env->fill($request->all());
|
||||
$env->save();
|
||||
|
||||
return response()->json($this->removeSensitiveData($env))->setStatusCode(201);
|
||||
}
|
||||
|
||||
#[OA\Patch(
|
||||
summary: 'Update Envs (Bulk)',
|
||||
description: 'Update multiple envs by service UUID.',
|
||||
path: '/services/{uuid}/envs/bulk',
|
||||
operationId: 'update-envs-by-service-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Services'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the service.',
|
||||
required: true,
|
||||
schema: new OA\Schema(
|
||||
type: 'string',
|
||||
format: 'uuid',
|
||||
)
|
||||
),
|
||||
],
|
||||
requestBody: new OA\RequestBody(
|
||||
description: 'Bulk envs updated.',
|
||||
required: true,
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
required: ['data'],
|
||||
properties: [
|
||||
'data' => [
|
||||
'type' => 'array',
|
||||
'items' => new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'],
|
||||
'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'],
|
||||
'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'],
|
||||
'is_build_time' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in build time.'],
|
||||
'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'],
|
||||
'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'],
|
||||
'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'],
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 201,
|
||||
description: 'Environment variables updated.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'message' => ['type' => 'string', 'example' => 'Environment variables updated.'],
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 400,
|
||||
ref: '#/components/responses/400',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 404,
|
||||
ref: '#/components/responses/404',
|
||||
),
|
||||
]
|
||||
)]
|
||||
public function create_bulk_envs(Request $request)
|
||||
{
|
||||
$teamId = getTeamIdFromToken();
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
||||
$bulk_data = $request->get('data');
|
||||
if (! $bulk_data) {
|
||||
return response()->json(['message' => 'Bulk data is required.'], 400);
|
||||
}
|
||||
|
||||
$updatedEnvs = collect();
|
||||
foreach ($bulk_data as $item) {
|
||||
$validator = customApiValidator($item, [
|
||||
'key' => 'string|required',
|
||||
'value' => 'string|nullable',
|
||||
'is_build_time' => 'boolean',
|
||||
'is_literal' => 'boolean',
|
||||
'is_multiline' => 'boolean',
|
||||
'is_shown_once' => 'boolean',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => $validator->errors(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$env = $service->environment_variables()->updateOrCreate(
|
||||
['key' => $item['key']],
|
||||
$item
|
||||
);
|
||||
|
||||
$updatedEnvs->push($this->removeSensitiveData($env));
|
||||
}
|
||||
|
||||
return response()->json($updatedEnvs)->setStatusCode(201);
|
||||
}
|
||||
|
||||
#[OA\Post(
|
||||
summary: 'Create Env',
|
||||
description: 'Create env by service UUID.',
|
||||
path: '/services/{uuid}/envs',
|
||||
operationId: 'create-env-by-service-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Services'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the service.',
|
||||
required: true,
|
||||
schema: new OA\Schema(
|
||||
type: 'string',
|
||||
format: 'uuid',
|
||||
)
|
||||
),
|
||||
],
|
||||
requestBody: new OA\RequestBody(
|
||||
required: true,
|
||||
description: 'Env created.',
|
||||
content: new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'key' => ['type' => 'string', 'description' => 'The key of the environment variable.'],
|
||||
'value' => ['type' => 'string', 'description' => 'The value of the environment variable.'],
|
||||
'is_preview' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in preview deployments.'],
|
||||
'is_build_time' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is used in build time.'],
|
||||
'is_literal' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is a literal, nothing espaced.'],
|
||||
'is_multiline' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable is multiline.'],
|
||||
'is_shown_once' => ['type' => 'boolean', 'description' => 'The flag to indicate if the environment variable\'s value is shown on the UI.'],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 201,
|
||||
description: 'Environment variable created.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'uuid' => ['type' => 'string', 'example' => 'nc0k04gk8g0cgsk440g0koko'],
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 400,
|
||||
ref: '#/components/responses/400',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 404,
|
||||
ref: '#/components/responses/404',
|
||||
),
|
||||
]
|
||||
)]
|
||||
public function create_env(Request $request)
|
||||
{
|
||||
$teamId = getTeamIdFromToken();
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'key' => 'string|required',
|
||||
'value' => 'string|nullable',
|
||||
'is_build_time' => 'boolean',
|
||||
'is_literal' => 'boolean',
|
||||
'is_multiline' => 'boolean',
|
||||
'is_shown_once' => 'boolean',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'message' => 'Validation failed.',
|
||||
'errors' => $validator->errors(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$existingEnv = $service->environment_variables()->where('key', $request->key)->first();
|
||||
if ($existingEnv) {
|
||||
return response()->json([
|
||||
'message' => 'Environment variable already exists. Use PATCH request to update it.',
|
||||
], 409);
|
||||
}
|
||||
|
||||
$env = $service->environment_variables()->create($request->all());
|
||||
|
||||
return response()->json($this->removeSensitiveData($env))->setStatusCode(201);
|
||||
}
|
||||
|
||||
#[OA\Delete(
|
||||
summary: 'Delete Env',
|
||||
description: 'Delete env by UUID.',
|
||||
path: '/services/{uuid}/envs/{env_uuid}',
|
||||
operationId: 'delete-env-by-service-uuid',
|
||||
security: [
|
||||
['bearerAuth' => []],
|
||||
],
|
||||
tags: ['Services'],
|
||||
parameters: [
|
||||
new OA\Parameter(
|
||||
name: 'uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the service.',
|
||||
required: true,
|
||||
schema: new OA\Schema(
|
||||
type: 'string',
|
||||
format: 'uuid',
|
||||
)
|
||||
),
|
||||
new OA\Parameter(
|
||||
name: 'env_uuid',
|
||||
in: 'path',
|
||||
description: 'UUID of the environment variable.',
|
||||
required: true,
|
||||
schema: new OA\Schema(
|
||||
type: 'string',
|
||||
format: 'uuid',
|
||||
)
|
||||
),
|
||||
],
|
||||
responses: [
|
||||
new OA\Response(
|
||||
response: 200,
|
||||
description: 'Environment variable deleted.',
|
||||
content: [
|
||||
new OA\MediaType(
|
||||
mediaType: 'application/json',
|
||||
schema: new OA\Schema(
|
||||
type: 'object',
|
||||
properties: [
|
||||
'message' => ['type' => 'string', 'example' => 'Environment variable deleted.'],
|
||||
]
|
||||
)
|
||||
),
|
||||
]),
|
||||
new OA\Response(
|
||||
response: 401,
|
||||
ref: '#/components/responses/401',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 400,
|
||||
ref: '#/components/responses/400',
|
||||
),
|
||||
new OA\Response(
|
||||
response: 404,
|
||||
ref: '#/components/responses/404',
|
||||
),
|
||||
]
|
||||
)]
|
||||
public function delete_env_by_uuid(Request $request)
|
||||
{
|
||||
$teamId = getTeamIdFromToken();
|
||||
if (is_null($teamId)) {
|
||||
return invalidTokenResponse();
|
||||
}
|
||||
|
||||
$service = Service::whereRelation('environment.project.team', 'id', $teamId)->whereUuid($request->uuid)->first();
|
||||
if (! $service) {
|
||||
return response()->json(['message' => 'Service not found.'], 404);
|
||||
}
|
||||
|
||||
$env = EnvironmentVariable::where('uuid', $request->env_uuid)
|
||||
->where('service_id', $service->id)
|
||||
->first();
|
||||
|
||||
if (! $env) {
|
||||
return response()->json(['message' => 'Environment variable not found.'], 404);
|
||||
}
|
||||
|
||||
$env->forceDelete();
|
||||
|
||||
return response()->json(['message' => 'Environment variable deleted.']);
|
||||
}
|
||||
|
||||
#[OA\Get(
|
||||
summary: 'Start',
|
||||
description: 'Start service. `Post` request is also accepted.',
|
||||
|
||||
@@ -12,6 +12,7 @@ use App\Models\ApplicationPreview;
|
||||
use App\Models\EnvironmentVariable;
|
||||
use App\Models\GithubApp;
|
||||
use App\Models\GitlabApp;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandaloneDocker;
|
||||
use App\Models\SwarmDocker;
|
||||
@@ -1065,15 +1066,55 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$this->environment_variables = $envs;
|
||||
}
|
||||
|
||||
private function elixir_finetunes()
|
||||
{
|
||||
if ($this->pull_request_id === 0) {
|
||||
$envType = 'environment_variables';
|
||||
} else {
|
||||
$envType = 'environment_variables_preview';
|
||||
}
|
||||
$mix_env = $this->application->{$envType}->where('key', 'MIX_ENV')->first();
|
||||
if ($mix_env) {
|
||||
if ($mix_env->is_build_time === false) {
|
||||
$this->application_deployment_queue->addLogEntry('MIX_ENV environment variable is not set as build time.', type: 'error');
|
||||
$this->application_deployment_queue->addLogEntry('Please set MIX_ENV environment variable to be build time variable if you facing any issues with the deployment.', type: 'error');
|
||||
}
|
||||
} else {
|
||||
$this->application_deployment_queue->addLogEntry('MIX_ENV environment variable not found.', type: 'error');
|
||||
$this->application_deployment_queue->addLogEntry('Please add MIX_ENV environment variable and set it to be build time variable if you facing any issues with the deployment.', type: 'error');
|
||||
}
|
||||
$secret_key_base = $this->application->{$envType}->where('key', 'SECRET_KEY_BASE')->first();
|
||||
if ($secret_key_base) {
|
||||
if ($secret_key_base->is_build_time === false) {
|
||||
$this->application_deployment_queue->addLogEntry('SECRET_KEY_BASE environment variable is not set as build time.', type: 'error');
|
||||
$this->application_deployment_queue->addLogEntry('Please set SECRET_KEY_BASE environment variable to be build time variable if you facing any issues with the deployment.', type: 'error');
|
||||
}
|
||||
} else {
|
||||
$this->application_deployment_queue->addLogEntry('SECRET_KEY_BASE environment variable not found.', type: 'error');
|
||||
$this->application_deployment_queue->addLogEntry('Please add SECRET_KEY_BASE environment variable and set it to be build time variable if you facing any issues with the deployment.', type: 'error');
|
||||
}
|
||||
$database_url = $this->application->{$envType}->where('key', 'DATABASE_URL')->first();
|
||||
if ($database_url) {
|
||||
if ($database_url->is_build_time === false) {
|
||||
$this->application_deployment_queue->addLogEntry('DATABASE_URL environment variable is not set as build time.', type: 'error');
|
||||
$this->application_deployment_queue->addLogEntry('Please set DATABASE_URL environment variable to be build time variable if you facing any issues with the deployment.', type: 'error');
|
||||
}
|
||||
} else {
|
||||
$this->application_deployment_queue->addLogEntry('DATABASE_URL environment variable not found.', type: 'error');
|
||||
$this->application_deployment_queue->addLogEntry('Please add DATABASE_URL environment variable and set it to be build time variable if you facing any issues with the deployment.', type: 'error');
|
||||
}
|
||||
}
|
||||
|
||||
private function laravel_finetunes()
|
||||
{
|
||||
if ($this->pull_request_id === 0) {
|
||||
$nixpacks_php_fallback_path = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first();
|
||||
$nixpacks_php_root_dir = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first();
|
||||
$envType = 'environment_variables';
|
||||
} else {
|
||||
$nixpacks_php_fallback_path = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first();
|
||||
$nixpacks_php_root_dir = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first();
|
||||
$envType = 'environment_variables_preview';
|
||||
}
|
||||
$nixpacks_php_fallback_path = $this->application->{$envType}->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first();
|
||||
$nixpacks_php_root_dir = $this->application->{$envType}->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first();
|
||||
|
||||
if (! $nixpacks_php_fallback_path) {
|
||||
$nixpacks_php_fallback_path = new EnvironmentVariable;
|
||||
$nixpacks_php_fallback_path->key = 'NIXPACKS_PHP_FALLBACK_PATH';
|
||||
@@ -1293,7 +1334,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
private function prepare_builder_image()
|
||||
{
|
||||
$settings = InstanceSettings::get();
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$helperImage = "{$helperImage}:{$settings->helper_version}";
|
||||
// Get user home directory
|
||||
$this->serverUserHomeDir = instant_remote_process(['echo $HOME'], $this->server);
|
||||
$this->dockerConfigFileExists = instant_remote_process(["test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'"], $this->server);
|
||||
@@ -1530,6 +1573,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
|
||||
data_set($parsed, 'variables.NIXPACKS_PHP_FALLBACK_PATH', $variables[0]->value);
|
||||
data_set($parsed, 'variables.NIXPACKS_PHP_ROOT_DIR', $variables[1]->value);
|
||||
}
|
||||
if ($this->nixpacks_type === 'elixir') {
|
||||
$this->elixir_finetunes();
|
||||
}
|
||||
$this->nixpacks_plan = json_encode($parsed, JSON_PRETTY_PRINT);
|
||||
$this->application_deployment_queue->addLogEntry("Final Nixpacks plan: {$this->nixpacks_plan}", hidden: true);
|
||||
if ($this->nixpacks_type === 'rust') {
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Traits\ExecuteRemoteCommand;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ApplicationRestartJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, ExecuteRemoteCommand, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 3600;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public string $applicationDeploymentQueueId;
|
||||
|
||||
public function __construct(string $applicationDeploymentQueueId)
|
||||
{
|
||||
$this->applicationDeploymentQueueId = $applicationDeploymentQueueId;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
ray('Restarting application');
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class CheckForUpdatesJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
@@ -25,12 +26,14 @@ class CheckForUpdatesJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$response = Http::retry(3, 1000)->get('https://cdn.coollabs.io/coolify/versions.json');
|
||||
if ($response->successful()) {
|
||||
$versions = $response->json();
|
||||
|
||||
$latest_version = data_get($versions, 'coolify.v4.version');
|
||||
$current_version = config('version');
|
||||
|
||||
if (version_compare($latest_version, $current_version, '>')) {
|
||||
// New version available
|
||||
$settings->update(['new_version_available' => true]);
|
||||
File::put(base_path('versions.json'), json_encode($versions, JSON_PRETTY_PRINT));
|
||||
} else {
|
||||
$settings->update(['new_version_available' => false]);
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Actions\Server\InstallLogDrain;
|
||||
use App\Models\Server;
|
||||
use App\Notifications\Container\ContainerRestarted;
|
||||
use App\Notifications\Container\ContainerStopped;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Sleep;
|
||||
|
||||
class CheckLogDrainContainerJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function __construct(public Server $server) {}
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping($this->server->id))->dontRelease()];
|
||||
}
|
||||
|
||||
public function uniqueId(): int
|
||||
{
|
||||
return $this->server->id;
|
||||
}
|
||||
|
||||
public function healthcheck()
|
||||
{
|
||||
$status = instant_remote_process(["docker inspect --format='{{json .State.Status}}' coolify-log-drain"], $this->server, false);
|
||||
if (str($status)->contains('running')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
// ray("checking log drain statuses for {$this->server->id}");
|
||||
try {
|
||||
if (! $this->server->isFunctional()) {
|
||||
return;
|
||||
}
|
||||
$containers = instant_remote_process(['docker container ls -q'], $this->server, false);
|
||||
if (! $containers) {
|
||||
return;
|
||||
}
|
||||
$containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this->server);
|
||||
$containers = format_docker_command_output_to_json($containers);
|
||||
|
||||
$foundLogDrainContainer = $containers->filter(function ($value, $key) {
|
||||
return data_get($value, 'Name') === '/coolify-log-drain';
|
||||
})->first();
|
||||
if (! $foundLogDrainContainer || ! $this->healthcheck()) {
|
||||
ray('Log drain container not found or unhealthy. Restarting...');
|
||||
InstallLogDrain::run($this->server);
|
||||
Sleep::for(10)->seconds();
|
||||
if ($this->healthcheck()) {
|
||||
if ($this->server->log_drain_notification_sent) {
|
||||
$this->server->team?->notify(new ContainerRestarted('Coolify Log Drainer', $this->server));
|
||||
$this->server->update(['log_drain_notification_sent' => false]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (! $this->server->log_drain_notification_sent) {
|
||||
ray('Log drain container still unhealthy. Sending notification...');
|
||||
// $this->server->team?->notify(new ContainerStopped('Coolify Log Drainer', $this->server, null));
|
||||
$this->server->update(['log_drain_notification_sent' => true]);
|
||||
}
|
||||
} else {
|
||||
if ($this->server->log_drain_notification_sent) {
|
||||
$this->server->team?->notify(new ContainerRestarted('Coolify Log Drainer', $this->server));
|
||||
$this->server->update(['log_drain_notification_sent' => false]);
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
if (! isCloud()) {
|
||||
send_internal_notification("CheckLogDrainContainerJob failed on ({$this->server->id}) with: ".$e->getMessage());
|
||||
}
|
||||
ray($e->getMessage());
|
||||
|
||||
return handleError($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
app/Jobs/CleanupStaleMultiplexedConnections.php
Normal file
37
app/Jobs/CleanupStaleMultiplexedConnections.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Server;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
|
||||
class CleanupStaleMultiplexedConnections implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function handle()
|
||||
{
|
||||
Server::chunk(100, function ($servers) {
|
||||
foreach ($servers as $server) {
|
||||
$this->cleanupStaleConnection($server);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private function cleanupStaleConnection(Server $server)
|
||||
{
|
||||
$muxSocket = "/tmp/mux_{$server->id}";
|
||||
$checkCommand = "ssh -O check -o ControlPath=$muxSocket {$server->user}@{$server->ip} 2>/dev/null";
|
||||
$checkProcess = Process::run($checkCommand);
|
||||
|
||||
if ($checkProcess->exitCode() !== 0) {
|
||||
$closeCommand = "ssh -O exit -o ControlPath=$muxSocket {$server->user}@{$server->ip} 2>/dev/null";
|
||||
Process::run($closeCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Models\InstanceSettings;
|
||||
|
||||
class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
@@ -493,12 +494,15 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
} else {
|
||||
$network = $this->database->destination->network;
|
||||
}
|
||||
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro ghcr.io/coollabsio/coolify-helper";
|
||||
|
||||
$this->ensureHelperImageAvailable();
|
||||
|
||||
$fullImageName = $this->getFullImageName();
|
||||
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro {$fullImageName}";
|
||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key $secret";
|
||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc cp $this->backup_location temporary/$bucket{$this->backup_dir}/";
|
||||
instant_remote_process($commands, $this->server);
|
||||
$this->add_to_backup_output('Uploaded to S3.');
|
||||
ray('Uploaded to S3. '.$this->backup_location.' to s3://'.$bucket.$this->backup_dir);
|
||||
} catch (\Throwable $e) {
|
||||
$this->add_to_backup_output($e->getMessage());
|
||||
throw $e;
|
||||
@@ -507,4 +511,40 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
instant_remote_process([$command], $this->server);
|
||||
}
|
||||
}
|
||||
|
||||
private function ensureHelperImageAvailable(): void
|
||||
{
|
||||
$fullImageName = $this->getFullImageName();
|
||||
|
||||
$imageExists = $this->checkImageExists($fullImageName);
|
||||
|
||||
if (!$imageExists) {
|
||||
$this->pullHelperImage($fullImageName);
|
||||
}
|
||||
}
|
||||
|
||||
private function checkImageExists(string $fullImageName): bool
|
||||
{
|
||||
$result = instant_remote_process(["docker image inspect {$fullImageName} >/dev/null 2>&1 && echo 'exists' || echo 'not exists'"], $this->server, false);
|
||||
return trim($result) === 'exists';
|
||||
}
|
||||
|
||||
private function pullHelperImage(string $fullImageName): void
|
||||
{
|
||||
try {
|
||||
instant_remote_process(["docker pull {$fullImageName}"], $this->server);
|
||||
} catch (\Exception $e) {
|
||||
$errorMessage = "Failed to pull helper image: " . $e->getMessage();
|
||||
$this->add_to_backup_output($errorMessage);
|
||||
throw new \RuntimeException($errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private function getFullImageName(): string
|
||||
{
|
||||
$settings = InstanceSettings::get();
|
||||
$helperImage = config('coolify.helper_image');
|
||||
$latestVersion = $settings->helper_version;
|
||||
return "{$helperImage}:{$latestVersion}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Actions\Server\UpdateCoolify;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class InstanceAutoUpdateJob implements ShouldBeEncrypted, ShouldBeUnique, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 600;
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public function __construct() {}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
UpdateCoolify::run();
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class PullCoolifyImageJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
if (isDev() || isCloud()) {
|
||||
return;
|
||||
}
|
||||
$settings = InstanceSettings::get();
|
||||
$server = Server::findOrFail(0);
|
||||
$response = Http::retry(3, 1000)->get('https://cdn.coollabs.io/coolify/versions.json');
|
||||
if ($response->successful()) {
|
||||
$versions = $response->json();
|
||||
File::put(base_path('versions.json'), json_encode($versions, JSON_PRETTY_PRINT));
|
||||
}
|
||||
$latest_version = get_latest_version_of_coolify();
|
||||
instant_remote_process(["docker pull -q ghcr.io/coollabsio/coolify:{$latest_version}"], $server, false);
|
||||
|
||||
$current_version = config('version');
|
||||
if (! $settings->is_auto_update_enabled) {
|
||||
return;
|
||||
}
|
||||
if ($latest_version === $current_version) {
|
||||
return;
|
||||
}
|
||||
if (version_compare($latest_version, $current_version, '<')) {
|
||||
return;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
|
||||
@@ -10,6 +11,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
@@ -32,10 +34,20 @@ class PullHelperImageJob implements ShouldBeEncrypted, ShouldQueue
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
$helperImage = config('coolify.helper_image');
|
||||
ray("Pulling {$helperImage}");
|
||||
instant_remote_process(["docker pull -q {$helperImage}"], $this->server, false);
|
||||
ray('PullHelperImageJob done');
|
||||
$response = Http::retry(3, 1000)->get('https://cdn.coollabs.io/coolify/versions.json');
|
||||
if ($response->successful()) {
|
||||
$versions = $response->json();
|
||||
$settings = InstanceSettings::get();
|
||||
$latest_version = data_get($versions, 'coolify.helper.version');
|
||||
$current_version = $settings->helper_version;
|
||||
if (version_compare($latest_version, $current_version, '>')) {
|
||||
// New version available
|
||||
$helperImage = config('coolify.helper_image');
|
||||
instant_remote_process(["docker pull -q {$helperImage}:{$latest_version}"], $this->server);
|
||||
$settings->update(['helper_version' => $latest_version]);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
send_internal_notification('PullHelperImageJob failed with: '.$e->getMessage());
|
||||
ray($e->getMessage());
|
||||
|
||||
@@ -26,6 +26,8 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
public $tries = 3;
|
||||
|
||||
public $timeout = 60;
|
||||
|
||||
public $containers;
|
||||
|
||||
public $applications;
|
||||
@@ -43,15 +45,15 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
public function __construct(public Server $server) {}
|
||||
|
||||
// public function middleware(): array
|
||||
// {
|
||||
// return [(new WithoutOverlapping($this->server->uuid))];
|
||||
// }
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping($this->server->uuid))];
|
||||
}
|
||||
|
||||
// public function uniqueId(): int
|
||||
// {
|
||||
// return $this->server->uuid;
|
||||
// }
|
||||
public function uniqueId(): int
|
||||
{
|
||||
return $this->server->uuid;
|
||||
}
|
||||
|
||||
public function handle()
|
||||
{
|
||||
@@ -124,6 +126,9 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
private function checkLogDrainContainer()
|
||||
{
|
||||
if (! $this->server->isLogDrainEnabled()) {
|
||||
return;
|
||||
}
|
||||
$foundLogDrainContainer = $this->containers->filter(function ($value, $key) {
|
||||
return data_get($value, 'Name') === '/coolify-log-drain';
|
||||
})->first();
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Livewire\Project\Application\Deployment;
|
||||
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
|
||||
class Show extends Component
|
||||
@@ -69,6 +70,20 @@ class Show extends Component
|
||||
}
|
||||
}
|
||||
|
||||
public function getLogLinesProperty()
|
||||
{
|
||||
return decode_remote_command_output($this->application_deployment_queue)->map(function ($logLine) {
|
||||
$logLine['line'] = e($logLine['line']);
|
||||
$logLine['line'] = preg_replace(
|
||||
'/(https?:\/\/[^\s]+)/',
|
||||
'<a href="$1" target="_blank" rel="noopener noreferrer" class="underline text-neutral-400">$1</a>',
|
||||
$logLine['line'],
|
||||
);
|
||||
|
||||
return $logLine;
|
||||
});
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.application.deployment.show');
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Livewire;
|
||||
|
||||
use App\Actions\Server\UpdateCoolify;
|
||||
use App\Models\InstanceSettings;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Livewire\Component;
|
||||
|
||||
class Upgrade extends Component
|
||||
@@ -22,13 +21,8 @@ class Upgrade extends Component
|
||||
public function checkUpdate()
|
||||
{
|
||||
try {
|
||||
$settings = InstanceSettings::get();
|
||||
$response = Http::retry(3, 1000)->get('https://cdn.coollabs.io/coolify/versions.json');
|
||||
if ($response->successful()) {
|
||||
$versions = $response->json();
|
||||
$this->latestVersion = data_get($versions, 'coolify.v4.version');
|
||||
}
|
||||
$this->isUpgradeAvailable = $settings->new_version_available;
|
||||
$this->latestVersion = get_latest_version_of_coolify();
|
||||
$this->isUpgradeAvailable = data_get(InstanceSettings::get(), 'new_version_available', false);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
|
||||
@@ -11,6 +11,7 @@ use OpenApi\Attributes as OA;
|
||||
'id' => ['type' => 'integer'],
|
||||
'uuid' => ['type' => 'string'],
|
||||
'name' => ['type' => 'string'],
|
||||
'description' => ['type' => 'string'],
|
||||
'environments' => new OA\Property(
|
||||
property: 'environments',
|
||||
type: 'array',
|
||||
|
||||
@@ -22,7 +22,8 @@ class ScheduledDatabaseBackup extends BaseModel
|
||||
|
||||
public function executions(): HasMany
|
||||
{
|
||||
return $this->hasMany(ScheduledDatabaseBackupExecution::class);
|
||||
// Last execution first
|
||||
return $this->hasMany(ScheduledDatabaseBackupExecution::class)->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
public function s3()
|
||||
|
||||
@@ -28,6 +28,7 @@ class ScheduledTask extends BaseModel
|
||||
|
||||
public function executions(): HasMany
|
||||
{
|
||||
// Last execution first
|
||||
return $this->hasMany(ScheduledTaskExecution::class)->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
|
||||
@@ -880,7 +880,7 @@ $schema://$host {
|
||||
|
||||
public function muxFilename()
|
||||
{
|
||||
return "{$this->ip}_{$this->port}_{$this->user}";
|
||||
return $this->uuid;
|
||||
}
|
||||
|
||||
public function team()
|
||||
|
||||
@@ -1016,10 +1016,20 @@ class Service extends BaseModel
|
||||
$commands[] = 'rm -f .env || true';
|
||||
|
||||
$envs_from_coolify = $this->environment_variables()->get();
|
||||
foreach ($envs_from_coolify as $env) {
|
||||
$sorted = $envs_from_coolify->sortBy(function ($env) {
|
||||
if (str($env->key)->startsWith('SERVICE_')) {
|
||||
return 1;
|
||||
}
|
||||
if (str($env->value)->startsWith('$SERVICE_') || str($env->value)->startsWith('${SERVICE_')) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 3;
|
||||
});
|
||||
foreach ($sorted as $env) {
|
||||
$commands[] = "echo '{$env->key}={$env->real_value}' >> .env";
|
||||
}
|
||||
if ($envs_from_coolify->count() === 0) {
|
||||
if ($sorted->count() === 0) {
|
||||
$commands[] = 'touch .env';
|
||||
}
|
||||
instant_remote_process($commands, $this->server);
|
||||
|
||||
@@ -95,8 +95,26 @@ function generateScpCommand(Server $server, string $source, string $dest)
|
||||
$timeout = config('constants.ssh.command_timeout');
|
||||
$connectionTimeout = config('constants.ssh.connection_timeout');
|
||||
$serverInterval = config('constants.ssh.server_interval');
|
||||
$muxPersistTime = config('constants.ssh.mux_persist_time');
|
||||
|
||||
$scp_command = "timeout $timeout scp ";
|
||||
// Check if multiplexing is enabled
|
||||
$muxEnabled = config('constants.ssh.mux_enabled', true);
|
||||
// ray('SSH Multiplexing Enabled:', $muxEnabled)->blue();
|
||||
|
||||
if ($muxEnabled) {
|
||||
// Always use multiplexing when enabled
|
||||
$muxSocket = "/var/www/html/storage/app/ssh/mux/{$server->muxFilename()}";
|
||||
$scp_command .= "-o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} ";
|
||||
ensureMultiplexedConnection($server);
|
||||
// ray('Using SSH Multiplexing')->green();
|
||||
} else {
|
||||
// ray('Not using SSH Multiplexing')->red();
|
||||
}
|
||||
|
||||
if (data_get($server, 'settings.is_cloudflare_tunnel')) {
|
||||
$scp_command .= '-o ProxyCommand="/usr/local/bin/cloudflared access ssh --hostname %h" ';
|
||||
}
|
||||
$scp_command .= "-i {$privateKeyLocation} "
|
||||
.'-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '
|
||||
.'-o PasswordAuthentication=no '
|
||||
@@ -145,9 +163,20 @@ function generateSshCommand(Server $server, string $command)
|
||||
|
||||
$ssh_command = "timeout $timeout ssh ";
|
||||
|
||||
if (config('coolify.mux_enabled') && config('coolify.is_windows_docker_desktop') == false) {
|
||||
$ssh_command .= "-o ControlMaster=auto -o ControlPersist={$muxPersistTime} -o ControlPath=/var/www/html/storage/app/ssh/mux/%h_%p_%r ";
|
||||
// Check if multiplexing is enabled
|
||||
$muxEnabled = config('constants.ssh.mux_enabled', true);
|
||||
// ray('SSH Multiplexing Enabled:', $muxEnabled)->blue();
|
||||
|
||||
if ($muxEnabled) {
|
||||
// Always use multiplexing when enabled
|
||||
$muxSocket = "/var/www/html/storage/app/ssh/mux/{$server->muxFilename()}";
|
||||
$ssh_command .= "-o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} ";
|
||||
ensureMultiplexedConnection($server);
|
||||
// ray('Using SSH Multiplexing')->green();
|
||||
} else {
|
||||
// ray('Not using SSH Multiplexing')->red();
|
||||
}
|
||||
|
||||
if (data_get($server, 'settings.is_cloudflare_tunnel')) {
|
||||
$ssh_command .= '-o ProxyCommand="/usr/local/bin/cloudflared access ssh --hostname %h" ';
|
||||
}
|
||||
@@ -167,11 +196,100 @@ function generateSshCommand(Server $server, string $command)
|
||||
.$command.PHP_EOL
|
||||
.$delimiter;
|
||||
|
||||
// ray($ssh_command);
|
||||
return $ssh_command;
|
||||
}
|
||||
|
||||
function ensureMultiplexedConnection(Server $server)
|
||||
{
|
||||
static $ensuredConnections = [];
|
||||
|
||||
if (isset($ensuredConnections[$server->id])) {
|
||||
if (! shouldResetMultiplexedConnection($server)) {
|
||||
// ray('Using Existing Multiplexed Connection')->green();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$muxSocket = "/var/www/html/storage/app/ssh/mux/{$server->muxFilename()}";
|
||||
$checkCommand = "ssh -O check -o ControlPath=$muxSocket {$server->user}@{$server->ip} 2>/dev/null";
|
||||
|
||||
$process = Process::run($checkCommand);
|
||||
|
||||
if ($process->exitCode() === 0) {
|
||||
// ray('Existing Multiplexed Connection is Valid')->green();
|
||||
$ensuredConnections[$server->id] = [
|
||||
'timestamp' => now(),
|
||||
'muxSocket' => $muxSocket,
|
||||
];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// ray('Establishing New Multiplexed Connection')->orange();
|
||||
|
||||
$privateKeyLocation = savePrivateKeyToFs($server);
|
||||
$connectionTimeout = config('constants.ssh.connection_timeout');
|
||||
$serverInterval = config('constants.ssh.server_interval');
|
||||
$muxPersistTime = config('constants.ssh.mux_persist_time');
|
||||
|
||||
$establishCommand = "ssh -fNM -o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} "
|
||||
."-i {$privateKeyLocation} "
|
||||
.'-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null '
|
||||
.'-o PasswordAuthentication=no '
|
||||
."-o ConnectTimeout=$connectionTimeout "
|
||||
."-o ServerAliveInterval=$serverInterval "
|
||||
.'-o RequestTTY=no '
|
||||
.'-o LogLevel=ERROR '
|
||||
."-p {$server->port} "
|
||||
."{$server->user}@{$server->ip}";
|
||||
|
||||
$establishProcess = Process::run($establishCommand);
|
||||
|
||||
if ($establishProcess->exitCode() !== 0) {
|
||||
throw new \RuntimeException('Failed to establish multiplexed connection: '.$establishProcess->errorOutput());
|
||||
}
|
||||
|
||||
$ensuredConnections[$server->id] = [
|
||||
'timestamp' => now(),
|
||||
'muxSocket' => $muxSocket,
|
||||
];
|
||||
|
||||
// ray('Established New Multiplexed Connection')->green();
|
||||
}
|
||||
|
||||
function shouldResetMultiplexedConnection(Server $server)
|
||||
{
|
||||
static $ensuredConnections = [];
|
||||
|
||||
if (! isset($ensuredConnections[$server->id])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$lastEnsured = $ensuredConnections[$server->id]['timestamp'];
|
||||
$muxPersistTime = config('constants.ssh.mux_persist_time');
|
||||
$resetInterval = strtotime($muxPersistTime) - time();
|
||||
|
||||
return $lastEnsured->addSeconds($resetInterval)->isPast();
|
||||
}
|
||||
|
||||
function resetMultiplexedConnection(Server $server)
|
||||
{
|
||||
static $ensuredConnections = [];
|
||||
|
||||
if (isset($ensuredConnections[$server->id])) {
|
||||
$muxSocket = $ensuredConnections[$server->id]['muxSocket'];
|
||||
$closeCommand = "ssh -O exit -o ControlPath=$muxSocket {$server->user}@{$server->ip}";
|
||||
Process::run($closeCommand);
|
||||
unset($ensuredConnections[$server->id]);
|
||||
}
|
||||
}
|
||||
|
||||
function instant_remote_process(Collection|array $command, Server $server, bool $throwError = true, bool $no_sudo = false): ?string
|
||||
{
|
||||
static $processCount = 0;
|
||||
$processCount++;
|
||||
|
||||
$timeout = config('constants.ssh.command_timeout');
|
||||
if ($command instanceof Collection) {
|
||||
$command = $command->toArray();
|
||||
@@ -180,10 +298,18 @@ function instant_remote_process(Collection|array $command, Server $server, bool
|
||||
$command = parseCommandsByLineForSudo(collect($command), $server);
|
||||
}
|
||||
$command_string = implode("\n", $command);
|
||||
$ssh_command = generateSshCommand($server, $command_string, $no_sudo);
|
||||
$process = Process::timeout($timeout)->run($ssh_command);
|
||||
|
||||
$start_time = microtime(true);
|
||||
$sshCommand = generateSshCommand($server, $command_string);
|
||||
$process = Process::timeout($timeout)->run($sshCommand);
|
||||
$end_time = microtime(true);
|
||||
|
||||
$execution_time = ($end_time - $start_time) * 1000; // Convert to milliseconds
|
||||
// ray('SSH command execution time:', $execution_time.' ms')->orange();
|
||||
|
||||
$output = trim($process->output());
|
||||
$exitCode = $process->exitCode();
|
||||
|
||||
if ($exitCode !== 0) {
|
||||
if (! $throwError) {
|
||||
return null;
|
||||
@@ -223,7 +349,6 @@ function decode_remote_command_output(?ApplicationDeploymentQueue $application_d
|
||||
if (is_null($application_deployment_queue)) {
|
||||
return collect([]);
|
||||
}
|
||||
// ray(data_get($application_deployment_queue, 'logs'));
|
||||
try {
|
||||
$decoded = json_decode(
|
||||
data_get($application_deployment_queue, 'logs'),
|
||||
@@ -233,7 +358,7 @@ function decode_remote_command_output(?ApplicationDeploymentQueue $application_d
|
||||
} catch (\JsonException $exception) {
|
||||
return collect([]);
|
||||
}
|
||||
// ray($decoded );
|
||||
$seenCommands = collect();
|
||||
$formatted = collect($decoded);
|
||||
if (! $is_debug_enabled) {
|
||||
$formatted = $formatted->filter(fn ($i) => $i['hidden'] === false ?? false);
|
||||
@@ -244,7 +369,42 @@ function decode_remote_command_output(?ApplicationDeploymentQueue $application_d
|
||||
data_set($i, 'timestamp', Carbon::parse(data_get($i, 'timestamp'))->format('Y-M-d H:i:s.u'));
|
||||
|
||||
return $i;
|
||||
});
|
||||
})
|
||||
->reduce(function ($deploymentLogLines, $logItem) use ($seenCommands) {
|
||||
$command = data_get($logItem, 'command');
|
||||
$isStderr = data_get($logItem, 'type') === 'stderr';
|
||||
$isNewCommand = ! is_null($command) && ! $seenCommands->first(function ($seenCommand) use ($logItem) {
|
||||
return data_get($seenCommand, 'command') === data_get($logItem, 'command') && data_get($seenCommand, 'batch') === data_get($logItem, 'batch');
|
||||
});
|
||||
|
||||
if ($isNewCommand) {
|
||||
$deploymentLogLines->push([
|
||||
'line' => $command,
|
||||
'timestamp' => data_get($logItem, 'timestamp'),
|
||||
'stderr' => $isStderr,
|
||||
'hidden' => data_get($logItem, 'hidden'),
|
||||
'command' => true,
|
||||
]);
|
||||
|
||||
$seenCommands->push([
|
||||
'command' => $command,
|
||||
'batch' => data_get($logItem, 'batch'),
|
||||
]);
|
||||
}
|
||||
|
||||
$lines = explode(PHP_EOL, data_get($logItem, 'output'));
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$deploymentLogLines->push([
|
||||
'line' => $line,
|
||||
'timestamp' => data_get($logItem, 'timestamp'),
|
||||
'stderr' => $isStderr,
|
||||
'hidden' => data_get($logItem, 'hidden'),
|
||||
]);
|
||||
}
|
||||
|
||||
return $deploymentLogLines;
|
||||
}, collect());
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
@@ -258,6 +418,10 @@ function remove_mux_and_private_key(Server $server)
|
||||
{
|
||||
$muxFilename = $server->muxFilename();
|
||||
$privateKeyLocation = savePrivateKeyToFs($server);
|
||||
|
||||
$closeCommand = "ssh -O exit -o ControlPath=/var/www/html/storage/app/ssh/mux/{$muxFilename} {$server->user}@{$server->ip}";
|
||||
Process::run($closeCommand);
|
||||
|
||||
Storage::disk('ssh-mux')->delete($muxFilename);
|
||||
Storage::disk('ssh-keys')->delete($privateKeyLocation);
|
||||
}
|
||||
@@ -267,7 +431,10 @@ function refresh_server_connection(?PrivateKey $private_key = null)
|
||||
return;
|
||||
}
|
||||
foreach ($private_key->servers as $server) {
|
||||
Storage::disk('ssh-mux')->delete($server->muxFilename());
|
||||
$muxFilename = $server->muxFilename();
|
||||
$closeCommand = "ssh -O exit -o ControlPath=/var/www/html/storage/app/ssh/mux/{$muxFilename} {$server->user}@{$server->ip}";
|
||||
Process::run($closeCommand);
|
||||
Storage::disk('ssh-mux')->delete($muxFilename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,24 +444,17 @@ function checkRequiredCommands(Server $server)
|
||||
foreach ($commands as $command) {
|
||||
$commandFound = instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'command -v {$command}'"], $server, false);
|
||||
if ($commandFound) {
|
||||
ray($command.' found');
|
||||
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'apt update && apt install -y {$command}'"], $server);
|
||||
} catch (\Throwable $e) {
|
||||
ray('could not install '.$command);
|
||||
ray($e);
|
||||
break;
|
||||
}
|
||||
$commandFound = instant_remote_process(["docker run --rm --privileged --net=host --pid=host --ipc=host --volume /:/host busybox chroot /host bash -c 'command -v {$command}'"], $server, false);
|
||||
if ($commandFound) {
|
||||
ray($command.' found');
|
||||
|
||||
continue;
|
||||
}
|
||||
ray('could not install '.$command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use App\Models\Application;
|
||||
use App\Models\EnvironmentVariable;
|
||||
use App\Models\ServiceApplication;
|
||||
use App\Models\ServiceDatabase;
|
||||
use Illuminate\Support\Stringable;
|
||||
use Spatie\Url\Url;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
@@ -15,9 +16,9 @@ function collectRegex(string $name)
|
||||
{
|
||||
return "/{$name}\w+/";
|
||||
}
|
||||
function replaceVariables($variable)
|
||||
function replaceVariables(string $variable): Stringable
|
||||
{
|
||||
return $variable->before('}')->replaceFirst('$', '')->replaceFirst('{', '');
|
||||
return str($variable)->before('}')->replaceFirst('$', '')->replaceFirst('{', '');
|
||||
}
|
||||
|
||||
function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Application $oneService, bool $isInit = false)
|
||||
|
||||
@@ -1866,7 +1866,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
'key' => $key,
|
||||
'service_id' => $resource->id,
|
||||
])->first();
|
||||
$value = str(replaceVariables($value));
|
||||
$value = replaceVariables($value);
|
||||
$key = $value;
|
||||
if ($value->startsWith('SERVICE_')) {
|
||||
$foundEnv = EnvironmentVariable::where([
|
||||
@@ -2627,7 +2627,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
'application_id' => $resource->id,
|
||||
'is_preview' => false,
|
||||
])->first();
|
||||
$value = str(replaceVariables($value));
|
||||
$value = replaceVariables($value);
|
||||
$key = $value;
|
||||
if ($value->startsWith('SERVICE_')) {
|
||||
$foundEnv = EnvironmentVariable::where([
|
||||
@@ -2864,6 +2864,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
return collect($finalServices);
|
||||
}
|
||||
}
|
||||
|
||||
function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $preview_id = null): Collection
|
||||
{
|
||||
$isApplication = $resource instanceof Application;
|
||||
@@ -2920,6 +2921,182 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
}
|
||||
|
||||
$parsedServices = collect([]);
|
||||
ray()->clearAll();
|
||||
|
||||
$allMagicEnvironments = collect([]);
|
||||
foreach ($services as $serviceName => $service) {
|
||||
$magicEnvironments = collect([]);
|
||||
$image = data_get_str($service, 'image');
|
||||
$environment = collect(data_get($service, 'environment', []));
|
||||
$buildArgs = collect(data_get($service, 'build.args', []));
|
||||
$environment = $environment->merge($buildArgs);
|
||||
$isDatabase = isDatabaseImage(data_get_str($service, 'image'));
|
||||
|
||||
if ($isService) {
|
||||
if ($isDatabase) {
|
||||
$savedService = ServiceDatabase::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
'image' => $image,
|
||||
'service_id' => $resource->id,
|
||||
]);
|
||||
} else {
|
||||
$savedService = ServiceApplication::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
'image' => $image,
|
||||
'service_id' => $resource->id,
|
||||
]);
|
||||
}
|
||||
$environment = collect(data_get($service, 'environment', []));
|
||||
$buildArgs = collect(data_get($service, 'build.args', []));
|
||||
$environment = $environment->merge($buildArgs);
|
||||
|
||||
// convert environment variables to one format
|
||||
$environment = convertComposeEnvironmentToArray($environment);
|
||||
|
||||
// Add Coolify defined environments
|
||||
$allEnvironments = $resource->environment_variables()->get(['key', 'value']);
|
||||
|
||||
$allEnvironments = $allEnvironments->mapWithKeys(function ($item) {
|
||||
return [$item['key'] => $item['value']];
|
||||
});
|
||||
// filter and add magic environments
|
||||
foreach ($environment as $key => $value) {
|
||||
// Get all SERVICE_ variables from keys and values
|
||||
$key = str($key);
|
||||
$value = str($value);
|
||||
|
||||
$regex = '/\$(\{?([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\}?)/';
|
||||
preg_match_all($regex, $value, $valueMatches);
|
||||
if (count($valueMatches[1]) > 0) {
|
||||
foreach ($valueMatches[1] as $match) {
|
||||
$match = replaceVariables($match);
|
||||
if ($match->startsWith('SERVICE_')) {
|
||||
if ($magicEnvironments->has($match->value())) {
|
||||
continue;
|
||||
}
|
||||
$magicEnvironments->put($match->value(), '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get magic environments where we need to preset the FQDN
|
||||
if ($key->startsWith('SERVICE_FQDN_')) {
|
||||
// SERVICE_FQDN_APP or SERVICE_FQDN_APP_3000
|
||||
$fqdnFor = $key->after('SERVICE_FQDN_')->lower()->value();
|
||||
if ($isApplication) {
|
||||
$fqdn = generateFqdn($server, "{$resource->name}-$uuid");
|
||||
} elseif ($isService) {
|
||||
if ($fqdnFor) {
|
||||
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
|
||||
} else {
|
||||
$fqdn = generateFqdn($server, "{$savedService->name}-$uuid");
|
||||
}
|
||||
}
|
||||
if ($value && get_class($value) === 'Illuminate\Support\Stringable' && $value->startsWith('/')) {
|
||||
$path = $value->value();
|
||||
if ($path !== '/') {
|
||||
$fqdn = "$fqdn$path";
|
||||
}
|
||||
}
|
||||
if ($isApplication && is_null($resource->fqdn)) {
|
||||
data_forget($resource, 'environment_variables');
|
||||
data_forget($resource, 'environment_variables_preview');
|
||||
$resource->fqdn = $fqdn;
|
||||
$resource->save();
|
||||
} elseif ($isService && is_null($savedService->fqdn)) {
|
||||
$savedService->fqdn = $fqdn;
|
||||
$savedService->save();
|
||||
}
|
||||
|
||||
if (substr_count(str($key)->value(), '_') === 2) {
|
||||
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key->value(),
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $fqdn,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
}
|
||||
if (substr_count(str($key)->value(), '_') === 3) {
|
||||
$newKey = str($key)->beforeLast('_');
|
||||
$resource->environment_variables()->where('key', $newKey->value())->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $newKey->value(),
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $fqdn,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$allMagicEnvironments = $allMagicEnvironments->merge($magicEnvironments);
|
||||
|
||||
if ($magicEnvironments->count() > 0) {
|
||||
foreach ($magicEnvironments as $key => $value) {
|
||||
$key = str($key);
|
||||
$value = replaceVariables($value);
|
||||
$command = $key->after('SERVICE_')->before('_');
|
||||
$found = $resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->first();
|
||||
if ($found) {
|
||||
continue;
|
||||
}
|
||||
if ($command->value() === 'FQDN') {
|
||||
$fqdnFor = $key->after('SERVICE_FQDN_')->lower()->value();
|
||||
if (str($fqdnFor)->contains('_')) {
|
||||
$fqdnFor = str($fqdnFor)->before('_');
|
||||
}
|
||||
if ($isApplication) {
|
||||
$fqdn = generateFqdn($server, "{$resource->name}-$uuid");
|
||||
} elseif ($isService) {
|
||||
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
|
||||
}
|
||||
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key->value(),
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $fqdn,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
} elseif ($command->value() === 'URL') {
|
||||
$fqdnFor = $key->after('SERVICE_URL_')->lower()->value();
|
||||
if (str($fqdnFor)->contains('_')) {
|
||||
$fqdnFor = str($fqdnFor)->before('_');
|
||||
}
|
||||
if ($isApplication) {
|
||||
$fqdn = generateFqdn($server, "{$resource->name}-$uuid");
|
||||
} elseif ($isService) {
|
||||
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
|
||||
}
|
||||
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key->value(),
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $fqdn,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
} else {
|
||||
$value = generateEnvValue($command, $resource);
|
||||
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key->value(),
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $value,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the rest of the services
|
||||
foreach ($services as $serviceName => $service) {
|
||||
$image = data_get_str($service, 'image');
|
||||
$restart = data_get_str($service, 'restart', RESTART_MODE);
|
||||
@@ -2932,12 +3109,17 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
}
|
||||
$volumes = collect(data_get($service, 'volumes', []));
|
||||
$networks = collect(data_get($service, 'networks', []));
|
||||
$use_network_mode = data_get($service, 'network_mode') !== null;
|
||||
$depends_on = collect(data_get($service, 'depends_on', []));
|
||||
$labels = collect(data_get($service, 'labels', []));
|
||||
$environment = collect(data_get($service, 'environment', []));
|
||||
$ports = collect(data_get($service, 'ports', []));
|
||||
$buildArgs = collect(data_get($service, 'build.args', []));
|
||||
$environment = $environment->merge($buildArgs);
|
||||
|
||||
$environment = convertComposeEnvironmentToArray($environment);
|
||||
$coolifyEnvironments = collect([]);
|
||||
|
||||
$isDatabase = isDatabaseImage(data_get_str($service, 'image'));
|
||||
$volumesParsed = collect([]);
|
||||
|
||||
@@ -3069,10 +3251,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
if ($topLevel->get('volumes')->has($source->value())) {
|
||||
$temp = $topLevel->get('volumes')->get($source->value());
|
||||
if (data_get($temp, 'driver_opts.type') === 'cifs') {
|
||||
return $volume;
|
||||
continue;
|
||||
}
|
||||
if (data_get($temp, 'driver_opts.type') === 'nfs') {
|
||||
return $volume;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$slugWithoutUuid = Str::slug($source, '-');
|
||||
@@ -3127,32 +3309,34 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
$depends_on = $newDependsOn;
|
||||
}
|
||||
}
|
||||
if ($topLevel->get('networks')?->count() > 0) {
|
||||
foreach ($topLevel->get('networks') as $networkName => $network) {
|
||||
if ($networkName === 'default') {
|
||||
continue;
|
||||
}
|
||||
// ignore aliases
|
||||
if ($network['aliases'] ?? false) {
|
||||
continue;
|
||||
}
|
||||
$networkExists = $networks->contains(function ($value, $key) use ($networkName) {
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
if (! $networkExists) {
|
||||
$networks->put($networkName, null);
|
||||
if (! $use_network_mode) {
|
||||
if ($topLevel->get('networks')?->count() > 0) {
|
||||
foreach ($topLevel->get('networks') as $networkName => $network) {
|
||||
if ($networkName === 'default') {
|
||||
continue;
|
||||
}
|
||||
// ignore aliases
|
||||
if ($network['aliases'] ?? false) {
|
||||
continue;
|
||||
}
|
||||
$networkExists = $networks->contains(function ($value, $key) use ($networkName) {
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
if (! $networkExists) {
|
||||
$networks->put($networkName, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$baseNetworkExists = $networks->contains(function ($value, $_) use ($baseNetwork) {
|
||||
return $value == $baseNetwork;
|
||||
});
|
||||
if (! $baseNetworkExists) {
|
||||
foreach ($baseNetwork as $network) {
|
||||
$topLevel->get('networks')->put($network, [
|
||||
'name' => $network,
|
||||
'external' => true,
|
||||
]);
|
||||
$baseNetworkExists = $networks->contains(function ($value, $_) use ($baseNetwork) {
|
||||
return $value == $baseNetwork;
|
||||
});
|
||||
if (! $baseNetworkExists) {
|
||||
foreach ($baseNetwork as $network) {
|
||||
$topLevel->get('networks')->put($network, [
|
||||
'name' => $network,
|
||||
'external' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3178,180 +3362,46 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
|
||||
$networks_temp = collect();
|
||||
|
||||
foreach ($networks as $key => $network) {
|
||||
if (gettype($network) === 'string') {
|
||||
// networks:
|
||||
// - appwrite
|
||||
$networks_temp->put($network, null);
|
||||
} elseif (gettype($network) === 'array') {
|
||||
// networks:
|
||||
// default:
|
||||
// ipv4_address: 192.168.203.254
|
||||
$networks_temp->put($key, $network);
|
||||
if (! $use_network_mode) {
|
||||
foreach ($networks as $key => $network) {
|
||||
if (gettype($network) === 'string') {
|
||||
// networks:
|
||||
// - appwrite
|
||||
$networks_temp->put($network, null);
|
||||
} elseif (gettype($network) === 'array') {
|
||||
// networks:
|
||||
// default:
|
||||
// ipv4_address: 192.168.203.254
|
||||
$networks_temp->put($key, $network);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($baseNetwork as $key => $network) {
|
||||
$networks_temp->put($network, null);
|
||||
}
|
||||
|
||||
if ($isApplication) {
|
||||
if (data_get($resource, 'settings.connect_to_docker_network')) {
|
||||
$network = $resource->destination->network;
|
||||
foreach ($baseNetwork as $key => $network) {
|
||||
$networks_temp->put($network, null);
|
||||
$topLevel->get('networks')->put($network, [
|
||||
'name' => $network,
|
||||
'external' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
// convert environment variables to one format
|
||||
$environment = convertComposeEnvironmentToArray($environment);
|
||||
|
||||
// Add Coolify defined environments
|
||||
$allEnvironments = $resource->environment_variables()->get(['key', 'value']);
|
||||
|
||||
$allEnvironments = $allEnvironments->mapWithKeys(function ($item) {
|
||||
return [$item['key'] => $item['value']];
|
||||
});
|
||||
|
||||
// remove $environment from $allEnvironments
|
||||
$coolifyDefinedEnvironments = $allEnvironments->diffKeys($environment);
|
||||
|
||||
// filter magic environments
|
||||
$magicEnvironments = $environment->filter(function ($value, $key) {
|
||||
$value = str(replaceVariables(str($value)));
|
||||
|
||||
return str($key)->startsWith('SERVICE_') || str($value)->startsWith('SERVICE_');
|
||||
});
|
||||
$normalEnvironments = $environment->diffKeys($magicEnvironments);
|
||||
if ($magicEnvironments->count() > 0) {
|
||||
foreach ($magicEnvironments as $key => $value) {
|
||||
$key = str($key);
|
||||
$value = str(replaceVariables(str($value)));
|
||||
$originalValue = $value;
|
||||
$keyCommand = $key->after('SERVICE_')->before('_');
|
||||
$valueCommand = $value->after('SERVICE_')->before('_');
|
||||
if ($key->startsWith('SERVICE_FQDN_')) {
|
||||
$fqdnFor = $key->after('SERVICE_FQDN_')->lower()->value();
|
||||
if (str($fqdnFor)->contains('_')) {
|
||||
$fqdnFor = str($fqdnFor)->before('_');
|
||||
}
|
||||
} elseif ($value->startsWith('SERVICE_FQDN_')) {
|
||||
$fqdnFor = $value->after('SERVICE_FQDN_')->lower()->value();
|
||||
if (str($fqdnFor)->contains('_')) {
|
||||
$fqdnFor = str($fqdnFor)->before('_');
|
||||
}
|
||||
} else {
|
||||
$fqdnFor = null;
|
||||
}
|
||||
if ($keyCommand->value() === 'FQDN' || $valueCommand->value() === 'FQDN') {
|
||||
if ($isApplication) {
|
||||
$fqdn = generateFqdn($server, "{$resource->name}-$uuid");
|
||||
} elseif ($isService) {
|
||||
if ($fqdnFor) {
|
||||
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
|
||||
} else {
|
||||
$fqdn = generateFqdn($server, "{$savedService->name}-$uuid");
|
||||
}
|
||||
}
|
||||
if ($value && get_class($value) === 'Illuminate\Support\Stringable' && $value->startsWith('/')) {
|
||||
$path = $value->value();
|
||||
if ($value === '/') {
|
||||
$value = "$fqdn";
|
||||
} else {
|
||||
$value = "$fqdn$path";
|
||||
}
|
||||
} else {
|
||||
$value = $fqdn;
|
||||
}
|
||||
if (! $isDatabase) {
|
||||
if ($isApplication && is_null($resource->fqdn)) {
|
||||
data_forget($resource, 'environment_variables');
|
||||
data_forget($resource, 'environment_variables_preview');
|
||||
$resource->fqdn = $value;
|
||||
$resource->save();
|
||||
} elseif ($isService && is_null($savedService->fqdn)) {
|
||||
if ($key->startsWith('SERVICE_FQDN_')) {
|
||||
$savedService->fqdn = $value;
|
||||
$savedService->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ($keyCommand->value() === 'URL' || $valueCommand->value() === 'URL') {
|
||||
if ($isApplication) {
|
||||
$fqdn = generateFqdn($server, "{$resource->name}-{$uuid}");
|
||||
} elseif ($isService) {
|
||||
$fqdn = generateFqdn($server, "{$savedService->name}-{$uuid}");
|
||||
}
|
||||
if ($value && get_class($value) === 'Illuminate\Support\Stringable' && $value->startsWith('/')) {
|
||||
$path = $value->value();
|
||||
$value = "$fqdn$path";
|
||||
} else {
|
||||
$value = $fqdn;
|
||||
}
|
||||
$value = str($fqdn)->replace('http://', '')->replace('https://', '');
|
||||
} else {
|
||||
$generatedValue = generateEnvValue($valueCommand, $resource);
|
||||
if ($generatedValue) {
|
||||
$value = $generatedValue;
|
||||
}
|
||||
}
|
||||
if (str($fqdnFor)->startsWith('/')) {
|
||||
$fqdnFor = null;
|
||||
}
|
||||
// Lets save the magic value to the environment variables
|
||||
if (! $originalValue->startsWith('/')) {
|
||||
if ($key->startsWith('SERVICE_')) {
|
||||
$originalValue = $key;
|
||||
}
|
||||
$resource->environment_variables()->where('key', $originalValue->value())->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $originalValue->value(),
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $value,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
if ($isApplication) {
|
||||
if (data_get($resource, 'settings.connect_to_docker_network')) {
|
||||
$network = $resource->destination->network;
|
||||
$networks_temp->put($network, null);
|
||||
$topLevel->get('networks')->put($network, [
|
||||
'name' => $network,
|
||||
'external' => true,
|
||||
]);
|
||||
}
|
||||
// Save the original value to the environment variables
|
||||
if ($originalValue->startsWith('SERVICE_')) {
|
||||
$value = "$$originalValue";
|
||||
}
|
||||
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key->value(),
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => "$value",
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$normalEnvironments = $environment->diffKeys($allMagicEnvironments);
|
||||
$normalEnvironments = $normalEnvironments->filter(function ($value, $key) {
|
||||
return ! str($value)->startsWith('SERVICE_');
|
||||
});
|
||||
|
||||
foreach ($normalEnvironments as $key => $value) {
|
||||
$key = str($key);
|
||||
$value = str($value);
|
||||
if ($value->startsWith('$') || $value->contains('${')) {
|
||||
if ($value->contains('${')) {
|
||||
$value = $value->after('${')->before('}');
|
||||
}
|
||||
$value = str(replaceVariables(str($value)));
|
||||
if ($value->contains(':-')) {
|
||||
$key = $value->before(':');
|
||||
$value = $value->after(':-');
|
||||
} elseif ($value->contains('-')) {
|
||||
$key = $value->before('-');
|
||||
$value = $value->after('-');
|
||||
} elseif ($value->contains(':?')) {
|
||||
$key = $value->before(':');
|
||||
$value = $value->after(':?');
|
||||
} elseif ($value->contains('?')) {
|
||||
$key = $value->before('?');
|
||||
$value = $value->after('?');
|
||||
} else {
|
||||
$key = $value;
|
||||
$value = null;
|
||||
}
|
||||
$originalValue = $value;
|
||||
$parsedValue = replaceVariables($value);
|
||||
if ($value->startsWith('$SERVICE_')) {
|
||||
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key,
|
||||
$nameOfId => $resource->id,
|
||||
@@ -3360,6 +3410,57 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
if (! $value->startsWith('$')) {
|
||||
continue;
|
||||
}
|
||||
if ($key->value() === $parsedValue->value()) {
|
||||
$value = null;
|
||||
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key,
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $value,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
} else {
|
||||
if ($value->startsWith('$')) {
|
||||
if ($value->contains(':-')) {
|
||||
$value = replaceVariables($value);
|
||||
$key = $value->before(':');
|
||||
$value = $value->after(':-');
|
||||
} elseif ($value->contains('-')) {
|
||||
$value = replaceVariables($value);
|
||||
|
||||
$key = $value->before('-');
|
||||
$value = $value->after('-');
|
||||
} elseif ($value->contains(':?')) {
|
||||
$value = replaceVariables($value);
|
||||
|
||||
$key = $value->before(':');
|
||||
$value = $value->after(':?');
|
||||
} elseif ($value->contains('?')) {
|
||||
$value = replaceVariables($value);
|
||||
|
||||
$key = $value->before('?');
|
||||
$value = $value->after('?');
|
||||
}
|
||||
if ($originalValue->value() === $value->value()) {
|
||||
continue;
|
||||
}
|
||||
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
|
||||
'key' => $key,
|
||||
$nameOfId => $resource->id,
|
||||
], [
|
||||
'value' => $value,
|
||||
'is_build_time' => false,
|
||||
'is_preview' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if ($isApplication) {
|
||||
@@ -3368,13 +3469,13 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
$branch = "pull/{$pullRequestId}/head";
|
||||
}
|
||||
if ($originalResource->environment_variables->where('key', 'COOLIFY_BRANCH')->isEmpty()) {
|
||||
$environment->put('COOLIFY_BRANCH', $branch);
|
||||
$coolifyEnvironments->put('COOLIFY_BRANCH', $branch);
|
||||
}
|
||||
}
|
||||
|
||||
// Add COOLIFY_CONTAINER_NAME to environment
|
||||
if ($resource->environment_variables->where('key', 'COOLIFY_CONTAINER_NAME')->isEmpty()) {
|
||||
$environment->put('COOLIFY_CONTAINER_NAME', $containerName);
|
||||
$coolifyEnvironments->put('COOLIFY_CONTAINER_NAME', $containerName);
|
||||
}
|
||||
|
||||
if ($isApplication) {
|
||||
@@ -3428,15 +3529,20 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
}
|
||||
// Add COOLIFY_FQDN & COOLIFY_URL to environment
|
||||
if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) {
|
||||
$environment->put('COOLIFY_URL', $fqdns->implode(','));
|
||||
$coolifyEnvironments->put('COOLIFY_URL', $fqdns->implode(','));
|
||||
|
||||
$urls = $fqdns->map(function ($fqdn) {
|
||||
return str($fqdn)->replace('http://', '')->replace('https://', '');
|
||||
});
|
||||
$environment->put('COOLIFY_FQDN', $urls->implode(','));
|
||||
$coolifyEnvironments->put('COOLIFY_FQDN', $urls->implode(','));
|
||||
}
|
||||
add_coolify_default_environment_variables($resource, $environment, $resource->environment_variables);
|
||||
add_coolify_default_environment_variables($resource, $coolifyEnvironments, $resource->environment_variables);
|
||||
|
||||
if ($environment->count() > 0) {
|
||||
$environment = $environment->filter(function ($value, $key) {
|
||||
return ! str($key)->startsWith('SERVICE_FQDN_');
|
||||
});
|
||||
}
|
||||
$serviceLabels = $labels->merge($defaultLabels);
|
||||
if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) {
|
||||
if ($isApplication) {
|
||||
@@ -3522,17 +3628,19 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
$payload = collect($service)->merge([
|
||||
'container_name' => $containerName,
|
||||
'restart' => $restart->value(),
|
||||
'networks' => $networks_temp,
|
||||
'labels' => $serviceLabels,
|
||||
]);
|
||||
if (! $use_network_mode) {
|
||||
$payload['networks'] = $networks_temp;
|
||||
}
|
||||
if ($ports->count() > 0) {
|
||||
$payload['ports'] = $ports;
|
||||
}
|
||||
if ($volumesParsed->count() > 0) {
|
||||
$payload['volumes'] = $volumesParsed;
|
||||
}
|
||||
if ($environment->count() > 0 || $coolifyDefinedEnvironments->count() > 0) {
|
||||
$payload['environment'] = $environment->merge($coolifyDefinedEnvironments);
|
||||
if ($environment->count() > 0 || $coolifyEnvironments->count() > 0) {
|
||||
$payload['environment'] = $environment->merge($coolifyEnvironments);
|
||||
}
|
||||
if ($logging) {
|
||||
$payload['logging'] = $logging;
|
||||
|
||||
@@ -6,7 +6,8 @@ return [
|
||||
'contact' => 'https://coolify.io/docs/contact',
|
||||
],
|
||||
'ssh' => [
|
||||
'mux_persist_time' => env('SSH_MUX_PERSIST_TIME', '1m'),
|
||||
'mux_enabled' => env('SSH_MUX_ENABLED', true),
|
||||
'mux_persist_time' => env('SSH_MUX_PERSIST_TIME', '1h'),
|
||||
'connection_timeout' => 10,
|
||||
'server_interval' => 20,
|
||||
'command_timeout' => 7200,
|
||||
|
||||
@@ -11,7 +11,7 @@ return [
|
||||
'dev_webhook' => env('SERVEO_URL'),
|
||||
'is_windows_docker_desktop' => env('IS_WINDOWS_DOCKER_DESKTOP', false),
|
||||
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
|
||||
'helper_image' => env('HELPER_IMAGE', 'ghcr.io/coollabsio/coolify-helper:latest'),
|
||||
'helper_image' => env('HELPER_IMAGE', 'ghcr.io/coollabsio/coolify-helper'),
|
||||
'is_horizon_enabled' => env('HORIZON_ENABLED', true),
|
||||
'is_scheduler_enabled' => env('SCHEDULER_ENABLED', true),
|
||||
];
|
||||
|
||||
@@ -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.329',
|
||||
'release' => '4.0.0-beta.332',
|
||||
// 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.329';
|
||||
return '4.0.0-beta.332';
|
||||
|
||||
@@ -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('instance_settings', function (Blueprint $table) {
|
||||
$table->string('helper_version')->default('1.0.0');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('instance_settings', function (Blueprint $table) {
|
||||
$table->dropColumn('helper_version');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use App\Models\ServerSetting;
|
||||
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('server_settings', function (Blueprint $table) {
|
||||
$table->boolean('force_docker_cleanup')->default(true)->change();
|
||||
});
|
||||
$serverSettings = ServerSetting::all();
|
||||
foreach ($serverSettings as $serverSetting) {
|
||||
if ($serverSetting->force_docker_cleanup === false) {
|
||||
$serverSetting->force_docker_cleanup = true;
|
||||
$serverSetting->docker_cleanup_frequency = '*/10 * * * *';
|
||||
$serverSetting->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->boolean('force_docker_cleanup')->default(false)->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use App\Models\ServerSetting;
|
||||
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('server_settings', function (Blueprint $table) {
|
||||
$table->string('docker_cleanup_frequency')->default('0 0 * * *')->change();
|
||||
});
|
||||
|
||||
$serverSettings = ServerSetting::all();
|
||||
foreach ($serverSettings as $serverSetting) {
|
||||
if ($serverSetting->force_docker_cleanup && $serverSetting->docker_cleanup_frequency === '*/10 * * * *') {
|
||||
$serverSetting->docker_cleanup_frequency = '0 0 * * *';
|
||||
$serverSetting->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->string('docker_cleanup_frequency')->default('*/10 * * * *')->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class UpdateServerSettingsDefaultTimezone extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->string('server_timezone')->default('UTC')->change();
|
||||
});
|
||||
|
||||
DB::table('server_settings')
|
||||
->whereNull('server_timezone')
|
||||
->orWhere('server_timezone', '')
|
||||
->update(['server_timezone' => 'UTC']);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::table('server_settings', function (Blueprint $table) {
|
||||
$table->string('server_timezone')->default('')->change();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ ARG DOCKER_COMPOSE_VERSION=2.27.1
|
||||
# https://github.com/docker/buildx/releases
|
||||
ARG DOCKER_BUILDX_VERSION=0.14.1
|
||||
# https://github.com/buildpacks/pack/releases
|
||||
ARG PACK_VERSION=0.34.1
|
||||
ARG PACK_VERSION=0.35.1
|
||||
# https://github.com/railwayapp/nixpacks/releases
|
||||
ARG NIXPACKS_VERSION=1.24.1
|
||||
ARG NIXPACKS_VERSION=1.28.0
|
||||
|
||||
USER root
|
||||
WORKDIR /artifacts
|
||||
|
||||
276
openapi.yaml
276
openapi.yaml
@@ -2831,7 +2831,7 @@ paths:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'Deployment Uuid'
|
||||
description: 'Deployment UUID'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -2879,7 +2879,7 @@ paths:
|
||||
type: boolean
|
||||
responses:
|
||||
'200':
|
||||
description: "Get deployment(s) Uuid's"
|
||||
description: "Get deployment(s) UUID's"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -2993,7 +2993,7 @@ paths:
|
||||
tags:
|
||||
- Projects
|
||||
summary: List
|
||||
description: 'list projects.'
|
||||
description: 'List projects.'
|
||||
operationId: list-projects
|
||||
responses:
|
||||
'200':
|
||||
@@ -3024,7 +3024,7 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
uuid:
|
||||
name:
|
||||
type: string
|
||||
description: 'The name of the project.'
|
||||
description:
|
||||
@@ -3054,7 +3054,7 @@ paths:
|
||||
tags:
|
||||
- Projects
|
||||
summary: Get
|
||||
description: 'Get project by Uuid.'
|
||||
description: 'Get project by UUID.'
|
||||
operationId: get-project-by-uuid
|
||||
parameters:
|
||||
-
|
||||
@@ -3323,7 +3323,7 @@ paths:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'Private Key Uuid'
|
||||
description: 'Private Key UUID'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -3355,7 +3355,7 @@ paths:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'Private Key Uuid'
|
||||
description: 'Private Key UUID'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -3475,7 +3475,7 @@ paths:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: "Server's Uuid"
|
||||
description: "Server's UUID"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -3595,7 +3595,7 @@ paths:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: "Server's Uuid"
|
||||
description: "Server's UUID"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -3627,7 +3627,7 @@ paths:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: "Server's Uuid"
|
||||
description: "Server's UUID"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
@@ -3784,7 +3784,7 @@ paths:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: 'Get a service by Uuid.'
|
||||
description: 'Get a service by UUID.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -3814,7 +3814,7 @@ paths:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: 'Delete a service by Uuid'
|
||||
description: 'Delete a service by UUID'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -3830,6 +3830,256 @@ paths:
|
||||
security:
|
||||
-
|
||||
bearerAuth: []
|
||||
'/services/{uuid}/envs':
|
||||
get:
|
||||
tags:
|
||||
- Services
|
||||
summary: 'List Envs'
|
||||
description: 'List all envs by service UUID.'
|
||||
operationId: list-envs-by-service-uuid
|
||||
parameters:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'UUID of the service.'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: 'All environment variables by service UUID.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/EnvironmentVariable'
|
||||
'401':
|
||||
$ref: '#/components/responses/401'
|
||||
'400':
|
||||
$ref: '#/components/responses/400'
|
||||
'404':
|
||||
$ref: '#/components/responses/404'
|
||||
security:
|
||||
-
|
||||
bearerAuth: []
|
||||
post:
|
||||
tags:
|
||||
- Services
|
||||
summary: 'Create Env'
|
||||
description: 'Create env by service UUID.'
|
||||
operationId: create-env-by-service-uuid
|
||||
parameters:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'UUID of the service.'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
requestBody:
|
||||
description: 'Env created.'
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
description: 'The key of the environment variable.'
|
||||
value:
|
||||
type: string
|
||||
description: 'The value of the environment variable.'
|
||||
is_preview:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is used in preview deployments.'
|
||||
is_build_time:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is used in build time.'
|
||||
is_literal:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is a literal, nothing espaced.'
|
||||
is_multiline:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is multiline.'
|
||||
is_shown_once:
|
||||
type: boolean
|
||||
description: "The flag to indicate if the environment variable's value is shown on the UI."
|
||||
type: object
|
||||
responses:
|
||||
'201':
|
||||
description: 'Environment variable created.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
uuid: { type: string, example: nc0k04gk8g0cgsk440g0koko }
|
||||
type: object
|
||||
'401':
|
||||
$ref: '#/components/responses/401'
|
||||
'400':
|
||||
$ref: '#/components/responses/400'
|
||||
'404':
|
||||
$ref: '#/components/responses/404'
|
||||
security:
|
||||
-
|
||||
bearerAuth: []
|
||||
patch:
|
||||
tags:
|
||||
- Services
|
||||
summary: 'Update Env'
|
||||
description: 'Update env by service UUID.'
|
||||
operationId: update-env-by-service-uuid
|
||||
parameters:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'UUID of the service.'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
requestBody:
|
||||
description: 'Env updated.'
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
required:
|
||||
- key
|
||||
- value
|
||||
properties:
|
||||
key:
|
||||
type: string
|
||||
description: 'The key of the environment variable.'
|
||||
value:
|
||||
type: string
|
||||
description: 'The value of the environment variable.'
|
||||
is_preview:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is used in preview deployments.'
|
||||
is_build_time:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is used in build time.'
|
||||
is_literal:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is a literal, nothing espaced.'
|
||||
is_multiline:
|
||||
type: boolean
|
||||
description: 'The flag to indicate if the environment variable is multiline.'
|
||||
is_shown_once:
|
||||
type: boolean
|
||||
description: "The flag to indicate if the environment variable's value is shown on the UI."
|
||||
type: object
|
||||
responses:
|
||||
'201':
|
||||
description: 'Environment variable updated.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
message: { type: string, example: 'Environment variable updated.' }
|
||||
type: object
|
||||
'401':
|
||||
$ref: '#/components/responses/401'
|
||||
'400':
|
||||
$ref: '#/components/responses/400'
|
||||
'404':
|
||||
$ref: '#/components/responses/404'
|
||||
security:
|
||||
-
|
||||
bearerAuth: []
|
||||
'/services/{uuid}/envs/bulk':
|
||||
patch:
|
||||
tags:
|
||||
- Services
|
||||
summary: 'Update Envs (Bulk)'
|
||||
description: 'Update multiple envs by service UUID.'
|
||||
operationId: update-envs-by-service-uuid
|
||||
parameters:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'UUID of the service.'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
requestBody:
|
||||
description: 'Bulk envs updated.'
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
required:
|
||||
- data
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items: { properties: { key: { type: string, description: 'The key of the environment variable.' }, value: { type: string, description: 'The value of the environment variable.' }, is_preview: { type: boolean, description: 'The flag to indicate if the environment variable is used in preview deployments.' }, is_build_time: { type: boolean, description: 'The flag to indicate if the environment variable is used in build time.' }, is_literal: { type: boolean, description: 'The flag to indicate if the environment variable is a literal, nothing espaced.' }, is_multiline: { type: boolean, description: 'The flag to indicate if the environment variable is multiline.' }, is_shown_once: { type: boolean, description: "The flag to indicate if the environment variable's value is shown on the UI." } }, type: object }
|
||||
type: object
|
||||
responses:
|
||||
'201':
|
||||
description: 'Environment variables updated.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
message: { type: string, example: 'Environment variables updated.' }
|
||||
type: object
|
||||
'401':
|
||||
$ref: '#/components/responses/401'
|
||||
'400':
|
||||
$ref: '#/components/responses/400'
|
||||
'404':
|
||||
$ref: '#/components/responses/404'
|
||||
security:
|
||||
-
|
||||
bearerAuth: []
|
||||
'/services/{uuid}/envs/{env_uuid}':
|
||||
delete:
|
||||
tags:
|
||||
- Services
|
||||
summary: 'Delete Env'
|
||||
description: 'Delete env by UUID.'
|
||||
operationId: delete-env-by-service-uuid
|
||||
parameters:
|
||||
-
|
||||
name: uuid
|
||||
in: path
|
||||
description: 'UUID of the service.'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
-
|
||||
name: env_uuid
|
||||
in: path
|
||||
description: 'UUID of the environment variable.'
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
'200':
|
||||
description: 'Environment variable deleted.'
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
message: { type: string, example: 'Environment variable deleted.' }
|
||||
type: object
|
||||
'401':
|
||||
$ref: '#/components/responses/401'
|
||||
'400':
|
||||
$ref: '#/components/responses/400'
|
||||
'404':
|
||||
$ref: '#/components/responses/404'
|
||||
security:
|
||||
-
|
||||
bearerAuth: []
|
||||
'/services/{uuid}/start':
|
||||
get:
|
||||
tags:
|
||||
@@ -4480,6 +4730,8 @@ components:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
environments:
|
||||
description: 'The environments of the project.'
|
||||
type: array
|
||||
|
||||
@@ -6,7 +6,7 @@ set -e # Exit immediately if a command exits with a non-zero status
|
||||
#set -u # Treat unset variables as an error and exit
|
||||
set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status
|
||||
|
||||
VERSION="1.3.4"
|
||||
VERSION="1.4"
|
||||
DOCKER_VERSION="26.0"
|
||||
|
||||
CDN="https://cdn.coollabs.io/coolify-nightly"
|
||||
@@ -45,6 +45,12 @@ if [ "$OS_TYPE" = 'amzn' ]; then
|
||||
fi
|
||||
|
||||
LATEST_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $2}' | tr -d ',')
|
||||
LATEST_HELPER_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $6}' | tr -d ',')
|
||||
|
||||
if [ -z "$LATEST_HELPER_VERSION" ]; then
|
||||
LATEST_HELPER_VERSION=latest
|
||||
fi
|
||||
|
||||
DATE=$(date +"%Y%m%d-%H%M%S")
|
||||
|
||||
if [ $EUID != 0 ]; then
|
||||
@@ -75,6 +81,7 @@ echo -e "-------------"
|
||||
|
||||
echo "OS: $OS_TYPE $OS_VERSION"
|
||||
echo "Coolify version: $LATEST_VERSION"
|
||||
echo "Helper version: $LATEST_HELPER_VERSION"
|
||||
|
||||
echo -e "-------------"
|
||||
echo "Installing required packages..."
|
||||
@@ -342,7 +349,7 @@ if ! grep -qw "root@coolify" ~/.ssh/authorized_keys; then
|
||||
addSshKey
|
||||
fi
|
||||
|
||||
bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}"
|
||||
bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}"
|
||||
|
||||
echo "Waiting for 20 seconds for Coolify to be ready..."
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#!/bin/bash
|
||||
## Do not modify this file. You will lose the ability to autoupdate!
|
||||
|
||||
VERSION="1.0.6"
|
||||
VERSION="1.1"
|
||||
CDN="https://cdn.coollabs.io/coolify-nightly"
|
||||
LATEST_IMAGE=${1:-latest}
|
||||
LATEST_HELPER_VERSION=${2:-latest}
|
||||
|
||||
curl -fsSL $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml
|
||||
curl -fsSL $CDN/docker-compose.prod.yml -o /data/coolify/source/docker-compose.prod.yml
|
||||
@@ -31,7 +33,7 @@ docker network create --attachable coolify 2>/dev/null
|
||||
|
||||
if [ -f /data/coolify/source/docker-compose.custom.yml ]; then
|
||||
echo "docker-compose.custom.yml detected."
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml -f /data/coolify/source/docker-compose.custom.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper:${LATEST_HELPER_VERSION:-latest} bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml -f /data/coolify/source/docker-compose.custom.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
else
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper:${LATEST_HELPER_VERSION:-latest} bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
fi
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.324"
|
||||
"version": "4.0.0-beta.330"
|
||||
},
|
||||
"nightly": {
|
||||
"version": "4.0.0-beta.324"
|
||||
"version": "4.0.0-beta.331"
|
||||
},
|
||||
"helper": {
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
public/svgs/browserless.svg
Normal file
1
public/svgs/browserless.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 83.14 159.66"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="-19.19" y1="72.36" x2="89.91" y2="101.6" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#faed24"/><stop offset="0.5" stop-color="#f79421"/><stop offset="1" stop-color="#d41c5c"/></linearGradient></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="53.43 71.61 53.43 31.67 35.58 21.11 35.58 109.91 65.24 96 65.24 115.47 17.96 138.97 18 123.48 18 10.44 0.2 0 0 148.13 17.16 159.66 83.14 126.89 83.08 89.09 53.43 71.61"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 711 B |
1
public/svgs/plunk.svg
Normal file
1
public/svgs/plunk.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 1080 1080"><path fill="#fff" d="M0 0h1080v1080H0z"></path><path fill="#000" d="M976 284.628q0 95.414-49.38 175.112-49.379 79.699-143.65 130.212-94.27 50.512-224.453 59.493L510.26 919.971Q482.204 1076 357.632 1076q-68.459 0-126.816-40.41-57.235-40.41-92.026-123.477Q104 829.048 104 707.816q0-227.871 72.947-386.145 74.07-159.396 197.519-237.973Q499.037 4 648.299 4q105.492 0 178.44 37.043 74.069 37.042 111.104 101.026Q976 204.929 976 284.628M578.718 533.826q230.064-29.185 230.065-239.095 0-74.086-49.38-120.109-48.258-47.145-150.384-47.146-115.593 0-202.007 72.964-85.293 72.963-132.428 203.175-46.013 129.088-46.013 295.221 0 69.596 13.468 123.476 14.59 53.88 35.912 84.189 22.446 29.185 42.646 29.185 28.057 0 42.646-77.454l37.035-212.154q-43.769-6.736-38.157-5.613-33.668-5.613-43.768-20.205-10.101-15.715-10.101-39.288 0-24.696 13.467-39.288 14.59-14.593 39.28-14.593 11.223 0 16.834 1.123 26.934 4.49 41.524 5.612 14.589-87.556 41.523-234.605 6.734-38.166 30.302-53.881 24.689-16.837 57.235-16.837 37.035 0 52.746 14.592 16.834 13.47 16.834 43.778 0 17.96-2.244 29.186z"></path><path fill="#fff" d="m304.835 467.541 121.264 22.411-14.248 90.985-20.76 118.879-125.003-23.173z"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -31,11 +31,12 @@
|
||||
@endif
|
||||
@forelse ($deployments as $deployment)
|
||||
<div @class([
|
||||
'dark:bg-coolgray-100 p-2 border-l border-dashed transition-colors hover:no-underline box-without-bg-without-border bg-white flex-col cursor-pointer dark:hover:text-neutral-400 dark:hover:bg-coolgray-200',
|
||||
'border-warning' =>
|
||||
'dark:bg-coolgray-100 p-2 border-l-2 transition-colors hover:no-underline box-without-bg-without-border bg-white flex-col cursor-pointer dark:hover:text-neutral-400 dark:hover:bg-coolgray-200',
|
||||
'border-warning border-dashed ' =>
|
||||
data_get($deployment, 'status') === 'in_progress' ||
|
||||
data_get($deployment, 'status') === 'cancelled-by-user',
|
||||
'border-error' => data_get($deployment, 'status') === 'failed',
|
||||
'border-error border-dashed ' =>
|
||||
data_get($deployment, 'status') === 'failed',
|
||||
'border-success' => data_get($deployment, 'status') === 'finished',
|
||||
])
|
||||
x-on:click.stop="goto('{{ $current_url . '/' . data_get($deployment, 'deployment_uuid') }}')">
|
||||
@@ -106,7 +107,7 @@
|
||||
<div class="flex flex-col" x-data="elapsedTime('{{ $deployment->deployment_uuid }}', '{{ $deployment->status }}', '{{ $deployment->created_at }}', '{{ $deployment->updated_at }}')">
|
||||
<div>
|
||||
@if ($deployment->status !== 'in_progress')
|
||||
Finished <span x-text="measure_since_started()">0s</span> in
|
||||
Finished <span x-text="measure_since_started()">0s</span> ago in
|
||||
<span class="font-bold" x-text="measure_finished_time()">0s</span>
|
||||
@else
|
||||
Running for <span class="font-bold" x-text="measure_since_started()">0s</span>
|
||||
@@ -157,7 +158,7 @@
|
||||
}
|
||||
},
|
||||
measure_since_started() {
|
||||
return dayjs.utc(created_at).fromNow();
|
||||
return dayjs.utc(created_at).fromNow(true); // "true" prevents the "ago" suffix
|
||||
},
|
||||
}))
|
||||
</script>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
fullscreen: false,
|
||||
alwaysScroll: false,
|
||||
intervalId: null,
|
||||
showTimestamps: true,
|
||||
makeFullscreen() {
|
||||
this.fullscreen = !this.fullscreen;
|
||||
if (this.fullscreen === false) {
|
||||
@@ -53,63 +54,69 @@
|
||||
class="dark:text-warning">{{ Str::headline(data_get($application_deployment_queue, 'status')) }}</span>.
|
||||
</div>
|
||||
@endif
|
||||
<div id="screen" :class="fullscreen ? 'fullscreen' : ''">
|
||||
<div id="screen" :class="fullscreen ? 'fullscreen' : 'relative'">
|
||||
<div @if ($isKeepAliveOn) wire:poll.2000ms="polling" @endif
|
||||
class="relative flex flex-col-reverse w-full p-2 px-4 mt-4 overflow-y-auto bg-white dark:text-white dark:bg-coolgray-100 scrollbar dark:border-coolgray-300"
|
||||
:class="fullscreen ? '' : 'max-h-[40rem] border border-dotted rounded'">
|
||||
<button title="Minimize" x-show="fullscreen" class="fixed top-4 right-4"
|
||||
x-on:click="makeFullscreen"><svg class="icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M6 14h4m0 0v4m0-4l-6 6m14-10h-4m0 0V6m0 4l6-6" />
|
||||
</svg></button>
|
||||
<button title="Go Top" x-show="fullscreen" class="fixed top-4 right-28" x-on:click="goTop"> <svg
|
||||
class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M12 5v14m4-10l-4-4M8 9l4-4" />
|
||||
</svg></button>
|
||||
<button title="Follow Logs" x-show="fullscreen" :class="alwaysScroll ? 'dark:text-warning' : ''"
|
||||
class="fixed top-4 right-16" x-on:click="toggleScroll"><svg class="icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M12 5v14m4-4l-4 4m-4-4l4 4" />
|
||||
</svg></button>
|
||||
class="flex flex-col-reverse w-full p-2 px-4 mt-4 overflow-y-auto bg-white dark:text-white dark:bg-coolgray-100 scrollbar dark:border-coolgray-300"
|
||||
:class="fullscreen ? '' : 'min-h-14 max-h-[40rem] border border-dotted rounded'">
|
||||
<div :class="fullscreen ? 'fixed' : 'absolute'" class="top-4 right-6">
|
||||
<div class="flex justify-end gap-4 fixed -translate-x-full">
|
||||
<button title="Toggle timestamps" x-on:click="showTimestamps = !showTimestamps">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Go Top" x-show="fullscreen" x-on:click="goTop">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2" d="M12 5v14m4-10l-4-4M8 9l4-4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Follow Logs" x-show="fullscreen" :class="alwaysScroll ? 'dark:text-warning' : ''"
|
||||
x-on:click="toggleScroll">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2" d="M12 5v14m4-4l-4 4m-4-4l4 4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Fullscreen" x-show="!fullscreen" x-on:click="makeFullscreen">
|
||||
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none">
|
||||
<path
|
||||
d="M24 0v24H0V0h24ZM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018Zm.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022Zm-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01l-.184-.092Z" />
|
||||
<path fill="currentColor"
|
||||
d="M9.793 12.793a1 1 0 0 1 1.497 1.32l-.083.094L6.414 19H9a1 1 0 0 1 .117 1.993L9 21H4a1 1 0 0 1-.993-.883L3 20v-5a1 1 0 0 1 1.993-.117L5 15v2.586l4.793-4.793ZM20 3a1 1 0 0 1 .993.883L21 4v5a1 1 0 0 1-1.993.117L19 9V6.414l-4.793 4.793a1 1 0 0 1-1.497-1.32l.083-.094L17.586 5H15a1 1 0 0 1-.117-1.993L15 3h5Z" />
|
||||
</g>
|
||||
</svg>
|
||||
</button>
|
||||
<button title="Minimize" x-show="fullscreen" x-on:click="makeFullscreen">
|
||||
<svg class="icon" viewBox="0 0 24 24"xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="none" stroke="currentColor" stroke-linecap="round"
|
||||
stroke-linejoin="round" stroke-width="2"
|
||||
d="M6 14h4m0 0v4m0-4l-6 6m14-10h-4m0 0V6m0 4l6-6" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button title="Fullscreen" x-show="!fullscreen" class="absolute top-2 right-8"
|
||||
x-on:click="makeFullscreen"><svg class="fixed icon" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none">
|
||||
<path
|
||||
d="M24 0v24H0V0h24ZM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018Zm.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022Zm-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01l-.184-.092Z" />
|
||||
<path fill="currentColor"
|
||||
d="M9.793 12.793a1 1 0 0 1 1.497 1.32l-.083.094L6.414 19H9a1 1 0 0 1 .117 1.993L9 21H4a1 1 0 0 1-.993-.883L3 20v-5a1 1 0 0 1 1.993-.117L5 15v2.586l4.793-4.793ZM20 3a1 1 0 0 1 .993.883L21 4v5a1 1 0 0 1-1.993.117L19 9V6.414l-4.793 4.793a1 1 0 0 1-1.497-1.32l.083-.094L17.586 5H15a1 1 0 0 1-.117-1.993L15 3h5Z" />
|
||||
</g>
|
||||
</svg></button>
|
||||
<div id="logs" class="flex flex-col font-mono">
|
||||
@if (decode_remote_command_output($application_deployment_queue)->count() > 0)
|
||||
@foreach (decode_remote_command_output($application_deployment_queue) as $line)
|
||||
@forelse ($this->logLines as $line)
|
||||
<div @class([
|
||||
'mt-2' => $line['command'] ?? false,
|
||||
'flex gap-2 dark:hover:bg-coolgray-500 hover:bg-gray-100',
|
||||
])>
|
||||
<span x-show="showTimestamps" class="shrink-0 text-gray-500">{{ $line['timestamp'] }}</span>
|
||||
<span @class([
|
||||
'text-coollabs dark:text-warning whitespace-pre-line' => $line['hidden'],
|
||||
'text-red-500 font-bold whitespace-pre-line' => $line['type'] == 'stderr',
|
||||
])>[{{ $line['timestamp'] }}] @if ($line['hidden'])
|
||||
<br><br>[COMMAND] {{ $line['command'] }}<br>[OUTPUT]
|
||||
@endif @if (str($line['output'])->contains('http://') || str($line['output'])->contains('https://'))
|
||||
@php
|
||||
$line['output'] = preg_replace(
|
||||
'/(https?:\/\/[^\s]+)/',
|
||||
'<a href="$1" target="_blank" class="underline text-neutral-400">$1</a>',
|
||||
$line['output'],
|
||||
);
|
||||
@endphp {!! $line['output'] !!}
|
||||
@else
|
||||
{{ $line['output'] }}
|
||||
|
||||
@endif
|
||||
</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="font-mono text-neutral-400">No logs yet.</span>
|
||||
@endif
|
||||
'text-coollabs dark:text-warning' => $line['hidden'],
|
||||
'text-red-500' => $line['stderr'],
|
||||
'font-bold' => $line['command'] ?? false,
|
||||
'whitespace-pre-wrap',
|
||||
])>{!! $line['line'] !!}</span>
|
||||
</div>
|
||||
@empty
|
||||
<span class="font-mono text-neutral-400 mb-2">No logs yet.</span>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<h3 class="py-4">Executions</h3>
|
||||
<x-forms.button wire:click='cleanupFailed'>Cleanup Failed Backups</x-forms.button>
|
||||
</div>
|
||||
<div class="flex flex-col-reverse gap-4">
|
||||
<div class="flex flex-col gap-4">
|
||||
@forelse($executions as $execution)
|
||||
<div wire:key="{{ data_get($execution, 'id') }}" @class([
|
||||
'flex flex-col border-l-2 transition-colors p-4 ',
|
||||
@@ -54,7 +54,7 @@
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div class="p-4 bg-gray-100 dark:bg-coolgray-200 rounded">No executions found.</div>
|
||||
<div class="p-4 bg-gray-100 dark:bg-coolgray-100 rounded">No executions found.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
<script>
|
||||
|
||||
@@ -32,18 +32,18 @@
|
||||
@if (data_get($this->parameters, 'application_uuid'))
|
||||
@foreach ($containers as $container)
|
||||
<option value="{{ data_get($container, 'container.Names') }}">
|
||||
{{ data_get($container, 'container.Names') }}
|
||||
{{ data_get($container, 'container.Names') }} ({{ data_get($container, 'server.name') }})
|
||||
</option>
|
||||
@endforeach
|
||||
@elseif(data_get($this->parameters, 'service_uuid'))
|
||||
@foreach ($containers as $container)
|
||||
<option value="{{ $container }}">
|
||||
{{ $container }}
|
||||
{{ $container }} ({{ data_get($servers, '0.name') }})
|
||||
</option>
|
||||
@endforeach
|
||||
@else
|
||||
<option value="{{ $container }}">
|
||||
{{ $container }}
|
||||
{{ $container }} ({{ data_get($servers, '0.name') }})
|
||||
</option>
|
||||
@endif
|
||||
</x-forms.select>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</x-forms.select>
|
||||
@else
|
||||
<x-forms.input placeholder="php" id="container"
|
||||
helper="You can leave it empty if your resource only have one container." label="Container name" />
|
||||
helper="You can leave this empty if your resource only has one container." label="Container name" />
|
||||
@endif
|
||||
@elseif ($type === 'service')
|
||||
<x-forms.select id="container" label="Container name">
|
||||
|
||||
@@ -1,36 +1,38 @@
|
||||
<div class="flex flex-col-reverse gap-4">
|
||||
<div class="flex flex-col gap-4">
|
||||
@forelse($executions as $execution)
|
||||
@if (data_get($execution, 'id') == $selectedKey)
|
||||
<div class="p-4 mb-2 bg-gray-100 dark:bg-coolgray-200 rounded">
|
||||
@if (data_get($execution, 'message'))
|
||||
<div>
|
||||
<pre class="whitespace-pre-wrap">{{ data_get($execution, 'message') }}</pre>
|
||||
</div>
|
||||
@else
|
||||
<div>No output was recorded for this execution.</div>
|
||||
<a wire:click="selectTask({{ data_get($execution, 'id') }})" @class([
|
||||
'flex flex-col border-l-2 transition-colors p-4 cursor-pointer',
|
||||
'bg-white hover:bg-gray-100 dark:bg-coolgray-100 dark:hover:bg-coolgray-200',
|
||||
'text-black dark:text-white',
|
||||
'bg-gray-200 dark:bg-coolgray-200' =>
|
||||
data_get($execution, 'id') == $selectedKey,
|
||||
'border-green-500' => data_get($execution, 'status') === 'success',
|
||||
'border-red-500' => data_get($execution, 'status') === 'failed',
|
||||
'border-yellow-500' => data_get($execution, 'status') === 'running',
|
||||
])>
|
||||
@if (data_get($execution, 'status') === 'running')
|
||||
<div class="absolute top-2 right-2">
|
||||
<x-loading />
|
||||
</div>
|
||||
@endif
|
||||
<div class="text-gray-700 dark:text-gray-300 font-semibold mb-1">Status: {{ data_get($execution, 'status') }}
|
||||
</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at', now())) }}
|
||||
</div>
|
||||
</a>
|
||||
@if (data_get($execution, 'id') == $selectedKey)
|
||||
<div class="p-4 mb-2 bg-gray-100 dark:bg-coolgray-200 rounded">
|
||||
@if (data_get($execution, 'message'))
|
||||
<div>
|
||||
<pre class="whitespace-pre-wrap">{{ data_get($execution, 'message') }}</pre>
|
||||
</div>
|
||||
@else
|
||||
<div>No output was recorded for this execution.</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
<a wire:click="selectTask({{ data_get($execution, 'id') }})" @class([
|
||||
'flex flex-col border-l-4 transition-colors cursor-pointer p-4 rounded',
|
||||
'bg-white hover:bg-gray-100 dark:bg-coolgray-100 dark:hover:bg-coolgray-200',
|
||||
'text-black dark:text-white',
|
||||
'bg-gray-200 dark:bg-coolgray-200' => data_get($execution, 'id') == $selectedKey,
|
||||
'border-green-500' => data_get($execution, 'status') === 'success',
|
||||
'border-red-500' => data_get($execution, 'status') === 'failed',
|
||||
'border-yellow-500' => data_get($execution, 'status') === 'running',
|
||||
])>
|
||||
@if (data_get($execution, 'status') === 'running')
|
||||
<div class="absolute top-2 right-2">
|
||||
<x-loading />
|
||||
</div>
|
||||
@endif
|
||||
<div class="text-gray-700 dark:text-gray-300 font-semibold mb-1">Status: {{ data_get($execution, 'status') }}</div>
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at', now())) }}
|
||||
</div>
|
||||
</a>
|
||||
@empty
|
||||
<div class="p-4 bg-gray-100 dark:bg-coolgray-200 rounded">No executions found.</div>
|
||||
<div class="p-4 bg-gray-100 dark:bg-coolgray-100 rounded">No executions found.</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,11 +30,11 @@
|
||||
<x-forms.input placeholder="0 0 * * * or daily" id="task.frequency" label="Frequency" required />
|
||||
@if ($type === 'application')
|
||||
<x-forms.input placeholder="php"
|
||||
helper="You can leave it empty if your resource only have one container." id="task.container"
|
||||
helper="You can leave this empty if your resource only has one container." id="task.container"
|
||||
label="Container name" />
|
||||
@elseif ($type === 'service')
|
||||
<x-forms.input placeholder="php"
|
||||
helper="You can leave it empty if your resource only have one service in your stack. Otherwise use the stack name, without the random generated id. So if you have a mysql service in your stack, use mysql."
|
||||
helper="You can leave this empty if your resource only has one service in your stack. Otherwise use the stack name, without the random generated ID. So if you have a mysql service in your stack, use mysql."
|
||||
id="task.container" label="Service name" />
|
||||
@endif
|
||||
</div>
|
||||
@@ -42,6 +42,6 @@
|
||||
|
||||
<div class="pt-4">
|
||||
<h3 class="py-4">Recent executions <span class="text-xs text-neutral-500">(click to check output)</span></h3>
|
||||
<livewire:project.shared.scheduled-task.executions :task="$task" key="{{ $task->id }}" selectedKey="" :executions="$task->executions->take(-20)" />
|
||||
<livewire:project.shared.scheduled-task.executions :task="$task" key="{{ $task->id }}" selectedKey="" :executions="$task->executions->take(20)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -178,64 +178,58 @@
|
||||
</x-modal-input>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($server->isFunctional())
|
||||
<h3 class="pt-4">Settings</h3>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-col flex-wrap gap-2 sm:flex-nowrap">
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox
|
||||
helper="Enable force Docker Cleanup. This will cleanup build caches / unused images / etc."
|
||||
instantSave id="server.settings.force_docker_cleanup" label="Force Docker Cleanup" />
|
||||
<div class="flex flex-col gap-1">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-col flex-wrap gap-2 sm:flex-nowrap">
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox
|
||||
helper="Enable force Docker Cleanup. This will cleanup build caches / unused images / etc."
|
||||
instantSave id="server.settings.force_docker_cleanup" label="Force Docker Cleanup" />
|
||||
</div>
|
||||
@if ($server->settings->force_docker_cleanup)
|
||||
<x-forms.input placeholder="*/10 * * * *" id="server.settings.docker_cleanup_frequency"
|
||||
label="Docker cleanup frequency" required
|
||||
helper="Cron expression for Docker Cleanup.<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every 10 minutes." />
|
||||
@else
|
||||
<x-forms.input id="server.settings.docker_cleanup_threshold"
|
||||
label="Docker cleanup threshold (%)" required
|
||||
helper="The Docker cleanup tasks will run when the disk usage exceeds this threshold." />
|
||||
@endif
|
||||
</div>
|
||||
@if ($server->settings->force_docker_cleanup)
|
||||
<x-forms.input placeholder="*/10 * * * *" id="server.settings.docker_cleanup_frequency"
|
||||
label="Docker cleanup frequency" required
|
||||
helper="Cron expression for Docker Cleanup.<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every 10 minutes." />
|
||||
@else
|
||||
<x-forms.input id="server.settings.docker_cleanup_threshold"
|
||||
label="Docker cleanup threshold (%)" required
|
||||
helper="The Docker cleanup tasks will run when the disk usage exceeds this threshold." />
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<x-forms.input id="cleanup_after_percentage" label="Disk cleanup threshold (%)" required
|
||||
helper="The disk cleanup task will run when the disk usage exceeds this threshold." />
|
||||
<div class="w-64">
|
||||
<x-forms.checkbox helper="This will cleanup build caches / unused images / etc every 10 minutes."
|
||||
instantSave id="server.settings.is_force_cleanup_enabled"
|
||||
label="Force Cleanup Docker Engine" />
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input id="server.settings.concurrent_builds" label="Number of concurrent builds" required
|
||||
helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
|
||||
<x-forms.input id="server.settings.dynamic_timeout" label="Deployment timeout (seconds)" required
|
||||
helper="You can define the maximum duration for a deployment to run before timing it out." />
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input id="server.settings.concurrent_builds" label="Number of concurrent builds" required
|
||||
helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
|
||||
<x-forms.input id="server.settings.dynamic_timeout" label="Deployment timeout (seconds)" required
|
||||
helper="You can define the maximum duration for a deployment to run before timing it out." />
|
||||
</div>
|
||||
<div class="flex items-center gap-2 pt-4 pb-2">
|
||||
<h3>Sentinel</h3>
|
||||
{{-- @if ($server->isSentinelEnabled()) --}}
|
||||
{{-- <x-forms.button wire:click='restartSentinel'>Restart</x-forms.button> --}}
|
||||
{{-- @endif --}}
|
||||
</div>
|
||||
<div>Metrics are disabled until a few bugs are fixed.</div>
|
||||
{{-- <div class="w-64">
|
||||
</div>
|
||||
<div class="flex items-center gap-2 pt-4 pb-2">
|
||||
<h3>Sentinel</h3>
|
||||
{{-- @if ($server->isSentinelEnabled()) --}}
|
||||
{{-- <x-forms.button wire:click='restartSentinel'>Restart</x-forms.button> --}}
|
||||
{{-- @endif --}}
|
||||
</div>
|
||||
<div>Metrics are disabled until a few bugs are fixed.</div>
|
||||
{{-- <div class="w-64">
|
||||
<x-forms.checkbox instantSave id="server.settings.is_metrics_enabled" label="Enable Metrics" />
|
||||
</div>
|
||||
<div class="pt-4">
|
||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
|
||||
<x-forms.input type="password" id="server.settings.metrics_token" label="Metrics token" required
|
||||
helper="Token for collector (Sentinel)." />
|
||||
helper="Token for collector (Sentinel)." />
|
||||
<x-forms.input id="server.settings.metrics_refresh_rate_seconds" label="Metrics rate (seconds)"
|
||||
required
|
||||
helper="The interval for gathering metrics. Lower means more disk space will be used." />
|
||||
required
|
||||
helper="The interval for gathering metrics. Lower means more disk space will be used." />
|
||||
<x-forms.input id="server.settings.metrics_history_days" label="Metrics history (days)" required
|
||||
helper="How many days should the metrics data should be reserved." />
|
||||
helper="How many days should the metrics data should be reserved." />
|
||||
</div>
|
||||
</div> --}}
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -84,7 +84,7 @@ Route::group([
|
||||
Route::get('/applications/{uuid}/envs', [ApplicationsController::class, 'envs']);
|
||||
Route::post('/applications/{uuid}/envs', [ApplicationsController::class, 'create_env'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::patch('/applications/{uuid}/envs/bulk', [ApplicationsController::class, 'create_bulk_envs'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid']);
|
||||
Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::delete('/applications/{uuid}/envs/{env_uuid}', [ApplicationsController::class, 'delete_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
|
||||
Route::match(['get', 'post'], '/applications/{uuid}/start', [ApplicationsController::class, 'action_deploy'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
@@ -116,6 +116,12 @@ Route::group([
|
||||
// Route::patch('/services/{uuid}', [ServicesController::class, 'update_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::delete('/services/{uuid}', [ServicesController::class, 'delete_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
|
||||
Route::get('/services/{uuid}/envs', [ServicesController::class, 'envs']);
|
||||
Route::post('/services/{uuid}/envs', [ServicesController::class, 'create_env'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::patch('/services/{uuid}/envs/bulk', [ServicesController::class, 'create_bulk_envs'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::patch('/services/{uuid}/envs', [ServicesController::class, 'update_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::delete('/services/{uuid}/envs/{env_uuid}', [ServicesController::class, 'delete_env_by_uuid'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
|
||||
Route::match(['get', 'post'], '/services/{uuid}/start', [ServicesController::class, 'action_deploy'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::match(['get', 'post'], '/services/{uuid}/restart', [ServicesController::class, 'action_restart'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
Route::match(['get', 'post'], '/services/{uuid}/stop', [ServicesController::class, 'action_stop'])->middleware([IgnoreReadOnlyApiToken::class]);
|
||||
|
||||
@@ -6,7 +6,7 @@ set -e # Exit immediately if a command exits with a non-zero status
|
||||
#set -u # Treat unset variables as an error and exit
|
||||
set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status
|
||||
|
||||
VERSION="1.3.4"
|
||||
VERSION="1.4"
|
||||
DOCKER_VERSION="26.0"
|
||||
|
||||
CDN="https://cdn.coollabs.io/coolify"
|
||||
@@ -45,6 +45,12 @@ if [ "$OS_TYPE" = 'amzn' ]; then
|
||||
fi
|
||||
|
||||
LATEST_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $2}' | tr -d ',')
|
||||
LATEST_HELPER_VERSION=$(curl --silent $CDN/versions.json | grep -i version | xargs | awk '{print $6}' | tr -d ',')
|
||||
|
||||
if [ -z "$LATEST_HELPER_VERSION" ]; then
|
||||
LATEST_HELPER_VERSION=latest
|
||||
fi
|
||||
|
||||
DATE=$(date +"%Y%m%d-%H%M%S")
|
||||
|
||||
if [ $EUID != 0 ]; then
|
||||
@@ -75,6 +81,7 @@ echo -e "-------------"
|
||||
|
||||
echo "OS: $OS_TYPE $OS_VERSION"
|
||||
echo "Coolify version: $LATEST_VERSION"
|
||||
echo "Helper version: $LATEST_HELPER_VERSION"
|
||||
|
||||
echo -e "-------------"
|
||||
echo "Installing required packages..."
|
||||
@@ -342,7 +349,7 @@ if ! grep -qw "root@coolify" ~/.ssh/authorized_keys; then
|
||||
addSshKey
|
||||
fi
|
||||
|
||||
bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}"
|
||||
bash /data/coolify/source/upgrade.sh "${LATEST_VERSION:-latest}" "${LATEST_HELPER_VERSION:-latest}"
|
||||
|
||||
echo "Waiting for 20 seconds for Coolify to be ready..."
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#!/bin/bash
|
||||
## Do not modify this file. You will lose the ability to autoupdate!
|
||||
|
||||
VERSION="1.0.6"
|
||||
VERSION="1.1"
|
||||
CDN="https://cdn.coollabs.io/coolify"
|
||||
LATEST_IMAGE=${1:-latest}
|
||||
LATEST_HELPER_VERSION=${2:-latest}
|
||||
|
||||
curl -fsSL $CDN/docker-compose.yml -o /data/coolify/source/docker-compose.yml
|
||||
curl -fsSL $CDN/docker-compose.prod.yml -o /data/coolify/source/docker-compose.prod.yml
|
||||
@@ -31,7 +33,7 @@ docker network create --attachable coolify 2>/dev/null
|
||||
|
||||
if [ -f /data/coolify/source/docker-compose.custom.yml ]; then
|
||||
echo "docker-compose.custom.yml detected."
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml -f /data/coolify/source/docker-compose.custom.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper:${LATEST_HELPER_VERSION:-latest} bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml -f /data/coolify/source/docker-compose.custom.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
else
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper:${LATEST_HELPER_VERSION:-latest} bash -c "LATEST_IMAGE=${1:-} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60"
|
||||
fi
|
||||
|
||||
@@ -11,23 +11,23 @@ services:
|
||||
- SERVICE_FQDN_ACTIVEPIECES
|
||||
- AP_API_KEY=$SERVICE_PASSWORD_64_APIKEY
|
||||
- AP_ENCRYPTION_KEY=$SERVICE_PASSWORD_ENCRYPTIONKEY
|
||||
- AP_ENGINE_EXECUTABLE_PATH=dist/packages/engine/main.js
|
||||
- AP_ENVIRONMENT=prod
|
||||
- AP_EXECUTION_MODE=UNSANDBOXED
|
||||
- AP_FRONTEND_URL=$SERVICE_FQDN_ACTIVEPIECES
|
||||
- AP_ENGINE_EXECUTABLE_PATH=${AP_ENGINE_EXECUTABLE_PATH:-dist/packages/engine/main.js}
|
||||
- AP_ENVIRONMENT=${AP_ENVIRONMENT:-prod}
|
||||
- AP_EXECUTION_MODE=${AP_EXECUTION_MODE:-UNSANDBOXED}
|
||||
- AP_FRONTEND_URL=${SERVICE_FQDN_ACTIVEPIECES}
|
||||
- AP_JWT_SECRET=$SERVICE_PASSWORD_64_JWT
|
||||
- AP_POSTGRES_DATABASE=activepieces
|
||||
- AP_POSTGRES_HOST=postgres
|
||||
- AP_POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
- AP_POSTGRES_PORT=5432
|
||||
- AP_POSTGRES_DATABASE=${POSTGRES_DB:-activepieces}
|
||||
- AP_POSTGRES_HOST=${POSTGRES_HOST:-postgres}
|
||||
- AP_POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
|
||||
- AP_POSTGRES_PORT=${POSTGRES_PORT:-5432}
|
||||
- AP_POSTGRES_USERNAME=$SERVICE_USER_POSTGRES
|
||||
- AP_REDIS_HOST=redis
|
||||
- AP_REDIS_PORT=6379
|
||||
- AP_SANDBOX_RUN_TIME_SECONDS=600
|
||||
- AP_TELEMETRY_ENABLED=true
|
||||
- "AP_TEMPLATES_SOURCE_URL=https://cloud.activepieces.com/api/v1/flow-templates"
|
||||
- AP_TRIGGER_DEFAULT_POLL_INTERVAL=5
|
||||
- AP_WEBHOOK_TIMEOUT_SECONDS=30
|
||||
- AP_REDIS_HOST=${REDIS_HOST:-redis}
|
||||
- AP_REDIS_PORT=${REDIS_PORT:-6379}
|
||||
- AP_SANDBOX_RUN_TIME_SECONDS=${AP_SANDBOX_RUN_TIME_SECONDS:-600}
|
||||
- AP_TELEMETRY_ENABLED=${AP_TELEMETRY_ENABLED:-false}
|
||||
- AP_TEMPLATES_SOURCE_URL=${AP_TEMPLATES_SOURCE_URL:-https://cloud.activepieces.com/api/v1/flow-templates}
|
||||
- AP_TRIGGER_DEFAULT_POLL_INTERVAL=${AP_TRIGGER_DEFAULT_POLL_INTERVAL:-5}
|
||||
- AP_WEBHOOK_TIMEOUT_SECONDS=${AP_WEBHOOK_TIMEOUT_SECONDS:-30}
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
@@ -41,9 +41,10 @@ services:
|
||||
postgres:
|
||||
image: "postgres:latest"
|
||||
environment:
|
||||
- POSTGRES_DB=activepieces
|
||||
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
- POSTGRES_USER=$SERVICE_USER_POSTGRES
|
||||
- POSTGRES_DB=${POSTGRES_DB:-activepieces}
|
||||
- POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}
|
||||
- POSTGRES_USER=${SERVICE_USER_POSTGRES}
|
||||
- POSTGRES_PORT=${POSTGRES_PORT:-5432}
|
||||
volumes:
|
||||
- "pg-data:/var/lib/postgresql/data"
|
||||
healthcheck:
|
||||
|
||||
@@ -8,11 +8,11 @@ services:
|
||||
image: index.docker.io/appsmith/appsmith-ce:latest
|
||||
environment:
|
||||
- SERVICE_FQDN_APPSMITH
|
||||
- APPSMITH_MAIL_ENABLED=false
|
||||
- APPSMITH_DISABLE_TELEMETRY=true
|
||||
- APPSMITH_DISABLE_INTERCOM=true
|
||||
- APPSMITH_SENTRY_DSN=
|
||||
- APPSMITH_SMART_LOOK_ID=
|
||||
- APPSMITH_MAIL_ENABLED=${APPSMITH_MAIL_ENABLED:-false}
|
||||
- APPSMITH_DISABLE_TELEMETRY=${APPSMITH_DISABLE_TELEMETRY:-false}
|
||||
- APPSMITH_DISABLE_INTERCOM=${APPSMITH_DISABLE_INTERCOM:-true}
|
||||
- APPSMITH_SENTRY_DSN=${APPSMITH_SENTRY_DSN}
|
||||
- APPSMITH_SMART_LOOK_ID=${APPSMITH_SMART_LOOK_ID}
|
||||
volumes:
|
||||
- stacks-data:/appsmith-stacks
|
||||
healthcheck:
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
_APP_ENV=production
|
||||
_APP_LOCALE=en
|
||||
_APP_OPTIONS_ABUSE=enabled
|
||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||
_APP_OPENSSL_KEY_V1=
|
||||
_APP_CONSOLE_WHITELIST_ROOT=enabled
|
||||
_APP_CONSOLE_WHITELIST_EMAILS=
|
||||
_APP_CONSOLE_WHITELIST_IPS=
|
||||
_APP_CONSOLE_HOSTNAMES=localhost,appwrite.io,*.appwrite.io
|
||||
_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=appwrite-redis
|
||||
_APP_REDIS_PORT=6379
|
||||
_APP_REDIS_USER=
|
||||
_APP_REDIS_PASS=
|
||||
_APP_DB_HOST=appwrite-mariadb
|
||||
_APP_DB_PORT=3306
|
||||
_APP_DB_SCHEMA=appwrite
|
||||
_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=appwrite-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-20.0,php-8.2,python-3.11,ruby-3.2
|
||||
_APP_EXECUTOR_HOST=http://appwrite-executor/v1
|
||||
_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes
|
||||
_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_DELAY=
|
||||
_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,6 +1,5 @@
|
||||
# documentation: https://appwrite.io
|
||||
# slogan: A backend-as-a-service platform that simplifies the web & mobile app development.
|
||||
# env_file: appwrite.env
|
||||
# tags: backend-as-a-service, platform
|
||||
# logo: svgs/appwrite.svg
|
||||
|
||||
@@ -28,97 +27,97 @@ services:
|
||||
- appwrite-redis
|
||||
environment:
|
||||
- SERVICE_FQDN_APPWRITE=/
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_LOCALE
|
||||
- _APP_CONSOLE_WHITELIST_ROOT
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||
- _APP_CONSOLE_WHITELIST_IPS
|
||||
- _APP_CONSOLE_HOSTNAMES
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_SYSTEM_RESPONSE_FORMAT
|
||||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_LOCALE=${_APP_LOCALE:-en}
|
||||
- _APP_CONSOLE_WHITELIST_ROOT=${_APP_CONSOLE_WHITELIST_ROOT:-enabled}
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS=${_APP_CONSOLE_WHITELIST_EMAILS}
|
||||
- _APP_CONSOLE_WHITELIST_IPS=${_APP_CONSOLE_WHITELIST_IPS}
|
||||
- _APP_CONSOLE_HOSTNAMES=${_APP_CONSOLE_HOSTNAMES:-localhost,appwrite.io,*.appwrite.io}
|
||||
- _APP_SYSTEM_EMAIL_NAME=${_APP_SYSTEM_EMAIL_NAME:-Appwrite}
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS=${_APP_SYSTEM_EMAIL_ADDRESS:-team@appwrite.io}
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS:-certs@appwrite.io}
|
||||
- _APP_SYSTEM_RESPONSE_FORMAT=${_APP_SYSTEM_RESPONSE_FORMAT}
|
||||
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
||||
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_DOMAIN=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_DB_ROOT_PASS=$SERVICE_PASSWORD_MARIADBROOT
|
||||
- _APP_SMTP_HOST
|
||||
- _APP_SMTP_PORT
|
||||
- _APP_SMTP_SECURE
|
||||
- _APP_SMTP_USERNAME
|
||||
- _APP_SMTP_PASSWORD
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_STORAGE_LIMIT
|
||||
- _APP_STORAGE_PREVIEW_LIMIT
|
||||
- _APP_STORAGE_ANTIVIRUS
|
||||
- _APP_STORAGE_ANTIVIRUS_HOST
|
||||
- _APP_STORAGE_ANTIVIRUS_PORT
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET
|
||||
- _APP_STORAGE_BACKBLAZE_REGION
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- _APP_STORAGE_LINODE_SECRET
|
||||
- _APP_STORAGE_LINODE_REGION
|
||||
- _APP_STORAGE_LINODE_BUCKET
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_FUNCTIONS_RUNTIMES
|
||||
- _APP_SMTP_HOST=${_APP_SMTP_HOST}
|
||||
- _APP_SMTP_PORT=${_APP_SMTP_PORT}
|
||||
- _APP_SMTP_SECURE=${_APP_SMTP_SECURE}
|
||||
- _APP_SMTP_USERNAME=${_APP_SMTP_USERNAME}
|
||||
- _APP_SMTP_PASSWORD=${_APP_SMTP_PASSWORD}
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
- _APP_STORAGE_LIMIT=${_APP_STORAGE_LIMIT:-30000000}
|
||||
- _APP_STORAGE_PREVIEW_LIMIT=${_APP_STORAGE_PREVIEW_LIMIT:-20000000}
|
||||
- _APP_STORAGE_ANTIVIRUS=${_APP_STORAGE_ANTIVIRUS:-disabled}
|
||||
- _APP_STORAGE_ANTIVIRUS_HOST=${_APP_STORAGE_ANTIVIRUS_HOST:-appwrite-clamav}
|
||||
- _APP_STORAGE_ANTIVIRUS_PORT=${_APP_STORAGE_ANTIVIRUS_PORT:-3310}
|
||||
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY}
|
||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET}
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY}
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET}
|
||||
- _APP_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION:-us-west-004}
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET}
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY}
|
||||
- _APP_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET}
|
||||
- _APP_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET}
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY}
|
||||
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT=${_APP_FUNCTIONS_SIZE_LIMIT:-30000000}
|
||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
||||
- _APP_FUNCTIONS_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES:-node-20.0,php-8.2,python-3.11,ruby-3.2}
|
||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_MAINTENANCE_INTERVAL
|
||||
- _APP_MAINTENANCE_DELAY
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_SMS_PROVIDER
|
||||
- _APP_SMS_FROM
|
||||
- _APP_GRAPHQL_MAX_BATCH_SIZE
|
||||
- _APP_GRAPHQL_MAX_COMPLEXITY
|
||||
- _APP_GRAPHQL_MAX_DEPTH
|
||||
- _APP_VCS_GITHUB_APP_NAME
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
- _APP_VCS_GITHUB_APP_ID
|
||||
- _APP_VCS_GITHUB_WEBHOOK_SECRET
|
||||
- _APP_VCS_GITHUB_CLIENT_SECRET
|
||||
- _APP_VCS_GITHUB_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_MAINTENANCE_INTERVAL=${_APP_MAINTENANCE_INTERVAL:-86400}
|
||||
- _APP_MAINTENANCE_DELAY=${_APP_MAINTENANCE_DELAY}
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION:-1209600}
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
||||
- _APP_SMS_PROVIDER=${_APP_SMS_PROVIDER}
|
||||
- _APP_SMS_FROM=${_APP_SMS_FROM}
|
||||
- _APP_GRAPHQL_MAX_BATCH_SIZE=${_APP_GRAPHQL_MAX_BATCH_SIZE:-10}
|
||||
- _APP_GRAPHQL_MAX_COMPLEXITY=${_APP_GRAPHQL_MAX_COMPLEXITY:-250}
|
||||
- _APP_GRAPHQL_MAX_DEPTH=${_APP_GRAPHQL_MAX_DEPTH:-3}
|
||||
- _APP_VCS_GITHUB_APP_NAME=${_APP_VCS_GITHUB_APP_NAME}
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY=${_APP_VCS_GITHUB_PRIVATE_KEY}
|
||||
- _APP_VCS_GITHUB_APP_ID=${_APP_VCS_GITHUB_APP_ID}
|
||||
- _APP_VCS_GITHUB_WEBHOOK_SECRET=${_APP_VCS_GITHUB_WEBHOOK_SECRET}
|
||||
- _APP_VCS_GITHUB_CLIENT_SECRET=${_APP_VCS_GITHUB_CLIENT_SECRET}
|
||||
- _APP_VCS_GITHUB_CLIENT_ID=${_APP_VCS_GITHUB_CLIENT_ID}
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID=${_APP_MIGRATIONS_FIREBASE_CLIENT_ID}
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=${_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET}
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY}
|
||||
|
||||
appwrite-realtime:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -129,22 +128,22 @@ services:
|
||||
- appwrite-redis
|
||||
environment:
|
||||
- SERVICE_FQDN_APPWRITE=/v1/realtime
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-audits:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -155,20 +154,20 @@ services:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-webhooks:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -179,16 +178,16 @@ services:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS:-certs@appwrite.io}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-deletes:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -205,43 +204,43 @@ services:
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET
|
||||
- _APP_STORAGE_BACKBLAZE_REGION
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- _APP_STORAGE_LINODE_SECRET
|
||||
- _APP_STORAGE_LINODE_REGION
|
||||
- _APP_STORAGE_LINODE_BUCKET
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET}
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY}
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET}
|
||||
- _APP_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION:-us-west-004}
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET}
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY}
|
||||
- _APP_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET}
|
||||
- _APP_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET}
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY}
|
||||
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||
|
||||
appwrite-worker-databases:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -252,20 +251,20 @@ services:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-builds:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -279,52 +278,52 @@ services:
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_VCS_GITHUB_APP_NAME
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||
- _APP_VCS_GITHUB_APP_ID
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_DOMAIN
|
||||
- _APP_STORAGE_DEVICE
|
||||
- _APP_STORAGE_S3_ACCESS_KEY
|
||||
- _APP_STORAGE_S3_SECRET
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET
|
||||
- _APP_STORAGE_BACKBLAZE_REGION
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- _APP_STORAGE_LINODE_SECRET
|
||||
- _APP_STORAGE_LINODE_REGION
|
||||
- _APP_STORAGE_LINODE_BUCKET
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- _APP_STORAGE_WASABI_SECRET
|
||||
- _APP_STORAGE_WASABI_REGION
|
||||
- _APP_STORAGE_WASABI_BUCKET
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_VCS_GITHUB_APP_NAME=${_APP_VCS_GITHUB_APP_NAME}
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY=${_APP_VCS_GITHUB_PRIVATE_KEY}
|
||||
- _APP_VCS_GITHUB_APP_ID=${_APP_VCS_GITHUB_APP_ID}
|
||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
||||
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||
- _APP_DOMAIN=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||
- _APP_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET}
|
||||
- _APP_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY}
|
||||
- _APP_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET}
|
||||
- _APP_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION:-us-west-004}
|
||||
- _APP_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET}
|
||||
- _APP_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY}
|
||||
- _APP_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET}
|
||||
- _APP_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET}
|
||||
- _APP_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY}
|
||||
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||
|
||||
appwrite-worker-certificates:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -338,24 +337,24 @@ services:
|
||||
- appwrite-config:/storage/config:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_DOMAIN=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS:-certs@appwrite.io}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-functions:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -367,29 +366,30 @@ services:
|
||||
- appwrite-mariadb
|
||||
- openruntimes-executor
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_FUNCTIONS_TIMEOUT
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
||||
- _APP_FUNCTIONS_CPUS
|
||||
- _APP_FUNCTIONS_MEMORY
|
||||
- _APP_EXECUTOR_SECRET
|
||||
- _APP_EXECUTOR_HOST
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_DOCKER_HUB_USERNAME
|
||||
- _APP_DOCKER_HUB_PASSWORD
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
- _APP_DOCKER_HUB_USERNAME=${_APP_DOCKER_HUB_USERNAME}
|
||||
- _APP_DOCKER_HUB_PASSWORD=${_APP_DOCKER_HUB_PASSWORD}
|
||||
- _APP_DOCKER_HUB_EMAIL=${_APP_DOCKER_HUB_EMAIL}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
|
||||
appwrite-worker-mails:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -399,22 +399,22 @@ services:
|
||||
depends_on:
|
||||
- appwrite-redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_SMTP_HOST
|
||||
- _APP_SMTP_PORT
|
||||
- _APP_SMTP_SECURE
|
||||
- _APP_SMTP_USERNAME
|
||||
- _APP_SMTP_PASSWORD
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_SYSTEM_EMAIL_NAME=${_APP_SYSTEM_EMAIL_NAME:-Appwrite}
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS=${_APP_SYSTEM_EMAIL_ADDRESS:-team@appwrite.io}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_SMTP_HOST=${_APP_SMTP_HOST}
|
||||
- _APP_SMTP_PORT=${_APP_SMTP_PORT}
|
||||
- _APP_SMTP_SECURE=${_APP_SMTP_SECURE}
|
||||
- _APP_SMTP_USERNAME=${_APP_SMTP_USERNAME}
|
||||
- _APP_SMTP_PASSWORD=${_APP_SMTP_PASSWORD}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-messaging:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -424,22 +424,22 @@ services:
|
||||
depends_on:
|
||||
- appwrite-redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_SMS_FROM
|
||||
- _APP_SMS_PROVIDER
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_SMS_FROM=${_APP_SMS_FROM}
|
||||
- _APP_SMS_PROVIDER=${_APP_SMS_PROVIDER}
|
||||
|
||||
appwrite-worker-migrations:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -449,25 +449,25 @@ services:
|
||||
depends_on:
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_DOMAIN=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS:-certs@appwrite.io}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID=${_APP_MIGRATIONS_FIREBASE_CLIENT_ID}
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=${_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET}
|
||||
|
||||
appwrite-maintenance:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -477,28 +477,28 @@ services:
|
||||
depends_on:
|
||||
- appwrite-redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_MAINTENANCE_INTERVAL
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_DOMAIN=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_FQDN_APPWRITE
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_MAINTENANCE_INTERVAL=${_APP_MAINTENANCE_INTERVAL}
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION}
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
||||
|
||||
appwrite-worker-usage:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -510,22 +510,22 @@ services:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL:-30}
|
||||
|
||||
appwrite-worker-usage-dump:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -536,22 +536,22 @@ services:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_LOGGING_PROVIDER
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
- _APP_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL:-30}
|
||||
|
||||
appwrite-scheduler-functions:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -563,18 +563,18 @@ services:
|
||||
- appwrite-mariadb
|
||||
- appwrite-redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
|
||||
appwrite-scheduler-messages:
|
||||
image: appwrite/appwrite:1.5
|
||||
@@ -586,18 +586,18 @@ services:
|
||||
- appwrite-mariadb
|
||||
- appwrite-redis
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
- _APP_REDIS_PASS
|
||||
- _APP_DB_HOST
|
||||
- _APP_DB_PORT
|
||||
- _APP_DB_SCHEMA
|
||||
- _APP_DB_USER
|
||||
- _APP_DB_PASS
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=${_APP_OPENSSL_KEY_V1}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
|
||||
appwrite-assistant:
|
||||
image: appwrite/assistant:0.4.0
|
||||
@@ -616,37 +616,37 @@ services:
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- /tmp:/tmp:rw
|
||||
environment:
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL
|
||||
- OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK
|
||||
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
|
||||
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
|
||||
- OPR_EXECUTOR_ENV=$_APP_ENV
|
||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
|
||||
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
||||
- OPR_EXECUTOR_LOGGING_PROVIDER=$_APP_LOGGING_PROVIDER
|
||||
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
|
||||
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
|
||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION
|
||||
- OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_BUCKET=$_APP_STORAGE_DO_SPACES_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_ACCESS_KEY=$_APP_STORAGE_BACKBLAZE_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_SECRET=$_APP_STORAGE_BACKBLAZE_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_REGION=$_APP_STORAGE_BACKBLAZE_REGION
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_BUCKET=$_APP_STORAGE_BACKBLAZE_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_ACCESS_KEY=$_APP_STORAGE_LINODE_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_SECRET=$_APP_STORAGE_LINODE_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_REGION=$_APP_STORAGE_LINODE_REGION
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_BUCKET=$_APP_STORAGE_LINODE_BUCKET
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_ACCESS_KEY=$_APP_STORAGE_WASABI_ACCESS_KEY
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_SECRET=$_APP_STORAGE_WASABI_SECRET
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_REGION=$_APP_STORAGE_WASABI_REGION
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_BUCKET=$_APP_STORAGE_WASABI_BUCKET
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=${_APP_FUNCTIONS_INACTIVE_THRESHOLD}
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=${_APP_FUNCTIONS_MAINTENANCE_INTERVAL}
|
||||
- OPR_EXECUTOR_NETWORK=${_APP_FUNCTIONS_RUNTIMES_NETWORK}
|
||||
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=${_APP_DOCKER_HUB_USERNAME}
|
||||
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=${_APP_DOCKER_HUB_PASSWORD}
|
||||
- OPR_EXECUTOR_ENV=${_APP_ENV:-production}
|
||||
- OPR_EXECUTOR_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES}
|
||||
- OPR_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- OPR_EXECUTOR_LOGGING_PROVIDER=${_APP_LOGGING_PROVIDER}
|
||||
- OPR_EXECUTOR_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- OPR_EXECUTOR_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
||||
- OPR_EXECUTOR_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- OPR_EXECUTOR_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION}
|
||||
- OPR_EXECUTOR_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION}
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_BUCKET=${_APP_STORAGE_DO_SPACES_BUCKET}
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_ACCESS_KEY=${_APP_STORAGE_BACKBLAZE_ACCESS_KEY}
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_SECRET=${_APP_STORAGE_BACKBLAZE_SECRET}
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_REGION=${_APP_STORAGE_BACKBLAZE_REGION}
|
||||
- OPR_EXECUTOR_STORAGE_BACKBLAZE_BUCKET=${_APP_STORAGE_BACKBLAZE_BUCKET}
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_ACCESS_KEY=${_APP_STORAGE_LINODE_ACCESS_KEY}
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_SECRET=${_APP_STORAGE_LINODE_SECRET}
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_REGION=${_APP_STORAGE_LINODE_REGION}
|
||||
- OPR_EXECUTOR_STORAGE_LINODE_BUCKET=${_APP_STORAGE_LINODE_BUCKET}
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_ACCESS_KEY=${_APP_STORAGE_WASABI_ACCESS_KEY}
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION}
|
||||
- OPR_EXECUTOR_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||
|
||||
appwrite-mariadb:
|
||||
image: mariadb:10.11
|
||||
@@ -655,10 +655,10 @@ services:
|
||||
volumes:
|
||||
- appwrite-mariadb:/var/lib/mysql:rw
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
|
||||
- MYSQL_DATABASE=${_APP_DB_SCHEMA}
|
||||
- MYSQL_USER=${_APP_DB_USER}
|
||||
- MYSQL_PASSWORD=${_APP_DB_PASS}
|
||||
- MYSQL_ROOT_PASSWORD=$SERVICE_PASSWORD_MARIADBROOT
|
||||
- MYSQL_DATABASE=${_APP_DB_SCHEMA:-appwrite}
|
||||
- MYSQL_USER=$SERVICE_USER_MARIADB
|
||||
- MYSQL_PASSWORD=$SERVICE_PASSWORD_MARIADB
|
||||
command: 'mysqld --innodb-flush-method=fsync'
|
||||
appwrite-redis:
|
||||
image: redis:7.2.4-alpine
|
||||
|
||||
@@ -5,41 +5,17 @@
|
||||
# port: 9000
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: docker.io/library/postgres:12-alpine
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
volumes:
|
||||
- authentik-db:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL}
|
||||
- POSTGRES_USER=${SERVICE_USER_POSTGRESQL}
|
||||
- POSTGRES_DB=authentik
|
||||
redis:
|
||||
image: docker.io/library/redis:alpine
|
||||
command: --save 60 1 --loglevel warning
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
volumes:
|
||||
- redis:/data
|
||||
|
||||
authentik-server:
|
||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2024.2.2}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
- SERVICE_FQDN_AUTHENTIKSERVER_9000
|
||||
- AUTHENTIK_REDIS__HOST=redis
|
||||
- AUTHENTIK_POSTGRESQL__HOST=postgresql
|
||||
- AUTHENTIK_REDIS__HOST=${REDIS_HOST:-redis}
|
||||
- AUTHENTIK_POSTGRESQL__HOST=${POSTGRES_HOST:-postgresql}
|
||||
- AUTHENTIK_POSTGRESQL__USER=${SERVICE_USER_POSTGRESQL}
|
||||
- AUTHENTIK_POSTGRESQL__NAME=authentik
|
||||
- AUTHENTIK_POSTGRESQL__NAME=${POSTGRES_DB:-authentik}
|
||||
- AUTHENTIK_POSTGRESQL__PASSWORD=${SERVICE_PASSWORD_POSTGRESQL}
|
||||
- AUTHENTIK_SECRET_KEY=${SERVICE_PASSWORD_64_AUTHENTIKSERVER}
|
||||
- AUTHENTIK_ERROR_REPORTING__ENABLED=${AUTHENTIK_ERROR_REPORTING__ENABLED:-true}
|
||||
@@ -64,10 +40,10 @@ services:
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
- AUTHENTIK_REDIS__HOST=redis
|
||||
- AUTHENTIK_POSTGRESQL__HOST=postgresql
|
||||
- AUTHENTIK_REDIS__HOST=${REDIS_HOST:-redis}
|
||||
- AUTHENTIK_POSTGRESQL__HOST=${POSTGRES_HOST:-postgresql}
|
||||
- AUTHENTIK_POSTGRESQL__USER=${SERVICE_USER_POSTGRESQL}
|
||||
- AUTHENTIK_POSTGRESQL__NAME=authentik
|
||||
- AUTHENTIK_POSTGRESQL__NAME=${POSTGRES_DB:-authentik}
|
||||
- AUTHENTIK_POSTGRESQL__PASSWORD=${SERVICE_PASSWORD_POSTGRESQL}
|
||||
- AUTHENTIK_SECRET_KEY=${SERVICE_PASSWORD_64_AUTHENTIKSERVER}
|
||||
- AUTHENTIK_ERROR_REPORTING__ENABLED=${AUTHENTIK_ERROR_REPORTING__ENABLED}
|
||||
@@ -96,3 +72,28 @@ services:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
postgresql:
|
||||
image: docker.io/library/postgres:12-alpine
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
volumes:
|
||||
- authentik-db:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL}
|
||||
- POSTGRES_USER=${SERVICE_USER_POSTGRESQL}
|
||||
- POSTGRES_DB=${POSTGRES_DB:-authentik}
|
||||
redis:
|
||||
image: docker.io/library/redis:alpine
|
||||
command: --save 60 1 --loglevel warning
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
volumes:
|
||||
- redis:/data
|
||||
|
||||
19
templates/compose/browserless.yaml
Normal file
19
templates/compose/browserless.yaml
Normal file
@@ -0,0 +1,19 @@
|
||||
# documentation: https://docs.browserless.io/
|
||||
# slogan: A headless Chrome browser as a service .
|
||||
# tags: chrome,headless,browser,service
|
||||
# logo: svgs/browserless.svg
|
||||
# port: 3000
|
||||
|
||||
services:
|
||||
browserless:
|
||||
image: ghcr.io/browserless/chromium
|
||||
environment:
|
||||
- SERVICE_FQDN_BROWSERLESS_3000
|
||||
- TOKEN=$SERVICE_BASE64_BROWSERLESS_TOKEN
|
||||
expose:
|
||||
- 3000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://127.0.0.1:3000/docs"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
@@ -5,7 +5,7 @@
|
||||
# port: 3000
|
||||
|
||||
services:
|
||||
rails:
|
||||
chatwoot:
|
||||
image: chatwoot/chatwoot:latest
|
||||
depends_on:
|
||||
- postgres
|
||||
|
||||
59
templates/compose/plunk.yaml
Normal file
59
templates/compose/plunk.yaml
Normal file
@@ -0,0 +1,59 @@
|
||||
# documentation: https://docs.useplunk.com/getting-started/introduction
|
||||
# slogan: Plunk, The Open-Source Email Platform for AWS
|
||||
# tags: plunk,email,automation,aws
|
||||
# logo: svgs/plunk.svg
|
||||
# port: 3000
|
||||
|
||||
version: '3'
|
||||
services:
|
||||
plunk:
|
||||
image: driaug/plunk
|
||||
depends_on:
|
||||
postgresql:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
environment:
|
||||
- SERVICE_FQDN_PLUNK_3000
|
||||
- REDIS_URL=redis://redis:6379
|
||||
- DATABASE_URL=postgresql://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@postgresql/plunk?schema=public
|
||||
- JWT_SECRET=${SERVICE_PASSWORD_JWT_SECRET}
|
||||
- AWS_REGION=${AWS_REGION}
|
||||
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
|
||||
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
|
||||
- AWS_SES_CONFIGURATION_SET=${AWS_SES_CONFIGURATION_SET}
|
||||
- NEXT_PUBLIC_API_URI=${API_URI}
|
||||
- APP_URI=${SERVICE_FQDN_PLUNK}
|
||||
- API_URI=${SERVICE_FQDN_PLUNK}/api
|
||||
- DISABLE_SIGNUPS=False
|
||||
entrypoint: [ "/app/entry.sh" ]
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000"]
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
retries: 15
|
||||
postgresql:
|
||||
image: postgres:16-alpine
|
||||
environment:
|
||||
- POSTGRES_USER=$SERVICE_USER_POSTGRES
|
||||
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
- POSTGRES_DB=${POSTGRES_DB:-plunk}
|
||||
volumes:
|
||||
- postgresql-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "pg_isready -U postgres -d postgres" ]
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
redis:
|
||||
image: "redis:7.4-alpine"
|
||||
volumes:
|
||||
- "redis-data:/data"
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- redis-cli
|
||||
- PING
|
||||
interval: 5s
|
||||
timeout: 10s
|
||||
retries: 20
|
||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Actions\Service\DeleteService;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\GithubApp;
|
||||
@@ -8,7 +9,6 @@ use App\Models\Service;
|
||||
use App\Models\StandaloneDocker;
|
||||
use Illuminate\Support\Collection;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->applicationYaml = '
|
||||
@@ -21,6 +21,7 @@ services:
|
||||
APP_KEY: base64
|
||||
APP_DEBUG: "${APP_DEBUG:-false}"
|
||||
APP_URL: $SERVICE_FQDN_APP
|
||||
DB_URL: postgres://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@db:5432/postgres?schema=public
|
||||
volumes:
|
||||
- "./nginx:/etc/nginx"
|
||||
- "data:/var/www/html"
|
||||
@@ -29,8 +30,8 @@ services:
|
||||
db:
|
||||
image: postgres
|
||||
environment:
|
||||
POSTGRES_USER: "${POSTGRES_USER:-postgres}"
|
||||
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:-postgres}"
|
||||
POSTGRES_USER: "${SERVICE_USER_POSTGRES}"
|
||||
POSTGRES_PASSWORD: "${SERVICE_PASSWORD_POSTGRES}"
|
||||
volumes:
|
||||
- "dbdata:/var/lib/postgresql/data"
|
||||
healthcheck:
|
||||
@@ -86,75 +87,73 @@ networks:
|
||||
'pull_request_html_url' => 'https://github.com/coollabsio/coolify-examples/pull/1',
|
||||
]);
|
||||
$this->serviceYaml = '
|
||||
version: "3.8"
|
||||
services:
|
||||
activepieces:
|
||||
image: ghcr.io/activepieces/activepieces:latest
|
||||
image: "ghcr.io/activepieces/activepieces:latest"
|
||||
environment:
|
||||
- SERVICE_FQDN_ACTIVEPIECES
|
||||
- AP_API_KEY=$SERVICE_PASSWORD_64_APIKEY
|
||||
- AP_ENCRYPTION_KEY=$SERVICE_PASSWORD_ENCRYPTIONKEY
|
||||
- AP_EXECUTION_MODE=UNSANDBOXED
|
||||
- AP_ENGINE_EXECUTABLE_PATH=dist/packages/engine/main.js
|
||||
- AP_ENVIRONMENT=prod
|
||||
- AP_EXECUTION_MODE=${AP_EXECUTION_MODE}
|
||||
- AP_FRONTEND_URL=$SERVICE_FQDN_ACTIVEPIECES
|
||||
- AP_TEST=${AP_TEST:-test}
|
||||
volumes:
|
||||
- "dbdata:/var/lib/postgresql/data"
|
||||
- AP_JWT_SECRET=$SERVICE_PASSWORD_64_JWT
|
||||
- AP_POSTGRES_DATABASE=activepieces
|
||||
- AP_POSTGRES_HOST=postgres
|
||||
- AP_POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
- AP_POSTGRES_PORT=5432
|
||||
- AP_POSTGRES_USERNAME=$SERVICE_USER_POSTGRES
|
||||
- AP_REDIS_HOST=redis
|
||||
- AP_REDIS_PORT=6379
|
||||
- AP_SANDBOX_RUN_TIME_SECONDS=600
|
||||
- AP_TELEMETRY_ENABLED=true
|
||||
- "AP_TEMPLATES_SOURCE_URL=https://cloud.activepieces.com/api/v1/flow-templates"
|
||||
- AP_TRIGGER_DEFAULT_POLL_INTERVAL=5
|
||||
- AP_WEBHOOK_TIMEOUT_SECONDS=30
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
activepieces2:
|
||||
image: ghcr.io/activepieces/activepieces:latest
|
||||
environment:
|
||||
TEST: $SERVICE_FQDN_ACTIVEPIECES
|
||||
volumes:
|
||||
- "dbdata:/var/lib/postgresql/data"
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
postgres:
|
||||
image: postgres:latest
|
||||
environment:
|
||||
POSTGRES_DB: activepieces
|
||||
POSTGRES_USER: $SERVICE_USER_POSTGRES
|
||||
POSTGRES_PASSWORD: $SERVICE_PASSWORD_POSTGRES
|
||||
volumes:
|
||||
- "dbdata:/var/lib/postgresql/data"
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- pg_isready
|
||||
- "-U"
|
||||
- "postgres"
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
test: ["CMD", "curl", "-f", "http://127.0.0.1:80"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
postgres:
|
||||
image: "nginx"
|
||||
environment:
|
||||
- SERVICE_FQDN_ACTIVEPIECES=/api
|
||||
- POSTGRES_DB=activepieces
|
||||
- PASSW=$AP_POSTGRES_PASSWORD
|
||||
- AP_FRONTEND_URL=$SERVICE_FQDN_ACTIVEPIECES
|
||||
- POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES
|
||||
- POSTGRES_USER=$SERVICE_USER_POSTGRES
|
||||
volumes:
|
||||
- "pg-data:/var/lib/postgresql/data"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
redis:
|
||||
image: redis:latest
|
||||
image: "redis:latest"
|
||||
volumes:
|
||||
- "redis_data:/data"
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- redis-cli
|
||||
- ping
|
||||
interval: 2s
|
||||
timeout: 10s
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 20s
|
||||
retries: 10
|
||||
volumes:
|
||||
dbdata:
|
||||
redis_data:
|
||||
networks:
|
||||
default:
|
||||
name: something
|
||||
external: true
|
||||
noinet:
|
||||
driver: bridge
|
||||
internal: true';
|
||||
|
||||
';
|
||||
|
||||
$this->serviceComposeFileString = Yaml::parse($this->serviceYaml);
|
||||
|
||||
$this->service = Service::create([
|
||||
'name' => 'Service for tests',
|
||||
'uuid' => (string) new Cuid2(),
|
||||
'uuid' => 'tgwcg8w4s844wkog8kskw44g',
|
||||
'docker_compose_raw' => $this->serviceYaml,
|
||||
'environment_id' => 1,
|
||||
'server_id' => 0,
|
||||
@@ -166,9 +165,19 @@ networks:
|
||||
afterEach(function () {
|
||||
// $this->applicationPreview->forceDelete();
|
||||
$this->application->forceDelete();
|
||||
DeleteService::run($this->service);
|
||||
$this->service->forceDelete();
|
||||
});
|
||||
|
||||
test('ServiceComposeParseNew', function () {
|
||||
$output = newParser($this->service);
|
||||
$this->service->saveComposeConfigs();
|
||||
// ray('New parser');
|
||||
// ray($output->toArray());
|
||||
ray($this->service->environment_variables->pluck('value', 'key')->toArray());
|
||||
expect($output)->toBeInstanceOf(Collection::class);
|
||||
});
|
||||
|
||||
// test('ApplicationComposeParse', function () {
|
||||
// expect($this->jsonapplicationComposeFile)->toBeJson()->ray();
|
||||
|
||||
@@ -332,14 +341,6 @@ afterEach(function () {
|
||||
|
||||
// });
|
||||
|
||||
// test('ServiceComposeParseNew', function () {
|
||||
// $output = newParser($this->application, pull_request_id: 1, preview_id: $this->applicationPreview->id);
|
||||
// // ray('New parser');
|
||||
// // ray($output->toArray());
|
||||
// ray($this->service->environment_variables_preview->pluck('value', 'key')->toArray());
|
||||
// expect($output)->toBeInstanceOf(Collection::class);
|
||||
// });
|
||||
|
||||
// test('ServiceComposeParseOld', function () {
|
||||
// $output = parseDockerComposeFile($this->service);
|
||||
// ray('Old parser');
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.329"
|
||||
"version": "4.0.0-beta.332"
|
||||
},
|
||||
"nightly": {
|
||||
"version": "4.0.0-beta.330"
|
||||
"version": "4.0.0-beta.333"
|
||||
},
|
||||
"helper": {
|
||||
"version": "1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user