A modern, full-featured web-based terminal interface built with Next.js 14, TypeScript, and xterm.js to access your VPS via SSH. Features a built-in connection manager with encrypted credential storage.
- 🚀 Next.js 14 App Router - Modern React architecture with Server Components
- 💪 TypeScript - Full type safety throughout the application
- 🎨 Tailwind CSS - Utility-first styling with custom terminal theme
- 🖥️ xterm.js - Full terminal emulation with 256 color support
- 🔐 Secure Authentication - Session-based web login with iron-session
- 🗄️ SQLite Database - Lightweight, file-based database for connections
- 🔒 Encrypted Storage - Passwords encrypted using AES-256-CBC
- ➕ Connection Management - Add, edit, and delete VPS connections via UI
- 🔄 Multi-Connection Support - Switch between different VPS servers
- 🔑 Advanced SSH Key Management:
- Upload SSH keys directly through the UI
- Generate SSH key pairs in the browser
- Multiple SSH keys per connection with automatic fallback
- Display SSH key fingerprints for verification
- Support for both file paths and uploaded key content
- 📱 Responsive Design - Works seamlessly on desktop and mobile
- 🌐 Clickable URLs - Web links in terminal output are clickable
- ⚡ Performance - Optimized builds with Next.js
- Node.js 18+
- npm, yarn, or pnpm
- Access to one or more VPS via SSH
cd nextjs-web-terminal
npm installCopy the example environment file:
cp .env.example .envEdit .env and configure your settings:
# Session Secret (generate a random 32+ character string)
SESSION_SECRET=your-random-secret-key-min-32-chars
# Encryption Key (generate a different random 32+ character string)
ENCRYPTION_KEY=your-random-encryption-key-min-32-chars
# Web Authentication
WEB_USERNAME=admin
WEB_PASSWORD=change-this-passwordImportant: Generate secure random keys for production:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"npm run devOpen http://localhost:3000 in your browser.
Use the credentials you set in .env:
- Username:
admin(or your custom username) - Password: Your configured password
- Click the "Connections" button in the header
- Click "Add New Connection"
- Fill in your VPS details:
- Connection Name: A friendly name (e.g., "Production Server")
- Host: Your VPS IP or domain
- Port: SSH port (usually 22)
- Username: SSH username
- Password: SSH password (or use SSH key)
- Click "Create Connection"
- Go back to the terminal (click "Back to Terminal")
- Select your connection from the dropdown
- Click "Connect"
- Start using your terminal!
nextjs-web-terminal/
├── src/
│ ├── app/
│ │ ├── page.tsx # Main terminal page
│ │ ├── login/page.tsx # Login page
│ │ ├── connections/page.tsx # Connection management
│ │ ├── layout.tsx # Root layout
│ │ └── api/
│ │ ├── auth/ # Authentication APIs
│ │ └── connections/ # Connection CRUD APIs
│ ├── components/
│ │ ├── Terminal.tsx # xterm.js terminal component
│ │ ├── Header.tsx # Header with navigation
│ │ └── LoginForm.tsx # Login form component
│ ├── lib/
│ │ ├── config.ts # Configuration
│ │ ├── session.ts # Session management
│ │ └── db.ts # Database & encryption
│ └── styles/
│ └── globals.css # Global styles + Tailwind
├── data/
│ └── connections.db # SQLite database (auto-created)
├── server.js # Custom server (Next.js + WS)
├── package.json
├── tsconfig.json
└── next.config.js
- Type: SQLite (file-based, no external dependencies)
- Location:
data/connections.db(auto-created on first run) - Schema: Connections table with encrypted credentials
- Algorithm: AES-256-CBC
- Key Derivation: scrypt with salt
- Encrypted Fields:
- SSH passwords
- SSH key passphrases
- Uploaded SSH key content
- Key Storage: Environment variable (
ENCRYPTION_KEY)
Security Best Practices:
- Never commit
.envfile - Use strong, unique encryption keys
- Backup your database regularly
- Set proper file permissions on
data/directory - Use HTTPS in production
When adding a connection, select "Password" and enter your SSH password. The password will be encrypted before storage.
The terminal supports multiple ways to use SSH keys:
- Select "SSH Key" as authentication method
- Choose "File Path" as key type
- Enter the full path to your private key file (e.g.,
/home/user/.ssh/id_rsa) - If your key has a passphrase, enter it (will be encrypted)
- Ensure the server running the terminal can access the key file
- Select "SSH Key" as authentication method
- Choose "Upload Key" as key type
- Click "Browse" and select your private key file
- If your key has a passphrase, enter it
- The key content is encrypted and stored in the database
- Select "SSH Key" as authentication method
- Click "Generate Key Pair"
- A new 4096-bit RSA key pair will be generated
- Download both the private and public keys
- Add the public key to your server's
~/.ssh/authorized_keys - The private key is automatically added to your connection
You can add multiple SSH keys to a single connection:
- Add your first key (upload, file path, or generate)
- Click "Add Key" to add it to the connection
- Repeat for additional keys
- Set one key as "Primary" (tried first)
- If the primary key fails, the system automatically tries the next key
Benefits:
- Increased reliability - fallback if one key fails
- Multiple authentication methods
- Easy key rotation without downtime
All generated and uploaded keys display their SHA256 fingerprint. This helps you:
- Verify you're using the correct key
- Match keys with server-side authorized_keys
- Track which key is being used for each connection
- Navigate to
/connections - Click "Add New Connection"
- Fill in the form with your VPS details
- Click "Create Connection"
- Find your connection in the list
- Click "Edit"
- Modify the details (leave password blank to keep existing)
- Click "Update Connection"
- Find your connection in the list
- Click "Delete"
- Confirm the deletion
- On the main terminal page, select a connection from the dropdown
- Click "Connect"
- The terminal will establish an SSH connection
- Switch connections anytime by selecting a different one
npm run build
npm start- ✅ Set strong passwords in
.env - ✅ Generate secure
SESSION_SECRET(32+ chars) - ✅ Generate secure
ENCRYPTION_KEY(32+ chars) - ✅ Use HTTPS with SSL certificates
- ✅ Configure firewall rules
- ✅ Prefer SSH key authentication
- ✅ Set
NODE_ENV=production - ✅ Backup
data/connections.dbregularly - ✅ Set proper file permissions
- ✅ Deploy behind reverse proxy (nginx/Apache)
NODE_ENV=production
PORT=3000
SESSION_SECRET=<generated-secure-key>
ENCRYPTION_KEY=<generated-secure-key>
WEB_AUTH_ENABLED=true
WEB_USERNAME=admin
WEB_PASSWORD=<strong-password>server {
listen 80;
server_name terminal.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}npm run devnpm run type-checknpm run lintProblem: "No connection selected"
- Add a connection in
/connectionsfirst - Select a connection from the dropdown
- Click "Connect" button
Problem: "SSH connection failed"
- Verify credentials in connection settings
- Check VPS firewall allows SSH connections
- Test SSH access manually:
ssh username@host - Check server logs for detailed error messages
Problem: "Failed to read private key file"
- Verify the private key path is correct and absolute
- Ensure the server process has read permissions
- Check the key file exists and is a valid SSH key
- Alternative: Use "Upload Key" instead of file path to store key in database
Problem: "No valid SSH keys found"
- Check that you've added at least one SSH key to the connection
- Verify uploaded keys contain valid SSH private key format
- For file-based keys, ensure paths are correct and accessible
- Try regenerating keys using the built-in key generator
Problem: "Error loading connections"
- Check
data/directory exists and is writable - Verify
ENCRYPTION_KEYis set in.env - Check file permissions on
data/connections.db
Problem: "Connection not found after adding"
- Refresh the page
- Check browser console for errors
- Verify database file is writable
Problem: Terminal doesn't render
- Clear
.nextfolder:rm -rf .next - Reinstall dependencies:
rm -rf node_modules && npm install - Check browser console for JavaScript errors
- Framework: Next.js 14 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS
- Terminal: xterm.js + addons (fit, web-links)
- Backend: Node.js + Custom Server
- Database: better-sqlite3 (SQLite)
- Encryption: Node.js crypto module
- WebSocket: ws library
- SSH: ssh2 client
- Session: iron-session
- Use HTTPS in production - Obtain SSL certificates (Let's Encrypt)
- Strong passwords - Use password managers
- Secure encryption keys - Generate with crypto.randomBytes
- SSH keys preferred - More secure than passwords
- Environment variables - Never commit sensitive data
- Rate limiting - Implement to prevent brute force
- IP whitelisting - Restrict access to known IPs
- Regular updates - Keep dependencies updated
- Monitor logs - Watch for suspicious activity
- Separate servers - Don't host terminal on target VPS
- Backup database - Regular backups of
data/connections.db - File permissions - Restrict access to data directory
MIT License
For issues or questions, check the documentation or review the code comments.
Author: MiniMax Agent
Version: 3.0.0
Features: Advanced SSH key management with upload, generation, and multi-key fallback
Built with: Next.js 14 + TypeScript + Tailwind CSS + xterm.js + SQLite
Last Updated: 2025-11-25