diff --git a/apps/api/src/routes/api/v1/handlers.ts b/apps/api/src/routes/api/v1/handlers.ts index ae558320e..ed7a77c6e 100644 --- a/apps/api/src/routes/api/v1/handlers.ts +++ b/apps/api/src/routes/api/v1/handlers.ts @@ -73,6 +73,23 @@ export async function update(request: FastifyRequest) { return errorHandler({ status, message }) } } +export async function restartCoolify(request: FastifyRequest) { + try { + const teamId = request.user.teamId; + if (teamId === '0') { + if (!isDev) { + await asyncExecShell(`docker restart coolify`); + return {}; + } else { + console.log('Restarting Coolify') + return {}; + } + } + throw { status: 500, message: 'You are not authorized to restart Coolify.' }; + } catch ({ status, message }) { + return errorHandler({ status, message }) + } +} export async function showUsage() { try { return { diff --git a/apps/api/src/routes/api/v1/index.ts b/apps/api/src/routes/api/v1/index.ts index 0d145312d..8f9f821f8 100644 --- a/apps/api/src/routes/api/v1/index.ts +++ b/apps/api/src/routes/api/v1/index.ts @@ -1,5 +1,5 @@ import { FastifyPluginAsync } from 'fastify'; -import { checkUpdate, login, showDashboard, update, showUsage, getCurrentUser, cleanupManually } from './handlers'; +import { checkUpdate, login, showDashboard, update, showUsage, getCurrentUser, cleanupManually, restartCoolify } from './handlers'; import { GetCurrentUser } from './types'; export interface Update { @@ -47,6 +47,10 @@ const root: FastifyPluginAsync = async (fastify): Promise => { onRequest: [fastify.authenticate] }, async () => await showUsage()); + fastify.post('/internal/restart', { + onRequest: [fastify.authenticate] + }, async (request) => await restartCoolify(request)); + fastify.post('/internal/cleanup', { onRequest: [fastify.authenticate] }, async () => await cleanupManually()); diff --git a/apps/ui/src/lib/components/Usage.svelte b/apps/ui/src/lib/components/Usage.svelte index 66b201da3..a461f8419 100644 --- a/apps/ui/src/lib/components/Usage.svelte +++ b/apps/ui/src/lib/components/Usage.svelte @@ -20,7 +20,8 @@ let usageInterval: any; let loading = { usage: false, - cleanup: false + cleanup: false, + restart: false }; import { addToast, appSession } from '$lib/store'; import { onDestroy, onMount } from 'svelte'; @@ -33,6 +34,25 @@ usage = data.usage; 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`, {}); + addToast({ + type: 'success', + message: 'Coolify restarted successfully. It will take a moment.' + }); + } catch (error) { + return errorNotification(error); + } finally { + loading.restart = false; + } + } + } onDestroy(() => { clearInterval(usageInterval); }); @@ -67,51 +87,56 @@

Hardware Details

- {#if $appSession.teamId === '0'} - - {/if} +
+ {#if $appSession.teamId === '0'} + + + {/if} +
-
+
+
Memory
-
Total Memory
+
Total
{(usage?.memory.totalMemMb).toFixed(0)}MB
-
Used Memory
+
Used
{(usage?.memory.usedMemMb).toFixed(0)}MB
-
Free Memory
+
Free
{usage?.memory.freeMemPercentage}%
-