
Hvordan lage et autonomt system for oppdatering av sårbarheter ved hjelp av LM Studio 0.4.1, Devstral og Claude CLI.
Enterprise KI-sikkerhetsverktøy som Cogent Security hentet nettopp inn $42 millioner for å automatisere sårbarhetshåndtering. Imponerende. Men hva om du kunne bygge noe lignende for ditt eget hjemmelab — ved hjelp av åpen kildekode-verktøy og lokal KI?
I denne artikkelen viser jeg deg hvordan du lager din egen KI-sikkerhetsagent som:
- Scanner Docker-containere, Proxmox-VM-er og LXC-containere for sårbarheter
- Bruker LM Studio 0.4.1 med Anthropic-kompatibelt API — fungerer naturlig med Claude CLI
- Kjører Mistral Devstral Small 2-modellen lokalt (68 % på SWE-bench Verified)
- Koster $0 i API-avgifter — alt kjører på din maskinvare
Dette er guiden jeg ønsket eksisterte da jeg begynte å automatisere hjemmelab-sikkerheten min.
Hva endret seg i januar 2026
LM Studio 0.4.1 (utgitt 29. januar 2026) introduserte en spillveksler: naturlig Anthropic API-kompatibilitet.
Dette betyr:
- ✅ Claude CLI fungerer direkte med lokale modeller
- ✅ Bruk
/v1/messages-endepunktet (samme som Anthropic) - ✅ Erstatning uten kodeendringer for Anthropic SDKer
- ✅ Streaming-støtte (
message_start,content_block_delta,message_stop)
Ingen mer omveier. Ingen mer OpenAI-kompatibilitets-lag. Bare naturlig Claude-integrasjon med dine lokale modeller.
Stakken
| Komponent | Formål |
|---|---|
| LM Studio 0.4.1 | Lokal modellserver med Anthropic API |
| Devstral Small 2 | 24B-parameter kodespesialisert modell |
| Claude CLI | Agentgrensesnitt |
| Trivy | Skanner for containersårbarheter |
| Grype | Alternativ sårbarhetsskanner |
| proxmoxer | Proxmox Python API |
Del 1: Sette opp LM Studio 0.4.1+ med Anthropic API
Hvorfor LM Studio 0.4.1?
Utgivelsen 29. januar 2026 la til naturlig Anthropic API-kompatibilitet:
- Endepunkt:
http://localhost:1234/v1/messages - Miljø:
ANTHROPIC_BASE_URL=http://localhost:1234 - Auth:
ANTHROPIC_AUTH_TOKEN=lmstudio(eller en hvilken som helst streng)
Dette gjør LM Studio til en erstatning uten kodeendringer for Anthropics cloud-API.
Installasjon
Linux (AppImage):
# Last ned LM Studio 0.4.1+
wget https://releases.lmstudio.ai/linux/0.4.1/LM-Studio-0.4.1-x86_64.AppImage
chmod +x LM-Studio-0.4.1-x86_64.AppImage
./LM-Studio-0.4.1-x86_64.AppImage
macOS:
brew install --cask lm-studio
Windows: Last ned installasjonsprogram fra https://lmstudio.ai/
Installere LM Studio CLI
LM Studio 0.4.1+ inkluderer kommandolinjeverktøyet lms:
# Verifiser CLI-installasjon (etter å ha kjørt LM Studio GUI minst én gang)
lms --help
# Sjekk om server kjører
lms ps
# List opp lastede modeller
lms ls
Laste ned Devstral Small 2-modellen
# Installer Hugging Face Hub
pip install -U huggingface-hub
# Last ned Devstral Small 2 (Q4_K_M-kvantisering)
huggingface-cli download \
unsloth/Devstral-Small-2-24B-Instruct-2512-GGUF \
Devstral-Small-2-24B-Instruct-2512-Q4_K_M.gguf \
--local-dir ~/.lmstudio/models
# Alternativ: Codestral-22B (mindre, raskere)
huggingface-cli download \
lmstudio-community/Codestral-22B-v0.1-GGUF \
Codestral-22B-v0.1-Q4_K_M.gguf \
--local-dir ~/.lmstudio/models
Aktivere den Anthropic-kompatible serveren
# Last inn modell og start server
lms load unsloth/Devstral-Small-2-24B-Instruct-2512-GGUF \
--gpu 1.0 \
--context-length 32768
# Start server
lms server start --port 1234
Verifiser serverstatus
lms ps
# Forventet utdata:
# ✓ Server running on port 1234
# ✓ Model loaded: Devstral-Small-2-24B-Instruct-2512
# ✓ API format: Anthropic Messages
Teste det Anthropic-kompatible API-et
Python-test:
#!/usr/bin/env python3
from anthropic import Anthropic
def test_lm_studio():
client = Anthropic(
base_url="http://localhost:1234",
api_key="lmstudio"
)
try:
message = client.messages.create(
model="devstral-small-24b",
max_tokens=1024,
messages=[{"role": "user", "content": "What is CVE-2024-3094?"}]
)
print("✅ Connection successful!")
print(f"Response: {message.content[0].text}")
return True
except Exception as e:
print(f"❌ Connection failed: {e}")
return False
if __name__ == "__main__":
test_lm_studio()
cURL-test:
curl http://localhost:1234/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: lmstudio" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "devstral-small-24b",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Explain CVE scanning in one paragraph"}]
}'
Del 2: Installere Claude CLI
Installasjon
# macOS, Linux, WSL
curl -fsSL https://claude.ai/install.sh | bash
# Verifiser
claude --version
Konfigurasjon
# Legg til i ~/.bashrc eller ~/.zshrc
export ANTHROPIC_BASE_URL="http://localhost:1234"
export ANTHROPIC_AUTH_TOKEN="lmstudio"
source ~/.bashrc
Test Claude CLI
# Interaktiv økt
claude
# Enkelt kommando
claude "List all Python files and check for SQL injection vulnerabilities"
# Utskriftsmodus (spørring og avslutt)
claude -p "Review this Dockerfile for security issues"
Verifiser tilkobling
DEBUG=1 claude -p "What is 2+2?"
# Forventet utdata inkluderer:
# → Connecting to http://localhost:1234/v1/messages
# → Model: devstral-small-24b
Del 3: Oppsett av sårbarhetsskanning
Trivy (Anbefalt for Docker)
# Installer siste Trivy
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | \
sh -s -- -b /usr/local/bin
# Skann et Docker-bilde
trivy image nginx:latest --format json --output trivy-report.json
# Skann alle kjørende containere
mkdir -p reports
docker ps --format '{{.Image}}' | while read img; do
safe_name=$(echo "$img" | tr '/:' '_')
trivy image "$img" --format json --output "reports/${safe_name}.json"
done
Grype (Alternativ)
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | \
sh -s -- -b /usr/local/bin
grype nginx:latest -o json > grype-report.json
Proxmox-skanner
#!/usr/bin/env python3
import json, os
from typing import List, Dict, Any, Optional
from proxmoxer import ProxmoxAPI
class ProxmoxScanner:
def __init__(self, host: str, user: str,
password: Optional[str] = None, verify_ssl: bool = False):
password = password or os.getenv('PROXMOX_PASSWORD')
if not password:
raise ValueError("Password required (set PROXMOX_PASSWORD env var)")
self.proxmox = ProxmoxAPI(host, user=user, password=password, verify_ssl=verify_ssl)
def scan_lxc_containers(self) -> List[Dict[str, Any]]:
results = []
for node in self.proxmox.nodes.get():
node_name = node['node']
for container in self.proxmox.nodes(node_name).lxc.get():
if container['status'] != 'running':
continue
vmid = container['vmid']
try:
result = self.proxmox.nodes(node_name).lxc(vmid).exec.post(
command='apt list --upgradable 2>/dev/null | grep -i security'
)
results.append({
'type': 'lxc', 'node': node_name, 'vmid': vmid,
'name': container.get('name', f'CT-{vmid}'),
'security_updates': result
})
except Exception as e:
print(f"Error scanning LXC {vmid}: {e}")
return results
if __name__ == "__main__":
scanner = ProxmoxScanner(
host=os.getenv('PROXMOX_HOST', '192.168.1.100'),
user=os.getenv('PROXMOX_USER', 'root@pam'),
password=os.getenv('PROXMOX_PASSWORD')
)
results = scanner.scan_lxc_containers()
with open('proxmox-scan-results.json', 'w') as f:
json.dump(results, f, indent=2)
Del 4: Bygge KI-sikkerhetsagenten
#!/usr/bin/env python3
import json, subprocess, os
from datetime import datetime
from pathlib import Path
from typing import List, Dict, Any
from anthropic import Anthropic
class SecurityAgent:
def __init__(self, lm_studio_url: str = "http://localhost:1234"):
if not lm_studio_url.startswith(('http://', 'https://')):
raise ValueError("Invalid LM Studio URL format")
self.client = Anthropic(base_url=lm_studio_url, api_key="lmstudio")
self.model = "devstral-small-24b"
self.scans_dir = Path("scans")
self.patches_dir = Path("patches")
self.scans_dir.mkdir(parents=True, exist_ok=True)
self.patches_dir.mkdir(parents=True, exist_ok=True)
def call_devstral(self, system_prompt: str, user_message: str) -> str:
try:
message = self.client.messages.create(
model=self.model, max_tokens=4096,
system=system_prompt,
messages=[{"role": "user", "content": user_message}]
)
return message.content[0].text
except Exception as e:
print(f"Error calling Devstral: {e}")
return ""
def scan_docker(self) -> List[Dict[str, Any]]:
print("🔍 Scanning Docker containers...")
result = subprocess.run(
["docker", "ps", "--format", "{{.Names}}\t{{.Image}}"],
capture_output=True, text=True, check=False
)
containers = [
{'name': parts[0], 'image': parts[1]}
for line in result.stdout.strip().split('\n')
if line and len(parts := line.split('\t')) == 2
]
scan_results = []
for container in containers:
print(f" Scanning {container['name']} ({container['image']})...")
scan_file = self.scans_dir / f"docker_{container['name']}.json"
subprocess.run(
["trivy", "image", container['image'],
"--format", "json", "--output", str(scan_file), "--quiet"],
capture_output=True, check=False
)
if scan_file.exists():
with open(scan_file) as f:
scan_data = json.load(f)
vulnerabilities = [
{
'id': v.get('VulnerabilityID'),
'severity': v.get('Severity'),
'package': v.get('PkgName'),
'installed': v.get('InstalledVersion'),
'fixed': v.get('FixedVersion'),
}
for r in scan_data.get('Results', [])
for v in r.get('Vulnerabilities', [])
]
scan_results.append({
'container': container['name'],
'image': container['image'],
'vulnerabilities': vulnerabilities
})
return scan_results
def analyze_vulnerabilities(self, scan_results: List[Dict[str, Any]]) -> Dict[str, Any]:
system_prompt = """You are a security expert AI. Analyze vulnerability scan results and
output a JSON remediation plan: {"summary":"...","critical_vulnerabilities":[...],"remediation_steps":[...],"automation_candidates":[...]}"""
response = self.call_devstral(
system_prompt,
f"Analyze these scan results:\n\n{json.dumps(scan_results, indent=2)}"
)
try:
start, end = response.find('{'), response.rfind('}') + 1
if start >= 0 and end > start:
return json.loads(response[start:end])
except json.JSONDecodeError:
pass
return {"raw_analysis": response}
def run_full_scan_and_patch_cycle(self) -> Dict[str, Any]:
print("=" * 60)
print("🤖 Homelab AI Security Agent - Starting Scan")
print("=" * 60)
scan_results = self.scan_docker()
print("\n🧠 Analyzing vulnerabilities with Devstral...")
analysis = self.analyze_vulnerabilities(scan_results)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
analysis_file = self.scans_dir / f"analysis_{timestamp}.json"
with open(analysis_file, 'w') as f:
json.dump(analysis, f, indent=2)
print(f"\n✅ Analysis saved to {analysis_file}")
return {'scan_results': scan_results, 'analysis': analysis}
if __name__ == "__main__":
agent = SecurityAgent()
agent.run_full_scan_and_patch_cycle()
Del 5: Bruke Claude CLI for autonom lapping
# Skann nginx og bruk patcher for CRITICAL/HIGH CVE-er
claude -p "Scan nginx container for vulnerabilities using trivy, then apply security patches if any HIGH or CRITICAL CVEs are found"
# Lag Proxmox-lappende spillebok
claude -p "Create an Ansible playbook that updates all security packages on Proxmox LXC containers. Include error handling and rollback capabilities."
Python-innpakning:
#!/usr/bin/env python3
import subprocess, os
def run_claude_agent(prompt: str, workdir: str = ".") -> str:
env = os.environ.copy()
env["ANTHROPIC_BASE_URL"] = "http://localhost:1234"
env["ANTHROPIC_AUTH_TOKEN"] = "lmstudio"
result = subprocess.run(
["claude", "-p", prompt],
cwd=workdir, env=env, capture_output=True, text=True, check=False
)
return result.stdout
print(run_claude_agent("Scan docker-compose.yml for security issues"))
Del 6: Automatisert planlegging
Systemd Timer
# /etc/systemd/system/security-agent.service
[Unit]
Description=Homelab AI Security Agent
After=network.target docker.service
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /opt/security-agent/main.py
WorkingDirectory=/opt/security-agent
Environment="ANTHROPIC_BASE_URL=http://localhost:1234"
Environment="ANTHROPIC_AUTH_TOKEN=lmstudio"
# /etc/systemd/system/security-agent.timer
[Unit]
Description=Run security agent daily at 6 AM
[Timer]
OnCalendar=*-*-* 06:00:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now security-agent.timer
sudo systemctl list-timers security-agent.timer
Telegram-varsler
import requests, os
def send_telegram_alert(message: str) -> bool:
bot_token = os.getenv("TELEGRAM_BOT_TOKEN")
chat_id = os.getenv("TELEGRAM_CHAT_ID")
if not bot_token or not chat_id:
return False
try:
r = requests.post(
f"https://api.telegram.org/bot{bot_token}/sendMessage",
json={"chat_id": chat_id, "text": message, "parse_mode": "HTML"},
timeout=10
)
return r.status_code == 200
except Exception:
return False
send_telegram_alert("🚨 <b>5 critical vulnerabilities found in nginx</b>")
Maskinvarekrav
- Minimum: 16 GB VRAM for Q4_K_M-kvantisering
- Anbefalt: 32K kontekstlengde (≈ 18-20 GB VRAM totalt)
- Claude CLI fungerer best med 25K+ kontekst
Feilsøking
LM Studio-serverproblemer
lms ps
lms server stop && lms server start --port 1234
Claude CLI-tilkoblingsproblemer
echo $ANTHROPIC_BASE_URL # should be http://localhost:1234
echo $ANTHROPIC_AUTH_TOKEN # should be lmstudio
DEBUG=1 claude -p "test"
sudo lsof -i :1234 # check port
OOM / Problemer med innlasting av modell
nvidia-smi # check VRAM
# Reduser kontekst eller kvantisering
lms load model-name --gpu 0.7 --context-length 16384
Viktige poeng
- LM Studio 0.4.1 har naturlig Anthropic API-støtte — ingen omveier nødvendig
- Claude CLI fungerer direkte med lokale modeller via
ANTHROPIC_BASE_URL - Devstral Small 2 scorer 68 % på SWE-bench Verified
- 16 GB VRAM minimum for Q4_K_M-kvantisering
- 25K+ kontekst kreves for best Claude CLI-ytelse
- Total API-kostnad: $0 — alt kjører på din maskinvare
Jeg er seniorarkitekt med spesialisering i KI/ML, Linux-systemer og datasentre. Jeg hjelper organisasjoner med å bygge sikker, automatisert infrastruktur ved hjelp av åpen kildekode-verktøy.
#KI #KIAgenter #Cybersikkerhet #Hjemmelab #Proxmox #Docker #LMStudio #Devstral #ClaudeCLI #Anthropic #OpenSource #DevSecOps #Automatisering