Featured image of post AI-Powered VPS Terminal Copilot: Managing Servers with Natural Language

AI-Powered VPS Terminal Copilot: Managing Servers with Natural Language

Explore how to build an AI-powered VPS terminal copilot using LLMs, enabling operations teams to manage servers, troubleshoot issues, and optimize performance through natural language — dramatically lowering the VPS operations barrier

Introduction: When Operations No Longer Require Memorizing Commands

Have you ever faced a brand-new VPS and needed to dig through documentation just to remember the right diagnostic commands? Or found yourself frantically typing long grep pipelines in the middle of the night to troubleshoot a production issue?

The pain points of traditional VPS operations are clear: high command learning curve, frequent context switching, and complex troubleshooting that relies heavily on experience.

AI terminal copilots are changing this paradigm. Imagine saying “help me figure out why the server is slow” and having the system automatically run diagnostic commands, analyze the results, and provide actionable fix recommendations — that’s exactly what we’re building today.


1. System Architecture Design

┌─────────────────────────────────────────────────────────────┐
│                     User Interaction Layer                   │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │  Web Terminal│  │  SSH Client  │  │  API Gateway │      │
│  │  (xterm.js)  │  │  (bash/zsh)  │  │  (REST/WS)   │      │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘      │
└─────────┼─────────────────┼─────────────────┼───────────────┘
          │                 │                 │
          └─────────────────┴────────┬────────┘
                                    │
┌───────────────────────────────────┼───────────────────────────────┐
│                     AI Copilot Engine                            │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐           │
│  │  LLM Inference│←→│ Command      │←→│ Context      │           │
│  │  (local/cloud)│  │ Sandbox      │  │ Management   │           │
│  │              │  │ (Docker)     │  │ (RAG+Memory) │           │
│  └──────────────┘  └──────────────┘  └──────────────┘           │
└──────────────────────────┬───────────────────────────────────────┘
                           │
┌──────────────────────────┼───────────────────────────────────────┐
│                     VPS Execution Layer                          │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐           │
│  │  Command      │  │  Result      │  │  Security    │           │
│  │  Executor     │  │  Parser      │  │  Auditor     │           │
│  │  (subprocess)│  │  (structured)│  │  (RBAC/audit)│           │
│  └──────────────┘  └──────────────┘  └──────────────┘           │
└─────────────────────────────────────────────────────────────────┘

Core Components

ComponentTech StackResponsibility
LLM InferenceOllama + DeepSeek / OpenAI APIUnderstand intent, generate commands
Command SandboxDocker + seccompIsolated execution, prevent damage
Context ManagementLangChain + vector DBSession history and knowledge base
Command ExecutorPython subprocessSafe command execution with output capture
Security AuditorCustom RBAC + audit logsAccess control, operation traceability

2. Core Implementation

2.1 Natural Language Intent Parsing

The core capability of the copilot is converting natural language into executable operations commands. We use Structured Output to ensure the LLM returns parseable command formats.

# copilot/intent_parser.py
from pydantic import BaseModel, Field
from typing import Literal, Optional

class CommandIntent(BaseModel):
    """Command intent definition"""
    action: Literal[
        "diagnose", "monitor", "manage", "debug", "optimize", "security"
    ] = Field(..., description="Operation type")
    target: str = Field(..., description="Target, e.g. 'nginx', 'docker', 'system'")
    command: str = Field(..., description="Generated specific command")
    explanation: str = Field(..., description="Command explanation")
    risk_level: Literal["low", "medium", "high"] = Field(
        ..., description="Risk level"
    )
    requires_approval: bool = Field(
        False, description="Requires human approval"
    )

    def validate_safety(self) -> bool:
        """Safety validation: reject high-risk dangerous operations"""
        dangerous_patterns = [
            r"rm\s+/-rf\s*/", r">\s*/dev/sda", r"dd\s+if=.*of=/dev/"
        ]
        import re
        for pattern in dangerous_patterns:
            if re.search(pattern, self.command):
                return False
        return True

2.2 Command Execution Sandbox

To prevent AI-generated dangerous commands from causing irreversible damage, all commands execute in a Docker sandbox:

# Dockerfile.sandbox
FROM ubuntu:22.04

# Install common operations tools
RUN apt-get update && apt-get install -y \
    procps net-tools iproute2 curl wget \
    htop iotop nload lm-sensors \
    docker.io nginx mysql-client postgresql-client \
    && rm -rf /var/lib/apt/lists/*

# Resource limits applied at runtime
CMD ["/bin/bash"]
# copilot/sandbox.py
import docker
import json
from datetime import timedelta

class CommandSandbox:
    def __init__(self):
        self.client = docker.from_env()
        self.container = None

    def execute(self, command: str, timeout: int = 30) -> dict:
        """Execute command in sandbox, return structured result"""
        self.container = self.client.containers.run(
            "vps-copilot-sandbox:latest",
            command,
            detach=True,
            network_mode="none",      # Disable network, prevent outbound commands
            mem_limit="512m",
            cpu_period=100000,
            cpu_quota=200000,        # Limit to 0.2 CPU
            read_only=True,
            tmpfs={"/tmp": "rw,nosuid,noexec,size=64m"},
            security_opt=["no-new-privileges:true"],
            user="nobody",
        )

        try:
            result = self.container.wait(timeout=timeout)
            logs = self.container.logs().decode("utf-8", errors="replace")
            exit_code = result.get("StatusCode", -1)

            return {
                "exit_code": exit_code,
                "stdout": logs,
                "success": exit_code == 0,
                "sandbox_id": self.container.id[:12],
            }
        finally:
            self.container.remove(force=True)

2.3 Context Management & Memory System

VPS operations require context awareness — the system needs to understand historical operations, current state, and operational background.

# copilot/context_manager.py
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
import json

class VPSContextManager:
    def __init__(self, llm_model: str = "deepseek-r1:8b"):
        self.embeddings = OllamaEmbeddings(model=llm_model)
        self.vectorstore = Chroma(
            persist_directory="./data/vps_knowledge",
            embedding_function=self.embeddings,
        )
        self.session_history = []
        self.system_state = self._collect_system_state()

    def _collect_system_state(self) -> dict:
        """Collect current VPS system state as context"""
        state = {
            "os": self._run_simple("cat /etc/os-release | grep PRETTY_NAME"),
            "cpu": self._run_simple("nproc"),
            "memory_total_gb": self._run_simple(
                "free -g | awk '/^Mem:/{print $2}'"
            ),
            "disk_total_gb": self._run_simple(
                "df -BG / | awk 'NR==2{print $2}' | tr -d 'G'"
            ),
            "running_services": self._run_simple(
                "systemctl list-units --type=service --state=running "
                "| awk 'NR>2{print $1}' | sed 's/.service//'"
            ),
            "uptime": self._run_simple("uptime -p"),
        }
        return state

    def add_to_context(self, message: str, role: str = "user"):
        """Add conversation history to context"""
        self.session_history.append({
            "role": role,
            "content": message,
            "timestamp": __import__("datetime").datetime.now().isoformat(),
        })
        # Keep last 20 turns of conversation
        if len(self.session_history) > 20:
            self.session_history = self.session_history[-20:]

    def get_system_prompt(self) -> str:
        """Build complete prompt with system state"""
        state_desc = json.dumps(self.system_state, ensure_ascii=False, indent=2)
        history_desc = json.dumps(
            self.session_history[-10:], ensure_ascii=False, indent=2
        )

        return f"""You are a professional VPS operations AI assistant.

【Current System State】
{state_desc}

【Recent Conversation History】
{history_desc}

Please provide accurate, safe operations recommendations based on system state and history.
For operations that may affect production, always mark the risk level and request confirmation."""

2.4 Intelligent Diagnostics & Fix Recommendations

The copilot doesn’t just execute commands — it diagnoses problems and provides fix solutions:

# copilot/diagnostician.py
class VPSDiagnostician:
    """Intelligent diagnostic engine"""

    DIAGNOSTIC_CHECKS = {
        "cpu": {
            "command": "top -bn1 | head -20",
            "alert_threshold": {"load_avg_1min": 8.0, "cpu_usage": 90},
        },
        "memory": {
            "command": "free -h && vmstat -s",
            "alert_threshold": {"memory_usage": 85, "swap_usage": 70},
        },
        "disk": {
            "command": "df -h && du -sh /var/log/* 2>/dev/null | sort -hr | head -10",
            "alert_threshold": {"disk_usage": 90},
        },
        "network": {
            "command": "ss -tuln | head -30 && curl -s --max-time 5 https://www.baidu.com > /dev/null && echo 'Network OK'",
            "alert_threshold": {"connection_count": 1000},
        },
        "process": {
            "command": "ps aux --sort=-%mem | head -15",
            "alert_threshold": {"max_procs": 500},
        },
    }

    def diagnose(self, scope: str = "all") -> dict:
        """Run diagnostics and return structured results"""
        results = {}
        if scope == "all":
            checks = self.DIAGNOSTIC_CHECKS
        else:
            checks = {scope: self.DIAGNOSTIC_CHECKS[scope]}

        for check_name, config in checks.items():
            output = self._execute_command(config["command"])
            alerts = self._analyze_output(check_name, output, config["alert_threshold"])
            results[check_name] = {
                "output": output[:2000],  # Truncate long output
                "alerts": alerts,
                "status": "healthy" if not alerts else "warning",
            }

        return results

3. Complete Deployment Guide

3.1 Project Structure

vps-copilot/
├── copilot/
│   ├── __init__.py
│   ├── intent_parser.py      # Intent parsing
│   ├── sandbox.py            # Command sandbox
│   ├── context_manager.py    # Context management
│   ├── diagnostician.py      # Diagnostic engine
│   ├── security.py           # Security audit
│   └── llm_engine.py         # LLM inference engine
├── api/
│   ├── routes.py             # FastAPI routes
│   ├── websocket.py          # WebSocket real-time terminal
│   └── middleware.py         # Security middleware
├── web/
│   ├── index.html            # Web terminal interface
│   └── assets/
├── config/
│   ├── copilot.yaml          # Configuration file
│   └── rbac.json             # Permission control
├── data/
│   └── vps_knowledge/        # Vector database
├── docker-compose.yml
├── Dockerfile
└── requirements.txt

3.2 Docker Compose Deployment

# docker-compose.yml
version: "3.8"

services:
  copilot-api:
    build: .
    container_name: vps-copilot-api
    ports:
      - "8080:8080"
    environment:
      - LLM_PROVIDER=ollama
      - OLLAMA_HOST=http://ollama:11434
      - LLM_MODEL=deepseek-r1:8b
      - AUTH_SECRET=${AUTH_SECRET}
      - ENABLE_DANGER_APPROVAL=true
    volumes:
      - ./data:/app/data
      - /var/run/docker.sock:/var/run/docker.sock:ro  # Read-only access
    networks:
      - copilot-net
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true

  ollama:
    image: ollama/ollama:latest
    container_name: vps-copilot-ollama
    ports:
      - "11434:11434"
    volumes:
      - ./ollama-data:/root/.ollama
    networks:
      - copilot-net
    restart: unless-stopped

  chroma:
    image: chromadb/chroma:latest
    container_name: vps-copilot-chroma
    volumes:
      - ./chroma-data:/chroma/chroma
    networks:
      - copilot-net
    restart: unless-stopped

networks:
  copilot-net:
    driver: bridge

3.3 API Interface Design

# api/routes.py
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel

app = FastAPI(title="VPS Copilot API", version="1.0.0")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_methods=["*"],
    allow_headers=["*"],
)

class ChatRequest(BaseModel):
    message: str
    session_id: str = ""
    stream: bool = True

class ChatResponse(BaseModel):
    response: str
    commands_executed: list[dict] = []
    diagnostics: dict = {}

@app.post("/api/chat", response_model=ChatResponse)
async def chat(request: ChatRequest):
    """Process natural language instructions"""
    copilot = get_copilot_instance(request.session_id)
    response = await copilot.process_message(request.message)

    # Security audit
    audit_log = await security_auditor.log(
        session_id=request.session_id,
        message=request.message,
        commands=response.commands_executed,
    )

    return ChatResponse(
        response=response.text,
        commands_executed=response.commands_executed,
        diagnostics=response.diagnostics,
    )

@app.websocket("/ws/terminal")
async def terminal_websocket(websocket: WebSocket):
    """Real-time terminal WebSocket"""
    await websocket.accept()
    try:
        while True:
            data = await websocket.receive_text()
            response = await process_terminal_input(data, websocket)
            await websocket.send_text(response)
    except WebSocketDisconnect:
        print("Client disconnected")

4. Typical Usage Scenarios

Scenario 1: Performance Diagnosis

User: “help me figure out why the server is slow”

Copilot Response:

Running system performance diagnostics...

[CPU] Normal (load avg: 0.45, 0.52, 0.48)
[Memory] ⚠️ Usage at 87%, ~1.2GB remaining
  - Suggestion: Check top memory-consuming processes
  - Top processes: nginx(256MB), postgres(512MB), node(380MB)
[Disk] ✅ Usage at 62%
[Network] ✅ Connection count normal (234)

[Conclusion] Memory pressure is the primary bottleneck
[Recommended Actions]
  1. Restart the anomalous node process
  2. Adjust nginx worker_connections configuration
  3. Consider upgrading to 4GB memory configuration

Scenario 2: Security Investigation

User: “check for suspicious login activity”

Copilot Response:

Checking security logs...

[SSH Login Records]
  - Login attempts in last 24h: 47
  - Failed attempts: 23 (sources: 185.220.101.xx, 45.141.88.xx)
  - Successful logins: 24 (from normal IP ranges)

[Anomaly Detection]
  ⚠️ Brute-force迹象: IP 185.220.101.xx attempted 15 failed logins
  ⚠️ Off-hours login detected: Successful login at 2:33 AM from unknown IP

[Recommended Actions]
  1. Block suspicious IPs immediately: firewall-cmd --permanent --add-rich-rule=
     'rule family=ipv4 source address=185.220.101.0/24 reject'
  2. Check the off-hours session: who | grep pts
  3. Enable two-factor authentication: install google-authenticator

Execute block operation? (confirmation required)

Scenario 3: Automated Operations

User: “clean /tmp and logs at 3 AM daily, keep only last 7 days”

Copilot Response:

Generating scheduled task configuration...

[Scheduled Task]
  Time: Daily at 03:00
  Operation: Clean /tmp and old logs

[Generated Script]
  #!/bin/bash
  # Auto-generated by VPS Copilot
  find /tmp -type f -mtime +7 -delete 2>/dev/null
  find /var/log -name "*.log" -mtime +7 -exec gzip {} \;
  find /var/log -name "*.gz" -mtime +30 -delete

[Security Audit]
  - Risk level: Low
  - Impact scope: Only cleans expired files, does not affect running services
  - Requires approval: No

[Deployment]
  1. Save script to /usr/local/bin/vps-cleanup.sh
  2. Add systemd timer or crontab execution
  3. Log to /var/log/vps-cleanup.log

Deploy this scheduled task?

5. Security & Access Control

5.1 RBAC Permission Model

// config/rbac.json
{
  "roles": {
    "admin": {
      "permissions": ["read", "write", "execute", "approve", "manage"],
      "dangerous_commands": false,
      "max_concurrent_sessions": 10
    },
    "operator": {
      "permissions": ["read", "execute"],
      "dangerous_commands": true,
      "requires_approval_for": ["systemctl restart", "iptables"],
      "max_concurrent_sessions": 3
    },
    "viewer": {
      "permissions": ["read"],
      "dangerous_commands": false,
      "max_concurrent_sessions": 1
    }
  }
}

5.2 Operation Audit Logs

# copilot/security.py
import json
import logging
from datetime import datetime
from pathlib import Path

AUDIT_LOG = Path("/var/log/vps-copilot/audit.log")

class SecurityAuditor:
    def __init__(self):
        AUDIT_LOG.parent.mkdir(parents=True, exist_ok=True)
        self.logger = logging.getLogger("copilot.audit")

    async def log(self, session_id: str, message: str,
                  commands: list[dict], user: str = "anonymous") -> dict:
        """Log operation audit trail"""
        entry = {
            "timestamp": datetime.now().isoformat(),
            "session_id": session_id,
            "user": user,
            "natural_language": message,
            "commands_executed": commands,
            "risk_assessment": self._assess_risk(commands),
            "audit_id": self._generate_audit_id(),
        }

        with open(AUDIT_LOG, "a") as f:
            f.write(json.dumps(entry, ensure_ascii=False) + "\n")

        return entry

    def _assess_risk(self, commands: list[dict]) -> str:
        """Assess operation risk level"""
        risk_score = 0
        for cmd in commands:
            if "rm -rf" in cmd.get("command", ""):
                risk_score += 10
            if "iptables" in cmd.get("command", ""):
                risk_score += 5
            if "systemctl" in cmd.get("command", ""):
                risk_score += 3

        if risk_score >= 10:
            return "critical"
        elif risk_score >= 5:
            return "high"
        return "low"

6. Results & Benefits

6.1 Quantitative Metrics

MetricTraditional OpsAI CopilotImprovement
Command lookup time5-15 min<30 sec95% ↓
Troubleshooting efficiency30+ min5 min83% ↓
Operations barrierRequires expertiseNatural languageSignificantly lowered
Operation error rate5-10%<1%90% ↓
Newbie learning curve2-4 weeks1-2 days90% ↓

6.2 Qualitative Benefits

  1. Lower the operations barrier: Non-technical users can perform basic VPS management
  2. Knowledge preservation: All operations are automatically recorded and searchable
  3. Reduce human error: AI-generated commands undergo safety validation
  4. 24/7 response: No human on-call needed; system handles common tasks automatically
  5. Continuous evolution: The AI learns your VPS environment and operations habits over time

Conclusion

The AI-powered VPS terminal copilot represents a new direction in operations tooling — letting technology serve humans, rather than making humans adapt to technology. Through natural language interaction, we lower the VPS operations barrier while ensuring safety through sandbox isolation and security auditing.

Future evolution directions:

  • Multi-VPS coordinated management (one command, batch execution)
  • Deep integration with CI/CD pipelines
  • Predictive operations (proactive intervention before problems occur)
  • Multi-language and localization support

Every VPS user deserves professional operations team-level intelligent assistance — that’s the true value of AI + VPS convergence.

📺 看视频版教程 → DuckDB Lab YouTube

Subscribe for more DuckDB & AI automation tutorials