This commit is contained in:
Andras Bacsai
2022-09-06 15:33:32 +02:00
committed by GitHub
parent 73bd62c51e
commit 12ca20432d
15 changed files with 380 additions and 193 deletions

View File

@@ -5,11 +5,11 @@ on:
types: [released] types: [released]
jobs: jobs:
making-something-cool: arm64-build:
runs-on: ubuntu-latest runs-on: [self-hosted, arm64]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -26,11 +26,56 @@ jobs:
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: linux/arm64
push: true push: true
tags: coollabsio/coolify:latest,coollabsio/coolify:${{steps.package-version.outputs.current-version}} tags: coollabsio/coolify:${{steps.package-version.outputs.current-version}}-arm64
cache-from: type=registry,ref=coollabsio/coolify:buildcache cache-from: type=registry,ref=coollabsio/coolify:buildcache-arm64
cache-to: type=registry,ref=coollabsio/coolify:buildcache,mode=max cache-to: type=registry,ref=coollabsio/coolify:buildcache-arm64,mode=max
amd64-build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get current package version
uses: martinbeentjes/npm-get-version-action@v1.2.3
id: package-version
- name: Build and push
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64
push: true
tags: coollabsio/coolify:${{steps.package-version.outputs.current-version}}-amd64
cache-from: type=registry,ref=coollabsio/coolify:buildcache-amd64
cache-to: type=registry,ref=coollabsio/coolify:buildcache-amd64,mode=max
merge-manifest:
runs-on: ubuntu-latest
needs: [amd64-build, arm64-build]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create & publish manifest
run: |
docker manifest create coollabsio/coolify:${{steps.package-version.outputs.current-version}} --amend coollabsio/coolify:${{steps.package-version.outputs.current-version}}-amd64 --amend coollabsio/coolify:${{steps.package-version.outputs.current-version}}-arm64
docker manifest push coollabsio/coolify:${{steps.package-version.outputs.current-version}}
- uses: sarisia/actions-status-discord@v1 - uses: sarisia/actions-status-discord@v1
if: always() if: always()
with: with:

View File

@@ -1,17 +1,16 @@
name: release-candidate name: release-candidate
on: on:
release: release:
types: [prereleased] types: [prereleased]
jobs: jobs:
making-something-cool: arm64-making-something-cool:
runs-on: ubuntu-latest runs-on: [self-hosted, arm64]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
ref: 'next' ref: "next"
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -28,12 +27,64 @@ jobs:
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: linux/arm64
push: true push: true
tags: coollabsio/coolify:${{github.event.release.name}} tags: coollabsio/coolify:${{github.event.release.name}}-arm64
cache-from: type=registry,ref=coollabsio/coolify:buildcache-rc cache-from: type=registry,ref=coollabsio/coolify:buildcache-rc-arm64
cache-to: type=registry,ref=coollabsio/coolify:buildcache-rc,mode=max cache-to: type=registry,ref=coollabsio/coolify:buildcache-rc-arm64,mode=max
- uses: sarisia/actions-status-discord@v1 - uses: sarisia/actions-status-discord@v1
if: always() if: always()
with: with:
webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }} webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}
amd64-making-something-cool:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "next"
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get current package version
uses: martinbeentjes/npm-get-version-action@v1.2.3
id: package-version
- name: Build and push
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64
push: true
tags: coollabsio/coolify:${{github.event.release.name}}-amd64
cache-from: type=registry,ref=coollabsio/coolify:buildcache-rc-amd64
cache-to: type=registry,ref=coollabsio/coolify:buildcache-rc-amd64,mode=max
- uses: sarisia/actions-status-discord@v1
if: always()
with:
webhook: ${{ secrets.DISCORD_WEBHOOK_DEV_RELEASE_CHANNEL }}
merge-manifest-to-be-cool:
runs-on: ubuntu-latest
needs: [arm64-making-something-cool, amd64-making-something-cool]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create & publish manifest
run: |
docker manifest create coollabsio/coolify:${{github.event.release.name}} --amend coollabsio/coolify:${{github.event.release.name}}-amd64 --amend coollabsio/coolify:${{github.event.release.name}}-arm64
docker manifest push coollabsio/coolify:${{github.event.release.name}}

View File

@@ -6,11 +6,13 @@ on:
- next - next
jobs: jobs:
staging-release: arm64-making-something-cool:
runs-on: ubuntu-latest runs-on: [self-hosted, arm64]
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
with:
ref: "next"
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -20,15 +22,65 @@ jobs:
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get current package version
uses: martinbeentjes/npm-get-version-action@v1.2.3
id: package-version
- name: Build and push - name: Build and push
uses: docker/build-push-action@v2 uses: docker/build-push-action@v2
with:
context: .
platforms: linux/arm64
push: true
tags: coollabsio/coolify:next-arm64
cache-from: type=registry,ref=coollabsio/coolify:buildcache-next-arm64
cache-to: type=registry,ref=coollabsio/coolify:buildcache-next-arm64,mode=max
amd64-making-something-cool:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: "next"
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get current package version
uses: martinbeentjes/npm-get-version-action@v1.2.3
id: package-version
- name: Build and push
uses: docker/build-push-action@v3
with: with:
context: . context: .
platforms: linux/amd64 platforms: linux/amd64
push: true push: true
tags: coollabsio/coolify:next tags: coollabsio/coolify:next-amd64,coollabsio/coolify:next-test
cache-from: type=registry,ref=coollabsio/coolify:buildcache-next cache-from: type=registry,ref=coollabsio/coolify:buildcache-next-amd64
cache-to: type=registry,ref=coollabsio/coolify:buildcache-next,mode=max cache-to: type=registry,ref=coollabsio/coolify:buildcache-next-amd64,mode=max
merge-manifest-to-be-cool:
runs-on: ubuntu-latest
needs: [arm64-making-something-cool, amd64-making-something-cool]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Create & publish manifest
run: |
docker manifest create coollabsio/coolify:next --amend coollabsio/coolify:next-amd64 --amend coollabsio/coolify:next-arm64
docker manifest push coollabsio/coolify:next
- uses: sarisia/actions-status-discord@v1 - uses: sarisia/actions-status-discord@v1
if: always() if: always()
with: with:

View File

@@ -1,8 +1,11 @@
ARG PNPM_VERSION=7.11.0
ARG NPM_VERSION=8.19.1
FROM node:18-slim as build FROM node:18-slim as build
WORKDIR /app WORKDIR /app
RUN apt update && apt -y install curl RUN apt update && apt -y install curl
RUN curl -sL https://unpkg.com/@pnpm/self-installer | node RUN npm --no-update-notifier --no-fund --global install pnpm@${PNPM_VERSION}
COPY . . COPY . .
RUN pnpm install RUN pnpm install
@@ -14,8 +17,10 @@ WORKDIR /app
ENV NODE_ENV production ENV NODE_ENV production
ARG TARGETPLATFORM ARG TARGETPLATFORM
RUN apt update && apt -y install git git-lfs openssh-client curl jq cmake sqlite3 openssl psmisc python3 && apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/ RUN apt update && apt -y install --no-install-recommends ca-certificates git git-lfs openssh-client curl jq cmake sqlite3 openssl psmisc python3
RUN curl -sL https://unpkg.com/@pnpm/self-installer | node RUN apt-get clean autoclean && apt-get autoremove --yes && rm -rf /var/lib/{apt,dpkg,cache,log}/
RUN npm --no-update-notifier --no-fund --global install pnpm@${PNPM_VERSION}
RUN npm install -g npm@${PNPM_VERSION}
RUN mkdir -p ~/.docker/cli-plugins/ RUN mkdir -p ~/.docker/cli-plugins/
# https://download.docker.com/linux/static/stable/ # https://download.docker.com/linux/static/stable/

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Setting" ADD COLUMN "isAPIDebuggingEnabled" BOOLEAN DEFAULT false;

View File

@@ -11,6 +11,7 @@ datasource db {
model Setting { model Setting {
id String @id @default(cuid()) id String @id @default(cuid())
fqdn String? @unique fqdn String? @unique
isAPIDebuggingEnabled Boolean? @default(false)
isRegistrationEnabled Boolean @default(false) isRegistrationEnabled Boolean @default(false)
dualCerts Boolean @default(false) dualCerts Boolean @default(false)
minPort Int @default(9000) minPort Int @default(9000)

View File

@@ -5,7 +5,7 @@ import env from '@fastify/env';
import cookie from '@fastify/cookie'; import cookie from '@fastify/cookie';
import path, { join } from 'path'; import path, { join } from 'path';
import autoLoad from '@fastify/autoload'; import autoLoad from '@fastify/autoload';
import { asyncExecShell, createRemoteEngineConfiguration, isDev, listSettings, prisma, version } from './lib/common'; import { asyncExecShell, createRemoteEngineConfiguration, getDomain, isDev, listSettings, prisma, version } from './lib/common';
import { scheduler } from './lib/scheduler'; import { scheduler } from './lib/scheduler';
import { compareVersions } from 'compare-versions'; import { compareVersions } from 'compare-versions';
import Graceful from '@ladjs/graceful' import Graceful from '@ladjs/graceful'
@@ -26,11 +26,12 @@ declare module 'fastify' {
const port = isDev ? 3001 : 3000; const port = isDev ? 3001 : 3000;
const host = '0.0.0.0'; const host = '0.0.0.0';
const fastify = Fastify({ prisma.setting.findFirst().then(async (settings) => {
logger: false, const fastify = Fastify({
logger: settings?.isAPIDebuggingEnabled || false,
trustProxy: true trustProxy: true
}); });
const schema = { const schema = {
type: 'object', type: 'object',
required: ['COOLIFY_SECRET_KEY', 'COOLIFY_DATABASE_URL', 'COOLIFY_IS_ON'], required: ['COOLIFY_SECRET_KEY', 'COOLIFY_DATABASE_URL', 'COOLIFY_IS_ON'],
properties: { properties: {
@@ -66,14 +67,14 @@ const schema = {
}, },
} }
}; };
const options = { const options = {
schema, schema,
dotenv: true dotenv: true
}; };
fastify.register(env, options); fastify.register(env, options);
if (!isDev) { if (!isDev) {
fastify.register(serve, { fastify.register(serve, {
root: path.join(__dirname, './public'), root: path.join(__dirname, './public'),
preCompressed: true preCompressed: true
@@ -86,17 +87,35 @@ if (!isDev) {
} }
return reply.status(200).sendFile('index.html'); return reply.status(200).sendFile('index.html');
}); });
} }
fastify.register(autoLoad, { fastify.register(autoLoad, {
dir: join(__dirname, 'plugins') dir: join(__dirname, 'plugins')
}); });
fastify.register(autoLoad, { fastify.register(autoLoad, {
dir: join(__dirname, 'routes') dir: join(__dirname, 'routes')
}); });
fastify.register(cookie) fastify.register(cookie)
fastify.register(cors); fastify.register(cors);
fastify.listen({ port, host }, async (err: any, address: any) => { fastify.addHook('onRequest', async (request, reply) => {
let allowedList = ['coolify:3000'];
const { ipv4, ipv6, fqdn } = await prisma.setting.findFirst({})
ipv4 && allowedList.push(`${ipv4}:3000`);
ipv6 && allowedList.push(ipv6);
fqdn && allowedList.push(getDomain(fqdn));
isDev && allowedList.push('localhost:3000') && allowedList.push('localhost:3001') && allowedList.push('host.docker.internal:3001');
const remotes = await prisma.destinationDocker.findMany({ where: { remoteEngine: true, remoteVerified: true } })
if (remotes.length > 0) {
remotes.forEach(remote => {
allowedList.push(`${remote.remoteIpAddress}:3000`);
})
}
if (!allowedList.includes(request.headers.host)) {
// console.log('not allowed', request.headers.host)
}
})
fastify.listen({ port, host }, async (err: any, address: any) => {
if (err) { if (err) {
console.error(err); console.error(err);
process.exit(1); process.exit(1);
@@ -139,9 +158,11 @@ fastify.listen({ port, host }, async (err: any, address: any) => {
await Promise.all([ await Promise.all([
getArch(), getArch(),
getIPAddress(), getIPAddress(),
// configureRemoteDockers(), configureRemoteDockers(),
]) ])
}); });
})
async function getIPAddress() { async function getIPAddress() {
const { publicIpv4, publicIpv6 } = await import('public-ip') const { publicIpv4, publicIpv6 } = await import('public-ip')
try { try {

View File

@@ -357,21 +357,15 @@ import * as buildpacks from '../lib/buildPacks';
await saveBuildLog({ line: error, buildId, applicationId: application.id }); await saveBuildLog({ line: error, buildId, applicationId: application.id });
} }
}); });
} }
await pAll.default(actions, { concurrency }) await pAll.default(actions, { concurrency })
} }
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} finally {
} }
}) })
while (true) { while (true) {
await th() await th()
} }
} else process.exit(0); } else process.exit(0);
})(); })();

View File

@@ -21,7 +21,7 @@ import { scheduler } from './scheduler';
import { supportedServiceTypesAndVersions } from './services/supportedVersions'; import { supportedServiceTypesAndVersions } from './services/supportedVersions';
import { includeServices } from './services/common'; import { includeServices } from './services/common';
export const version = '3.9.0'; export const version = '3.9.1';
export const isDev = process.env.NODE_ENV === 'development'; export const isDev = process.env.NODE_ENV === 'development';
const algorithm = 'aes-256-ctr'; const algorithm = 'aes-256-ctr';
@@ -974,9 +974,14 @@ export const createDirectories = async ({
}): Promise<{ workdir: string; repodir: string }> => { }): Promise<{ workdir: string; repodir: string }> => {
const repodir = `/tmp/build-sources/${repository}/`; const repodir = `/tmp/build-sources/${repository}/`;
const workdir = `/tmp/build-sources/${repository}/${buildId}`; const workdir = `/tmp/build-sources/${repository}/${buildId}`;
let workdirFound = false;
try {
workdirFound = !!(await fs.stat(workdir));
} catch (error) { }
if (workdirFound) {
await asyncExecShell(`rm -fr ${workdir}`);
}
await asyncExecShell(`mkdir -p ${workdir}`); await asyncExecShell(`mkdir -p ${workdir}`);
return { return {
workdir, workdir,
repodir repodir

View File

@@ -28,6 +28,7 @@ export async function saveSettings(request: FastifyRequest<SaveSettings>, reply:
try { try {
const { const {
fqdn, fqdn,
isAPIDebuggingEnabled,
isRegistrationEnabled, isRegistrationEnabled,
dualCerts, dualCerts,
minPort, minPort,
@@ -39,7 +40,7 @@ export async function saveSettings(request: FastifyRequest<SaveSettings>, reply:
const { id } = await listSettings(); const { id } = await listSettings();
await prisma.setting.update({ await prisma.setting.update({
where: { id }, where: { id },
data: { isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, isDNSCheckEnabled, DNSServers } data: { isRegistrationEnabled, dualCerts, isAutoUpdateEnabled, isDNSCheckEnabled, DNSServers, isAPIDebuggingEnabled }
}); });
if (fqdn) { if (fqdn) {
await prisma.setting.update({ where: { id }, data: { fqdn } }); await prisma.setting.update({ where: { id }, data: { fqdn } });

View File

@@ -3,6 +3,7 @@ import { OnlyId } from "../../../../types"
export interface SaveSettings { export interface SaveSettings {
Body: { Body: {
fqdn: string, fqdn: string,
isAPIDebuggingEnabled: boolean,
isRegistrationEnabled: boolean, isRegistrationEnabled: boolean,
dualCerts: boolean, dualCerts: boolean,
minPort: number, minPort: number,

View File

@@ -1,4 +1,5 @@
import { FastifyPluginAsync } from 'fastify'; import { FastifyPluginAsync } from 'fastify';
import { OnlyId } from '../../../types';
import { remoteTraefikConfiguration, traefikConfiguration, traefikOtherConfiguration } from './handlers'; import { remoteTraefikConfiguration, traefikConfiguration, traefikOtherConfiguration } from './handlers';
import { TraefikOtherConfiguration } from './types'; import { TraefikOtherConfiguration } from './types';
@@ -6,7 +7,7 @@ const root: FastifyPluginAsync = async (fastify): Promise<void> => {
fastify.get('/main.json', async (request, reply) => traefikConfiguration(request, reply)); fastify.get('/main.json', async (request, reply) => traefikConfiguration(request, reply));
fastify.get<TraefikOtherConfiguration>('/other.json', async (request, reply) => traefikOtherConfiguration(request)); fastify.get<TraefikOtherConfiguration>('/other.json', async (request, reply) => traefikOtherConfiguration(request));
fastify.get('/remote/:id', async (request) => remoteTraefikConfiguration(request)); fastify.get<OnlyId>('/remote/:id', async (request) => remoteTraefikConfiguration(request));
}; };
export default root; export default root;

View File

@@ -20,13 +20,12 @@
let usageInterval: any; let usageInterval: any;
let loading = { let loading = {
usage: false, usage: false,
cleanup: false, cleanup: false
restart: false
}; };
import { addToast, appSession } from '$lib/store'; import { addToast, appSession } from '$lib/store';
import { onDestroy, onMount } from 'svelte'; import { onDestroy, onMount } from 'svelte';
import { get, post } from '$lib/api'; import { get, post } from '$lib/api';
import { asyncSleep, errorNotification } from '$lib/common'; import { errorNotification } from '$lib/common';
async function getStatus() { async function getStatus() {
if (loading.usage) return; if (loading.usage) return;
loading.usage = true; loading.usage = true;
@@ -34,45 +33,7 @@
usage = data.usage; usage = data.usage;
loading.usage = false; loading.usage = false;
} }
async function restartCoolify() {
const sure = confirm(
'Are you sure you would like to restart Coolify? Currently running deployments will be stopped and restarted.'
);
if (sure) {
loading.restart = true;
try {
await post(`/internal/restart`, {});
await asyncSleep(10000);
let reachable = false;
let tries = 0;
do {
await asyncSleep(4000);
try {
await get(`/undead`);
reachable = true;
} catch (error) {
reachable = false;
}
if (reachable) break;
tries++;
} while (!reachable || tries < 120);
addToast({
message: 'New version reachable. Reloading...',
type: 'success'
});
await asyncSleep(3000);
return window.location.reload();
addToast({
type: 'success',
message: 'Coolify restarted successfully. It will take a moment.'
});
} catch (error) {
return errorNotification(error);
} finally {
loading.restart = false;
}
}
}
onDestroy(() => { onDestroy(() => {
clearInterval(usageInterval); clearInterval(usageInterval);
}); });
@@ -112,11 +73,6 @@
<button on:click={manuallyCleanupStorage} class:loading={loading.cleanup} class="btn btn-sm" <button on:click={manuallyCleanupStorage} class:loading={loading.cleanup} class="btn btn-sm"
>Cleanup Storage</button >Cleanup Storage</button
> >
<button
on:click={restartCoolify}
class:loading={loading.restart}
class="btn btn-sm bg-red-600 hover:bg-red-500">Restart Coolify</button
>
{/if} {/if}
</div> </div>
</div> </div>

View File

@@ -23,10 +23,11 @@
import { browser } from '$app/env'; import { browser } from '$app/env';
import { t } from '$lib/translations'; import { t } from '$lib/translations';
import { addToast, appSession, features } from '$lib/store'; import { addToast, appSession, features } from '$lib/store';
import { errorNotification, getDomain } from '$lib/common'; import { asyncSleep, errorNotification, getDomain } from '$lib/common';
import Menu from './_Menu.svelte'; import Menu from './_Menu.svelte';
import Explainer from '$lib/components/Explainer.svelte'; import Explainer from '$lib/components/Explainer.svelte';
let isAPIDebuggingEnabled = settings.isAPIDebuggingEnabled;
let isRegistrationEnabled = settings.isRegistrationEnabled; let isRegistrationEnabled = settings.isRegistrationEnabled;
let dualCerts = settings.dualCerts; let dualCerts = settings.dualCerts;
let isAutoUpdateEnabled = settings.isAutoUpdateEnabled; let isAutoUpdateEnabled = settings.isAutoUpdateEnabled;
@@ -44,7 +45,8 @@
let loading = { let loading = {
save: false, save: false,
remove: false, remove: false,
proxyMigration: false proxyMigration: false,
restart: false
}; };
async function removeFqdn() { async function removeFqdn() {
@@ -75,8 +77,11 @@
if (name === 'isDNSCheckEnabled') { if (name === 'isDNSCheckEnabled') {
isDNSCheckEnabled = !isDNSCheckEnabled; isDNSCheckEnabled = !isDNSCheckEnabled;
} }
if (name === 'isAPIDebuggingEnabled') {
isAPIDebuggingEnabled = !isAPIDebuggingEnabled;
}
await post(`/settings`, { await post(`/settings`, {
isAPIDebuggingEnabled,
isRegistrationEnabled, isRegistrationEnabled,
dualCerts, dualCerts,
isAutoUpdateEnabled, isAutoUpdateEnabled,
@@ -152,6 +157,41 @@
function resetView() { function resetView() {
forceSave = false; forceSave = false;
} }
async function restartCoolify() {
const sure = confirm(
'Are you sure you would like to restart Coolify? Currently running deployments will be stopped and restarted.'
);
if (sure) {
loading.restart = true;
try {
await post(`/internal/restart`, {});
await asyncSleep(10000);
let reachable = false;
let tries = 0;
do {
await asyncSleep(4000);
try {
await get(`/undead`);
reachable = true;
} catch (error) {
reachable = false;
}
if (reachable) break;
tries++;
} while (!reachable || tries < 120);
addToast({
message: 'New version reachable. Reloading...',
type: 'success'
});
await asyncSleep(3000);
return window.location.reload();
} catch (error) {
return errorNotification(error);
} finally {
loading.restart = false;
}
}
}
</script> </script>
<div class="flex space-x-1 p-6 font-bold"> <div class="flex space-x-1 p-6 font-bold">
@@ -182,11 +222,14 @@
on:click|preventDefault={removeFqdn} on:click|preventDefault={removeFqdn}
disabled={loading.remove} disabled={loading.remove}
class="btn btn-sm" class="btn btn-sm"
class:bg-red-600={!loading.remove}
class:hover:bg-red-500={!loading.remove}
>{loading.remove ? $t('forms.removing') : $t('forms.remove_domain')}</button >{loading.remove ? $t('forms.removing') : $t('forms.remove_domain')}</button
> >
{/if} {/if}
<button
on:click={restartCoolify}
class:loading={loading.restart}
class="btn btn-sm bg-red-600 hover:bg-red-500">Restart Coolify</button
>
</div> </div>
<div class="grid grid-flow-row gap-2 px-10"> <div class="grid grid-flow-row gap-2 px-10">
<!-- <Language /> --> <!-- <Language /> -->
@@ -310,6 +353,15 @@
on:click={() => changeSettings('isRegistrationEnabled')} on:click={() => changeSettings('isRegistrationEnabled')}
/> />
</div> </div>
<div class="grid grid-cols-2 items-center">
<Setting
id="isAPIDebuggingEnabled"
bind:setting={isAPIDebuggingEnabled}
title="API Debugging"
description="Enable API debugging. This will log all API requests and responses.<br><br>You need to restart the Coolify for this to take effect."
on:click={() => changeSettings('isAPIDebuggingEnabled')}
/>
</div>
{#if browser && $features.beta} {#if browser && $features.beta}
<div class="grid grid-cols-2 items-center"> <div class="grid grid-cols-2 items-center">
<Setting <Setting

View File

@@ -1,7 +1,7 @@
{ {
"name": "coolify", "name": "coolify",
"description": "An open-source & self-hostable Heroku / Netlify alternative.", "description": "An open-source & self-hostable Heroku / Netlify alternative.",
"version": "3.9.0", "version": "3.9.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": "github:coollabsio/coolify", "repository": "github:coollabsio/coolify",
"scripts": { "scripts": {