diff --git a/.github/workflows/lock-closed-issues-discussions-and-prs.yml b/.github/workflows/chore-lock-closed-issues-discussions-and-prs.yml
similarity index 100%
rename from .github/workflows/lock-closed-issues-discussions-and-prs.yml
rename to .github/workflows/chore-lock-closed-issues-discussions-and-prs.yml
diff --git a/.github/workflows/manage-stale-issues-and-prs.yml b/.github/workflows/chore-manage-stale-issues-and-prs.yml
similarity index 100%
rename from .github/workflows/manage-stale-issues-and-prs.yml
rename to .github/workflows/chore-manage-stale-issues-and-prs.yml
diff --git a/.github/workflows/remove-labels-and-assignees-on-close.yml b/.github/workflows/chore-remove-labels-and-assignees-on-close.yml
similarity index 100%
rename from .github/workflows/remove-labels-and-assignees-on-close.yml
rename to .github/workflows/chore-remove-labels-and-assignees-on-close.yml
diff --git a/.github/workflows/coolify-helper-next.yml b/.github/workflows/coolify-helper-next.yml
index 4add8516e..4354294b1 100644
--- a/.github/workflows/coolify-helper-next.yml
+++ b/.github/workflows/coolify-helper-next.yml
@@ -1,4 +1,4 @@
-name: Coolify Helper Image Development (v4)
+name: Coolify Helper Image Development
on:
push:
@@ -8,7 +8,8 @@ on:
- docker/coolify-helper/Dockerfile
env:
- REGISTRY: ghcr.io
+ GITHUB_REGISTRY: ghcr.io
+ DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-helper"
jobs:
@@ -19,25 +20,36 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_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
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-helper/Dockerfile
platforms: linux/amd64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next
labels: |
coolify.managed=true
aarch64:
@@ -47,27 +59,39 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_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
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-helper/Dockerfile
platforms: linux/aarch64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64
labels: |
coolify.managed=true
+
merge-manifest:
runs-on: ubuntu-latest
permissions:
@@ -75,25 +99,42 @@ jobs:
packages: write
needs: [ amd64, aarch64 ]
steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to ghcr.io
+ - uses: actions/checkout@v4
+ - uses: docker/setup-buildx-action@v3
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_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
+
+ - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
- 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
+ docker buildx imagetools create \
+ --append ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:next
+
+ - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:next
+
- uses: sarisia/actions-status-discord@v1
if: always()
with:
diff --git a/.github/workflows/coolify-helper.yml b/.github/workflows/coolify-helper.yml
index a9e8a5dd0..6d852a2b3 100644
--- a/.github/workflows/coolify-helper.yml
+++ b/.github/workflows/coolify-helper.yml
@@ -1,4 +1,4 @@
-name: Coolify Helper Image (v4)
+name: Coolify Helper Image
on:
push:
@@ -8,7 +8,8 @@ on:
- docker/coolify-helper/Dockerfile
env:
- REGISTRY: ghcr.io
+ GITHUB_REGISTRY: ghcr.io
+ DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-helper"
jobs:
@@ -19,25 +20,36 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_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
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-helper/Dockerfile
platforms: linux/amd64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
labels: |
coolify.managed=true
aarch64:
@@ -47,25 +59,36 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_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
+ 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 and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-helper/Dockerfile
platforms: linux/aarch64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
labels: |
coolify.managed=true
merge-manifest:
@@ -75,25 +98,43 @@ jobs:
packages: write
needs: [ amd64, aarch64 ]
steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to ghcr.io
+ - uses: actions/checkout@v4
+
+ - uses: docker/setup-buildx-action@v3
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_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
+ 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 on ${{ env.GITHUB_REGISTRY }}
run: |
- 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
+ docker buildx imagetools create \
+ --append ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
+ - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
- uses: sarisia/actions-status-discord@v1
if: always()
with:
diff --git a/.github/workflows/coolify-production-build.yml b/.github/workflows/coolify-production-build.yml
new file mode 100644
index 000000000..771687d4b
--- /dev/null
+++ b/.github/workflows/coolify-production-build.yml
@@ -0,0 +1,143 @@
+name: Production Build (v4)
+
+on:
+ push:
+ branches: ["main"]
+ paths-ignore:
+ - .github/workflows/coolify-helper.yml
+ - .github/workflows/coolify-helper-next.yml
+ - .github/workflows/coolify-realtime.yml
+ - .github/workflows/coolify-realtime-next.yml
+ - docker/coolify-helper/Dockerfile
+ - docker/coolify-realtime/Dockerfile
+ - docker/testing-host/Dockerfile
+ - templates/service-templates.json
+
+env:
+ GITHUB_REGISTRY: ghcr.io
+ DOCKER_REGISTRY: docker.io
+ IMAGE_NAME: "coollabsio/coolify"
+
+jobs:
+ amd64:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.GITHUB_REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Get Version
+ id: version
+ run: |
+ echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT]
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: docker/prod/Dockerfile
+ platforms: linux/amd64
+ push: true
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
+ labels: |
+ coolify.managed=true
+
+ aarch64:
+ runs-on: [self-hosted, arm64]
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.GITHUB_REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Get Version
+ id: version
+ run: |
+ echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT]
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: docker/prod/Dockerfile
+ platforms: linux/aarch64
+ push: true
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
+ labels: |
+ coolify.managed=true
+
+ merge-manifest:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ needs: [amd64, aarch64]
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: docker/setup-buildx-action@v3
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.GITHUB_REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Get Version
+ id: version
+ run: |
+ echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT
+
+ - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
+ - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
+ - uses: sarisia/actions-status-discord@v1
+ if: always()
+ with:
+ webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }}
diff --git a/.github/workflows/coolify-realtime-next.yml b/.github/workflows/coolify-realtime-next.yml
index 33e048627..7e937d17a 100644
--- a/.github/workflows/coolify-realtime-next.yml
+++ b/.github/workflows/coolify-realtime-next.yml
@@ -1,17 +1,18 @@
-name: Coolify Realtime Development (v4)
+name: Coolify Realtime Development
on:
push:
branches: [ "next" ]
paths:
- - .github/workflows/coolify-realtime.yml
+ - .github/workflows/coolify-realtime-next.yml
- docker/coolify-realtime/Dockerfile
- docker/coolify-realtime/terminal-server.js
- docker/coolify-realtime/package.json
- docker/coolify-realtime/soketi-entrypoint.sh
env:
- REGISTRY: ghcr.io
+ GITHUB_REGISTRY: ghcr.io
+ DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-realtime"
jobs:
@@ -22,27 +23,39 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-realtime/Dockerfile
platforms: linux/amd64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next
labels: |
coolify.managed=true
+
aarch64:
runs-on: [ self-hosted, arm64 ]
permissions:
@@ -50,27 +63,39 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-realtime/Dockerfile
platforms: linux/aarch64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64
labels: |
coolify.managed=true
+
merge-manifest:
runs-on: ubuntu-latest
permissions:
@@ -78,26 +103,44 @@ jobs:
packages: write
needs: [ amd64, aarch64 ]
steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to ghcr.io
+ - uses: actions/checkout@v4
+
+ - uses: docker/setup-buildx-action@v3
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT
- - name: Create & publish manifest
+
+ - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
- 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
+ docker buildx imagetools create \
+ --append ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:next
+
+ - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-aarch64 \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:next
+
- uses: sarisia/actions-status-discord@v1
if: always()
with:
- webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }}
+ webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}
diff --git a/.github/workflows/coolify-realtime.yml b/.github/workflows/coolify-realtime.yml
index 30910ae0b..97bfd52eb 100644
--- a/.github/workflows/coolify-realtime.yml
+++ b/.github/workflows/coolify-realtime.yml
@@ -1,4 +1,4 @@
-name: Coolify Realtime (v4)
+name: Coolify Realtime
on:
push:
@@ -11,7 +11,8 @@ on:
- docker/coolify-realtime/soketi-entrypoint.sh
env:
- REGISTRY: ghcr.io
+ GITHUB_REGISTRY: ghcr.io
+ DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-realtime"
jobs:
@@ -22,27 +23,39 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-realtime/Dockerfile
platforms: linux/amd64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
labels: |
coolify.managed=true
+
aarch64:
runs-on: [ self-hosted, arm64 ]
permissions:
@@ -50,27 +63,39 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/coolify-realtime/Dockerfile
platforms: linux/aarch64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
labels: |
coolify.managed=true
+
merge-manifest:
runs-on: ubuntu-latest
permissions:
@@ -78,25 +103,43 @@ jobs:
packages: write
needs: [ amd64, aarch64 ]
steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to ghcr.io
+ - uses: actions/checkout@v4
+
+ - uses: docker/setup-buildx-action@v3
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app ghcr.io/jqlang/jq:latest '.coolify.realtime.version' versions.json)"|xargs >> $GITHUB_OUTPUT
- - name: Create & publish manifest
+
+ - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
- 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
+ docker buildx imagetools create \
+ --append ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
+ - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
- uses: sarisia/actions-status-discord@v1
if: always()
with:
diff --git a/.github/workflows/coolify-staging-build.yml b/.github/workflows/coolify-staging-build.yml
new file mode 100644
index 000000000..dd5e6ebd6
--- /dev/null
+++ b/.github/workflows/coolify-staging-build.yml
@@ -0,0 +1,129 @@
+name: Staging Build
+
+on:
+ push:
+ branches-ignore: ["main", "v3"]
+ paths-ignore:
+ - .github/workflows/coolify-helper.yml
+ - .github/workflows/coolify-helper-next.yml
+ - .github/workflows/coolify-realtime.yml
+ - .github/workflows/coolify-realtime-next.yml
+ - docker/coolify-helper/Dockerfile
+ - docker/coolify-realtime/Dockerfile
+ - docker/testing-host/Dockerfile
+ - templates/service-templates.json
+
+env:
+ GITHUB_REGISTRY: ghcr.io
+ DOCKER_REGISTRY: docker.io
+ IMAGE_NAME: "coollabsio/coolify"
+
+jobs:
+ amd64:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.GITHUB_REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: docker/prod/Dockerfile
+ platforms: linux/amd64
+ push: true
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
+ labels: |
+ coolify.managed=true
+
+ aarch64:
+ runs-on: [self-hosted, arm64]
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.GITHUB_REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: docker/prod/Dockerfile
+ platforms: linux/aarch64
+ push: true
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64
+ labels: |
+ coolify.managed=true
+
+ merge-manifest:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ needs: [amd64, aarch64]
+ steps:
+ - uses: actions/checkout@v4
+
+ - uses: docker/setup-buildx-action@v3
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.GITHUB_REGISTRY }}
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64 \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
+
+ - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64 \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
+
+ - uses: sarisia/actions-status-discord@v1
+ if: always()
+ with:
+ webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}
diff --git a/.github/workflows/coolify-testing-host.yml b/.github/workflows/coolify-testing-host.yml
index 5fdc32991..95a228114 100644
--- a/.github/workflows/coolify-testing-host.yml
+++ b/.github/workflows/coolify-testing-host.yml
@@ -1,14 +1,15 @@
-name: Coolify Testing Host (v4-non-prod)
+name: Coolify Testing Host
on:
push:
- branches: [ "main", "next" ]
+ branches: [ "next" ]
paths:
- .github/workflows/coolify-testing-host.yml
- docker/testing-host/Dockerfile
env:
- REGISTRY: ghcr.io
+ GITHUB_REGISTRY: ghcr.io
+ DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-testing-host"
jobs:
@@ -19,21 +20,34 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/testing-host/Dockerfile
platforms: linux/amd64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+ labels: |
+ coolify.managed=true
+
aarch64:
runs-on: [ self-hosted, arm64 ]
permissions:
@@ -41,21 +55,34 @@ jobs:
packages: write
steps:
- uses: actions/checkout@v4
- - name: Login to ghcr.io
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Build and Push Image
+ uses: docker/build-push-action@v6
with:
- no-cache: true
context: .
file: docker/testing-host/Dockerfile
platforms: linux/aarch64
push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64
+ tags: |
+ ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64
+ ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64
+ labels: |
+ coolify.managed=true
+
merge-manifest:
runs-on: ubuntu-latest
permissions:
@@ -63,21 +90,36 @@ jobs:
packages: write
needs: [ amd64, aarch64 ]
steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to ghcr.io
+ - uses: actions/checkout@v4
+
+ - uses: docker/setup-buildx-action@v3
+
+ - name: Login to ${{ env.GITHUB_REGISTRY }}
uses: docker/login-action@v3
with:
- registry: ${{ env.REGISTRY }}
+ registry: ${{ env.GITHUB_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- - name: Create & publish manifest
+
+ - name: Login to ${{ env.DOCKER_REGISTRY }}
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ env.DOCKER_REGISTRY }}
+ username: ${{ secrets.DOCKER_USERNAME }}
+ password: ${{ secrets.DOCKER_TOKEN }}
+
+ - name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
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.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 \
+ --tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
+ - name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
+ run: |
+ docker buildx imagetools create \
+ --append ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-aarch64 \
+ --tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
+
- uses: sarisia/actions-status-discord@v1
if: always()
with:
diff --git a/.github/workflows/development-build.yml b/.github/workflows/development-build.yml
deleted file mode 100644
index 268b885ac..000000000
--- a/.github/workflows/development-build.yml
+++ /dev/null
@@ -1,79 +0,0 @@
-name: Development Build (v4)
-
-on:
- push:
- branches-ignore: ["main", "v3"]
- paths-ignore:
- - .github/workflows/coolify-helper.yml
- - docker/coolify-helper/Dockerfile
-
-env:
- REGISTRY: ghcr.io
- IMAGE_NAME: "coollabsio/coolify"
-
-jobs:
- amd64:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Login to ghcr.io
- uses: docker/login-action@v3
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
- with:
- context: .
- file: docker/prod/Dockerfile
- platforms: linux/amd64
- push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
- aarch64:
- runs-on: [self-hosted, arm64]
- permissions:
- contents: read
- packages: write
- steps:
- - uses: actions/checkout@v4
- - name: Login to ghcr.io
- uses: docker/login-action@v3
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
- with:
- context: .
- file: docker/prod/Dockerfile
- platforms: linux/aarch64
- push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64
- merge-manifest:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- needs: [amd64, aarch64]
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to ghcr.io
- uses: docker/login-action@v3
- with:
- registry: ${{ env.REGISTRY }}
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
- - name: Create & publish manifest
- run: |
- docker buildx imagetools create --append ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}-aarch64 --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
- - uses: sarisia/actions-status-discord@v1
- if: always()
- with:
- webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}
diff --git a/.github/workflows/production-build.yml b/.github/workflows/production-build.yml
deleted file mode 100644
index c78c865bf..000000000
--- a/.github/workflows/production-build.yml
+++ /dev/null
@@ -1,89 +0,0 @@
-name: Production Build (v4)
-
-on:
- push:
- branches: ["main"]
- paths-ignore:
- - .github/workflows/coolify-helper.yml
- - docker/coolify-helper/Dockerfile
- - templates/service-templates.json
-
-env:
- REGISTRY: ghcr.io
- IMAGE_NAME: "coollabsio/coolify"
-
-jobs:
- amd64:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Login to ghcr.io
- uses: docker/login-action@v3
- with:
- 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 php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
- with:
- context: .
- file: docker/prod/Dockerfile
- platforms: linux/amd64
- push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}
- aarch64:
- runs-on: [self-hosted, arm64]
- steps:
- - uses: actions/checkout@v4
- - name: Login to ghcr.io
- uses: docker/login-action@v3
- with:
- 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 php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT
- - name: Build image and push to registry
- uses: docker/build-push-action@v5
- with:
- context: .
- file: docker/prod/Dockerfile
- platforms: linux/aarch64
- push: true
- tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64
- merge-manifest:
- runs-on: ubuntu-latest
- permissions:
- contents: read
- packages: write
- needs: [amd64, aarch64]
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to ghcr.io
- uses: docker/login-action@v3
- with:
- 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 php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT
- - name: Create & publish manifest
- run: |
- 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:
- webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }}
diff --git a/app/Actions/Server/InstallDocker.php b/app/Actions/Server/InstallDocker.php
index f671f2d2a..2e1df8185 100644
--- a/app/Actions/Server/InstallDocker.php
+++ b/app/Actions/Server/InstallDocker.php
@@ -17,7 +17,7 @@ class InstallDocker
throw new \Exception('Server OS type is not supported for automated installation. Please install Docker manually before continuing: documentation.');
}
ray('Installing Docker on server: '.$server->name.' ('.$server->ip.')'.' with OS type: '.$supported_os_type);
- $dockerVersion = '24.0';
+ $dockerVersion = '26.0';
$config = base64_encode('{
"log-driver": "json-file",
"log-opts": {
diff --git a/app/Actions/Server/StartSentinel.php b/app/Actions/Server/StartSentinel.php
index b79bc8f67..e7c613eb0 100644
--- a/app/Actions/Server/StartSentinel.php
+++ b/app/Actions/Server/StartSentinel.php
@@ -2,6 +2,7 @@
namespace App\Actions\Server;
+use App\Models\InstanceSettings;
use App\Models\Server;
use Lorisleiva\Actions\Concerns\AsAction;
@@ -9,18 +10,46 @@ class StartSentinel
{
use AsAction;
- public function handle(Server $server, $version = 'latest', bool $restart = false)
+ public function handle(Server $server, $version = 'next', bool $restart = false)
{
if ($restart) {
StopSentinel::run($server);
}
- $metrics_history = $server->settings->metrics_history_days;
- $refresh_rate = $server->settings->metrics_refresh_rate_seconds;
- $token = $server->settings->metrics_token;
- instant_remote_process([
- "docker run --rm --pull always -d -e \"TOKEN={$token}\" -e \"SCHEDULER=true\" -e \"METRICS_HISTORY={$metrics_history}\" -e \"REFRESH_RATE={$refresh_rate}\" --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v /data/coolify/metrics:/app/metrics -v /data/coolify/logs:/app/logs --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 ghcr.io/coollabsio/sentinel:$version",
- 'chown -R 9999:root /data/coolify/metrics /data/coolify/logs',
- 'chmod -R 700 /data/coolify/metrics /data/coolify/logs',
+ $metrics_history = $server->settings->sentinel_metrics_history_days;
+ $refresh_rate = $server->settings->sentinel_metrics_refresh_rate_seconds;
+ $token = $server->settings->sentinel_token;
+ $endpoint = InstanceSettings::get()->fqdn;
+ if (isDev()) {
+ $endpoint = 'http://host.docker.internal:8000';
+ }
+ if (! $endpoint) {
+ throw new \Exception('You should set FQDN in Instance Settings.');
+ }
+ // Ensure the endpoint is using HTTPS
+ $endpoint = str($endpoint)->replace('http://', 'https://')->value();
+ $environments = [
+ 'TOKEN' => $token,
+ 'ENDPOINT' => $endpoint,
+ 'COLLECTOR_ENABLED' => 'true',
+ 'COLLECTOR_REFRESH_RATE_SECONDS' => $refresh_rate,
+ 'COLLECTOR_RETENTION_PERIOD_DAYS' => $metrics_history,
+ ];
+ if (isDev()) {
+ data_set($environments, 'GIN_MODE', 'debug');
+ }
+ $mount_dir = '/data/coolify/sentinel';
+ if (isDev()) {
+ $mount_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/sentinel';
+ }
+ $docker_environments = '-e "'.implode('" -e "', array_map(fn ($key, $value) => "$key=$value", array_keys($environments), $environments)).'"';
+ $docker_command = "docker run --pull always --rm -d $docker_environments --name coolify-sentinel -v /var/run/docker.sock:/var/run/docker.sock -v $mount_dir:/app/db --pid host --health-cmd \"curl --fail http://127.0.0.1:8888/api/health || exit 1\" --health-interval 10s --health-retries 3 --add-host=host.docker.internal:host-gateway ghcr.io/coollabsio/sentinel:$version";
+
+ return instant_remote_process([
+ 'docker rm -f coolify-sentinel || true',
+ "mkdir -p $mount_dir",
+ $docker_command,
+ "chown -R 9999:root $mount_dir",
+ "chmod -R 700 $mount_dir",
], $server, true);
}
}
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 1430fcdd1..6da32b461 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -38,7 +38,7 @@ class Kernel extends ConsoleKernel
$schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer();
// Server Jobs
$this->check_scheduled_backups($schedule);
- $this->check_resources($schedule);
+ // $this->check_resources($schedule);
$this->check_scheduled_tasks($schedule);
$schedule->command('uploads:clear')->everyTwoMinutes();
diff --git a/app/Http/Controllers/Api/ServersController.php b/app/Http/Controllers/Api/ServersController.php
index a49515579..6d512e578 100644
--- a/app/Http/Controllers/Api/ServersController.php
+++ b/app/Http/Controllers/Api/ServersController.php
@@ -23,7 +23,7 @@ class ServersController extends Controller
return serializeApiResponse($settings);
}
$settings = $settings->makeHidden([
- 'metrics_token',
+ 'sentinel_token',
]);
return serializeApiResponse($settings);
diff --git a/app/Jobs/PushServerUpdateJob.php b/app/Jobs/PushServerUpdateJob.php
new file mode 100644
index 000000000..e029a3bf5
--- /dev/null
+++ b/app/Jobs/PushServerUpdateJob.php
@@ -0,0 +1,364 @@
+containers = collect();
+ $this->foundApplicationIds = collect();
+ $this->foundDatabaseUuids = collect();
+ $this->foundServiceApplicationIds = collect();
+ $this->foundApplicationPreviewsIds = collect();
+ $this->foundServiceDatabaseIds = collect();
+ $this->allApplicationIds = collect();
+ $this->allDatabaseUuids = collect();
+ $this->allTcpProxyUuids = collect();
+ $this->allServiceApplicationIds = collect();
+ $this->allServiceDatabaseIds = collect();
+ }
+
+ public function handle()
+ {
+ try {
+ if (! $this->data) {
+ throw new \Exception('No data provided');
+ }
+ $data = collect($this->data);
+ $this->containers = collect(data_get($data, 'containers'));
+ if ($this->containers->isEmpty()) {
+ return;
+ }
+ $this->applications = $this->server->applications();
+ $this->databases = $this->server->databases();
+ $this->previews = $this->server->previews();
+ $this->services = $this->server->services()->get();
+ $this->allApplicationIds = $this->applications->filter(function ($application) {
+ return $application->additional_servers->count() === 0;
+ })->pluck('id');
+ $this->allApplicationsWithAdditionalServers = $this->applications->filter(function ($application) {
+ return $application->additional_servers->count() > 0;
+ });
+ $this->allApplicationPreviewsIds = $this->previews->pluck('id');
+ $this->allDatabaseUuids = $this->databases->pluck('uuid');
+ $this->allTcpProxyUuids = $this->databases->where('is_public', true)->pluck('uuid');
+ $this->services->each(function ($service) {
+ $service->applications()->pluck('id')->each(function ($applicationId) {
+ $this->allServiceApplicationIds->push($applicationId);
+ });
+ $service->databases()->pluck('id')->each(function ($databaseId) {
+ $this->allServiceDatabaseIds->push($databaseId);
+ });
+ });
+
+ ray('allServiceApplicationIds', ['allServiceApplicationIds' => $this->allServiceApplicationIds]);
+
+ foreach ($this->containers as $container) {
+ $containerStatus = data_get($container, 'state', 'exited');
+ $containerHealth = data_get($container, 'health_status', 'unhealthy');
+ $containerStatus = "$containerStatus ($containerHealth)";
+ $labels = collect(data_get($container, 'labels'));
+ $coolify_managed = $labels->has('coolify.managed');
+ if ($coolify_managed) {
+ if ($labels->has('coolify.applicationId')) {
+ $applicationId = $labels->get('coolify.applicationId');
+ $pullRequestId = data_get($labels, 'coolify.pullRequestId', '0');
+ try {
+ if ($pullRequestId === '0') {
+ if ($this->allApplicationIds->contains($applicationId) && $this->isRunning($containerStatus)) {
+ $this->foundApplicationIds->push($applicationId);
+ }
+ $this->updateApplicationStatus($applicationId, $containerStatus);
+ } else {
+ if ($this->allApplicationPreviewsIds->contains($applicationId) && $this->isRunning($containerStatus)) {
+ $this->foundApplicationPreviewsIds->push($applicationId);
+ }
+ $this->updateApplicationPreviewStatus($applicationId, $containerStatus);
+ }
+ } catch (\Exception $e) {
+ ray()->error($e);
+ }
+ } elseif ($labels->has('coolify.serviceId')) {
+ $serviceId = $labels->get('coolify.serviceId');
+ $subType = $labels->get('coolify.service.subType');
+ $subId = $labels->get('coolify.service.subId');
+ if ($subType === 'application' && $this->isRunning($containerStatus)) {
+ $this->foundServiceApplicationIds->push($subId);
+ $this->updateServiceSubStatus($serviceId, $subType, $subId, $containerStatus);
+ } elseif ($subType === 'database' && $this->isRunning($containerStatus)) {
+ $this->foundServiceDatabaseIds->push($subId);
+ $this->updateServiceSubStatus($serviceId, $subType, $subId, $containerStatus);
+ }
+
+ } else {
+ $name = data_get($container, 'name');
+ $uuid = $labels->get('com.docker.compose.service');
+ $type = $labels->get('coolify.type');
+ if ($name === 'coolify-proxy' && $this->isRunning($containerStatus)) {
+ $this->foundProxy = true;
+ } elseif ($type === 'service' && $this->isRunning($containerStatus)) {
+ ray("Service: $uuid, $containerStatus");
+ } else {
+ if ($this->allDatabaseUuids->contains($uuid) && $this->isRunning($containerStatus)) {
+ $this->foundDatabaseUuids->push($uuid);
+ if ($this->allTcpProxyUuids->contains($uuid) && $this->isRunning($containerStatus)) {
+ $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: true);
+ } else {
+ $this->updateDatabaseStatus($uuid, $containerStatus, tcpProxy: false);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ $this->updateProxyStatus();
+
+ $this->updateNotFoundApplicationStatus();
+ $this->updateNotFoundApplicationPreviewStatus();
+ $this->updateNotFoundDatabaseStatus();
+ $this->updateNotFoundServiceStatus();
+
+ $this->updateAdditionalServersStatus();
+ } catch (\Exception $e) {
+ throw $e;
+ }
+
+ }
+
+ private function updateApplicationStatus(string $applicationId, string $containerStatus)
+ {
+ $application = $this->applications->where('id', $applicationId)->first();
+ if (! $application) {
+ return;
+ }
+ $application->status = $containerStatus;
+ $application->save();
+ ray('Application updated', ['application_id' => $applicationId, 'status' => $containerStatus]);
+ }
+
+ private function updateApplicationPreviewStatus(string $applicationId, string $containerStatus)
+ {
+ $application = $this->previews->where('id', $applicationId)->first();
+ if (! $application) {
+ return;
+ }
+ $application->status = $containerStatus;
+ $application->save();
+ ray('Application preview updated', ['application_id' => $applicationId, 'status' => $containerStatus]);
+ }
+
+ private function updateNotFoundApplicationStatus()
+ {
+ $notFoundApplicationIds = $this->allApplicationIds->diff($this->foundApplicationIds);
+ if ($notFoundApplicationIds->isNotEmpty()) {
+ ray('Not found application ids', ['application_ids' => $notFoundApplicationIds]);
+ $notFoundApplicationIds->each(function ($applicationId) {
+ ray('Updating application status', ['application_id' => $applicationId, 'status' => 'exited']);
+ $application = Application::find($applicationId);
+ if ($application) {
+ $application->status = 'exited';
+ $application->save();
+ ray('Application status updated', ['application_id' => $applicationId, 'status' => 'exited']);
+ }
+ });
+ }
+ }
+
+ private function updateNotFoundApplicationPreviewStatus()
+ {
+ $notFoundApplicationPreviewsIds = $this->allApplicationPreviewsIds->diff($this->foundApplicationPreviewsIds);
+ if ($notFoundApplicationPreviewsIds->isNotEmpty()) {
+ ray('Not found application previews ids', ['application_previews_ids' => $notFoundApplicationPreviewsIds]);
+ $notFoundApplicationPreviewsIds->each(function ($applicationPreviewId) {
+ ray('Updating application preview status', ['application_preview_id' => $applicationPreviewId, 'status' => 'exited']);
+ $applicationPreview = ApplicationPreview::find($applicationPreviewId);
+ if ($applicationPreview) {
+ $applicationPreview->status = 'exited';
+ $applicationPreview->save();
+ ray('Application preview status updated', ['application_preview_id' => $applicationPreviewId, 'status' => 'exited']);
+ }
+ });
+ }
+ }
+
+ private function updateProxyStatus()
+ {
+ // If proxy is not found, start it
+ if (! $this->foundProxy && $this->server->isProxyShouldRun()) {
+ ray('Proxy not found, starting it.');
+ StartProxy::dispatch($this->server);
+ }
+
+ }
+
+ private function updateDatabaseStatus(string $databaseUuid, string $containerStatus, bool $tcpProxy = false)
+ {
+ $database = $this->databases->where('uuid', $databaseUuid)->first();
+ if (! $database) {
+ return;
+ }
+ $database->status = $containerStatus;
+ $database->save();
+ ray('Database status updated', ['database_uuid' => $databaseUuid, 'status' => $containerStatus]);
+ if ($this->isRunning($containerStatus) && $tcpProxy) {
+ $tcpProxyContainerFound = $this->containers->filter(function ($value, $key) use ($databaseUuid) {
+ return data_get($value, 'name') === "$databaseUuid-proxy" && data_get($value, 'state') === 'running';
+ })->first();
+ if (! $tcpProxyContainerFound) {
+ ray('Starting TCP proxy for database', ['database_uuid' => $databaseUuid]);
+ StartDatabaseProxy::dispatch($database);
+ } else {
+ ray('TCP proxy for database found in containers', ['database_uuid' => $databaseUuid]);
+ }
+ }
+ }
+
+ private function updateNotFoundDatabaseStatus()
+ {
+ $notFoundDatabaseUuids = $this->allDatabaseUuids->diff($this->foundDatabaseUuids);
+ if ($notFoundDatabaseUuids->isNotEmpty()) {
+ ray('Not found database uuids', ['database_uuids' => $notFoundDatabaseUuids]);
+ $notFoundDatabaseUuids->each(function ($databaseUuid) {
+ ray('Updating database status', ['database_uuid' => $databaseUuid, 'status' => 'exited']);
+ $database = $this->databases->where('uuid', $databaseUuid)->first();
+ if ($database) {
+ $database->status = 'exited';
+ $database->save();
+ ray('Database status updated', ['database_uuid' => $databaseUuid, 'status' => 'exited']);
+ ray('Database is public', ['database_uuid' => $databaseUuid, 'is_public' => $database->is_public]);
+ if ($database->is_public) {
+ ray('Stopping TCP proxy for database', ['database_uuid' => $databaseUuid]);
+ StopDatabaseProxy::dispatch($database);
+ }
+ }
+ });
+ }
+ }
+
+ private function updateServiceSubStatus(string $serviceId, string $subType, string $subId, string $containerStatus)
+ {
+ $service = $this->services->where('id', $serviceId)->first();
+ if (! $service) {
+ return;
+ }
+ if ($subType === 'application') {
+ $application = $service->applications()->where('id', $subId)->first();
+ $application->status = $containerStatus;
+ $application->save();
+ ray('Service application updated', ['service_id' => $serviceId, 'sub_type' => $subType, 'sub_id' => $subId, 'status' => $containerStatus]);
+ } elseif ($subType === 'database') {
+ $database = $service->databases()->where('id', $subId)->first();
+ $database->status = $containerStatus;
+ $database->save();
+ ray('Service database updated', ['service_id' => $serviceId, 'sub_type' => $subType, 'sub_id' => $subId, 'status' => $containerStatus]);
+ } else {
+ ray()->warning('Unknown sub type', ['service_id' => $serviceId, 'sub_type' => $subType, 'sub_id' => $subId, 'status' => $containerStatus]);
+ }
+ }
+
+ private function updateNotFoundServiceStatus()
+ {
+ $notFoundServiceApplicationIds = $this->allServiceApplicationIds->diff($this->foundServiceApplicationIds);
+ $notFoundServiceDatabaseIds = $this->allServiceDatabaseIds->diff($this->foundServiceDatabaseIds);
+ if ($notFoundServiceApplicationIds->isNotEmpty()) {
+ ray('Not found service application ids', ['service_application_ids' => $notFoundServiceApplicationIds]);
+ $notFoundServiceApplicationIds->each(function ($serviceApplicationId) {
+ ray('Updating service application status', ['service_application_id' => $serviceApplicationId, 'status' => 'exited']);
+ $application = ServiceApplication::find($serviceApplicationId);
+ if ($application) {
+ $application->status = 'exited';
+ $application->save();
+ ray('Service application status updated', ['service_application_id' => $serviceApplicationId, 'status' => 'exited']);
+ }
+ });
+ }
+ if ($notFoundServiceDatabaseIds->isNotEmpty()) {
+ ray('Not found service database ids', ['service_database_ids' => $notFoundServiceDatabaseIds]);
+ $notFoundServiceDatabaseIds->each(function ($serviceDatabaseId) {
+ ray('Updating service database status', ['service_database_id' => $serviceDatabaseId, 'status' => 'exited']);
+ $database = ServiceDatabase::find($serviceDatabaseId);
+ if ($database) {
+ $database->status = 'exited';
+ $database->save();
+ ray('Service database status updated', ['service_database_id' => $serviceDatabaseId, 'status' => 'exited']);
+ }
+ });
+ }
+ }
+
+ private function updateAdditionalServersStatus()
+ {
+ $this->allApplicationsWithAdditionalServers->each(function ($application) {
+ ray('Updating additional servers status for application', ['application_id' => $application->id]);
+ ComplexStatusCheck::run($application);
+ });
+ }
+
+ private function isRunning(string $containerStatus)
+ {
+ return str($containerStatus)->contains('running');
+ }
+}
diff --git a/app/Livewire/Project/Index.php b/app/Livewire/Project/Index.php
index 0e4f15a5c..f8eb838be 100644
--- a/app/Livewire/Project/Index.php
+++ b/app/Livewire/Project/Index.php
@@ -18,7 +18,11 @@ class Index extends Component
public function mount()
{
$this->private_keys = PrivateKey::ownedByCurrentTeam()->get();
- $this->projects = Project::ownedByCurrentTeam()->get();
+ $this->projects = Project::ownedByCurrentTeam()->get()->map(function ($project) {
+ $project->settingsRoute = route('project.edit', ['project_uuid' => $project->uuid]);
+
+ return $project;
+ });
$this->servers = Server::ownedByCurrentTeam()->count();
}
diff --git a/app/Livewire/Project/Resource/Index.php b/app/Livewire/Project/Resource/Index.php
index 71ce2c356..283496887 100644
--- a/app/Livewire/Project/Resource/Index.php
+++ b/app/Livewire/Project/Resource/Index.php
@@ -32,8 +32,11 @@ class Index extends Component
public $services = [];
+ public array $parameters;
+
public function mount()
{
+ $this->parameters = get_route_parameters();
$project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first();
if (! $project) {
return redirect()->route('dashboard');
@@ -44,7 +47,6 @@ class Index extends Component
}
$this->project = $project;
$this->environment = $environment;
-
$this->applications = $this->environment->applications->load(['tags']);
$this->applications = $this->applications->map(function ($application) {
if (data_get($application, 'environment.project.uuid')) {
diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php
index fe7fc6020..0bb7e4742 100644
--- a/app/Livewire/Server/Form.php
+++ b/app/Livewire/Server/Form.php
@@ -7,6 +7,7 @@ use App\Actions\Server\StopSentinel;
use App\Jobs\DockerCleanupJob;
use App\Jobs\PullSentinelImageJob;
use App\Models\Server;
+use Illuminate\Support\Facades\Http;
use Livewire\Component;
class Form extends Component
@@ -54,9 +55,9 @@ class Form extends Component
'server.settings.concurrent_builds' => 'required|integer|min:1',
'server.settings.dynamic_timeout' => 'required|integer|min:1',
'server.settings.is_metrics_enabled' => 'required|boolean',
- 'server.settings.metrics_token' => 'required',
- 'server.settings.metrics_refresh_rate_seconds' => 'required|integer|min:1',
- 'server.settings.metrics_history_days' => 'required|integer|min:1',
+ 'server.settings.sentinel_token' => 'required',
+ 'server.settings.sentinel_metrics_refresh_rate_seconds' => 'required|integer|min:1',
+ 'server.settings.sentinel_metrics_history_days' => 'required|integer|min:1',
'wildcard_domain' => 'nullable|url',
'server.settings.is_server_api_enabled' => 'required|boolean',
'server.settings.server_timezone' => 'required|string|timezone',
@@ -81,9 +82,9 @@ class Form extends Component
'server.settings.concurrent_builds' => 'Concurrent Builds',
'server.settings.dynamic_timeout' => 'Dynamic Timeout',
'server.settings.is_metrics_enabled' => 'Metrics',
- 'server.settings.metrics_token' => 'Metrics Token',
- 'server.settings.metrics_refresh_rate_seconds' => 'Metrics Interval',
- 'server.settings.metrics_history_days' => 'Metrics History',
+ 'server.settings.sentinel_token' => 'Metrics Token',
+ 'server.settings.sentinel_metrics_refresh_rate_seconds' => 'Metrics Interval',
+ 'server.settings.sentinel_metrics_history_days' => 'Metrics History',
'server.settings.is_server_api_enabled' => 'Server API',
'server.settings.server_timezone' => 'Server Timezone',
'server.settings.delete_unused_volumes' => 'Delete Unused Volumes',
@@ -101,6 +102,17 @@ class Form extends Component
$this->server->settings->delete_unused_networks = $server->settings->delete_unused_networks;
}
+ public function regenerateSentinelToken()
+ {
+ try {
+ $this->server->generateSentinelToken();
+ $this->server->settings->refresh();
+ $this->dispatch('success', 'Metrics token regenerated.');
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+
public function updated($field)
{
if ($field === 'server.settings.docker_cleanup_frequency') {
@@ -174,6 +186,29 @@ class Form extends Component
}
}
+ public function getPushData()
+ {
+ try {
+ if (! isDev()) {
+ throw new \Exception('This feature is only available in dev mode.');
+ }
+ $response = Http::withHeaders([
+ 'Authorization' => 'Bearer '.$this->server->settings->sentinel_token,
+ ])->post('http://host.docker.internal:8888/api/push', [
+ 'data' => 'test',
+ ]);
+ if ($response->successful()) {
+ $this->dispatch('success', 'Push data sent.');
+
+ return;
+ }
+ $error = data_get($response->json(), 'error');
+ throw new \Exception($error);
+ } catch (\Throwable $e) {
+ return handleError($e, $this);
+ }
+ }
+
public function restartSentinel()
{
try {
@@ -254,6 +289,7 @@ class Form extends Component
return handleError($e, $this);
}
}
+
public function manualCleanup()
{
try {
@@ -271,4 +307,10 @@ class Form extends Component
$this->server->refresh();
$this->dispatch('success', 'Cloudflare Tunnels enabled.');
}
+
+ public function startSentinel()
+ {
+ StartSentinel::run($this->server);
+ $this->dispatch('success', 'Sentinel started.');
+ }
}
diff --git a/app/Livewire/Source/Github/Create.php b/app/Livewire/Source/Github/Create.php
index f85e8646e..103c5c9fb 100644
--- a/app/Livewire/Source/Github/Create.php
+++ b/app/Livewire/Source/Github/Create.php
@@ -23,7 +23,7 @@ class Create extends Component
public function mount()
{
- $this->name = generate_random_name();
+ $this->name = substr(generate_random_name(), 0, 34); // GitHub Apps names can only be 34 characters long
}
public function createGitHubApp()
diff --git a/app/Models/Application.php b/app/Models/Application.php
index 07aeb4c5b..10ef8079c 100644
--- a/app/Models/Application.php
+++ b/app/Models/Application.php
@@ -1406,7 +1406,7 @@ class Application extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/InstanceSettings.php b/app/Models/InstanceSettings.php
index bb3d1478b..3ee142050 100644
--- a/app/Models/InstanceSettings.php
+++ b/app/Models/InstanceSettings.php
@@ -21,6 +21,7 @@ class InstanceSettings extends Model implements SendsEmail
'is_auto_update_enabled' => 'boolean',
'auto_update_frequency' => 'string',
'update_check_frequency' => 'string',
+ 'sentinel_token' => 'encrypted',
];
public function fqdn(): Attribute
diff --git a/app/Models/Server.php b/app/Models/Server.php
index 0eca3c168..9e947c20b 100644
--- a/app/Models/Server.php
+++ b/app/Models/Server.php
@@ -525,6 +525,19 @@ $schema://$host {
Storage::disk('ssh-mux')->delete($this->muxFilename());
}
+ public function generateSentinelToken()
+ {
+ $data = [
+ 'server_uuid' => $this->uuid,
+ ];
+ $token = json_encode($data);
+ $encrypted = encrypt($token);
+ $this->settings->sentinel_token = $encrypted;
+ $this->settings->save();
+
+ return $encrypted;
+ }
+
public function isSentinelEnabled()
{
return $this->isMetricsEnabled() || $this->isServerApiEnabled();
@@ -555,7 +568,6 @@ $schema://$host {
ray($process->exitCode(), $process->output(), $process->errorOutput());
throw new \Exception("Server API is not reachable on http://{$server_ip}:12172");
}
-
}
}
@@ -579,7 +591,7 @@ $schema://$host {
{
if ($this->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $cpu = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$this->settings->metrics_token}\" http://localhost:8888/api/cpu/history?from=$from'"], $this, false);
+ $cpu = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$this->settings->sentinel_token}\" http://localhost:8888/api/cpu/history?from=$from'"], $this, false);
if (str($cpu)->contains('error')) {
$error = json_decode($cpu, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
@@ -606,7 +618,7 @@ $schema://$host {
{
if ($this->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $memory = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$this->settings->metrics_token}\" http://localhost:8888/api/memory/history?from=$from'"], $this, false);
+ $memory = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$this->settings->sentinel_token}\" http://localhost:8888/api/memory/history?from=$from'"], $this, false);
if (str($memory)->contains('error')) {
$error = json_decode($memory, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
@@ -977,7 +989,8 @@ $schema://$host {
public function isProxyShouldRun()
{
- if ($this->proxyType() === ProxyTypes::NONE->value || $this->settings->is_build_server) {
+ // TODO: Do we need "|| $this->proxy->force_stop" here?
+ if ($this->proxyType() === ProxyTypes::NONE->value || $this->isBuildServer()) {
return false;
}
diff --git a/app/Models/ServerSetting.php b/app/Models/ServerSetting.php
index c44a393b4..f5e0f7b0b 100644
--- a/app/Models/ServerSetting.php
+++ b/app/Models/ServerSetting.php
@@ -35,9 +35,9 @@ use OpenApi\Attributes as OA;
'logdrain_highlight_project_id' => ['type' => 'string'],
'logdrain_newrelic_base_uri' => ['type' => 'string'],
'logdrain_newrelic_license_key' => ['type' => 'string'],
- 'metrics_history_days' => ['type' => 'integer'],
- 'metrics_refresh_rate_seconds' => ['type' => 'integer'],
- 'metrics_token' => ['type' => 'string'],
+ 'sentinel_metrics_history_days' => ['type' => 'integer'],
+ 'sentinel_metrics_refresh_rate_seconds' => ['type' => 'integer'],
+ 'sentinel_token' => ['type' => 'string'],
'docker_cleanup_frequency' => ['type' => 'string'],
'docker_cleanup_threshold' => ['type' => 'integer'],
'server_id' => ['type' => 'integer'],
@@ -53,6 +53,7 @@ class ServerSetting extends Model
protected $casts = [
'force_docker_cleanup' => 'boolean',
'docker_cleanup_threshold' => 'integer',
+ 'sentinel_token' => 'encrypted',
];
public function server()
diff --git a/app/Models/StandaloneClickhouse.php b/app/Models/StandaloneClickhouse.php
index e4341b1b9..6274f51b2 100644
--- a/app/Models/StandaloneClickhouse.php
+++ b/app/Models/StandaloneClickhouse.php
@@ -272,7 +272,7 @@ class StandaloneClickhouse extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/StandaloneDragonfly.php b/app/Models/StandaloneDragonfly.php
index 94ab2d745..3555e7afd 100644
--- a/app/Models/StandaloneDragonfly.php
+++ b/app/Models/StandaloneDragonfly.php
@@ -272,7 +272,7 @@ class StandaloneDragonfly extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/StandaloneKeydb.php b/app/Models/StandaloneKeydb.php
index 335c8931c..4725ca533 100644
--- a/app/Models/StandaloneKeydb.php
+++ b/app/Models/StandaloneKeydb.php
@@ -272,7 +272,7 @@ class StandaloneKeydb extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/StandaloneMariadb.php b/app/Models/StandaloneMariadb.php
index c6c08dee5..8f1a2c1ee 100644
--- a/app/Models/StandaloneMariadb.php
+++ b/app/Models/StandaloneMariadb.php
@@ -272,7 +272,7 @@ class StandaloneMariadb extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php
index 99893b1d1..41b2ce9eb 100644
--- a/app/Models/StandaloneMongodb.php
+++ b/app/Models/StandaloneMongodb.php
@@ -292,7 +292,7 @@ class StandaloneMongodb extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/StandaloneMysql.php b/app/Models/StandaloneMysql.php
index f2a5b5c14..da2ac070f 100644
--- a/app/Models/StandaloneMysql.php
+++ b/app/Models/StandaloneMysql.php
@@ -273,7 +273,7 @@ class StandaloneMysql extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php
index 1b18a5ca7..e0f42269d 100644
--- a/app/Models/StandalonePostgresql.php
+++ b/app/Models/StandalonePostgresql.php
@@ -274,7 +274,7 @@ class StandalonePostgresql extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php
index a5868e243..fe9f6dfc7 100644
--- a/app/Models/StandaloneRedis.php
+++ b/app/Models/StandaloneRedis.php
@@ -268,7 +268,7 @@ class StandaloneRedis extends BaseModel
$container_name = $this->uuid;
if ($server->isMetricsEnabled()) {
$from = now()->subMinutes($mins)->toIso8601ZuluString();
- $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->metrics_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
+ $metrics = instant_remote_process(["docker exec coolify-sentinel sh -c 'curl -H \"Authorization: Bearer {$server->settings->sentinel_token}\" http://localhost:8888/api/container/{$container_name}/metrics/history?from=$from'"], $server, false);
if (str($metrics)->contains('error')) {
$error = json_decode($metrics, true);
$error = data_get($error, 'error', 'Something is not okay, are you okay?');
diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php
index 309ccee4a..e2693a2cd 100644
--- a/bootstrap/helpers/proxy.php
+++ b/bootstrap/helpers/proxy.php
@@ -241,6 +241,7 @@ function generate_default_proxy_configuration(Server $server)
'ports' => [
'80:80',
'443:443',
+ '443:443/udp',
],
'labels' => [
'coolify.managed=true',
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index ea9d6ff3c..86c6def76 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -1338,13 +1338,6 @@ function isAnyDeploymentInprogress()
exit(0);
}
-function generateSentinelToken()
-{
- $token = Str::random(64);
-
- return $token;
-}
-
function isBase64Encoded($strValue)
{
return base64_encode(base64_decode($strValue, true)) === $strValue;
diff --git a/composer.json b/composer.json
index 7bb2b761a..fbd77d0cf 100644
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,7 @@
"lcobucci/jwt": "^5.0.0",
"league/flysystem-aws-s3-v3": "^3.0",
"league/flysystem-sftp-v3": "^3.0",
- "livewire/livewire": "3.5.2",
+ "livewire/livewire": "3.4.9",
"log1x/laravel-webfonts": "^1.0",
"lorisleiva/laravel-actions": "^2.7",
"nubs/random-name-generator": "^2.2",
diff --git a/composer.lock b/composer.lock
index e0456481c..0b8da82d0 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "e6b8a44dc3fbcd52d0d5b17628efac99",
+ "content-hash": "c47adf3684eb727e22503937435c0914",
"packages": [
{
"name": "amphp/amp",
@@ -4402,16 +4402,16 @@
},
{
"name": "livewire/livewire",
- "version": "v3.5.2",
+ "version": "v3.4.9",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
- "reference": "636725c1f87bc7844dd80277488268db27eec1aa"
+ "reference": "c65b3f0798ab2c9338213ede3588c3cdf4e6fcc0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/livewire/livewire/zipball/636725c1f87bc7844dd80277488268db27eec1aa",
- "reference": "636725c1f87bc7844dd80277488268db27eec1aa",
+ "url": "https://api.github.com/repos/livewire/livewire/zipball/c65b3f0798ab2c9338213ede3588c3cdf4e6fcc0",
+ "reference": "c65b3f0798ab2c9338213ede3588c3cdf4e6fcc0",
"shasum": ""
},
"require": {
@@ -4421,16 +4421,15 @@
"illuminate/validation": "^10.0|^11.0",
"league/mime-type-detection": "^1.9",
"php": "^8.1",
- "symfony/console": "^6.0|^7.0",
"symfony/http-kernel": "^6.2|^7.0"
},
"require-dev": {
"calebporzio/sushi": "^2.1",
- "laravel/framework": "^10.15.0|^11.0",
+ "laravel/framework": "^10.0|^11.0",
"laravel/prompts": "^0.1.6",
"mockery/mockery": "^1.3.1",
- "orchestra/testbench": "^8.21.0|^9.0",
- "orchestra/testbench-dusk": "^8.24|^9.1",
+ "orchestra/testbench": "8.20.0|^9.0",
+ "orchestra/testbench-dusk": "8.20.0|^9.0",
"phpunit/phpunit": "^10.4",
"psy/psysh": "^0.11.22|^0.12"
},
@@ -4466,7 +4465,7 @@
"description": "A front-end framework for Laravel.",
"support": {
"issues": "https://github.com/livewire/livewire/issues",
- "source": "https://github.com/livewire/livewire/tree/v3.5.2"
+ "source": "https://github.com/livewire/livewire/tree/v3.4.9"
},
"funding": [
{
@@ -4474,7 +4473,7 @@
"type": "github"
}
],
- "time": "2024-07-03T17:22:45+00:00"
+ "time": "2024-03-14T14:03:32+00:00"
},
{
"name": "log1x/laravel-webfonts",
diff --git a/config/sentry.php b/config/sentry.php
index cf1271119..e8b6ab098 100644
--- a/config/sentry.php
+++ b/config/sentry.php
@@ -7,7 +7,8 @@ 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.360',
+ 'release' => '4.0.0-beta.361',
+
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),
diff --git a/config/version.php b/config/version.php
index 305c873ce..0e83ff40e 100644
--- a/config/version.php
+++ b/config/version.php
@@ -1,3 +1,3 @@
boolean('is_metrics_enabled')->default(false);
$table->integer('metrics_refresh_rate_seconds')->default(5);
$table->integer('metrics_history_days')->default(30);
- $table->string('metrics_token')->default(generateSentinelToken());
+ $table->string('metrics_token')->nullable();
});
}
diff --git a/database/migrations/2024_10_14_090416_update_metrics_token_in_server_settings.php b/database/migrations/2024_10_14_090416_update_metrics_token_in_server_settings.php
new file mode 100644
index 000000000..21c871cf4
--- /dev/null
+++ b/database/migrations/2024_10_14_090416_update_metrics_token_in_server_settings.php
@@ -0,0 +1,44 @@
+dropColumn('metrics_token');
+ $table->dropColumn('metrics_refresh_rate_seconds');
+ $table->dropColumn('metrics_history_days');
+ $table->text('sentinel_token')->nullable();
+ $table->integer('sentinel_metrics_refresh_rate_seconds')->default(5);
+ $table->integer('sentinel_metrics_history_days')->default(30);
+ });
+ Schema::table('servers', function (Blueprint $table) {
+ $table->dateTime('sentinel_update_at')->default(now());
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('server_settings', function (Blueprint $table) {
+ $table->string('metrics_token')->nullable();
+ $table->integer('metrics_refresh_rate_seconds')->default(5);
+ $table->integer('metrics_history_days')->default(30);
+ $table->dropColumn('sentinel_token');
+ $table->dropColumn('sentinel_metrics_refresh_rate_seconds');
+ $table->dropColumn('sentinel_metrics_history_days');
+ });
+ Schema::table('servers', function (Blueprint $table) {
+ $table->dropColumn('sentinel_update_at');
+ });
+ }
+};
diff --git a/lang/ar.json b/lang/ar.json
index c5ec96c8d..4b9afbe99 100644
--- a/lang/ar.json
+++ b/lang/ar.json
@@ -26,5 +26,12 @@
"input.code": "الرمز لمرة واحدة",
"input.recovery_code": "رمز الاسترداد",
"button.save": "حفظ",
- "repository.url": "أمثلة
للمستودعات العامة، استخدم https://....
للمستودعات الخاصة، استخدم git@....
سيتم تحديد الفرع main لـ https://github.com/coollabsio/coolify-examples
سيتم تحديد الفرع nodejs-fastify لـ https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify
سيتم تحديد الفرع main لـ https://gitea.com/sedlav/expressjs.git
سيتم تحديد الفرع main لـ https://gitlab.com/andrasbacsai/nodejs-example.git."
+ "repository.url": "أمثلة
للمستودعات العامة، استخدم https://....
للمستودعات الخاصة، استخدم git@....
سيتم تحديد الفرع main لـ https://github.com/coollabsio/coolify-examples
سيتم تحديد الفرع nodejs-fastify لـ https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify
سيتم تحديد الفرع main لـ https://gitea.com/sedlav/expressjs.git
سيتم تحديد الفرع main لـ https://gitlab.com/andrasbacsai/nodejs-example.git.",
+ "service.stop": "سيتم إيقاف هذه الخدمة.",
+ "resource.docker_cleanup": "قم بتشغيل Docker Cleanup (قم بإزالة الصور غير المستخدمة وذاكرة التخزين المؤقت للمنشئ).",
+ "resource.non_persistent": "سيتم حذف جميع البيانات غير الدائمة.",
+ "resource.delete_volumes": "حذف جميع المجلدات والملفات المرتبطة بهذا المورد بشكل دائم.",
+ "resource.delete_connected_networks": "حذف جميع الشبكات غير المحددة مسبقًا والمرتبطة بهذا المورد بشكل دائم.",
+ "resource.delete_configurations": "حذف جميع ملفات التعريف من الخادم بشكل دائم.",
+ "database.delete_backups_locally": "حذف كافة النسخ الاحتياطية نهائيًا من التخزين المحلي."
}
diff --git a/lang/ro.json b/lang/ro.json
new file mode 100644
index 000000000..db1aa85db
--- /dev/null
+++ b/lang/ro.json
@@ -0,0 +1,37 @@
+{
+ "auth.login": "Autentificare",
+ "auth.login.azure": "Autentificare prin Microsoft",
+ "auth.login.bitbucket": "Autentificare prin Bitbucket",
+ "auth.login.github": "Autentificare prin GitHub",
+ "auth.login.gitlab": "Autentificare prin Gitlab",
+ "auth.login.google": "Autentificare prin Google",
+ "auth.already_registered": "Sunteți deja înregistrat?",
+ "auth.confirm_password": "Confirmați parola",
+ "auth.forgot_password": "Ați uitat parola",
+ "auth.forgot_password_send_email": "Trimiteți e-mail-ul pentru resetarea parolei",
+ "auth.register_now": "Înregistrare",
+ "auth.logout": "Deconectare",
+ "auth.register": "Înregistrare",
+ "auth.registration_disabled": "Înregistrarea este dezactivată. Vă rugăm să contactați administratorul site-ului.",
+ "auth.reset_password": "Resetare parolă",
+ "auth.failed": "Autentificare nereușită. Vă rugăm să verificați datele introduse.",
+ "auth.failed.callback": "A apărut o eroare în timpul autentificării cu furnizorul extern.",
+ "auth.failed.password": "Parola furnizată este incorectă.",
+ "auth.failed.email": "Nu putem găsi un utilizator cu această adresă de e-mail.",
+ "auth.throttle": "Prea multe încercări de autentificare. Vă rugăm să încercați din nou în :seconds secunde.",
+ "input.name": "Nume",
+ "input.email": "E-mail",
+ "input.password": "Parolă",
+ "input.password.again": "Repetați parola",
+ "input.code": "Cod de unică folosință",
+ "input.recovery_code": "Cod de recuperare",
+ "button.save": "Salvare",
+ "repository.url": "Exemple
Pentru depozite publice, utilizați https://....
Pentru depozite private, utilizați git@....
https://github.com/coollabsio/coolify-examples va fi selectată ramura main
https://github.com/coollabsio/coolify-examples/tree/nodejs-fastify va fi selectată ramura nodejs-fastify.
https://gitea.com/sedlav/expressjs.git va fi selectată ramura main.
https://gitlab.com/andrasbacsai/nodejs-example.git va fi selectată ramura main.",
+ "service.stop": "Acest serviciu va fi oprit.",
+ "resource.docker_cleanup": "Executați curățarea Docker (eliminați imaginile neutilizate și memoria cache a constructorului).",
+ "resource.non_persistent": "Toate datele nepersistente vor fi șterse.",
+ "resource.delete_volumes": "Ștergeți definitiv toate volumele asociate cu această resursă.",
+ "resource.delete_connected_networks": "Ștergeți definitiv toate rețelele non-predefinite asociate cu această resursă.",
+ "resource.delete_configurations": "Ștergeți definitiv toate fișierele de configurare de pe server.",
+ "database.delete_backups_locally": "Toate copiile de rezervă vor fi șterse definitiv din stocarea locală."
+}
diff --git a/openapi.yaml b/openapi.yaml
index 91d5c1443..3521b7de4 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -4981,11 +4981,11 @@ components:
type: string
logdrain_newrelic_license_key:
type: string
- metrics_history_days:
+ sentinel_metrics_refresh_rate_seconds:
type: integer
- metrics_refresh_rate_seconds:
+ sentinel_metrics_history_days:
type: integer
- metrics_token:
+ sentinel_token:
type: string
docker_cleanup_frequency:
type: string
diff --git a/public/svgs/calcom.svg b/public/svgs/calcom.svg
new file mode 100644
index 000000000..446b16655
--- /dev/null
+++ b/public/svgs/calcom.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/public/svgs/edgedb.svg b/public/svgs/edgedb.svg
new file mode 100644
index 000000000..a906f7f7e
--- /dev/null
+++ b/public/svgs/edgedb.svg
@@ -0,0 +1,3 @@
+
diff --git a/resources/views/livewire/project/index.blade.php b/resources/views/livewire/project/index.blade.php
index 10719456e..cb8e1bbed 100644
--- a/resources/views/livewire/project/index.blade.php
+++ b/resources/views/livewire/project/index.blade.php
@@ -24,6 +24,12 @@