The need for remote access and management of servers and applications is ever-growing in today's world. Occasionally, a customized requirement emerges wherein we find the necessity for a terminal that facilitates remote access from within our own web-based applications. Let's understand a bit more about web-based terminals.
Why do we need a terminal in the browser?
Instead of distributing server access via keys, there is an option to provide individuals entry to a web-based terminal located behind a secure login interface. This login interface remains under admin control. For example - Digital Ocean provides browser-based terminal access to droplets and Play with Dockers provides terminal access to containers right within the browser. When involved in developer tools, there's a high likelihood of eventually finding the need to create an embedded terminal.
How to build a terminal
One powerful way to achieve this is by creating a browser-based terminal using xterm.js, Web Socket & Node.js. This blog post will guide you through the steps to build your own browser-based terminal, enabling you to interact with remote systems and applications directly from your web browser.
How does this work?
First, a server and client need to be created. Use Socket.IO to send and receive data.
The frontend implementation involves recreating a terminal emulator using the classic HTML, CSS, and JavaScript trio. When a user inputs a command in the emulator, it is transmitted to a NodeJS backend through a WebSocket, diverging from the standard HTTP protocol. This is because of the terminal's behavior. Upon receiving a command from the emulator, the backend executes it within an actual terminal. On inputting the command 'ls', a list of files and folders of that particular directory is returned to the emulator. It is a perfect one-way communication. Yet, specific commands like "netstat" trigger dynamic screen updates in the terminal, making back-and-forth HTTP communication cumbersome. With a WebSocket, the real terminal can send output whenever available, and the frontend emulator can do the same. This facilitates the emulation of features like progress bars without complications.
What is Xterm.Js?
- Xterm.js is a TypeScript-based frontend element enabling applications to provide comprehensive terminal experiences to their users through web browsers. It finds use in VS Code, Hyper, and Theia.
- Xterm.js does not function as a standalone terminal application available for direct download and local use.
- Xterm.js is not like "bash." Instead, it can establish connections to processes such as "bash," enabling interactive interactions where users can supply input and receive corresponding output.
Client-side setup:
Setting up the client side is straightforward. Generate a terminal using xterm and link it to a designated container within the Document Object Model (DOM). Next, transmit input from the terminal to the associated server of socket.io. Additionally, include an event listener for the socket.io-client, responsible for displaying responses received from the socket.io server on the xterm.js terminal.
On a html page, create a div where xtermjs will attach a terminal.
Before starting socket.io client, create a wrapper class containing xtermjs-related functions and the required event listeners for socket.io-client.
Users can customize it further by updating TerminalUI.js file and customize the this.terminal object.
Finally, initialize the socket.io client to send/receive events from the node-pty process from the server.
Backend Implementation:
The backend implementation functions as a bridge, facilitating communication between the emulator and the real terminal by forwarding both inputs and outputs seamlessly between the two.
First, set up the basics. Create a server from NodeJS HTTP module and pass it to socket.io server.
Index.js
SocketService.js
Next, create a wrapper class to add event listeners for socket.io events. For this, create a SocketService Js file.