This commit is contained in:
Andras Bacsai 2021-06-24 23:31:08 +02:00 committed by GitHub
parent a8e9668c2b
commit 2d0f22b379
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 2220 additions and 1070 deletions

View File

@ -54,7 +54,6 @@ With Github integration
- [VSCode Server](https://github.com/cdr/code-server) - [VSCode Server](https://github.com/cdr/code-server)
- [MinIO](https://min.io) - [MinIO](https://min.io)
## Support ## Support
- Twitter: [@andrasbacsai](https://twitter.com/andrasbacsai) - Twitter: [@andrasbacsai](https://twitter.com/andrasbacsai)

View File

@ -1,7 +1,7 @@
{ {
"name": "coolify", "name": "coolify",
"description": "An open-source, hassle-free, self-hostable Heroku & Netlify alternative.", "description": "An open-source, hassle-free, self-hostable Heroku & Netlify alternative.",
"version": "1.0.21", "version": "1.0.22",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"scripts": { "scripts": {
"dev:docker:start": "docker-compose -f docker-compose-dev.yml up -d", "dev:docker:start": "docker-compose -f docker-compose-dev.yml up -d",
@ -50,6 +50,7 @@
"generate-password": "^1.6.0", "generate-password": "^1.6.0",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"microtip": "^0.2.2",
"mongoose": "^5.12.13", "mongoose": "^5.12.13",
"shelljs": "^0.8.4", "shelljs": "^0.8.4",
"svelte-kit-cookie-session": "^1.0.6", "svelte-kit-cookie-session": "^1.0.6",

2528
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,6 @@
<link rel="dns-prefetch" href="https://cdn.coollabs.io/" /> <link rel="dns-prefetch" href="https://cdn.coollabs.io/" />
<link rel="preconnect" href="https://cdn.coollabs.io/" crossorigin="" /> <link rel="preconnect" href="https://cdn.coollabs.io/" crossorigin="" />
<link rel="stylesheet" href="https://cdn.coollabs.io/fonts/montserrat/montserrat.css" /> <link rel="stylesheet" href="https://cdn.coollabs.io/fonts/montserrat/montserrat.css" />
<link rel="stylesheet" href="https://cdn.coollabs.io/css/microtip-0.2.2.min.css" />
%svelte.head% %svelte.head%
</head> </head>
<body> <body>

View File

@ -101,7 +101,7 @@ export async function handle({ request, resolve }) {
cookie: { path: '/', secure: true } cookie: { path: '/', secure: true }
}); });
} catch (error) { } catch (error) {
console.log(error) console.log(error);
return { return {
status: 302, status: 302,
headers: { headers: {
@ -124,7 +124,7 @@ export async function handle({ request, resolve }) {
if (!session['set-cookie']) { if (!session['set-cookie']) {
if (!session?.data?.coolToken && !publicPages.includes(request.path)) { if (!session?.data?.coolToken && !publicPages.includes(request.path)) {
return { return {
status: 301, status: 302,
headers: { headers: {
location: '/' location: '/'
} }

View File

@ -70,9 +70,9 @@ export default async function (configuration, imageChanged) {
} }
async function purgeImagesAsync(found) { async function purgeImagesAsync(found) {
await delay(10000); await delay(10000);
await purgeImagesContainers(found, true); await purgeImagesContainers(found);
} }
purgeImagesAsync(configuration); //purgeImagesAsync(configuration);
await saveAppLog('### Published done!', configuration); await saveAppLog('### Published done!', configuration);
} }

View File

@ -1,2 +1,8 @@
export const publicPages = ['/', '/api/v1/login/github/app', '/api/v1/webhooks/deploy', '/success', '/api/v1/login/email'] export const publicPages = [
export const VITE_GITHUB_APP_NAME = import.meta.env.VITE_GITHUB_APP_NAME '/',
'/api/v1/login/github/app',
'/api/v1/webhooks/deploy',
'/success',
'/api/v1/login/email'
];
export const VITE_GITHUB_APP_NAME = import.meta.env.VITE_GITHUB_APP_NAME;

View File

@ -9,7 +9,7 @@
if (!publicPages.includes(path)) { if (!publicPages.includes(path)) {
if (!session.session.isLoggedIn) { if (!session.session.isLoggedIn) {
return { return {
status: 301, status: 302,
redirect: '/' redirect: '/'
}; };
} }
@ -17,7 +17,7 @@
} }
if (!publicPages.includes(path)) { if (!publicPages.includes(path)) {
return { return {
status: 301, status: 302,
redirect: '/' redirect: '/'
}; };
} }
@ -26,6 +26,7 @@
</script> </script>
<script lang="ts"> <script lang="ts">
import 'microtip/microtip.css';
import '../app.postcss'; import '../app.postcss';
export let initDashboard; export let initDashboard;
import { onMount } from 'svelte'; import { onMount } from 'svelte';

View File

@ -9,7 +9,7 @@ import type { Request } from '@sveltejs/kit';
const saltRounds = 15; const saltRounds = 15;
export async function post(request: Request) { export async function post(request: Request) {
const { email, password } = request.body const { email, password } = request.body;
const { JWT_SIGN_KEY } = process.env; const { JWT_SIGN_KEY } = process.env;
const settings = await Settings.findOne({ applicationName: 'coolify' }); const settings = await Settings.findOne({ applicationName: 'coolify' });
const registeredUsers = await User.find().countDocuments(); const registeredUsers = await User.find().countDocuments();
@ -26,7 +26,7 @@ export async function post(request: Request) {
}; };
} }
uid = foundUser.uid; uid = foundUser.uid;
if (!await bcrypt.compare(password, foundUser.password)) { if (!(await bcrypt.compare(password, foundUser.password))) {
return { return {
status: 500, status: 500,
body: { body: {
@ -95,11 +95,10 @@ export async function post(request: Request) {
return { return {
status: 200, status: 200,
body: { body: {
message: "Successfully logged in." message: 'Successfully logged in.'
} }
}; };
} catch (error) { } catch (error) {
return { status: 500, body: { error: error.message || error } }; return { status: 500, body: { error: error.message || error } };
} }
} }

View File

@ -2,17 +2,19 @@ import { saveServerLog } from '$lib/api/applications/logging';
import { execShellAsync } from '$lib/api/common'; import { execShellAsync } from '$lib/api/common';
import type { Request } from '@sveltejs/kit'; import type { Request } from '@sveltejs/kit';
export async function post(request: Request) { export async function post(request: Request) {
try { try {
const output = await execShellAsync('docker builder prune -af') const output = await execShellAsync('docker builder prune -af');
return { return {
status: 200, status: 200,
body: { body: {
message: 'OK', message: 'OK',
output: output.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm,"").split('\n').pop() output: output
} .replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, '')
.split('\n')
.pop()
} }
};
} catch (error) { } catch (error) {
await saveServerLog(error); await saveServerLog(error);
return { return {

View File

@ -2,17 +2,19 @@ import { saveServerLog } from '$lib/api/applications/logging';
import { execShellAsync } from '$lib/api/common'; import { execShellAsync } from '$lib/api/common';
import type { Request } from '@sveltejs/kit'; import type { Request } from '@sveltejs/kit';
export async function post(request: Request) { export async function post(request: Request) {
try { try {
const output = await execShellAsync('docker container prune -f') const output = await execShellAsync('docker container prune -f');
return { return {
status: 200, status: 200,
body: { body: {
message: 'OK', message: 'OK',
output: output.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm,"").split('\n').pop() output: output
} .replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, '')
.split('\n')
.pop()
} }
};
} catch (error) { } catch (error) {
await saveServerLog(error); await saveServerLog(error);
return { return {

View File

@ -2,17 +2,19 @@ import { saveServerLog } from '$lib/api/applications/logging';
import { execShellAsync } from '$lib/api/common'; import { execShellAsync } from '$lib/api/common';
import type { Request } from '@sveltejs/kit'; import type { Request } from '@sveltejs/kit';
export async function post(request: Request) { export async function post(request: Request) {
try { try {
const output = await execShellAsync('docker image prune -af') const output = await execShellAsync('docker image prune -af');
return { return {
status: 200, status: 200,
body: { body: {
message: 'OK', message: 'OK',
output: output.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm,"").split('\n').pop() output: output
} .replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, '')
.split('\n')
.pop()
} }
};
} catch (error) { } catch (error) {
await saveServerLog(error); await saveServerLog(error);
return { return {

View File

@ -2,17 +2,19 @@ import { saveServerLog } from '$lib/api/applications/logging';
import { execShellAsync } from '$lib/api/common'; import { execShellAsync } from '$lib/api/common';
import type { Request } from '@sveltejs/kit'; import type { Request } from '@sveltejs/kit';
export async function post(request: Request) { export async function post(request: Request) {
try { try {
const output = await execShellAsync('docker volume prune -f') const output = await execShellAsync('docker volume prune -f');
return { return {
status: 200, status: 200,
body: { body: {
message: 'OK', message: 'OK',
output: output.replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm,"").split('\n').pop() output: output
} .replace(/^(?=\n)$|^\s*|\s*$|\n\n+/gm, '')
.split('\n')
.pop()
} }
};
} catch (error) { } catch (error) {
await saveServerLog(error); await saveServerLog(error);
return { return {

View File

@ -2,26 +2,26 @@ import { saveServerLog } from '$lib/api/applications/logging';
import { execShellAsync } from '$lib/api/common'; import { execShellAsync } from '$lib/api/common';
import { docker } from '$lib/api/docker'; import { docker } from '$lib/api/docker';
import type { Request } from '@sveltejs/kit'; import type { Request } from '@sveltejs/kit';
import systeminformation from 'systeminformation' import systeminformation from 'systeminformation';
export async function get(request: Request) { export async function get(request: Request) {
try { try {
const df = await execShellAsync( const df = await execShellAsync(`docker system df --format '{{ json . }}'`);
`docker system df --format '{{ json . }}'`
);
const dockerReclaimable = df const dockerReclaimable = df
.split('\n') .split('\n')
.filter((n) => n) .filter((n) => n)
.map((s) => JSON.parse(s)) .map((s) => JSON.parse(s));
return { return {
status: 200, status: 200,
body: { body: {
hostname: await (await systeminformation.osInfo()).hostname, hostname: await (await systeminformation.osInfo()).hostname,
filesystems: await (await systeminformation.fsSize()).filter(fs => !fs.fs.match('/dev/loop') || !fs.fs.match('/var/lib/docker/')), filesystems: await (
await systeminformation.fsSize()
).filter((fs) => !fs.fs.match('/dev/loop') || !fs.fs.match('/var/lib/docker/')),
dockerReclaimable dockerReclaimable
} }
} };
} catch (error) { } catch (error) {
await saveServerLog(error); await saveServerLog(error);
return { return {

View File

@ -59,8 +59,8 @@ export async function post(request: Request) {
volumes: { volumes: {
[`${deployId}-code-server-data`]: { [`${deployId}-code-server-data`]: {
external: true external: true
}, }
}, }
}; };
await execShellAsync(`mkdir -p ${workdir}`); await execShellAsync(`mkdir -p ${workdir}`);
await fs.writeFile(`${workdir}/stack.yml`, yaml.dump(stack)); await fs.writeFile(`${workdir}/stack.yml`, yaml.dump(stack));

View File

@ -1,6 +1,6 @@
import { execShellAsync } from '$lib/api/common'; import { execShellAsync } from '$lib/api/common';
import type { Request } from '@sveltejs/kit'; import type { Request } from '@sveltejs/kit';
import yaml from "js-yaml" import yaml from 'js-yaml';
export async function get(request: Request) { export async function get(request: Request) {
// const { POSTGRESQL_USERNAME, POSTGRESQL_PASSWORD, POSTGRESQL_DATABASE } = JSON.parse( // const { POSTGRESQL_USERNAME, POSTGRESQL_PASSWORD, POSTGRESQL_DATABASE } = JSON.parse(
@ -15,9 +15,11 @@ export async function get(request: Request) {
.trim() .trim()
.split('\n'); .split('\n');
const codeServer = containers.find((container) => container.startsWith('code-server')); const codeServer = containers.find((container) => container.startsWith('code-server'));
const configYaml = yaml.load(await execShellAsync( const configYaml = yaml.load(
await execShellAsync(
`docker exec ${codeServer} cat /home/coder/.config/code-server/config.yaml` `docker exec ${codeServer} cat /home/coder/.config/code-server/config.yaml`
)) )
);
return { return {
status: 200, status: 200,
body: { message: 'OK', password: configYaml.password } body: { message: 'OK', password: configYaml.password }

View File

@ -13,9 +13,14 @@ export async function post(request: Request) {
const workdir = '/tmp/minio'; const workdir = '/tmp/minio';
const deployId = 'minio'; const deployId = 'minio';
const secrets = [ const secrets = [
{ name: 'MINIO_ROOT_USER', value: generator.generate({ length: 12, numbers: true, strict: true }) }, {
{ name: 'MINIO_ROOT_PASSWORD', value: generator.generate({ length: 24, numbers: true, strict: true }) } name: 'MINIO_ROOT_USER',
value: generator.generate({ length: 12, numbers: true, strict: true })
},
{
name: 'MINIO_ROOT_PASSWORD',
value: generator.generate({ length: 24, numbers: true, strict: true })
}
]; ];
const generateEnvsMinIO = {}; const generateEnvsMinIO = {};
for (const secret of secrets) generateEnvsMinIO[secret.name] = secret.value; for (const secret of secrets) generateEnvsMinIO[secret.name] = secret.value;
@ -62,8 +67,8 @@ export async function post(request: Request) {
volumes: { volumes: {
[`${deployId}-minio-data`]: { [`${deployId}-minio-data`]: {
external: true external: true
}, }
}, }
}; };
await execShellAsync(`mkdir -p ${workdir}`); await execShellAsync(`mkdir -p ${workdir}`);
await fs.writeFile(`${workdir}/stack.yml`, yaml.dump(stack)); await fs.writeFile(`${workdir}/stack.yml`, yaml.dump(stack));

View File

@ -10,16 +10,20 @@ export async function post(request: Request) {
let { baseURL, remoteDB, database, wordpressExtraConfiguration } = request.body; let { baseURL, remoteDB, database, wordpressExtraConfiguration } = request.body;
const traefikURL = baseURL; const traefikURL = baseURL;
baseURL = `https://${baseURL}`; baseURL = `https://${baseURL}`;
console.log({ baseURL, remoteDB, database, wordpressExtraConfiguration }) console.log({ baseURL, remoteDB, database, wordpressExtraConfiguration });
const workdir = '/tmp/wordpress'; const workdir = '/tmp/wordpress';
const deployId = `wp-${generator.generate({ length: 5, numbers: true, strict: true })}` const deployId = `wp-${generator.generate({ length: 5, numbers: true, strict: true })}`;
const defaultDatabaseName = generator.generate({ length: 12, numbers: true, strict: true }) const defaultDatabaseName = generator.generate({ length: 12, numbers: true, strict: true });
const defaultDatabaseHost = `${deployId}-mysql` const defaultDatabaseHost = `${deployId}-mysql`;
const defaultDatabaseUser = generator.generate({ length: 12, numbers: true, strict: true }) const defaultDatabaseUser = generator.generate({ length: 12, numbers: true, strict: true });
const defaultDatabasePassword = generator.generate({ length: 24, numbers: true, strict: true }) const defaultDatabasePassword = generator.generate({ length: 24, numbers: true, strict: true });
const defaultDatabaseRootPassword = generator.generate({ length: 24, numbers: true, strict: true }) const defaultDatabaseRootPassword = generator.generate({
const defaultDatabaseRootUser = generator.generate({ length: 12, numbers: true, strict: true }) length: 24,
numbers: true,
strict: true
});
const defaultDatabaseRootUser = generator.generate({ length: 12, numbers: true, strict: true });
let secrets = [ let secrets = [
{ name: 'WORDPRESS_DB_HOST', value: defaultDatabaseHost }, { name: 'WORDPRESS_DB_HOST', value: defaultDatabaseHost },
{ name: 'WORDPRESS_DB_USER', value: defaultDatabaseUser }, { name: 'WORDPRESS_DB_USER', value: defaultDatabaseUser },
@ -46,7 +50,7 @@ export async function post(request: Request) {
{ name: 'WORDPRESS_DB_NAME', value: database.name }, { name: 'WORDPRESS_DB_NAME', value: database.name },
{ name: 'WORDPRESS_TABLE_PREFIX', value: database.tablePrefix }, { name: 'WORDPRESS_TABLE_PREFIX', value: database.tablePrefix },
{ name: 'WORDPRESS_CONFIG_EXTRA', value: wordpressExtraConfiguration } { name: 'WORDPRESS_CONFIG_EXTRA', value: wordpressExtraConfiguration }
] ];
} }
const generateEnvsWordpress = {}; const generateEnvsWordpress = {};
@ -91,11 +95,7 @@ export async function post(request: Request) {
volumes: [volume], volumes: [volume],
deploy: { deploy: {
...baseServiceConfiguration, ...baseServiceConfiguration,
labels: [ labels: ['managedBy=coolify', 'type=service', 'serviceName=' + deployId]
'managedBy=coolify',
'type=service',
'serviceName=' + deployId,
]
} }
} }
}, },
@ -111,7 +111,7 @@ export async function post(request: Request) {
[`${deployId}-mysql-data`]: { [`${deployId}-mysql-data`]: {
external: true external: true
} }
}, }
}; };
if (remoteDB) { if (remoteDB) {
stack = { stack = {
@ -157,7 +157,7 @@ export async function post(request: Request) {
[`${deployId}-wordpress-data`]: { [`${deployId}-wordpress-data`]: {
external: true external: true
} }
}, }
}; };
} }
await execShellAsync(`mkdir -p ${workdir}`); await execShellAsync(`mkdir -p ${workdir}`);

View File

@ -5,7 +5,7 @@
export async function load(session) { export async function load(session) {
if (!browser && !process.env.VITE_GITHUB_APP_CLIENTID) { if (!browser && !process.env.VITE_GITHUB_APP_CLIENTID) {
return { return {
status: 301, status: 302,
redirect: '/dashboard/services' redirect: '/dashboard/services'
}; };
} }

View File

@ -6,7 +6,7 @@
export async function load(session) { export async function load(session) {
if (!browser && !process.env.VITE_GITHUB_APP_CLIENTID) { if (!browser && !process.env.VITE_GITHUB_APP_CLIENTID) {
return { return {
status: 301, status: 302,
redirect: '/dashboard/services' redirect: '/dashboard/services'
}; };
} }

View File

@ -5,7 +5,7 @@
export async function load(session) { export async function load(session) {
if (!browser && !process.env.VITE_GITHUB_APP_CLIENTID) { if (!browser && !process.env.VITE_GITHUB_APP_CLIENTID) {
return { return {
status: 301, status: 302,
redirect: '/dashboard/services' redirect: '/dashboard/services'
}; };
} }

View File

@ -8,7 +8,7 @@ import type {
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
export const settings = writable({ export const settings = writable({
clientId: null clientId: null
}) });
export const dashboard = writable<Dashboard>({ export const dashboard = writable<Dashboard>({
databases: { databases: {
deployed: [] deployed: []