Compare commits

...

30 commits

Author SHA1 Message Date
rosslh
65d85fb890 fix(coolify-access): prefer managed root team
All checks were successful
Build MapleDeploy Coolify Image / build (push) Successful in 41s
2026-06-14 14:39:05 -04:00
rosslh
e3cb2675dd feat(auth): add dashboard-managed Coolify users
All checks were successful
Build MapleDeploy Coolify Image / build (push) Successful in 1m26s
2026-06-14 11:47:50 -04:00
rosslh
4ca700dfe7 feat(branding): apply MapleDeploy mark to collapsed sidebar
All checks were successful
Build MapleDeploy Coolify Image / build (push) Successful in 1m36s
Upstream added a collapsible sidebar that shows /coolify-logo.svg when
collapsed. Swap it for the MapleDeploy mark so the brand stays consistent
in both states.
2026-05-24 11:59:46 -04:00
rosslh
f1bafd372e chore(ci): remove upstream GitHub workflow 2026-05-24 11:57:58 -04:00
rosslh
03b2d5504e style: hue-normalize red palette to brand OKLCH h=29.38 2026-05-24 11:57:58 -04:00
rosslh
6ecec449eb style(branding): fix squished mobile header logo 2026-05-24 11:57:53 -04:00
rosslh
b9e17f4995 style(branding): remap neutral/gray to stone and fix chart theming
Remap neutral and gray scales to stone equivalents in @theme block for
warm tone consistency across all three apps. Interpolate coolgray-200 to
avoid invisible dark-mode elements. Add gridColor/textColor to ApexCharts
initial options so axis labels render on first load. Update warning color
and fix add-tag opacity.
2026-05-24 11:57:53 -04:00
rosslh
b275bd2d9f style(branding): replace gray-50 with stone-50 and darken base to stone-800 2026-05-24 11:57:53 -04:00
rosslh
74e183f777 fix(sentinel): pull sentinel image from ghcr.io and fall back to latest tag 2026-05-24 11:57:53 -04:00
rosslh
52bc65de96 feat(branding): disable FQDN and IP fields instead of hiding/leaving editable 2026-05-24 11:57:53 -04:00
rosslh
b18a77d857 fix(versioning): move version bumping to CI build time
Version was never bumped because git rebase doesn't run pre-commit
hooks. CI now appends a YYYYMMDDHHmm timestamp to the upstream base
version and injects it into the Docker image via build arg.
2026-05-24 11:57:53 -04:00
rosslh
d8b6e26364 feat(branding): yellow scrollbar and hide FQDN settings field
- Change scrollbar thumb from Coolify red to MapleDeploy yellow
- Hide FQDN field from settings UI (managed during provisioning)
2026-05-24 11:57:53 -04:00
rosslh
7e5d568de0 feat(auth): notify MapleDeploy on first-user registration
After the first user registers, clears the setup token and dispatches
NotifySetupCompleteJob to POST the token to MapleDeploy's callback URL.
Adds setup_callback_url column to instance_settings.
2026-05-24 11:57:53 -04:00
rosslh
59a6ad42a2 feat(auth): gate first-user registration with setup token
Require a setup_token query parameter to access the registration page
when no users exist, preventing admin hijacking on new instances.
2026-05-24 11:57:53 -04:00
rosslh
0c1cac1eb1 fix(dns): replace Cloudflare defaults with CIRA Canadian Shield
Replace hardcoded 1.1.1.1/1.0.0.1 (Cloudflare) DNS defaults with
CIRA Canadian Shield (149.112.121.10, 149.112.122.10) to maintain
Canadian data sovereignty for DNS resolution.
2026-05-24 11:57:53 -04:00
rosslh
06ee8538d9 chore(branding): remove sponsorship popup remnants 2026-05-24 11:57:53 -04:00
rosslh
4e922d89a6 style(branding): replace Coolify purple and yellow with MapleDeploy palette
Replace #6b16ed (Coolify purple) with #d52b1e (MapleDeploy red) and
form focus states, dirty indicators, chart colors, and theme tokens.
Also fix warning color scale to use standard Tailwind yellow values.
2026-05-24 11:57:53 -04:00
rosslh
1eb1067b90 feat(onboarding): skip boarding wizard for new users
Customers land directly on the dashboard instead of the setup wizard,
which shows a misleading localhost vs remote server warning that
conflicts with MapleDeploy's single-VM model.
2026-05-24 11:57:53 -04:00
rosslh
867f2f4fd2 style(branding): add header logo gap and use stone-900 background
Add 4px gap between logo and header elements with flex-shrink support.
Change base background from near-black (#0c0a09) to stone-900 (#1c1917)
to match the marketing site's darkest dark-mode color.
2026-05-24 11:57:53 -04:00
rosslh
16586d70b1 fix(branding): preserve sidebar logo aspect ratio when constrained 2026-05-24 11:57:27 -04:00
rosslh
37f8698a71 fix(branding): replace "self-hosted" subtitle on dashboard 2026-05-24 11:57:27 -04:00
rosslh
8c1fbf4f13 fix(branding): constrain sidebar logo to prevent overflow
Replace max-w-none with max-w-full so the logo respects the sidebar
container width instead of overflowing it.
2026-05-24 11:57:27 -04:00
rosslh
6017d041ed fix(branding): preserve sidebar logo aspect ratio, bump to 463.2
Add max-w-none to logo images to prevent Tailwind base styles from
constraining the image width within the narrow sidebar flex container.
2026-05-24 11:57:27 -04:00
rosslh
97eb0540e7 chore: remove broken feedback form and all entrypoints
The feedback form relies on instance SMTP being configured, which
MapleDeploy customers won't do. Without SMTP it silently logs to
the server and shows a misleading success message. Removed the
navbar button, onboarding modal, subscription page link, API
endpoint, and all associated dead code.
2026-05-24 11:57:27 -04:00
rosslh
4d144d5bfe fix(ci): recreate CDN storage zone in EU (DE) region
Storage zone was accidentally created in NY. Recreated as
'coolify-update' in DE (Falkenstein) to keep update artifacts
in EU jurisdiction, consistent with Bunny.net data sovereignty
justification. Updated storage zone name, pull zone ID, and
reverted storage endpoint to default (storage.bunnycdn.com).
2026-05-24 11:56:19 -04:00
rosslh
ab30093c4b fix(ci): use NY region storage endpoint for Bunny CDN uploads 2026-05-24 11:56:19 -04:00
rosslh
dfa2a2c4e4 fix(ci): use apk instead of apt-get for curl install 2026-05-24 11:56:19 -04:00
rosslh
5da91e9fed fix(ci): install curl in runner for CDN uploads 2026-05-24 11:56:19 -04:00
rosslh
e8d7c9c93f feat: add update pipeline with MapleDeploy CDN and versioning
Route all Coolify update artifacts (versions.json, upgrade.sh,
compose files) through updates.mapledeploy.ca instead of upstream
cdn.coollabs.io. Extend CI to publish artifacts to Bunny CDN
storage zone and purge cache on each build.

- Point CDN_URL, versions_url, upgrade_script_url to updates.mapledeploy.ca
- Hardcode helper/realtime images to ghcr.io (not mirrored to Forgejo)
- Pass registry_url as 3rd arg to upgrade.sh for main image pulls
- Adopt versioning scheme 4.0.0-beta.X.N (bump to 4.0.0-beta.463.1)
- Add CI steps: generate versions.json, upload to Bunny, purge cache
2026-05-24 11:56:19 -04:00
rosslh
c45efe942e feat(branding): apply MapleDeploy branding to Coolify
Replace Coolify branding with MapleDeploy throughout the UI: logos,
favicon, fonts (Overlock 900), color scheme, help links, and page
titles. Remove GitHub Actions workflows and add Forgejo CI build
workflow. Strip cloud-only features (subscription prompts, sponsor
links, server creation cloud options).
2026-05-24 11:55:58 -04:00
170 changed files with 1617 additions and 1748 deletions

View file

@ -15,4 +15,5 @@ ROOT_USERNAME=
ROOT_USER_EMAIL= ROOT_USER_EMAIL=
ROOT_USER_PASSWORD= ROOT_USER_PASSWORD=
REGISTRY_URL=ghcr.io REGISTRY_URL=forgejo.mapledeploy.ca
CDN_URL=https://updates.mapledeploy.ca

View file

@ -0,0 +1,103 @@
name: Build MapleDeploy Coolify Image
on:
push:
branches: [mapledeploy]
paths-ignore:
- "*.md"
- ".github/**"
- "templates/**"
env:
REGISTRY: forgejo.mapledeploy.ca
CDN_STORAGE_ZONE: coolify-update
CDN_PULL_ZONE_ID: "5338895"
CDN_BASE_URL: https://updates.mapledeploy.ca
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get version
id: version
run: |
BASE_VERSION=$(sed -n "s/.*'version' => '\([^']*\)'.*/\1/p" config/constants.php)
TIMESTAMP=$(date -u +%Y%m%d%H%M)
VERSION="${BASE_VERSION}.${TIMESTAMP}"
HELPER_VERSION=$(sed -n "s/.*'helper_version' => '\([^']*\)'.*/\1/p" config/constants.php)
REALTIME_VERSION=$(sed -n "s/.*'realtime_version' => '\([^']*\)'.*/\1/p" config/constants.php)
echo "VERSION=${VERSION}" >> "$GITHUB_OUTPUT"
echo "HELPER_VERSION=${HELPER_VERSION}" >> "$GITHUB_OUTPUT"
echo "REALTIME_VERSION=${REALTIME_VERSION}" >> "$GITHUB_OUTPUT"
echo "Building version: ${VERSION} (helper: ${HELPER_VERSION}, realtime: ${REALTIME_VERSION})"
- name: Login to Forgejo registry
run: |
echo "${{ secrets.FORGEJO_TOKEN }}" | docker login ${{ env.REGISTRY }} -u ${{ github.repository_owner }} --password-stdin
- name: Build image
run: |
DOCKER_BUILDKIT=1 docker build -f docker/production/Dockerfile \
--build-arg MAPLEDEPLOY_VERSION=${{ steps.version.outputs.VERSION }} \
-t ${{ env.REGISTRY }}/${{ github.repository }}:${{ steps.version.outputs.VERSION }} \
-t ${{ env.REGISTRY }}/${{ github.repository }}:latest \
.
- name: Push image
run: |
docker push ${{ env.REGISTRY }}/${{ github.repository }}:${{ steps.version.outputs.VERSION }}
docker push ${{ env.REGISTRY }}/${{ github.repository }}:latest
- name: Generate versions.json
run: |
cat > versions.json <<EOF
{
"coolify": {
"v4": {
"version": "${{ steps.version.outputs.VERSION }}"
},
"helper": {
"version": "${{ steps.version.outputs.HELPER_VERSION }}"
},
"realtime": {
"version": "${{ steps.version.outputs.REALTIME_VERSION }}"
}
}
}
EOF
echo "Generated versions.json:"
cat versions.json
- name: Install curl
run: apk add --no-cache curl
- name: Upload artifacts to Bunny CDN
run: |
STORAGE_URL="https://storage.bunnycdn.com/${{ env.CDN_STORAGE_ZONE }}/coolify"
upload() {
local file="$1"
local dest="$2"
echo "Uploading ${file} -> ${dest}"
curl -fsSL -X PUT "${STORAGE_URL}/${dest}" \
-H "AccessKey: ${{ secrets.BUNNY_CDN_STORAGE_KEY }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"${file}"
}
upload versions.json versions.json
upload scripts/upgrade.sh upgrade.sh
upload docker-compose.yml docker-compose.yml
upload docker-compose.prod.yml docker-compose.prod.yml
upload .env.production .env.production
echo "All artifacts uploaded."
- name: Purge CDN cache
run: |
curl -fsSL -X POST "https://api.bunny.net/pullzone/${{ env.CDN_PULL_ZONE_ID }}/purgeCache" \
-H "AccessKey: ${{ secrets.BUNNY_API_KEY }}" \
-H "Content-Type: application/json"
echo "CDN cache purged."

View file

@ -1,22 +0,0 @@
name: Lock closed Issues, Discussions, and PRs
on:
schedule:
- cron: '0 1 * * *'
permissions:
issues: write
discussions: write
pull-requests: write
jobs:
lock-threads:
runs-on: ubuntu-latest
steps:
- name: Lock threads after 30 days of inactivity
uses: dessant/lock-threads@v5
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: '30'
discussion-inactive-days: '30'
pr-inactive-days: '30'

View file

@ -1,32 +0,0 @@
name: Manage Stale Issues and PRs
on:
schedule:
- cron: '0 2 * * *'
permissions:
issues: write
pull-requests: write
jobs:
manage-stale:
runs-on: ubuntu-latest
steps:
- name: Manage stale issues and PRs
uses: actions/stale@v9
id: stale
with:
stale-issue-message: 'This issue will be automatically closed in a few days if no response is received. Please provide an update with the requested information.'
stale-pr-message: 'This pull request requires attention. If no changes or response is received within the next few days, it will be automatically closed. Please update your PR or leave a comment with the requested information.'
close-issue-message: 'This issue has been automatically closed due to inactivity.'
close-pr-message: 'Thank you for your contribution. Due to inactivity, this PR was automatically closed. If you would like to continue working on this change in the future, feel free to reopen this PR or submit a new one.'
days-before-stale: 14
days-before-close: 7
stale-issue-label: '⏱︎ Stale'
stale-pr-label: '⏱︎ Stale'
only-labels: '💤 Waiting for feedback, 💤 Waiting for changes'
remove-stale-when-updated: true
operations-per-run: 100
labels-to-remove-when-unstale: '⏱︎ Stale, 💤 Waiting for feedback, 💤 Waiting for changes'
close-issue-reason: 'not_planned'
exempt-all-milestones: false

View file

@ -1,49 +0,0 @@
name: Add comment based on label
on:
pull_request_target:
types:
- labeled
permissions:
pull-requests: write
jobs:
add-comment:
runs-on: ubuntu-latest
strategy:
matrix:
include:
- label: "⚙️ Service"
body: |
Hi @${{ github.event.pull_request.user.login }}! 👋
It appears to us that you are either adding a new service or making changes to an existing one.
We kindly ask you to also review and update the **Coolify Documentation** to include this new service or it's new configuration needs.
This will help ensure that our documentation remains accurate and up-to-date for all users.
Coolify Docs Repository: https://github.com/coollabsio/coolify-docs
How to Contribute a new Service to the Docs: https://coolify.io/docs/get-started/contribute/service#adding-a-new-service-template-to-the-coolify-documentation
- label: "🛠️ Feature"
body: |
Hi @${{ github.event.pull_request.user.login }}! 👋
It appears to us that you are adding a new feature to Coolify.
We kindly ask you to also update the **Coolify Documentation** to include information about this new feature.
This will help ensure that our documentation remains accurate and up-to-date for all users.
Coolify Docs Repository: https://github.com/coollabsio/coolify-docs
How to Contribute to the Docs: https://coolify.io/docs/get-started/contribute/documentation
# - label: "✨ Enhancement"
# body: |
# It appears to us that you are making an enhancement to Coolify.
# We kindly ask you to also review and update the Coolify Documentation to include information about this enhancement if applicable.
# This will help ensure that our documentation remains accurate and up-to-date for all users.
steps:
- name: Add comment
if: github.event.label.name == matrix.label
run: gh pr comment "$NUMBER" --body "$BODY"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
NUMBER: ${{ github.event.pull_request.number }}
BODY: ${{ matrix.body }}

View file

@ -1,37 +0,0 @@
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
claude_args: '--model opus'

View file

@ -1,22 +0,0 @@
name: Cleanup Untagged GHCR Images
on:
workflow_dispatch:
permissions:
packages: write
jobs:
cleanup-all-packages:
runs-on: ubuntu-latest
strategy:
matrix:
package: ['coolify', 'coolify-helper', 'coolify-realtime', 'coolify-testing-host']
steps:
- name: Delete untagged ${{ matrix.package }} images
uses: actions/delete-package-versions@v5
with:
package-name: ${{ matrix.package }}
package-type: 'container'
min-versions-to-keep: 0
delete-only-untagged-versions: 'true'

View file

@ -1,117 +0,0 @@
name: Coolify Helper Image Development
on:
push:
branches: [ "next" ]
paths:
- .github/workflows/coolify-helper-next.yml
- docker/coolify-helper/Dockerfile
permissions:
contents: read
packages: write
env:
GITHUB_REGISTRY: ghcr.io
DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-helper"
jobs:
build-push:
strategy:
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: aarch64
platform: linux/aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Build and Push Image (${{ matrix.arch }})
uses: docker/build-push-action@v6
with:
context: .
file: docker/coolify-helper/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }}
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }}
labels: |
coolify.managed=true
merge-manifest:
runs-on: ubuntu-24.04
needs: build-push
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
docker buildx imagetools create \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \
${{ 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 \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \
${{ 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_DEV_RELEASE_CHANNEL }}

View file

@ -1,116 +0,0 @@
name: Coolify Helper Image
on:
push:
branches: [ "v4.x" ]
paths:
- .github/workflows/coolify-helper.yml
- docker/coolify-helper/Dockerfile
permissions:
contents: read
packages: write
env:
GITHUB_REGISTRY: ghcr.io
DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-helper"
jobs:
build-push:
strategy:
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: aarch64
platform: linux/aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Build and Push Image (${{ matrix.arch }})
uses: docker/build-push-action@v6
with:
context: .
file: docker/coolify-helper/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
labels: |
coolify.managed=true
merge-manifest:
runs-on: ubuntu-24.04
needs: build-push
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getHelperVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
docker buildx imagetools create \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
${{ 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 \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
${{ 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 }}

View file

@ -1,122 +0,0 @@
name: Production Build (v4)
on:
push:
branches: ["v4.x"]
paths-ignore:
- .github/workflows/coolify-helper.yml
- .github/workflows/coolify-helper-next.yml
- .github/workflows/coolify-realtime.yml
- .github/workflows/coolify-realtime-next.yml
- .github/workflows/pr-quality.yaml
- docker/coolify-helper/Dockerfile
- docker/coolify-realtime/Dockerfile
- docker/testing-host/Dockerfile
- templates/**
- CHANGELOG.md
permissions:
contents: read
packages: write
env:
GITHUB_REGISTRY: ghcr.io
DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify"
jobs:
build-push:
strategy:
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: aarch64
platform: linux/aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_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 (${{ matrix.arch }})
uses: docker/build-push-action@v6
with:
context: .
file: docker/production/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
merge-manifest:
runs-on: ubuntu-24.04
needs: build-push
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_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 \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
${{ 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 \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
${{ 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 }}

View file

@ -1,120 +0,0 @@
name: Coolify Realtime Development
on:
push:
branches: [ "next" ]
paths:
- .github/workflows/coolify-realtime-next.yml
- docker/coolify-realtime/Dockerfile
- docker/coolify-realtime/terminal-server.js
- docker/coolify-realtime/package.json
- docker/coolify-realtime/package-lock.json
- docker/coolify-realtime/soketi-entrypoint.sh
permissions:
contents: read
packages: write
env:
GITHUB_REGISTRY: ghcr.io
DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-realtime"
jobs:
build-push:
strategy:
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: aarch64
platform: linux/aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Build and Push Image (${{ matrix.arch }})
uses: docker/build-push-action@v6
with:
context: .
file: docker/coolify-realtime/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }}
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-${{ matrix.arch }}
labels: |
coolify.managed=true
merge-manifest:
runs-on: ubuntu-24.04
needs: build-push
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
docker buildx imagetools create \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \
${{ 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 \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-next-amd64 \
${{ 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_DEV_RELEASE_CHANNEL }}

View file

@ -1,120 +0,0 @@
name: Coolify Realtime
on:
push:
branches: [ "v4.x" ]
paths:
- .github/workflows/coolify-realtime.yml
- docker/coolify-realtime/Dockerfile
- docker/coolify-realtime/terminal-server.js
- docker/coolify-realtime/package.json
- docker/coolify-realtime/package-lock.json
- docker/coolify-realtime/soketi-entrypoint.sh
permissions:
contents: read
packages: write
env:
GITHUB_REGISTRY: ghcr.io
DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-realtime"
jobs:
build-push:
strategy:
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: aarch64
platform: linux/aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Build and Push Image (${{ matrix.arch }})
uses: docker/build-push-action@v6
with:
context: .
file: docker/coolify-realtime/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
labels: |
coolify.managed=true
merge-manifest:
runs-on: ubuntu-24.04
needs: build-push
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get Version
id: version
run: |
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getRealtimeVersion.php)"|xargs >> $GITHUB_OUTPUT
- name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
docker buildx imagetools create \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
${{ 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 \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
${{ 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 }}

View file

@ -1,134 +0,0 @@
name: Staging Build
on:
push:
branches-ignore:
- v4.x
- v3.x
- '**v5.x**'
paths-ignore:
- .github/workflows/coolify-helper.yml
- .github/workflows/coolify-helper-next.yml
- .github/workflows/coolify-realtime.yml
- .github/workflows/coolify-realtime-next.yml
- .github/workflows/pr-quality.yaml
- docker/coolify-helper/Dockerfile
- docker/coolify-realtime/Dockerfile
- docker/testing-host/Dockerfile
- templates/**
- CHANGELOG.md
permissions:
contents: read
packages: write
env:
GITHUB_REGISTRY: ghcr.io
DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify"
jobs:
build-push:
strategy:
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: aarch64
platform: linux/aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- name: Sanitize branch name for Docker tag
id: sanitize
run: |
# Replace slashes and other invalid characters with dashes
SANITIZED_NAME=$(echo "${{ github.ref_name }}" | sed 's/[\/]/-/g')
echo "tag=${SANITIZED_NAME}" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Image (${{ matrix.arch }})
uses: docker/build-push-action@v6
with:
context: .
file: docker/production/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-${{ matrix.arch }}
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-${{ matrix.arch }}
cache-from: |
type=gha,scope=build-${{ matrix.arch }}
type=registry,ref=${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache-${{ matrix.arch }}
cache-to: type=gha,mode=max,scope=build-${{ matrix.arch }}
merge-manifest:
runs-on: ubuntu-24.04
needs: build-push
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- name: Sanitize branch name for Docker tag
id: sanitize
run: |
# Replace slashes and other invalid characters with dashes
SANITIZED_NAME=$(echo "${{ github.ref_name }}" | sed 's/[\/]/-/g')
echo "tag=${SANITIZED_NAME}" >> $GITHUB_OUTPUT
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
docker buildx imagetools create \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-amd64 \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-aarch64 \
--tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}
- name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
run: |
docker buildx imagetools create \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-amd64 \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}-aarch64 \
--tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.sanitize.outputs.tag }}
- uses: sarisia/actions-status-discord@v1
if: always()
with:
webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}

View file

@ -1,104 +0,0 @@
name: Coolify Testing Host
on:
push:
branches: [ "next" ]
paths:
- .github/workflows/coolify-testing-host.yml
- docker/testing-host/Dockerfile
permissions:
contents: read
packages: write
env:
GITHUB_REGISTRY: ghcr.io
DOCKER_REGISTRY: docker.io
IMAGE_NAME: "coollabsio/coolify-testing-host"
jobs:
build-push:
strategy:
matrix:
include:
- arch: amd64
platform: linux/amd64
runner: ubuntu-24.04
- arch: aarch64
platform: linux/aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and Push Image (${{ matrix.arch }})
uses: docker/build-push-action@v6
with:
context: .
file: docker/testing-host/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-${{ matrix.arch }}
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-${{ matrix.arch }}
labels: |
coolify.managed=true
merge-manifest:
runs-on: ubuntu-24.04
needs: build-push
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- 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.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
run: |
docker buildx imagetools create \
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64 \
${{ 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 \
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64 \
${{ 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:
webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}

View file

@ -1,42 +0,0 @@
name: Generate Changelog
on:
push:
branches: [ v4.x ]
paths-ignore:
- .github/workflows/coolify-helper.yml
- .github/workflows/coolify-helper-next.yml
- .github/workflows/coolify-realtime.yml
- .github/workflows/coolify-realtime-next.yml
- .github/workflows/pr-quality.yaml
workflow_dispatch:
permissions:
contents: write
jobs:
changelog:
name: Generate changelog
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
uses: orhun/git-cliff-action@v4
with:
config: cliff.toml
args: --verbose
env:
OUTPUT: CHANGELOG.md
GITHUB_REPO: ${{ github.repository }}
- name: Commit
run: |
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git add CHANGELOG.md
git commit -m "docs: update changelog"
git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git v4.x

View file

@ -1,111 +0,0 @@
name: PR Quality
permissions:
contents: read
issues: read
pull-requests: write
on:
pull_request_target:
types: [opened, reopened]
jobs:
pr-quality:
runs-on: ubuntu-latest
steps:
- uses: peakoss/anti-slop@v0
with:
# General Settings
max-failures: 4
# PR Branch Checks
allowed-target-branches: "next"
blocked-target-branches: ""
allowed-source-branches: ""
blocked-source-branches: |
main
master
v4.x
# PR Quality Checks
max-negative-reactions: 0
require-maintainer-can-modify: true
# PR Title Checks
require-conventional-title: true
# PR Description Checks
require-description: true
max-description-length: 2500
max-emoji-count: 2
max-code-references: 5
require-linked-issue: false
blocked-terms: |
STRAWBERRY
🤖 Generated with Claude Code
Generated with Claude Code
blocked-issue-numbers: 8154
# PR Template Checks
require-pr-template: true
strict-pr-template-sections: "Contributor Agreement"
optional-pr-template-sections: "Issues,Preview"
max-additional-pr-template-sections: 2
# Commit Message Checks
max-commit-message-length: 500
require-conventional-commits: false
require-commit-author-match: true
blocked-commit-authors: ""
# File Checks
allowed-file-extensions: ""
allowed-paths: ""
blocked-paths: |
README.md
SECURITY.md
LICENSE
CODE_OF_CONDUCT.md
templates/service-templates-latest.json
templates/service-templates.json
require-final-newline: true
max-added-comments: 10
# User Checks
detect-spam-usernames: true
min-account-age: 30
max-daily-forks: 7
min-profile-completeness: 4
# Merge Checks
min-repo-merged-prs: 0
min-repo-merge-ratio: 0
min-global-merge-ratio: 30
global-merge-ratio-exclude-own: false
# Exemptions
exempt-draft-prs: false
exempt-bots: |
actions-user
dependabot[bot]
renovate[bot]
github-actions[bot]
exempt-users: ""
exempt-author-association: "OWNER,MEMBER,COLLABORATOR"
exempt-label: "quality/exempt"
exempt-pr-label: ""
exempt-all-milestones: false
exempt-all-pr-milestones: false
exempt-milestones: ""
exempt-pr-milestones: ""
# PR Success Actions
success-add-pr-labels: ""
# PR Failure Actions
failure-remove-pr-labels: ""
failure-remove-all-pr-labels: true
failure-add-pr-labels: "quality/rejected"
failure-pr-message: "This PR did not pass quality checks so it will be closed. If you believe this is a mistake please let us know."
close-pr: true
lock-pr: false

View file

@ -6,6 +6,7 @@
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rules\Password; use Illuminate\Validation\Rules\Password;
use Illuminate\Validation\ValidationException;
use Laravel\Fortify\Contracts\ResetsUserPasswords; use Laravel\Fortify\Contracts\ResetsUserPasswords;
class ResetUserPassword implements ResetsUserPasswords class ResetUserPassword implements ResetsUserPasswords
@ -17,6 +18,13 @@ class ResetUserPassword implements ResetsUserPasswords
*/ */
public function reset(User $user, array $input): void public function reset(User $user, array $input): void
{ {
if ($user->isMapledeployRevoked()) {
// MapleDeploy branding: dashboard-managed revocation is restored only by mapledeploy:user:set-password.
throw ValidationException::withMessages([
'email' => [trans('passwords.user')],
]);
}
Validator::make($input, [ Validator::make($input, [
'password' => ['required', Password::defaults(), 'confirmed'], 'password' => ['required', Password::defaults(), 'confirmed'],
])->validate(); ])->validate();

View file

@ -102,7 +102,8 @@ public function handle(Server $server, $fromUI = false): bool
foreach ($conflicts as $port => $conflict) { foreach ($conflicts as $port => $conflict) {
if ($conflict) { if ($conflict) {
if ($fromUI) { if ($fromUI) {
throw new \Exception("Port $port is in use.<br>You must stop the process using this port.<br><br>Docs: <a target='_blank' class='dark:text-white hover:underline' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' class='dark:text-white hover:underline' href='https://coolify.io/discord'>https://coolify.io/discord</a>"); // MapleDeploy branding: support links
throw new \Exception("Port $port is in use.<br>You must stop the process using this port.<br><br>Support: <a target='_blank' class='dark:text-white hover:underline' href='https://mapledeploy.ca/contact'>https://mapledeploy.ca/contact</a>");
} else { } else {
return false; return false;
} }

View file

@ -26,7 +26,8 @@ public function handle(Server $server, bool $restart = false, ?string $latestVer
$endpoint = data_get($server, 'settings.sentinel_custom_url'); $endpoint = data_get($server, 'settings.sentinel_custom_url');
$debug = data_get($server, 'settings.is_sentinel_debug_enabled'); $debug = data_get($server, 'settings.is_sentinel_debug_enabled');
$mountDir = '/data/coolify/sentinel'; $mountDir = '/data/coolify/sentinel';
$image = config('constants.coolify.registry_url').'/coollabsio/sentinel:'.$version; // MapleDeploy branding: Sentinel is not mirrored to our Forgejo registry, so pull from ghcr.io directly (upstream image)
$image = 'ghcr.io/coollabsio/sentinel:'.$version;
if (! $endpoint) { if (! $endpoint) {
throw new \RuntimeException('You should set FQDN in Instance Settings.'); throw new \RuntimeException('You should set FQDN in Instance Settings.');
} }

View file

@ -119,9 +119,11 @@ private function update()
$latestHelperImageVersion = getHelperVersion(); $latestHelperImageVersion = getHelperVersion();
$upgradeScriptUrl = config('constants.coolify.upgrade_script_url'); $upgradeScriptUrl = config('constants.coolify.upgrade_script_url');
$registryUrl = config('constants.coolify.registry_url');
remote_process([ remote_process([
"curl -fsSL {$upgradeScriptUrl} -o /data/coolify/source/upgrade.sh", "curl -fsSL {$upgradeScriptUrl} -o /data/coolify/source/upgrade.sh",
"bash /data/coolify/source/upgrade.sh $this->latestVersion $latestHelperImageVersion", "bash /data/coolify/source/upgrade.sh $this->latestVersion $latestHelperImageVersion $registryUrl",
], $this->server); ], $this->server);
} }
} }

View file

@ -264,15 +264,11 @@ private function restoreCoolifyDbBackup()
} }
} }
// MapleDeploy branding: telemetry disabled — no phone-home signal
private function sendAliveSignal() private function sendAliveSignal()
{ {
$id = config('app.id'); // Disabled for MapleDeploy: do not send telemetry to coolify.io
$version = config('constants.coolify.version'); return;
try {
Http::get("https://undead.coolify.io/v4/alive?appId=$id&version=$version");
} catch (\Throwable $e) {
echo "Error in sending live signal: {$e->getMessage()}\n";
}
} }
private function replaceSlashInEnvironmentName() private function replaceSlashInEnvironmentName()

View file

@ -0,0 +1,160 @@
<?php
namespace App\Console\Commands\Mapledeploy;
use App\Enums\Role;
use App\Models\Team;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class UserCreate extends Command
{
protected $signature = 'mapledeploy:user:create
{--email= : User email address}
{--name= : User display name}
{--admin : Create the first root admin user}
{--team-role=member : Root team role for non-admin users}';
protected $description = 'Create a Coolify user for MapleDeploy dashboard access management';
public function handle(): int
{
$password = $this->readPassword();
$input = [
'email' => $this->option('email'),
'name' => $this->option('name'),
'password' => $password,
'team_role' => $this->option('team-role'),
];
$validator = Validator::make($input, [
'email' => ['required', 'string', 'email', 'max:255'],
'name' => ['required', 'string', 'max:255'],
'password' => ['required', 'string', 'min:8'],
'team_role' => ['required', Rule::in([Role::ADMIN->value, Role::MEMBER->value])],
]);
if ($validator->fails()) {
return $this->failWith('INVALID_INPUT');
}
$input['email'] = Str::lower((string) $input['email']);
if (User::whereEmail($input['email'])->exists()) {
return $this->failWith('EMAIL_EXISTS');
}
if ($this->option('admin')) {
return $this->createAdmin($input);
}
return $this->createMember($input);
}
private function createAdmin(array $input): int
{
if (User::count() !== 0) {
return $this->failWith('USERS_ALREADY_EXIST');
}
$user = DB::transaction(function () use ($input) {
$user = (new User)->forceFill([
'id' => 0,
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
$user->save();
$user->markEmailAsVerified();
$settings = instanceSettings();
$settings->is_registration_enabled = false;
$attributes = $settings->getAttributes();
if (array_key_exists('setup_token', $attributes)) {
$settings->setup_token = null;
}
if (array_key_exists('setup_callback_url', $attributes)) {
$settings->setup_callback_url = null;
}
$settings->save();
return $user;
});
return $this->succeedWithUser($user);
}
private function createMember(array $input): int
{
$rootTeam = Team::find(0);
if (! $rootTeam) {
return $this->failWith('ROOT_TEAM_MISSING');
}
$user = DB::transaction(function () use ($input, $rootTeam) {
$user = User::create([
'name' => $input['name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
$user->markEmailAsVerified();
$this->deletePersonalTeams($user);
$user->teams()->syncWithoutDetaching([
$rootTeam->id => ['role' => $input['team_role']],
]);
return $user;
});
return $this->succeedWithUser($user);
}
private function deletePersonalTeams(User $user): void
{
// MapleDeploy branding: dashboard-managed users should only see the
// managed instance root team, not an empty personal Coolify team.
$personalTeams = Team::query()
->where('teams.id', '!=', 0)
->where('personal_team', true)
->whereHas('members', fn ($query) => $query->whereKey($user->id))
->get();
foreach ($personalTeams as $team) {
DB::table('team_user')
->where('team_id', $team->id)
->where('user_id', $user->id)
->delete();
DB::table('teams')->where('id', $team->id)->delete();
}
}
private function readPassword(): string
{
return rtrim((string) stream_get_contents(STDIN), "\n");
}
private function succeedWithUser(User $user): int
{
$this->line(json_encode([
'user' => [
'id' => $user->id,
'email' => $user->email,
'name' => $user->name,
],
], JSON_THROW_ON_ERROR));
return self::SUCCESS;
}
private function failWith(string $code): int
{
$this->line(json_encode(['error' => $code], JSON_THROW_ON_ERROR));
return self::FAILURE;
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace App\Console\Commands\Mapledeploy;
use App\Models\User;
use Illuminate\Console\Command;
class UserList extends Command
{
protected $signature = 'mapledeploy:user:list';
protected $description = 'List Coolify users for MapleDeploy dashboard access management';
public function handle(): int
{
$users = User::with('teams')
->orderBy('id')
->get()
->map(fn (User $user) => [
'id' => $user->id,
'email' => $user->email,
'name' => $user->name,
'created_at' => $user->created_at?->toISOString(),
'teams' => $user->teams
->map(fn ($team) => [
'id' => $team->id,
'name' => $team->name,
'role' => $team->pivot?->role,
])
->values()
->all(),
])
->values()
->all();
$this->line(json_encode(['users' => $users], JSON_THROW_ON_ERROR));
return self::SUCCESS;
}
}

View file

@ -0,0 +1,55 @@
<?php
namespace App\Console\Commands\Mapledeploy;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class UserRevoke extends Command
{
protected $signature = 'mapledeploy:user:revoke {user_id : Coolify user id}';
protected $description = 'Revoke a Coolify user login for MapleDeploy dashboard access management';
public function handle(): int
{
$userId = (int) $this->argument('user_id');
if ($userId === 0) {
return $this->failWith('CANNOT_REVOKE_ROOT_USER');
}
$user = User::find($userId);
if (! $user) {
return $this->failWith('USER_NOT_FOUND');
}
$user->forceFill([
'password' => Hash::make(Str::random(64)),
// MapleDeploy branding: OAuth login matches by email, so keep a
// persistent marker that the callback can reject after revocation.
'remember_token' => 'mapledeploy-revoked:'.Str::random(40),
])->save();
$user->tokens()->delete();
// MapleDeploy branding: revocation must end any active browser sessions.
DB::table('sessions')->where('user_id', $user->id)->delete();
$this->line(json_encode([
'revoked' => [
'id' => $user->id,
'email' => $user->email,
],
], JSON_THROW_ON_ERROR));
return self::SUCCESS;
}
private function failWith(string $code): int
{
$this->line(json_encode(['error' => $code], JSON_THROW_ON_ERROR));
return self::FAILURE;
}
}

View file

@ -0,0 +1,107 @@
<?php
namespace App\Console\Commands\Mapledeploy;
use App\Enums\Role;
use App\Models\Team;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class UserSetPassword extends Command
{
protected $signature = 'mapledeploy:user:set-password
{user_id : Coolify user id}
{--email= : New user email address}
{--name= : New user display name}';
protected $description = 'Set a Coolify user password for MapleDeploy dashboard access management';
public function handle(): int
{
$password = rtrim((string) stream_get_contents(STDIN), "\n");
$updatesOwner = $this->option('email') !== null || $this->option('name') !== null;
$input = [
'password' => $password,
'email' => $this->option('email'),
'name' => $this->option('name'),
];
$rules = ['password' => ['required', 'string', 'min:8']];
if ($updatesOwner) {
$rules['email'] = ['required', 'string', 'email', 'max:255'];
$rules['name'] = ['required', 'string', 'max:255'];
}
$validator = Validator::make($input, $rules);
if ($validator->fails()) {
return $this->failWith('INVALID_INPUT');
}
$user = User::find($this->argument('user_id'));
if (! $user) {
return $this->failWith('USER_NOT_FOUND');
}
$rootTeam = null;
if ((int) $user->id !== 0) {
$rootTeam = Team::find(0);
if (! $rootTeam) {
return $this->failWith('ROOT_TEAM_MISSING');
}
}
$changes = [
'password' => Hash::make($password),
// MapleDeploy branding: clear the revocation marker when the
// dashboard intentionally restores this Coolify login.
'remember_token' => null,
];
if ($updatesOwner) {
$email = Str::lower((string) $input['email']);
if (User::whereEmail($email)->whereKeyNot($user->id)->exists()) {
return $this->failWith('EMAIL_EXISTS');
}
// MapleDeploy branding: claiming root admin transfers the Coolify
// account identity so the previous email holder cannot recover it.
$changes['email'] = $email;
$changes['name'] = $input['name'];
}
DB::transaction(function () use ($user, $changes, $updatesOwner, $rootTeam) {
$user->forceFill($changes)->save();
if ($updatesOwner && ! $user->hasVerifiedEmail()) {
$user->markEmailAsVerified();
}
if ($rootTeam) {
// MapleDeploy branding: matching an existing Coolify user by
// email must grant the same root-team admin access as a newly
// dashboard-created user.
$user->teams()->syncWithoutDetaching([
$rootTeam->id => ['role' => Role::ADMIN->value],
]);
}
// MapleDeploy branding: password resets from the dashboard should
// end browser sessions authenticated with the previous password.
DB::table('sessions')->where('user_id', $user->id)->delete();
});
$this->line(json_encode([
'user' => [
'id' => $user->id,
'email' => $user->email,
'name' => $user->name,
],
], JSON_THROW_ON_ERROR));
return self::SUCCESS;
}
private function failWith(string $code): int
{
$this->line(json_encode(['error' => $code], JSON_THROW_ON_ERROR));
return self::FAILURE;
}
}

View file

@ -4,8 +4,9 @@
use OpenApi\Attributes as OA; use OpenApi\Attributes as OA;
#[OA\Info(title: 'Coolify', version: '0.1')] // MapleDeploy branding: API documentation
#[OA\Server(url: 'https://app.coolify.io/api/v1', description: 'Coolify Cloud API. Change the host to your own instance if you are self-hosting.')] #[OA\Info(title: 'MapleDeploy', version: '0.1')]
#[OA\Server(url: '/api/v1', description: 'MapleDeploy API. Powered by Coolify.')]
#[OA\SecurityScheme( #[OA\SecurityScheme(
type: 'http', type: 'http',
scheme: 'bearer', scheme: 'bearer',

View file

@ -4,7 +4,6 @@
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use OpenApi\Attributes as OA; use OpenApi\Attributes as OA;
class OtherController extends Controller class OtherController extends Controller
@ -265,23 +264,6 @@ public function disable_mcp(Request $request)
return response()->json(['message' => 'MCP server disabled.'], 200); return response()->json(['message' => 'MCP server disabled.'], 200);
} }
public function feedback(Request $request)
{
$data = $request->validate([
'content' => ['required', 'string', 'min:10', 'max:2000'],
]);
$webhook_url = config('constants.webhooks.feedback_discord_webhook');
if ($webhook_url) {
Http::timeout(5)->post($webhook_url, [
'content' => $data['content'],
'allowed_mentions' => ['parse' => []],
]);
}
return response()->json(['message' => 'Feedback sent.'], 200);
}
#[OA\Get( #[OA\Get(
summary: 'Healthcheck', summary: 'Healthcheck',
description: 'Healthcheck endpoint.', description: 'Healthcheck endpoint.',

View file

@ -78,6 +78,11 @@ public function forgot_password(Request $request)
return response()->json(['message' => 'Transactional emails are not active'], 400); return response()->json(['message' => 'Transactional emails are not active'], 400);
} }
$request->validate([Fortify::email() => 'required|email']); $request->validate([Fortify::email() => 'required|email']);
$user = User::where('email', $request->input(Fortify::email()))->first();
if ($user?->isMapledeployRevoked()) {
// MapleDeploy branding: only the dashboard set-password path can restore revoked users.
return app(SuccessfulPasswordResetLinkRequestResponse::class, ['status' => Password::RESET_LINK_SENT]);
}
$status = Password::broker(config('fortify.passwords'))->sendResetLink( $status = Password::broker(config('fortify.passwords'))->sendResetLink(
$request->only(Fortify::email()) $request->only(Fortify::email())
); );
@ -112,7 +117,9 @@ public function link()
$user->teams()->attach($team->id, ['role' => $invitation->first()->role]); $user->teams()->attach($team->id, ['role' => $invitation->first()->role]);
$invitation->delete(); $invitation->delete();
} else { } else {
$team = $user->teams()->first(); // MapleDeploy branding: root-team admins should land in
// the managed instance team, not their empty personal team.
$team = $user->mapledeployPreferredTeam();
} }
Auth::login($user); Auth::login($user);
session(['currentTeam' => $team]); session(['currentTeam' => $team]);

View file

@ -25,6 +25,12 @@ public function callback(string $provider)
} }
$email = strtolower($email); $email = strtolower($email);
$user = User::whereEmail($email)->first(); $user = User::whereEmail($email)->first();
// MapleDeploy branding: dashboard revocation scrambles passwords,
// clears sessions, and marks the user so email-matched OAuth cannot
// reopen access.
if ($user?->isMapledeployRevoked()) {
abort(403, 'User access has been revoked');
}
if (! $user) { if (! $user) {
$settings = instanceSettings(); $settings = instanceSettings();
if (! $settings->is_registration_enabled) { if (! $settings->is_registration_enabled) {

View file

@ -14,6 +14,7 @@
use App\Http\Middleware\EnsureMcpEnabled; use App\Http\Middleware\EnsureMcpEnabled;
use App\Http\Middleware\PreventRequestsDuringMaintenance; use App\Http\Middleware\PreventRequestsDuringMaintenance;
use App\Http\Middleware\RedirectIfAuthenticated; use App\Http\Middleware\RedirectIfAuthenticated;
use App\Http\Middleware\RejectMapledeployRevokedUser;
use App\Http\Middleware\TrimStrings; use App\Http\Middleware\TrimStrings;
use App\Http\Middleware\TrustHosts; use App\Http\Middleware\TrustHosts;
use App\Http\Middleware\TrustProxies; use App\Http\Middleware\TrustProxies;
@ -70,6 +71,7 @@ class Kernel extends HttpKernel
ShareErrorsFromSession::class, ShareErrorsFromSession::class,
VerifyCsrfToken::class, VerifyCsrfToken::class,
SubstituteBindings::class, SubstituteBindings::class,
RejectMapledeployRevokedUser::class,
CheckForcePasswordReset::class, CheckForcePasswordReset::class,
DecideWhatToDoWithUser::class, DecideWhatToDoWithUser::class,

View file

@ -16,6 +16,16 @@ public function handle(Request $request, Closure $next): Response
$currentTeam = auth()->user()?->recreate_personal_team(); $currentTeam = auth()->user()?->recreate_personal_team();
refreshSession($currentTeam); refreshSession($currentTeam);
} }
$preferredTeam = auth()?->user()?->mapledeployPreferredTeam();
if (
$preferredTeam &&
$preferredTeam->id === 0 &&
auth()?->user()?->currentTeam()?->id !== 0
) {
// MapleDeploy branding: repair sessions that landed in the empty
// personal team before dashboard-managed root-team access existed.
refreshSession($preferredTeam);
}
if (auth()?->user()?->currentTeam()) { if (auth()?->user()?->currentTeam()) {
refreshSession(auth()->user()->currentTeam()); refreshSession(auth()->user()->currentTeam());
} elseif (auth()?->user()?->teams?->count() > 0) { } elseif (auth()?->user()?->teams?->count() > 0) {

View file

@ -0,0 +1,37 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class RejectMapledeployRevokedUser
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
$user = auth()->user();
if (! $user?->isMapledeployRevoked()) {
return $next($request);
}
// MapleDeploy branding: revocation is marked on the user row so old
// browser sessions are rejected even when SESSION_DRIVER is not database.
auth()->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
if ($request->routeIs('login') || $request->path() === 'login') {
return $next($request);
}
return redirect()->route('login')->withErrors([
'email' => __('auth.failed'),
]);
}
}

View file

@ -1,58 +0,0 @@
<?php
namespace App\Livewire;
use DanHarrin\LivewireRateLimiting\WithRateLimiting;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Http;
use Livewire\Attributes\Validate;
use Livewire\Component;
class Help extends Component
{
use WithRateLimiting;
#[Validate(['required', 'min:10', 'max:1000'])]
public string $description;
#[Validate(['required', 'min:3', 'max:600'])]
public string $subject;
public function submit()
{
try {
$this->validate();
$this->rateLimit(3, 30);
$settings = instanceSettings();
$mail = new MailMessage;
$mail->view(
'emails.help',
[
'description' => $this->description,
]
);
$mail->subject("[HELP]: {$this->subject}");
$type = set_transanctional_email_settings($settings);
// Sending feedback through Cloud API
if (blank($type)) {
$url = 'https://app.coolify.io/api/feedback';
Http::post($url, [
'content' => 'User: `'.auth()->user()?->email.'` with subject: `'.$this->subject.'` has the following problem: `'.$this->description.'`',
]);
} else {
send_user_an_email($mail, auth()->user()?->email, 'feedback@coollabs.io');
}
$this->dispatch('success', 'Feedback sent.', 'We will get in touch with you as soon as possible.');
$this->reset('description', 'subject');
} catch (\Throwable $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.help')->layout('layouts.app');
}
}

View file

@ -28,8 +28,7 @@ class Advanced extends Component
public ?string $allowed_ips = null; public ?string $allowed_ips = null;
#[Validate('boolean')] // MapleDeploy branding: is_sponsorship_popup_enabled removed (popup removed)
public bool $is_sponsorship_popup_enabled;
#[Validate('boolean')] #[Validate('boolean')]
public bool $disable_two_step_confirmation; public bool $disable_two_step_confirmation;
@ -49,7 +48,6 @@ public function rules()
'custom_dns_servers' => ['nullable', 'string', new ValidDnsServers], 'custom_dns_servers' => ['nullable', 'string', new ValidDnsServers],
'is_api_enabled' => 'boolean', 'is_api_enabled' => 'boolean',
'allowed_ips' => ['nullable', 'string', new ValidIpOrCidr], 'allowed_ips' => ['nullable', 'string', new ValidIpOrCidr],
'is_sponsorship_popup_enabled' => 'boolean',
'disable_two_step_confirmation' => 'boolean', 'disable_two_step_confirmation' => 'boolean',
'is_wire_navigate_enabled' => 'boolean', 'is_wire_navigate_enabled' => 'boolean',
'is_mcp_server_enabled' => 'boolean', 'is_mcp_server_enabled' => 'boolean',
@ -69,7 +67,6 @@ public function mount()
$this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled; $this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
$this->is_api_enabled = $this->settings->is_api_enabled; $this->is_api_enabled = $this->settings->is_api_enabled;
$this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation; $this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation;
$this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled;
$this->is_wire_navigate_enabled = $this->settings->is_wire_navigate_enabled ?? true; $this->is_wire_navigate_enabled = $this->settings->is_wire_navigate_enabled ?? true;
$this->is_mcp_server_enabled = $this->settings->is_mcp_server_enabled ?? false; $this->is_mcp_server_enabled = $this->settings->is_mcp_server_enabled ?? false;
} }
@ -152,7 +149,6 @@ public function instantSave()
$this->settings->custom_dns_servers = $this->custom_dns_servers; $this->settings->custom_dns_servers = $this->custom_dns_servers;
$this->settings->is_api_enabled = $this->is_api_enabled; $this->settings->is_api_enabled = $this->is_api_enabled;
$this->settings->allowed_ips = $this->allowed_ips; $this->settings->allowed_ips = $this->allowed_ips;
$this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled;
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation; $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation;
$this->settings->is_wire_navigate_enabled = $this->is_wire_navigate_enabled; $this->settings->is_wire_navigate_enabled = $this->is_wire_navigate_enabled;
$this->settings->is_mcp_server_enabled = $this->is_mcp_server_enabled; $this->settings->is_mcp_server_enabled = $this->is_mcp_server_enabled;

View file

@ -92,7 +92,7 @@ protected static function boot()
$team = [ $team = [
'name' => $user->name."'s Team", 'name' => $user->name."'s Team",
'personal_team' => true, 'personal_team' => true,
'show_boarding' => true, 'show_boarding' => false,
]; ];
if ($user->id === 0) { if ($user->id === 0) {
$team['id'] = 0; $team['id'] = 0;
@ -196,7 +196,7 @@ public function recreate_personal_team()
$team = [ $team = [
'name' => $this->name."'s Team", 'name' => $this->name."'s Team",
'personal_team' => true, 'personal_team' => true,
'show_boarding' => true, 'show_boarding' => false,
]; ];
if ($this->id === 0) { if ($this->id === 0) {
$team['id'] = 0; $team['id'] = 0;
@ -209,6 +209,20 @@ public function recreate_personal_team()
return $new_team; return $new_team;
} }
public function mapledeployPreferredTeam(): ?Team
{
// MapleDeploy branding: dashboard-managed users are attached to the
// root team so they can administer the customer's managed instance.
$rootTeam = $this->teams->firstWhere('id', 0);
$rootRole = data_get($rootTeam, 'pivot.role');
if ($rootTeam && ($rootRole === 'admin' || $rootRole === 'owner')) {
return $rootTeam;
}
return $this->teams->firstWhere('personal_team', true)
?? $this->teams->first();
}
public function createToken(string $name, array $abilities = ['*'], ?DateTimeInterface $expiresAt = null) public function createToken(string $name, array $abilities = ['*'], ?DateTimeInterface $expiresAt = null)
{ {
$plainTextToken = sprintf( $plainTextToken = sprintf(
@ -269,9 +283,19 @@ public function sendVerificationEmail()
public function sendPasswordResetNotification($token): void public function sendPasswordResetNotification($token): void
{ {
if ($this->isMapledeployRevoked()) {
return;
}
$this?->notify(new TransactionalEmailsResetPassword($token)); $this?->notify(new TransactionalEmailsResetPassword($token));
} }
public function isMapledeployRevoked(): bool
{
// MapleDeploy branding: dashboard-managed revocation stores a persistent marker.
return str_starts_with((string) $this->remember_token, 'mapledeploy-revoked:');
}
public function isAdmin() public function isAdmin()
{ {
return $this->role() === 'admin' || $this->role() === 'owner'; return $this->role() === 'admin' || $this->role() === 'owner';

View file

@ -7,6 +7,7 @@
use App\Actions\Fortify\UpdateUserPassword; use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation; use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Models\OauthSetting; use App\Models\OauthSetting;
use App\Models\TeamInvitation;
use App\Models\User; use App\Models\User;
use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -44,13 +45,13 @@ public function boot(): void
{ {
Fortify::createUsersUsing(CreateNewUser::class); Fortify::createUsersUsing(CreateNewUser::class);
Fortify::registerView(function () { Fortify::registerView(function () {
$isFirstUser = User::count() === 0;
$settings = instanceSettings(); $settings = instanceSettings();
if (! $settings->is_registration_enabled) { if (! $settings->is_registration_enabled) {
return redirect()->route('login'); return redirect()->route('login');
} }
$isFirstUser = User::count() === 0;
return view('auth.register', [ return view('auth.register', [
'isFirstUser' => $isFirstUser, 'isFirstUser' => $isFirstUser,
]); ]);
@ -60,8 +61,11 @@ public function boot(): void
$settings = instanceSettings(); $settings = instanceSettings();
$enabled_oauth_providers = OauthSetting::where('enabled', true)->get(); $enabled_oauth_providers = OauthSetting::where('enabled', true)->get();
$users = User::count(); $users = User::count();
if ($users == 0) { // MapleDeploy branding: public registration is disabled by default
// If there are no users, redirect to registration // because the dashboard creates the first admin over SSH. Do not
// redirect to /register in that fail-closed state, or fresh/failed
// provisioning loops between login and registration.
if ($users == 0 && $settings->is_registration_enabled) {
return redirect()->route('register'); return redirect()->route('register');
} }
@ -82,7 +86,7 @@ public function boot(): void
$user->save(); $user->save();
// Check if user has a pending invitation they haven't accepted yet // Check if user has a pending invitation they haven't accepted yet
$invitation = \App\Models\TeamInvitation::whereEmail($email)->first(); $invitation = TeamInvitation::whereEmail($email)->first();
if ($invitation && $invitation->isValid()) { if ($invitation && $invitation->isValid()) {
// User is logging in for the first time after being invited // User is logging in for the first time after being invited
// Attach them to the invited team if not already attached // Attach them to the invited team if not already attached
@ -92,8 +96,9 @@ public function boot(): void
$user->currentTeam = $invitation->team; $user->currentTeam = $invitation->team;
$invitation->delete(); $invitation->delete();
} else { } else {
// Normal login - use personal team // MapleDeploy branding: root-team admins should land in
$user->currentTeam = $user->teams->firstWhere('personal_team', true); // the managed instance team, not their empty personal team.
$user->currentTeam = $user->mapledeployPreferredTeam();
if (! $user->currentTeam) { if (! $user->currentTeam) {
$user->currentTeam = $user->recreate_personal_team(); $user->currentTeam = $user->recreate_personal_team();
} }

View file

@ -410,13 +410,14 @@ function get_route_parameters(): array
function get_latest_sentinel_version(): string function get_latest_sentinel_version(): string
{ {
// MapleDeploy branding: our versions.json omits the sentinel key, so fall back to 'latest' (matches upstream's fallback in CheckAndStartSentinelJob)
try { try {
$response = Http::get(config('constants.coolify.versions_url')); $response = Http::get(config('constants.coolify.versions_url'));
$versions = $response->json(); $versions = $response->json();
return data_get($versions, 'coolify.sentinel.version'); return data_get($versions, 'coolify.sentinel.version') ?? 'latest';
} catch (Throwable) { } catch (\Throwable) {
return '0.0.0'; return 'latest';
} }
} }
function get_latest_version_of_coolify(): string function get_latest_version_of_coolify(): string

View file

@ -17,7 +17,7 @@
| |
*/ */
'name' => env('APP_NAME', 'Coolify'), 'name' => env('APP_NAME', 'MapleDeploy'), // MapleDeploy branding
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View file

@ -1,27 +1,28 @@
<?php <?php
return [ return [
// MapleDeploy branding: registry pointed to Forgejo, auto-update disabled by default
'coolify' => [ 'coolify' => [
'version' => '4.1.0', 'version' => '4.1.0',
'helper_version' => '1.0.14', 'helper_version' => '1.0.14',
'realtime_version' => '1.0.15', 'realtime_version' => '1.0.15',
'railpack_version' => '0.23.0', 'railpack_version' => '0.23.0',
'self_hosted' => env('SELF_HOSTED', true), 'self_hosted' => env('SELF_HOSTED', true),
'autoupdate' => env('AUTOUPDATE'), 'autoupdate' => env('AUTOUPDATE', false),
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
'registry_url' => env('REGISTRY_URL', 'ghcr.io'), 'registry_url' => env('REGISTRY_URL', 'forgejo.mapledeploy.ca'),
'helper_image' => env('HELPER_IMAGE', env('REGISTRY_URL', 'ghcr.io').'/coollabsio/coolify-helper'), 'helper_image' => env('HELPER_IMAGE', 'ghcr.io/coollabsio/coolify-helper'),
'realtime_image' => env('REALTIME_IMAGE', env('REGISTRY_URL', 'ghcr.io').'/coollabsio/coolify-realtime'), 'realtime_image' => env('REALTIME_IMAGE', 'ghcr.io/coollabsio/coolify-realtime'),
'is_windows_docker_desktop' => env('IS_WINDOWS_DOCKER_DESKTOP', false), 'is_windows_docker_desktop' => env('IS_WINDOWS_DOCKER_DESKTOP', false),
'cdn_url' => env('CDN_URL', 'https://cdn.coollabs.io'), 'cdn_url' => env('CDN_URL', 'https://updates.mapledeploy.ca'),
'versions_url' => env('VERSIONS_URL', env('CDN_URL', 'https://cdn.coollabs.io').'/coolify/versions.json'), 'versions_url' => env('VERSIONS_URL', env('CDN_URL', 'https://updates.mapledeploy.ca').'/coolify/versions.json'),
'upgrade_script_url' => env('UPGRADE_SCRIPT_URL', env('CDN_URL', 'https://cdn.coollabs.io').'/coolify/upgrade.sh'), 'upgrade_script_url' => env('UPGRADE_SCRIPT_URL', env('CDN_URL', 'https://updates.mapledeploy.ca').'/coolify/upgrade.sh'),
'releases_url' => 'https://cdn.coolify.io/releases.json', 'releases_url' => 'https://cdn.coolify.io/releases.json',
], ],
'urls' => [ 'urls' => [
'docs' => 'https://coolify.io/docs', 'docs' => 'https://mapledeploy.ca/docs',
'contact' => 'https://coolify.io/docs/contact', 'contact' => 'https://mapledeploy.ca/contact',
], ],
'services' => [ 'services' => [
@ -90,12 +91,12 @@
'verification_code_expiry_minutes' => 10, 'verification_code_expiry_minutes' => 10,
], ],
// MapleDeploy branding: telemetry disabled
'sentry' => [ 'sentry' => [
'sentry_dsn' => env('SENTRY_DSN'), 'sentry_dsn' => null,
], ],
'webhooks' => [ 'webhooks' => [
'feedback_discord_webhook' => env('FEEDBACK_DISCORD_WEBHOOK'),
'dev_webhook' => env('SERVEO_URL'), 'dev_webhook' => env('SERVEO_URL'),
], ],

View file

@ -48,14 +48,14 @@
'prefix_indexes' => true, 'prefix_indexes' => true,
'search_path' => 'public', 'search_path' => 'public',
'sslmode' => 'prefer', 'sslmode' => 'prefer',
'options' => [ 'options' => defined('\PDO::PGSQL_ATTR_DISABLE_PREPARES')
(defined('Pdo\Pgsql::ATTR_DISABLE_PREPARES') ? \Pdo\Pgsql::ATTR_DISABLE_PREPARES : \PDO::PGSQL_ATTR_DISABLE_PREPARES) => env('DB_DISABLE_PREPARES', false), ? [PDO::PGSQL_ATTR_DISABLE_PREPARES => env('DB_DISABLE_PREPARES', false)]
], : [],
], ],
'testing' => [ 'testing' => [
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => ':memory:', 'database' => env('DB_DATABASE', ':memory:'),
'prefix' => '', 'prefix' => '',
'foreign_key_constraints' => true, 'foreign_key_constraints' => true,
], ],

View file

@ -118,7 +118,7 @@
'navigate' => [ 'navigate' => [
'show_progress_bar' => true, 'show_progress_bar' => true,
'progress_bar_color' => '#ffff00', 'progress_bar_color' => '#fde047',
], ],
/* /*

View file

@ -13,7 +13,7 @@ public function up(): void
{ {
Schema::table('instance_settings', function (Blueprint $table) { Schema::table('instance_settings', function (Blueprint $table) {
$table->boolean('is_dns_validation_enabled')->default(true); $table->boolean('is_dns_validation_enabled')->default(true);
$table->string('custom_dns_servers')->nullable()->default('1.1.1.1'); $table->string('custom_dns_servers')->nullable()->default('149.112.121.10,149.112.122.10');
}); });
} }

View file

@ -0,0 +1,47 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
$columns = array_values(array_filter(
['setup_token', 'setup_callback_url'],
fn (string $column) => Schema::hasColumn('instance_settings', $column),
));
if ($columns === []) {
return;
}
Schema::table('instance_settings', function (Blueprint $table) use ($columns) {
// MapleDeploy branding: remove legacy one-time setup columns from customer instances.
$table->dropColumn($columns);
});
}
public function down(): void
{
$missingColumns = array_values(array_filter(
['setup_token', 'setup_callback_url'],
fn (string $column) => ! Schema::hasColumn('instance_settings', $column),
));
if ($missingColumns === []) {
return;
}
Schema::table('instance_settings', function (Blueprint $table) use ($missingColumns) {
if (in_array('setup_token', $missingColumns, true)) {
$table->text('setup_token')->nullable();
}
if (in_array('setup_callback_url', $missingColumns, true)) {
$table->text('setup_callback_url')->nullable();
}
});
}
};

View file

@ -15,7 +15,9 @@ public function run(): void
{ {
InstanceSettings::create([ InstanceSettings::create([
'id' => 0, 'id' => 0,
'is_registration_enabled' => true, // MapleDeploy branding: dashboard provisioning creates the first
// admin over SSH, so public registration must fail closed.
'is_registration_enabled' => false,
'is_api_enabled' => isDev(), 'is_api_enabled' => isDev(),
'smtp_enabled' => true, 'smtp_enabled' => true,
'smtp_host' => 'coolify-mail', 'smtp_host' => 'coolify-mail',

View file

@ -47,6 +47,9 @@ public function run(): void
if (InstanceSettings::find(0) == null) { if (InstanceSettings::find(0) == null) {
InstanceSettings::create([ InstanceSettings::create([
'id' => 0, 'id' => 0,
// MapleDeploy branding: dashboard provisioning creates the
// first admin over SSH, so public registration must fail closed.
'is_registration_enabled' => false,
]); ]);
} }

View file

@ -1,6 +1,6 @@
services: services:
coolify: coolify:
image: "${REGISTRY_URL:-ghcr.io}/coollabsio/coolify:${LATEST_IMAGE:-latest}" image: "${REGISTRY_URL:-forgejo.mapledeploy.ca}/rosslh/coolify:${LATEST_IMAGE:-latest}"
volumes: volumes:
- type: bind - type: bind
source: /data/coolify/source/.env source: /data/coolify/source/.env
@ -60,7 +60,7 @@ services:
retries: 10 retries: 10
timeout: 2s timeout: 2s
soketi: soketi:
image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.15' image: 'ghcr.io/coollabsio/coolify-realtime:1.0.15' # MapleDeploy branding: pinned to ghcr.io, not mirrored
ports: ports:
- "${SOKETI_PORT:-6001}:6001" - "${SOKETI_PORT:-6001}:6001"
- "6002:6002" - "6002:6002"

View file

@ -144,6 +144,16 @@ COPY --chown=www-data:www-data composer.json composer.lock ./
COPY --chown=www-data:www-data app ./app COPY --chown=www-data:www-data app ./app
COPY --chown=www-data:www-data bootstrap ./bootstrap COPY --chown=www-data:www-data bootstrap ./bootstrap
COPY --chown=www-data:www-data config ./config COPY --chown=www-data:www-data config ./config
# MapleDeploy: inject build version into constants.php at build time.
# The version in git stays at the upstream value to avoid rebase conflicts.
# CI passes the timestamped version (e.g. 4.0.0-beta.468.202603140006) as a build arg.
ARG MAPLEDEPLOY_VERSION=""
RUN if [ -n "$MAPLEDEPLOY_VERSION" ]; then \
sed -i "s/'version' => '[^']*'/'version' => '$MAPLEDEPLOY_VERSION'/" config/constants.php && \
chown www-data:www-data config/constants.php; \
fi
COPY --chown=www-data:www-data database ./database COPY --chown=www-data:www-data database ./database
COPY --chown=www-data:www-data lang ./lang COPY --chown=www-data:www-data lang ./lang
COPY --chown=www-data:www-data public ./public COPY --chown=www-data:www-data public ./public

View file

@ -18,7 +18,7 @@
"auth.register_now": "Register", "auth.register_now": "Register",
"auth.logout": "Logout", "auth.logout": "Logout",
"auth.register": "Register", "auth.register": "Register",
"auth.registration_disabled": "Registration is disabled. Please contact the administrator.", "auth.registration_disabled": "Set up server access in the MapleDeploy dashboard.",
"auth.reset_password": "Reset password", "auth.reset_password": "Reset password",
"auth.failed": "These credentials do not match our records.", "auth.failed": "These credentials do not match our records.",
"auth.failed.callback": "Failed to process callback from login provider.", "auth.failed.callback": "Failed to process callback from login provider.",
@ -41,4 +41,4 @@
"resource.delete_configurations": "Permanently delete all configuration files from the server.", "resource.delete_configurations": "Permanently delete all configuration files from the server.",
"database.delete_backups_locally": "All backups will be permanently deleted from local storage.", "database.delete_backups_locally": "All backups will be permanently deleted from local storage.",
"warning.sslipdomain": "Your configuration is saved, but sslip domain with https is <span class='dark:text-red-500 text-red-500 font-bold'>NOT</span> recommended, because Let's Encrypt servers with this public domain are rate limited (SSL certificate validation will fail). <br><br>Use your own domain instead." "warning.sslipdomain": "Your configuration is saved, but sslip domain with https is <span class='dark:text-red-500 text-red-500 font-bold'>NOT</span> recommended, because Let's Encrypt servers with this public domain are rate limited (SSL certificate validation will fail). <br><br>Use your own domain instead."
} }

View file

@ -17,7 +17,7 @@
"auth.register_now": "S'enregistrer", "auth.register_now": "S'enregistrer",
"auth.logout": "Déconnexion", "auth.logout": "Déconnexion",
"auth.register": "S'enregistrer", "auth.register": "S'enregistrer",
"auth.registration_disabled": "L'enregistrement est désactivé. Merci de contacter l'administrateur.", "auth.registration_disabled": "Configurez laccès au serveur dans le tableau de bord MapleDeploy.",
"auth.reset_password": "Réinitialiser le mot de passe", "auth.reset_password": "Réinitialiser le mot de passe",
"auth.failed": "Aucune correspondance n'a été trouvée pour les informations d'identification renseignées.", "auth.failed": "Aucune correspondance n'a été trouvée pour les informations d'identification renseignées.",
"auth.failed.callback": "Erreur lors du processus de retour de la plateforme de connexion.", "auth.failed.callback": "Erreur lors du processus de retour de la plateforme de connexion.",
@ -40,4 +40,4 @@
"resource.delete_configurations": "Supprimer définitivement tous les fichiers de configuration du serveur.", "resource.delete_configurations": "Supprimer définitivement tous les fichiers de configuration du serveur.",
"database.delete_backups_locally": "Toutes les sauvegardes seront définitivement supprimées du stockage local.", "database.delete_backups_locally": "Toutes les sauvegardes seront définitivement supprimées du stockage local.",
"warning.sslipdomain": "Votre configuration est enregistrée, mais l'utilisation du domaine sslip avec https <span class='dark:text-red-500 text-red-500 font-bold'>N'EST PAS</span> recommandée, car les serveurs Let's Encrypt avec ce domaine public sont limités en taux (la validation du certificat SSL échouera). <br><br>Utilisez plutôt votre propre domaine." "warning.sslipdomain": "Votre configuration est enregistrée, mais l'utilisation du domaine sslip avec https <span class='dark:text-red-500 text-red-500 font-bold'>N'EST PAS</span> recommandée, car les serveurs Let's Encrypt avec ce domaine public sont limités en taux (la validation du certificat SSL échouera). <br><br>Utilisez plutôt votre propre domaine."
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -13,36 +13,77 @@
@custom-variant dark (&:where(.dark, .dark *)); @custom-variant dark (&:where(.dark, .dark *));
/* MapleDeploy branding: Canadian red accent, stone greys */
@theme { @theme {
--font-sans: 'Geist Sans', Inter, sans-serif; --font-sans: Inter, sans-serif;
--font-mono: 'Geist Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; --font-display: 'Overlock', sans-serif;
--font-geist-sans: 'Geist Sans', Inter, sans-serif; --font-mono: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
--font-logs: 'Geist Mono', 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace; --font-logs: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
--color-base: #101010; --color-base: #292524;
--color-warning: #fcd452; --color-warning: #fde047;
--color-warning-50: #fefce8; --color-warning-50: #fefce8;
--color-warning-100: #fef9c3; --color-warning-100: #fef9c3;
--color-warning-200: #fef08a; --color-warning-200: #fef08a;
--color-warning-300: #fde047; --color-warning-300: #fde047;
--color-warning-400: #fcd452; --color-warning-400: #facc15;
--color-warning-500: #facc15; --color-warning-500: #eab308;
--color-warning-600: #ca8a04; --color-warning-600: #ca8a04;
--color-warning-700: #a16207; --color-warning-700: #a16207;
--color-warning-800: #854d0e; --color-warning-800: #854d0e;
--color-warning-900: #713f12; --color-warning-900: #713f12;
--color-success: #22C55E; --color-success: #22C55E;
--color-error: #dc2626; /* MapleDeploy branding: red palette hue-normalized to OKLCH h=29.38 (#D52A1E) */
--color-coollabs-50: #f5f0ff; --color-error: #dc281c;
--color-coollabs: #6b16ed; --color-coollabs-50: #fef3f1;
--color-coollabs-100: #7317ff; --color-coollabs: #d52b1f;
--color-coollabs-200: #5a12c7; --color-coollabs-100: #f34d3d;
--color-coollabs-300: #4a0fa3; --color-coollabs-200: #bc251a;
--color-coolgray-100: #181818; --color-coollabs-300: #9c2117;
--color-coolgray-200: #202020; /* Override Tailwind's red scale so red-* utility classes match the MapleDeploy brand hue */
--color-coolgray-300: #242424; --color-red-50: #fef1ef;
--color-coolgray-400: #282828; --color-red-100: #ffe3df;
--color-coolgray-500: #323232; --color-red-200: #ffcec5;
--color-red-300: #feaa9d;
--color-red-400: #fb7968;
--color-red-500: #f34d3d;
--color-red-600: #d52b1f;
--color-red-700: #bc251a;
--color-red-800: #9c2117;
--color-red-900: #812219;
--color-red-950: #460d08;
--color-coolgray-100: #1c1917;
--color-coolgray-200: #35322f;
--color-coolgray-300: #44403c;
--color-coolgray-400: #57534e;
--color-coolgray-500: #78716c;
/* MapleDeploy branding: remap neutral and gray stone for warm tone consistency with marketing/dashboard.
Upstream uses neutral for text/borders and gray for backgrounds/surfaces. Remapping both to stone
warms the entire UI to match our design system, covering ~1000 class references without touching
any Blade templates. */
--color-neutral-50: oklch(98.5% 0.001 106.423);
--color-neutral-100: oklch(97% 0.001 106.424);
--color-neutral-200: oklch(92.3% 0.003 48.717);
--color-neutral-300: oklch(86.9% 0.005 56.366);
--color-neutral-400: oklch(70.9% 0.01 56.259);
--color-neutral-500: oklch(55.3% 0.013 58.071);
--color-neutral-600: oklch(44.4% 0.011 73.639);
--color-neutral-700: oklch(37.4% 0.01 67.558);
--color-neutral-800: oklch(26.8% 0.007 34.298);
--color-neutral-900: oklch(21.6% 0.006 56.043);
--color-neutral-950: oklch(14.7% 0.004 49.25);
--color-gray-50: oklch(98.5% 0.001 106.423);
--color-gray-100: oklch(97% 0.001 106.424);
--color-gray-200: oklch(92.3% 0.003 48.717);
--color-gray-300: oklch(86.9% 0.005 56.366);
--color-gray-400: oklch(70.9% 0.01 56.259);
--color-gray-500: oklch(55.3% 0.013 58.071);
--color-gray-600: oklch(44.4% 0.011 73.639);
--color-gray-700: oklch(37.4% 0.01 67.558);
--color-gray-800: oklch(26.8% 0.007 34.298);
--color-gray-900: oklch(21.6% 0.006 56.043);
--color-gray-950: oklch(14.7% 0.004 49.25);
} }
/* /*
@ -95,7 +136,8 @@ @keyframes lds-heart {
*/ */
html, html,
body { body {
@apply w-full min-h-full bg-gray-50 dark:bg-base dark:text-neutral-400; /* MapleDeploy branding: text-stone-800 body text matches marketing/dashboard */
@apply w-full min-h-full text-stone-800 bg-gray-50 dark:bg-base dark:text-neutral-400;
} }
body { body {
@ -125,19 +167,19 @@ button[isHighlighted]:not(:disabled) {
} }
h1 { h1 {
@apply text-3xl font-bold dark:text-white; @apply text-3xl font-bold font-display dark:text-white;
} }
h2 { h2 {
@apply text-xl font-bold dark:text-white; @apply text-xl font-bold font-display dark:text-white;
} }
h3 { h3 {
@apply text-lg font-bold dark:text-white; @apply text-lg font-bold font-display dark:text-white;
} }
h4 { h4 {
@apply text-base font-bold dark:text-white; @apply text-base font-bold font-display dark:text-white;
} }
a { a {

View file

@ -70,18 +70,12 @@ @font-face {
src: url('../fonts/inter-v13-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2') format('woff2'); src: url('../fonts/inter-v13-cyrillic_cyrillic-ext_greek_greek-ext_latin_latin-ext_vietnamese-regular.woff2') format('woff2');
} }
/* MapleDeploy branding: Overlock for headings */
@font-face { @font-face {
font-display: swap; font-display: swap;
font-family: 'Geist Mono'; font-family: 'Overlock';
font-style: normal; font-style: normal;
font-weight: 100 900; font-weight: 900;
src: url('../fonts/geist-mono-variable.woff2') format('woff2'); src: url('../fonts/overlock-v19-latin-900.woff2') format('woff2'),
} url('../fonts/overlock-v19-latin-900.ttf') format('truetype');
@font-face {
font-display: swap;
font-family: 'Geist Sans';
font-style: normal;
font-weight: 100 900;
src: url('../fonts/geist-sans-variable.woff2') format('woff2');
} }

View file

@ -40,11 +40,11 @@ @utility input-sticky {
} }
&:focus-visible { &:focus-visible {
box-shadow: inset 4px 0 0 #6b16ed, inset 0 0 0 1px #e5e5e5; box-shadow: inset 4px 0 0 #d52b1f, inset 0 0 0 1px #e5e5e5;
} }
&:where(.dark, .dark *):focus-visible { &:where(.dark, .dark *):focus-visible {
box-shadow: inset 4px 0 0 #fcd452, inset 0 0 0 1px #242424; box-shadow: inset 4px 0 0 #fde047, inset 0 0 0 1px #242424;
} }
} }
@ -82,11 +82,11 @@ @utility input {
@apply focus-visible:outline-none; @apply focus-visible:outline-none;
&:focus-visible { &:focus-visible {
box-shadow: inset 4px 0 0 #6b16ed, inset 0 0 0 2px #e5e5e5; box-shadow: inset 4px 0 0 #d52b1f, inset 0 0 0 2px #e5e5e5;
} }
&:where(.dark, .dark *):focus-visible { &:where(.dark, .dark *):focus-visible {
box-shadow: inset 4px 0 0 #fcd452, inset 0 0 0 2px #242424; box-shadow: inset 4px 0 0 #fde047, inset 0 0 0 2px #242424;
} }
&:read-only { &:read-only {
@ -113,11 +113,11 @@ @utility select {
} }
&:focus-visible { &:focus-visible {
box-shadow: inset 4px 0 0 #6b16ed, inset 0 0 0 2px #e5e5e5; box-shadow: inset 4px 0 0 #d52b1f, inset 0 0 0 2px #e5e5e5;
} }
&:where(.dark, .dark *):focus-visible { &:where(.dark, .dark *):focus-visible {
box-shadow: inset 4px 0 0 #fcd452, inset 0 0 0 2px #242424; box-shadow: inset 4px 0 0 #fde047, inset 0 0 0 2px #242424;
} }
} }
@ -138,7 +138,7 @@ @utility tag {
} }
@utility add-tag { @utility add-tag {
@apply flex items-center px-2 text-xs cursor-pointer dark:text-neutral-500/20 text-neutral-500 group-hover:text-neutral-700 dark:group-hover:text-white dark:hover:bg-coolgray-300 hover:bg-neutral-200; @apply flex items-center px-2 text-xs cursor-pointer dark:text-neutral-500 text-neutral-500 group-hover:text-neutral-700 dark:group-hover:text-white dark:hover:bg-coolgray-300 hover:bg-neutral-200;
} }
@utility dropdown-item { @utility dropdown-item {
@ -213,7 +213,8 @@ @utility icon {
} }
@utility scrollbar { @utility scrollbar {
@apply scrollbar-thumb-coollabs-100 scrollbar-track-neutral-200 dark:scrollbar-track-coolgray-200 scrollbar-thin; /* MapleDeploy branding: yellow scrollbar thumb instead of Coolify red */
@apply scrollbar-thumb-warning scrollbar-track-neutral-200 dark:scrollbar-track-coolgray-200 scrollbar-thin;
} }
@utility main { @utility main {
@ -273,7 +274,8 @@ @utility description {
} }
@utility bg-coollabs-gradient { @utility bg-coollabs-gradient {
@apply from-purple-500 via-pink-500 to-red-500 bg-linear-to-r; /* MapleDeploy branding */
@apply from-red-700 via-red-500 to-red-400 bg-linear-to-r;
} }
@utility text-helper { @utility text-helper {
@ -337,7 +339,7 @@ @utility log-warning {
} }
@utility log-debug { @utility log-debug {
@apply bg-purple-500/10 dark:bg-purple-500/15; @apply bg-stone-500/10 dark:bg-stone-500/15;
} }
@utility log-info { @utility log-info {

Binary file not shown.

Binary file not shown.

View file

@ -3,9 +3,10 @@
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0"> <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<div class="w-full max-w-md space-y-8"> <div class="w-full max-w-md space-y-8">
<div class="text-center space-y-2"> <div class="text-center space-y-2">
<h1 class="!text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white"> <div class="flex justify-center">
Coolify <img src="https://mapledeploy.ca/api/logo/lockup?height=80" alt="MapleDeploy" class="h-12 dark:hidden" />
</h1> <img src="https://mapledeploy.ca/api/logo/lockup?height=80&dark=true" alt="MapleDeploy" class="hidden h-12 dark:block" />
</div>
<p class="text-lg dark:text-neutral-400"> <p class="text-lg dark:text-neutral-400">
Confirm Your Password Confirm Your Password
</p> </p>

View file

@ -3,9 +3,10 @@
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0"> <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<div class="w-full max-w-md space-y-8"> <div class="w-full max-w-md space-y-8">
<div class="text-center space-y-2"> <div class="text-center space-y-2">
<h1 class="!text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white"> <div class="flex justify-center">
Coolify <img src="https://mapledeploy.ca/api/logo/lockup?height=80" alt="MapleDeploy" class="h-12 dark:hidden" />
</h1> <img src="https://mapledeploy.ca/api/logo/lockup?height=80&dark=true" alt="MapleDeploy" class="hidden h-12 dark:block" />
</div>
<p class="text-lg dark:text-neutral-400"> <p class="text-lg dark:text-neutral-400">
{{ __('auth.forgot_password_heading') }} {{ __('auth.forgot_password_heading') }}
</p> </p>

View file

@ -3,12 +3,33 @@
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0"> <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<div class="w-full max-w-md space-y-8"> <div class="w-full max-w-md space-y-8">
<div class="text-center space-y-2"> <div class="text-center space-y-2">
<h1 class="!text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white"> <div class="flex justify-center">
Coolify <img src="https://mapledeploy.ca/api/logo/lockup?height=80" alt="MapleDeploy" class="h-12 dark:hidden" />
</h1> <img src="https://mapledeploy.ca/api/logo/lockup?height=80&dark=true" alt="MapleDeploy" class="hidden h-12 dark:block" />
</div>
</div> </div>
<div class="space-y-6"> <div class="space-y-6">
@if (!empty($setup_pending))
{{-- MapleDeploy: setup token required but not provided --}}
<div class="mb-6 p-4 bg-warning/10 border border-warning rounded-lg">
<div class="flex gap-3">
<svg class="size-5 text-warning flex-shrink-0 mt-0.5" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
clip-rule="evenodd" />
</svg>
<div>
<p class="font-bold text-warning">Setup pending</p>
<p class="text-sm dark:text-white text-black">
Initial setup has not been completed. Please use the setup link from your
<a href="https://app.mapledeploy.ca" class="underline hover:text-warning">MapleDeploy dashboard</a>.
</p>
</div>
</div>
</div>
@else
@if (session('status')) @if (session('status'))
<div class="mb-6 p-4 bg-success/10 border border-success rounded-lg"> <div class="mb-6 p-4 bg-success/10 border border-success rounded-lg">
<p class="text-sm text-success">{{ session('status') }}</p> <p class="text-sm text-success">{{ session('status') }}</p>
@ -95,6 +116,7 @@ class="block w-full text-center py-3 px-4 rounded-lg border border-neutral-300 d
@endforeach @endforeach
</div> </div>
@endif @endif
@endif {{-- end setup_pending --}}
</div> </div>
</div> </div>
</div> </div>

View file

@ -15,9 +15,10 @@ function getOldOrLocal($key, $localValue)
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0"> <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<div class="w-full max-w-md space-y-8"> <div class="w-full max-w-md space-y-8">
<div class="text-center space-y-2"> <div class="text-center space-y-2">
<h1 class="!text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white"> <div class="flex justify-center">
Coolify <img src="https://mapledeploy.ca/api/logo/lockup?height=80" alt="MapleDeploy" class="h-12 dark:hidden" />
</h1> <img src="https://mapledeploy.ca/api/logo/lockup?height=80&dark=true" alt="MapleDeploy" class="hidden h-12 dark:block" />
</div>
<p class="text-lg dark:text-neutral-400"> <p class="text-lg dark:text-neutral-400">
Create your account Create your account
</p> </p>
@ -96,4 +97,4 @@ class="block w-full text-center py-3 px-4 rounded-lg border border-neutral-300 d
</div> </div>
</div> </div>
</section> </section>
</x-layout-simple> </x-layout-simple>

View file

@ -3,9 +3,10 @@
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0"> <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<div class="w-full max-w-md space-y-8"> <div class="w-full max-w-md space-y-8">
<div class="text-center space-y-2"> <div class="text-center space-y-2">
<h1 class="!text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white"> <div class="flex justify-center">
Coolify <img src="https://mapledeploy.ca/api/logo/lockup?height=80" alt="MapleDeploy" class="h-12 dark:hidden" />
</h1> <img src="https://mapledeploy.ca/api/logo/lockup?height=80&dark=true" alt="MapleDeploy" class="hidden h-12 dark:block" />
</div>
<p class="text-lg dark:text-neutral-400"> <p class="text-lg dark:text-neutral-400">
{{ __('auth.reset_password') }} {{ __('auth.reset_password') }}
</p> </p>

View file

@ -47,9 +47,10 @@
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0"> <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<div class="w-full max-w-md space-y-8"> <div class="w-full max-w-md space-y-8">
<div class="text-center space-y-2"> <div class="text-center space-y-2">
<h1 class="!text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white"> <div class="flex justify-center">
Coolify <img src="https://mapledeploy.ca/api/logo/lockup?height=80" alt="MapleDeploy" class="h-12 dark:hidden" />
</h1> <img src="https://mapledeploy.ca/api/logo/lockup?height=80&dark=true" alt="MapleDeploy" class="hidden h-12 dark:block" />
</div>
<p class="text-lg dark:text-neutral-400"> <p class="text-lg dark:text-neutral-400">
Two-Factor Authentication Two-Factor Authentication
</p> </p>

View file

@ -48,7 +48,7 @@
{!! $icon !!} {!! $icon !!}
</div> </div>
<div class="ml-3 {{ $dismissible ? 'pr-8' : '' }}"> <div class="ml-3 {{ $dismissible ? 'pr-8' : '' }}">
<div class="text-base font-bold {{ $colorScheme['title'] }}"> <div class="text-base font-bold font-display {{ $colorScheme['title'] }}">
{{ $title }} {{ $title }}
</div> </div>
<div class="mt-2 text-sm {{ $colorScheme['text'] }}"> <div class="mt-2 text-sm {{ $colorScheme['text'] }}">

View file

@ -1,6 +1,7 @@
{{ Illuminate\Mail\Markdown::parse('---') }} {{ Illuminate\Mail\Markdown::parse('---') }}
Thank you,<br> Thank you,<br>
{{ config('app.name') ?? 'Coolify' }} {{ config('app.name') ?? 'MapleDeploy' }}
{{ Illuminate\Mail\Markdown::parse('[Contact Support](https://coolify.io/docs/contact)') }} {{-- MapleDeploy branding: support link --}}
{{ Illuminate\Mail\Markdown::parse('[Contact Support](https://mapledeploy.ca/contact)') }}

View file

@ -99,9 +99,10 @@
{{-- Unified Input Container with Tags Inside --}} {{-- Unified Input Container with Tags Inside --}}
<div @click="$refs.searchInput.focus()" x-data="{ focused: false }" @focusin="focused = true" @focusout="focused = false" <div @click="$refs.searchInput.focus()" x-data="{ focused: false }" @focusin="focused = true" @focusout="focused = false"
class="flex flex-wrap gap-1.5 max-h-40 overflow-y-auto scrollbar py-1.5 px-2 w-full text-sm rounded-sm border-0 bg-white dark:bg-coolgray-100 cursor-text px-1 text-black dark:text-white" class="flex flex-wrap gap-1.5 max-h-40 overflow-y-auto scrollbar py-1.5 px-2 w-full text-sm rounded-sm border-0 bg-white dark:bg-coolgray-100 cursor-text px-1 text-black dark:text-white"
{{-- MapleDeploy branding: red accent instead of Coolify purple --}}
:style="(() => { :style="(() => {
const isDark = document.documentElement.classList.contains('dark'); const isDark = document.documentElement.classList.contains('dark');
const accent = isDark ? '#fcd452' : '#6b16ed'; const accent = isDark ? '#fde047' : '#d52b1f';
const border = isDark ? '#242424' : '#e5e5e5'; const border = isDark ? '#242424' : '#e5e5e5';
return focused return focused
? 'box-shadow: inset 4px 0 0 ' + accent + ', inset 0 0 0 2px ' + border + ';' ? 'box-shadow: inset 4px 0 0 ' + accent + ', inset 0 0 0 2px ' + border + ';'
@ -110,7 +111,7 @@ class="flex flex-wrap gap-1.5 max-h-40 overflow-y-auto scrollbar py-1.5 px-2 w-
:class="{ :class="{
'opacity-50': {{ $disabled ? 'true' : 'false' }} 'opacity-50': {{ $disabled ? 'true' : 'false' }}
}" wire:loading.class="opacity-50" }" wire:loading.class="opacity-50"
wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]"> wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]">
{{-- Selected Tags Inside Input --}} {{-- Selected Tags Inside Input --}}
<template x-for="value in selected" :key="value"> <template x-for="value in selected" :key="value">
@ -231,9 +232,10 @@ class="w-4 h-4 rounded border-neutral-300 dark:border-neutral-600 bg-white dark:
{{-- Input Container --}} {{-- Input Container --}}
<div @click="openDropdown()" x-data="{ focused: false }" @focusin="focused = true" @focusout="focused = false" <div @click="openDropdown()" x-data="{ focused: false }" @focusin="focused = true" @focusout="focused = false"
class="flex items-center gap-2 py-1.5 w-full text-sm rounded-sm border-0 bg-white dark:bg-coolgray-100 cursor-text text-black dark:text-white" class="flex items-center gap-2 py-1.5 w-full text-sm rounded-sm border-0 bg-white dark:bg-coolgray-100 cursor-text text-black dark:text-white"
{{-- MapleDeploy branding: red accent instead of Coolify purple --}}
:style="(() => { :style="(() => {
const isDark = document.documentElement.classList.contains('dark'); const isDark = document.documentElement.classList.contains('dark');
const accent = isDark ? '#fcd452' : '#6b16ed'; const accent = isDark ? '#fde047' : '#d52b1f';
const border = isDark ? '#242424' : '#e5e5e5'; const border = isDark ? '#242424' : '#e5e5e5';
return focused return focused
? 'box-shadow: inset 4px 0 0 ' + accent + ', inset 0 0 0 2px ' + border + ';' ? 'box-shadow: inset 4px 0 0 ' + accent + ', inset 0 0 0 2px ' + border + ';'
@ -241,7 +243,7 @@ class="flex items-center gap-2 py-1.5 w-full text-sm rounded-sm border-0 bg-whit
})()" })()"
:class="{ :class="{
'opacity-50': {{ $disabled ? 'true' : 'false' }} 'opacity-50': {{ $disabled ? 'true' : 'false' }}
}" wire:loading.class="opacity-50" wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]"> }" wire:loading.class="opacity-50" wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]">
{{-- Display Selected Value or Search Input --}} {{-- Display Selected Value or Search Input --}}
<div class="flex-1 flex items-center min-w-0 px-1"> <div class="flex-1 flex items-center min-w-0 px-1">

View file

@ -39,7 +39,7 @@ class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer dark:hov
x-bind:type="type" x-bind:type="type"
x-bind:class="{ 'truncate': type === 'text' && ! $el.disabled }" x-bind:class="{ 'truncate': type === 'text' && ! $el.disabled }"
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required) {{ $attributes->merge(['class' => $defaultClass]) }} @required($required)
@if ($modelBinding !== 'null') wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @endif @if ($modelBinding !== 'null') wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]" @endif
wire:loading.attr="disabled" wire:loading.attr="disabled"
@readonly($readonly) @disabled($disabled) id="{{ $htmlId }}" @readonly($readonly) @disabled($disabled) id="{{ $htmlId }}"
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}" name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
@ -50,7 +50,7 @@ class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer dark:hov
@else @else
<input autocomplete="{{ $autocomplete }}" @if ($value) value="{{ $value }}" @endif <input autocomplete="{{ $autocomplete }}" @if ($value) value="{{ $value }}" @endif
{{ $attributes->merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly) {{ $attributes->merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly)
@if ($modelBinding !== 'null') wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @endif @if ($modelBinding !== 'null') wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]" @endif
wire:loading.attr="disabled" wire:loading.attr="disabled"
type="{{ $type }}" @disabled($disabled) min="{{ $attributes->get('min') }}" type="{{ $type }}" @disabled($disabled) min="{{ $attributes->get('min') }}"
max="{{ $attributes->get('max') }}" minlength="{{ $attributes->get('minlength') }}" max="{{ $attributes->get('max') }}" minlength="{{ $attributes->get('minlength') }}"

View file

@ -12,7 +12,7 @@ class="flex gap-1 items-center mb-1 text-sm font-medium {{ $disabled ? 'text-neu
@endif @endif
<select {{ $attributes->merge(['class' => $defaultClass]) }} @disabled($disabled) @required($required) <select {{ $attributes->merge(['class' => $defaultClass]) }} @disabled($disabled) @required($required)
wire:loading.attr="disabled" name={{ $modelBinding }} id="{{ $htmlId }}" wire:loading.attr="disabled" name={{ $modelBinding }} id="{{ $htmlId }}"
@if ($attributes->whereStartsWith('wire:model')->first()) {{ $attributes->whereStartsWith('wire:model')->first() }} wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @else wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @endif> @if ($attributes->whereStartsWith('wire:model')->first()) {{ $attributes->whereStartsWith('wire:model')->first() }} wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]" @else wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]" @endif>
{{ $slot }} {{ $slot }}
</select> </select>
@error($modelBinding) @error($modelBinding)

View file

@ -53,16 +53,16 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer
@endif @endif
<input x-cloak x-show="type === 'password'" value="{{ $value }}" <input x-cloak x-show="type === 'password'" value="{{ $value }}"
{{ $attributes->merge(['class' => $defaultClassInput]) }} @required($required) {{ $attributes->merge(['class' => $defaultClassInput]) }} @required($required)
@if ($modelBinding !== 'null') wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @endif @if ($modelBinding !== 'null') wire:model={{ $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]" @endif
wire:loading.attr="disabled" wire:loading.attr="disabled"
type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $htmlId }}" type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $htmlId }}"
name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}" name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}"
aria-placeholder="{{ $attributes->get('placeholder') }}"> aria-placeholder="{{ $attributes->get('placeholder') }}">
<textarea minlength="{{ $minlength }}" maxlength="{{ $maxlength }}" x-cloak x-show="type !== 'password'" <textarea minlength="{{ $minlength }}" maxlength="{{ $maxlength }}" x-cloak x-show="type !== 'password'"
placeholder="{{ $placeholder }}" {{ $attributes->merge(['class' => $defaultClass]) }} placeholder="{{ $placeholder }}" {{ $attributes->merge(['class' => $defaultClass]) }}
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $modelBinding }}" wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @if ($realtimeValidation) wire:model.debounce.200ms="{{ $modelBinding }}" wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]"
@else @else
wire:model={{ $value ?? $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @endif wire:model={{ $value ?? $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]" @endif
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}" @disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}"
name="{{ $name }}" name={{ $modelBinding }} name="{{ $name }}" name={{ $modelBinding }}
@if ($autofocus) x-ref="autofocusInput" @endif></textarea> @if ($autofocus) x-ref="autofocusInput" @endif></textarea>
@ -72,9 +72,9 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer
<textarea minlength="{{ $minlength }}" maxlength="{{ $maxlength }}" <textarea minlength="{{ $minlength }}" maxlength="{{ $maxlength }}"
{{ $allowTab ? '@keydown.tab=handleKeydown' : '' }} placeholder="{{ $placeholder }}" {{ $allowTab ? '@keydown.tab=handleKeydown' : '' }} placeholder="{{ $placeholder }}"
{{ !$spellcheck ? 'spellcheck=false' : '' }} {{ $attributes->merge(['class' => $defaultClass]) }} {{ !$spellcheck ? 'spellcheck=false' : '' }} {{ $attributes->merge(['class' => $defaultClass]) }}
@if ($realtimeValidation) wire:model.debounce.200ms="{{ $modelBinding }}" wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @if ($realtimeValidation) wire:model.debounce.200ms="{{ $modelBinding }}" wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]"
@else @else
wire:model={{ $value ?? $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#6b16ed,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fcd452,inset_0_0_0_2px_#242424]" @endif wire:model={{ $value ?? $modelBinding }} wire:dirty.class="[box-shadow:inset_4px_0_0_#d52b1f,inset_0_0_0_2px_#e5e5e5] dark:[box-shadow:inset_4px_0_0_#fde047,inset_0_0_0_2px_#242424]" @endif
@disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}" @disabled($disabled) @readonly($readonly) @required($required) id="{{ $htmlId }}"
name="{{ $name }}" name={{ $modelBinding }} name="{{ $name }}" name={{ $modelBinding }}
@if ($autofocus) x-ref="autofocusInput" @endif></textarea> @if ($autofocus) x-ref="autofocusInput" @endif></textarea>

View file

@ -1,5 +1,5 @@
<div class="flex flex-col items-center justify-center h-32"> <div class="flex flex-col items-center justify-center h-32">
<span class="text-xl font-bold dark:text-white">You have reached the limit of {{ $name }} you can create.</span> <span class="text-xl font-bold font-display dark:text-white">You have reached the limit of {{ $name }} you can create.</span>
<span>Please <a class="dark:text-white underline" {{ wireNavigate() }} href="{{ route('subscription.show') }}">upgrade your <span>Please <a class="dark:text-white underline" {{ wireNavigate() }} href="{{ route('subscription.show') }}">upgrade your
subscription</a> to create more subscription</a> to create more
{{ $name }}.</span> {{ $name }}.</span>

View file

@ -94,16 +94,21 @@
}"> }">
<div class="flex pt-4 pb-4 pl-2 items-start gap-2 motion-safe:transition-all motion-safe:duration-200 motion-safe:ease-out motion-reduce:transition-none" <div class="flex pt-4 pb-4 pl-2 items-start gap-2 motion-safe:transition-all motion-safe:duration-200 motion-safe:ease-out motion-reduce:transition-none"
:class="collapsed ? 'lg:flex-col lg:items-center lg:pl-0 lg:gap-3 lg:pt-7' : 'lg:pt-6'"> :class="collapsed ? 'lg:flex-col lg:items-center lg:pl-0 lg:gap-3 lg:pt-7' : 'lg:pt-6'">
<div class="flex flex-col w-full" :class="collapsed && 'lg:hidden'"> {{-- MapleDeploy branding --}}
<a href="/" {{ wireNavigate() }} class="text-2xl font-bold tracking-tight dark:text-white hover:opacity-80 transition-opacity">Coolify</a> <div class="flex flex-col min-w-0 flex-1" :class="collapsed && 'lg:hidden'">
<x-version /> <a href="/" {{ wireNavigate() }} class="hover:opacity-80 transition-opacity">
<img src="https://mapledeploy.ca/api/logo/lockup?height=40" alt="MapleDeploy" class="max-h-6 w-auto max-w-full dark:hidden" />
<img src="https://mapledeploy.ca/api/logo/lockup?height=40&dark=true" alt="MapleDeploy" class="hidden max-h-6 w-auto max-w-full dark:block" />
</a>
<span class="text-xs opacity-75 dark:text-neutral-400">Powered by Coolify</span>
</div> </div>
{{-- MapleDeploy branding: collapsed-sidebar mark --}}
<div class="hidden flex-col items-center w-full gap-1" <div class="hidden flex-col items-center w-full gap-1"
:class="collapsed && 'lg:flex'"> :class="collapsed && 'lg:flex'">
<a href="/" {{ wireNavigate() }} <a href="/" {{ wireNavigate() }}
class="hover:opacity-80 transition-opacity" class="hover:opacity-80 transition-opacity"
title="Coolify"> title="MapleDeploy">
<img src="/coolify-logo.svg" alt="Coolify" class="w-6 h-6" /> <img src="https://mapledeploy.ca/api/logo/mark?height=64" alt="MapleDeploy" class="w-6 h-6" />
</a> </a>
<x-version class="text-[10px]" /> <x-version class="text-[10px]" />
</div> </div>
@ -318,20 +323,7 @@ class="{{ request()->is('team*') ? 'menu-item-active menu-item' : 'menu-item' }}
<span class="menu-item-label" :class="collapsed && 'lg:hidden'">Teams</span> <span class="menu-item-label" :class="collapsed && 'lg:hidden'">Teams</span>
</a> </a>
</li> </li>
@if (isCloud() && auth()->user()->isAdmin()) {{-- MapleDeploy branding: Cloud subscription menu removed --}}
<li>
<a title="Subscription" {{ wireNavigate() }}
class="{{ request()->is('subscription*') ? 'menu-item-active menu-item' : 'menu-item' }}"
href="{{ route('subscription.show') }}">
<svg class="menu-item-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M3 8a3 3 0 0 1 3-3h12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3zm0 2h18M7 15h.01M11 15h2" />
</svg>
<span class="menu-item-label" :class="collapsed && 'lg:hidden'">Subscription</span>
</a>
</li>
@endif
@if (isInstanceAdmin()) @if (isInstanceAdmin())
<li> <li>
@ -351,20 +343,7 @@ class="{{ request()->is('settings*') ? 'menu-item-active menu-item' : 'menu-item
</li> </li>
@endif @endif
@if (isCloud() || isDev()) {{-- MapleDeploy branding: Cloud admin menu removed --}}
@if (isInstanceAdmin() || session('impersonating'))
<li>
<a title="Admin" class="menu-item" href="/admin" {{ wireNavigate() }}>
<svg class="text-pink-500 menu-item-icon" viewBox="0 0 256 256"
xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="M177.62 159.6a52 52 0 0 1-34 34a12.2 12.2 0 0 1-3.6.55a12 12 0 0 1-3.6-23.45a28 28 0 0 0 18.32-18.32a12 12 0 0 1 22.9 7.2ZM220 144a92 92 0 0 1-184 0c0-28.81 11.27-58.18 33.48-87.28a12 12 0 0 1 17.9-1.33l19.69 19.11L127 19.89a12 12 0 0 1 18.94-5.12C168.2 33.25 220 82.85 220 144m-24 0c0-41.71-30.61-78.39-52.52-99.29l-20.21 55.4a12 12 0 0 1-19.63 4.5L80.71 82.36C67 103.38 60 124.06 60 144a68 68 0 0 0 136 0" />
</svg>
<span class="menu-item-label" :class="collapsed && 'lg:hidden'">Admin</span>
</a>
</li>
@endif
@endif
<div class="flex-1"></div> <div class="flex-1"></div>
@if (isInstanceAdmin() && !isCloud()) @if (isInstanceAdmin() && !isCloud())
@persist('upgrade') @persist('upgrade')
@ -384,39 +363,19 @@ class="{{ request()->is('onboarding*') ? 'menu-item-active menu-item' : 'menu-it
Onboarding Onboarding
</a> </a>
</li> --}} </li> --}}
{{-- MapleDeploy branding: AGPL source code link (license requirement) --}}
<li> <li>
<a title="Sponsor us" class="menu-item" href="https://coolify.io/sponsorships" <a title="Source code (AGPL-3.0)" class="menu-item" href="https://forgejo.mapledeploy.ca/rosslh/coolify"
target="_blank"> target="_blank">
<svg class="text-pink-500 menu-item-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <svg class="menu-item-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" <path fill="none" stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"> stroke-linejoin="round" stroke-width="2"
<path d="M19.5 12.572L12 20l-7.5-7.428A5 5 0 1 1 12 6.006a5 5 0 1 1 7.5 6.572" /> d="M16 18l6-6-6-6M8 6l-6 6 6 6" />
<path
d="M12 6L8.707 9.293a1 1 0 0 0 0 1.414l.543.543c.69.69 1.81.69 2.5 0l1-1a3.182 3.182 0 0 1 4.5 0l2.25 2.25m-7 3l2 2M15 13l2 2" />
</g>
</svg> </svg>
<span class="menu-item-label" :class="collapsed && 'lg:hidden'">Sponsor us</span> <span class="menu-item-label" :class="collapsed && 'lg:hidden'">Source code</span>
</a> </a>
</li> </li>
@endif @endif
@if (!isSubscribed() && isCloud() && auth()->user()->teams()->get()->count() > 1)
<livewire:navbar-delete-team />
@endif
<li>
<x-modal-input title="How can we help?">
<x-slot:content>
<div title="Send us feedback or get help!" class="cursor-pointer menu-item"
wire:click="help">
<svg class="menu-item-icon" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="M140 180a12 12 0 1 1-12-12a12 12 0 0 1 12 12M128 72c-22.06 0-40 16.15-40 36v4a8 8 0 0 0 16 0v-4c0-11 10.77-20 24-20s24 9 24 20s-10.77 20-24 20a8 8 0 0 0-8 8v8a8 8 0 0 0 16 0v-.72c18.24-3.35 32-17.9 32-35.28c0-19.85-17.94-36-40-36m104 56A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104m-16 0a88 88 0 1 0-88 88a88.1 88.1 0 0 0 88-88" />
</svg>
<span class="menu-item-label" :class="collapsed && 'lg:hidden'">Feedback</span>
</div>
</x-slot:content>
<livewire:help />
</x-modal-input>
</li>
<li> <li>
<form action="/logout" method="POST"> <form action="/logout" method="POST">
@csrf @csrf

View file

@ -35,19 +35,21 @@ class="font-bold dark:text-warning">{{ config('constants.limits.trial_period') }
</div> </div>
</div> </div>
<div class="p-4 rounded-sm bg-coolgray-400"> <div class="p-4 rounded-sm bg-coolgray-400">
{{-- MapleDeploy branding: link to Forgejo source repo --}}
<h2 id="tier-hobby" class="flex items-start gap-4 text-4xl font-bold tracking-tight">Unlimited Trial <h2 id="tier-hobby" class="flex items-start gap-4 text-4xl font-bold tracking-tight">Unlimited Trial
<x-forms.button><a class="font-bold dark:text-white hover:no-underline" <x-forms.button><a class="font-bold dark:text-white hover:no-underline"
href="https://github.com/coollabsio/coolify">Get Started</a></x-forms.button> href="https://forgejo.mapledeploy.ca/rosslh/coolify">Get Started</a></x-forms.button>
</h2> </h2>
<p class="mt-4 text-sm leading-6">Start self-hosting <span class="dark:text-warning">without limits</span> <p class="mt-4 text-sm leading-6">Start self-hosting <span class="dark:text-warning">without limits</span>
with with
our the
OSS version. Same features as the paid version, but you have to manage by yourself.</p> open source version. Same features as the paid version, but you have to manage by yourself.</p>
</div> </div>
<div class="flow-root mt-12"> <div class="flow-root mt-12">
{{-- MapleDeploy branding: link to mapledeploy.ca --}}
<div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a <div class="pb-10 text-xl text-center">For the detailed list of features, please visit our landing page: <a
class="font-bold underline dark:text-white" href="https://coolify.io">coolify.io</a></div> class="font-bold underline dark:text-white" href="https://mapledeploy.ca">mapledeploy.ca</a></div>
<div <div
class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-3 lg:divide-x lg:divide-y-0 xl:-mx-4"> class="grid max-w-sm grid-cols-1 -mt-16 divide-y divide-neutral-200 dark:divide-coolgray-500 isolate gap-y-16 sm:mx-auto lg:-mx-8 lg:mt-0 lg:max-w-none lg:grid-cols-3 lg:divide-x lg:divide-y-0 xl:-mx-4">

View file

@ -1,6 +1,6 @@
<div class="pb-5"> <div class="pb-5">
<h1>Settings</h1> <h1>Settings</h1>
<div class="subtitle">Instance wide settings for Coolify.</div> <div class="subtitle">Instance wide settings for MapleDeploy.</div>
<div class="navbar-main"> <div class="navbar-main">
<nav class="flex items-center gap-6 min-h-10 whitespace-nowrap"> <nav class="flex items-center gap-6 min-h-10 whitespace-nowrap">
<a class="{{ request()->routeIs('settings.index') ? 'dark:text-white' : '' }}" {{ wireNavigate() }} <a class="{{ request()->routeIs('settings.index') ? 'dark:text-white' : '' }}" {{ wireNavigate() }}

View file

@ -1,4 +1,4 @@
<a {{ $attributes->merge(['class' => 'text-xs cursor-pointer opacity-90 hover:opacity-100 dark:hover:text-white hover:text-black']) }} {{-- MapleDeploy branding: show version without linking to upstream releases --}}
href="https://github.com/coollabsio/coolify/releases/tag/v{{ config('constants.coolify.version') }}" target="_blank"> <span {{ $attributes->merge(['class' => 'text-xs opacity-90 dark:text-neutral-500']) }}>
v{{ config('constants.coolify.version') }} v{{ config('constants.coolify.version') }}
</a> </span>

View file

@ -1,7 +1,7 @@
<x-emails.layout> <x-emails.layout>
We would like to inform you that a {{ config('constants.limits.trial_period') }} days of trial has been added to all subscription plans. We would like to inform you that a {{ config('constants.limits.trial_period') }} days of trial has been added to all subscription plans.
You can try out Coolify, without payment information for free. If you like it, you can upgrade to a paid plan at any time. You can try out MapleDeploy, without payment information for free. If you like it, you can upgrade to a paid plan at any time.
[Click here](https://app.coolify.io/subscription/new) to start your trial. [Click here](https://app.coolify.io/subscription/new) to start your trial.
</x-emails.layout> </x-emails.layout>

View file

@ -2,6 +2,7 @@
A resource ({{ $containerName }}) has been restarted automatically on {{ $serverName }}, because it was stopped unexpectedly. A resource ({{ $containerName }}) has been restarted automatically on {{ $serverName }}, because it was stopped unexpectedly.
@if ($containerName === 'coolify-proxy') @if ($containerName === 'coolify-proxy')
{{-- Note: Coolify Proxy is the technical component name, not a branding reference --}}
Coolify Proxy should run on your server as you have FQDNs set up in one of your resources. Coolify Proxy should run on your server as you have FQDNs set up in one of your resources.
If you don't want to use Coolify Proxy, please remove FQDN from your resources or set Proxy type to Custom(None). If you don't want to use Coolify Proxy, please remove FQDN from your resources or set Proxy type to Custom(None).

View file

@ -1,5 +0,0 @@
{{ $description }}
{{ Illuminate\Mail\Markdown::parse('---') }}
{{-- {{ Illuminate\Mail\Markdown::parse($debug) }} --}}

View file

@ -6,7 +6,7 @@
{{ $errorMessage }} {{ $errorMessage }}
</pre> </pre>
The server has been removed from Coolify, but may still exist in your Hetzner Cloud account. The server has been removed from MapleDeploy, but may still exist in your Hetzner Cloud account.
Please check your Hetzner Cloud console and manually delete the server if needed to avoid ongoing charges. Please check your Hetzner Cloud console and manually delete the server if needed to avoid ongoing charges.

View file

@ -9,5 +9,5 @@
--- ---
You can manage your server and view more details in your [Coolify Dashboard]({{ $server_url }}). You can manage your server and view more details in your [MapleDeploy dashboard]({{ $server_url }}).
</x-emails.layout> </x-emails.layout>

View file

@ -41,7 +41,7 @@
1. Review the available updates 1. Review the available updates
2. Plan maintenance window if critical packages are involved 2. Plan maintenance window if critical packages are involved
3. Apply updates through the Coolify dashboard 3. Apply updates through the MapleDeploy dashboard
4. Monitor services after updates are applied 4. Monitor services after updates are applied
@else @else
Your server is up to date! No packages require updating at this time. Your server is up to date! No packages require updating at this time.
@ -49,5 +49,5 @@
--- ---
You can manage server patches in your [Coolify Dashboard]({{ $server_url }}). You can manage server patches in your [MapleDeploy dashboard]({{ $server_url }}).
</x-emails.layout> </x-emails.layout>

View file

@ -1,5 +1,6 @@
{{-- MapleDeploy branding: Coolify Cloud references removed --}}
<x-emails.layout> <x-emails.layout>
Your last invoice has failed to be paid for Coolify Cloud. Your last invoice has failed to be paid for MapleDeploy.
Please update payment details [here]({{ $stripeCustomerPortal }}). Please update your payment details [here]({{ $stripeCustomerPortal }}).
</x-emails.layout> </x-emails.layout>

View file

@ -1,5 +1,6 @@
{{-- MapleDeploy branding: Coolify Cloud references removed --}}
<x-emails.layout> <x-emails.layout>
Your trial ended. All automations and integrations are disabled for all of your servers. Your trial has ended. All automations and integrations are disabled for your servers.
Please update payment details [here]({{ $stripeCustomerPortal }}) or in [Coolify Cloud](https://app.coolify.io) to continue using our services. Please update your payment details [here]({{ $stripeCustomerPortal }}) to continue using MapleDeploy.
</x-emails.layout> </x-emails.layout>

View file

@ -65,9 +65,12 @@ class="absolute top-8 -right-3 z-50 hidden lg:flex items-center justify-center w
<div <div
class="sticky top-0 z-40 flex items-center justify-between px-4 py-4 gap-x-6 sm:px-6 lg:hidden bg-white/95 dark:bg-base/95 backdrop-blur-sm border-b border-neutral-300/50 dark:border-coolgray-200/50"> class="sticky top-0 z-40 flex items-center justify-between px-4 py-4 gap-x-6 sm:px-6 lg:hidden bg-white/95 dark:bg-base/95 backdrop-blur-sm border-b border-neutral-300/50 dark:border-coolgray-200/50">
<div class="flex items-center gap-3 flex-shrink-0"> {{-- MapleDeploy branding --}}
<a href="/" <div class="flex items-center gap-3 min-w-0 flex-1">
class="text-xl font-bold tracking-wide dark:text-white hover:opacity-80 transition-opacity">Coolify</a> <a href="/" class="hover:opacity-80 transition-opacity min-w-0">
<img src="https://mapledeploy.ca/api/logo/lockup?height=40" alt="MapleDeploy" class="max-h-6 w-auto max-w-full dark:hidden" />
<img src="https://mapledeploy.ca/api/logo/lockup?height=40&dark=true" alt="MapleDeploy" class="hidden max-h-6 w-auto max-w-full dark:block" />
</a>
<livewire:switch-team /> <livewire:switch-team />
</div> </div>
<button type="button" class="-m-2.5 p-2.5 dark:text-warning" x-on:click="open = !open"> <button type="button" class="-m-2.5 p-2.5 dark:text-warning" x-on:click="open = !open">

View file

@ -16,19 +16,17 @@
<meta name="robots" content="noindex"> <meta name="robots" content="noindex">
<meta name="theme-color" content="#ffffff" id="theme-color-meta" /> <meta name="theme-color" content="#ffffff" id="theme-color-meta" />
<meta name="color-scheme" content="dark light" /> <meta name="color-scheme" content="dark light" />
<meta name="Description" content="Coolify: An open-source & self-hostable Heroku / Netlify / Vercel alternative" /> {{-- MapleDeploy branding --}}
<meta name="Description" content="MapleDeploy: Managed Coolify hosting on Canadian infrastructure" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="twitter:card" content="summary_large_image" /> <meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@coolifyio" /> <meta name="twitter:title" content="MapleDeploy" />
<meta name="twitter:title" content="Coolify" /> <meta name="twitter:description" content="Managed Coolify hosting on Canadian infrastructure." />
<meta name="twitter:description" content="An open-source & self-hostable Heroku / Netlify / Vercel alternative." />
<meta name="twitter:image" content="https://cdn.coollabs.io/assets/coolify/og-image.png" />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content="https://coolify.io" /> <meta property="og:url" content="https://mapledeploy.ca" />
<meta property="og:title" content="Coolify" /> <meta property="og:title" content="MapleDeploy" />
<meta property="og:description" content="An open-source & self-hostable Heroku / Netlify / Vercel alternative." /> <meta property="og:description" content="Managed Coolify hosting on Canadian infrastructure." />
<meta property="og:site_name" content="Coolify" /> <meta property="og:site_name" content="MapleDeploy" />
<meta property="og:image" content="https://cdn.coollabs.io/assets/coolify/og-image.png" />
@use('App\Models\InstanceSettings') @use('App\Models\InstanceSettings')
@php @php
@ -43,12 +41,9 @@
} }
} }
@endphp @endphp
<title>{{ $name }}{{ $title ?? 'Coolify' }}</title> <title>{{ $name }}{{ $title ?? 'MapleDeploy' }}</title> {{-- MapleDeploy branding --}}
@env('local') {{-- MapleDeploy branding: single favicon for all environments --}}
<link rel="icon" href="{{ asset('coolify-logo-dev-transparent.png') }}" type="image/png" /> <link rel="icon" href="{{ asset('mapledeploy-favicon.ico') }}" type="image/x-icon" />
@else
<link rel="icon" href="{{ asset('coolify-logo.svg') }}" type="image/svg+xml" />
@endenv
<meta name="csrf-token" content="{{ csrf_token() }}"> <meta name="csrf-token" content="{{ csrf_token() }}">
@vite(['resources/js/app.js', 'resources/css/app.css']) @vite(['resources/js/app.js', 'resources/css/app.css'])
<script> <script>
@ -62,10 +57,7 @@
display: none !important; display: none !important;
} }
</style> </style>
@if (config('app.name') == 'Coolify Cloud') {{-- MapleDeploy branding: Coolify Cloud analytics removed --}}
<script defer data-domain="app.coolify.io" src="https://analytics.coollabs.io/js/plausible.js"></script>
<script src="https://js.sentry-cdn.com/0f8593910512b5cdd48c6da78d4093be.min.js" crossorigin="anonymous"></script>
@endif
@auth @auth
<script type="text/javascript" src="{{ URL::asset('js/echo.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/echo.js') }}"></script>
<script type="text/javascript" src="{{ URL::asset('js/pusher.js') }}"></script> <script type="text/javascript" src="{{ URL::asset('js/pusher.js') }}"></script>
@ -148,6 +140,7 @@
let cpuColor = '#1e90ff' let cpuColor = '#1e90ff'
let ramColor = '#00ced1' let ramColor = '#00ced1'
let textColor = '#ffffff' let textColor = '#ffffff'
let gridColor = '#44403c'
let editorBackground = '#181818' let editorBackground = '#181818'
let editorTheme = 'blackboard' let editorTheme = 'blackboard'
@ -160,12 +153,14 @@ function checkTheme() {
cpuColor = '#1e90ff' cpuColor = '#1e90ff'
ramColor = '#00ced1' ramColor = '#00ced1'
textColor = '#ffffff' textColor = '#ffffff'
gridColor = '#44403c'
editorBackground = '#181818' editorBackground = '#181818'
editorTheme = 'blackboard' editorTheme = 'blackboard'
} else { } else {
cpuColor = '#1e90ff' cpuColor = '#1e90ff'
ramColor = '#00ced1' ramColor = '#00ced1'
textColor = '#000000' textColor = '#000000'
gridColor = '#d6d3d1'
editorBackground = '#ffffff' editorBackground = '#ffffff'
editorTheme = null editorTheme = null
} }

View file

@ -1,13 +1,13 @@
@php use App\Enums\ProxyTypes; @endphp @php use App\Enums\ProxyTypes; @endphp
<x-slot:title> <x-slot:title>
Onboarding | Coolify Onboarding | MapleDeploy
</x-slot> </x-slot>
<section class="w-full"> <section class="w-full">
<div class="flex flex-col items-center w-full space-y-8"> <div class="flex flex-col items-center w-full space-y-8">
@if ($currentState === 'welcome') @if ($currentState === 'welcome')
<div class="w-full max-w-2xl text-center space-y-8"> <div class="w-full max-w-2xl text-center space-y-8">
<div class="space-y-4"> <div class="space-y-4">
<h1 class="text-4xl font-bold lg:text-6xl">Welcome to Coolify</h1> <h1 class="text-4xl font-bold lg:text-6xl">Welcome to MapleDeploy</h1>
<p class="text-lg lg:text-xl dark:text-neutral-400"> <p class="text-lg lg:text-xl dark:text-neutral-400">
Connect your first server and start deploying in minutes Connect your first server and start deploying in minutes
</p> </p>
@ -81,17 +81,17 @@ class="text-sm dark:text-neutral-400 hover:text-coollabs dark:hover:text-warning
<x-boarding-progress :currentStep="0" /> <x-boarding-progress :currentStep="0" />
<x-boarding-step title="Platform Overview"> <x-boarding-step title="Platform Overview">
<x-slot:question> <x-slot:question>
Coolify automates deployment and infrastructure management on your own servers. Deploy applications MapleDeploy automates deployment and infrastructure management on your own servers. Deploy applications
from Git, manage databases, and monitor everything—without vendor lock-in. from Git, manage databases, and monitor everything—without vendor lock-in.
</x-slot:question> </x-slot:question>
<x-slot:explanation> <x-slot:explanation>
<p> <p>
<x-highlighted text="Automation:" /> Coolify handles server configuration, Docker management, <x-highlighted text="Automation:" /> MapleDeploy handles server configuration, Docker management,
and and
deployments automatically. deployments automatically.
</p> </p>
<p> <p>
<x-highlighted text="Self-hosted:" /> All data and configurations live on your infrastructure. <x-highlighted text="Your infrastructure:" /> All data and configurations live on your servers.
Works offline except for external integrations. Works offline except for external integrations.
</p> </p>
<p> <p>
@ -132,7 +132,7 @@ class="px-2 py-1 text-xs font-bold uppercase tracking-wide bg-neutral-100 dark:b
<div> <div>
<h3 class="text-xl font-bold mb-2">This Machine</h3> <h3 class="text-xl font-bold mb-2">This Machine</h3>
<p class="text-sm dark:text-neutral-400"> <p class="text-sm dark:text-neutral-400">
Deploy on the server running Coolify. Best for testing and single-server setups. Deploy on the server running MapleDeploy. Best for testing and single-server setups.
</p> </p>
</div> </div>
</div> </div>
@ -163,38 +163,7 @@ class="px-2 py-1 text-xs font-bold uppercase tracking-wide bg-coollabs/10 dark:b
</div> </div>
</div> </div>
</button> </button>
@can('viewAny', App\Models\CloudProviderToken::class) {{-- MapleDeploy branding: Hetzner Cloud provider removed --}}
@if ($currentState === 'select-server-type')
<x-modal-input title="Connect a Hetzner Server" isFullWidth>
<x-slot:content>
<div
class="group relative box-without-bg cursor-pointer hover:border-coollabs transition-all duration-200 p-6 h-full min-h-[210px]">
<div class="flex flex-col gap-4 text-left">
<div class="flex items-center justify-between">
<svg class="size-10" viewBox="0 0 200 200"
xmlns="http://www.w3.org/2000/svg">
<rect width="200" height="200" fill="#D50C2D" rx="8" />
<path d="M40 40 H60 V90 H140 V40 H160 V160 H140 V110 H60 V160 H40 Z"
fill="white" />
</svg>
<span
class="px-2 py-1 text-xs font-bold uppercase tracking-wide bg-coollabs/10 dark:bg-warning/20 text-coollabs dark:text-warning rounded">
Recommended
</span>
</div>
<div>
<h3 class="text-xl font-bold mb-2">Hetzner Cloud</h3>
<p class="text-sm dark:text-neutral-400">
Deploy servers directly from your Hetzner Cloud account.
</p>
</div>
</div>
</div>
</x-slot:content>
<livewire:server.new.by-hetzner :limit_reached="false" :from_onboarding="true" />
</x-modal-input>
@endif
@endcan
</div> </div>
@if (!$serverReachable) @if (!$serverReachable)
@ -211,6 +180,7 @@ class="px-2 py-1 text-xs font-bold uppercase tracking-wide bg-coollabs/10 dark:b
wire:model="remoteServerUser" :value="$remoteServerUser" /> wire:model="remoteServerUser" :value="$remoteServerUser" />
<p class="text-xs mt-1"> <p class="text-xs mt-1">
Non-root user is experimental: Non-root user is experimental:
{{-- MapleDeploy branding: link to upstream Coolify docs for technical reference --}}
<a class="font-bold underline" target="_blank" <a class="font-bold underline" target="_blank"
href="https://coolify.io/docs/knowledge-base/server/non-root-user">docs</a> href="https://coolify.io/docs/knowledge-base/server/non-root-user">docs</a>
</p> </p>
@ -229,6 +199,7 @@ class="bg-red-200 dark:bg-red-900 px-1 rounded-sm">~/.ssh/authorized_keys</code>
</div> </div>
<p class="mb-4"> <p class="mb-4">
{{-- MapleDeploy branding: link to upstream Coolify docs for technical reference --}}
For more help, check this <a target="_blank" class="underline font-semibold" For more help, check this <a target="_blank" class="underline font-semibold"
href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a>. href="https://coolify.io/docs/knowledge-base/server/openssh">documentation</a>.
</p> </p>
@ -248,12 +219,12 @@ class="bg-red-200 dark:bg-red-900 px-1 rounded-sm">~/.ssh/authorized_keys</code>
called resources). All CPU-intensive operations run on the target server. called resources). All CPU-intensive operations run on the target server.
</p> </p>
<p> <p>
<x-highlighted text="Localhost:" /> The machine running Coolify. Not recommended for production <x-highlighted text="Localhost:" /> The machine running MapleDeploy. Not recommended for production
workloads due to resource contention. workloads due to resource contention.
</p> </p>
<p> <p>
<x-highlighted text="Remote Server:" /> Any SSH-accessible server—cloud providers (AWS, Hetzner, <x-highlighted text="Remote Server:" /> Any SSH-accessible server—cloud providers,
DigitalOcean), bare metal, or self-hosted infrastructure. bare metal, or self-hosted infrastructure.
</p> </p>
</x-slot:explanation> </x-slot:explanation>
</x-boarding-step> </x-boarding-step>
@ -336,7 +307,7 @@ class="text-xs bg-coolgray-300 dark:bg-coolgray-400 px-1 py-0.5 rounded">~/.ssh/
file. file.
</p> </p>
<p> <p>
<x-highlighted text="Key Generation:" /> Coolify generates ED25519 keys by default for optimal <x-highlighted text="Key Generation:" /> MapleDeploy generates ED25519 keys by default for optimal
security and performance. security and performance.
</p> </p>
</x-slot:explanation> </x-slot:explanation>
@ -386,7 +357,7 @@ class="text-xs bg-coolgray-300 dark:bg-coolgray-400 px-1 py-0.5 rounded">~/.ssh/
</x-slot:actions> </x-slot:actions>
<x-slot:explanation> <x-slot:explanation>
<p> <p>
<x-highlighted text="Key Storage:" /> Private keys are encrypted at rest in Coolify's database. <x-highlighted text="Key Storage:" /> Private keys are encrypted at rest in the database.
</p> </p>
<p> <p>
<x-highlighted text="Public Key Distribution:" /> Deploy the public key to <x-highlighted text="Public Key Distribution:" /> Deploy the public key to
@ -443,6 +414,7 @@ class="grid grid-cols-1 lg:grid-cols-2 gap-4 p-4 rounded-lg border border-neutra
wire:model="remoteServerUser" /> wire:model="remoteServerUser" />
<p class="mt-1 text-xs dark:text-white text-black"> <p class="mt-1 text-xs dark:text-white text-black">
Non-root user support is experimental. Non-root user support is experimental.
{{-- MapleDeploy branding: link to upstream Coolify docs for technical reference --}}
<a class="font-bold underline hover:text-coollabs" target="_blank" <a class="font-bold underline hover:text-coollabs" target="_blank"
href="https://coolify.io/docs/knowledge-base/server/non-root-user">Learn href="https://coolify.io/docs/knowledge-base/server/non-root-user">Learn
more</a> more</a>
@ -473,7 +445,7 @@ class="grid grid-cols-1 lg:grid-cols-2 gap-4 p-4 rounded-lg border border-neutra
<x-boarding-progress :currentStep="2" /> <x-boarding-progress :currentStep="2" />
<x-boarding-step title="Server Validation"> <x-boarding-step title="Server Validation">
<x-slot:question> <x-slot:question>
Coolify will automatically install Docker {{ $minDockerVersion }}+ if not present. MapleDeploy will automatically install Docker {{ $minDockerVersion }}+ if not present.
</x-slot:question> </x-slot:question>
<x-slot:actions> <x-slot:actions>
<div class="w-full space-y-6"> <div class="w-full space-y-6">
@ -567,7 +539,7 @@ class="p-6 bg-neutral-50 dark:bg-coolgray-200 rounded-lg border border-neutral-2
</x-slot:actions> </x-slot:actions>
<x-slot:explanation> <x-slot:explanation>
<p> <p>
<x-highlighted text="Automated Setup:" /> Coolify installs Docker Engine, Docker Compose, and <x-highlighted text="Automated Setup:" /> MapleDeploy installs Docker Engine, Docker Compose, and
configures system requirements automatically. configures system requirements automatically.
</p> </p>
<p> <p>
@ -734,15 +706,6 @@ class="dark:text-neutral-400 hover:text-coollabs dark:hover:text-warning hover:u
Restart Restart
</button> </button>
</div> </div>
<x-modal-input title="Need Help?">
<x-slot:content>
<button
class="text-sm dark:text-neutral-400 hover:text-coollabs dark:hover:text-warning hover:underline transition-colors">
Contact Support
</button>
</x-slot:content>
<livewire:help />
</x-modal-input>
</div> </div>
@endif @endif
</section> </section>

View file

@ -1,12 +1,13 @@
<div> <div>
<x-slot:title> <x-slot:title>
Dashboard | Coolify Dashboard | MapleDeploy
</x-slot> </x-slot>
@if (session('error')) @if (session('error'))
<span x-data x-init="$wire.emit('error', '{{ session('error') }}')" /> <span x-data x-init="$wire.emit('error', '{{ session('error') }}')" />
@endif @endif
<h1>Dashboard</h1> <h1>Dashboard</h1>
<div class="subtitle">Your self-hosted infrastructure.</div> {{-- MapleDeploy branding --}}
<div class="subtitle">Your deployment platform.</div>
<section class="-mt-2"> <section class="-mt-2">
<div class="flex items-center gap-2 pb-2"> <div class="flex items-center gap-2 pb-2">

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Destinations | Coolify Destinations | MapleDeploy
</x-slot> </x-slot>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h1>Destinations</h1> <h1>Destinations</h1>

View file

@ -1,8 +1,9 @@
<section class="bg-gray-50 dark:bg-base"> <section class="bg-gray-50 dark:bg-base">
<div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0"> <div class="flex flex-col items-center justify-center px-6 py-8 mx-auto md:h-screen lg:py-0">
<a class="flex items-center mb-6 text-5xl font-extrabold tracking-tight text-gray-900 dark:text-white"> <div class="flex items-center justify-center mb-6">
Coolify <img src="https://mapledeploy.ca/api/logo/lockup?height=80" alt="MapleDeploy" class="h-12 dark:hidden" />
</a> <img src="https://mapledeploy.ca/api/logo/lockup?height=80&dark=true" alt="MapleDeploy" class="hidden h-12 dark:block" />
</div>
<div class="w-full bg-white shadow-sm md:mt-0 sm:max-w-md xl:p-0 dark:bg-base "> <div class="w-full bg-white shadow-sm md:mt-0 sm:max-w-md xl:p-0 dark:bg-base ">
<div class="p-6 space-y-4 md:space-y-6 sm:p-8"> <div class="p-6 space-y-4 md:space-y-6 sm:p-8">
<form class="flex flex-col gap-2" wire:submit='submit'> <form class="flex flex-col gap-2" wire:submit='submit'>

View file

@ -1,11 +0,0 @@
<div class="flex flex-col w-full gap-2">
<div>Your feedback helps us to improve Coolify. Thank you! 💜</div>
<form wire:submit="submit" class="flex flex-col gap-4 pt-4">
<x-forms.input minlength="3" required id="subject" label="Subject" placeholder="Help with..."></x-forms.input>
<x-forms.textarea minlength="10" maxlength="1000" required rows="10" id="description" label="Description"
class="font-sans" spellcheck
placeholder="Having trouble with... Please provide as much information as possible."></x-forms.textarea>
<div></div>
<x-forms.button class="w-full mt-4" type="submit">Send</x-forms.button>
</form>
</div>

View file

@ -1,12 +1,10 @@
<div x-data="{ <div x-data="{
popups: { popups: {
sponsorship: true,
notification: true, notification: true,
realtime: false, realtime: false,
}, },
isDevelopment: {{ isDev() ? 'true' : 'false' }}, isDevelopment: {{ isDev() ? 'true' : 'false' }},
init() { init() {
this.popups.sponsorship = this.shouldShowMonthlyPopup('popupSponsorship');
this.popups.notification = this.shouldShowMonthlyPopup('popupNotification'); this.popups.notification = this.shouldShowMonthlyPopup('popupNotification');
this.popups.realtime = localStorage.getItem('popupRealtime'); this.popups.realtime = localStorage.getItem('popupRealtime');
@ -24,8 +22,8 @@
if (checkNumber > 5) { if (checkNumber > 5) {
this.popups.realtime = true; this.popups.realtime = true;
console.error( console.error(
'Coolify could not connect to its real-time service. This will cause unusual problems on the UI if not fixed! Please check the related documentation (https://coolify.io/docs/knowledge-base/cloudflare/tunnels/overview) or get help on Discord (https://coollabs.io/discord).)' 'MapleDeploy could not connect to its real-time service. This will cause unusual problems on the UI if not fixed! Please contact support at support@mapledeploy.ca.'
); ); // MapleDeploy branding
} }
} }
@ -70,13 +68,11 @@
<x-slot:title> <x-slot:title>
<span class="font-bold text-left text-red-500">WARNING: </span> Cannot connect to real-time service <span class="font-bold text-left text-red-500">WARNING: </span> Cannot connect to real-time service
</x-slot:title> </x-slot:title>
{{-- MapleDeploy branding: support links updated --}}
<x-slot:description> <x-slot:description>
<div>This will cause unusual problems on the <div>This will cause unusual problems on the
UI! <br><br> UI! <br><br>
Please ensure that you have opened the Please contact <a class="underline" href='mailto:support@mapledeploy.ca'>MapleDeploy support</a> for help.
<a class="underline" href='https://coolify.io/docs/knowledge-base/server/firewall'
target='_blank'>required ports</a> or get
help on <a class="underline" href='https://coollabs.io/discord' target='_blank'>Discord</a>.
</div> </div>
</x-slot:description> </x-slot:description>
<x-slot:button-text @click="disableRealtime()"> <x-slot:button-text @click="disableRealtime()">
@ -86,52 +82,7 @@
@endif @endif
</span> </span>
@endauth @endauth
@if (instanceSettings()->is_sponsorship_popup_enabled && !isCloud()) {{-- MapleDeploy branding: Coolify sponsorship popup removed --}}
<span x-show="popups.sponsorship">
<x-popup>
<x-slot:customActions>
<div
class="flex md:flex-row flex-col max-w-4xl p-6 mx-auto bg-white border shadow-lg lg:border-t dark:border-coolgray-300 border-neutral-200 dark:bg-coolgray-100 lg:p-8 lg:pb-4 sm:rounded-sm gap-2">
<div class="md:block hidden">
<img src="{{ asset('heart.png') }}" class="w-20 h-20">
</div>
<div class="flex flex-col gap-2 lg:px-10 px-1">
<div class="lg:text-xl text-md dark:text-white font-bold">Love Coolify? Support our work.
</div>
<div class="lg:text-sm text-xs dark:text-white">
We are already profitable thanks to <span class="font-bold text-pink-500">YOU</span>
but...<br />We
would
like to
make
more cool features.
</div>
<div class="lg:text-sm text-xs dark:text-white pt-2 ">
For this we need your help to support our work financially.
</div>
</div>
<div class="flex flex-col gap-2 text-center md:mx-auto lg:py-0 pt-2">
<x-forms.button isHighlighted class="md:w-36 w-full"><a target="_blank"
href="https://github.com/sponsors/coollabsio"
class="font-bold dark:text-white">GitHub
Sponsors</a></x-forms.button>
<x-forms.button isHighlighted class="md:w-36 w-full"><a target="_blank"
href="https://opencollective.com/coollabsio/donate?interval=month&amount=10&name=&legalName=&email="
class="font-bold dark:text-white">Open
Collective</a></x-forms.button>
<x-forms.button isHighlighted class="md:w-36 w-full"><a
href="https://donate.stripe.com/8x2bJ104ifmB9kB45u38402" target="_blank"
class="font-bold dark:text-white">Stripe</a></x-forms.button>
<div class="pt-4 dark:text-white hover:underline cursor-pointer lg:text-base text-xs"
@click="bannerVisible=false;disableSponsorship()">
Maybe next time
</div>
</div>
</div>
</x-slot:customActions>
</x-popup>
</span>
@endif
@if (request()->query->get('cancelled')) @if (request()->query->get('cancelled'))
<x-banner> <x-banner>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
@ -209,10 +160,7 @@ class="underline dark:text-white">/subscription</a> to update your subscription
</span> </span>
@endif @endif
<script> <script>
function disableSponsorship() { // MapleDeploy branding: disableSponsorship() removed (popup removed)
// Store current timestamp instead of just 'false'
localStorage.setItem('popupSponsorship', Date.now().toString());
}
function disableNotification() { function disableNotification() {
// Store current timestamp instead of just 'false' // Store current timestamp instead of just 'false'

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Notifications | Coolify Notifications | MapleDeploy
</x-slot> </x-slot>
<x-notification.navbar /> <x-notification.navbar />
<form wire:submit='submit' class="flex flex-col gap-4 pb-4"> <form wire:submit='submit' class="flex flex-col gap-4 pb-4">

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Notifications | Coolify Notifications | MapleDeploy
</x-slot> </x-slot>
<x-notification.navbar /> <x-notification.navbar />
<form wire:submit='submit' class="flex flex-col gap-4 pb-4"> <form wire:submit='submit' class="flex flex-col gap-4 pb-4">

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Notifications | Coolify Notifications | MapleDeploy
</x-slot> </x-slot>
<x-notification.navbar /> <x-notification.navbar />
<form wire:submit='submit' class="flex flex-col gap-4 pb-4"> <form wire:submit='submit' class="flex flex-col gap-4 pb-4">

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Notifications | Coolify Notifications | MapleDeploy
</x-slot> </x-slot>
<x-notification.navbar /> <x-notification.navbar />
<form wire:submit='submit' class="flex flex-col gap-4 pb-4"> <form wire:submit='submit' class="flex flex-col gap-4 pb-4">

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Notifications | Coolify Notifications | MapleDeploy
</x-slot> </x-slot>
<x-notification.navbar /> <x-notification.navbar />
<form wire:submit='submit' class="flex flex-col gap-4 pb-4"> <form wire:submit='submit' class="flex flex-col gap-4 pb-4">

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Notifications | Coolify Notifications | MapleDeploy
</x-slot> </x-slot>
<x-notification.navbar /> <x-notification.navbar />
<form wire:submit='submit' class="flex flex-col gap-4 pb-4"> <form wire:submit='submit' class="flex flex-col gap-4 pb-4">
@ -29,7 +29,7 @@ class="normal-case dark:text-white btn btn-xs no-animation btn-primary">
<div class="flex items-end gap-2"> <div class="flex items-end gap-2">
<x-forms.input canGate="update" :canResource="$settings" type="password" <x-forms.input canGate="update" :canResource="$settings" type="password"
helper="Enter a valid HTTP or HTTPS URL. Coolify will send POST requests to this endpoint when events occur." helper="Enter a valid HTTP or HTTPS URL. MapleDeploy will send POST requests to this endpoint when events occur."
required id="webhookUrl" label="Webhook URL (POST)" /> required id="webhookUrl" label="Webhook URL (POST)" />
</div> </div>
</form> </form>

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
Profile | Coolify Profile | MapleDeploy
</x-slot> </x-slot>
<h1>Profile</h1> <h1>Profile</h1>
<div class="subtitle -mt-2">Your user profile settings.</div> <div class="subtitle -mt-2">Your user profile settings.</div>

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
{{ data_get_str($application, 'name')->limit(10) }} > Configuration | Coolify {{ data_get_str($application, 'name')->limit(10) }} > Configuration | MapleDeploy
</x-slot> </x-slot>
<h1>Configuration</h1> <h1>Configuration</h1>
<livewire:project.shared.configuration-checker :resource="$application" /> <livewire:project.shared.configuration-checker :resource="$application" />

View file

@ -1,5 +1,5 @@
<div> <div>
<x-slot:title>{{ data_get_str($application, 'name')->limit(10) }} > Deployments | Coolify</x-slot> <x-slot:title>{{ data_get_str($application, 'name')->limit(10) }} > Deployments | MapleDeploy</x-slot>
<h1>Deployments</h1> <h1>Deployments</h1>
<livewire:project.shared.configuration-checker :resource="$application" /> <livewire:project.shared.configuration-checker :resource="$application" />
<livewire:project.application.heading :application="$application" /> <livewire:project.application.heading :application="$application" />
@ -38,7 +38,7 @@
'p-2 border-l-2 bg-white dark:bg-coolgray-100', 'p-2 border-l-2 bg-white dark:bg-coolgray-100',
'border-blue-500/50 border-dashed' => 'border-blue-500/50 border-dashed' =>
data_get($deployment, 'status') === 'in_progress', data_get($deployment, 'status') === 'in_progress',
'border-purple-500/50 border-dashed' => 'border-amber-500/50 border-dashed' =>
data_get($deployment, 'status') === 'queued', data_get($deployment, 'status') === 'queued',
'border-white border-dashed' => 'border-white border-dashed' =>
data_get($deployment, 'status') === 'cancelled-by-user', data_get($deployment, 'status') === 'cancelled-by-user',
@ -52,7 +52,7 @@
'px-3 py-1 rounded-md text-xs font-medium shadow-xs', 'px-3 py-1 rounded-md text-xs font-medium shadow-xs',
'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300' => 'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300' =>
data_get($deployment, 'status') === 'in_progress', data_get($deployment, 'status') === 'in_progress',
'bg-purple-100/80 text-purple-700 dark:bg-purple-500/20 dark:text-purple-300' => 'bg-amber-100/80 text-amber-700 dark:bg-amber-500/20 dark:text-amber-300' =>
data_get($deployment, 'status') === 'queued', data_get($deployment, 'status') === 'queued',
'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200' => 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200' =>
data_get($deployment, 'status') === 'failed', data_get($deployment, 'status') === 'failed',

View file

@ -1,6 +1,6 @@
<div class="flex h-[calc(100vh-10rem)] min-h-[50rem] flex-col overflow-hidden"> <div class="flex h-[calc(100vh-10rem)] min-h-[50rem] flex-col overflow-hidden">
<x-slot:title> <x-slot:title>
{{ data_get_str($application, 'name')->limit(10) }} > Deployment | Coolify {{ data_get_str($application, 'name')->limit(10) }} > Deployment | MapleDeploy
</x-slot> </x-slot>
<h1 class="py-0">Deployment</h1> <h1 class="py-0">Deployment</h1>
<livewire:project.shared.configuration-checker :resource="$application" /> <livewire:project.shared.configuration-checker :resource="$application" />

View file

@ -1,6 +1,6 @@
<form> <form>
<x-slot:title> <x-slot:title>
{{ data_get_str($project, 'name')->limit(10) }} > Clone | Coolify {{ data_get_str($project, 'name')->limit(10) }} > Clone | MapleDeploy
</x-slot> </x-slot>
<div class="flex flex-col"> <div class="flex flex-col">
<h1>Clone</h1> <h1>Clone</h1>

View file

@ -1,6 +1,6 @@
<div> <div>
<x-slot:title> <x-slot:title>
{{ data_get_str($database, 'name')->limit(10) }} > Backup | Coolify {{ data_get_str($database, 'name')->limit(10) }} > Backup | MapleDeploy
</x-slot> </x-slot>
<h1>Backups</h1> <h1>Backups</h1>
<livewire:project.shared.configuration-checker :resource="$database" /> <livewire:project.shared.configuration-checker :resource="$database" />

Some files were not shown because too many files have changed in this diff Show more