| name | local-ai-security-hygiene |
| description | Sichere Installation, Konfiguration und vollständige Entfernung lokaler AI-Services (Ollama, llama.cpp, etc.) inklusive Hermes-Config-Synchronisation und Offline/Online-Fallback-Strategien.
|
| version | 1.1.0 |
| author | Hermes Agent |
| license | MIT |
Local AI Security Hygiene
Trigger
- User will lokalen LLM-Hosting einrichten oder komplett abschalten
- Security-Audit zeigt unnötige lokale AI-Services (offene Ports, große Model-Dirs)
- Hermes soll zwischen Online-Provider (Nous Portal, OpenRouter) und Offline (lokal) umschalten
- Nach Deinstallation sind API-Fehler (401) aufgetreten
- Ollama soll nur als Offline-Fallback laufen — nicht parallel zum Online-Provider
Core Principles
- Minimal Exposure: Lokale Services nur aktiv wenn nötig; sonst Firewall + Abschaltung
- Clean Teardown: Deinstallation muss Binary, Libs, Modelle UND Config-Referenzen entfernen
- Config Sync: Hermes
config.yaml muss nach Install/Deinstall angepasst werden
- Explicit Provider: Kein
provider: auto bei Auxiliary Services wenn lokaler Service entfernt wurde
- Online-First: Lokale Ollama nur als Fallback — nicht als aktiver Default wenn Internet verfügbar
Ollama: Complete Removal Checkliste
systemctl --user status ollama 2>/dev/null | grep -E "Active|Loaded"
systemctl --user stop ollama 2>/dev/null
systemctl --user disable ollama 2>/dev/null
rm -f ~/.config/systemd/user/ollama.service
systemctl --user daemon-reload
which ollama
ls -la $(which ollama) 2>/dev/null
rm -f ~/.local/bin/ollama
rm -rf ~/.local/lib/ollama
du -sh ~/.ollama 2>/dev/null || echo "~/.ollama nicht vorhanden"
rm -rf ~/.ollama
rm -rf ~/.local/share/ollama
rm -rf /usr/share/ollama
snap list | grep ollama && snap remove ollama
rm -f ~/.local/bin/ollama_network_monitor.sh
crontab -l | grep -v "ollama_network_monitor" | crontab -
which ollama && echo "WARNUNG: Binary noch vorhanden!" || echo "✓ Binary entfernt"
ls -d ~/.ollama 2>/dev/null && echo "WARNUNG: ~/.ollama existiert!" || echo "✓ ~/.ollama entfernt"
systemctl --user status ollama 2>/dev/null | grep -q "Active" && echo "WARNUNG: Service läuft!" || echo "✓ Service gestoppt"
Hermes Config: Nach Ollama-Deinstall bereinigen
Referenzen finden (alle Stellen!)
grep -in "ollama" ~/.hermes/config.yaml
Typische Treffer:
providers.ollama-launch → Dict entfernen
custom_providers mit name: ollama-local → Listenelement entfernen
fallback_providers mit provider: custom:ollama-local → Listenelement entfernen
model.api_key: ollama → auf '' setzen
auxiliary.*.provider → niemals ollama oder auto wenn Ollama weg ist
Direkte YAML-Bearbeitung (notwendig für Listen/Dicts)
hermes config set kann keine Listen/Dicts bearbeiten. Python direkt:
import yaml
with open('/home/bratan/.hermes/config.yaml') as f:
data = yaml.safe_load(f)
data['providers'].pop('ollama-launch', None)
data['custom_providers'] = [
cp for cp in data.get('custom_providers', [])
if cp.get('name') != 'ollama-local'
]
data['fallback_providers'] = [
fp for fp in data.get('fallback_providers', [])
if 'ollama' not in str(fp.get('provider', ''))
]
data['model']['api_key'] = ''
with open('/home/bratan/.hermes/config.yaml', 'w') as f:
yaml.dump(data, f, default_flow_style=False, sort_keys=False, allow_unicode=True)
CLI-Methoden (nur für einfache Keys)
hermes config set model.api_key '' --profile default
hermes config set auxiliary.title_generation.provider openrouter --profile default
401-Fehler: Root-Cause & Fix
Symptom: Alle API-Calls schlagen mit 401 fehl, obwohl Nous Portal/OpenRouter Key gültig ist.
Ursache: model.api_key: ollama in config.yaml überschreibt den echten Key aus .env. Hermes sendet Authorization: Bearer ollama an die API.
Fix:
hermes config check
hermes config set model.api_key '' --profile default
Ollama: Offline-Only Fallback (Network Monitor)
Wenn Ollama installiert bleiben soll aber NUR bei fehlendem Internet aktivieren:
Beschreibung
Ein cron-basierter Network Monitor prüft alle 5 Minuten die Internet-Erreichbarkeit. Bei Offline-Status wird Ollama gestartet, bei Online-Status wird Ollama gestoppt. Hermes benutzt Ollama nur über die fallback_providers Kette.
Script installieren
cp ~/.hermes/skills/devops/local-ai-security-hygiene/references/ollama_network_monitor.sh ~/.local/bin/
chmod +x ~/.local/bin/ollama_network_monitor.sh
(crontab -l 2>/dev/null; echo "*/5 * * * * ~/.local/bin/ollama_network_monitor.sh >> /tmp/ollama_monitor.log 2>&1") | crontab -
~/.local/bin/ollama_network_monitor.sh
Hermes Config (nur Fallback, nie Default)
model:
provider: nous
default: qwen3.7-plus
api_key: ''
fallback_providers:
- provider: anthropic
model: claude-sonnet-4-20250514
- provider: custom:ollama-local
model: deepseek-r1:8b
base_url: "http://127.0.0.1:11434/v1"
custom_providers:
- name: ollama-local
base_url: http://127.0.0.1:11434/v1
api_key: ''
agent:
api_max_retries: 1
auxiliary:
title_generation:
provider: openrouter
Wichtig
- Niemals
model.provider: custom:ollama-local als Default setzen
- Niemals
api_key: ollama verwenden (verursacht 401)
- Ollama läuft nur wenn Internet UNTENRREICHT, sonst Brave-Browserkrieg
- Bei Systemneustart:
systemctl --user start ollama manuell oder Network Monitor startet es beim ersten Offline-Check
Security Checklist (lokale Services)
Additional Pitfalls
Snap AppArmor Restrictions
Snap packages ship managed AppArmor profiles that cannot be directly edited. If a snap service needs additional permissions (e.g., NVIDIA GPU access), create a local override in /etc/apparmor.d/local/snap.<name>.server:
sudo bash -c 'cat > /etc/apparmor.d/local/snap.<name>.server << EOF
/dev/char/195:[0-9]* rw,
/dev/char/506:[0-9]* rw,
capability perfmon,
/proc/driver/nvidia/capabilities/mig/ r,
/proc/driver/nvidia/capabilities/mig/** r,
EOF'
sudo apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.<name>.server
Check denials: sudo dmesg | grep -i "apparmor.*<name>"
Swappiness on Desktop Linux
Default swappiness (60) or cloud-optimized (100) causes aggressive swapping with GPU workloads. Set to 10-20: sudo sysctl vm.swappiness=20 + persist in /etc/sysctl.d/99-swappiness.conf.
Cloud-to-Local Migration Pattern
When cloud providers become unavailable:
- Primary: Ollama local model (qwen3.5-9b-hermes, 6.6GB)
- Fallback: NVIDIA Nemotron 120B via Snap, port 8332, start/stop on demand
- Hermes config is protected from automated editing — backup before changes
Swap Cycle
Force-clear swap: sudo swapoff -a && sudo swapon -a (brief CPU spike). Check with free -h | grep -i auslager.
- Snap-Residue:
snap remove ollama entfernt das Binary, aber ~/.ollama (20 GB+ Modelle) bleibt liegen.
- Symlink-Trap:
which ollama zeigt ~/.local/bin/ollama, das ist aber ein Symlink. Das eigentliche Binary liegt in ~/.local/lib/ollama/bin/ollama.
- Magic API Key:
api_key: ollama ist ein Platzhalter für Ollamas interne API, KEIN echter Key. Er verursacht 401 bei echten Cloud-Providern.
- Auto-Provider-Falle:
provider: auto bei Auxiliary Services probiert nacheinander alle Provider. Wenn eine tote Ollama-Referenz in der Config steht, blockiert oder fehlschlägt der Call.
- ~/.ollama ist riesig: Nutzer vergessen die Modelle.
du -sh ~/.ollama zeigt die wahre Größe.
- Systemd Stealth Mode: Ollama läuft als
systemd --user Service weiter, auch wenn das Binary gelöscht wurde. Der Service startet bei Login neu! IMMER systemctl --user status ollama prüfen.
- hermes config set Limitation:
hermes config set key value funktioniert nur für flache Keys. Listen (fallback_providers, custom_providers) und Dicts (providers) müssen direkt im YAML oder via Python bearbeitet werden.
- Nutzer sagt "gelöscht" → immer verifizieren: "Aus Sicherheitsgründen gelöscht" bedeutet oft nur
rm -rf ~/.ollama/models, nicht das Binary oder den Service. Grep + Status + which prüfen.
Related Skills
ollama-local-hosting – Installation & Setup (Komplement zu diesem Teardown-Skill)
linux-system-maintenance – Allgemeines System-Cleanup
hermes-agent – Config-Verwaltung via hermes config CLI
Session-Referenzen
references/session-2026-06-05-ollama-teardown.md – Erstes 401-Fix + vollständige Deinstallation
references/session-2026-06-05-systemd-stealth-teardown.md – Systemd stealth mode: Ollama läuft weiter obwohl Nutzer "gelöscht" sagte; Python-YAML für Listen/Dicts; Kimi-K2.6 als Nous-Default