Dette repo er skræddersyet til én konkret maskine. Det kan sagtens bruges af andre, men kun hvis hardwaren matcher — flere ting er hårdt knyttet til den:
Krav Hvorfor det er vigtigt Sapphire Edge AI 340 (AMD Ryzen AI 5 340, Radeon 840M) Acceleration sker via AMD-iGPU + Vulkan, og /dev/dri/renderD128mappes ind til Frigate. Andre CPU'er/GPU'er kræver andre indstillinger.Ubuntu 26.04 LTS (Server) Scriptene bruger Ubuntu 26.04's pakker (Docker 29, kernel 7.0, Mesa/Vulkan). Andre distroer/versioner er ikke testet. Google Coral USB Al kamera-objektgenkendelse i Frigate forudsætter en Coral USB-TPU. Uden den skal Frigate-detektoren konfigureres anderledes. Reolink-kamera på samme LAN Bevægelses-flowet er bygget mod Reolinks Snap-API. Kører du på anden hardware, så forvent at skulle justere især
02-ollama.sh(acceleration) og Frigate-/stack-filerne. Setup-scriptet advarer dig, hvis det ikke ligner den forventede maskine, men stopper dig ikke.
Automatiseret opsætning af en Sapphire Edge AI 340 (AMD Ryzen AI 5 340, Radeon 840M, XDNA2 NPU) som lokal AI-/automatiseringsserver på Ubuntu 26.04 LTS.
Stakken: Ollama (på værten, Vulkan-accel) + N8N + Home Assistant (begge i Docker) + Reolink-kamera-integration + hærdet SSH.
Det vigtigste: Kamera-detektionen (person/bil/dyr) kører på Coral USB-TPU'en via Frigate og er helt uafhængig af sprogmodellen. Den kritiske overvågnings-funktion virker uanset hvad der sker med Ollama. Sprogmodellen er kun et ekstra lag.
| Komponent | Hvad vi bruger den til — og hvor stabilt |
|---|---|
| Coral USB-TPU | Al kamera-objektgenkendelse (Frigate). Bevist, real-time, stenstabilt. Dette er din kritiske vej. |
| Radeon 840M iGPU | Accelererer Ollama (LLM) via Vulkan — nu stabilt i Ollama 0.22+. Ét-tryks-fallback til CPU hvis det driller (OLLAMA_USE_VULKAN=0), så det kører altid. |
| CPU (6× Zen5) | Kører LLM hvis Vulkan slås fra. 100% pålidelig fallback. |
| ROCm | Bruges ikke — og er ikke nødvendigt. Vulkan er den rette vej til denne iGPU. |
| XDNA2 NPU | Bruges ikke — og behøves ikke. Coral laver detektion, CPU/iGPU laver LLM. At NPU'en står ubrugt påvirker intet. |
| RAM (32 GB) | Rigeligt. Med MoE-modeller (fx gpt-oss:20b) får du stor-models kvalitet i lille-models fart. |
| SSD (480 GB) | Fint. Frigate-optagelser styres af retention (se nedenfor); logs ryddes automatisk. |
Der er altså ingen ustabil komponent i den kritiske vej — det vi flaggede (ROCm/NPU) bruges slet ikke.
┌──────────────────────── Sapphire Edge AI 340 (Ubuntu 26.04) ────────────────────────┐
│ │
│ Ollama (host, systemd) ── Vulkan ──> Radeon 840M │
│ :11434 │
│ ▲ ▲ │
│ │ │ host.docker.internal:11434 │
│ ┌────┴─────┐ ┌──┴───────────────┐ │
│ │ HA │ │ N8N │ │
│ │ (host-net)│ │ (docker bridge) │ │
│ │ :8123 │ │ :5678 │ │
│ └────┬─────┘ └──────┬───────────┘ │
└────────┼────────────────┼────────────────────────────────────────────────────────────┘
│ motion-event │ henter snapshot (HTTP Snap API)
▼ ▼
(webhook) ┌──────────────┐
│ Reolink-kamera│ (samme LAN)
└──────────────┘
Bevægelses-flow: Home Assistant (Reolink-integration) registrerer bevægelse → kalder N8N-webhook → N8N henter selv nyeste snapshot fra kameraets Snap-API → sender billedet til Ollama vision-model → returnerer en kort beskrivelse.
git clone https://github.com/tpbillund/sapphire-edge-ai-setup.git
cd sapphire-edge-ai-setup
cp .env.example .env
nano .env # udfyld SSH-nøgle, Reolink-IP/login, m.m.
chmod +x *.sh
sudo ./setup-all.sh # kører alle trin; spørger ja/nej for hver stackUnder trin 03 bliver du spurgt for hver stack (N8N, Home Assistant, Deepstack,
Frigate) om den skal sættes op. Svar ja/nej. Vil du svare på forhånd, så sæt
DEPLOY_N8N=1/0 osv. i .env.
Kør enkelttrin i stedet:
sudo ./setup-all.sh 02 03 # kun Ollama + stacks
# eller direkte:
sudo ./00-system-update.shGenstart efter trin 00 (ny kernel/firmware) før du fortsætter.
| Script | Funktion |
|---|---|
00-system-update.sh |
apt full-upgrade, firmware via fwupd/LVFS, Mesa/Vulkan-drivere, verificerer amdgpu + Vulkan, server-tuning (tuned, performance-governor, sleep fra), zram. |
01-docker.sh |
Docker Engine + Compose v2, log-rotation, bruger i docker-gruppen, verificerer at Docker virker og opretter stack-mappen ~/Docker-Stacks. |
02-ollama.sh |
Ollama på værten, systemd-override (host-binding + Vulkan + keep-alive), henter tool-/coder-/embed-/vision-modeller, firewall. |
03-stack.sh |
Valgfrit — spørger ja/nej for hver stack (N8N, Home Assistant, Deepstack, Frigate) og lægger hver i sin egen mappe under ~/Docker-Stacks. |
04-ssh.sh |
OpenSSH-server, nøgle-installation, hærdning, ufw + fail2ban. |
05-housekeeping.sh |
journald-loft (500 MB / 10 dage), installerer cleanup.sh som daglig systemd-timer. |
cleanup.sh |
Selve oprydningen (kaldes af timeren, kan også køres manuelt). |
01-docker.sh opretter ~/Docker-Stacks/ (fx /home/sysadmin/Docker-Stacks).
Hver stack får sin egen undermappe med sin egen docker-compose.yml, .env og data:
~/Docker-Stacks/
├── n8n/ docker-compose.yml .env data/
├── homeassistant/ docker-compose.yml .env config/
├── deepstack/ docker-compose.yml .env datastore/
└── frigate/ docker-compose.yml .env config.yml media/
03-stack.sh spørger ja/nej for hver og kopierer skabelonen fra repoets stacks/-mappe
ind i din ~/Docker-Stacks/<navn>/. Du kan også bare oprette dine egne mapper her i
hånden og lægge en docker-compose.yml i hver — strukturen er din. I .env kan du sætte
DEPLOY_N8N=1/0 osv. for at svare på forhånd, og DOCKER_STACKS_DIR for at vælge en
anden placering.
Tre ting kan fylde SSD'en — de håndteres hver for sig:
| Kilde | Hvordan det styres |
|---|---|
| Logs (system + docker) | 05-housekeeping.sh: journald-loft + daglig cleanup.sh der fjerner logs/docker-skrald ældre end 10 dage. Docker-logs er desuden størrelses-roteret (30 MB/container). |
| Frigate-optagelser | IKKE et log-problem — sættes med record.retain.days i ~/Docker-Stacks/frigate/config.yml. Cache lægges på tmpfs (RAM), så den ikke sliter på SSD'en. |
| AI-modeller | Vokser ikke af sig selv (kun ved ollama pull). cleanup.sh rapporterer størrelser men sletter aldrig. Fjern ubrugte med ollama rm <navn>. |
Manuel kørsel:
sudo /usr/local/sbin/edge-cleanup.sh # ryd op nu
sudo DRY_RUN=1 /usr/local/sbin/edge-cleanup.sh # vis kun hvad der ville skeHvad cleanup.sh aldrig rører: dine stack-mapper og deres data
(~/Docker-Stacks/*), Ollama-modeller, og tagged/brugte images.
Klargøres af 03-stack.sh i hver sin mappe. Deepstack starter med det samme;
Frigate kræver din kamera-config først:
nano ~/Docker-Stacks/frigate/config.yml # indsæt din RTSP-URL + ret retention
cd ~/Docker-Stacks/frigate && docker compose up -dCoral USB er sat op som edgetpu-detektor med /dev/bus/usb mappet ind, og
AMD-iGPU'en bruges til video-decode via VAAPI. Frigate-UI: http://<ip>:8971.
Nogle ting kan ikke scriptes (de bruger Home Assistants config-flow i browseren):
-
Reolink i Home Assistant
http://<ip>:8123→ Indstillinger → Enheder & tjenester → Tilføj integration → Reolink → IP + bruger/kode. Find dit motion-sensor-navn under Udviklerværktøjer → Tilstande og opdatérbinary_sensor.reolink_motioni~/Docker-Stacks/homeassistant/config/configuration.snippet.yaml. -
Ollama i Home Assistant (valgfrit — til tale/Assist) Tilføj integration → Ollama → URL
http://localhost:11434→ vælg model. -
Indsæt HA-snippet'en fra
~/Docker-Stacks/homeassistant/config/configuration.snippet.yamli~/Docker-Stacks/homeassistant/config/configuration.yamlog genstart HA. -
Importér N8N-workflow
http://<ip>:5678→ opret ejer-konto → Import from File →n8n-workflows/reolink-motion-workflow.json→ Aktivér den.
Test hele kæden: udløs bevægelse foran kameraet, og se eksekveringen i N8N.
Denne maskine har ingen separat VRAM; alt kører fra system-RAM. Derfor er MoE-modeller (Mixture-of-Experts) ideelle: de har mange parametre for kvalitet, men aktiverer kun få pr. token, så de er hurtige selv uden et stærkt GPU.
| Opgave | Anbefalet model | Hvorfor |
|---|---|---|
| Tools / N8N-agent + generelt | gpt-oss:20b |
MoE (~3.6B aktive), Apache 2.0, meget stabil tool-calling. Bedste alrounder her. |
| HTML / kodning | qwen2.5-coder:14b |
Stadig bedst til kode/FIM på alle størrelser. |
| Bedste lokale kvalitet (valgfrit) | qwen3.6:35b-a3b |
MoE 35B total / 3B aktive — nær-toptekst i ~RAM-fart. Fylder ~20 GB. Tjek tag på ollama.com. |
| Vision (kamerabeskrivelse) | qwen2.5vl:7b |
Beskriver snapshots i N8N-flowet. |
| Embedding (RAG i N8N) | nomic-embed-text |
Standard til vector-søgning. |
Det vil jeg ikke pakke ind: ingen lokal model på denne hardware kommer i nærheden af
Opus 4.8. Frontier-cloud-modeller er hundredvis af gange større og kører på store
GPU-klynger. Det bedste du realistisk kan køre her (gpt-oss:20b / qwen3.6:35b-a3b)
svarer nogenlunde til hvad cloud-assistenter kunne for ca. et år siden — godt nok til
HTML, scripts og N8N-tool-logik, men et tydeligt niveau under frontier, og i moderat
tempo (forvent få til ~10–15 tokens/sek afhængigt af model). Hvis du har brug for
Opus-niveau til en konkret opgave, er den rigtige løsning at kombinere: lokal model
til det meste + et cloud-API til de sværeste 20%. Men 100% lokalt og gratis: ovenstående
er det bedste valg lige nu.
Vigtig afklaring: modellen pinger ikke selv. I N8N's AI-Agent-node giver du modellen
et sæt værktøjer (fx en Execute Command-node der kører ping, eller en HTTP-node).
Modellens job er at beslutte hvilket værktøj den skal kalde og med hvilke argumenter —
selve ping'en udføres af N8N. Derfor er det vigtigste ved modelvalget her pålidelig
tool-calling, og det er præcis hvad gpt-oss:20b og Qwen-modellerne er stærke til.
Standardværdierne i .env er sat efter ovenstående.
journalctl -u ollama -e # Ollama-log (se Vulkan/GPU-linjer)
vulkaninfo --summary | grep Radeon # bekræft iGPU ses
docker ps # alle kørende containere
cd ~/Docker-Stacks/homeassistant && docker compose logs -f
amdgpu-top # live iGPU-forbrugDet er uden for denne opsætning, men stikordene er: AMD Ryzen AI Software /
Lemonade Server + ONNX-modeller + amdxdna-driveren i kernel 7.0. Det giver
en OpenAI-kompatibel endpoint som N8N kan kalde — men det er en separat stak end
Ollama og er stadig under udvikling på Linux.
Repoet indeholder de filer GitHub forventer:
| Fil | Formål |
|---|---|
README.md |
Dokumentationen (denne fil). |
LICENSE |
MIT-licens — husk at skrive dit navn i stedet for <DIT NAVN>. |
.gitignore |
Holder hemmeligheder ude af git — især .env (SSH-nøgle, kameralogin osv.). |
.gitattributes |
Tvinger Unix-linjeskift (LF), så scripts ikke går i stykker på Windows. |
.env.example |
Skabelon — denne committes; din rigtige .env gør ikke. |
cd sapphire-edge-ai-setup
git init
git add .
git status # tjek at .env IKKE er på listen (kun .env.example)
git commit -m "Initial commit: Sapphire Edge AI opsætning"
git branch -M main
git remote add origin https://github.com/tpbillund/sapphire-edge-ai-setup.git
git push -u origin mainVigtigt: opret aldrig din rigtige
.envfør.gitignoreer på plads, og kørgit statusfør dit første commit for at bekræfte at.envikke er med. Skulle en hemmelighed alligevel være blevet committet, skal den betragtes som kompromitteret — skift kode/nøgle, ikke bare slet filen.