Skip to content

Repository files navigation

Proxmox VPS Control Panel

Node.js Express License: MIT PRs Welcome

A production-grade infrastructure automation system for secure provisioning and management of virtual private servers on Proxmox VE.

Overview

The Proxmox VPS Control Panel is a Node.js/Express.js application that runs directly on your Proxmox host with root privileges. It provides a secure REST API and web interface for creating, managing, and deleting VPS instances with automatic SSH port forwarding and IP detection.

Key Features

  • Web Interface: Modern, responsive web panel for easy VPS management
  • Automated VPS Provisioning: Clone template VMs with custom CPU, RAM, and disk configurations
  • Automatic SSH Access: Assigns unique SSH ports (2200-2299) with iptables NAT forwarding
  • IP Detection: Polls for DHCP-assigned IP addresses via Cloud-Init
  • Rollback on Failure: Automatic cleanup of partial infrastructure on any error
  • JWT Authentication: Secure token-based authentication with bcrypt password hashing
  • Rate Limiting: Protection against brute-force and abuse
  • State Reconciliation: Startup reconciliation to detect orphaned VMs and invalid records

Architecture

Routes → Middleware → Services → System Layer (qm, iptables)
  • Routes: HTTP request handling and response formatting
  • Middleware: Authentication, validation, rate limiting
  • Services: Business logic, orchestration, rollback handling
  • System Layer: Safe execution of Proxmox CLI commands

Prerequisites

  • Proxmox VE host (Debian-based)
  • Node.js LTS (v20+)
  • Root access on Proxmox host
  • Template VM configured with Cloud-Init
  • Nginx Proxy Manager (recommended for HTTPS access)

Installation

1. Install Node.js

# Install Node.js LTS
curl -fsSL https://deb.nodesource.com/setup_lts.x | bash -
apt-get install -y nodejs

# Verify installation
node --version
npm --version

2. Clone and Setup Application

# Create application directory
mkdir -p /opt/vps-panel
cd /opt/vps-panel

# Copy application files to /opt/vps-panel
# (Upload your project files here)

# Install dependencies
npm install

3. Configure Environment Variables

# Copy example environment file
cp .env.example .env

# Generate JWT secret
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Generate admin password hash (replace 'your-secure-password' with your actual password)
node -e "const bcrypt = require('bcrypt'); bcrypt.hash('your-secure-password', 12).then(console.log)"

# Edit .env file with your values
nano .env

Required Configuration:

# Server
PORT=3000
BIND_ADDRESS=127.0.0.1

# Authentication (REPLACE THESE!)
JWT_SECRET=<generated-secret-from-above>
ADMIN_USERNAME=admin
ADMIN_PASSWORD_HASH=<generated-hash-from-above>

# Proxmox
TEMPLATE_VMID=100  # Your template VM ID
VMID_MIN=200
VMID_MAX=999
PROTECTED_VMIDS=100,101,102  # Include template and critical VMs

# SSH Ports
SSH_PORT_MIN=2200
SSH_PORT_MAX=2299

# Timeouts
IP_POLL_TIMEOUT=60000  # 60 seconds

4. Setup Systemd Service

# Copy service file
cp vps-panel.service /etc/systemd/system/

# Reload systemd
systemctl daemon-reload

# Enable service to start on boot
systemctl enable vps-panel

# Start service
systemctl start vps-panel

# Check status
systemctl status vps-panel

# View logs
journalctl -u vps-panel -f

5. Configure Nginx Reverse Proxy

Install Nginx Proxy Manager or configure Nginx manually:

server {
    listen 443 ssl http2;
    server_name panel.example.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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;
    }
}

6. Access Web Panel

Once configured, access the web panel at:

  • Local: http://127.0.0.1:3000
  • Production: https://panel.example.com

Login with your configured admin credentials and start managing VPS instances through the intuitive web interface!


Web Interface

The web panel provides:

  • Dashboard: Real-time statistics (Total VPS, Active VPS, CPU/RAM usage)
  • VPS Creation: Easy form-based VPS provisioning
  • VPS Management: View all VPS instances with detailed information
  • SSH Commands: Copy-ready SSH connection commands for each VPS
  • One-Click Actions: Delete VPS instances with confirmation
  • Auto-Refresh: Dashboard updates every 30 seconds
  • Responsive Design: Works on desktop, tablet, and mobile devices

API Usage

Authentication

# Login
curl -X POST https://panel.example.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"admin","password":"your-password"}'

# Response
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "expiresIn": 3600
  }
}

Create VPS

curl -X POST https://panel.example.com/api/vps/create \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "name": "client-vps-1",
    "cpu": 2,
    "ram": 2048,
    "disk": 30
  }'

# Response
{
  "success": true,
  "data": {
    "vmid": 201,
    "ssh_command": "ssh root@your-host -p 2200",
    "private_ip": "10.0.0.54",
    "ssh_port": 2200
  }
}

List VPS

curl -X GET https://panel.example.com/api/vps/list \
  -H "Authorization: Bearer YOUR_TOKEN"

# Response
{
  "success": true,
  "data": [
    {
      "vmid": 201,
      "name": "client-vps-1",
      "private_ip": "10.0.0.54",
      "ssh_port": 2200,
      "cpu": 2,
      "ram": 2048,
      "disk": 30,
      "created_at": "2026-02-13T10:30:00.000Z",
      "status": "active"
    }
  ]
}

Delete VPS

curl -X DELETE https://panel.example.com/api/vps/201 \
  -H "Authorization: Bearer YOUR_TOKEN"

# Response
{
  "success": true,
  "data": {
    "message": "VPS deleted successfully"
  }
}

Health Check

curl -X GET https://panel.example.com/api/health

# Response
{
  "success": true,
  "data": {
    "status": "healthy",
    "uptime": 3600,
    "proxmox": "connected",
    "persistence": "ok"
  }
}

Backup and Restore

What to Backup

  1. VPS Metadata: /opt/vps-panel/data/vps.json
  2. Configuration: /opt/vps-panel/.env
  3. iptables Rules: /etc/iptables/rules.v4

Backup Script

#!/bin/bash
# backup-vps-panel.sh

BACKUP_DIR="/backup/vps-panel"
DATE=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR

# Backup VPS data
cp /opt/vps-panel/data/vps.json $BACKUP_DIR/vps_$DATE.json

# Backup environment config
cp /opt/vps-panel/.env $BACKUP_DIR/env_$DATE

# Backup iptables rules
iptables-save > $BACKUP_DIR/iptables_$DATE.rules

# Keep only last 7 days
find $BACKUP_DIR -type f -mtime +7 -delete

echo "Backup completed: $BACKUP_DIR"

Automated Daily Backup

# Add to crontab
crontab -e

# Run daily at 2 AM
0 2 * * * /opt/vps-panel/backup-vps-panel.sh

Restore Procedure

# Stop service
systemctl stop vps-panel

# Restore VPS data
cp /backup/vps-panel/vps_YYYYMMDD_HHMMSS.json /opt/vps-panel/data/vps.json

# Restore environment config
cp /backup/vps-panel/env_YYYYMMDD_HHMMSS /opt/vps-panel/.env

# Restore iptables rules
iptables-restore < /backup/vps-panel/iptables_YYYYMMDD_HHMMSS.rules
netfilter-persistent save

# Start service
systemctl start vps-panel

# Verify reconciliation
journalctl -u vps-panel -n 50

Troubleshooting

Service Won't Start

# Check service status
systemctl status vps-panel

# View detailed logs
journalctl -u vps-panel -n 100 --no-pager

# Check environment file
cat /opt/vps-panel/.env

# Test Node.js manually
cd /opt/vps-panel
node server.js

VPS Creation Fails

# Check Proxmox connectivity
qm list

# Check template VM exists
qm status 100

# Check available VMIDs
qm list | grep -E "20[0-9]|2[1-9][0-9]|[3-9][0-9]{2}"

# Check SSH port availability
iptables -t nat -L VPS_PANEL_NAT -n --line-numbers

# View application logs
journalctl -u vps-panel -f

IP Detection Timeout

# Verify guest agent is installed in template
qm agent 100 ping

# Check Cloud-Init configuration
qm cloudinit dump 100 user

# Increase timeout in .env
IP_POLL_TIMEOUT=90000  # 90 seconds

SSH Port Forwarding Not Working

# Check iptables rules
iptables -t nat -L VPS_PANEL_NAT -n -v

# Verify chain exists
iptables -t nat -L PREROUTING -n | grep VPS_PANEL_NAT

# Test port forwarding
ssh root@proxmox-host -p 2200

# Check VM IP is correct
qm guest cmd 201 network-get-interfaces

Orphaned VMs Detected

# View reconciliation logs
journalctl -u vps-panel | grep reconciliation

# Manually clean orphaned VM
qm stop 205
qm destroy 205

# Remove orphaned iptables rule
iptables -t nat -D VPS_PANEL_NAT -p tcp --dport 2205 -j DNAT --to-destination 10.0.0.55:22
netfilter-persistent save

Security Considerations

Critical Security Rules

  1. Never expose panel directly: Always use Nginx reverse proxy with HTTPS
  2. Strong passwords: Use 16+ character passwords for admin account
  3. Rotate JWT secret: Change JWT_SECRET periodically
  4. Monitor logs: Watch for failed authentication attempts
  5. Firewall rules: Restrict access to panel port (3000) to localhost only
  6. Regular updates: Keep Node.js and dependencies updated

Rate Limiting

  • Login attempts: 5 per minute per IP
  • VPS creation: 5 per hour per admin

Protected VMIDs

Always include critical VMs in PROTECTED_VMIDS:

  • Template VMs
  • Production infrastructure VMs
  • Database VMs

Limitations

Single-Process Architecture

IMPORTANT: This application uses in-memory locking for resource allocation. Do NOT run multiple instances or use PM2 cluster mode. Only one process should run at a time.

Supported Configurations

  • Single Proxmox host (no cluster support in v1)
  • Single admin user (multi-tenant support planned)
  • JSON file storage (database migration planned)

Monitoring

Health Check Endpoint

# Monitor application health
curl http://127.0.0.1:3000/api/health

Log Monitoring

# Real-time logs
journalctl -u vps-panel -f

# Error logs only
journalctl -u vps-panel -p err -f

# Last 100 lines
journalctl -u vps-panel -n 100

Resource Usage

# Check process status
systemctl status vps-panel

# Memory usage
ps aux | grep "node server.js"

# Disk usage
du -sh /opt/vps-panel/data/

Maintenance

Update Application

# Stop service
systemctl stop vps-panel

# Backup current version
cp -r /opt/vps-panel /opt/vps-panel.backup

# Update files
cd /opt/vps-panel
git pull  # or copy new files

# Install dependencies
npm install

# Start service
systemctl start vps-panel

# Verify
systemctl status vps-panel

Log Rotation

Logs are managed by systemd journald. Configure retention:

# Edit journald config
nano /etc/systemd/journald.conf

# Set limits
SystemMaxUse=500M
MaxRetentionSec=7day

# Restart journald
systemctl restart systemd-journald

Support and Contributing

For issues, feature requests, or contributions, please visit the project repository.

License

MIT - see LICENSE for details.


Production Infrastructure Software - Handle with care. Every operation affects real compute resources.

About

Self-hosted Proxmox VE control panel: provision, manage, and monitor VPS instances via web UI with JWT auth, rate limiting, and automated SSH port forwarding.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages