Compare commits

...

163 Commits

Author SHA1 Message Date
Andras Bacsai
bae9ea79de Merge pull request #3366 from coollabsio/next
v4.0.0-beta.332
2024-09-10 14:41:41 +02:00
Andras Bacsai
d57c9d8aa0 feat: add elixir finetunes to the deployment job 2024-09-10 12:44:16 +02:00
Andras Bacsai
c7c2924990 fix: Update remoteProcess.php to handle null values in logItem properties 2024-09-10 12:05:10 +02:00
Andras Bacsai
aa30e83f4a fix: delete older versions of the helper image other than the latest one 2024-09-10 11:33:52 +02:00
Andras Bacsai
77455cd444 fix: scp through cloudflare 2024-09-10 10:19:13 +02:00
Andras Bacsai
2777fbc0ec fix: Remove debug statement in shared.php 2024-09-10 08:52:25 +02:00
Andras Bacsai
2c929b300a feat: Expose project description in API response 2024-09-10 08:49:25 +02:00
Andras Bacsai
27ad4441ee formatting 2024-09-10 08:49:20 +02:00
Andras Bacsai
63729c7bbf Merge pull request #3373 from mattstein/api-project-description
feat: Expose project description in API response
2024-09-10 08:49:08 +02:00
Andras Bacsai
1e68444f10 Merge pull request #3374 from Vahor/host-network
fix: don't add `networks` key if `network_mode` is used
2024-09-10 08:42:17 +02:00
Andras Bacsai
f8dfe643f4 chore: Update appwrite.yaml to include OpenSSL key variable assignment 2024-09-10 08:37:57 +02:00
Vahor
66cf6df4b3 skip docker network creation 2024-09-09 23:46:29 +02:00
Vahor
29acc4ee25 fix: don't add networks key if network_mode is used 2024-09-09 23:30:47 +02:00
Matt Stein
f73983e3dd Include project’s description in API response. 2024-09-09 09:44:43 -07:00
Matt Stein
44d417c07e Fix user-facing string case. 2024-09-09 09:38:40 -07:00
Andras Bacsai
1d72f76072 fix: appwrite template + parser 2024-09-09 15:04:51 +02:00
Andras Bacsai
c2f7e85022 Merge pull request #3364 from peaklabs-dev/improve-persist-ssh-sessions
Feat: Implement SSH multiplexing to reduce the number of SSH authentications in remote processes
2024-09-09 11:23:24 +02:00
Andras Bacsai
9e6486fa66 Merge pull request #3367 from peaklabs-dev/default-timezone
Fix: Set a default server timezone
2024-09-09 11:20:10 +02:00
peaklabs-dev
28bcd0023c remove cache 2024-09-09 10:33:57 +02:00
Andras Bacsai
84093afaf6 refactor: Improve environment variable handling in shared.php 2024-09-09 10:16:12 +02:00
Andras Bacsai
40347744e0 chore: Set timeout for ServerCheckJob to 60 seconds 2024-09-09 09:08:43 +02:00
Andras Bacsai
060988d923 fix: reenable overlapping servercheckjob 2024-09-09 09:05:40 +02:00
Andras Bacsai
b093c9757c Merge branch 'next' into improve-persist-ssh-sessions 2024-09-09 08:30:04 +02:00
peaklabs-dev
4f9e1a3e5e Feat: Cleanup stale multiplexing connections 2024-09-08 19:37:00 +02:00
peaklabs-dev
c8218e6901 Fix: Enabel mux 2024-09-08 19:15:37 +02:00
peaklabs-dev
cc10d08a7c Feat: Implement SSH Multiplexing 2024-09-08 18:13:00 +02:00
peaklabs-dev
e5a980d544 Merge pull request #3361 from coollabsio/main
merge main into next
2024-09-08 15:33:59 +02:00
peaklabs-dev
59c7f2cb56 Fix: Set a default server timezone 2024-09-08 15:24:27 +02:00
Andras Bacsai
d2a306dab9 refactor: Skip returning volume if driver type is cifs or nfs 2024-09-08 13:53:20 +02:00
Andras Bacsai
681a745fc7 chore: Update coolify-helper.yml to include "next" branch in push trigger 2024-09-08 13:09:14 +02:00
Andras Bacsai
abb6655fef chore: Update versions.json to version 1.0.1 2024-09-08 12:42:46 +02:00
Andras Bacsai
aa586a5677 chore: Update docker cleanup schedule to run daily at midnight 2024-09-08 12:40:53 +02:00
Andras Bacsai
87ee3c511c chore: Update docker image pruning command to exclude managed images 2024-09-08 12:38:22 +02:00
Andras Bacsai
a17daf96be chore: Add coolify.managed=true label to Docker image builds 2024-09-08 12:38:16 +02:00
Andras Bacsai
a419496066 testing label 2024-09-08 12:35:11 +02:00
Andras Bacsai
c668d2d1ff chore: Update DATABASE_URL in plunk.yaml to use plunk database 2024-09-07 20:59:51 +02:00
Andras Bacsai
4611332a8f newparser parser parsing parser parse 2024-09-07 20:57:56 +02:00
Andras Bacsai
8b3eed5895 chore: Update version to 4.0.0-beta.332 2024-09-07 20:56:56 +02:00
Andras Bacsai
9861ad4045 refactor: Update cleanup schedule to run daily at midnight 2024-09-07 20:56:52 +02:00
Andras Bacsai
5fb560dbbf chore: Update versions.json and sentry.php to 4.0.0-beta.332 2024-09-07 20:56:26 +02:00
Andras Bacsai
435c0baa87 Merge pull request #3350 from coollabsio/next
v4.0.0-beta.331
2024-09-07 14:14:26 +02:00
Andras Bacsai
bb1454d255 Merge pull request #3353 from coollabsio/fix-helper-pull-s3-backup
Fix: Pull helper image if not available otherwise s3 backup upload fails
2024-09-07 14:11:24 +02:00
peaklabs-dev
a882d3c713 code cleanup 2024-09-07 12:25:50 +02:00
peaklabs-dev
6010b3209d remove duplicated code 2024-09-07 12:23:15 +02:00
peaklabs-dev
504133232a Improve logic, made it simpler 2024-09-07 12:19:40 +02:00
peaklabs-dev
d816863d31 Fix: Pull helper image if not available otherwise s3 backup upload fails 2024-09-07 11:48:20 +02:00
ayntk-ai
3eb909d3bc Update version to 4.0.0-beta.331 2024-09-06 20:29:02 +02:00
ayntk-ai
a102e812cf fix: Plunk NEXT_PUBLIC_API_URI 2024-09-06 20:25:51 +02:00
Andras Bacsai
254611dda8 Merge pull request #3348 from coollabsio/next
fix fix fix friday fix
2024-09-06 16:55:54 +02:00
Andras Bacsai
d8f9e5910f refactor: Improve handling of server timezones in scheduled backups and tasks 2024-09-06 16:52:46 +02:00
Andras Bacsai
68d4a30eb0 refactor: Improve handling of server timezones in scheduled backups and tasks 2024-09-06 16:51:15 +02:00
Andras Bacsai
5c05ea4463 Merge pull request #3347 from coollabsio/next
refactor: Improve handling of server timezones in scheduled backups
2024-09-06 16:42:54 +02:00
Andras Bacsai
a2dac9394a refactor: Improve handling of server timezones in scheduled backups and tasks 2024-09-06 16:42:12 +02:00
Andras Bacsai
7fabeec08d Merge pull request #3316 from coollabsio/next
v4.0.0-beta.330
2024-09-06 14:53:39 +02:00
Andras Bacsai
a9228b110e chore: Update coolify version to 4.0.0-beta.331 2024-09-06 14:33:30 +02:00
Andras Bacsai
148c7d212c update install scripts to pull the latest helper version during installation 2024-09-06 14:33:06 +02:00
Andras Bacsai
98154549cf chore: Update Ray configuration and Dockerfile 2024-09-06 12:06:35 +02:00
Andras Bacsai
3d4f02afde Merge pull request #3326 from grantmagdanz/fix-chatwoot-config
Bug fix: Update chatwoot service name to fix issues with reverse proxy
2024-09-06 12:06:51 +02:00
Andras Bacsai
b57e2960f2 fix: parser 2024-09-06 12:05:22 +02:00
Andras Bacsai
110fac944d chore: Expose port 3000 in browserless.yaml template 2024-09-06 12:05:14 +02:00
Andras Bacsai
518ba3502d Merge pull request #3338 from coollabsio/add-missing-api-endpoints-for-service-envs
Add missing api endpoints for service envs
2024-09-06 10:52:04 +02:00
Andras Bacsai
676cee9e3e Merge pull request #3331 from galer7/add-missing-api-endpoints-for-service-envs
Add API endpoints for service environment variables
2024-09-06 10:51:10 +02:00
Andras Bacsai
ec7b18556e Update services controller to include new service envs commands 2024-09-06 10:48:47 +02:00
Andras Bacsai
8d2b280b03 chore: Add middleware for updating environment variables by UUID in api.php routes 2024-09-06 10:48:25 +02:00
Andras Bacsai
ba0e29aaf4 chore: Update Ray configuration and Dockerfile 2024-09-06 10:21:23 +02:00
Andras Bacsai
fccd31009c chore: Enable Ray by default and update Dockerfile with latest versions of PACK and NIXPACKS 2024-09-06 10:21:02 +02:00
Andras Bacsai
34e213202a chore: Disable Ray by default 2024-09-06 10:20:35 +02:00
Andras Bacsai
e7ab43c018 Merge branch 'next' of github.com:coollabsio/coolify into next 2024-09-06 10:13:05 +02:00
Andras Bacsai
0c87a8f4ec chore: Update Dockerfile with latest versions of PACK and NIXPACKS 2024-09-06 10:13:02 +02:00
Andras Bacsai
54e69de2af docs: Update Plunk documentation link in compose/plunk.yaml 2024-09-06 10:12:59 +02:00
Andras Bacsai
545613b554 Merge branch 'main' into next 2024-09-06 10:04:37 +02:00
Andras Bacsai
5c7b9473f8 feat: Refactor shared.php to improve environment variable handling 2024-09-06 10:03:09 +02:00
Andras Bacsai
a32e53c5a3 feat: Update Docker Compose file with DB_URL environment variable 2024-09-06 10:02:44 +02:00
Andras Bacsai
b44f4e49e8 chore: Update server form layout and settings 2024-09-06 08:46:27 +02:00
Andras Bacsai
321b8559e0 feat: Update server_settings table to force docker cleanup 2024-09-06 08:46:24 +02:00
Gabriel Galer
69794f4ca8 Update api.php routes to include middleware for updating environment variables by UUID 2024-09-06 08:31:32 +03:00
Gabriel Galer
4e1663e9db Fix bulk rename problems in api.php 2024-09-06 00:10:40 +03:00
Gabriel Galer
2e5ed5969d Update services controller to include new service envs commands 2024-09-05 23:58:52 +03:00
Gabriel Galer
ab055e0692 Update api.php routes 2024-09-05 23:58:52 +03:00
Gabriel Galer
6c2717ad08 Update openapi spec 2024-09-05 23:58:52 +03:00
Andras Bacsai
3ac52af673 Update coolify-helper.yml 2024-09-05 23:58:52 +03:00
Andras Bacsai
22d99dec52 Update coolify-helper.yml 2024-09-05 23:58:52 +03:00
ayntk-ai
6a654e31bd Update service-templates.json 2024-09-05 20:52:49 +02:00
ayntk-ai
d07cf59460 Fix: Plunk svg 2024-09-05 20:51:36 +02:00
peaklabs-dev
90e435d392 Merge pull request #3201 from FranckKe/add_plunk_template
feat: add Plunk template
2024-09-05 20:39:04 +02:00
Grant Magdanz
dfadadda10 Update chatwoot service name to fix issues with reverse proxy 2024-09-05 11:08:01 -07:00
ayntk-ai
0a7c7036f1 Update service-templates.json 2024-09-05 18:57:56 +02:00
peaklabs-dev
9215054d72 Merge pull request #3148 from Skeyelab/adding-browserless-template
feat: adding Browserless template
2024-09-05 18:39:18 +02:00
Andras Bacsai
22de8a7d2b chore: Ignore unnecessary files in production build workflow 2024-09-05 14:54:47 +02:00
Andras Bacsai
6f5b92d322 Update coolify-helper.yml 2024-09-05 14:53:49 +02:00
Andras Bacsai
9ef44f9ffb Update coolify-helper.yml 2024-09-05 14:53:10 +02:00
Andras Bacsai
5a604b2fc4 Update versions.json 2024-09-05 14:51:49 +02:00
Andras Bacsai
65b8d3c6d4 Merge pull request #3320 from coollabsio/update_helper_image
chore: Update coolify-helper.yml to get version from versions.json
2024-09-05 14:50:03 +02:00
Andras Bacsai
e05e0da058 chore: Update coolify-helper.yml to get version from versions.json 2024-09-05 14:42:27 +02:00
Andras Bacsai
e4854aaa1b Refactor muxFilename method to use UUID instead of IP, port, and user 2024-09-05 14:41:04 +02:00
Andras Bacsai
2531574a9a Merge pull request #3256 from Vahor/add-server-name
Add server name in execute command container options
2024-09-05 11:47:21 +02:00
Andras Bacsai
3aa31f3da6 fix: Update helper image pulling logic to only pull if the version is newer 2024-09-05 11:44:33 +02:00
Andras Bacsai
645337b09c Merge pull request #3264 from Vahor/install-log-drain-spam
fix: don't check logDrain installation if it's not enabled
2024-09-05 11:40:22 +02:00
Andras Bacsai
bd3220ad73 Merge pull request #3283 from TimKochDev/fix-deployments-typo
fix: Deployment running for - without "ago"
2024-09-05 11:34:04 +02:00
Andras Bacsai
6528bc5766 chore: Update UI for displaying deployment status in deployment list 2024-09-05 11:25:01 +02:00
Andras Bacsai
93af54ef84 chore: Update UI for displaying deployment status in deployment list 2024-09-05 11:23:59 +02:00
Andras Bacsai
08b9c79298 fix: Handle project not found error in environment_details API endpoint 2024-09-05 11:18:00 +02:00
Andras Bacsai
22bd305e8f chore: Update UI for displaying no executions found in scheduled task list 2024-09-05 11:15:56 +02:00
Andras Bacsai
dbad08f4dd Merge pull request #3288 from julienbeugras/fix-project-create-api-docs
Fix project create api docs
2024-09-05 11:16:05 +02:00
Andras Bacsai
b5232f3d32 Merge pull request #3300 from Vahor/remove-reverse-scheduled
fix: recent executions in wrong order in scheduled-task list ui
2024-09-05 11:07:48 +02:00
Andras Bacsai
58234ef65e Merge pull request #3301 from mattstein/main
Improve language in scheduled task container name helper
2024-09-05 11:06:11 +02:00
Andras Bacsai
d211362ab3 improvement: only pull helper image if the version is newer than the one 2024-09-05 11:04:58 +02:00
Andras Bacsai
629316d68a chore: Update GitHub workflow to use jq container for version extraction 2024-09-05 10:49:00 +02:00
Andras Bacsai
05084cb69c chore: Update GitHub workflow to use jq container for version extraction 2024-09-05 10:45:46 +02:00
Andras Bacsai
401c410adb Merge pull request #3302 from mahansky/deployment-logs-improvements
deployment log improvements
2024-09-05 10:29:10 +02:00
Andras Bacsai
4888f4c405 refactor: upgrade process of Coolify 2024-09-05 10:15:22 +02:00
Andras Bacsai
b241f17eee Merge pull request #3312 from Vahor/pull-coolify-only-on-updates
fix: pull coolify image only when the app needs to be updated
2024-09-05 10:07:50 +02:00
Andras Bacsai
bc22ec63e6 chore: Update GitHub workflow to use versions.json instead of version.json 2024-09-05 10:03:26 +02:00
Andras Bacsai
458a461388 chore: Update GitHub workflow to use versions.json instead of version.json 2024-09-05 10:02:22 +02:00
Andras Bacsai
a725ff0a75 chore: Update GitHub workflow to use versions.json instead of version.json 2024-09-05 09:51:02 +02:00
Andras Bacsai
a8fd7db9a8 Update version.json to versions.json in GitHub workflow 2024-09-05 09:44:48 +02:00
Andras Bacsai
fbb7568786 chore: Cleanup stucked resources and scheduled backups 2024-09-05 09:41:29 +02:00
Andras Bacsai
fae175039a chore: Update version.json to versions.json in GitHub workflow 2024-09-05 09:30:36 +02:00
Andras Bacsai
9196571737 test versioned helper image 2024-09-05 09:29:18 +02:00
Vahor
0dad77af33 save versions.json during CheckForUpdatesJob 2024-09-04 21:25:45 +02:00
Nathan
f43298a610 Merge branch 'next' into pull-coolify-only-on-updates 2024-09-04 19:43:16 +02:00
Vahor
02f950edc7 fix: pull coolify image only when the app needs to be updated 2024-09-04 19:38:13 +02:00
Andras Bacsai
817a72e753 chore: Update sponsor links in README.md 2024-09-04 16:55:29 +02:00
Andras Bacsai
9c2f4ec04e Update version to 4.0.0-beta.330 2024-09-04 16:55:25 +02:00
Andras Bacsai
3f34df251e Merge pull request #3310 from coollabsio/next
v4.0.0-beta.329
2024-09-04 14:35:34 +02:00
Andras Bacsai
bfeaae9caa fix: env variable in value parsed 2024-09-04 14:33:16 +02:00
Andras Bacsai
ba90a52344 Update version to 4.0.0-beta.329 2024-09-04 14:10:19 +02:00
Andras Bacsai
a3a61dbe55 refactor: Update Docker Compose location handling in PublicGitRepository 2024-09-04 14:09:55 +02:00
Andras Bacsai
5799e6d8b0 fix: logical volumes could be overwritten with new path 2024-09-04 14:09:52 +02:00
mahansky
3b533c7d06 fix same commands different batch 2024-09-04 13:57:03 +02:00
Andras Bacsai
b2944f11db Merge pull request #3308 from coollabsio/next
v4.0.0-beta.328
2024-09-04 13:38:19 +02:00
Andras Bacsai
25e2b812cb fix: Convert environment variables to one format in shared.php 2024-09-04 13:37:15 +02:00
Andras Bacsai
59383d3678 Update README.md 2024-09-04 13:04:09 +02:00
Andras Bacsai
7b2d09f9d1 Update README.md 2024-09-04 12:44:22 +02:00
Andras Bacsai
d30faf7bc4 refactor: Update background color of sponsor section in README.md 2024-09-04 12:30:53 +02:00
Andras Bacsai
b9d3f9da62 chore: Update Coolify version to 4.0.0-beta.328 2024-09-04 12:30:02 +02:00
Andras Bacsai
86ee9c09ce feat: Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid 2024-09-04 12:28:57 +02:00
Andras Bacsai
4f32b48d29 Merge pull request #3306 from coollabsio/next
v4.0.0-beta.327
2024-09-04 11:40:40 +02:00
Andras Bacsai
04ce622465 refactor: Update build_args property type in ApplicationDeploymentJob 2024-09-04 11:34:31 +02:00
Andras Bacsai
ed7817906a feat: Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid 2024-09-04 11:06:30 +02:00
Andras Bacsai
e0748ee240 chore: Update Coolify version to 4.0.0-beta.327 2024-09-04 10:09:14 +02:00
Andras Bacsai
25480fe624 fix: openapi endpoint urls 2024-09-04 10:09:10 +02:00
mahansky
b0039885eb use computed property 2024-09-04 03:39:50 +02:00
Vahor
cadb12986c fix: wrong executions order 2024-09-03 21:10:44 +02:00
mahansky
63a07e7649 deployment log improvements 2024-09-03 20:09:42 +02:00
Andras Bacsai
37915234ad Merge pull request #3299 from coollabsio/next
chore: Add cd command to change directory before removing .env file
2024-09-03 17:28:05 +02:00
Andras Bacsai
eaabf94cd7 chore: Add cd command to change directory before removing .env file 2024-09-03 17:27:22 +02:00
Andras Bacsai
3badbafd89 Merge pull request #3298 from coollabsio/next
v4.0.0-beta.326
2024-09-03 17:13:26 +02:00
Andras Bacsai
7b041f3f22 refactor: Improve handling of COOLIFY_URL in shared.php 2024-09-03 17:13:13 +02:00
Andras Bacsai
8150b6fdaf fix: check if array is associative or not 2024-09-03 17:04:56 +02:00
Andras Bacsai
8d9a7f0b3c chore: Update Coolify version to 4.0.0-beta.326 2024-09-03 11:48:06 +02:00
Andras Bacsai
a7d67e44ca fix: copy large compose files through scp (not ssh) 2024-09-03 11:47:30 +02:00
Matt Stein
08a80876f9 Fix language in helper messages. 2024-09-02 19:43:16 -07:00
root
ae4c889fa2 Fix API documentation for project creation endpoint 2024-09-02 11:05:58 +02:00
Andras Bacsai
eb6add358a Merge pull request #3287 from coollabsio/next
v4.0.0-beta.325
2024-09-02 10:59:16 +02:00
Andras Bacsai
dfd5cc9cef fix: log drain only for Applications 2024-09-02 10:57:03 +02:00
Andras Bacsai
a2ab23529f chore: Update Coolify version to 4.0.0-beta.325 2024-09-02 10:56:48 +02:00
Tim Koch
f072823f00 fix: Deployment running for - without "ago" 2024-09-01 22:01:05 +02:00
Vahor
bf475e538c don't check logDrain installation if it's not enabled 2024-08-30 17:29:25 +02:00
Vahor
fe477ba325 add server name in execute command container options 2024-08-29 22:46:00 +02:00
Franck Kerbiriou
a26bc65137 Add Plunk template 2024-08-22 22:42:56 +02:00
Eric Dahl
b73db2d725 Update browserless.yaml 2024-08-20 19:17:00 -04:00
Eric Dahl
8168b564ea adding browserless service 2024-08-20 19:09:05 -04:00
89 changed files with 2799 additions and 1449 deletions

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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:

View File

@@ -4,6 +4,8 @@ on:
push:
branches: ["main"]
paths-ignore:
- .github/workflows/coolify-helper.yml
- docker/coolify-helper/Dockerfile
- templates/service-templates.json
env:

View File

@@ -35,22 +35,32 @@ Thank you so much!
Special thanks to our biggest sponsors!
<a href="https://cccareers.org/" target="_blank"><img src="./other/logos/ccc-logo.webp" alt="cccareers logo" width="200"/></a>
<a href="http://htznr.li/CoolifyXHetzner" target="_blank"><img src="./other/logos/hetzner.jpg" alt="hetzner logo" width="150"/></a>
<a href="https://logto.io/?ref=coolify" target="_blank"><img src="./other/logos/logto.webp" alt="logto logo" width="150"/></a>
<a href="https://bc.direct/?ref=coolify.io" target="_blank"><img src="./other/logos/bc.png" alt="bc direct logo" width="200"/></a>
<a href="https://www.quantcdn.io/?ref=coolify.io" target="_blank"><img src="./other/logos/quant.svg" alt="quantcdn logo" width="150"/></a>
<a href="https://arcjet.com/?ref=coolify.io" target="_blank"><img src="./other/logos/arcjet.svg" alt="arcjet logo" width="200"/></a>
<a href="https://supa.guide/?ref=coolify.io" target="_blank"><img src="./other/logos/supaguide.png" alt="supaguide logo" width="200"/></a>
<a href="https://tigrisdata.com/?ref=coolify.io" target="_blank"><img src="./other/logos/tigris.svg" alt="tigris logo" width="140"/></a>
<a href="https://fractalnetworks.co/?ref=coolify.io" target="_blank"><img src="./other/logos/fractal.svg" alt="fractal logo" width="180"/></a>
<a href="https://coolify.ad.vin/?ref=coolify.io" target="_blank"><img src="./other/logos/advin.png" alt="advin logo" width="250"/></a>
<a href="https://trieve.ai/?ref=coolify.io" target="_blank"><img src="./other/logos/trieve_bg.png" alt="trieve logo" width="180"/></a>
<a href="https://blacksmith.sh/?ref=coolify.io" target="_blank"><img src="./other/logos/blacksmith.svg" alt="blacksmith logo" width="200"/></a>
<a href="https://latitude.sh/?ref=coolify.io" target="_blank"><img src="./other/logos/latitude.svg" alt="latitude logo" width="200"/></a>
<a href="https://brand.dev/?ref=coolify.io" target="_blank"><img src="./other/logos/branddev.png" alt="branddev logo" width="200"/></a>
<a href="https://jobscollider.com/remote-jobs?ref=coolify.io" target="_blank"><img src="./other/logos/jobscollider.svg" alt="jobscollider logo" width="200"/></a>
<a href="https://hostinger.com?ref=coolify.io" target="_blank"><img src="./other/logos/hostinger.svg" alt="hostinger logo" width="200"/></a>
### Special Sponsors
![image](https://github.com/user-attachments/assets/c95a07df-7c5a-4e77-a35a-81f25fcbece1)
* [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+)
<a href="https://serpapi.com/?ref=coolify.io"><img width="60px" alt="SerpAPI" src="https://github.com/serpapi.png"/></a>
@@ -77,6 +87,7 @@ Special thanks to our biggest sponsors!
<a href="https://github.com/urtho"><img src="https://github.com/urtho.png" width="60px" alt="Paweł Pierścionek" /></a>
<a href="https://github.com/monocursive"><img src="https://github.com/monocursive.png" width="60px" alt="Michael Mazurczak" /></a>
<a href="https://formbricks.com/?utm_source=coolify.io"><img src="https://github.com/formbricks.png" width="60px" alt="Formbricks" /></a>
<a href="https://x.com/adithsuhas17?utm_source=coolify.io"><img src="https://github.com/adith-suhas-sv.png" width="60px" alt="Adith Suhas" /></a>
## Organizations
<a href="https://opencollective.com/coollabsio/organization/0/website"><img src="https://opencollective.com/coollabsio/organization/0/avatar.svg"></a>

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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';

View File

@@ -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();

View File

@@ -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])) {

View File

@@ -53,6 +53,7 @@ class ApplicationsController extends Controller
summary: 'List',
description: 'List all applications.',
path: '/applications',
operationId: 'list-applications',
security: [
['bearerAuth' => []],
],
@@ -101,6 +102,7 @@ class ApplicationsController extends Controller
summary: 'Create (Public)',
description: 'Create new application based on a public git repository.',
path: '/applications/public',
operationId: 'create-public-application',
security: [
['bearerAuth' => []],
],
@@ -202,6 +204,7 @@ class ApplicationsController extends Controller
summary: 'Create (Private - GH App)',
description: 'Create new application based on a private repository through a Github App.',
path: '/applications/private-github-app',
operationId: 'create-private-github-app-application',
security: [
['bearerAuth' => []],
],
@@ -303,6 +306,7 @@ class ApplicationsController extends Controller
summary: 'Create (Private - Deploy Key)',
description: 'Create new application based on a private repository through a Deploy Key.',
path: '/applications/private-deploy-key',
operationId: 'create-private-deploy-key-application',
security: [
['bearerAuth' => []],
],
@@ -404,6 +408,7 @@ class ApplicationsController extends Controller
summary: 'Create (Dockerfile)',
description: 'Create new application based on a simple Dockerfile.',
path: '/applications/dockerfile',
operationId: 'create-dockerfile-application',
security: [
['bearerAuth' => []],
],
@@ -490,6 +495,7 @@ class ApplicationsController extends Controller
summary: 'Create (Docker Image)',
description: 'Create new application based on a prebuilt docker image',
path: '/applications/dockerimage',
operationId: 'create-dockerimage-application',
security: [
['bearerAuth' => []],
],
@@ -573,6 +579,7 @@ class ApplicationsController extends Controller
summary: 'Create (Docker Compose)',
description: 'Create new application based on a docker-compose file.',
path: '/applications/dockercompose',
operationId: 'create-dockercompose-application',
security: [
['bearerAuth' => []],
],
@@ -1171,6 +1178,7 @@ class ApplicationsController extends Controller
summary: 'Get',
description: 'Get application by UUID.',
path: '/applications/{uuid}',
operationId: 'get-application-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -1235,6 +1243,7 @@ class ApplicationsController extends Controller
summary: 'Delete',
description: 'Delete application by UUID.',
path: '/applications/{uuid}',
operationId: 'delete-application-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -1321,6 +1330,7 @@ class ApplicationsController extends Controller
summary: 'Update',
description: 'Update application by UUID.',
path: '/applications/{uuid}',
operationId: 'update-application-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -1557,6 +1567,7 @@ class ApplicationsController extends Controller
summary: 'List Envs',
description: 'List all envs by application UUID.',
path: '/applications/{uuid}/envs',
operationId: 'list-envs-by-application-uuid',
security: [
['bearerAuth' => []],
],
@@ -1639,6 +1650,7 @@ class ApplicationsController extends Controller
summary: 'Update Env',
description: 'Update env by application UUID.',
path: '/applications/{uuid}/envs',
operationId: 'update-env-by-application-uuid',
security: [
['bearerAuth' => []],
],
@@ -1821,6 +1833,7 @@ class ApplicationsController extends Controller
summary: 'Update Envs (Bulk)',
description: 'Update multiple envs by application UUID.',
path: '/applications/{uuid}/envs/bulk',
operationId: 'update-envs-by-application-uuid',
security: [
['bearerAuth' => []],
],
@@ -2012,6 +2025,7 @@ class ApplicationsController extends Controller
summary: 'Create Env',
description: 'Create env by application UUID.',
path: '/applications/{uuid}/envs',
operationId: 'create-env-by-application-uuid',
security: [
['bearerAuth' => []],
],
@@ -2171,6 +2185,7 @@ class ApplicationsController extends Controller
summary: 'Delete Env',
description: 'Delete env by UUID.',
path: '/applications/{uuid}/envs/{env_uuid}',
operationId: 'delete-env-by-application-uuid',
security: [
['bearerAuth' => []],
],
@@ -2256,6 +2271,7 @@ class ApplicationsController extends Controller
summary: 'Start',
description: 'Start application. `Post` request is also accepted.',
path: '/applications/{uuid}/start',
operationId: 'start-application-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -2359,6 +2375,7 @@ class ApplicationsController extends Controller
summary: 'Stop',
description: 'Stop application. `Post` request is also accepted.',
path: '/applications/{uuid}/stop',
operationId: 'stop-application-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -2431,6 +2448,7 @@ class ApplicationsController extends Controller
summary: 'Restart',
description: 'Restart application. `Post` request is also accepted.',
path: '/applications/{uuid}/restart',
operationId: 'restart-application-by-uuid',
security: [
['bearerAuth' => []],
],

View File

@@ -46,6 +46,7 @@ class DatabasesController extends Controller
summary: 'List',
description: 'List all databases.',
path: '/databases',
operationId: 'list-databases',
security: [
['bearerAuth' => []],
],
@@ -91,6 +92,7 @@ class DatabasesController extends Controller
summary: 'Get',
description: 'Get database by UUID.',
path: '/databases/{uuid}',
operationId: 'get-database-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -151,6 +153,7 @@ class DatabasesController extends Controller
summary: 'Update',
description: 'Update database by UUID.',
path: '/databases/{uuid}',
operationId: 'update-database-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -510,6 +513,7 @@ class DatabasesController extends Controller
summary: 'Create (PostgreSQL)',
description: 'Create a new PostgreSQL database.',
path: '/databases/postgresql',
operationId: 'create-database-postgresql',
security: [
['bearerAuth' => []],
],
@@ -575,6 +579,7 @@ class DatabasesController extends Controller
summary: 'Create (Clickhouse)',
description: 'Create a new Clickhouse database.',
path: '/databases/clickhouse',
operationId: 'create-database-clickhouse',
security: [
['bearerAuth' => []],
],
@@ -636,6 +641,7 @@ class DatabasesController extends Controller
summary: 'Create (DragonFly)',
description: 'Create a new DragonFly database.',
path: '/databases/dragonfly',
operationId: 'create-database-dragonfly',
security: [
['bearerAuth' => []],
],
@@ -696,6 +702,7 @@ class DatabasesController extends Controller
summary: 'Create (Redis)',
description: 'Create a new Redis database.',
path: '/databases/redis',
operationId: 'create-database-redis',
security: [
['bearerAuth' => []],
],
@@ -757,6 +764,7 @@ class DatabasesController extends Controller
summary: 'Create (KeyDB)',
description: 'Create a new KeyDB database.',
path: '/databases/keydb',
operationId: 'create-database-keydb',
security: [
['bearerAuth' => []],
],
@@ -818,6 +826,7 @@ class DatabasesController extends Controller
summary: 'Create (MariaDB)',
description: 'Create a new MariaDB database.',
path: '/databases/mariadb',
operationId: 'create-database-mariadb',
security: [
['bearerAuth' => []],
],
@@ -882,6 +891,7 @@ class DatabasesController extends Controller
summary: 'Create (MySQL)',
description: 'Create a new MySQL database.',
path: '/databases/mysql',
operationId: 'create-database-mysql',
security: [
['bearerAuth' => []],
],
@@ -945,6 +955,7 @@ class DatabasesController extends Controller
summary: 'Create (MongoDB)',
description: 'Create a new MongoDB database.',
path: '/databases/mongodb',
operationId: 'create-database-mongodb',
security: [
['bearerAuth' => []],
],
@@ -1514,6 +1525,7 @@ class DatabasesController extends Controller
summary: 'Delete',
description: 'Delete database by UUID.',
path: '/databases/{uuid}',
operationId: 'delete-database-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -1597,6 +1609,7 @@ class DatabasesController extends Controller
summary: 'Start',
description: 'Start database. `Post` request is also accepted.',
path: '/databases/{uuid}/start',
operationId: 'start-database-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -1672,6 +1685,7 @@ class DatabasesController extends Controller
summary: 'Stop',
description: 'Stop database. `Post` request is also accepted.',
path: '/databases/{uuid}/stop',
operationId: 'stop-database-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -1747,6 +1761,7 @@ class DatabasesController extends Controller
summary: 'Restart',
description: 'Restart database. `Post` request is also accepted.',
path: '/databases/{uuid}/restart',
operationId: 'restart-database-by-uuid',
security: [
['bearerAuth' => []],
],

View File

@@ -32,6 +32,7 @@ class DeployController extends Controller
summary: 'List',
description: 'List currently running deployments',
path: '/deployments',
operationId: 'list-deployments',
security: [
['bearerAuth' => []],
],
@@ -79,12 +80,13 @@ class DeployController extends Controller
summary: 'Get',
description: 'Get deployment by UUID.',
path: '/deployments/{uuid}',
operationId: 'get-deployment-by-uuid',
security: [
['bearerAuth' => []],
],
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(
@@ -134,6 +136,7 @@ class DeployController extends Controller
summary: 'Deploy',
description: 'Deploy by tag or uuid. `Post` request also accepted.',
path: '/deploy',
operationId: 'deploy-by-tag-or-uuid',
security: [
['bearerAuth' => []],
],
@@ -147,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',

View File

@@ -13,6 +13,7 @@ class OtherController extends Controller
summary: 'Version',
description: 'Get Coolify version.',
path: '/version',
operationId: 'version',
security: [
['bearerAuth' => []],
],
@@ -43,6 +44,7 @@ class OtherController extends Controller
summary: 'Enable API',
description: 'Enable API (only with root permissions).',
path: '/enable',
operationId: 'enable-api',
security: [
['bearerAuth' => []],
],
@@ -94,6 +96,7 @@ class OtherController extends Controller
summary: 'Disable API',
description: 'Disable API (only with root permissions).',
path: '/disable',
operationId: 'disable-api',
security: [
['bearerAuth' => []],
],
@@ -158,6 +161,7 @@ class OtherController extends Controller
summary: 'Healthcheck',
description: 'Healthcheck endpoint.',
path: '/healthcheck',
operationId: 'healthcheck',
responses: [
new OA\Response(
response: 200,

View File

@@ -11,8 +11,9 @@ class ProjectController extends Controller
{
#[OA\Get(
summary: 'List',
description: 'list projects.',
description: 'List projects.',
path: '/projects',
operationId: 'list-projects',
security: [
['bearerAuth' => []],
],
@@ -46,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),
);
@@ -54,8 +55,9 @@ 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: [
['bearerAuth' => []],
],
@@ -102,6 +104,7 @@ class ProjectController extends Controller
summary: 'Environment',
description: 'Get environment by name.',
path: '/projects/{uuid}/{environment_name}',
operationId: 'get-environment-by-name',
security: [
['bearerAuth' => []],
],
@@ -136,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);
@@ -155,6 +161,7 @@ class ProjectController extends Controller
summary: 'Create',
description: 'Create Project.',
path: '/projects',
operationId: 'create-project',
security: [
['bearerAuth' => []],
],
@@ -167,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.'],
],
),
@@ -250,6 +257,7 @@ class ProjectController extends Controller
summary: 'Update',
description: 'Update Project.',
path: '/projects/{uuid}',
operationId: 'update-project-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -333,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();
@@ -355,6 +363,7 @@ class ProjectController extends Controller
summary: 'Delete',
description: 'Delete project by UUID.',
path: '/projects/{uuid}',
operationId: 'delete-project-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -408,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) {

View File

@@ -13,6 +13,7 @@ class ResourcesController extends Controller
summary: 'List',
description: 'Get all resources.',
path: '/resources',
operationId: 'list-resources',
security: [
['bearerAuth' => []],
],

View File

@@ -26,6 +26,7 @@ class SecurityController extends Controller
summary: 'List',
description: 'List all private keys.',
path: '/security/keys',
operationId: 'list-private-keys',
security: [
['bearerAuth' => []],
],
@@ -68,12 +69,13 @@ class SecurityController extends Controller
summary: 'Get',
description: 'Get key by UUID.',
path: '/security/keys/{uuid}',
operationId: 'get-private-key-by-uuid',
security: [
['bearerAuth' => []],
],
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(
@@ -124,6 +126,7 @@ class SecurityController extends Controller
summary: 'Create',
description: 'Create a new private key.',
path: '/security/keys',
operationId: 'create-private-key',
security: [
['bearerAuth' => []],
],
@@ -217,6 +220,7 @@ class SecurityController extends Controller
summary: 'Update',
description: 'Update a private key.',
path: '/security/keys',
operationId: 'update-private-key',
security: [
['bearerAuth' => []],
],
@@ -313,12 +317,13 @@ class SecurityController extends Controller
summary: 'Delete',
description: 'Delete a private key.',
path: '/security/keys/{uuid}',
operationId: 'delete-private-key-by-uuid',
security: [
['bearerAuth' => []],
],
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(

View File

@@ -46,6 +46,7 @@ class ServersController extends Controller
summary: 'List',
description: 'List all servers.',
path: '/servers',
operationId: 'list-servers',
security: [
['bearerAuth' => []],
],
@@ -100,12 +101,13 @@ class ServersController extends Controller
summary: 'Get',
description: 'Get server by UUID.',
path: '/servers/{uuid}',
operationId: 'get-server-by-uuid',
security: [
['bearerAuth' => []],
],
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(
@@ -177,12 +179,13 @@ class ServersController extends Controller
summary: 'Resources',
description: 'Get resources by server.',
path: '/servers/{uuid}/resources',
operationId: 'get-resources-by-server-uuid',
security: [
['bearerAuth' => []],
],
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(
@@ -254,12 +257,13 @@ class ServersController extends Controller
summary: 'Domains',
description: 'Get domains by server.',
path: '/servers/{uuid}/domains',
operationId: 'get-domains-by-server-uuid',
security: [
['bearerAuth' => []],
],
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(
@@ -401,6 +405,7 @@ class ServersController extends Controller
summary: 'Create',
description: 'Create Server.',
path: '/servers',
operationId: 'create-server',
security: [
['bearerAuth' => []],
],
@@ -545,6 +550,7 @@ class ServersController extends Controller
summary: 'Update',
description: 'Update Server.',
path: '/servers/{uuid}',
operationId: 'update-server-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -655,6 +661,7 @@ class ServersController extends Controller
summary: 'Delete',
description: 'Delete server by UUID.',
path: '/servers/{uuid}',
operationId: 'delete-server-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -727,6 +734,7 @@ class ServersController extends Controller
summary: 'Validate',
description: 'Validate server by UUID.',
path: '/servers/{uuid}/validate',
operationId: 'validate-server-by-uuid',
security: [
['bearerAuth' => []],
],

View File

@@ -38,6 +38,7 @@ class ServicesController extends Controller
summary: 'List',
description: 'List all services.',
path: '/services',
operationId: 'list-services',
security: [
['bearerAuth' => []],
],
@@ -88,6 +89,7 @@ class ServicesController extends Controller
summary: 'Create',
description: 'Create a one-click service',
path: '/services',
operationId: 'create-service',
security: [
['bearerAuth' => []],
],
@@ -365,6 +367,7 @@ class ServicesController extends Controller
summary: 'Get',
description: 'Get service by UUID.',
path: '/services/{uuid}',
operationId: 'get-service-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -375,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',
@@ -422,6 +425,7 @@ class ServicesController extends Controller
summary: 'Delete',
description: 'Delete service by UUID.',
path: '/services/{uuid}',
operationId: 'delete-service-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -432,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',
@@ -479,10 +483,521 @@ 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.',
path: '/services/{uuid}/start',
operationId: 'start-service-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -558,6 +1073,7 @@ class ServicesController extends Controller
summary: 'Stop',
description: 'Stop service. `Post` request is also accepted.',
path: '/services/{uuid}/stop',
operationId: 'stop-service-by-uuid',
security: [
['bearerAuth' => []],
],
@@ -633,6 +1149,7 @@ class ServicesController extends Controller
summary: 'Restart',
description: 'Restart service. `Post` request is also accepted.',
path: '/services/{uuid}/restart',
operationId: 'restart-service-by-uuid',
security: [
['bearerAuth' => []],
],

View File

@@ -32,6 +32,7 @@ class TeamController extends Controller
summary: 'List',
description: 'Get all teams.',
path: '/teams',
operationId: 'list-teams',
security: [
['bearerAuth' => []],
],
@@ -79,6 +80,7 @@ class TeamController extends Controller
summary: 'Get',
description: 'Get team by TeamId.',
path: '/teams/{id}',
operationId: 'get-team-by-id',
security: [
['bearerAuth' => []],
],
@@ -129,6 +131,7 @@ class TeamController extends Controller
summary: 'Members',
description: 'Get members by TeamId.',
path: '/teams/{id}/members',
operationId: 'get-members-by-team-id',
security: [
['bearerAuth' => []],
],
@@ -189,6 +192,7 @@ class TeamController extends Controller
summary: 'Authenticated Team',
description: 'Get currently authenticated team.',
path: '/teams/current',
operationId: 'get-current-team',
security: [
['bearerAuth' => []],
],
@@ -225,6 +229,7 @@ class TeamController extends Controller
summary: 'Authenticated Team Members',
description: 'Get currently authenticated team members.',
path: '/teams/current/members',
operationId: 'get-current-team-members',
security: [
['bearerAuth' => []],
],

View File

@@ -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;
@@ -109,7 +110,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
private bool $is_debug_enabled;
private $build_args;
private Collection|string $build_args;
private $env_args;
@@ -168,6 +169,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
$this->application_deployment_queue = ApplicationDeploymentQueue::find($application_deployment_queue_id);
$this->application = Application::find($this->application_deployment_queue->application_id);
$this->build_pack = data_get($this->application, 'build_pack');
$this->build_args = collect([]);
$this->application_deployment_queue_id = $application_deployment_queue_id;
$this->deployment_uuid = $this->application_deployment_queue->deployment_uuid;
@@ -1064,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';
@@ -1292,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);
@@ -1529,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') {

View File

@@ -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');
}
}

View File

@@ -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]);
}

View File

@@ -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);
}
}
}

View 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);
}
}
}

View File

@@ -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}";
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}
}

View File

@@ -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());

View File

@@ -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();

View File

@@ -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');

View File

@@ -99,6 +99,16 @@ class PublicGitRepository extends Component
}
}
public function updatedDockerComposeLocation()
{
if ($this->docker_compose_location) {
$this->docker_compose_location = rtrim($this->docker_compose_location, '/');
if (! str($this->docker_compose_location)->startsWith('/')) {
$this->docker_compose_location = '/'.$this->docker_compose_location;
}
}
}
public function updatedBuildPack()
{
if ($this->build_pack === 'nixpacks') {

View File

@@ -43,6 +43,7 @@ class EditCompose extends Component
{
$this->dispatch('info', 'Saving new docker compose...');
$this->dispatch('saveCompose', $this->service->docker_compose_raw);
$this->dispatch('refreshStorages');
}
public function instantSave()

View File

@@ -24,6 +24,7 @@ class All extends Component
protected $listeners = [
'saveKey' => 'submit',
'refreshEnvs',
'environmentVariableDeleted' => 'refreshEnvs',
];
@@ -61,7 +62,7 @@ class All extends Component
$sortBy = data_get($this->resource, 'settings.is_env_sorting_enabled') ? 'key' : 'order';
$sortFunction = function ($variables) use ($sortBy) {
if (!$variables) {
if (! $variables) {
return $variables;
}
if ($sortBy === 'key') {

View File

@@ -136,4 +136,4 @@ class Show extends Component
return handleError($e);
}
}
}
}

View File

@@ -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);

View File

@@ -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',

View File

@@ -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()

View File

@@ -28,6 +28,7 @@ class ScheduledTask extends BaseModel
public function executions(): HasMany
{
// Last execution first
return $this->hasMany(ScheduledTaskExecution::class)->orderBy('created_at', 'desc');
}

View File

@@ -880,7 +880,7 @@ $schema://$host {
public function muxFilename()
{
return "{$this->ip}_{$this->port}_{$this->user}";
return $this->uuid;
}
public function team()

View File

@@ -7,9 +7,10 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use OpenApi\Attributes as OA;
use Spatie\Url\Url;
use Symfony\Component\Yaml\Yaml;
use Visus\Cuid2\Cuid2;
#[OA\Schema(
description: 'Service model',
@@ -999,21 +1000,36 @@ class Service extends BaseModel
public function saveComposeConfigs()
{
$workdir = $this->workdir();
$commands[] = "mkdir -p $workdir";
instant_remote_process([
"mkdir -p $workdir",
"cd $workdir",
], $this->server);
$filename = new Cuid2.'-docker-compose.yml';
Storage::disk('local')->put("tmp/{$filename}", $this->docker_compose);
$path = Storage::path("tmp/{$filename}");
instant_scp($path, "{$workdir}/docker-compose.yml", $this->server);
Storage::disk('local')->delete("tmp/{$filename}");
$commands[] = "cd $workdir";
$json = Yaml::parse($this->docker_compose);
$this->docker_compose = Yaml::dump($json, 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);
$docker_compose_base64 = base64_encode($this->docker_compose);
$commands[] = "echo $docker_compose_base64 | base64 -d | tee docker-compose.yml > /dev/null";
$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);

View File

@@ -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;
}
}

View File

@@ -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)

View File

@@ -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([
@@ -2819,8 +2819,10 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$defaultLabels = defaultLabels($resource->id, $containerName, $pull_request_id, type: 'application');
$serviceLabels = $serviceLabels->merge($defaultLabels);
if ($server->isLogDrainEnabled() && $resource->isLogDrainEnabled()) {
data_set($service, 'logging', generate_fluentd_configuration());
if ($server->isLogDrainEnabled()) {
if ($resource instanceof Application && $resource->isLogDrainEnabled()) {
data_set($service, 'logging', generate_fluentd_configuration());
}
}
if ($serviceLabels->count() > 0) {
if ($resource->settings->is_container_label_escape_enabled) {
@@ -2862,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;
@@ -2918,22 +2921,205 @@ 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);
$logging = data_get($service, 'logging');
if ($server->isLogDrainEnabled() && $resource->isLogDrainEnabled()) {
$logging = generate_fluentd_configuration();
if ($server->isLogDrainEnabled()) {
if ($resource instanceof Application && $resource->isLogDrainEnabled()) {
$logging = generate_fluentd_configuration();
}
}
$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([]);
@@ -3065,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, '-');
@@ -3088,10 +3274,9 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$topLevel->get('volumes')->put($name, [
'name' => $name,
]);
LocalPersistentVolume::updateOrCreate(
[
'mount_path' => $target,
'name' => $name,
'resource_id' => $originalResource->id,
'resource_type' => get_class($originalResource),
],
@@ -3124,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,
]);
}
}
}
@@ -3175,177 +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 = 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,
@@ -3354,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) {
@@ -3362,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) {
@@ -3421,18 +3528,23 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$defaultLabels = defaultLabels($resource->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id);
}
// Add COOLIFY_FQDN & COOLIFY_URL to environment
if (! $isDatabase && $fqdns?->count() > 0) {
$environment->put('COOLIFY_URL', $fqdns->implode(','));
if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) {
$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?->count() > 0) {
if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) {
if ($isApplication) {
$shouldGenerateLabelsExactly = $resource->destination->server->settings->generate_exact_labels;
$uuid = $resource->uuid;
@@ -3516,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;
@@ -3540,7 +3654,6 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$parsedServices->put($serviceName, $payload);
}
ray($parsedServices);
$topLevel->put('services', $parsedServices);
$customOrder = ['services', 'volumes', 'networks', 'configs', 'secrets'];
@@ -3570,6 +3683,23 @@ function generate_fluentd_configuration(): array
];
}
function isAssociativeArray($array)
{
if ($array instanceof Collection) {
$array = $array->toArray();
}
if (! is_array($array)) {
throw new \InvalidArgumentException('Input must be an array or a Collection.');
}
if ($array === []) {
return false;
}
return array_keys($array) !== range(0, count($array) - 1);
}
/**
* This method adds the default environment variables to the resource.
* - COOLIFY_APP_NAME
@@ -3581,37 +3711,39 @@ function generate_fluentd_configuration(): array
*/
function add_coolify_default_environment_variables(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse|Application|Service $resource, Collection &$where_to_add, ?Collection $where_to_check = null)
{
if ($resource instanceof Service) {
$ip = $resource->server->ip;
} else {
$ip = $resource->destination->server->ip;
}
if (isAssociativeArray($where_to_add)) {
$isAssociativeArray = true;
} else {
$isAssociativeArray = false;
}
if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_APP_NAME')->isEmpty()) {
if ($resource instanceof Application && $resource->build_pack === 'dockercompose') {
$where_to_add->put('COOLIFY_APP_NAME', $resource->name);
} elseif ($resource instanceof Service) {
if ($isAssociativeArray) {
$where_to_add->put('COOLIFY_APP_NAME', $resource->name);
} else {
$where_to_add->push("COOLIFY_APP_NAME={$resource->name}");
}
}
if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_SERVER_IP')->isEmpty()) {
if ($resource instanceof Application && $resource->build_pack === 'dockercompose') {
$where_to_add->put('COOLIFY_SERVER_IP', $resource->destination->server->ip);
} elseif ($resource instanceof Service) {
$where_to_add->put('COOLIFY_SERVER_IP', $resource->server->ip);
if ($isAssociativeArray) {
$where_to_add->put('COOLIFY_SERVER_IP', $ip);
} else {
$where_to_add->push("COOLIFY_SERVER_IP={$resource->destination->server->ip}");
$where_to_add->push("COOLIFY_SERVER_IP={$ip}");
}
}
if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_ENVIRONMENT_NAME')->isEmpty()) {
if ($resource instanceof Application && $resource->build_pack === 'dockercompose') {
$where_to_add->put('COOLIFY_ENVIRONMENT_NAME', $resource->environment->name);
} elseif ($resource instanceof Service) {
if ($isAssociativeArray) {
$where_to_add->put('COOLIFY_ENVIRONMENT_NAME', $resource->environment->name);
} else {
$where_to_add->push("COOLIFY_ENVIRONMENT_NAME={$resource->environment->name}");
}
}
if ($where_to_check != null && $where_to_check->where('key', 'COOLIFY_PROJECT_NAME')->isEmpty()) {
if ($resource instanceof Application && $resource->build_pack === 'dockercompose') {
$where_to_add->put('COOLIFY_PROJECT_NAME', $resource->project()->name);
} elseif ($resource instanceof Service) {
if ($isAssociativeArray) {
$where_to_add->put('COOLIFY_PROJECT_NAME', $resource->project()->name);
} else {
$where_to_add->push("COOLIFY_PROJECT_NAME={$resource->project()->name}");
@@ -3622,29 +3754,17 @@ function add_coolify_default_environment_variables(StandaloneRedis|StandalonePos
function convertComposeEnvironmentToArray($environment)
{
$convertedServiceVariables = collect([]);
foreach ($environment as $variableName => $variableValue) {
if (is_array($variableValue)) {
$key = str(collect($variableValue)->keys()->first());
$value = str(collect($variableValue)->values()->first());
} elseif (is_string($variableValue)) {
if (str($variableValue)->contains('=')) {
$key = str($variableValue)->before('=');
$value = str($variableValue)->after('=');
} else {
if (is_numeric($variableName)) {
$key = str($variableValue);
$value = null;
} else {
$key = str($variableName);
if ($variableValue) {
$value = str($variableValue);
} else {
$value = null;
}
}
if (isAssociativeArray($environment)) {
$convertedServiceVariables = $environment;
} else {
foreach ($environment as $value) {
$parts = explode('=', $value, 2);
$key = $parts[0];
$realValue = $parts[1] ?? '';
if ($key) {
$convertedServiceVariables->put($key, $realValue);
}
}
$convertedServiceVariables->put($key->value(), $value?->value() ?? null);
}
return $convertedServiceVariables;

View File

@@ -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,

View File

@@ -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),
];

View File

@@ -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.324',
'release' => '4.0.0-beta.332',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),

View File

@@ -1,3 +1,3 @@
<?php
return '4.0.0-beta.324';
return '4.0.0-beta.332';

View File

@@ -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');
});
}
};

View File

@@ -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();
});
}
};

View File

@@ -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();
});
}
};

View File

@@ -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();
});
}
}

View File

@@ -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

View File

@@ -13,7 +13,7 @@ paths:
- Applications
summary: List
description: 'List all applications.'
operationId: 02978e79fc0b54d573b2359f2a1f7d86
operationId: list-applications
responses:
'200':
description: 'Get all applications.'
@@ -36,7 +36,7 @@ paths:
- Applications
summary: 'Create (Public)'
description: 'Create new application based on a public git repository.'
operationId: cb56324ad19693469b4461d3f6065a5b
operationId: create-public-application
requestBody:
description: 'Application object that needs to be created.'
required: true
@@ -253,7 +253,7 @@ paths:
- Applications
summary: 'Create (Private - GH App)'
description: 'Create new application based on a private repository through a Github App.'
operationId: 8b7af9c9a509385963bf3e72eeeea786
operationId: create-private-github-app-application
requestBody:
description: 'Application object that needs to be created.'
required: true
@@ -474,7 +474,7 @@ paths:
- Applications
summary: 'Create (Private - Deploy Key)'
description: 'Create new application based on a private repository through a Deploy Key.'
operationId: e3eaa989ffb05366247a00cdfd551efa
operationId: create-private-deploy-key-application
requestBody:
description: 'Application object that needs to be created.'
required: true
@@ -695,7 +695,7 @@ paths:
- Applications
summary: 'Create (Dockerfile)'
description: 'Create new application based on a simple Dockerfile.'
operationId: 2b433ad6f5d259eb7f4f3b5af9913708
operationId: create-dockerfile-application
requestBody:
description: 'Application object that needs to be created.'
required: true
@@ -867,7 +867,7 @@ paths:
- Applications
summary: 'Create (Docker Image)'
description: 'Create new application based on a prebuilt docker image'
operationId: e9a2d6dd9404acf880dc3053f09477fc
operationId: create-dockerimage-application
requestBody:
description: 'Application object that needs to be created.'
required: true
@@ -1030,7 +1030,7 @@ paths:
- Applications
summary: 'Create (Docker Compose)'
description: 'Create new application based on a docker-compose file.'
operationId: 3731add8226c2d664455978cac46c242
operationId: create-dockercompose-application
requestBody:
description: 'Application object that needs to be created.'
required: true
@@ -1084,7 +1084,7 @@ paths:
- Applications
summary: Get
description: 'Get application by UUID.'
operationId: 3630b62c28e7358e7f0087c1d8fe1845
operationId: get-application-by-uuid
parameters:
-
name: uuid
@@ -1115,7 +1115,7 @@ paths:
- Applications
summary: Delete
description: 'Delete application by UUID.'
operationId: 1e110b190a1045d34f3e1c61608a8702
operationId: delete-application-by-uuid
parameters:
-
name: uuid
@@ -1156,7 +1156,7 @@ paths:
- Applications
summary: Update
description: 'Update application by UUID.'
operationId: 62a3b1775e8cba5d39a236ebb69830b7
operationId: update-application-by-uuid
requestBody:
description: 'Application updated.'
required: true
@@ -1376,7 +1376,7 @@ paths:
- Applications
summary: 'List Envs'
description: 'List all envs by application UUID.'
operationId: 7c8e0c286870e23294a075cc0584df2f
operationId: list-envs-by-application-uuid
parameters:
-
name: uuid
@@ -1409,7 +1409,7 @@ paths:
- Applications
summary: 'Create Env'
description: 'Create env by application UUID.'
operationId: 4699ffbb7d6e58581fd0b0a14f36ffc2
operationId: create-env-by-application-uuid
parameters:
-
name: uuid
@@ -1471,7 +1471,7 @@ paths:
- Applications
summary: 'Update Env'
description: 'Update env by application UUID.'
operationId: 3d70a2d569f395be220b3f09ad36674b
operationId: update-env-by-application-uuid
parameters:
-
name: uuid
@@ -1537,7 +1537,7 @@ paths:
- Applications
summary: 'Update Envs (Bulk)'
description: 'Update multiple envs by application UUID.'
operationId: ae96f0f585ed158b2abd2d9ba40f3cf9
operationId: update-envs-by-application-uuid
parameters:
-
name: uuid
@@ -1584,7 +1584,7 @@ paths:
- Applications
summary: 'Delete Env'
description: 'Delete env by UUID.'
operationId: 96097c5cfc7dc0e7a3de229645f630c7
operationId: delete-env-by-application-uuid
parameters:
-
name: uuid
@@ -1626,7 +1626,7 @@ paths:
- Applications
summary: Start
description: 'Start application. `Post` request is also accepted.'
operationId: dc87c2061ab303757a0e061f87900c4c
operationId: start-application-by-uuid
parameters:
-
name: uuid
@@ -1675,7 +1675,7 @@ paths:
- Applications
summary: Stop
description: 'Stop application. `Post` request is also accepted.'
operationId: 133ef3c7bd5043901f24bb5002a536eb
operationId: stop-application-by-uuid
parameters:
-
name: uuid
@@ -1709,7 +1709,7 @@ paths:
- Applications
summary: Restart
description: 'Restart application. `Post` request is also accepted.'
operationId: b231ae7baab9ef47f0627be820e735bc
operationId: restart-application-by-uuid
parameters:
-
name: uuid
@@ -1744,7 +1744,7 @@ paths:
- Databases
summary: List
description: 'List all databases.'
operationId: ecd0ee1e46e4c854c18e6c9daa3d37f3
operationId: list-databases
responses:
'200':
description: 'Get all databases'
@@ -1766,7 +1766,7 @@ paths:
- Databases
summary: Get
description: 'Get database by UUID.'
operationId: b49cb2d3e8f34c4e80cdffd8a201031d
operationId: get-database-by-uuid
parameters:
-
name: uuid
@@ -1798,7 +1798,7 @@ paths:
- Databases
summary: Delete
description: 'Delete database by UUID.'
operationId: 20610931b2bae8aba34eee68624ab673
operationId: delete-database-by-uuid
parameters:
-
name: uuid
@@ -1839,7 +1839,7 @@ paths:
- Databases
summary: Update
description: 'Update database by UUID.'
operationId: 5ba459ed390a721711a1708760e9de3b
operationId: update-database-by-uuid
parameters:
-
name: uuid
@@ -1989,7 +1989,7 @@ paths:
- Databases
summary: 'Create (PostgreSQL)'
description: 'Create a new PostgreSQL database.'
operationId: 8f7f491ddc46a9fa065b4424512231cd
operationId: create-database-postgresql
requestBody:
description: 'Database data'
required: true
@@ -2087,7 +2087,7 @@ paths:
- Databases
summary: 'Create (Clickhouse)'
description: 'Create a new Clickhouse database.'
operationId: a1189fa7f956f238f0e95c9150ff57f6
operationId: create-database-clickhouse
requestBody:
description: 'Database data'
required: true
@@ -2173,7 +2173,7 @@ paths:
- Databases
summary: 'Create (DragonFly)'
description: 'Create a new DragonFly database.'
operationId: e73f7de1c8eee4219e5ec98c4b9b7efe
operationId: create-database-dragonfly
requestBody:
description: 'Database data'
required: true
@@ -2256,7 +2256,7 @@ paths:
- Databases
summary: 'Create (Redis)'
description: 'Create a new Redis database.'
operationId: 4d352d13544ee2953fd48ad7b0651098
operationId: create-database-redis
requestBody:
description: 'Database data'
required: true
@@ -2342,7 +2342,7 @@ paths:
- Databases
summary: 'Create (KeyDB)'
description: 'Create a new KeyDB database.'
operationId: b908f3929c371c217d489638e0a21ff6
operationId: create-database-keydb
requestBody:
description: 'Database data'
required: true
@@ -2428,7 +2428,7 @@ paths:
- Databases
summary: 'Create (MariaDB)'
description: 'Create a new MariaDB database.'
operationId: 6bea521ddcd738dcbb5f3783a7308acf
operationId: create-database-mariadb
requestBody:
description: 'Database data'
required: true
@@ -2523,7 +2523,7 @@ paths:
- Databases
summary: 'Create (MySQL)'
description: 'Create a new MySQL database.'
operationId: 0a1158cf759c4493cbb1e30024c60623
operationId: create-database-mysql
requestBody:
description: 'Database data'
required: true
@@ -2615,7 +2615,7 @@ paths:
- Databases
summary: 'Create (MongoDB)'
description: 'Create a new MongoDB database.'
operationId: fdba3de84d02519bb37599fea34b115d
operationId: create-database-mongodb
requestBody:
description: 'Database data'
required: true
@@ -2701,7 +2701,7 @@ paths:
- Databases
summary: Start
description: 'Start database. `Post` request is also accepted.'
operationId: 4c6eb21e734d411e2b3388578761123d
operationId: start-database-by-uuid
parameters:
-
name: uuid
@@ -2735,7 +2735,7 @@ paths:
- Databases
summary: Stop
description: 'Stop database. `Post` request is also accepted.'
operationId: cb6d983c2679aff841c7501ce612a372
operationId: stop-database-by-uuid
parameters:
-
name: uuid
@@ -2769,7 +2769,7 @@ paths:
- Databases
summary: Restart
description: 'Restart database. `Post` request is also accepted.'
operationId: 04c7a5e4752b4a00036addb433f3f218
operationId: restart-database-by-uuid
parameters:
-
name: uuid
@@ -2803,7 +2803,7 @@ paths:
- Deployments
summary: List
description: 'List currently running deployments'
operationId: a2c05736269191ad0d99cadfd4708986
operationId: list-deployments
responses:
'200':
description: 'Get all currently running deployments.'
@@ -2826,12 +2826,12 @@ paths:
- Deployments
summary: Get
description: 'Get deployment by UUID.'
operationId: ccf9856174c115a1430d952ccbd36aea
operationId: get-deployment-by-uuid
parameters:
-
name: uuid
in: path
description: 'Deployment Uuid'
description: 'Deployment UUID'
required: true
schema:
type: string
@@ -2857,7 +2857,7 @@ paths:
- Deployments
summary: Deploy
description: 'Deploy by tag or uuid. `Post` request also accepted.'
operationId: 700eb6e51f4c9e86d722f600c65ed1d4
operationId: deploy-by-tag-or-uuid
parameters:
-
name: tag
@@ -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:
@@ -2897,7 +2897,7 @@ paths:
get:
summary: Version
description: 'Get Coolify version.'
operationId: 187b37139844731110757711ee71c215
operationId: version
responses:
'200':
description: 'Returns the version of the application'
@@ -2917,7 +2917,7 @@ paths:
get:
summary: 'Enable API'
description: 'Enable API (only with root permissions).'
operationId: 595019bae03d08277def667609779ff3
operationId: enable-api
responses:
'200':
description: 'Enable API.'
@@ -2946,7 +2946,7 @@ paths:
get:
summary: 'Disable API'
description: 'Disable API (only with root permissions).'
operationId: 50e2486a2d196a996b24a284a283bcdb
operationId: disable-api
responses:
'200':
description: 'Disable API.'
@@ -2975,7 +2975,7 @@ paths:
get:
summary: Healthcheck
description: 'Healthcheck endpoint.'
operationId: 64db893135e686704bb88c3c238022c1
operationId: healthcheck
responses:
'200':
description: 'Healthcheck endpoint.'
@@ -2993,8 +2993,8 @@ paths:
tags:
- Projects
summary: List
description: 'list projects.'
operationId: 762788f00f2dabb981df9adbc948d3f6
description: 'List projects.'
operationId: list-projects
responses:
'200':
description: 'Get all projects.'
@@ -3016,7 +3016,7 @@ paths:
- Projects
summary: Create
description: 'Create Project.'
operationId: cf067eb7cf18216cda3239329a2eeadb
operationId: create-project
requestBody:
description: 'Project created.'
required: true
@@ -3024,7 +3024,7 @@ paths:
application/json:
schema:
properties:
uuid:
name:
type: string
description: 'The name of the project.'
description:
@@ -3054,8 +3054,8 @@ paths:
tags:
- Projects
summary: Get
description: 'Get project by Uuid.'
operationId: 63bf8b6a68fbb757f09ab519331f6298
description: 'Get project by UUID.'
operationId: get-project-by-uuid
parameters:
-
name: uuid
@@ -3085,7 +3085,7 @@ paths:
- Projects
summary: Delete
description: 'Delete project by UUID.'
operationId: f668a936f505b4401948c74b6a663029
operationId: delete-project-by-uuid
parameters:
-
name: uuid
@@ -3118,7 +3118,7 @@ paths:
- Projects
summary: Update
description: 'Update Project.'
operationId: 2db343bd6fc14c658cb51a2b73b2f842
operationId: update-project-by-uuid
requestBody:
description: 'Project updated.'
required: true
@@ -3159,7 +3159,7 @@ paths:
- Projects
summary: Environment
description: 'Get environment by name.'
operationId: 7e44845dce5aa47ed7b0daf5595ad2e1
operationId: get-environment-by-name
parameters:
-
name: uuid
@@ -3197,7 +3197,7 @@ paths:
- Resources
summary: List
description: 'Get all resources.'
operationId: c399903694eb1314596832e49f7c66d7
operationId: list-resources
responses:
'200':
description: 'Get all resources'
@@ -3219,7 +3219,7 @@ paths:
- 'Private Keys'
summary: List
description: 'List all private keys.'
operationId: 8a5d8d3ccbbcef54ed0e913a27faea9d
operationId: list-private-keys
responses:
'200':
description: 'Get all private keys.'
@@ -3241,7 +3241,7 @@ paths:
- 'Private Keys'
summary: Create
description: 'Create a new private key.'
operationId: eb4780acaa990c594cdbe8ffa80b4fb0
operationId: create-private-key
requestBody:
required: true
content:
@@ -3279,7 +3279,7 @@ paths:
- 'Private Keys'
summary: Update
description: 'Update a private key.'
operationId: 371fd26b8949a070c26a264231fe233f
operationId: update-private-key
requestBody:
required: true
content:
@@ -3318,12 +3318,12 @@ paths:
- 'Private Keys'
summary: Get
description: 'Get key by UUID.'
operationId: 2f743a85eb65d5ddb8cd5b362bb3d26a
operationId: get-private-key-by-uuid
parameters:
-
name: uuid
in: path
description: 'Private Key Uuid'
description: 'Private Key UUID'
required: true
schema:
type: string
@@ -3350,12 +3350,12 @@ paths:
- 'Private Keys'
summary: Delete
description: 'Delete a private key.'
operationId: 8faa0bb399142f0084dfc3e003c42cf6
operationId: delete-private-key-by-uuid
parameters:
-
name: uuid
in: path
description: 'Private Key Uuid'
description: 'Private Key UUID'
required: true
schema:
type: string
@@ -3383,7 +3383,7 @@ paths:
- Servers
summary: List
description: 'List all servers.'
operationId: 787448df856cefd2d9a313566be30d34
operationId: list-servers
responses:
'200':
description: 'Get all servers.'
@@ -3405,7 +3405,7 @@ paths:
- Servers
summary: Create
description: 'Create Server.'
operationId: fa44b42490379e428ba5b8747716a8d9
operationId: create-server
requestBody:
description: 'Server created.'
required: true
@@ -3470,12 +3470,12 @@ paths:
- Servers
summary: Get
description: 'Get server by UUID.'
operationId: 5baf04bddb8302c7e07f5b4c41aad10c
operationId: get-server-by-uuid
parameters:
-
name: uuid
in: path
description: "Server's Uuid"
description: "Server's UUID"
required: true
schema:
type: string
@@ -3500,7 +3500,7 @@ paths:
- Servers
summary: Delete
description: 'Delete server by UUID.'
operationId: 0231fe0134f0306b21f006ce51b0a3dc
operationId: delete-server-by-uuid
parameters:
-
name: uuid
@@ -3533,7 +3533,7 @@ paths:
- Servers
summary: Update
description: 'Update Server.'
operationId: 41bbdaf79eb1938592494fc5494442a0
operationId: update-server-by-uuid
requestBody:
description: 'Server updated.'
required: true
@@ -3590,12 +3590,12 @@ paths:
- Servers
summary: Resources
description: 'Get resources by server.'
operationId: cef26c059941b44fbd8de3a7a58c10a5
operationId: get-resources-by-server-uuid
parameters:
-
name: uuid
in: path
description: "Server's Uuid"
description: "Server's UUID"
required: true
schema:
type: string
@@ -3622,12 +3622,12 @@ paths:
- Servers
summary: Domains
description: 'Get domains by server.'
operationId: 1ee227755be848d572f412272f53dd93
operationId: get-domains-by-server-uuid
parameters:
-
name: uuid
in: path
description: "Server's Uuid"
description: "Server's UUID"
required: true
schema:
type: string
@@ -3654,7 +3654,7 @@ paths:
- Servers
summary: Validate
description: 'Validate server by UUID.'
operationId: a543a12ef2cbc7a3dd22c3dbe6cbee89
operationId: validate-server-by-uuid
parameters:
-
name: uuid
@@ -3687,7 +3687,7 @@ paths:
- Services
summary: List
description: 'List all services.'
operationId: 5d014ac25d33391b8f4c2316060ba452
operationId: list-services
responses:
'200':
description: 'Get all services'
@@ -3709,7 +3709,7 @@ paths:
- Services
summary: Create
description: 'Create a one-click service'
operationId: 3d6cbfb54d919b53ba3984a113e837d7
operationId: create-service
requestBody:
required: true
content:
@@ -3773,7 +3773,7 @@ paths:
- Services
summary: Get
description: 'Get service by UUID.'
operationId: 895d39ee2cb3994285de57256c2d428d
operationId: get-service-by-uuid
parameters:
-
name: uuid
@@ -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:
@@ -3803,7 +3803,7 @@ paths:
- Services
summary: Delete
description: 'Delete service by UUID.'
operationId: 6e1a61e4fddaa9d95bb9fc66dfaf0442
operationId: delete-service-by-uuid
parameters:
-
name: uuid
@@ -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,13 +3830,263 @@ 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:
- Services
summary: Start
description: 'Start service. `Post` request is also accepted.'
operationId: d2ddd9c028d123fbdec830dc4b25b4cb
operationId: start-service-by-uuid
parameters:
-
name: uuid
@@ -3870,7 +4120,7 @@ paths:
- Services
summary: Stop
description: 'Stop service. `Post` request is also accepted.'
operationId: 87399d34758ce16830740c68626614db
operationId: stop-service-by-uuid
parameters:
-
name: uuid
@@ -3904,7 +4154,7 @@ paths:
- Services
summary: Restart
description: 'Restart service. `Post` request is also accepted.'
operationId: 836645faa615b75052759dae78639469
operationId: restart-service-by-uuid
parameters:
-
name: uuid
@@ -3938,7 +4188,7 @@ paths:
- Teams
summary: List
description: 'Get all teams.'
operationId: f9c530b5b25df9601cb87d6a58646f0a
operationId: list-teams
responses:
'200':
description: 'List of teams.'
@@ -3961,7 +4211,7 @@ paths:
- Teams
summary: Get
description: 'Get team by TeamId.'
operationId: ac57ff546c002032cef44602c46a4e76
operationId: get-team-by-id
parameters:
-
name: id
@@ -3992,7 +4242,7 @@ paths:
- Teams
summary: Members
description: 'Get members by TeamId.'
operationId: 7858f5a45d9ea55184c182852a7f0f6c
operationId: get-members-by-team-id
parameters:
-
name: id
@@ -4025,7 +4275,7 @@ paths:
- Teams
summary: 'Authenticated Team'
description: 'Get currently authenticated team.'
operationId: 6a4ec9fed1aad7b0b38356c47d7ac509
operationId: get-current-team
responses:
'200':
description: 'Current Team.'
@@ -4046,7 +4296,7 @@ paths:
- Teams
summary: 'Authenticated Team Members'
description: 'Get currently authenticated team members.'
operationId: 97e636a5796dbe71afb0bbcf1eec6e41
operationId: get-current-team-members
responses:
'200':
description: 'Currently authenticated team members.'
@@ -4480,6 +4730,8 @@ components:
type: string
name:
type: string
description:
type: string
environments:
description: 'The environments of the project.'
type: array

BIN
other/logos/glueops.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
other/logos/juxtdigital.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

View File

@@ -0,0 +1,20 @@
<svg xmlns="http://www.w3.org/2000/svg" width="236.333" height="33.468" viewBox="0 0 236.333 33.468">
<defs>
<style>
.cls-1{fill:#ffb300}.cls-2{fill:#fff}
</style>
</defs>
<g id="Group_448" transform="translate(-58.267 -97.906)">
<path id="Path_1278" d="M65.043 128.721h-6.776v-21.977h5.265l.779 2.746a11.819 11.819 0 0 1 3.205-2.38 8.572 8.572 0 0 1 3.891-.871q4.716 0 6.455 3.343a12.009 12.009 0 0 1 3.32-2.427 8.83 8.83 0 0 1 3.96-.916 6.683 6.683 0 0 1 7.371 7.463v15.018h-6.776v-14.331a3.188 3.188 0 0 0-.732-2.2 2.507 2.507 0 0 0-1.969-.824 5.464 5.464 0 0 0-2.29.55 5.036 5.036 0 0 0-1.969 1.6v15.2H72v-14.326a3.188 3.188 0 0 0-.732-2.2 2.507 2.507 0 0 0-1.969-.824 4.829 4.829 0 0 0-2.29.642 5.886 5.886 0 0 0-1.969 1.693z" class="cls-1" transform="translate(0 2.15)"/>
<path id="Path_1279" d="M88.567 108.667A18 18 0 0 1 92.8 106.9a17.737 17.737 0 0 1 4.831-.664 10.206 10.206 0 0 1 6.547 1.969q2.472 1.97 2.472 6.272v14.24h-5.173l-.6-2.173h-.177a6.671 6.671 0 0 1-2.541 1.927 9.076 9.076 0 0 1-3.823.749 8.916 8.916 0 0 1-3.273-.55 6.682 6.682 0 0 1-2.312-1.464 6.122 6.122 0 0 1-1.4-2.175 7.464 7.464 0 0 1-.481-2.678 6.149 6.149 0 0 1 .848-3.3 6.713 6.713 0 0 1 2.288-2.243 10.924 10.924 0 0 1 3.388-1.282 20 20 0 0 1 4.144-.411h2.29v-1.191a2.248 2.248 0 0 0-.871-1.9 4.011 4.011 0 0 0-2.472-.664 9.033 9.033 0 0 0-2.7.413 14.957 14.957 0 0 0-2.931 1.327zm11.308 10.576-1.511.045a9.971 9.971 0 0 0-2.151.278 4.732 4.732 0 0 0-1.4.577 2.043 2.043 0 0 0-.756.832 2.29 2.29 0 0 0-.229.993 2.134 2.134 0 0 0 .847 1.964 3.593 3.593 0 0 0 1.946.531 3.312 3.312 0 0 0 1.991-.647 3.768 3.768 0 0 0 1.259-1.433z" class="cls-1" transform="translate(7.381 2.15)"/>
<path id="Path_1280" d="M118.836 112.375a13.63 13.63 0 0 0-2.609-.938 10.94 10.94 0 0 0-2.656-.343 3.914 3.914 0 0 0-1.924.411 1.269 1.269 0 0 0-.732 1.145 1.575 1.575 0 0 0 .71 1.306 9.708 9.708 0 0 0 2.815 1.121l1.374.413a8.88 8.88 0 0 1 4.167 2.4 5.828 5.828 0 0 1 1.419 4.051 6.515 6.515 0 0 1-.687 3 6.722 6.722 0 0 1-1.945 2.312 9.031 9.031 0 0 1-3.022 1.466 14.282 14.282 0 0 1-3.915.5 18.715 18.715 0 0 1-4.144-.413 14.845 14.845 0 0 1-3.365-1.19l1.466-4.9a16.229 16.229 0 0 0 2.77 1.122 10.186 10.186 0 0 0 2.953.434 4.407 4.407 0 0 0 2.449-.5 1.446 1.446 0 0 0 .71-1.19 1.474 1.474 0 0 0-.16-.71 1.69 1.69 0 0 0-.572-.572 5.015 5.015 0 0 0-1.167-.527q-.755-.251-1.946-.618l-1.419-.413a8.078 8.078 0 0 1-3.938-2.4 6.69 6.69 0 0 1 1.077-9.112 8.134 8.134 0 0 1 2.746-1.464 12.1 12.1 0 0 1 3.731-.527 18.629 18.629 0 0 1 3.915.39 15.257 15.257 0 0 1 3.273 1.076z" class="cls-1" transform="translate(11.86 2.15)"/>
<path id="Path_1281" d="M133.176 112.375a13.641 13.641 0 0 0-2.61-.938 10.94 10.94 0 0 0-2.656-.343 3.908 3.908 0 0 0-1.922.411 1.266 1.266 0 0 0-.732 1.145 1.572 1.572 0 0 0 .71 1.306 9.708 9.708 0 0 0 2.815 1.121l1.374.413a8.882 8.882 0 0 1 4.165 2.4 5.829 5.829 0 0 1 1.42 4.051 6.515 6.515 0 0 1-.687 3 6.725 6.725 0 0 1-1.946 2.312 9.007 9.007 0 0 1-3.022 1.466 14.269 14.269 0 0 1-3.915.5 18.7 18.7 0 0 1-4.143-.413 14.8 14.8 0 0 1-3.365-1.19l1.466-4.9a16.216 16.216 0 0 0 2.769 1.122 10.2 10.2 0 0 0 2.954.434 4.41 4.41 0 0 0 2.449-.5 1.446 1.446 0 0 0 .71-1.19 1.474 1.474 0 0 0-.161-.71 1.685 1.685 0 0 0-.571-.572 5.04 5.04 0 0 0-1.167-.527q-.757-.251-1.946-.618l-1.419-.413a8.078 8.078 0 0 1-3.938-2.4 6.689 6.689 0 0 1 1.076-9.112 8.128 8.128 0 0 1 2.748-1.464 12.1 12.1 0 0 1 3.731-.527 18.617 18.617 0 0 1 3.914.39 15.211 15.211 0 0 1 3.273 1.076z" class="cls-1" transform="translate(15.56 2.15)"/>
<path id="Path_1282" d="M137.571 104.591a3.448 3.448 0 0 1-2.656-.985 3.339 3.339 0 0 1-.915-2.358 3.293 3.293 0 0 1 .938-2.358 3.46 3.46 0 0 1 2.632-.985 3.51 3.51 0 0 1 2.633.962 3.274 3.274 0 0 1 .938 2.38 3.318 3.318 0 0 1-.916 2.38 3.5 3.5 0 0 1-2.654.964zm-3.388 26.28v-21.976h6.776v21.976z" class="cls-1" transform="translate(19.541)"/>
<path id="Path_1283" d="M156.439 106.641h7.188l-7.693 21.976h-8.058l-7.325-21.976h7.234l2.656 9.614 1.511 7.646h.184l1.511-7.646z" class="cls-1" transform="translate(21.231 2.254)"/>
<path id="Path_1284" d="M179.227 119.7h-14.24v.184a3.591 3.591 0 0 0 1.786 3.341 8.7 8.7 0 0 0 4.486 1.053 13.226 13.226 0 0 0 3.3-.366 11.2 11.2 0 0 0 2.38-.869l1.237 4.67a15.866 15.866 0 0 1-3.136 1.053 20.217 20.217 0 0 1-4.647.458 16.3 16.3 0 0 1-4.694-.664 11.015 11.015 0 0 1-3.891-2.037 9.781 9.781 0 0 1-2.656-3.48 11.806 11.806 0 0 1-.984-5.036 13.713 13.713 0 0 1 .8-4.786 10.828 10.828 0 0 1 2.271-3.731 10.069 10.069 0 0 1 3.511-2.4 11.674 11.674 0 0 1 4.519-.848 9.719 9.719 0 0 1 7.25 2.748q2.706 2.747 2.707 7.829zm-6.959-4.624a6.22 6.22 0 0 0-.184-1.511 4.068 4.068 0 0 0-.572-1.3 2.911 2.911 0 0 0-1.006-.916 3.026 3.026 0 0 0-1.488-.343 3.488 3.488 0 0 0-2.656 1.122 5 5 0 0 0-1.237 3.044z" class="cls-1" transform="translate(25.776 2.15)"/>
<path id="Path_1285" d="M191.155 100.781a23.589 23.589 0 0 1 4.876.454 17.467 17.467 0 0 1 3.777 1.224l-1.419 4.549a13 13 0 0 0-3.273-1.122 16.923 16.923 0 0 0-3.32-.343 9.792 9.792 0 0 0-3.433.6 7.5 7.5 0 0 0-2.817 1.854 8.763 8.763 0 0 0-1.9 3.183 13.637 13.637 0 0 0-.687 4.578q0 4.853 2.129 7.44a7.465 7.465 0 0 0 6.113 2.587 14.871 14.871 0 0 0 1.74-.092 4.269 4.269 0 0 0 1.19-.274v-6.272H189.6v-5.128h11.218v14.833a21.548 21.548 0 0 1-4.212 1.283 27.009 27.009 0 0 1-5.448.5 18.853 18.853 0 0 1-6.113-.96 14.022 14.022 0 0 1-4.921-2.857 13.2 13.2 0 0 1-3.3-4.663 16 16 0 0 1-1.19-6.377 16.34 16.34 0 0 1 1.19-6.422 13.1 13.1 0 0 1 3.3-4.709 14.287 14.287 0 0 1 4.921-2.88 18.423 18.423 0 0 1 6.11-.986z" class="cls-2" transform="translate(30.283 .742)"/>
<path id="Path_1286" d="M197.979 101.182h11.447a12.451 12.451 0 0 1 4.372.71 8.855 8.855 0 0 1 3.159 1.945 8.15 8.15 0 0 1 1.9 2.885 9.664 9.664 0 0 1 .64 3.526 8.374 8.374 0 0 1-1.877 5.494 8.179 8.179 0 0 1-1.785 1.648 12.184 12.184 0 0 1-1.786 1.008l6.914 11.629h-8.012l-5.128-10.394h-2.885v10.394h-6.959zm6.959 13.185h2.106a6.91 6.91 0 0 0 3.846-.961 3.446 3.446 0 0 0 1.466-3.114 3.606 3.606 0 0 0-1.19-2.839 5.037 5.037 0 0 0-3.434-1.053h-2.793z" class="cls-2" transform="translate(36.049 .845)"/>
<path id="Path_1287" d="M224.336 101.182v28.844h-6.959v-28.844z" class="cls-2" transform="translate(41.054 .845)"/>
<path id="Path_1288" d="M236.195 101.182a20.883 20.883 0 0 1 6.226.869 13.074 13.074 0 0 1 4.784 2.61 11.526 11.526 0 0 1 3.068 4.326 15.616 15.616 0 0 1 1.076 6.02 15.974 15.974 0 0 1-1.282 6.662 13.019 13.019 0 0 1-3.5 4.67 14.816 14.816 0 0 1-5.2 2.77 21.383 21.383 0 0 1-6.318.916h-9.157v-28.843zm-3.343 23.533h1.785a13.7 13.7 0 0 0 3.549-.458 7.351 7.351 0 0 0 3-1.58 7.944 7.944 0 0 0 2.061-3 12.252 12.252 0 0 0 .779-4.671 8.247 8.247 0 0 0-2.335-6.34 8.908 8.908 0 0 0-6.319-2.175h-2.517z" class="cls-2" transform="translate(43.251 .845)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
other/logos/saasykit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
other/logos/saasykit.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

1
other/logos/ubicloud.svg Normal file
View File

@@ -0,0 +1 @@
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1229 354" width="1229" height="354"><style>.a{fill:#fff}.b{fill:#ff5c12}</style><path class="a" d="m512.2 195.3c0 9.4-2.7 17.2-8.2 23.3-5.4 6.2-12.4 9.3-20.9 9.3-7.5 0-13.8-2.6-18.9-7.7-5.1-5.1-7.7-12.1-7.7-20.8v-55.1h-18.8v60.5c0 12.3 4.1 22.1 12.4 29.4 8.2 7.4 18.1 11.1 29.4 11.1 14 0 24.9-5.6 32.6-16.9v15.2h18.8v-99.3h-18.8z"/><path fill-rule="evenodd" class="a" d="m641 157.3c9.4 10 14.2 22.4 14.2 36.5 0 14.1-4.7 26.2-14.2 36.2-9.5 10-20.8 15-35.4 15-14.6 0-26.1-5.6-34.3-17v15.6h-18.8v-131.2h18.8v47.8c8-11.5 19.4-17.4 34.3-17.6h0.6c13.7 0 25.4 4.9 34.8 14.7zm-3.3 36.7c0-9.4-3.3-17.5-9.9-24.2-6.6-6.7-14.4-10.1-23.8-10.1-9.4 0-17.3 3.4-23.9 10.1-6.5 6.8-9.8 14.9-9.8 24.2q0 13.9 9.9 24c6.6 6.7 14.4 10.1 23.8 10.1 9.4 0 17.3-3.3 23.9-10 6.5-6.7 9.8-14.8 9.8-24.1z"/><path fill-rule="evenodd" class="a" d="m669 118.8c0 3.5 1.2 6.4 3.7 8.6 2.4 2.3 5.5 3.4 9.1 3.4 3.6 0 6.5-1.2 8.9-3.5 2.5-2.3 3.7-5.1 3.7-8.5 0-3.4-1.2-6.4-3.7-8.8-2.4-2.4-5.4-3.6-8.9-3.6q-5.4 0-9 3.6c-2.5 2.3-3.8 5.3-3.8 8.8zm3.2 124.9h18.8v-99.4h-18.8z"/><path class="a" d="m758.5 159.6c6.5 0 12.3 1.8 17.4 5.3 5.1 3.6 9.1 8.3 11.8 14.2l17.4-4.5c-3.9-9.5-10-17.2-18.4-23.2-8.4-5.9-17.8-8.9-28.3-8.9q-21.2 0-36 15c-10 10-15 22.1-15 36.4 0 14.2 4.9 26 14.7 36.1 9.8 10.1 21.9 15.1 36.3 15.1 10.6 0 20.1-2.9 28.4-8.8 8.3-5.9 14.4-13.6 18.3-23.3l-17.4-4.5c-2.6 5.9-6.5 10.6-11.7 14.2-5.2 3.6-11 5.3-17.5 5.3-9.2 0-17.1-3.3-23.6-10-6.5-6.7-9.8-14.7-9.8-24.1 0-9.4 3.2-17.4 9.7-24.2 6.4-6.6 14.3-10 23.7-10.1z"/><path class="a" d="m839.9 112.4h-18.8v131.2h18.8z"/><path fill-rule="evenodd" class="a" d="m943.8 157.7c9.9 10.1 14.9 22 14.9 36.1 0 14.1-4.9 26.2-14.8 36.2-10 10.1-22.1 15.2-36.2 15.2-14.1 0-26.2-5-36.1-15.1-9.9-10.1-14.9-22.2-14.9-36.3 0-14.1 5-26.2 14.9-36.2 10-10 22-15 36.1-15 14.1 0 26.2 5.1 36.1 15.1zm-2.7 36.1c0-9.4-3.3-17.4-9.7-24q-9.6-9.9-23.7-9.9-14.1 0-23.7 9.9c-6.5 6.6-9.7 14.5-9.7 24 0 9.5 3.3 17.6 9.8 24.2 6.5 6.6 14.3 9.9 23.6 9.9 9.2 0 17.1-3.3 23.6-10 6.6-6.7 9.8-14.8 9.8-24.1z"/><path class="a" d="m1048.3 195.3c0 9.4-2.7 17.2-8.2 23.3-5.4 6.2-12.4 9.3-20.9 9.3-7.5 0-13.8-2.6-18.9-7.7-5.1-5.1-7.7-12.1-7.7-20.8v-55.1h-18.8v60.5c0 12.3 4.1 22.1 12.4 29.4 8.2 7.4 18.1 11.1 29.4 11.1 14 0 24.9-5.6 32.6-16.9v15.2h18.8v-99.3h-18.8z"/><path fill-rule="evenodd" class="a" d="m1187 112.4v131.3h-18.8v-15.6c-8.2 11.3-19.7 17-34.3 17-13.8 0-25.5-5-35.2-15.1-9.7-10.1-14.5-21.8-14.5-36.1 0-14.3 4.8-26.5 14.6-36.5 9.7-9.9 21.4-14.8 35.1-14.8 14.6 0 26.1 5.8 34.3 17.4v-47.6zm-17.8 81.5c0-9.4-3.2-17.4-9.8-24.2-6.6-6.7-14.5-10.1-23.9-10.1-9.4 0-17.3 3.4-23.9 10.1-6.5 6.8-9.8 14.7-9.8 24.2 0 9.5 3.3 17.6 9.8 24.2 6.5 6.6 14.8 9.9 24 9.9 9.2 0 17.2-3.4 23.8-10.1 6.7-6.7 10-14.6 9.8-24z"/><path fill-rule="evenodd" class="b" d="m41.4 183.5v18.1l69.4 34.2v-18.3l-47.4-23c-1.6-0.9-3.4-1.6-5.1-2.2 1.6-0.6 3.3-1.3 5-2.1l47.4-23v-17.8z"/><path fill-rule="evenodd" class="b" d="m391.4 183.5v18.1l-69.4 34.3v-18.3l47.4-23c1.6-0.9 3.4-1.6 5.1-2.2-1.6-0.6-3.3-1.3-5-2.1l-47.4-23v-17.9z"/><path fill-rule="evenodd" class="b" d="m263.1 248h-89.6c-31 0-57-24.5-58.1-54.8-0.6-15.6 5.1-30.4 15.9-41.6 10.6-10.9 24.7-17.1 39.8-17.4 8-17.8 25.6-29.2 45.1-29.2 22.8 0 42.2 15.2 47.8 36.6h0.1c14.6 0 28.2 5.8 38.3 16.3 10.1 10.4 15.4 24.2 14.9 38.8-1 28.3-25.3 51.2-54.2 51.2zm-77.6-106.5c-2.3 5.4-7.5 8.9-13.4 8.9-11.2 0-21.5 4.4-29.2 12.4-7.7 8-11.7 18.5-11.3 29.6 0.7 21.5 19.4 39 41.6 39h89.7c20.2 0 37.1-15.9 37.8-35.4 0.3-10.1-3.3-19.7-10.3-26.9-6.9-7.2-16.3-11.2-26.4-11.2-0.9 0-1.9 0.1-2.9 0.2-0.9 0-1.8 0.1-2.8 0.3l-1.8 0.3c-16.7 3.5-29.2 18.3-29.2 36v1.5h-16.4v-1.5c0-23.5 15.4-43.5 36.6-50.5-4.2-13.5-16.7-22.9-31.4-22.9-13.3 0-25.3 8-30.6 20.2z"/></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -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..."

View File

@@ -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

View File

@@ -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"
}
}
}
}

View 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
View 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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -4,7 +4,7 @@
<form class="flex flex-col gap-2" wire:submit='loadBranch'>
<div class="flex flex-col gap-2">
<div class="flex flex-col gap-2">
<div class="flex items-end gap-2">
<div class="flex gap-2 items-end">
<x-forms.input required id="repository_url" label="Repository URL (https://)"
helper="{!! __('repository.url') !!}" />
<x-forms.button type="submit">
@@ -47,7 +47,7 @@
@if ($build_pack === 'dockercompose')
<x-forms.input placeholder="/" wire:model.blur="base_directory" label="Base Directory"
helper="Directory to use as root. Useful for monorepos." />
<x-forms.input placeholder="/docker-compose.yaml" id="docker_compose_location"
<x-forms.input placeholder="/docker-compose.yaml" wire:model.blur="docker_compose_location"
label="Docker Compose Location"
helper="It is calculated together with the Base Directory:<br><span class='dark:text-warning'>{{ Str::start($base_directory . $docker_compose_location, '/') }}</span>" />
Compose file location in your repository:<span

View File

@@ -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>

View File

@@ -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">

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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]);

View File

@@ -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..."

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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=

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -5,7 +5,7 @@
# port: 3000
services:
rails:
chatwoot:
image: chatwoot/chatwoot:latest
depends_on:
- postgres

View 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

View File

@@ -0,0 +1,7 @@
<?php
test('isAssociativeArray', function () {
expect(isAssociativeArray([1, 2, 3]))->toBeFalse();
expect(isAssociativeArray(collect([1, 2, 3])))->toBeFalse();
expect(isAssociativeArray(collect(['a' => 1, 'b' => 2, 'c' => 3])))->toBeTrue();
});

View File

@@ -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');

View File

@@ -1,10 +1,13 @@
{
"coolify": {
"v4": {
"version": "4.0.0-beta.324"
"version": "4.0.0-beta.332"
},
"nightly": {
"version": "4.0.0-beta.324"
"version": "4.0.0-beta.333"
},
"helper": {
"version": "1.0.1"
}
}
}
}