From ae0e064cb4d48ebc453678380d455554a32f447f Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Thu, 4 Sep 2025 00:52:32 +0200 Subject: [PATCH 001/163] feat: update Evolution API slogan to better reflect its capabilities --- templates/compose/evolution-api.yaml | 2 +- templates/service-templates-latest.json | 2 +- templates/service-templates.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/compose/evolution-api.yaml b/templates/compose/evolution-api.yaml index f08a892e8..ac3fd42df 100644 --- a/templates/compose/evolution-api.yaml +++ b/templates/compose/evolution-api.yaml @@ -1,5 +1,5 @@ # documentation: https://doc.evolution-api.com/v1/pt/get-started/introduction -# slogan: Evolution API Installation with Postgres and Redis +# slogan: Multi-platform messaging (whatsapp and more) integration API # category: backend # tags: evolution-api,evo-api,evolution,whatsapp,api,postgres,redis # logo: svgs/evolution-api.svg diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 1c4ffb50b..12e84e077 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -950,7 +950,7 @@ }, "evolution-api": { "documentation": "https://doc.evolution-api.com/v1/pt/get-started/introduction?utm_source=coolify.io", - "slogan": "Evolution API Installation with Postgres and Redis", + "slogan": "Multi-platform messaging (whatsapp and more) integration API", "compose": "dmVyc2lvbjogJzMuOCcKc2VydmljZXM6CiAgYXBpOgogICAgaW1hZ2U6ICdldm9hcGljbG91ZC9ldm9sdXRpb24tYXBpOmxhdGVzdCcKICAgIHJlc3RhcnQ6IGFsd2F5cwogICAgZGVwZW5kc19vbjoKICAgICAgLSByZWRpcwogICAgICAtIHBvc3RncmVzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX1VSTF9FVk9fODA4MAogICAgICAtIFNFUlZFUl9VUkw9JFNFUlZJQ0VfVVJMX0VWTwogICAgICAtICdEQl9UWVBFPSR7REJfVFlQRTotcG9zdGdyZXNkYn0nCiAgICAgIC0gJ0RCX1BPU1RHUkVTREJfREFUQUJBU0U9JHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdEQl9QT1NUR1JFU0RCX0hPU1Q9JHtEQl9QT1NUR1JFU0RCX0hPU1Q6LXBvc3RncmVzfScKICAgICAgLSAnREJfUE9TVEdSRVNEQl9QT1JUPSR7REJfUE9TVEdSRVNEQl9QT1JUOi01NDMyfScKICAgICAgLSAnREJfUE9TVEdSRVNEQl9VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfScKICAgICAgLSAnREJfUE9TVEdSRVNEQl9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdEQVRBQkFTRV9QUk9WSURFUj0ke0RBVEFCQVNFX1BST1ZJREVSOi1wb3N0Z3Jlc3FsfScKICAgICAgLSAnREFUQUJBU0VfVVJMPXBvc3RncmVzcWw6Ly8ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU306JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfUBwb3N0Z3Jlczo1NDMyLyR7UE9TVEdSRVNfREI6LXBvc3RncmVzfScKICAgICAgLSAnREFUQUJBU0VfQ09OTkVDVElPTl9VUkk9cG9zdGdyZXNxbDovLyR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfToke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9QHBvc3RncmVzOjU0MzIvJHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdERUxfSU5TVEFOQ0U9JHtERUxfSU5TVEFOQ0U6LWZhbHNlfScKICAgICAgLSAnREFUQUJBU0VfU0FWRV9EQVRBX0lOU1RBTkNFPSR7REFUQUJBU0VfU0FWRV9EQVRBX0lOU1RBTkNFOi10cnVlfScKICAgICAgLSAnREFUQUJBU0VfU0FWRV9EQVRBX05FV19NRVNTQUdFPSR7REFUQUJBU0VfU0FWRV9EQVRBX05FV19NRVNTQUdFOi10cnVlfScKICAgICAgLSAnREFUQUJBU0VfU0FWRV9NRVNTQUdFX1VQREFURT0ke0RBVEFCQVNFX1NBVkVfTUVTU0FHRV9VUERBVEU6LXRydWV9JwogICAgICAtICdEQVRBQkFTRV9TQVZFX0RBVEFfQ09OVEFDVFM9JHtEQVRBQkFTRV9TQVZFX0RBVEFfQ09OVEFDVFM6LXRydWV9JwogICAgICAtICdEQVRBQkFTRV9TQVZFX0RBVEFfQ0hBVFM9JHtEQVRBQkFTRV9TQVZFX0RBVEFfQ0hBVFM6LXRydWV9JwogICAgICAtICdEQVRBQkFTRV9TQVZFX0RBVEFfTEFCRUxTPSR7REFUQUJBU0VfU0FWRV9EQVRBX0xBQkVMUzotdHJ1ZX0nCiAgICAgIC0gJ0RBVEFCQVNFX1NBVkVfREFUQV9ISVNUT1JJQz0ke0RBVEFCQVNFX1NBVkVfREFUQV9ISVNUT1JJQzotdHJ1ZX0nCiAgICAgIC0gJ0RBVEFCQVNFX0NPTk5FQ1RJT05fQ0xJRU5UX05BTUU9JHtEQVRBQkFTRV9DT05ORUNUSU9OX0NMSUVOVF9OQU1FOi1ldm9sdXRpb25fdjJ9JwogICAgICAtICdSQUJCSVRNUV9FTkFCTEVEPSR7UkFCQklUTVFfRU5BQkxFRDotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9VUkk9JHtSQUJCSVRNUV9VUkk6LWFtcXA6Ly9hZG1pbjphZG1pbkByYWJiaXRtcTo1NjcyL2RlZmF1bHR9JwogICAgICAtICdSQUJCSVRNUV9FWENIQU5HRV9OQU1FPSR7UkFCQklUTVFfRVhDSEFOR0VfTkFNRTotZXZvbHV0aW9uX3YyfScKICAgICAgLSAnUkFCQklUTVFfR0xPQkFMX0VOQUJMRUQ9JHtSQUJCSVRNUV9HTE9CQUxfRU5BQkxFRDotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfQVBQTElDQVRJT05fU1RBUlRVUD0ke1JBQkJJVE1RX0VWRU5UU19BUFBMSUNBVElPTl9TVEFSVFVQOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19JTlNUQU5DRV9DUkVBVEU9JHtSQUJCSVRNUV9FVkVOVFNfSU5TVEFOQ0VfQ1JFQVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19JTlNUQU5DRV9ERUxFVEU9JHtSQUJCSVRNUV9FVkVOVFNfSU5TVEFOQ0VfREVMRVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19RUkNPREVfVVBEQVRFRD0ke1JBQkJJVE1RX0VWRU5UU19RUkNPREVfVVBEQVRFRDotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfTUVTU0FHRVNfU0VUPSR7UkFCQklUTVFfRVZFTlRTX01FU1NBR0VTX1NFVDotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfTUVTU0FHRVNfVVBTRVJUPSR7UkFCQklUTVFfRVZFTlRTX01FU1NBR0VTX1VQU0VSVDotdHJ1ZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19FRElURUQ9JHtSQUJCSVRNUV9FVkVOVFNfTUVTU0FHRVNfRURJVEVEOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19VUERBVEU9JHtSQUJCSVRNUV9FVkVOVFNfTUVTU0FHRVNfVVBEQVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19ERUxFVEU9JHtSQUJCSVRNUV9FVkVOVFNfTUVTU0FHRVNfREVMRVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19TRU5EX01FU1NBR0U9JHtSQUJCSVRNUV9FVkVOVFNfU0VORF9NRVNTQUdFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DT05UQUNUU19TRVQ9JHtSQUJCSVRNUV9FVkVOVFNfQ09OVEFDVFNfU0VUOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DT05UQUNUU19VUFNFUlQ9JHtSQUJCSVRNUV9FVkVOVFNfQ09OVEFDVFNfVVBTRVJUOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DT05UQUNUU19VUERBVEU9JHtSQUJCSVRNUV9FVkVOVFNfQ09OVEFDVFNfVVBEQVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19QUkVTRU5DRV9VUERBVEU9JHtSQUJCSVRNUV9FVkVOVFNfUFJFU0VOQ0VfVVBEQVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DSEFUU19TRVQ9JHtSQUJCSVRNUV9FVkVOVFNfQ0hBVFNfU0VUOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DSEFUU19VUFNFUlQ9JHtSQUJCSVRNUV9FVkVOVFNfQ0hBVFNfVVBTRVJUOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DSEFUU19VUERBVEU9JHtSQUJCSVRNUV9FVkVOVFNfQ0hBVFNfVVBEQVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DSEFUU19ERUxFVEU9JHtSQUJCSVRNUV9FVkVOVFNfQ0hBVFNfREVMRVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19HUk9VUFNfVVBTRVJUPSR7UkFCQklUTVFfRVZFTlRTX0dST1VQU19VUFNFUlQ6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0dST1VQX1VQREFURT0ke1JBQkJJVE1RX0VWRU5UU19HUk9VUF9VUERBVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0dST1VQX1BBUlRJQ0lQQU5UU19VUERBVEU9JHtSQUJCSVRNUV9FVkVOVFNfR1JPVVBfUEFSVElDSVBBTlRTX1VQREFURTotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfQ09OTkVDVElPTl9VUERBVEU9JHtSQUJCSVRNUV9FVkVOVFNfQ09OTkVDVElPTl9VUERBVEU6LXRydWV9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfQ0FMTD0ke1JBQkJJVE1RX0VWRU5UU19DQUxMOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19UWVBFQk9UX1NUQVJUPSR7UkFCQklUTVFfRVZFTlRTX1RZUEVCT1RfU1RBUlQ6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX1RZUEVCT1RfQ0hBTkdFX1NUQVRVUz0ke1JBQkJJVE1RX0VWRU5UU19UWVBFQk9UX0NIQU5HRV9TVEFUVVM6LWZhbHNlfScKICAgICAgLSAnU1FTX0VOQUJMRUQ9JHtTUVNfRU5BQkxFRDotZmFsc2V9JwogICAgICAtICdTUVNfQUNDRVNTX0tFWV9JRD0ke1NRU19BQ0NFU1NfS0VZX0lEOi19JwogICAgICAtICdTUVNfU0VDUkVUX0FDQ0VTU19LRVk9JHtTUVNfU0VDUkVUX0FDQ0VTU19LRVk6LX0nCiAgICAgIC0gJ1NRU19BQ0NPVU5UX0lEPSR7U1FTX0FDQ09VTlRfSUQ6LX0nCiAgICAgIC0gJ1NRU19SRUdJT049JHtTUVNfUkVHSU9OOi19JwogICAgICAtICdXRUJTT0NLRVRfRU5BQkxFRD0ke1dFQlNPQ0tFVF9FTkFCTEVEOi1mYWxzZX0nCiAgICAgIC0gJ1dFQlNPQ0tFVF9HTE9CQUxfRVZFTlRTPSR7V0VCU09DS0VUX0dMT0JBTF9FVkVOVFM6LWZhbHNlfScKICAgICAgLSAnV0FfQlVTSU5FU1NfVE9LRU5fV0VCSE9PSz0ke1dBX0JVU0lORVNTX1RPS0VOX1dFQkhPT0s6LWV2b2x1dGlvbn0nCiAgICAgIC0gJ1dBX0JVU0lORVNTX1VSTD0ke1dBX0JVU0lORVNTX1VSTDotaHR0cHM6Ly9ncmFwaC5mYWNlYm9vay5jb219JwogICAgICAtICdXQV9CVVNJTkVTU19WRVJTSU9OPSR7V0FfQlVTSU5FU1NfVkVSU0lPTjotdjIwLjB9JwogICAgICAtICdXQV9CVVNJTkVTU19MQU5HVUFHRT0ke1dBX0JVU0lORVNTX0xBTkdVQUdFOi1wdF9CUn0nCiAgICAgIC0gIldFQkhPT0tfR0xPQkFMX1VSTD0ke1dFQkhPT0tfR0xPQkFMX1VSTDotJyd9IgogICAgICAtICdXRUJIT09LX0dMT0JBTF9FTkFCTEVEPSR7V0VCSE9PS19HTE9CQUxfRU5BQkxFRDotZmFsc2V9JwogICAgICAtICdXRUJIT09LX0dMT0JBTF9XRUJIT09LX0JZX0VWRU5UUz0ke1dFQkhPT0tfR0xPQkFMX1dFQkhPT0tfQllfRVZFTlRTOi1mYWxzZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0FQUExJQ0FUSU9OX1NUQVJUVVA9JHtXRUJIT09LX0VWRU5UU19BUFBMSUNBVElPTl9TVEFSVFVQOi1mYWxzZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX1FSQ09ERV9VUERBVEVEPSR7V0VCSE9PS19FVkVOVFNfUVJDT0RFX1VQREFURUQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19NRVNTQUdFU19TRVQ9JHtXRUJIT09LX0VWRU5UU19NRVNTQUdFU19TRVQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19NRVNTQUdFU19VUFNFUlQ9JHtXRUJIT09LX0VWRU5UU19NRVNTQUdFU19VUFNFUlQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19NRVNTQUdFU19FRElURUQ9JHtXRUJIT09LX0VWRU5UU19NRVNTQUdFU19FRElURUQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19NRVNTQUdFU19VUERBVEU9JHtXRUJIT09LX0VWRU5UU19NRVNTQUdFU19VUERBVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19NRVNTQUdFU19ERUxFVEU9JHtXRUJIT09LX0VWRU5UU19NRVNTQUdFU19ERUxFVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19TRU5EX01FU1NBR0U9JHtXRUJIT09LX0VWRU5UU19TRU5EX01FU1NBR0U6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DT05UQUNUU19TRVQ9JHtXRUJIT09LX0VWRU5UU19DT05UQUNUU19TRVQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DT05UQUNUU19VUFNFUlQ9JHtXRUJIT09LX0VWRU5UU19DT05UQUNUU19VUFNFUlQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DT05UQUNUU19VUERBVEU9JHtXRUJIT09LX0VWRU5UU19DT05UQUNUU19VUERBVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19QUkVTRU5DRV9VUERBVEU9JHtXRUJIT09LX0VWRU5UU19QUkVTRU5DRV9VUERBVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DSEFUU19TRVQ9JHtXRUJIT09LX0VWRU5UU19DSEFUU19TRVQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DSEFUU19VUFNFUlQ9JHtXRUJIT09LX0VWRU5UU19DSEFUU19VUFNFUlQ6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DSEFUU19VUERBVEU9JHtXRUJIT09LX0VWRU5UU19DSEFUU19VUERBVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DSEFUU19ERUxFVEU9JHtXRUJIT09LX0VWRU5UU19DSEFUU19ERUxFVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19HUk9VUFNfVVBTRVJUPSR7V0VCSE9PS19FVkVOVFNfR1JPVVBTX1VQU0VSVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0dST1VQU19VUERBVEU9JHtXRUJIT09LX0VWRU5UU19HUk9VUFNfVVBEQVRFOi10cnVlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfR1JPVVBfUEFSVElDSVBBTlRTX1VQREFURT0ke1dFQkhPT0tfRVZFTlRTX0dST1VQX1BBUlRJQ0lQQU5UU19VUERBVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19DT05ORUNUSU9OX1VQREFURT0ke1dFQkhPT0tfRVZFTlRTX0NPTk5FQ1RJT05fVVBEQVRFOi10cnVlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfTEFCRUxTX0VESVQ9JHtXRUJIT09LX0VWRU5UU19MQUJFTFNfRURJVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0xBQkVMU19BU1NPQ0lBVElPTj0ke1dFQkhPT0tfRVZFTlRTX0xBQkVMU19BU1NPQ0lBVElPTjotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NBTEw9JHtXRUJIT09LX0VWRU5UU19DQUxMOi10cnVlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfVFlQRUJPVF9TVEFSVD0ke1dFQkhPT0tfRVZFTlRTX1RZUEVCT1RfU1RBUlQ6LWZhbHNlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfVFlQRUJPVF9DSEFOR0VfU1RBVFVTPSR7V0VCSE9PS19FVkVOVFNfVFlQRUJPVF9DSEFOR0VfU1RBVFVTOi1mYWxzZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0VSUk9SUz0ke1dFQkhPT0tfRVZFTlRTX0VSUk9SUzotZmFsc2V9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19FUlJPUlNfV0VCSE9PSz0ke1dFQkhPT0tfRVZFTlRTX0VSUk9SU19XRUJIT09LOi19JwogICAgICAtICdDT05GSUdfU0VTU0lPTl9QSE9ORV9DTElFTlQ9JHtDT05GSUdfU0VTU0lPTl9QSE9ORV9DTElFTlQ6LUV2b2x1dGlvbiBBUEkgVjJ9JwogICAgICAtICdDT05GSUdfU0VTU0lPTl9QSE9ORV9OQU1FPSR7Q09ORklHX1NFU1NJT05fUEhPTkVfTkFNRTotQ2hyb21lfScKICAgICAgLSAnUVJDT0RFX0xJTUlUPSR7UVJDT0RFX0xJTUlUOi0zMH0nCiAgICAgIC0gJ09QRU5BSV9FTkFCTEVEPSR7T1BFTkFJX0VOQUJMRUQ6LXRydWV9JwogICAgICAtICdESUZZX0VOQUJMRUQ9JHtESUZZX0VOQUJMRUQ6LXRydWV9JwogICAgICAtICdGTE9XSVNFX0VOQUJMRUQ9JHtGTE9XSVNFX0VOQUJMRUQ6LXRydWV9JwogICAgICAtICdOOE5fRU5BQkxFRD0ke044Tl9FTkFCTEVEOi10cnVlfScKICAgICAgLSAnVFlQRUJPVF9FTkFCTEVEPSR7VFlQRUJPVF9FTkFCTEVEOi10cnVlfScKICAgICAgLSAnVFlQRUJPVF9BUElfVkVSU0lPTj0ke1RZUEVCT1RfQVBJX1ZFUlNJT046LWxhdGVzdH0nCiAgICAgIC0gJ0NIQVRXT09UX0VOQUJMRUQ9JHtDSEFUV09PVF9FTkFCTEVEOi10cnVlfScKICAgICAgLSAnQ0hBVFdPT1RfTUVTU0FHRV9SRUFEPSR7Q0hBVFdPT1RfTUVTU0FHRV9SRUFEOi10cnVlfScKICAgICAgLSAnQ0hBVFdPT1RfTUVTU0FHRV9ERUxFVEU9JHtDSEFUV09PVF9NRVNTQUdFX0RFTEVURTotdHJ1ZX0nCiAgICAgIC0gJ0NIQVRXT09UX0lNUE9SVF9EQVRBQkFTRV9DT05ORUNUSU9OX1VSST1wb3N0Z3Jlc3FsOi8vJHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9OiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AcG9zdGdyZXM6NTQzMi8ke1BPU1RHUkVTX0RCOi1jaGF0d29vdH0nCiAgICAgIC0gJ0NIQVRXT09UX0lNUE9SVF9QTEFDRUhPTERFUl9NRURJQV9NRVNTQUdFPSR7Q0hBVFdPT1RfSU1QT1JUX1BMQUNFSE9MREVSX01FRElBX01FU1NBR0U6LXRydWV9JwogICAgICAtICdDQUNIRV9SRURJU19FTkFCTEVEPSR7Q0FDSEVfUkVESVNfRU5BQkxFRDotdHJ1ZX0nCiAgICAgIC0gJ0NBQ0hFX1JFRElTX1VSST0ke0NBQ0hFX1JFRElTX1VSSTotcmVkaXM6Ly9yZWRpczo2Mzc5LzZ9JwogICAgICAtICdDQUNIRV9SRURJU19QUkVGSVhfS0VZPSR7Q0FDSEVfUkVESVNfUFJFRklYX0tFWTotZXZvbHV0aW9uX3YyfScKICAgICAgLSAnQ0FDSEVfUkVESVNfU0FWRV9JTlNUQU5DRVM9JHtDQUNIRV9SRURJU19TQVZFX0lOU1RBTkNFUzotZmFsc2V9JwogICAgICAtICdDQUNIRV9MT0NBTF9FTkFCTEVEPSR7Q0FDSEVfTE9DQUxfRU5BQkxFRDotZmFsc2V9JwogICAgICAtICdTM19FTkFCTEVEPSR7UzNfRU5BQkxFRDotZmFsc2V9JwogICAgICAtICdTM19BQ0NFU1NfS0VZPSR7UzNfQUNDRVNTX0tFWTotfScKICAgICAgLSAnUzNfU0VDUkVUX0tFWT0ke1MzX1NFQ1JFVF9LRVk6LX0nCiAgICAgIC0gJ1MzX0JVQ0tFVD0ke1MzX0JVQ0tFVDotZXZvbHV0aW9ufScKICAgICAgLSAnUzNfUE9SVD0ke1MzX1BPUlQ6LTQ0M30nCiAgICAgIC0gJ1MzX1JFR0lPTj0ke1MzX1JFR0lPTjotdXMtZWFzdC0xfScKICAgICAgLSAnUzNfRU5EUE9JTlQ9JHtTM19FTkRQT0lOVDotZmlsZXMuc2l0ZS5jb219JwogICAgICAtICdTM19VU0VfU1NMPSR7UzNfVVNFX1NTTDotdHJ1ZX0nCiAgICAgIC0gJ0FVVEhFTlRJQ0FUSU9OX0FQSV9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX0FVVEhFTlRJQ0FUSU9OQVBJS0VZfScKICAgICAgLSAnQVVUSEVOVElDQVRJT05fRVhQT1NFX0lOX0ZFVENIX0lOU1RBTkNFUz0ke0FVVEhFTlRJQ0FUSU9OX0VYUE9TRV9JTl9GRVRDSF9JTlNUQU5DRVM6LXRydWV9JwogICAgICAtICdMQU5HVUFHRT0ke0xBTkdVQUdFOi1lbn0nCiAgICB2b2x1bWVzOgogICAgICAtICdldm9sdXRpb25faW5zdGFuY2VzOi9ldm9sdXRpb24vaW5zdGFuY2VzJwogICAgZXhwb3NlOgogICAgICAtIDgwODAKICByZWRpczoKICAgIGltYWdlOiAncmVkaXM6bGF0ZXN0JwogICAgY29tbWFuZDogInJlZGlzLXNlcnZlciAtLXBvcnQgNjM3OSAtLWFwcGVuZG9ubHkgeWVzXG4iCiAgICByZXN0YXJ0OiBhbHdheXMKICAgIHZvbHVtZXM6CiAgICAgIC0gJ2V2b2x1dGlvbl9yZWRpczovZGF0YScKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTYtYWxwaW5lJwogICAgY29tbWFuZDoKICAgICAgLSBwb3N0Z3JlcwogICAgICAtICctYycKICAgICAgLSBtYXhfY29ubmVjdGlvbnM9MTAwMAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ0FVVEhFTlRJQ0FUSU9OX0FQSV9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX0FVVEhFTlRJQ0FUSU9OQVBJS0VZfScKICAgIHJlc3RhcnQ6IGFsd2F5cwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXNfZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCnZvbHVtZXM6CiAgZXZvbHV0aW9uX2luc3RhbmNlczogbnVsbAogIGV2b2x1dGlvbl9yZWRpczogbnVsbAogIHBvc3RncmVzX2RhdGE6IG51bGwK", "tags": [ "evolution-api", diff --git a/templates/service-templates.json b/templates/service-templates.json index 50509f326..5a687e6db 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -950,7 +950,7 @@ }, "evolution-api": { "documentation": "https://doc.evolution-api.com/v1/pt/get-started/introduction?utm_source=coolify.io", - "slogan": "Evolution API Installation with Postgres and Redis", + "slogan": "Multi-platform messaging (whatsapp and more) integration API", "compose": "dmVyc2lvbjogJzMuOCcKc2VydmljZXM6CiAgYXBpOgogICAgaW1hZ2U6ICdldm9hcGljbG91ZC9ldm9sdXRpb24tYXBpOmxhdGVzdCcKICAgIHJlc3RhcnQ6IGFsd2F5cwogICAgZGVwZW5kc19vbjoKICAgICAgLSByZWRpcwogICAgICAtIHBvc3RncmVzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fRVZPXzgwODAKICAgICAgLSBTRVJWRVJfVVJMPSRTRVJWSUNFX0ZRRE5fRVZPCiAgICAgIC0gJ0RCX1RZUEU9JHtEQl9UWVBFOi1wb3N0Z3Jlc2RifScKICAgICAgLSAnREJfUE9TVEdSRVNEQl9EQVRBQkFTRT0ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ0RCX1BPU1RHUkVTREJfSE9TVD0ke0RCX1BPU1RHUkVTREJfSE9TVDotcG9zdGdyZXN9JwogICAgICAtICdEQl9QT1NUR1JFU0RCX1BPUlQ9JHtEQl9QT1NUR1JFU0RCX1BPUlQ6LTU0MzJ9JwogICAgICAtICdEQl9QT1NUR1JFU0RCX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdEQl9QT1NUR1JFU0RCX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ0RBVEFCQVNFX1BST1ZJREVSPSR7REFUQUJBU0VfUFJPVklERVI6LXBvc3RncmVzcWx9JwogICAgICAtICdEQVRBQkFTRV9VUkw9cG9zdGdyZXNxbDovLyR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfToke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9QHBvc3RncmVzOjU0MzIvJHtQT1NUR1JFU19EQjotcG9zdGdyZXN9JwogICAgICAtICdEQVRBQkFTRV9DT05ORUNUSU9OX1VSST1wb3N0Z3Jlc3FsOi8vJHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9OiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU31AcG9zdGdyZXM6NTQzMi8ke1BPU1RHUkVTX0RCOi1wb3N0Z3Jlc30nCiAgICAgIC0gJ0RFTF9JTlNUQU5DRT0ke0RFTF9JTlNUQU5DRTotZmFsc2V9JwogICAgICAtICdEQVRBQkFTRV9TQVZFX0RBVEFfSU5TVEFOQ0U9JHtEQVRBQkFTRV9TQVZFX0RBVEFfSU5TVEFOQ0U6LXRydWV9JwogICAgICAtICdEQVRBQkFTRV9TQVZFX0RBVEFfTkVXX01FU1NBR0U9JHtEQVRBQkFTRV9TQVZFX0RBVEFfTkVXX01FU1NBR0U6LXRydWV9JwogICAgICAtICdEQVRBQkFTRV9TQVZFX01FU1NBR0VfVVBEQVRFPSR7REFUQUJBU0VfU0FWRV9NRVNTQUdFX1VQREFURTotdHJ1ZX0nCiAgICAgIC0gJ0RBVEFCQVNFX1NBVkVfREFUQV9DT05UQUNUUz0ke0RBVEFCQVNFX1NBVkVfREFUQV9DT05UQUNUUzotdHJ1ZX0nCiAgICAgIC0gJ0RBVEFCQVNFX1NBVkVfREFUQV9DSEFUUz0ke0RBVEFCQVNFX1NBVkVfREFUQV9DSEFUUzotdHJ1ZX0nCiAgICAgIC0gJ0RBVEFCQVNFX1NBVkVfREFUQV9MQUJFTFM9JHtEQVRBQkFTRV9TQVZFX0RBVEFfTEFCRUxTOi10cnVlfScKICAgICAgLSAnREFUQUJBU0VfU0FWRV9EQVRBX0hJU1RPUklDPSR7REFUQUJBU0VfU0FWRV9EQVRBX0hJU1RPUklDOi10cnVlfScKICAgICAgLSAnREFUQUJBU0VfQ09OTkVDVElPTl9DTElFTlRfTkFNRT0ke0RBVEFCQVNFX0NPTk5FQ1RJT05fQ0xJRU5UX05BTUU6LWV2b2x1dGlvbl92Mn0nCiAgICAgIC0gJ1JBQkJJVE1RX0VOQUJMRUQ9JHtSQUJCSVRNUV9FTkFCTEVEOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX1VSST0ke1JBQkJJVE1RX1VSSTotYW1xcDovL2FkbWluOmFkbWluQHJhYmJpdG1xOjU2NzIvZGVmYXVsdH0nCiAgICAgIC0gJ1JBQkJJVE1RX0VYQ0hBTkdFX05BTUU9JHtSQUJCSVRNUV9FWENIQU5HRV9OQU1FOi1ldm9sdXRpb25fdjJ9JwogICAgICAtICdSQUJCSVRNUV9HTE9CQUxfRU5BQkxFRD0ke1JBQkJJVE1RX0dMT0JBTF9FTkFCTEVEOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19BUFBMSUNBVElPTl9TVEFSVFVQPSR7UkFCQklUTVFfRVZFTlRTX0FQUExJQ0FUSU9OX1NUQVJUVVA6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0lOU1RBTkNFX0NSRUFURT0ke1JBQkJJVE1RX0VWRU5UU19JTlNUQU5DRV9DUkVBVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0lOU1RBTkNFX0RFTEVURT0ke1JBQkJJVE1RX0VWRU5UU19JTlNUQU5DRV9ERUxFVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX1FSQ09ERV9VUERBVEVEPSR7UkFCQklUTVFfRVZFTlRTX1FSQ09ERV9VUERBVEVEOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19TRVQ9JHtSQUJCSVRNUV9FVkVOVFNfTUVTU0FHRVNfU0VUOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19VUFNFUlQ9JHtSQUJCSVRNUV9FVkVOVFNfTUVTU0FHRVNfVVBTRVJUOi10cnVlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX01FU1NBR0VTX0VESVRFRD0ke1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19FRElURUQ6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX01FU1NBR0VTX1VQREFURT0ke1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19VUERBVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX01FU1NBR0VTX0RFTEVURT0ke1JBQkJJVE1RX0VWRU5UU19NRVNTQUdFU19ERUxFVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX1NFTkRfTUVTU0FHRT0ke1JBQkJJVE1RX0VWRU5UU19TRU5EX01FU1NBR0U6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0NPTlRBQ1RTX1NFVD0ke1JBQkJJVE1RX0VWRU5UU19DT05UQUNUU19TRVQ6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0NPTlRBQ1RTX1VQU0VSVD0ke1JBQkJJVE1RX0VWRU5UU19DT05UQUNUU19VUFNFUlQ6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0NPTlRBQ1RTX1VQREFURT0ke1JBQkJJVE1RX0VWRU5UU19DT05UQUNUU19VUERBVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX1BSRVNFTkNFX1VQREFURT0ke1JBQkJJVE1RX0VWRU5UU19QUkVTRU5DRV9VUERBVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0NIQVRTX1NFVD0ke1JBQkJJVE1RX0VWRU5UU19DSEFUU19TRVQ6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0NIQVRTX1VQU0VSVD0ke1JBQkJJVE1RX0VWRU5UU19DSEFUU19VUFNFUlQ6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0NIQVRTX1VQREFURT0ke1JBQkJJVE1RX0VWRU5UU19DSEFUU19VUERBVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0NIQVRTX0RFTEVURT0ke1JBQkJJVE1RX0VWRU5UU19DSEFUU19ERUxFVEU6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX0dST1VQU19VUFNFUlQ9JHtSQUJCSVRNUV9FVkVOVFNfR1JPVVBTX1VQU0VSVDotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfR1JPVVBfVVBEQVRFPSR7UkFCQklUTVFfRVZFTlRTX0dST1VQX1VQREFURTotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfR1JPVVBfUEFSVElDSVBBTlRTX1VQREFURT0ke1JBQkJJVE1RX0VWRU5UU19HUk9VUF9QQVJUSUNJUEFOVFNfVVBEQVRFOi1mYWxzZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DT05ORUNUSU9OX1VQREFURT0ke1JBQkJJVE1RX0VWRU5UU19DT05ORUNUSU9OX1VQREFURTotdHJ1ZX0nCiAgICAgIC0gJ1JBQkJJVE1RX0VWRU5UU19DQUxMPSR7UkFCQklUTVFfRVZFTlRTX0NBTEw6LWZhbHNlfScKICAgICAgLSAnUkFCQklUTVFfRVZFTlRTX1RZUEVCT1RfU1RBUlQ9JHtSQUJCSVRNUV9FVkVOVFNfVFlQRUJPVF9TVEFSVDotZmFsc2V9JwogICAgICAtICdSQUJCSVRNUV9FVkVOVFNfVFlQRUJPVF9DSEFOR0VfU1RBVFVTPSR7UkFCQklUTVFfRVZFTlRTX1RZUEVCT1RfQ0hBTkdFX1NUQVRVUzotZmFsc2V9JwogICAgICAtICdTUVNfRU5BQkxFRD0ke1NRU19FTkFCTEVEOi1mYWxzZX0nCiAgICAgIC0gJ1NRU19BQ0NFU1NfS0VZX0lEPSR7U1FTX0FDQ0VTU19LRVlfSUQ6LX0nCiAgICAgIC0gJ1NRU19TRUNSRVRfQUNDRVNTX0tFWT0ke1NRU19TRUNSRVRfQUNDRVNTX0tFWTotfScKICAgICAgLSAnU1FTX0FDQ09VTlRfSUQ9JHtTUVNfQUNDT1VOVF9JRDotfScKICAgICAgLSAnU1FTX1JFR0lPTj0ke1NRU19SRUdJT046LX0nCiAgICAgIC0gJ1dFQlNPQ0tFVF9FTkFCTEVEPSR7V0VCU09DS0VUX0VOQUJMRUQ6LWZhbHNlfScKICAgICAgLSAnV0VCU09DS0VUX0dMT0JBTF9FVkVOVFM9JHtXRUJTT0NLRVRfR0xPQkFMX0VWRU5UUzotZmFsc2V9JwogICAgICAtICdXQV9CVVNJTkVTU19UT0tFTl9XRUJIT09LPSR7V0FfQlVTSU5FU1NfVE9LRU5fV0VCSE9PSzotZXZvbHV0aW9ufScKICAgICAgLSAnV0FfQlVTSU5FU1NfVVJMPSR7V0FfQlVTSU5FU1NfVVJMOi1odHRwczovL2dyYXBoLmZhY2Vib29rLmNvbX0nCiAgICAgIC0gJ1dBX0JVU0lORVNTX1ZFUlNJT049JHtXQV9CVVNJTkVTU19WRVJTSU9OOi12MjAuMH0nCiAgICAgIC0gJ1dBX0JVU0lORVNTX0xBTkdVQUdFPSR7V0FfQlVTSU5FU1NfTEFOR1VBR0U6LXB0X0JSfScKICAgICAgLSAiV0VCSE9PS19HTE9CQUxfVVJMPSR7V0VCSE9PS19HTE9CQUxfVVJMOi0nJ30iCiAgICAgIC0gJ1dFQkhPT0tfR0xPQkFMX0VOQUJMRUQ9JHtXRUJIT09LX0dMT0JBTF9FTkFCTEVEOi1mYWxzZX0nCiAgICAgIC0gJ1dFQkhPT0tfR0xPQkFMX1dFQkhPT0tfQllfRVZFTlRTPSR7V0VCSE9PS19HTE9CQUxfV0VCSE9PS19CWV9FVkVOVFM6LWZhbHNlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfQVBQTElDQVRJT05fU1RBUlRVUD0ke1dFQkhPT0tfRVZFTlRTX0FQUExJQ0FUSU9OX1NUQVJUVVA6LWZhbHNlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfUVJDT0RFX1VQREFURUQ9JHtXRUJIT09LX0VWRU5UU19RUkNPREVfVVBEQVRFRDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX1NFVD0ke1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX1NFVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX1VQU0VSVD0ke1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX1VQU0VSVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX0VESVRFRD0ke1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX0VESVRFRDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX1VQREFURT0ke1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX1VQREFURTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX0RFTEVURT0ke1dFQkhPT0tfRVZFTlRTX01FU1NBR0VTX0RFTEVURTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX1NFTkRfTUVTU0FHRT0ke1dFQkhPT0tfRVZFTlRTX1NFTkRfTUVTU0FHRTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NPTlRBQ1RTX1NFVD0ke1dFQkhPT0tfRVZFTlRTX0NPTlRBQ1RTX1NFVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NPTlRBQ1RTX1VQU0VSVD0ke1dFQkhPT0tfRVZFTlRTX0NPTlRBQ1RTX1VQU0VSVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NPTlRBQ1RTX1VQREFURT0ke1dFQkhPT0tfRVZFTlRTX0NPTlRBQ1RTX1VQREFURTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX1BSRVNFTkNFX1VQREFURT0ke1dFQkhPT0tfRVZFTlRTX1BSRVNFTkNFX1VQREFURTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NIQVRTX1NFVD0ke1dFQkhPT0tfRVZFTlRTX0NIQVRTX1NFVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NIQVRTX1VQU0VSVD0ke1dFQkhPT0tfRVZFTlRTX0NIQVRTX1VQU0VSVDotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NIQVRTX1VQREFURT0ke1dFQkhPT0tfRVZFTlRTX0NIQVRTX1VQREFURTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NIQVRTX0RFTEVURT0ke1dFQkhPT0tfRVZFTlRTX0NIQVRTX0RFTEVURTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0dST1VQU19VUFNFUlQ9JHtXRUJIT09LX0VWRU5UU19HUk9VUFNfVVBTRVJUOi10cnVlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfR1JPVVBTX1VQREFURT0ke1dFQkhPT0tfRVZFTlRTX0dST1VQU19VUERBVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19HUk9VUF9QQVJUSUNJUEFOVFNfVVBEQVRFPSR7V0VCSE9PS19FVkVOVFNfR1JPVVBfUEFSVElDSVBBTlRTX1VQREFURTotdHJ1ZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0NPTk5FQ1RJT05fVVBEQVRFPSR7V0VCSE9PS19FVkVOVFNfQ09OTkVDVElPTl9VUERBVEU6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19MQUJFTFNfRURJVD0ke1dFQkhPT0tfRVZFTlRTX0xBQkVMU19FRElUOi10cnVlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfTEFCRUxTX0FTU09DSUFUSU9OPSR7V0VCSE9PS19FVkVOVFNfTEFCRUxTX0FTU09DSUFUSU9OOi10cnVlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfQ0FMTD0ke1dFQkhPT0tfRVZFTlRTX0NBTEw6LXRydWV9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19UWVBFQk9UX1NUQVJUPSR7V0VCSE9PS19FVkVOVFNfVFlQRUJPVF9TVEFSVDotZmFsc2V9JwogICAgICAtICdXRUJIT09LX0VWRU5UU19UWVBFQk9UX0NIQU5HRV9TVEFUVVM9JHtXRUJIT09LX0VWRU5UU19UWVBFQk9UX0NIQU5HRV9TVEFUVVM6LWZhbHNlfScKICAgICAgLSAnV0VCSE9PS19FVkVOVFNfRVJST1JTPSR7V0VCSE9PS19FVkVOVFNfRVJST1JTOi1mYWxzZX0nCiAgICAgIC0gJ1dFQkhPT0tfRVZFTlRTX0VSUk9SU19XRUJIT09LPSR7V0VCSE9PS19FVkVOVFNfRVJST1JTX1dFQkhPT0s6LX0nCiAgICAgIC0gJ0NPTkZJR19TRVNTSU9OX1BIT05FX0NMSUVOVD0ke0NPTkZJR19TRVNTSU9OX1BIT05FX0NMSUVOVDotRXZvbHV0aW9uIEFQSSBWMn0nCiAgICAgIC0gJ0NPTkZJR19TRVNTSU9OX1BIT05FX05BTUU9JHtDT05GSUdfU0VTU0lPTl9QSE9ORV9OQU1FOi1DaHJvbWV9JwogICAgICAtICdRUkNPREVfTElNSVQ9JHtRUkNPREVfTElNSVQ6LTMwfScKICAgICAgLSAnT1BFTkFJX0VOQUJMRUQ9JHtPUEVOQUlfRU5BQkxFRDotdHJ1ZX0nCiAgICAgIC0gJ0RJRllfRU5BQkxFRD0ke0RJRllfRU5BQkxFRDotdHJ1ZX0nCiAgICAgIC0gJ0ZMT1dJU0VfRU5BQkxFRD0ke0ZMT1dJU0VfRU5BQkxFRDotdHJ1ZX0nCiAgICAgIC0gJ044Tl9FTkFCTEVEPSR7TjhOX0VOQUJMRUQ6LXRydWV9JwogICAgICAtICdUWVBFQk9UX0VOQUJMRUQ9JHtUWVBFQk9UX0VOQUJMRUQ6LXRydWV9JwogICAgICAtICdUWVBFQk9UX0FQSV9WRVJTSU9OPSR7VFlQRUJPVF9BUElfVkVSU0lPTjotbGF0ZXN0fScKICAgICAgLSAnQ0hBVFdPT1RfRU5BQkxFRD0ke0NIQVRXT09UX0VOQUJMRUQ6LXRydWV9JwogICAgICAtICdDSEFUV09PVF9NRVNTQUdFX1JFQUQ9JHtDSEFUV09PVF9NRVNTQUdFX1JFQUQ6LXRydWV9JwogICAgICAtICdDSEFUV09PVF9NRVNTQUdFX0RFTEVURT0ke0NIQVRXT09UX01FU1NBR0VfREVMRVRFOi10cnVlfScKICAgICAgLSAnQ0hBVFdPT1RfSU1QT1JUX0RBVEFCQVNFX0NPTk5FQ1RJT05fVVJJPXBvc3RncmVzcWw6Ly8ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU306JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfUBwb3N0Z3Jlczo1NDMyLyR7UE9TVEdSRVNfREI6LWNoYXR3b290fScKICAgICAgLSAnQ0hBVFdPT1RfSU1QT1JUX1BMQUNFSE9MREVSX01FRElBX01FU1NBR0U9JHtDSEFUV09PVF9JTVBPUlRfUExBQ0VIT0xERVJfTUVESUFfTUVTU0FHRTotdHJ1ZX0nCiAgICAgIC0gJ0NBQ0hFX1JFRElTX0VOQUJMRUQ9JHtDQUNIRV9SRURJU19FTkFCTEVEOi10cnVlfScKICAgICAgLSAnQ0FDSEVfUkVESVNfVVJJPSR7Q0FDSEVfUkVESVNfVVJJOi1yZWRpczovL3JlZGlzOjYzNzkvNn0nCiAgICAgIC0gJ0NBQ0hFX1JFRElTX1BSRUZJWF9LRVk9JHtDQUNIRV9SRURJU19QUkVGSVhfS0VZOi1ldm9sdXRpb25fdjJ9JwogICAgICAtICdDQUNIRV9SRURJU19TQVZFX0lOU1RBTkNFUz0ke0NBQ0hFX1JFRElTX1NBVkVfSU5TVEFOQ0VTOi1mYWxzZX0nCiAgICAgIC0gJ0NBQ0hFX0xPQ0FMX0VOQUJMRUQ9JHtDQUNIRV9MT0NBTF9FTkFCTEVEOi1mYWxzZX0nCiAgICAgIC0gJ1MzX0VOQUJMRUQ9JHtTM19FTkFCTEVEOi1mYWxzZX0nCiAgICAgIC0gJ1MzX0FDQ0VTU19LRVk9JHtTM19BQ0NFU1NfS0VZOi19JwogICAgICAtICdTM19TRUNSRVRfS0VZPSR7UzNfU0VDUkVUX0tFWTotfScKICAgICAgLSAnUzNfQlVDS0VUPSR7UzNfQlVDS0VUOi1ldm9sdXRpb259JwogICAgICAtICdTM19QT1JUPSR7UzNfUE9SVDotNDQzfScKICAgICAgLSAnUzNfUkVHSU9OPSR7UzNfUkVHSU9OOi11cy1lYXN0LTF9JwogICAgICAtICdTM19FTkRQT0lOVD0ke1MzX0VORFBPSU5UOi1maWxlcy5zaXRlLmNvbX0nCiAgICAgIC0gJ1MzX1VTRV9TU0w9JHtTM19VU0VfU1NMOi10cnVlfScKICAgICAgLSAnQVVUSEVOVElDQVRJT05fQVBJX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfQVVUSEVOVElDQVRJT05BUElLRVl9JwogICAgICAtICdBVVRIRU5USUNBVElPTl9FWFBPU0VfSU5fRkVUQ0hfSU5TVEFOQ0VTPSR7QVVUSEVOVElDQVRJT05fRVhQT1NFX0lOX0ZFVENIX0lOU1RBTkNFUzotdHJ1ZX0nCiAgICAgIC0gJ0xBTkdVQUdFPSR7TEFOR1VBR0U6LWVufScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ2V2b2x1dGlvbl9pbnN0YW5jZXM6L2V2b2x1dGlvbi9pbnN0YW5jZXMnCiAgICBleHBvc2U6CiAgICAgIC0gODA4MAogIHJlZGlzOgogICAgaW1hZ2U6ICdyZWRpczpsYXRlc3QnCiAgICBjb21tYW5kOiAicmVkaXMtc2VydmVyIC0tcG9ydCA2Mzc5IC0tYXBwZW5kb25seSB5ZXNcbiIKICAgIHJlc3RhcnQ6IGFsd2F5cwogICAgdm9sdW1lczoKICAgICAgLSAnZXZvbHV0aW9uX3JlZGlzOi9kYXRhJwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNi1hbHBpbmUnCiAgICBjb21tYW5kOgogICAgICAtIHBvc3RncmVzCiAgICAgIC0gJy1jJwogICAgICAtIG1heF9jb25uZWN0aW9ucz0xMDAwCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LXBvc3RncmVzfScKICAgICAgLSAnQVVUSEVOVElDQVRJT05fQVBJX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfQVVUSEVOVElDQVRJT05BUElLRVl9JwogICAgcmVzdGFydDogYWx3YXlzCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlc19kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKdm9sdW1lczoKICBldm9sdXRpb25faW5zdGFuY2VzOiBudWxsCiAgZXZvbHV0aW9uX3JlZGlzOiBudWxsCiAgcG9zdGdyZXNfZGF0YTogbnVsbAo=", "tags": [ "evolution-api", From 84c8dc367cf01833f2e8a961a3fe62c4dd86a9c6 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Thu, 4 Sep 2025 00:59:10 +0200 Subject: [PATCH 002/163] fix(docs): update documentation URL to version 2 in evolution-api.yaml --- templates/compose/evolution-api.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/evolution-api.yaml b/templates/compose/evolution-api.yaml index ac3fd42df..a26e2fddb 100644 --- a/templates/compose/evolution-api.yaml +++ b/templates/compose/evolution-api.yaml @@ -1,4 +1,4 @@ -# documentation: https://doc.evolution-api.com/v1/pt/get-started/introduction +# documentation: https://doc.evolution-api.com/v2/en/get-started/introduction # slogan: Multi-platform messaging (whatsapp and more) integration API # category: backend # tags: evolution-api,evo-api,evolution,whatsapp,api,postgres,redis From 634e7593b3a340d7cc87040552939ea73faca5f3 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Fri, 5 Sep 2025 22:00:37 +0200 Subject: [PATCH 003/163] add(templates): Metamcp app --- public/svgs/metamcp.png | Bin 0 -> 57872 bytes templates/compose/metamcp.yaml | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 public/svgs/metamcp.png create mode 100644 templates/compose/metamcp.yaml diff --git a/public/svgs/metamcp.png b/public/svgs/metamcp.png new file mode 100644 index 0000000000000000000000000000000000000000..e1eeb5c06153cad6eb1f64a0d462afbb352ab1c0 GIT binary patch literal 57872 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 literal 0 HcmV?d00001 diff --git a/templates/compose/metamcp.yaml b/templates/compose/metamcp.yaml new file mode 100644 index 000000000..152b7a2d2 --- /dev/null +++ b/templates/compose/metamcp.yaml @@ -0,0 +1,53 @@ +# documentation: https://github.com/metatool-ai/metamcp +# slogan: MCP Aggregator, Orchestrator, Middleware, Gateway in one app +# tags: mcp, ai, sse +# category: mcp +# logo: svgs/metamcp.png +# port: 12008 + +services: + app: + container_name: metamcp + image: 'ghcr.io/metatool-ai/metamcp:latest' + ports: + - '12008:12008' + environment: + - SERVICE_URL_METAMCP_12008 + - 'POSTGRES_HOST=${POSTGRES_HOST:?postgres}' + - 'POSTGRES_PORT=${POSTGRES_PORT:?5432}' + - 'POSTGRES_USER=${SERVICE_USER_DB}' + - 'POSTGRES_PASSWORD=${SERVICE_PASSWORD_DB}' + - 'POSTGRES_DB=${POSTGRES_DB:-metamcp_db}' + - 'DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}' + - APP_URL=$SERVICE_URL_METAMCP + - 'NEXT_PUBLIC_APP_URL=${APP_URL}' + - BETTER_AUTH_SECRET=$SERVICE_PASSWORD_AUTH + - 'TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL=${TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL:?true}' + depends_on: + postgres: + condition: service_healthy + healthcheck: + test: + - CMD + - curl + - '-f' + - 'http://localhost:12008/health' + interval: 30s + timeout: 10s + postgres: + image: 'postgres:16-alpine' + container_name: metamcp-pg + environment: + - 'POSTGRES_DB=${POSTGRES_DB:-metamcp_db}' + - 'POSTGRES_USER=${POSTGRES_USER:-metamcp_user}' + - 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-m3t4mcp}' + ports: + - '9433:5432' + volumes: + - 'postgres_data:/var/lib/postgresql/data' + healthcheck: + test: + - CMD-SHELL + - 'pg_isready -U ${POSTGRES_USER:-metamcp_user} -d ${POSTGRES_DB:-metamcp_db}' + interval: 10s + timeout: 5s From 327e8ae3c9c78ef00ed9f5a5a37d834d75016ed1 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Fri, 5 Sep 2025 22:07:53 +0200 Subject: [PATCH 004/163] fix(template): remove default values for environment variables --- templates/compose/metamcp.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/compose/metamcp.yaml b/templates/compose/metamcp.yaml index 152b7a2d2..297ab3880 100644 --- a/templates/compose/metamcp.yaml +++ b/templates/compose/metamcp.yaml @@ -38,9 +38,9 @@ services: image: 'postgres:16-alpine' container_name: metamcp-pg environment: - - 'POSTGRES_DB=${POSTGRES_DB:-metamcp_db}' - - 'POSTGRES_USER=${POSTGRES_USER:-metamcp_user}' - - 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-m3t4mcp}' + - 'POSTGRES_DB=${POSTGRES_DB}' + - 'POSTGRES_USER=${POSTGRES_USER}' + - 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD}' ports: - '9433:5432' volumes: @@ -48,6 +48,6 @@ services: healthcheck: test: - CMD-SHELL - - 'pg_isready -U ${POSTGRES_USER:-metamcp_user} -d ${POSTGRES_DB:-metamcp_db}' + - 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}' interval: 10s timeout: 5s From ef89baf171a0197a0f600f5d9811e0bf559b6082 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Sun, 7 Sep 2025 20:27:34 +0200 Subject: [PATCH 005/163] fix(templates) Fixing MetaMCP template --- templates/compose/metamcp.yaml | 35 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/templates/compose/metamcp.yaml b/templates/compose/metamcp.yaml index 297ab3880..1bb8fb99c 100644 --- a/templates/compose/metamcp.yaml +++ b/templates/compose/metamcp.yaml @@ -9,16 +9,14 @@ services: app: container_name: metamcp image: 'ghcr.io/metatool-ai/metamcp:latest' - ports: - - '12008:12008' environment: - SERVICE_URL_METAMCP_12008 - - 'POSTGRES_HOST=${POSTGRES_HOST:?postgres}' - - 'POSTGRES_PORT=${POSTGRES_PORT:?5432}' - - 'POSTGRES_USER=${SERVICE_USER_DB}' - - 'POSTGRES_PASSWORD=${SERVICE_PASSWORD_DB}' - - 'POSTGRES_DB=${POSTGRES_DB:-metamcp_db}' - - 'DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}' + - POSTGRES_HOST=${POSTGRES_HOST:-postgres} + - POSTGRES_PORT=${POSTGRES_PORT:-5432} + - POSTGRES_USER=${SERVICE_USER_DB} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} + - POSTGRES_DB=${POSTGRES_DB:-metamcp_db} + - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}' - APP_URL=$SERVICE_URL_METAMCP - 'NEXT_PUBLIC_APP_URL=${APP_URL}' - BETTER_AUTH_SECRET=$SERVICE_PASSWORD_AUTH @@ -32,22 +30,23 @@ services: - curl - '-f' - 'http://localhost:12008/health' - interval: 30s - timeout: 10s + interval: 5s + timeout: 20s + retries: 10 postgres: image: 'postgres:16-alpine' - container_name: metamcp-pg + container_name: metamcp-DB environment: - - 'POSTGRES_DB=${POSTGRES_DB}' - - 'POSTGRES_USER=${POSTGRES_USER}' - - 'POSTGRES_PASSWORD=${POSTGRES_PASSWORD}' - ports: - - '9433:5432' + - POSTGRES_DB=${POSTGRES_DB:-postgres} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} + - POSTGRES_USER=${SERVICE_USER_POSTGRES} + - POSTGRES_PORT=${POSTGRES_PORT:-5432} volumes: - 'postgres_data:/var/lib/postgresql/data' healthcheck: test: - CMD-SHELL - 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}' - interval: 10s - timeout: 5s + interval: 5s + timeout: 20s + retries: 10 From 67580124f6c96b3ed558e1806a340d951a07cb33 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Wed, 8 Oct 2025 13:08:44 +0200 Subject: [PATCH 006/163] fix: update metamcp image version and clean up environment variable syntax --- templates/compose/metamcp.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/compose/metamcp.yaml b/templates/compose/metamcp.yaml index 1bb8fb99c..39c9f07fa 100644 --- a/templates/compose/metamcp.yaml +++ b/templates/compose/metamcp.yaml @@ -8,7 +8,7 @@ services: app: container_name: metamcp - image: 'ghcr.io/metatool-ai/metamcp:latest' + image: 'ghcr.io/metatool-ai/metamcp:2.4' environment: - SERVICE_URL_METAMCP_12008 - POSTGRES_HOST=${POSTGRES_HOST:-postgres} @@ -18,9 +18,9 @@ services: - POSTGRES_DB=${POSTGRES_DB:-metamcp_db} - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}' - APP_URL=$SERVICE_URL_METAMCP - - 'NEXT_PUBLIC_APP_URL=${APP_URL}' + - NEXT_PUBLIC_APP_URL=${APP_URL} - BETTER_AUTH_SECRET=$SERVICE_PASSWORD_AUTH - - 'TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL=${TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL:?true}' + - TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL=${TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL:?true} depends_on: postgres: condition: service_healthy From b3cf97de2418849bd11ce654c8045b6c80ab0f35 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Fri, 17 Oct 2025 12:09:15 +0200 Subject: [PATCH 007/163] Add Home Assistant docker compose template - Add Home Assistant template with version 2025.10.2 - Configure reverse proxy support for Coolify with trusted private IP ranges - Include D-Bus volume for Bluetooth integration support - Add healthcheck for container monitoring - Include configuration.yaml with reverse proxy settings to fix 400 Bad Request errors --- public/svgs/home-assistant.svg | 4 +++ templates/compose/home-assistant.yaml | 46 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 public/svgs/home-assistant.svg create mode 100644 templates/compose/home-assistant.yaml diff --git a/public/svgs/home-assistant.svg b/public/svgs/home-assistant.svg new file mode 100644 index 000000000..7bce628cf --- /dev/null +++ b/public/svgs/home-assistant.svg @@ -0,0 +1,4 @@ + + + + diff --git a/templates/compose/home-assistant.yaml b/templates/compose/home-assistant.yaml new file mode 100644 index 000000000..a54bca8c9 --- /dev/null +++ b/templates/compose/home-assistant.yaml @@ -0,0 +1,46 @@ +# documentation: https://www.home-assistant.io/installation/linux#docker-compose +# slogan: Open source home automation that puts local control and privacy first. +# category: automation +# tags: home-automation,iot,smart-home,automation,domotics,mqtt,zigbee,zwave +# logo: svgs/home-assistant.svg +# port: 8123 + +services: + homeassistant: + image: ghcr.io/home-assistant/home-assistant:2025.10.2 + environment: + - SERVICE_URL_HOMEASSISTANT_8123 + - TZ=${TZ:-UTC} + - DISABLE_JEMALLOC=${DISABLE_JEMALLOC:-false} + volumes: + - homeassistant-config:/config + - /etc/localtime:/etc/localtime:ro + - /run/dbus:/run/dbus:ro + + - type: bind + source: ./configuration.yaml + target: /config/configuration.yaml + content: | + # Loads default set of integrations. Do not remove. + default_config: + + # Configuration for reverse proxy support (required for Coolify) + http: + use_x_forwarded_for: true + trusted_proxies: + - 10.0.0.0/8 + - 172.16.0.0/12 + - 192.168.0.0/16 + ip_ban_enabled: true + login_attempts_threshold: 5 + + automation: !include automations.yaml + script: !include scripts.yaml + scene: !include scenes.yaml + privileged: true + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8123"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s From 1ad0da1e48532b72b211f4fca2b67f12ee9bfe93 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Fri, 17 Oct 2025 12:26:00 +0200 Subject: [PATCH 008/163] Remove unnecessary blank lines and commented-out automation configurations from Home Assistant template --- templates/compose/home-assistant.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/templates/compose/home-assistant.yaml b/templates/compose/home-assistant.yaml index a54bca8c9..f3a841b23 100644 --- a/templates/compose/home-assistant.yaml +++ b/templates/compose/home-assistant.yaml @@ -16,7 +16,6 @@ services: - homeassistant-config:/config - /etc/localtime:/etc/localtime:ro - /run/dbus:/run/dbus:ro - - type: bind source: ./configuration.yaml target: /config/configuration.yaml @@ -33,10 +32,6 @@ services: - 192.168.0.0/16 ip_ban_enabled: true login_attempts_threshold: 5 - - automation: !include automations.yaml - script: !include scripts.yaml - scene: !include scenes.yaml privileged: true healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8123"] From 057fbdf35487e83e6bc5830e66131016f08cfe81 Mon Sep 17 00:00:00 2001 From: ShadowArcanist Date: Fri, 17 Oct 2025 22:25:53 +0530 Subject: [PATCH 009/163] Added Redis insight service --- public/svgs/redisinsight.png | Bin 0 -> 4100 bytes templates/compose/redis-insight.yaml | 31 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 public/svgs/redisinsight.png create mode 100644 templates/compose/redis-insight.yaml diff --git a/public/svgs/redisinsight.png b/public/svgs/redisinsight.png new file mode 100644 index 0000000000000000000000000000000000000000..bc8056276e2d2ecee78d28b2750960f33af7665e GIT binary patch literal 4100 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 yboa891a^x<*_W Date: Fri, 17 Oct 2025 20:33:16 +0200 Subject: [PATCH 010/163] Changes auto-committed by Conductor (#6916) --- .github/workflows/cleanup-ghcr-untagged.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cleanup-ghcr-untagged.yml b/.github/workflows/cleanup-ghcr-untagged.yml index 1ad41ce16..394fba68f 100644 --- a/.github/workflows/cleanup-ghcr-untagged.yml +++ b/.github/workflows/cleanup-ghcr-untagged.yml @@ -1,24 +1,25 @@ name: Cleanup Untagged GHCR Images on: - workflow_dispatch: # Allow manual trigger - schedule: - - cron: '0 */6 * * *' # Run every 6 hours to handle large volume (16k+ images) + workflow_dispatch: # Manual trigger only env: GITHUB_REGISTRY: ghcr.io jobs: - cleanup-testing-host: + cleanup-all-packages: runs-on: ubuntu-latest permissions: contents: read packages: write + strategy: + matrix: + package: ['coolify', 'coolify-helper', 'coolify-realtime', 'coolify-testing-host'] steps: - - name: Delete untagged coolify-testing-host images + - name: Delete untagged ${{ matrix.package }} images uses: actions/delete-package-versions@v5 with: - package-name: 'coolify-testing-host' + package-name: ${{ matrix.package }} package-type: 'container' min-versions-to-keep: 0 delete-only-untagged-versions: 'true' From f7427fdea03ccd0da20ddce590c6eb6fd2119fd9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 17 Oct 2025 23:04:24 +0200 Subject: [PATCH 011/163] Changes auto-committed by Conductor --- app/Livewire/Security/PrivateKey/Index.php | 2 +- app/Livewire/Security/PrivateKey/Show.php | 8 +- app/Models/PrivateKey.php | 3 +- app/Models/User.php | 33 +++ app/Policies/PrivateKeyPolicy.php | 49 +++- package-lock.json | 22 +- .../security/private-key/index.blade.php | 45 ++-- tests/Unit/Policies/PrivateKeyPolicyTest.php | 209 ++++++++++++++++++ 8 files changed, 334 insertions(+), 37 deletions(-) create mode 100644 tests/Unit/Policies/PrivateKeyPolicyTest.php diff --git a/app/Livewire/Security/PrivateKey/Index.php b/app/Livewire/Security/PrivateKey/Index.php index 950ec152d..1eb66ae3e 100644 --- a/app/Livewire/Security/PrivateKey/Index.php +++ b/app/Livewire/Security/PrivateKey/Index.php @@ -12,7 +12,7 @@ class Index extends Component public function render() { - $privateKeys = PrivateKey::ownedByCurrentTeam(['name', 'uuid', 'is_git_related', 'description'])->get(); + $privateKeys = PrivateKey::ownedByCurrentTeam(['name', 'uuid', 'is_git_related', 'description', 'team_id'])->get(); return view('livewire.security.private-key.index', [ 'privateKeys' => $privateKeys, diff --git a/app/Livewire/Security/PrivateKey/Show.php b/app/Livewire/Security/PrivateKey/Show.php index 9928cfe97..c292d14a3 100644 --- a/app/Livewire/Security/PrivateKey/Show.php +++ b/app/Livewire/Security/PrivateKey/Show.php @@ -79,8 +79,14 @@ private function syncData(bool $toModel = false): void public function mount() { try { - $this->private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related'])->whereUuid(request()->private_key_uuid)->firstOrFail(); + $this->private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related', 'team_id'])->whereUuid(request()->private_key_uuid)->firstOrFail(); + + // Explicit authorization check - will throw 403 if not authorized + $this->authorize('view', $this->private_key); + $this->syncData(false); + } catch (\Illuminate\Auth\Access\AuthorizationException $e) { + abort(403, 'You do not have permission to view this private key.'); } catch (\Throwable) { abort(404); } diff --git a/app/Models/PrivateKey.php b/app/Models/PrivateKey.php index 08f3f1ebd..c5cbc6338 100644 --- a/app/Models/PrivateKey.php +++ b/app/Models/PrivateKey.php @@ -82,9 +82,10 @@ public function getPublicKey() public static function ownedByCurrentTeam(array $select = ['*']) { + $teamId = currentTeam()->id; $selectArray = collect($select)->concat(['id']); - return self::whereTeamId(currentTeam()->id)->select($selectArray->all()); + return self::whereTeamId($teamId)->select($selectArray->all()); } public static function validatePrivateKey($privateKey) diff --git a/app/Models/User.php b/app/Models/User.php index 9ab9fefe9..f04b6fa77 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -338,6 +338,39 @@ public function role() return data_get($user, 'pivot.role'); } + /** + * Check if the user is an admin or owner of a specific team + */ + public function isAdminOfTeam(int $teamId): bool + { + $team = $this->teams->where('id', $teamId)->first(); + + if (! $team) { + return false; + } + + $role = $team->pivot->role ?? null; + + return $role === 'admin' || $role === 'owner'; + } + + /** + * Check if the user can access system resources (team_id=0) + * Must be admin/owner of root team + */ + public function canAccessSystemResources(): bool + { + // Check if user is member of root team + $rootTeam = $this->teams->where('id', 0)->first(); + + if (! $rootTeam) { + return false; + } + + // Check if user is admin or owner of root team + return $this->isAdminOfTeam(0); + } + public function requestEmailChange(string $newEmail): void { // Generate 6-digit code diff --git a/app/Policies/PrivateKeyPolicy.php b/app/Policies/PrivateKeyPolicy.php index 996054c95..9f3381faf 100644 --- a/app/Policies/PrivateKeyPolicy.php +++ b/app/Policies/PrivateKeyPolicy.php @@ -20,8 +20,18 @@ public function viewAny(User $user): bool */ public function view(User $user, PrivateKey $privateKey): bool { - // return $user->teams->contains('id', $privateKey->team_id); - return true; + // Handle null team_id + if ($privateKey->team_id === null) { + return false; + } + + // System resource (team_id=0): Only root team admins/owners can access + if ($privateKey->team_id === 0) { + return $user->canAccessSystemResources(); + } + + // Regular resource: Check team membership + return $user->teams->contains('id', $privateKey->team_id); } /** @@ -29,8 +39,9 @@ public function view(User $user, PrivateKey $privateKey): bool */ public function create(User $user): bool { - // return $user->isAdmin(); - return true; + // Only admins/owners can create private keys + // Members should not be able to create SSH keys that could be used for deployments + return $user->isAdmin(); } /** @@ -38,8 +49,19 @@ public function create(User $user): bool */ public function update(User $user, PrivateKey $privateKey): bool { - // return $user->isAdmin() && $user->teams->contains('id', $privateKey->team_id); - return true; + // Handle null team_id + if ($privateKey->team_id === null) { + return false; + } + + // System resource (team_id=0): Only root team admins/owners can update + if ($privateKey->team_id === 0) { + return $user->canAccessSystemResources(); + } + + // Regular resource: Must be admin/owner of the team + return $user->isAdminOfTeam($privateKey->team_id) + && $user->teams->contains('id', $privateKey->team_id); } /** @@ -47,8 +69,19 @@ public function update(User $user, PrivateKey $privateKey): bool */ public function delete(User $user, PrivateKey $privateKey): bool { - // return $user->isAdmin() && $user->teams->contains('id', $privateKey->team_id); - return true; + // Handle null team_id + if ($privateKey->team_id === null) { + return false; + } + + // System resource (team_id=0): Only root team admins/owners can delete + if ($privateKey->team_id === 0) { + return $user->canAccessSystemResources(); + } + + // Regular resource: Must be admin/owner of the team + return $user->isAdminOfTeam($privateKey->team_id) + && $user->teams->contains('id', $privateKey->team_id); } /** diff --git a/package-lock.json b/package-lock.json index fa5ac7aae..ce1097097 100644 --- a/package-lock.json +++ b/package-lock.json @@ -916,8 +916,7 @@ "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@tailwindcss/forms": { "version": "0.5.10", @@ -1372,7 +1371,8 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/asynckit": { "version": "0.4.0", @@ -1535,7 +1535,6 @@ "integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1", @@ -1550,7 +1549,6 @@ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -1569,7 +1567,6 @@ "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" } @@ -2331,6 +2328,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2407,6 +2405,7 @@ "integrity": "sha512-wp3HqIIUc1GRyu1XrP6m2dgyE9MoCsXVsWNlohj0rjSkLf+a0jLvEyVubdg58oMk7bhjBWnFClgp8jfAa6Ak4Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "tweetnacl": "^1.0.3" } @@ -2491,7 +2490,6 @@ "integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", @@ -2508,7 +2506,6 @@ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -2527,7 +2524,6 @@ "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -2542,7 +2538,6 @@ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -2591,7 +2586,8 @@ "version": "4.1.10", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.10.tgz", "integrity": "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/tapable": { "version": "2.3.0", @@ -2660,6 +2656,7 @@ "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -2759,6 +2756,7 @@ "integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.16", "@vue/compiler-sfc": "3.5.16", @@ -2781,7 +2779,6 @@ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -2803,7 +2800,6 @@ "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz", "integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==", "dev": true, - "peer": true, "engines": { "node": ">=0.4.0" } diff --git a/resources/views/livewire/security/private-key/index.blade.php b/resources/views/livewire/security/private-key/index.blade.php index 47cfc9b1e..c51c7a00a 100644 --- a/resources/views/livewire/security/private-key/index.blade.php +++ b/resources/views/livewire/security/private-key/index.blade.php @@ -14,22 +14,41 @@
@forelse ($privateKeys as $key) - -
-
- {{ data_get($key, 'name') }} + @can('view', $key) + {{-- Admin/Owner: Clickable link --}} + +
+
+ {{ data_get($key, 'name') }} +
+
+ {{ $key->description }} + @if (!$key->isInUse()) + Unused + @endif +
-
- {{ $key->description }} - @if (!$key->isInUse()) - Unused - @endif + + @else + {{-- Member: Visible but not clickable --}} +
+
+
+ {{ data_get($key, 'name') }} + View Only +
+
+ {{ $key->description }} + @if (!$key->isInUse()) + Unused + @endif +
-
- + @endcan @empty
No private keys found.
@endforelse diff --git a/tests/Unit/Policies/PrivateKeyPolicyTest.php b/tests/Unit/Policies/PrivateKeyPolicyTest.php new file mode 100644 index 000000000..dd0037403 --- /dev/null +++ b/tests/Unit/Policies/PrivateKeyPolicyTest.php @@ -0,0 +1,209 @@ + 0, 'pivot' => (object) ['role' => 'admin']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->view($user, $privateKey))->toBeTrue(); +}); + +it('allows root team owner to view system private key', function () { + $teams = collect([ + (object) ['id' => 0, 'pivot' => (object) ['role' => 'owner']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->view($user, $privateKey))->toBeTrue(); +}); + +it('denies regular member of root team to view system private key', function () { + $teams = collect([ + (object) ['id' => 0, 'pivot' => (object) ['role' => 'member']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->view($user, $privateKey))->toBeFalse(); +}); + +it('denies non-root team member to view system private key', function () { + $teams = collect([ + (object) ['id' => 1, 'pivot' => (object) ['role' => 'owner']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->view($user, $privateKey))->toBeFalse(); +}); + +it('allows team member to view their own team private key', function () { + $teams = collect([ + (object) ['id' => 1, 'pivot' => (object) ['role' => 'member']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 1; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->view($user, $privateKey))->toBeTrue(); +}); + +it('denies team member to view another team private key', function () { + $teams = collect([ + (object) ['id' => 1, 'pivot' => (object) ['role' => 'owner']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 2; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->view($user, $privateKey))->toBeFalse(); +}); + +it('allows root team admin to update system private key', function () { + $teams = collect([ + (object) ['id' => 0, 'pivot' => (object) ['role' => 'admin']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->update($user, $privateKey))->toBeTrue(); +}); + +it('denies root team member to update system private key', function () { + $teams = collect([ + (object) ['id' => 0, 'pivot' => (object) ['role' => 'member']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->update($user, $privateKey))->toBeFalse(); +}); + +it('allows team admin to update their own team private key', function () { + $teams = collect([ + (object) ['id' => 1, 'pivot' => (object) ['role' => 'admin']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 1; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->update($user, $privateKey))->toBeTrue(); +}); + +it('denies team member to update their own team private key', function () { + $teams = collect([ + (object) ['id' => 1, 'pivot' => (object) ['role' => 'member']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 1; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->update($user, $privateKey))->toBeFalse(); +}); + +it('allows root team admin to delete system private key', function () { + $teams = collect([ + (object) ['id' => 0, 'pivot' => (object) ['role' => 'admin']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->delete($user, $privateKey))->toBeTrue(); +}); + +it('denies root team member to delete system private key', function () { + $teams = collect([ + (object) ['id' => 0, 'pivot' => (object) ['role' => 'member']], + ]); + + $user = Mockery::mock(User::class)->makePartial(); + $user->shouldReceive('getAttribute')->with('teams')->andReturn($teams); + + $privateKey = new class + { + public $team_id = 0; + }; + + $policy = new PrivateKeyPolicy; + expect($policy->delete($user, $privateKey))->toBeFalse(); +}); From 14bfdb4405a9e18f4cf2ec239dedbe4af3f08c19 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Sat, 18 Oct 2025 14:40:21 +0200 Subject: [PATCH 012/163] fix(templates) delete unused volume --- templates/compose/home-assistant.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/compose/home-assistant.yaml b/templates/compose/home-assistant.yaml index f3a841b23..36a6b452d 100644 --- a/templates/compose/home-assistant.yaml +++ b/templates/compose/home-assistant.yaml @@ -14,7 +14,6 @@ services: - DISABLE_JEMALLOC=${DISABLE_JEMALLOC:-false} volumes: - homeassistant-config:/config - - /etc/localtime:/etc/localtime:ro - /run/dbus:/run/dbus:ro - type: bind source: ./configuration.yaml From f6b8a471403654b1ac6cc3a9331363b71b056d38 Mon Sep 17 00:00:00 2001 From: Stellar Rounin Date: Sat, 18 Oct 2025 09:18:53 -0600 Subject: [PATCH 013/163] feat(servide): Add siyuan template --- public/svgs/siyuan.svg | 10 ++++++++++ templates/compose/siyuan.yaml | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 public/svgs/siyuan.svg create mode 100644 templates/compose/siyuan.yaml diff --git a/public/svgs/siyuan.svg b/public/svgs/siyuan.svg new file mode 100644 index 000000000..fc15edd5e --- /dev/null +++ b/public/svgs/siyuan.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/templates/compose/siyuan.yaml b/templates/compose/siyuan.yaml new file mode 100644 index 000000000..30f4054ed --- /dev/null +++ b/templates/compose/siyuan.yaml @@ -0,0 +1,28 @@ +# documentation: https://github.com/siyuan-note/siyuan +# slogan: A privacy-first, self-hosted, fully open source personal knowledge management software, written in typescript and golang. +# tags: note-taking,markdown,pkm +# logo: svgs/siyuan.svg +# port: 6806 + +services: + siyuan: + image: b3log/siyuan + volumes: + - 'siyuan_workspace:/siyuan/workspace' + environment: + - SERVICE_URL_SIYUAN_6806 + - TZ=${TZ:-UTC} + - PUID=1000 + - PGID=1000 + - 'SIYUAN_ACCESS_AUTH_CODE=${SERVICE_PASSWORD_SIYUAN}' + healthcheck: + test: + - CMD + - wget + - '--spider' + - '--quiet' + - 'http://127.0.0.1:6806/api/system/version' + interval: 15s + timeout: 10s + retries: 5 + start_period: 40s \ No newline at end of file From b0ee2d227a760e7c10754cd6906334a7a2306b4e Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Sun, 19 Oct 2025 18:04:06 +0200 Subject: [PATCH 014/163] Update metamcp.yaml: refine environment variables and healthcheck settings --- templates/compose/metamcp.yaml | 42 ++++++++++++++++------------------ 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/templates/compose/metamcp.yaml b/templates/compose/metamcp.yaml index 39c9f07fa..b2f7ce68e 100644 --- a/templates/compose/metamcp.yaml +++ b/templates/compose/metamcp.yaml @@ -1,26 +1,25 @@ # documentation: https://github.com/metatool-ai/metamcp # slogan: MCP Aggregator, Orchestrator, Middleware, Gateway in one app -# tags: mcp, ai, sse +# tags: mcp, ai, sse, aggregator, orchestrator, middleware # category: mcp # logo: svgs/metamcp.png # port: 12008 services: app: - container_name: metamcp - image: 'ghcr.io/metatool-ai/metamcp:2.4' + image: ghcr.io/metatool-ai/metamcp:2.4 environment: - SERVICE_URL_METAMCP_12008 - POSTGRES_HOST=${POSTGRES_HOST:-postgres} - POSTGRES_PORT=${POSTGRES_PORT:-5432} - - POSTGRES_USER=${SERVICE_USER_DB} + - POSTGRES_USER=${SERVICE_USER_POSTGRES} - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} - POSTGRES_DB=${POSTGRES_DB:-metamcp_db} - - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}' - - APP_URL=$SERVICE_URL_METAMCP - - NEXT_PUBLIC_APP_URL=${APP_URL} - - BETTER_AUTH_SECRET=$SERVICE_PASSWORD_AUTH - - TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL=${TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL:?true} + - DATABASE_URL=postgresql://${SERVICE_USER_POSTGRES}:${SERVICE_PASSWORD_POSTGRES}@${POSTGRES_HOST:-postgres}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-metamcp_db} + - APP_URL=${SERVICE_URL_METAMCP} + - NEXT_PUBLIC_APP_URL=${SERVICE_URL_METAMCP} + - BETTER_AUTH_SECRET=${SERVICE_PASSWORD_AUTH} + - TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL=${TRANSFORM_LOCALHOST_TO_DOCKER_INTERNAL:-true} depends_on: postgres: condition: service_healthy @@ -30,23 +29,22 @@ services: - curl - '-f' - 'http://localhost:12008/health' - interval: 5s - timeout: 20s - retries: 10 + interval: 10s + timeout: 5s + retries: 5 + postgres: - image: 'postgres:16-alpine' - container_name: metamcp-DB + image: postgres:16-alpine environment: - - POSTGRES_DB=${POSTGRES_DB:-postgres} - - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} + - POSTGRES_DB=${POSTGRES_DB:-metamcp_db} - POSTGRES_USER=${SERVICE_USER_POSTGRES} - - POSTGRES_PORT=${POSTGRES_PORT:-5432} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} volumes: - - 'postgres_data:/var/lib/postgresql/data' + - postgres_data:/var/lib/postgresql/data healthcheck: test: - CMD-SHELL - - 'pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}' - interval: 5s - timeout: 20s - retries: 10 + - 'pg_isready -U ${SERVICE_USER_POSTGRES} -d ${POSTGRES_DB:-metamcp_db}' + interval: 10s + timeout: 5s + retries: 5 From d1ab7ebb8efbdd29c59d6345dea8c85e5e601bec Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Sun, 19 Oct 2025 20:59:24 +0200 Subject: [PATCH 015/163] Add Pocket ID template Add Docker Compose template for Pocket ID, a simple and secure OIDC provider with passkey authentication support. --- public/svgs/pocketid-logo.png | Bin 0 -> 4463 bytes templates/compose/pocket-id.yaml | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 public/svgs/pocketid-logo.png create mode 100644 templates/compose/pocket-id.yaml diff --git a/public/svgs/pocketid-logo.png b/public/svgs/pocketid-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8aa7f00f905fe5b6885b8eb2db4a8fe2a969e32c GIT binary patch literal 4463 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 Date: Sun, 19 Oct 2025 21:34:26 +0200 Subject: [PATCH 016/163] Add Pocket ID with PostgreSQL template Add variant of Pocket ID template with PostgreSQL database support for better scalability and production use. --- .../compose/pocket-id-with-postgresql.yaml | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 templates/compose/pocket-id-with-postgresql.yaml diff --git a/templates/compose/pocket-id-with-postgresql.yaml b/templates/compose/pocket-id-with-postgresql.yaml new file mode 100644 index 000000000..46760d124 --- /dev/null +++ b/templates/compose/pocket-id-with-postgresql.yaml @@ -0,0 +1,45 @@ +# documentation: https://pocket-id.org/docs/setup/installation +# slogan: A simple and secure OIDC provider with passkey authentication +# category: auth +# tags: identity,oidc,oauth,passkey,webauthn,authentication,sso,openid,postgresql +# logo: svgs/pocketid-logo.png +# port: 1411 + +services: + pocket-id: + image: ghcr.io/pocket-id/pocket-id:v1.13 + environment: + - SERVICE_URL_POCKETID_1411 + - APP_URL=${SERVICE_URL_POCKETID} + - TRUST_PROXY=${TRUST_PROXY:-true} + - DB_PROVIDER=postgres + - DB_CONNECTION_STRING=postgresql://${SERVICE_USER_POSTGRESQL}:${SERVICE_PASSWORD_POSTGRESQL}@postgresql:5432/${POSTGRES_DB:-pocketid} + - ENCRYPTION_KEY=${SERVICE_PASSWORD_64_POCKETID} + - KEYS_STORAGE=${KEYS_STORAGE:-database} + - MAXMIND_LICENSE_KEY=${MAXMIND_LICENSE_KEY} + - PUID=${PUID:-1000} + - PGID=${PGID:-1000} + volumes: + - pocket-id-data:/app/data + healthcheck: + test: ["CMD", "/app/pocket-id", "healthcheck"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s + depends_on: + postgresql: + condition: service_healthy + postgresql: + image: postgres:16-alpine + volumes: + - pocket-id-postgresql-data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${SERVICE_USER_POSTGRESQL} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRESQL} + - POSTGRES_DB=${POSTGRES_DB:-pocketid} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 5s + timeout: 20s + retries: 10 From 2ae3d1b99b0acdc8690981783fafb51261f8021f Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Sun, 19 Oct 2025 21:35:18 +0200 Subject: [PATCH 017/163] Add SMTP configuration to Pocket ID with PostgreSQL template Include SMTP settings for email notifications and one-time access features. --- templates/compose/pocket-id-with-postgresql.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/templates/compose/pocket-id-with-postgresql.yaml b/templates/compose/pocket-id-with-postgresql.yaml index 46760d124..b620bec21 100644 --- a/templates/compose/pocket-id-with-postgresql.yaml +++ b/templates/compose/pocket-id-with-postgresql.yaml @@ -17,6 +17,16 @@ services: - ENCRYPTION_KEY=${SERVICE_PASSWORD_64_POCKETID} - KEYS_STORAGE=${KEYS_STORAGE:-database} - MAXMIND_LICENSE_KEY=${MAXMIND_LICENSE_KEY} + - SMTP_HOST=${SMTP_HOST} + - SMTP_PORT=${SMTP_PORT:-587} + - SMTP_FROM=${SMTP_FROM} + - SMTP_USER=${SMTP_USER} + - SMTP_PASSWORD=${SMTP_PASSWORD} + - SMTP_TLS=${SMTP_TLS:-starttls} + - SMTP_SKIP_CERT_VERIFY=${SMTP_SKIP_CERT_VERIFY:-false} + - EMAIL_LOGIN_NOTIFICATION_ENABLED=${EMAIL_LOGIN_NOTIFICATION_ENABLED:-false} + - EMAIL_ONE_TIME_ACCESS_AS_ADMIN_ENABLED=${EMAIL_ONE_TIME_ACCESS_AS_ADMIN_ENABLED:-false} + - EMAIL_API_KEY_EXPIRATION_ENABLED=${EMAIL_API_KEY_EXPIRATION_ENABLED:-false} - PUID=${PUID:-1000} - PGID=${PGID:-1000} volumes: From 9355cb2893bc3e818722aa2c1cc1177c2783c23a Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Sun, 19 Oct 2025 21:35:49 +0200 Subject: [PATCH 018/163] Add SMTP configuration to Pocket ID template Include SMTP settings for email notifications and one-time access features. --- templates/compose/pocket-id.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/templates/compose/pocket-id.yaml b/templates/compose/pocket-id.yaml index bc4409c53..10adfd025 100644 --- a/templates/compose/pocket-id.yaml +++ b/templates/compose/pocket-id.yaml @@ -13,6 +13,16 @@ services: - APP_URL=${SERVICE_URL_POCKETID} - TRUST_PROXY=${TRUST_PROXY:-true} - MAXMIND_LICENSE_KEY=${MAXMIND_LICENSE_KEY} + - SMTP_HOST=${SMTP_HOST} + - SMTP_PORT=${SMTP_PORT:-587} + - SMTP_FROM=${SMTP_FROM} + - SMTP_USER=${SMTP_USER} + - SMTP_PASSWORD=${SMTP_PASSWORD} + - SMTP_TLS=${SMTP_TLS:-starttls} + - SMTP_SKIP_CERT_VERIFY=${SMTP_SKIP_CERT_VERIFY:-false} + - EMAIL_LOGIN_NOTIFICATION_ENABLED=${EMAIL_LOGIN_NOTIFICATION_ENABLED:-false} + - EMAIL_ONE_TIME_ACCESS_AS_ADMIN_ENABLED=${EMAIL_ONE_TIME_ACCESS_AS_ADMIN_ENABLED:-false} + - EMAIL_API_KEY_EXPIRATION_ENABLED=${EMAIL_API_KEY_EXPIRATION_ENABLED:-false} - PUID=${PUID:-1000} - PGID=${PGID:-1000} volumes: From 50be79db85aca3b79a3afba77c1258e493474ca6 Mon Sep 17 00:00:00 2001 From: Stellar Rounin Date: Sun, 19 Oct 2025 18:09:01 -0600 Subject: [PATCH 019/163] fix(service): Update image version & healthcheck start period --- templates/compose/siyuan.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/siyuan.yaml b/templates/compose/siyuan.yaml index 30f4054ed..5654465bb 100644 --- a/templates/compose/siyuan.yaml +++ b/templates/compose/siyuan.yaml @@ -6,7 +6,7 @@ services: siyuan: - image: b3log/siyuan + image: b3log/siyuan:v3.3.5 volumes: - 'siyuan_workspace:/siyuan/workspace' environment: @@ -25,4 +25,4 @@ services: interval: 15s timeout: 10s retries: 5 - start_period: 40s \ No newline at end of file + start_period: 20s \ No newline at end of file From eca0c5cb0d60bd5649182d11b056350c76217892 Mon Sep 17 00:00:00 2001 From: Ariq Pradipa Santoso Date: Mon, 20 Oct 2025 10:14:17 +0700 Subject: [PATCH 020/163] feat(templates): add sparkyfitness compose template and logo Add Docker Compose template for SparkyFitness, a comprehensive fitness tracking application, including the SVG logo and configuration for frontend, server, and database services. --- public/svgs/sparkyfitness.svg | 1 + templates/compose/sparkyfitness.yaml | 57 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 public/svgs/sparkyfitness.svg create mode 100644 templates/compose/sparkyfitness.yaml diff --git a/public/svgs/sparkyfitness.svg b/public/svgs/sparkyfitness.svg new file mode 100644 index 000000000..7f599cef1 --- /dev/null +++ b/public/svgs/sparkyfitness.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/compose/sparkyfitness.yaml b/templates/compose/sparkyfitness.yaml new file mode 100644 index 000000000..ebba66f2f --- /dev/null +++ b/templates/compose/sparkyfitness.yaml @@ -0,0 +1,57 @@ +# documentation: https://codewithcj.github.io/SparkyFitness/ +# slogan: SparkyFitness is a comprehensive fitness tracking and management application designed to help users monitor their nutrition, exercise, and body measurements. It provides tools for daily progress tracking, goal setting, and insightful reports to support a healthy lifestyle. +# category: health +# tags: sparkyfitness, fitness, health, nutrition, exercise, body measurements +# logo: svgs/sparkyfitness.svg +# port: 80 + +services: + sparkyfitness-frontend: + image: 'codewithcj/sparkyfitness:latest' + restart: always + environment: + - SERVICE_URL_SPARKYFITNESS_80 + depends_on: + - sparkyfitness-server + + sparkyfitness-server: + image: 'codewithcj/sparkyfitness_server:latest' + restart: always + environment: + SPARKY_FITNESS_LOG_LEVEL: '${SPARKY_FITNESS_LOG_LEVEL:-info}' + SPARKY_FITNESS_DB_USER: '${SERVICE_USER_POSTGRES}' + SPARKY_FITNESS_DB_HOST: sparkyfitness-db + SPARKY_FITNESS_DB_NAME: '${SPARKY_FITNESS_DB_NAME:-sparkyfitness}' + SPARKY_FITNESS_DB_PASSWORD: '${SERVICE_PASSWORD_POSTGRES}' + SPARKY_FITNESS_DB_PORT: '${SPARKY_FITNESS_DB_PORT:-5432}' + SPARKY_FITNESS_API_ENCRYPTION_KEY: '${SERVICE_PASSWORD_64_SERVERAPIENCRYPTIONKEY}' + JWT_SECRET: '${SERVICE_PASSWORD_64_SERVERJWTSECRET}' + SPARKY_FITNESS_FRONTEND_URL: '${SERVICE_URL_SPARKYFITNESS_80}' + SPARKY_FITNESS_DISABLE_SIGNUP: '${SPARKY_FITNESS_DISABLE_SIGNUP:-false}' + SPARKY_FITNESS_ADMIN_EMAIL: '${SPARKY_FITNESS_ADMIN_EMAIL:-admin@example.com}' + SPARKY_FITNESS_EMAIL_HOST: '${SPARKY_FITNESS_EMAIL_HOST:-smtp.gmail.com}' + SPARKY_FITNESS_EMAIL_PORT: '${SPARKY_FITNESS_EMAIL_PORT:-587}' + SPARKY_FITNESS_EMAIL_SECURE: '${SPARKY_FITNESS_EMAIL_SECURE:-false}' + SPARKY_FITNESS_EMAIL_USER: '${SPARKY_FITNESS_EMAIL_USER}' + SPARKY_FITNESS_EMAIL_PASS: '${SPARKY_FITNESS_EMAIL_PASS}' + SPARKY_FITNESS_EMAIL_FROM: '${SPARKY_FITNESS_EMAIL_FROM:-"Sparky Fitness "}' + depends_on: + - sparkyfitness-db + volumes: + - 'sparkyfitness-server-backup:/app/SparkyFitnessServer/backup' + - 'sparkyfitness-server-uploads:/app/SparkyFitnessServer/uploads' + + sparkyfitness-db: + image: 'postgres:15-alpine' + restart: always + environment: + POSTGRES_DB: '${SPARKY_FITNESS_DB_NAME:-sparkyfitness}' + POSTGRES_USER: '${SERVICE_USER_POSTGRES}' + POSTGRES_PASSWORD: '${SERVICE_PASSWORD_POSTGRES}' + volumes: + - 'sparkyfitness-db-postgresql:/var/lib/postgresql/data' + +volumes: + sparkyfitness-server-backup: + sparkyfitness-server-uploads: + sparkyfitness-db-postgresql: From 84559a0e7d71c05be9a123a96cf589d0719500c7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 20 Oct 2025 09:48:37 +0200 Subject: [PATCH 021/163] Changes auto-committed by Conductor --- app/Http/Middleware/TrustHosts.php | 25 ++++++ .../views/components/forms/datalist.blade.php | 10 +-- tests/Feature/TrustHostsMiddlewareTest.php | 81 +++++++++++++++++++ 3 files changed, 111 insertions(+), 5 deletions(-) diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php index c2a2cb41a..080b18acc 100644 --- a/app/Http/Middleware/TrustHosts.php +++ b/app/Http/Middleware/TrustHosts.php @@ -4,11 +4,36 @@ use App\Models\InstanceSettings; use Illuminate\Http\Middleware\TrustHosts as Middleware; +use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Spatie\Url\Url; class TrustHosts extends Middleware { + /** + * Handle the incoming request. + * + * Skip host validation for certain routes: + * - Terminal auth routes (called by realtime container) + * - API routes (use token-based authentication, not host validation) + * - Webhook endpoints (use cryptographic signature validation) + */ + public function handle(Request $request, $next) + { + // Skip host validation for these routes + if ($request->is( + 'terminal/auth', + 'terminal/auth/ips', + 'api/*', + 'webhooks/*' + )) { + return $next($request); + } + + // For all other routes, use parent's host validation + return parent::handle($request, $next); + } + /** * Get the host patterns that should be trusted. * diff --git a/resources/views/components/forms/datalist.blade.php b/resources/views/components/forms/datalist.blade.php index 5bb12aa8d..05f6ca946 100644 --- a/resources/views/components/forms/datalist.blade.php +++ b/resources/views/components/forms/datalist.blade.php @@ -106,7 +106,7 @@ class="flex flex-wrap gap-1.5 max-h-40 overflow-y-auto scrollbar py-1.5 w-full t wire:dirty.class="dark:border-l-warning border-l-coollabs border-l-4"> {{-- Selected Tags Inside Input --}} -