From 5f6cdf7a71652cea5a08034f7ae8a2d30c73fafa Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Fri, 25 Apr 2025 10:25:26 +0200
Subject: [PATCH 001/144] feat(README): add InterviewPal sponsorship link and
corresponding SVG icon
---
README.md | 2 ++
public/svgs/interviewpal.svg | 1 +
2 files changed, 3 insertions(+)
create mode 100644 public/svgs/interviewpal.svg
diff --git a/README.md b/README.md
index 6e245aa22..5f583df75 100644
--- a/README.md
+++ b/README.md
@@ -131,6 +131,8 @@ Thank you so much!
+
+
...and many more at [GitHub Sponsors](https://github.com/sponsors/coollabsio)
diff --git a/public/svgs/interviewpal.svg b/public/svgs/interviewpal.svg
new file mode 100644
index 000000000..f0dc3731a
--- /dev/null
+++ b/public/svgs/interviewpal.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
From 2083ec1c0d5712b984b7531255689a9685d83a12 Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Fri, 25 Apr 2025 10:25:54 +0200
Subject: [PATCH 002/144] chore(versions): update coolify version to
4.0.0-beta.413 and nightly version to 4.0.0-beta.414 in configuration files
---
config/constants.php | 2 +-
other/nightly/versions.json | 4 ++--
versions.json | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/config/constants.php b/config/constants.php
index f05bc7d8e..2790258fa 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -2,7 +2,7 @@
return [
'coolify' => [
- 'version' => '4.0.0-beta.412',
+ 'version' => '4.0.0-beta.413',
'helper_version' => '1.0.8',
'realtime_version' => '1.0.7',
'self_hosted' => env('SELF_HOSTED', true),
diff --git a/other/nightly/versions.json b/other/nightly/versions.json
index c3f4ba912..31e0e279d 100644
--- a/other/nightly/versions.json
+++ b/other/nightly/versions.json
@@ -1,10 +1,10 @@
{
"coolify": {
"v4": {
- "version": "4.0.0-beta.412"
+ "version": "4.0.0-beta.413"
},
"nightly": {
- "version": "4.0.0-beta.413"
+ "version": "4.0.0-beta.414"
},
"helper": {
"version": "1.0.8"
diff --git a/versions.json b/versions.json
index c3f4ba912..31e0e279d 100644
--- a/versions.json
+++ b/versions.json
@@ -1,10 +1,10 @@
{
"coolify": {
"v4": {
- "version": "4.0.0-beta.412"
+ "version": "4.0.0-beta.413"
},
"nightly": {
- "version": "4.0.0-beta.413"
+ "version": "4.0.0-beta.414"
},
"helper": {
"version": "1.0.8"
From f5cc2728618b4011bdd01d991f8eeec86d4518ab Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Fri, 25 Apr 2025 15:35:23 +0200
Subject: [PATCH 003/144] fix(terminal): enhance WebSocket client verification
with authorized IPs in terminal server
---
config/constants.php | 2 +-
docker/coolify-realtime/terminal-server.js | 72 ++++++++++++++++++----
routes/web.php | 11 ++++
3 files changed, 72 insertions(+), 13 deletions(-)
diff --git a/config/constants.php b/config/constants.php
index 2790258fa..a849ae93e 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -4,7 +4,7 @@ return [
'coolify' => [
'version' => '4.0.0-beta.413',
'helper_version' => '1.0.8',
- 'realtime_version' => '1.0.7',
+ 'realtime_version' => '1.0.8',
'self_hosted' => env('SELF_HOSTED', true),
'autoupdate' => env('AUTOUPDATE'),
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
diff --git a/docker/coolify-realtime/terminal-server.js b/docker/coolify-realtime/terminal-server.js
index 6649f866c..61dd29453 100755
--- a/docker/coolify-realtime/terminal-server.js
+++ b/docker/coolify-realtime/terminal-server.js
@@ -3,7 +3,9 @@ import http from 'http';
import pty from 'node-pty';
import axios from 'axios';
import cookie from 'cookie';
-import 'dotenv/config'
+import 'dotenv/config';
+
+const userSessions = new Map();
const server = http.createServer((req, res) => {
if (req.url === '/ready') {
@@ -15,16 +17,20 @@ const server = http.createServer((req, res) => {
}
});
-const verifyClient = async (info, callback) => {
- const cookies = cookie.parse(info.req.headers.cookie || '');
- // const origin = new URL(info.origin);
- // const protocol = origin.protocol;
+const getSessionCookie = (req) => {
+ const cookies = cookie.parse(req.headers.cookie || '');
const xsrfToken = cookies['XSRF-TOKEN'];
-
- // Generate session cookie name based on APP_NAME
const appName = process.env.APP_NAME || 'laravel';
const sessionCookieName = `${appName.replace(/[^a-zA-Z0-9]/g, '_').toLowerCase()}_session`;
- const laravelSession = cookies[sessionCookieName];
+ return {
+ sessionCookieName,
+ xsrfToken: xsrfToken,
+ laravelSession: cookies[sessionCookieName]
+ }
+}
+
+const verifyClient = async (info, callback) => {
+ const { xsrfToken, laravelSession, sessionCookieName } = getSessionCookie(info.req);
// Verify presence of required tokens
if (!laravelSession || !xsrfToken) {
@@ -54,11 +60,24 @@ const verifyClient = async (info, callback) => {
const wss = new WebSocketServer({ server, path: '/terminal/ws', verifyClient: verifyClient });
-const userSessions = new Map();
-wss.on('connection', (ws) => {
+wss.on('connection', async (ws, req) => {
const userId = generateUserId();
- const userSession = { ws, userId, ptyProcess: null, isActive: false };
+ const userSession = { ws, userId, ptyProcess: null, isActive: false, authorizedIPs: [] };
+ const { xsrfToken, laravelSession, sessionCookieName } = getSessionCookie(req);
+
+ // Verify presence of required tokens
+ if (!laravelSession || !xsrfToken) {
+ ws.close(401, 'Unauthorized: Missing required tokens');
+ return;
+ }
+ const response = await axios.post(`http://coolify:8080/terminal/auth/ips`, null, {
+ headers: {
+ 'Cookie': `${sessionCookieName}=${laravelSession}`,
+ 'X-XSRF-TOKEN': xsrfToken
+ },
+ });
+ userSession.authorizedIPs = response.data.ipAddresses || [];
userSessions.set(userId, userSession);
ws.on('message', (message) => {
@@ -125,6 +144,20 @@ async function handleCommand(ws, command, userId) {
const timeout = extractTimeout(commandString);
const sshArgs = extractSshArgs(commandString);
const hereDocContent = extractHereDocContent(commandString);
+
+ // Extract target host from SSH command
+ const targetHost = extractTargetHost(sshArgs);
+ if (!targetHost) {
+ ws.send('Invalid SSH command: No target host found');
+ return;
+ }
+
+ // Validate target host against authorized IPs
+ if (!userSession.authorizedIPs.includes(targetHost)) {
+ ws.send(`Unauthorized: Target host ${targetHost} not in authorized list`);
+ return;
+ }
+
const options = {
name: 'xterm-color',
cols: 80,
@@ -152,7 +185,6 @@ async function handleCommand(ws, command, userId) {
console.error(`Process exited with code ${exitCode} and signal ${signal}`);
ws.send('pty-exited');
userSession.isActive = false;
-
});
if (timeout) {
@@ -162,6 +194,22 @@ async function handleCommand(ws, command, userId) {
}
}
+function extractTargetHost(sshArgs) {
+ // Find the argument that matches the pattern user@host
+ const userAtHost = sshArgs.find(arg => {
+ // Skip paths that contain 'storage/app/ssh/keys/'
+ if (arg.includes('storage/app/ssh/keys/')) {
+ return false;
+ }
+ return /^[^@]+@[^@]+$/.test(arg);
+ });
+ if (!userAtHost) return null;
+
+ // Extract host from user@host
+ const host = userAtHost.split('@')[1];
+ return host;
+}
+
async function handleError(err, userId) {
console.error('WebSocket error:', err);
await killPtyProcess(userId);
diff --git a/routes/web.php b/routes/web.php
index 3edfec910..3ddd77361 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -149,6 +149,17 @@ Route::middleware(['auth', 'verified'])->group(function () {
return response()->json(['authenticated' => false], 401);
})->name('terminal.auth');
+ Route::post('/terminal/auth/ips', function () {
+ if (auth()->check()) {
+ $team = auth()->user()->currentTeam();
+ $ipAddresses = $team->servers()->pluck('ip')->toArray();
+
+ return response()->json(['ipAddresses' => $ipAddresses], 200);
+ }
+
+ return response()->json(['ipAddresses' => []], 401);
+ })->name('terminal.auth.ips');
+
Route::prefix('invitations')->group(function () {
Route::get('/{uuid}', [Controller::class, 'acceptInvitation'])->name('team.invitation.accept');
Route::get('/{uuid}/revoke', [Controller::class, 'revoke_invitation'])->name('team.invitation.revoke');
From 41df085746f79564ac96b6ce4c569c80f33b0bcd Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Fri, 25 Apr 2025 15:35:42 +0200
Subject: [PATCH 004/144] chore(versions): update realtime version to 1.0.8 in
versions.json
---
other/nightly/versions.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/other/nightly/versions.json b/other/nightly/versions.json
index 31e0e279d..6dc9e7a02 100644
--- a/other/nightly/versions.json
+++ b/other/nightly/versions.json
@@ -10,7 +10,7 @@
"version": "1.0.8"
},
"realtime": {
- "version": "1.0.7"
+ "version": "1.0.8"
},
"sentinel": {
"version": "0.0.15"
From 0b26ea423cb71bfff904dcc192a5bed812eb755c Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Mon, 28 Apr 2025 10:44:17 +0200
Subject: [PATCH 005/144] chore(versions): update realtime version to 1.0.8 in
versions.json
---
versions.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/versions.json b/versions.json
index 31e0e279d..6dc9e7a02 100644
--- a/versions.json
+++ b/versions.json
@@ -10,7 +10,7 @@
"version": "1.0.8"
},
"realtime": {
- "version": "1.0.7"
+ "version": "1.0.8"
},
"sentinel": {
"version": "0.0.15"
From f4472909ede6589f869a49fbb865d76dc330f5ee Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Mon, 28 Apr 2025 10:55:31 +0200
Subject: [PATCH 006/144] chore(docker): update soketi image version to 1.0.8
in production configuration files
---
docker-compose.prod.yml | 2 +-
other/nightly/docker-compose.prod.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index 35fea6403..965fca276 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -61,7 +61,7 @@ services:
retries: 10
timeout: 2s
soketi:
- image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.6'
+ image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.8'
ports:
- "${SOKETI_PORT:-6001}:6001"
- "6002:6002"
diff --git a/other/nightly/docker-compose.prod.yml b/other/nightly/docker-compose.prod.yml
index 35fea6403..fa30677ad 100644
--- a/other/nightly/docker-compose.prod.yml
+++ b/other/nightly/docker-compose.prod.yml
@@ -61,7 +61,7 @@ services:
retries: 10
timeout: 2s
soketi:
- image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.6'
+ image: '${REGISTRY_URL:-ghcr.io}/coollabsio/coolify-realtime:1.0.8'
ports:
- "${SOKETI_PORT:-6001}:6001"
- "6002:6002"
From 8efcaf642af27edf22aad0524df385a7665d2118 Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Mon, 28 Apr 2025 10:55:34 +0200
Subject: [PATCH 007/144] chore(versions): update coolify version to
4.0.0-beta.414 and nightly version to 4.0.0-beta.415 in configuration files
---
config/constants.php | 2 +-
other/nightly/versions.json | 4 ++--
versions.json | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/config/constants.php b/config/constants.php
index a849ae93e..018971370 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -2,7 +2,7 @@
return [
'coolify' => [
- 'version' => '4.0.0-beta.413',
+ 'version' => '4.0.0-beta.414',
'helper_version' => '1.0.8',
'realtime_version' => '1.0.8',
'self_hosted' => env('SELF_HOSTED', true),
diff --git a/other/nightly/versions.json b/other/nightly/versions.json
index 6dc9e7a02..aabcec3d8 100644
--- a/other/nightly/versions.json
+++ b/other/nightly/versions.json
@@ -1,10 +1,10 @@
{
"coolify": {
"v4": {
- "version": "4.0.0-beta.413"
+ "version": "4.0.0-beta.414"
},
"nightly": {
- "version": "4.0.0-beta.414"
+ "version": "4.0.0-beta.415"
},
"helper": {
"version": "1.0.8"
diff --git a/versions.json b/versions.json
index 6dc9e7a02..aabcec3d8 100644
--- a/versions.json
+++ b/versions.json
@@ -1,10 +1,10 @@
{
"coolify": {
"v4": {
- "version": "4.0.0-beta.413"
+ "version": "4.0.0-beta.414"
},
"nightly": {
- "version": "4.0.0-beta.414"
+ "version": "4.0.0-beta.415"
},
"helper": {
"version": "1.0.8"
From 75200717ddedced73320874dea25db0f32384e69 Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Mon, 28 Apr 2025 20:43:00 +0200
Subject: [PATCH 008/144] fix(ApplicationDeploymentJob): ensure source is an
object before checking GitHub app properties
---
app/Jobs/ApplicationDeploymentJob.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php
index c29093ce0..7c34271a7 100644
--- a/app/Jobs/ApplicationDeploymentJob.php
+++ b/app/Jobs/ApplicationDeploymentJob.php
@@ -1377,7 +1377,7 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
private function check_git_if_build_needed()
{
- if ($this->source->getMorphClass() === \App\Models\GithubApp::class && $this->source->is_public === false) {
+ if (is_object($this->source) && $this->source->getMorphClass() === \App\Models\GithubApp::class && $this->source->is_public === false) {
$repository = githubApi($this->source, "repos/{$this->customRepository}");
$data = data_get($repository, 'data');
if (isset($data->id)) {
From d47946a0ad00cc6344256fb053307c9209a6702a Mon Sep 17 00:00:00 2001
From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com>
Date: Tue, 29 Apr 2025 09:04:24 +0200
Subject: [PATCH 009/144] fix(ui): Disable livewire navigate feature (causing
spam of setInterval())
---
app/Livewire/Dashboard.php | 2 +-
app/Livewire/Project/Application/Heading.php | 4 +-
app/Livewire/Project/Index.php | 2 +-
config/constants.php | 2 +-
other/nightly/versions.json | 4 +-
resources/views/components/navbar.blade.php | 32 +++----
.../components/notification/navbar.blade.php | 7 +-
.../resources/breadcrumbs.blade.php | 2 -
.../components/security/navbar.blade.php | 4 +-
.../views/components/server/navbar.blade.php | 6 +-
.../components/server/sidebar-proxy.blade.php | 6 +-
.../views/components/server/sidebar.blade.php | 16 ++--
.../components/settings/navbar.blade.php | 6 +-
.../views/components/team/navbar.blade.php | 7 +-
resources/views/livewire/dashboard.blade.php | 26 +++--
.../livewire/destination/index.blade.php | 4 +-
.../application/configuration.blade.php | 57 +++++------
.../application/deployment/index.blade.php | 95 +++++++++++--------
.../project/application/heading.blade.php | 8 +-
.../project/database/configuration.blade.php | 32 +++----
.../project/database/heading.blade.php | 7 +-
.../database/scheduled-backups.blade.php | 3 +-
.../project/environment-edit.blade.php | 4 +-
.../views/livewire/project/index.blade.php | 9 +-
.../livewire/project/resource/index.blade.php | 43 +++------
.../project/service/configuration.blade.php | 42 ++++----
.../livewire/project/service/index.blade.php | 7 +-
.../livewire/project/service/navbar.blade.php | 6 +-
.../livewire/project/shared/metrics.blade.php | 2 +-
.../shared/scheduled-task/all.blade.php | 4 +-
.../views/livewire/project/show.blade.php | 2 -
.../security/private-key/index.blade.php | 23 ++---
.../views/livewire/server/index.blade.php | 2 +-
.../environment/index.blade.php | 6 +-
.../livewire/shared-variables/index.blade.php | 6 +-
.../shared-variables/project/index.blade.php | 1 -
.../livewire/source/github/change.blade.php | 2 +-
.../views/livewire/storage/index.blade.php | 2 +-
.../views/livewire/tags/deployments.blade.php | 2 +-
resources/views/livewire/tags/show.blade.php | 8 +-
resources/views/source/all.blade.php | 4 +-
versions.json | 4 +-
42 files changed, 235 insertions(+), 276 deletions(-)
diff --git a/app/Livewire/Dashboard.php b/app/Livewire/Dashboard.php
index d89f2b970..edbdd25fe 100644
--- a/app/Livewire/Dashboard.php
+++ b/app/Livewire/Dashboard.php
@@ -51,7 +51,7 @@ class Dashboard extends Component
public function navigateToProject($projectUuid)
{
- return $this->redirect(collect($this->projects)->firstWhere('uuid', $projectUuid)->navigateTo(), true);
+ return $this->redirect(collect($this->projects)->firstWhere('uuid', $projectUuid)->navigateTo(), navigate: false);
}
public function render()
diff --git a/app/Livewire/Project/Application/Heading.php b/app/Livewire/Project/Application/Heading.php
index 475d2dfa8..5b0ae12ef 100644
--- a/app/Livewire/Project/Application/Heading.php
+++ b/app/Livewire/Project/Application/Heading.php
@@ -100,7 +100,7 @@ class Heading extends Component
'application_uuid' => $this->parameters['application_uuid'],
'deployment_uuid' => $this->deploymentUuid,
'environment_uuid' => $this->parameters['environment_uuid'],
- ], navigate: true);
+ ], navigate: false);
}
protected function setDeploymentUuid()
@@ -147,7 +147,7 @@ class Heading extends Component
'application_uuid' => $this->parameters['application_uuid'],
'deployment_uuid' => $this->deploymentUuid,
'environment_uuid' => $this->parameters['environment_uuid'],
- ], navigate: true);
+ ], navigate: false);
}
public function render()
diff --git a/app/Livewire/Project/Index.php b/app/Livewire/Project/Index.php
index 8bf511a66..5347d74f0 100644
--- a/app/Livewire/Project/Index.php
+++ b/app/Livewire/Project/Index.php
@@ -35,6 +35,6 @@ class Index extends Component
{
$project = collect($this->projects)->firstWhere('uuid', $projectUuid);
- return $this->redirect($project->navigateTo(), true);
+ return $this->redirect($project->navigateTo(), navigate: false);
}
}
diff --git a/config/constants.php b/config/constants.php
index 018971370..1479ae201 100644
--- a/config/constants.php
+++ b/config/constants.php
@@ -2,7 +2,7 @@
return [
'coolify' => [
- 'version' => '4.0.0-beta.414',
+ 'version' => '4.0.0-beta.415',
'helper_version' => '1.0.8',
'realtime_version' => '1.0.8',
'self_hosted' => env('SELF_HOSTED', true),
diff --git a/other/nightly/versions.json b/other/nightly/versions.json
index aabcec3d8..fc4d28de4 100644
--- a/other/nightly/versions.json
+++ b/other/nightly/versions.json
@@ -1,10 +1,10 @@
{
"coolify": {
"v4": {
- "version": "4.0.0-beta.414"
+ "version": "4.0.0-beta.415"
},
"nightly": {
- "version": "4.0.0-beta.415"
+ "version": "4.0.0-beta.416"
},
"helper": {
"version": "1.0.8"
diff --git a/resources/views/components/navbar.blade.php b/resources/views/components/navbar.blade.php
index 4148a61d3..9a75200b1 100644
--- a/resources/views/components/navbar.blade.php
+++ b/resources/views/components/navbar.blade.php
@@ -123,7 +123,7 @@