Skip to content

Latest commit

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

>_ Web Terminal

A browser-based SSH terminal built with NuxtJS — access your Linux server from any browser, anywhere, without installing anything.

image

✨ Features

  • Multiple tabs — open several terminal sessions simultaneously, just like Windows Terminal
  • Full terminal emulation — colors, cursor movement, scrollback, ANSI support via xterm.js
  • Real-time connection — WebSocket-based communication with zero latency
  • Status bar — live connection status, server IP, port, uptime timer, and latency
  • PWA support — installable as a desktop/mobile app
  • Keyboard shortcutsCtrl+T new tab, Ctrl+W close tab

🛠 Tech Stack

LayerTechnology
FrontendNuxtJS 3, Vue 3, xterm.js, xterm-addon-fit
BackendNitro (Nuxt server), Socket.io, ssh2
Process managerpm2
HTTPSCloudflare Tunnel
ServerHetzner VPS — Ubuntu 26.04 LTS

🏗 Architecture

Browser (xterm.js)
│
│ WebSocket (Socket.io)
│
Nuxt Backend (Node.js / Nitro)
│
│ SSH (ssh2 library)
│
Linux Server (bash shell)

The browser renders the terminal UI and sends keystrokes via WebSocket. The Nuxt server bridges the connection to the actual SSH session. All SSH credentials stay on the server — never exposed to the browser.

🚀 Getting Started

Prerequisites

  • Node.js 20+
  • A Linux server with SSH access
  • SSH key pair

1. Clone the repository

git clone https://github.com/yourusername/webterminal.git
cd webterminal

2. Install dependencies

npm install

3. Generate an SSH key (if you don't have one)

# On Linux/Mac
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519
# On Windows PowerShell
ssh-keygen -t ed25519 -f C:\Users\YourName\.ssh\id_ed25519

4. Add your public key to the server

# Linux/Mac
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server-ip
# Windows PowerShelltype C:\Users\YourName\.ssh\id_ed25519.pub | ssh root@your-server-ip "cat >> ~/.ssh/authorized_keys"

5. Configure environment variables

Create a .env file in the project root:

# Your server IP or hostnameSSH_HOST=your-server-ip# SSH port (default: 22)SSH_PORT=22# SSH usernameSSH_USER=root# Path to your private key (for local development)SSH_PRIVATE_KEY_PATH=/path/to/.ssh/id_ed25519# OR paste the raw key content (for cloud deployments like Vercel)# SSH_PRIVATE_KEY=-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----

6. Run locally

npm run dev

Open http://localhost:3000 in your browser.

🌐 Deploying to a Server

Build the app

npm run build

Upload to your server

scp -r .output root@your-server-ip:/root/webterminal/

Set up environment variables on the server

ssh root@your-server-ip
nano /root/webterminal/.env

Paste:

SSH_HOST=127.0.0.1SSH_PORT=22SSH_USER=rootSSH_PRIVATE_KEY_PATH=/root/.ssh/id_ed25519

Start with pm2

export SSH_HOST=127.0.0.1
export SSH_PORT=22
export SSH_USER=root
export SSH_PRIVATE_KEY_PATH=/root/.ssh/id_ed25519
pm2 start /root/webterminal/.output/server/index.mjs --name webterminal
pm2 save
pm2 startup

Open the firewall port

ufw allow 3000

Your app is now live at http://your-server-ip:3000.

🔒 HTTPS with Cloudflare Tunnel (Free)

Get a free HTTPS URL without a domain:

# Install cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 \
-o /usr/local/bin/cloudflared
chmod +x /usr/local/bin/cloudflared
# Start tunnel with pm2
pm2 start /usr/local/bin/cloudflared \
--name cloudflare-tunnel \
-- tunnel --url http://localhost:3000
pm2 save
# Get your HTTPS URL
pm2 logs cloudflare-tunnel --lines 50 --nostream | grep trycloudflare

You'll get a free URL like https://random-words.trycloudflare.com.

⚙️ Environment Variables

VariableRequiredDescription
SSH_HOSTIP or hostname of the SSH target server
SSH_PORTSSH port (usually 22)
SSH_USERSSH username (e.g. root)
SSH_PRIVATE_KEY_PATHOne of thesePath to private key file (local dev)
SSH_PRIVATE_KEYOne of theseRaw private key content (cloud deploy)

🔐 Security

Warning: This app gives full shell access to your server. Take security seriously.

Recommended steps before sharing the URL:

  • Add a login page / password protection
  • Use HTTPS (Cloudflare Tunnel or Caddy)
  • Disable SSH password authentication on your server
  • Create a non-root user for the terminal session
  • Never commit .env or private keys to git
# Disable password SSH login (after confirming key works)# In /etc/ssh/sshd_config:
PasswordAuthentication no
systemctl restart ssh

📁 Project Structure

webterminal/
├── app.vue # Main app — tab bar, layout
├── components/
│ └── TerminalTab.vue # Individual terminal tab + xterm.js
├── server/
│ └── plugins/
│ └── socket.ts # Socket.io server + SSH2 bridge
├── public/
│ └── terminal-icon.svg
├── nuxt.config.ts
├── package.json
└── .env # Never commit this!

📜 pm2 Commands

pm2 list # see all running processes
pm2 logs webterminal # view live logs
pm2 restart webterminal # restart the app
pm2 stop webterminal # stop the app
pm2 monit # live monitoring dashboard

🤝 Contributing

Pull requests are welcome. For major changes, please open an issue first.

📄 License

MIT


Built with ❤️ using NuxtJS, Socket.io, ssh2, and xterm.js

About

A browser-based SSH terminal built with NuxtJS — access your Linux server from any browser, anywhere, without installing anything.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors