forked from coollabsio/coolify
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit dbe82b3
Showing
101 changed files
with
12,479 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
dist | ||
.routify |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#################################### | ||
# Domain where your Coolify instance will be available and reachable. | ||
# It's the same as you set in Github OAuth App and Github App as <domain>. | ||
DOMAIN= | ||
## Let's Encrypt contact email required | ||
EMAIL= | ||
|
||
# JWT Token Sign Key for logging you in to Coolify's frontend | ||
JWT_SIGN_KEY= | ||
# Encryption key for SECRETS - do NOT share it with others! | ||
SECRETS_ENCRYPTION_KEY= | ||
|
||
# Docker Engine | ||
DOCKER_ENGINE=/var/run/docker.sock | ||
# Docker network to use internally between the proxy and your apps | ||
DOCKER_NETWORK=coollabs | ||
|
||
# Mongodb | ||
# Values in case if you are using our Mongodb installation - CHANGE user and password fields! | ||
MONGODB_HOST=coollabs-mongodb | ||
MONGODB_PORT=27017 | ||
MONGODB_USER=supercooldbuser | ||
MONGODB_PASSWORD=developmentPassword4db | ||
MONGODB_DB=coolLabs-prod | ||
|
||
# Frontend only variables | ||
VITE_GITHUB_APP_CLIENTID= | ||
VITE_GITHUB_APP_NAME= | ||
|
||
# Github OAuth & App secrets and private key - you can get it from Github. | ||
GITHUB_APP_CLIENT_SECRET= | ||
GITHUP_APP_WEBHOOK_SECRET= | ||
|
||
# It should look like this. Newlines breaks with \n | ||
GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA7Y+Uwkd8FINSwFktWGdtwCaOAazTDYR8ucEzGyR9r+ooJZhF\nOc32qgDSps6Q5DsqPOzvfhiviqU+et9VF+bJhfdzwJ+Le86QZH1RgsDMoY049XvI\nKSwP........" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.vscode | ||
.idea | ||
node_modules | ||
dist | ||
dist-ssr | ||
.routify | ||
.env | ||
yarn-error.log | ||
api/development/console.log | ||
.pnpm-debug.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"arrowParens": "avoid", | ||
"bracketSpacing": true, | ||
"printWidth": 80, | ||
"semi": true, | ||
"singleQuote": false, | ||
"tabWidth": 2, | ||
"trailingComma": "all", | ||
"svelteSortOrder" : "styles-scripts-markup", | ||
"svelteStrictMode": true, | ||
"svelteBracketNewLine": true, | ||
"svelteAllowShorthand": true, | ||
"plugins": ["prettier-plugin-svelte"] | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# About | ||
|
||
https://andrasbacsai.com/farewell-netlify-and-heroku-after-3-days-of-coding | ||
|
||
# Features | ||
- Deploy your Node.js and static sites just by pushing code to git. | ||
- Hassle-free installation and upgrade process. | ||
- One-click MongoDB, MySQL, PostgreSQL, CouchDB deployments! | ||
|
||
# Upcoming features | ||
- Backups & monitoring. | ||
- User analytics with privacy in mind. | ||
- And much more (see [Roadmap](https://github.com/coollabsio/coolify/projects/1)). | ||
|
||
|
||
# FAQ | ||
Q: What does Buildpack means? | ||
|
||
A: It defines your application's final form. Static means that it will be hosted as a static site in the end. (see next question below 👇) | ||
|
||
--- | ||
|
||
Q: How can I build a static site, like Next.js, Sapper (prerendered), etc ? | ||
|
||
A: Use `static` builder and set your `Build command`. | ||
|
||
# Screenshots | ||
|
||
[Login](https://coollabs.io/coolify/login.jpg) | ||
|
||
[Applications](https://coollabs.io/coolify/applications.jpg) | ||
|
||
[Databases](https://coollabs.io/coolify/databases.jpg) | ||
|
||
[Configuration](https://coollabs.io/coolify/configuration.jpg) | ||
|
||
[Settings](https://coollabs.io/coolify/settings.jpg) | ||
|
||
[Logs](https://coollabs.io/coolify/logs.jpg) | ||
|
||
# Getting Started | ||
|
||
Automatically: `sh <(curl -fsSL https://get.coollabs.io/install.sh) coolify` | ||
|
||
Manually: | ||
### Requirements before installation | ||
- [Docker](https://docs.docker.com/engine/install/) version 20+ | ||
- Docker in [swarm mode enabled](https://docs.docker.com/engine/reference/commandline/swarm_init/) (should be set manually before installation) | ||
- A [MongoDB](https://docs.mongodb.com/manual/installation/) instance. | ||
- We have a [simple installation](https://github.com/coollabsio/infrastructure/tree/main/mongo) if you need one | ||
- A configured DNS entry (see `.env.template`) | ||
- [Github App](https://docs.github.com/en/developers/apps/creating-a-github-app) | ||
|
||
- GitHub App name: could be anything weird | ||
- Homepage URL: https://yourdomain | ||
|
||
Identifying and authorizing users: | ||
- Callback URL: https://yourdomain/api/v1/login/github/app | ||
- Request user authorization (OAuth) during installation -> Check! | ||
|
||
Webhook: | ||
- Active -> Check! | ||
- Webhook URL: https://yourdomain/api/v1/webhooks/deploy | ||
- Webhook Secret: it should be super secret | ||
|
||
Repository permissions: | ||
- Contents: Read-only | ||
- Metadata: Read-only | ||
|
||
User permissions: | ||
- Email: Read-only | ||
|
||
Subscribe to events: | ||
- Push -> Check! | ||
|
||
### Installation | ||
- Clone this repository: `git clone [email protected]:coollabsio/coolify.git` | ||
- Set `.env` (see `.env.template`) | ||
- Installation: `bash install.sh all` | ||
|
||
## Updating process | ||
### Update everything (proxy+coolify) | ||
- `bash install.sh all` | ||
|
||
### Update coolify only | ||
- `bash install.sh coolify` | ||
|
||
### Update proxy only | ||
- `bash install.sh proxy` | ||
|
||
# Contact | ||
- Twitter: [@andrasbacsai](https://twitter.com/andrasbacsai) | ||
- Telegram: [@andrasbacsai](https://t.me/andrasbacsai) | ||
- Email: [[email protected]](mailto:[email protected]) | ||
|
||
# License | ||
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Please see the [LICENSE](/LICENSE) file in our repository for the full text. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
module.exports = async function (fastify, opts) { | ||
// Private routes | ||
fastify.register(async function (server) { | ||
if (process.env.NODE_ENV === 'production') server.register(require('./plugins/authentication')) | ||
server.register(require('./routes/v1/upgrade'), { prefix: '/upgrade' }) | ||
server.register(require('./routes/v1/settings'), { prefix: '/settings' }) | ||
server.register(require('./routes/v1/dashboard'), { prefix: '/dashboard' }) | ||
server.register(require('./routes/v1/config'), { prefix: '/config' }) | ||
server.register(require('./routes/v1/application/remove'), { prefix: '/application/remove' }) | ||
server.register(require('./routes/v1/application/logs'), { prefix: '/application/logs' }) | ||
server.register(require('./routes/v1/application/check'), { prefix: '/application/check' }) | ||
server.register(require('./routes/v1/application/deploy'), { prefix: '/application/deploy' }) | ||
server.register(require('./routes/v1/application/deploy/logs'), { prefix: '/application/deploy/logs' }) | ||
server.register(require('./routes/v1/databases'), { prefix: '/databases' }) | ||
}) | ||
// Public routes | ||
fastify.register(require('./routes/v1/verify'), { prefix: '/verify' }) | ||
fastify.register(require('./routes/v1/login/github'), { | ||
prefix: '/login/github' | ||
}) | ||
fastify.register(require('./routes/v1/webhooks/deploy'), { | ||
prefix: '/webhooks/deploy' | ||
}) | ||
fastify.register(require('./routes/v1/undead'), { | ||
prefix: '/undead' | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
const mongoose = require('mongoose') | ||
const { MongoMemoryServer } = require('mongodb-memory-server-core') | ||
|
||
const mongoServer = new MongoMemoryServer({ | ||
instance: { | ||
port: 27017, | ||
dbName: 'coolify', | ||
storageEngine: 'wiredTiger' | ||
}, | ||
binary: { | ||
version: '4.4.3' | ||
|
||
} | ||
}) | ||
|
||
mongoose.Promise = Promise | ||
mongoServer.getUri().then((mongoUri) => { | ||
const mongooseOpts = { | ||
useNewUrlParser: true, | ||
useUnifiedTopology: true | ||
} | ||
|
||
mongoose.connect(mongoUri, mongooseOpts) | ||
|
||
mongoose.connection.on('error', (e) => { | ||
if (e.message.code === 'ETIMEDOUT') { | ||
console.log(e) | ||
mongoose.connect(mongoUri, mongooseOpts) | ||
} | ||
console.log(e) | ||
}) | ||
|
||
mongoose.connection.once('open', () => { | ||
console.log(`Started in-memory mongodb ${mongoUri}`) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
const packs = require('../../../packs') | ||
const { saveAppLog } = require('../../logging') | ||
const Deployment = require('../../../models/Deployment') | ||
|
||
module.exports = async function (configuration) { | ||
const { id, organization, name, branch } = configuration.repository | ||
const { domain } = configuration.publish | ||
const deployId = configuration.general.deployId | ||
|
||
const execute = packs[configuration.build.pack] | ||
if (execute) { | ||
try { | ||
await Deployment.findOneAndUpdate( | ||
{ repoId: id, branch, deployId, organization, name, domain }, | ||
{ repoId: id, branch, deployId, organization, name, domain, progress: 'inprogress' }) | ||
await saveAppLog('### Building application.', configuration) | ||
|
||
await execute(configuration) | ||
|
||
await saveAppLog('### Building done.', configuration) | ||
} catch (error) { | ||
await Deployment.findOneAndUpdate( | ||
{ repoId: id, branch, deployId, organization, name, domain }, | ||
{ repoId: id, branch, deployId, organization, name, domain, progress: 'failed' }) | ||
if (error.stack) throw { error: error.stack, type: 'server' } | ||
throw { error, type: 'app' } | ||
} | ||
} else { | ||
await Deployment.findOneAndUpdate( | ||
{ repoId: id, branch, deployId, organization, name, domain }, | ||
{ repoId: id, branch, deployId, organization, name, domain, progress: 'failed' }) | ||
throw { error: 'No buildpack found.', type: 'app' } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
const { docker } = require('../../docker') | ||
const { execShellAsync, delay } = require('../../common') | ||
const Deployment = require('../../../models/Deployment') | ||
|
||
async function purgeOldThings () { | ||
try { | ||
await docker.engine.pruneImages() | ||
await docker.engine.pruneContainers() | ||
} catch (error) { | ||
throw { error, type: 'server' } | ||
} | ||
} | ||
|
||
async function cleanup (configuration) { | ||
const { id } = configuration.repository | ||
const deployId = configuration.general.deployId | ||
try { | ||
// Cleanup stucked deployments. | ||
const deployments = await Deployment.find({ repoId: id, deployId: { $ne: deployId }, progress: { $in: ['queued', 'inprogress'] } }) | ||
for (const deployment of deployments) { | ||
await Deployment.findByIdAndUpdate(deployment._id, { $set: { progress: 'failed' } }) | ||
} | ||
} catch (error) { | ||
throw { error, type: 'server' } | ||
} | ||
} | ||
|
||
async function deleteSameDeployments (configuration) { | ||
try { | ||
await (await docker.engine.listServices()).filter(r => r.Spec.Labels.managedBy === 'coolify' && r.Spec.Labels.type === 'application').map(async s => { | ||
const running = JSON.parse(s.Spec.Labels.configuration) | ||
if (running.repository.id === configuration.repository.id && running.repository.branch === configuration.repository.branch) { | ||
await execShellAsync(`docker stack rm ${s.Spec.Labels['com.docker.stack.namespace']}`) | ||
} | ||
}) | ||
} catch (error) { | ||
throw { error, type: 'server' } | ||
} | ||
} | ||
|
||
module.exports = { cleanup, deleteSameDeployments, purgeOldThings } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
const { uniqueNamesGenerator, adjectives, colors, animals } = require('unique-names-generator') | ||
const cuid = require('cuid') | ||
const { execShellAsync } = require('../common') | ||
const crypto = require('crypto') | ||
|
||
function getUniq () { | ||
return uniqueNamesGenerator({ dictionaries: [adjectives, animals, colors], length: 2 }) | ||
} | ||
|
||
function setDefaultConfiguration (configuration) { | ||
try { | ||
const nickname = getUniq() | ||
const deployId = cuid() | ||
|
||
const shaBase = JSON.stringify({ repository: configuration.repository }) | ||
const sha256 = crypto.createHash('sha256').update(shaBase).digest('hex') | ||
|
||
configuration.build.container.name = sha256.slice(0, 15) | ||
|
||
configuration.general.nickname = nickname | ||
configuration.general.deployId = deployId | ||
configuration.general.workdir = `/tmp/${deployId}` | ||
|
||
if (!configuration.publish.path) configuration.publish.path = '/' | ||
if (!configuration.publish.port) configuration.publish.port = configuration.build.pack === 'static' ? 80 : 3000 | ||
|
||
if (configuration.build.pack === 'static') { | ||
if (!configuration.build.command.installation) configuration.build.command.installation = 'yarn install' | ||
if (!configuration.build.directory) configuration.build.directory = '/' | ||
} | ||
|
||
if (configuration.build.pack === 'nodejs') { | ||
if (!configuration.build.command.installation) configuration.build.command.installation = 'yarn install' | ||
if (!configuration.build.directory) configuration.build.directory = '/' | ||
} | ||
|
||
return configuration | ||
} catch (error) { | ||
throw { error, type: 'server' } | ||
} | ||
} | ||
|
||
async function updateServiceLabels (configuration, services) { | ||
// In case of any failure during deployment, still update the current configuration. | ||
const found = services.find(s => { | ||
const config = JSON.parse(s.Spec.Labels.configuration) | ||
if (config.repository.id === configuration.repository.id && config.repository.branch === configuration.repository.branch) { | ||
return config | ||
} | ||
return null | ||
}) | ||
if (found) { | ||
const { ID } = found | ||
try { | ||
const Labels = { ...JSON.parse(found.Spec.Labels.configuration), ...configuration } | ||
execShellAsync(`docker service update --label-add configuration='${JSON.stringify(Labels)}' --label-add com.docker.stack.image='${configuration.build.container.name}:${configuration.build.container.tag}' ${ID}`) | ||
} catch (error) { | ||
console.log(error) | ||
} | ||
} | ||
} | ||
module.exports = { setDefaultConfiguration, updateServiceLabels } |
Oops, something went wrong.