mirror of
https://github.com/ershisan99/coolify.git
synced 2025-12-18 12:33:06 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f82207564f | ||
|
|
991a09838c | ||
|
|
25df4bfd85 | ||
|
|
d2f89d001b | ||
|
|
1971f227fd | ||
|
|
c1adffe260 | ||
|
|
e725887a55 | ||
|
|
5bf79b75b0 | ||
|
|
6926975e40 | ||
|
|
978a01c968 | ||
|
|
f421f5ee84 | ||
|
|
383831c7b8 | ||
|
|
41329facf7 | ||
|
|
7d3c644148 | ||
|
|
7fab9b5930 | ||
|
|
58763ef84c | ||
|
|
0e6abf172b | ||
|
|
9e681ece41 | ||
|
|
28f87a306d |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "coolify",
|
||||
"description": "An open-source & self-hostable Heroku / Netlify alternative.",
|
||||
"version": "2.4.5",
|
||||
"version": "2.4.8",
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
"dev": "docker-compose -f docker-compose-dev.yaml up -d && cross-env NODE_ENV=development & svelte-kit dev",
|
||||
|
||||
@@ -93,11 +93,16 @@ export const getUserDetails = async (
|
||||
}> => {
|
||||
const teamId = getTeam(event);
|
||||
const userId = event?.locals?.session?.data?.userId || null;
|
||||
const { permission = 'read' } = await db.prisma.permission.findFirst({
|
||||
where: { teamId, userId },
|
||||
select: { permission: true },
|
||||
rejectOnNotFound: true
|
||||
});
|
||||
let permission = 'read';
|
||||
if (teamId && userId) {
|
||||
const data = await db.prisma.permission.findFirst({
|
||||
where: { teamId, userId },
|
||||
select: { permission: true },
|
||||
rejectOnNotFound: true
|
||||
});
|
||||
if (data.permission) permission = data.permission;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
teamId,
|
||||
userId,
|
||||
|
||||
@@ -219,7 +219,6 @@ export function generateDatabaseConfiguration(database: Database & { settings: D
|
||||
return {
|
||||
privatePort: 5432,
|
||||
environmentVariables: {
|
||||
POSTGRESQL_POSTGRES_PASSWORD: rootUserPassword,
|
||||
POSTGRESQL_PASSWORD: dbUserPassword,
|
||||
POSTGRESQL_USERNAME: dbUser,
|
||||
POSTGRESQL_DATABASE: defaultDatabase
|
||||
|
||||
@@ -90,7 +90,7 @@ export async function addGitLabSource({
|
||||
appSecret,
|
||||
groupName
|
||||
}) {
|
||||
const encrptedAppSecret = encrypt(appSecret);
|
||||
const encryptedAppSecret = encrypt(appSecret);
|
||||
await prisma.gitSource.update({ where: { id }, data: { type, apiUrl, htmlUrl, name } });
|
||||
return await prisma.gitlabApp.create({
|
||||
data: {
|
||||
|
||||
@@ -46,8 +46,12 @@ export async function login({
|
||||
if (users === 0) {
|
||||
await prisma.setting.update({ where: { id }, data: { isRegistrationEnabled: false } });
|
||||
// Create default network & start Coolify Proxy
|
||||
await asyncExecShell(`docker network create --attachable coolify`);
|
||||
await startCoolifyProxy('/var/run/docker.sock');
|
||||
try {
|
||||
await asyncExecShell(`docker network create --attachable coolify`);
|
||||
} catch (error) {}
|
||||
try {
|
||||
await startCoolifyProxy('/var/run/docker.sock');
|
||||
} catch (error) {}
|
||||
uid = '0';
|
||||
}
|
||||
|
||||
|
||||
@@ -215,7 +215,8 @@ export async function configureHAProxy(): Promise<void> {
|
||||
plausibleAnalytics: true,
|
||||
vscodeserver: true,
|
||||
wordpress: true,
|
||||
ghost: true
|
||||
ghost: true,
|
||||
meiliSearch: true
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -236,9 +236,15 @@ export async function stopCoolifyProxy(
|
||||
export async function configureNetworkCoolifyProxy(engine: string): Promise<void> {
|
||||
const host = getEngine(engine);
|
||||
const destinations = await db.prisma.destinationDocker.findMany({ where: { engine } });
|
||||
const { stdout: networks } = await asyncExecShell(
|
||||
`DOCKER_HOST="${host}" docker ps -a --filter name=coolify-haproxy --format '{{json .Networks}}'`
|
||||
);
|
||||
const configuredNetworks = networks.replace(/"/g, '').replace('\n', '').split(',');
|
||||
for (const destination of destinations) {
|
||||
await asyncExecShell(
|
||||
`DOCKER_HOST="${host}" docker network connect ${destination.network} coolify-haproxy`
|
||||
);
|
||||
if (!configuredNetworks.includes(destination.network)) {
|
||||
await asyncExecShell(
|
||||
`DOCKER_HOST="${host}" docker network connect ${destination.network} coolify-haproxy`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import cuid from 'cuid';
|
||||
import fs from 'fs/promises';
|
||||
import getPort, { portNumbers } from 'get-port';
|
||||
import { supportedServiceTypesAndVersions } from '$lib/components/common';
|
||||
import { promises as dns } from 'dns';
|
||||
|
||||
export async function letsEncrypt(domain: string, id?: string, isCoolify = false): Promise<void> {
|
||||
try {
|
||||
@@ -148,7 +149,8 @@ export async function generateSSLCerts(): Promise<void> {
|
||||
plausibleAnalytics: true,
|
||||
vscodeserver: true,
|
||||
wordpress: true,
|
||||
ghost: true
|
||||
ghost: true,
|
||||
meiliSearch: true
|
||||
},
|
||||
orderBy: { createdAt: 'desc' }
|
||||
});
|
||||
@@ -198,16 +200,44 @@ export async function generateSSLCerts(): Promise<void> {
|
||||
file.endsWith('.pem') && certificates.push(file.replace(/\.pem$/, ''));
|
||||
}
|
||||
}
|
||||
const resolver = new dns.Resolver({ timeout: 2000 });
|
||||
resolver.setServers(['8.8.8.8', '1.1.1.1']);
|
||||
let ipv4, ipv6;
|
||||
try {
|
||||
ipv4 = await (await asyncExecShell(`curl -4s https://ifconfig.io`)).stdout;
|
||||
} catch (error) {}
|
||||
try {
|
||||
ipv6 = await (await asyncExecShell(`curl -6s https://ifconfig.io`)).stdout;
|
||||
} catch (error) {}
|
||||
for (const ssl of ssls) {
|
||||
if (!dev) {
|
||||
if (
|
||||
certificates.includes(ssl.domain) ||
|
||||
certificates.includes(ssl.domain.replace('www.', ''))
|
||||
) {
|
||||
console.log(`Certificate for ${ssl.domain} already exists`);
|
||||
// console.log(`Certificate for ${ssl.domain} already exists`);
|
||||
} else {
|
||||
console.log('Generating SSL for', ssl.domain);
|
||||
await letsEncrypt(ssl.domain, ssl.id, ssl.isCoolify);
|
||||
// Checking DNS entry before generating certificate
|
||||
if (ipv4 || ipv6) {
|
||||
let domains4 = [];
|
||||
let domains6 = [];
|
||||
try {
|
||||
domains4 = await resolver.resolve4(ssl.domain);
|
||||
} catch (error) {}
|
||||
try {
|
||||
domains6 = await resolver.resolve6(ssl.domain);
|
||||
} catch (error) {}
|
||||
if (domains4.length > 0 || domains6.length > 0) {
|
||||
if (
|
||||
(ipv4 && domains4.includes(ipv4.replace('\n', ''))) ||
|
||||
(ipv6 && domains6.includes(ipv6.replace('\n', '')))
|
||||
) {
|
||||
console.log('Generating SSL for', ssl.domain);
|
||||
return await letsEncrypt(ssl.domain, ssl.id, ssl.isCoolify);
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('DNS settings is incorrect for', ssl.domain, 'skipping.');
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
@@ -216,7 +246,27 @@ export async function generateSSLCerts(): Promise<void> {
|
||||
) {
|
||||
console.log(`Certificate for ${ssl.domain} already exists`);
|
||||
} else {
|
||||
console.log('Generating SSL for', ssl.domain);
|
||||
// Checking DNS entry before generating certificate
|
||||
if (ipv4 || ipv6) {
|
||||
let domains4 = [];
|
||||
let domains6 = [];
|
||||
try {
|
||||
domains4 = await resolver.resolve4(ssl.domain);
|
||||
} catch (error) {}
|
||||
try {
|
||||
domains6 = await resolver.resolve6(ssl.domain);
|
||||
} catch (error) {}
|
||||
if (domains4.length > 0 || domains6.length > 0) {
|
||||
if (
|
||||
(ipv4 && domains4.includes(ipv4.replace('\n', ''))) ||
|
||||
(ipv6 && domains6.includes(ipv6.replace('\n', '')))
|
||||
) {
|
||||
console.log('Generating SSL for', ssl.domain);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('DNS settings is incorrect for', ssl.domain, 'skipping.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +285,15 @@ export default async function (job: Job<BuilderJob, void, string>): Promise<void
|
||||
networks: [docker.network],
|
||||
labels,
|
||||
depends_on: [],
|
||||
restart: 'always'
|
||||
restart: 'always',
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -14,56 +14,23 @@ export default async function (): Promise<void> {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker rmi -f ${images}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//console.log(error);
|
||||
}
|
||||
try {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker container prune -f`);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//console.log(error);
|
||||
}
|
||||
try {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker image prune -f --filter "until=2h"`);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//console.log(error);
|
||||
}
|
||||
// Cleanup old images older than a day
|
||||
try {
|
||||
await asyncExecShell(`DOCKER_HOST=${host} docker image prune --filter "until=24h" -a -f`);
|
||||
} catch (error) {
|
||||
//console.log(error);
|
||||
}
|
||||
// Tagging images with labels
|
||||
// try {
|
||||
// const images = [
|
||||
// `coollabsio/${defaultProxyImageTcp}`,
|
||||
// `coollabsio/${defaultProxyImageHttp}`,
|
||||
// 'certbot/certbot:latest',
|
||||
// 'node:16.14.0-alpine',
|
||||
// 'alpine:latest',
|
||||
// 'nginx:stable-alpine',
|
||||
// 'node:lts',
|
||||
// 'php:apache',
|
||||
// 'rust:latest'
|
||||
// ];
|
||||
// for (const image of images) {
|
||||
// try {
|
||||
// await asyncExecShell(`DOCKER_HOST=${host} docker image inspect ${image}`);
|
||||
// } catch (error) {
|
||||
// await asyncExecShell(
|
||||
// `DOCKER_HOST=${host} docker pull ${image} && echo "FROM ${image}" | docker build --label coolify.image="true" -t "${image}" -`
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// } catch (error) {}
|
||||
// if (!dev) {
|
||||
// // Cleanup images that are not managed by coolify
|
||||
// try {
|
||||
// await asyncExecShell(
|
||||
// `DOCKER_HOST=${host} docker image prune --filter 'label!=coolify.image=true' -a -f`
|
||||
// );
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// }
|
||||
// // Cleanup old images >3 days
|
||||
// try {
|
||||
// await asyncExecShell(`DOCKER_HOST=${host} docker image prune --filter "until=72h" -a -f`);
|
||||
// } catch (error) {
|
||||
// console.log(error);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
export const publicPaths = [
|
||||
'/login',
|
||||
'/register',
|
||||
'/reset',
|
||||
'/reset/password',
|
||||
'/webhooks/success',
|
||||
'/webhooks/github',
|
||||
'/webhooks/github/install',
|
||||
|
||||
@@ -23,6 +23,14 @@ export type ComposeFileService = {
|
||||
dockerfile: string;
|
||||
args?: Record<string, unknown>;
|
||||
};
|
||||
deploy?: {
|
||||
restart_policy?: {
|
||||
condition?: string;
|
||||
delay?: string;
|
||||
max_attempts?: number;
|
||||
window?: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export type ComposerFileVersion =
|
||||
|
||||
@@ -36,8 +36,15 @@
|
||||
});
|
||||
}
|
||||
|
||||
async function loadBranchesByPage(page = 0) {
|
||||
return await get(`${apiUrl}/repos/${selected.repository}/branches?per_page=100&page=${page}`, {
|
||||
Authorization: `token ${$gitTokens.githubToken}`
|
||||
});
|
||||
}
|
||||
|
||||
let reposSelectOptions;
|
||||
let branchSelectOptions;
|
||||
|
||||
async function loadRepositories() {
|
||||
let page = 1;
|
||||
let reposCount = 0;
|
||||
@@ -58,24 +65,28 @@
|
||||
}));
|
||||
}
|
||||
async function loadBranches(event) {
|
||||
branches = [];
|
||||
selected.repository = event.detail.value;
|
||||
loading.branches = true;
|
||||
selected.branch = undefined;
|
||||
selected.projectId = repositories.find((repo) => repo.full_name === selected.repository).id;
|
||||
try {
|
||||
branches = await get(`${apiUrl}/repos/${selected.repository}/branches`, {
|
||||
Authorization: `token ${$gitTokens.githubToken}`
|
||||
});
|
||||
branchSelectOptions = branches.map((branch) => ({
|
||||
value: branch.name,
|
||||
label: branch.name
|
||||
}));
|
||||
return;
|
||||
} catch ({ error }) {
|
||||
return errorNotification(error);
|
||||
} finally {
|
||||
loading.branches = false;
|
||||
let page = 1;
|
||||
let branchCount = 0;
|
||||
loading.branches = true;
|
||||
const loadedBranches = await loadBranchesByPage();
|
||||
branches = branches.concat(loadedBranches);
|
||||
branchCount = branches.length;
|
||||
if (branchCount === 100) {
|
||||
while (branchCount === 100) {
|
||||
page = page + 1;
|
||||
const nextBranches = await loadBranchesByPage(page);
|
||||
branches = branches.concat(nextBranches);
|
||||
branchCount = nextBranches.length;
|
||||
}
|
||||
}
|
||||
loading.branches = false;
|
||||
branchSelectOptions = branches.map((branch) => ({
|
||||
value: branch.name,
|
||||
label: branch.name
|
||||
}));
|
||||
}
|
||||
async function isBranchAlreadyUsed(event) {
|
||||
selected.branch = event.detail.value;
|
||||
@@ -166,30 +177,36 @@
|
||||
{:else}
|
||||
<form on:submit|preventDefault={handleSubmit} class="flex flex-col justify-center text-center">
|
||||
<div class="flex-col space-y-3 md:space-y-0 space-x-1">
|
||||
<div class="flex gap-4">
|
||||
<div class="flex-col md:flex gap-4">
|
||||
<div class="custom-select-wrapper">
|
||||
<Select
|
||||
placeholder={loading.repositories
|
||||
? 'Loading repositories ...'
|
||||
? 'Loading repositories...'
|
||||
: 'Please select a repository'}
|
||||
id="repository"
|
||||
showIndicator={true}
|
||||
isWaiting={loading.repositories}
|
||||
on:select={loadBranches}
|
||||
items={reposSelectOptions}
|
||||
isDisabled={loading.repositories}
|
||||
isClearable={false}
|
||||
/>
|
||||
</div>
|
||||
<input class="hidden" bind:value={selected.projectId} name="projectId" />
|
||||
<div class="custom-select-wrapper">
|
||||
<Select
|
||||
placeholder={loading.branches
|
||||
? 'Loading branches ...'
|
||||
? 'Loading branches...'
|
||||
: !selected.repository
|
||||
? 'Please select a repository first'
|
||||
: 'Please select a branch'}
|
||||
id="repository"
|
||||
isWaiting={loading.branches}
|
||||
showIndicator={selected.repository}
|
||||
id="branches"
|
||||
on:select={isBranchAlreadyUsed}
|
||||
items={branchSelectOptions}
|
||||
isDisabled={loading.branches || !selected.repository}
|
||||
isClearable={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -202,13 +219,6 @@
|
||||
class:bg-orange-600={showSave}
|
||||
class:hover:bg-orange-500={showSave}>Save</button
|
||||
>
|
||||
<!-- <button class="w-40"
|
||||
><a
|
||||
class="no-underline"
|
||||
href="{apiUrl}/apps/{application.gitSource.githubApp.name}/installations/new"
|
||||
>Modify Repositories</a
|
||||
></button
|
||||
> -->
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
|
||||
@@ -45,7 +45,15 @@ export const post: RequestHandler = async (event) => {
|
||||
volumes: [volume],
|
||||
ulimits,
|
||||
labels,
|
||||
restart: 'always'
|
||||
restart: 'always',
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -76,10 +76,6 @@
|
||||
on:click|preventDefault={() => goto('/register')}
|
||||
class="bg-transparent hover:bg-coolgray-300 text-white ">Register</button
|
||||
>
|
||||
<button
|
||||
class="bg-transparent hover:bg-coolgray-300"
|
||||
on:click|preventDefault={() => goto('/reset')}>Reset password</button
|
||||
>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -105,6 +105,9 @@
|
||||
{#if userCount === 0}
|
||||
<div class="pt-5">
|
||||
You are registering the first user. It will be the administrator of your Coolify instance.
|
||||
<br />
|
||||
It will take a while, because Coolify will configure itself, the proxy and other docker related
|
||||
stuff.
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import * as db from '$lib/database';
|
||||
|
||||
export const get: RequestHandler = async () => {
|
||||
const users = await db.prisma.user.findMany({});
|
||||
return {
|
||||
status: 200,
|
||||
body: {
|
||||
users
|
||||
}
|
||||
};
|
||||
};
|
||||
export const post: RequestHandler = async (event) => {
|
||||
const { secretKey } = await event.request.json();
|
||||
if (secretKey !== process.env.COOLIFY_SECRET_KEY) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: 'Invalid secret key.'
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
status: 200
|
||||
};
|
||||
};
|
||||
@@ -1,96 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { get, post } from '$lib/api';
|
||||
import CopyPasswordField from '$lib/components/CopyPasswordField.svelte';
|
||||
import { errorNotification } from '$lib/form';
|
||||
import { toast } from '@zerodevx/svelte-toast';
|
||||
|
||||
let secretKey;
|
||||
let password = false;
|
||||
let users = [];
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
await post(`/reset.json`, { secretKey });
|
||||
password = true;
|
||||
const data = await get('/reset.json');
|
||||
users = data.users;
|
||||
return;
|
||||
} catch ({ error }) {
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
async function resetPassword(user) {
|
||||
try {
|
||||
await post(`/reset/password.json`, { secretKey, user });
|
||||
toast.push('Password reset done.');
|
||||
return;
|
||||
} catch ({ error }) {
|
||||
return errorNotification(error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="icons fixed top-0 left-0 m-3 cursor-pointer" on:click={() => goto('/')}>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
||||
<line x1="5" y1="12" x2="19" y2="12" />
|
||||
<line x1="5" y1="12" x2="11" y2="18" />
|
||||
<line x1="5" y1="12" x2="11" y2="6" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="pb-10 pt-24 text-center text-4xl font-bold">Reset Password</div>
|
||||
<div class="flex items-center justify-center">
|
||||
{#if password}
|
||||
<table class="mx-2 text-left">
|
||||
<thead class="mb-2">
|
||||
<tr>
|
||||
<th class="px-2">Email</th>
|
||||
<th>New password</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each users as user}
|
||||
<tr>
|
||||
<td class="px-2">{user.email}</td>
|
||||
<td class="flex space-x-2">
|
||||
<input
|
||||
id="newPassword"
|
||||
name="newPassword"
|
||||
bind:value={user.newPassword}
|
||||
placeholder="Super secure new password"
|
||||
/>
|
||||
<button
|
||||
class="mx-auto my-4 w-32 bg-coollabs hover:bg-coollabs-100"
|
||||
on:click={() => resetPassword(user)}>Reset</button
|
||||
></td
|
||||
>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{:else}
|
||||
<form class="flex flex-col" on:submit|preventDefault={handleSubmit}>
|
||||
<div class="text-center text-2xl py-2 font-bold">Secret Key</div>
|
||||
<CopyPasswordField
|
||||
isPasswordField={true}
|
||||
id="secretKey"
|
||||
name="secretKey"
|
||||
bind:value={secretKey}
|
||||
placeholder="You can find it in ~/coolify/.env (COOLIFY_SECRET_KEY)"
|
||||
/>
|
||||
<button type="submit" class="bg-coollabs hover:bg-coollabs-100 mx-auto w-32 my-4"
|
||||
>Submit</button
|
||||
>
|
||||
</form>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,27 +0,0 @@
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import * as db from '$lib/database';
|
||||
import { ErrorHandler, hashPassword } from '$lib/database';
|
||||
|
||||
export const post: RequestHandler = async (event) => {
|
||||
const { secretKey, user } = await event.request.json();
|
||||
if (secretKey !== process.env.COOLIFY_SECRET_KEY) {
|
||||
return {
|
||||
status: 500,
|
||||
body: {
|
||||
error: 'Invalid secret key.'
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
const hashedPassword = await hashPassword(user.newPassword);
|
||||
await db.prisma.user.update({
|
||||
where: { email: user.email },
|
||||
data: { password: hashedPassword }
|
||||
});
|
||||
return {
|
||||
status: 200
|
||||
};
|
||||
} catch (error) {
|
||||
return ErrorHandler(error);
|
||||
}
|
||||
};
|
||||
@@ -90,7 +90,15 @@ export const post: RequestHandler = async (event) => {
|
||||
environment: config.ghost.environmentVariables,
|
||||
restart: 'always',
|
||||
labels: makeLabelForServices('ghost'),
|
||||
depends_on: [`${id}-mariadb`]
|
||||
depends_on: [`${id}-mariadb`],
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
},
|
||||
[`${id}-mariadb`]: {
|
||||
container_name: `${id}-mariadb`,
|
||||
@@ -98,7 +106,15 @@ export const post: RequestHandler = async (event) => {
|
||||
networks: [network],
|
||||
volumes: [config.mariadb.volume],
|
||||
environment: config.mariadb.environmentVariables,
|
||||
restart: 'always'
|
||||
restart: 'always',
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -43,7 +43,15 @@ export const post: RequestHandler = async (event) => {
|
||||
environment: config.environmentVariables,
|
||||
restart: 'always',
|
||||
volumes: [config.volume],
|
||||
labels: makeLabelForServices('languagetool')
|
||||
labels: makeLabelForServices('languagetool'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -48,7 +48,15 @@ export const post: RequestHandler = async (event) => {
|
||||
environment: config.environmentVariables,
|
||||
restart: 'always',
|
||||
volumes: [config.volume],
|
||||
labels: makeLabelForServices('meilisearch')
|
||||
labels: makeLabelForServices('meilisearch'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -67,7 +67,15 @@ export const post: RequestHandler = async (event) => {
|
||||
networks: [network],
|
||||
volumes: [config.volume],
|
||||
restart: 'always',
|
||||
labels: makeLabelForServices('minio')
|
||||
labels: makeLabelForServices('minio'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -44,7 +44,15 @@ export const post: RequestHandler = async (event) => {
|
||||
volumes: [config.volume],
|
||||
environment: config.environmentVariables,
|
||||
restart: 'always',
|
||||
labels: makeLabelForServices('n8n')
|
||||
labels: makeLabelForServices('n8n'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -40,7 +40,15 @@ export const post: RequestHandler = async (event) => {
|
||||
networks: [network],
|
||||
environment: config.environmentVariables,
|
||||
restart: 'always',
|
||||
labels: makeLabelForServices('nocodb')
|
||||
labels: makeLabelForServices('nocodb'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -133,7 +133,15 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
|
||||
environment: config.plausibleAnalytics.environmentVariables,
|
||||
restart: 'always',
|
||||
depends_on: [`${id}-postgresql`, `${id}-clickhouse`],
|
||||
labels: makeLabelForServices('plausibleAnalytics')
|
||||
labels: makeLabelForServices('plausibleAnalytics'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '10s',
|
||||
max_attempts: 5,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
},
|
||||
[`${id}-postgresql`]: {
|
||||
container_name: `${id}-postgresql`,
|
||||
@@ -141,7 +149,15 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
|
||||
networks: [network],
|
||||
environment: config.postgresql.environmentVariables,
|
||||
volumes: [config.postgresql.volume],
|
||||
restart: 'always'
|
||||
restart: 'always',
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '10s',
|
||||
max_attempts: 5,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
},
|
||||
[`${id}-clickhouse`]: {
|
||||
build: workdir,
|
||||
@@ -149,7 +165,15 @@ COPY ./init-db.sh /docker-entrypoint-initdb.d/init-db.sh`;
|
||||
networks: [network],
|
||||
environment: config.clickhouse.environmentVariables,
|
||||
volumes: [config.clickhouse.volume],
|
||||
restart: 'always'
|
||||
restart: 'always',
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '10s',
|
||||
max_attempts: 5,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -42,7 +42,15 @@ export const post: RequestHandler = async (event) => {
|
||||
volumes: [config.volume],
|
||||
environment: config.environmentVariables,
|
||||
restart: 'always',
|
||||
labels: makeLabelForServices('uptimekuma')
|
||||
labels: makeLabelForServices('uptimekuma'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -43,7 +43,15 @@ export const post: RequestHandler = async (event) => {
|
||||
networks: [network],
|
||||
volumes: [config.volume],
|
||||
restart: 'always',
|
||||
labels: makeLabelForServices('vaultWarden')
|
||||
labels: makeLabelForServices('vaultWarden'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -52,7 +52,15 @@ export const post: RequestHandler = async (event) => {
|
||||
networks: [network],
|
||||
volumes: [config.volume],
|
||||
restart: 'always',
|
||||
labels: makeLabelForServices('vscodeServer')
|
||||
labels: makeLabelForServices('vscodeServer'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -77,7 +77,15 @@ export const post: RequestHandler = async (event) => {
|
||||
networks: [network],
|
||||
restart: 'always',
|
||||
depends_on: [`${id}-mysql`],
|
||||
labels: makeLabelForServices('wordpress')
|
||||
labels: makeLabelForServices('wordpress'),
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
},
|
||||
[`${id}-mysql`]: {
|
||||
container_name: `${id}-mysql`,
|
||||
@@ -85,7 +93,15 @@ export const post: RequestHandler = async (event) => {
|
||||
volumes: [config.mysql.volume],
|
||||
environment: config.mysql.environmentVariables,
|
||||
networks: [network],
|
||||
restart: 'always'
|
||||
restart: 'always',
|
||||
deploy: {
|
||||
restart_policy: {
|
||||
condition: 'on-failure',
|
||||
delay: '5s',
|
||||
max_attempts: 3,
|
||||
window: '120s'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
networks: {
|
||||
|
||||
@@ -50,7 +50,10 @@ textarea {
|
||||
}
|
||||
|
||||
#svelte .listContainer {
|
||||
@apply bg-coolgray-400 text-white scrollbar-w-2 scrollbar-thumb-coollabs scrollbar-track-coolgray-200;
|
||||
@apply bg-coolgray-400 text-white scrollbar-w-2 scrollbar-thumb-green-500 scrollbar-track-coolgray-200;
|
||||
}
|
||||
#svelte .selectedItem {
|
||||
@apply pl-3;
|
||||
}
|
||||
|
||||
#svelte .item.hover {
|
||||
|
||||
Reference in New Issue
Block a user