Fully functioning terminal on Coolify

A few months ago, Andras, the maintainer of Coolify, requested a feature as a bounty that would allow users to connect to their terminal directly from the web browser. How cool would that be? And since Coolify is Docker-based, we needed to connect to multiple containers and servers too!

I thought it would be a great feature and an excellent opportunity to learn about WebSockets. So, I decided to give it a try. Little did I know what I was getting myself into...

The PHP Struggle is Real

Many comments on the issue led me in the right direction. Using PTY (Pseudoterminal) and WebSockets

After some research, I realized that this feature was not that simple. It would require node-pty library because, well... who's going to reinvent the wheel?

I wondered about using only PHP for this, but we needed a robust event loop and the ability to handle asynchronous I/O operations for long-running processes like a terminal. PHP isn't built for long-running processes like Node.js is. It's designed to handle requests and then bow out, not hang around for an ongoing chat with a terminal.

And on top of that, how to write the translation layer between the browser and the terminal? So... node-pty it is!

Portainer uses it, and all Google searches about creating a terminal in web browsers pointed to this library. Its a Microsoft product, and VSCode uses it too!

Node.js to the Rescue

After banging my head against the PHP wall for a while, trying to re-use Laravel Pusher/Echo, I hit a dead-end. There's no SDK for it, and I tried to monkey-patch it, but it wasn't working. I decided to pivot to a simple Node.js server. And let me tell you, it was like a breath of fresh air! Node's event-driven, non-blocking I/O model is perfect for this kind of real-time, long-running process.

After setting up the magic of Xterm.js for the frontend and node-pty for creating pseudo-terminals. Suddenly, things started falling into place!

(On a side note: I even stumbled upon this WebSocket library for PHP which looks promising)

PoC, PoC, PoC, Who's There?

So, I started to build a PoC (Proof of Concept), using XTerm.js and Node.js magic. I encountered some challenges with authentication on the Laravel side and the extra container for Node.js, which turned out to be unnecessary. Thus, the Frankenstein monster was born:

  1. A Node.js server integrated into Coolify's existing "coolify-realtime" container.
  2. XTerm.js powering a slick web-based terminal interface.
  3. WebSocket connections for real-time communication.
  4. PTY magic to create a genuine terminal experience.
  5. Robust authentication to keep things secure.

The Cool Factor

I can't overstate how awesome it is to have a fully functioning terminal right in your browser. Need to quickly check a log file? Bam! Want to restart a service? Boom! All without leaving your Coolify dashboard. It's like having your entire server infrastructure at your fingertips.

Waiting to merge

I've created a Pull Request for this feature and am anxiously waiting to be merged. Fingers crossed that it will soon be available to all Coolify users!