Files

2569 lines
56 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Single source of truth for the homelab">
<link rel="canonical" href="http://192.168.1.8:13080/ideas/stack-ideas/">
<link rel="prev" href="../../security/transcripts/audit-chat-2026-05-21/">
<link rel="next" href="../../history/traefik-migration/">
<link rel="icon" href="../../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.6">
<title>Stack ideas - nuclide.systems docs</title>
<link rel="stylesheet" href="../../assets/stylesheets/main.484c7ddc.min.css">
<link rel="stylesheet" href="../../assets/stylesheets/palette.ab4e12ef.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="blue">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#stack-ideas-improvements" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../.." title="nuclide.systems docs" class="md-header__button md-logo" aria-label="nuclide.systems docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
nuclide.systems docs
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Stack ideas
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="blue" aria-hidden="true" type="radio" name="__palette" id="__palette_0">
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="blue" aria-hidden="true" type="radio" name="__palette" id="__palette_1">
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../.." class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../../CHANGELOG/" class="md-tabs__link">
Changelog
</a>
</li>
<li class="md-tabs__item">
<a href="../../RESUME/" class="md-tabs__link">
Resume
</a>
</li>
<li class="md-tabs__item">
<a href="../../ct-inventory/" class="md-tabs__link">
CT inventory
</a>
</li>
<li class="md-tabs__item">
<a href="../../infra/proxmox-state/" class="md-tabs__link">
Infra
</a>
</li>
<li class="md-tabs__item">
<a href="../../services/homelab-architecture/" class="md-tabs__link">
Services
</a>
</li>
<li class="md-tabs__item">
<a href="../../security/data-leak-audit-comparison/" class="md-tabs__link">
Security & audits
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
Ideas
</a>
</li>
<li class="md-tabs__item">
<a href="../../history/traefik-migration/" class="md-tabs__link">
History
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../.." title="nuclide.systems docs" class="md-nav__button md-logo" aria-label="nuclide.systems docs" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
</a>
nuclide.systems docs
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../.." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../CHANGELOG/" class="md-nav__link">
<span class="md-ellipsis">
Changelog
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../RESUME/" class="md-nav__link">
<span class="md-ellipsis">
Resume
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../ct-inventory/" class="md-nav__link">
<span class="md-ellipsis">
CT inventory
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Infra
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Infra
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../infra/proxmox-state/" class="md-nav__link">
<span class="md-ellipsis">
Proxmox state
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../infra/portmap/" class="md-nav__link">
<span class="md-ellipsis">
Port map
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../infra/storage/" class="md-nav__link">
<span class="md-ellipsis">
Storage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../infra/volumes/" class="md-nav__link">
<span class="md-ellipsis">
Volumes
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../infra/docker-networks/" class="md-nav__link">
<span class="md-ellipsis">
Docker networks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../infra/connection-hosts/" class="md-nav__link">
<span class="md-ellipsis">
Connection hosts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../infra/proxmox-memory-audit/" class="md-nav__link">
<span class="md-ellipsis">
Memory audit
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
<span class="md-ellipsis">
Services
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
Services
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../services/homelab-architecture/" class="md-nav__link">
<span class="md-ellipsis">
Homelab architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/dev-environment/" class="md-nav__link">
<span class="md-ellipsis">
Dev environment (Coder + Gitea)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/mcp-gateway/" class="md-nav__link">
<span class="md-ellipsis">
MCP gateway
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/mcp-servers/" class="md-nav__link">
<span class="md-ellipsis">
MCP servers
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/pocket-id/" class="md-nav__link">
<span class="md-ellipsis">
Pocket-ID (OIDC)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/backrest/" class="md-nav__link">
<span class="md-ellipsis">
Backrest (backups)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/databases/" class="md-nav__link">
<span class="md-ellipsis">
Databases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/secrets-manager/" class="md-nav__link">
<span class="md-ellipsis">
Secrets manager
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/comfyui/" class="md-nav__link">
<span class="md-ellipsis">
ComfyUI
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/zoraxy/" class="md-nav__link">
<span class="md-ellipsis">
Zoraxy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/adguard-dns/" class="md-nav__link">
<span class="md-ellipsis">
AdGuard DNS
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/cloud-gpu/" class="md-nav__link">
<span class="md-ellipsis">
Cloud GPU
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/arcane/" class="md-nav__link">
<span class="md-ellipsis">
Arcane
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/doc-ingestion/" class="md-nav__link">
<span class="md-ellipsis">
Doc ingestion pipeline
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../services/llm-benchmark/" class="md-nav__link">
<span class="md-ellipsis">
LLM benchmark
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7" >
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="0">
<span class="md-ellipsis">
Security & audits
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Security & audits
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../security/data-leak-audit-comparison/" class="md-nav__link">
<span class="md-ellipsis">
Comparison
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../security/data-leak-audit-2026-05-20-tr004-cloud-sandbox/" class="md-nav__link">
<span class="md-ellipsis">
2026-05-20 · cloud-sandbox breach
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../security/data-leak-audit-2026-05-21-tr004-artifacts/" class="md-nav__link">
<span class="md-ellipsis">
2026-05-21 · artifacts (clean)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../security/audit-claude-code-meta/" class="md-nav__link">
<span class="md-ellipsis">
Self-audit (Claude Code)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../security/transcripts/audit-chat-2026-05-21/" class="md-nav__link">
<span class="md-ellipsis">
Transcript (audit session)
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" checked>
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="">
<span class="md-ellipsis">
Ideas
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Ideas
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Stack ideas
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Stack ideas
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1-document-ingestion-lobechat-knowledge-base-mcp" class="md-nav__link">
<span class="md-ellipsis">
1. Document ingestion → LobeChat knowledge base + MCP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#2-document-conversion-pipeline" class="md-nav__link">
<span class="md-ellipsis">
2. Document conversion pipeline
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#3-on-device-llm-arc-igpu" class="md-nav__link">
<span class="md-ellipsis">
3. On-device LLM (Arc iGPU)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#4-arcane-agents-on-nuc-central-instance-on-proxmox-lxc" class="md-nav__link">
<span class="md-ellipsis">
4. Arcane agents on NUC (central instance on Proxmox LXC)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#5-ai-memory-personalization" class="md-nav__link">
<span class="md-ellipsis">
5. AI memory / personalization
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#6-workflow-automation-upgrades" class="md-nav__link">
<span class="md-ellipsis">
6. Workflow / automation upgrades
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#7-external-services-worth-considering" class="md-nav__link">
<span class="md-ellipsis">
7. External services worth considering
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#8-observability-on-proxmox-lxc-alongside-arcane" class="md-nav__link">
<span class="md-ellipsis">
8. Observability (on Proxmox LXC, alongside Arcane)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#9-storage-s3-improvements" class="md-nav__link">
<span class="md-ellipsis">
9. Storage / S3 improvements
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#9-comfyui-mcp-async-queue-image-to-image-reference" class="md-nav__link">
<span class="md-ellipsis">
9. ComfyUI MCP — async queue + image-to-image + reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#10-litellm-custom-provider-lobechat-provider-extension" class="md-nav__link">
<span class="md-ellipsis">
10. LiteLLM custom provider / LobeChat provider extension
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#11-dependency-updates-via-renovate-bot-gitea-actions" class="md-nav__link">
<span class="md-ellipsis">
11. Dependency updates via Renovate Bot (Gitea Actions)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#12-egress-firewall-on-udm-unifi" class="md-nav__link">
<span class="md-ellipsis">
12. Egress firewall on UDM (UniFi)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#13-local-llm-on-arc-gpu-via-vllm-ollama-for-sensitive-workloads" class="md-nav__link">
<span class="md-ellipsis">
13. Local LLM on Arc GPU via vllm / ollama for sensitive workloads
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#priority-order-rough" class="md-nav__link">
<span class="md-ellipsis">
Priority order (rough)
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_9" >
<label class="md-nav__link" for="__nav_9" id="__nav_9_label" tabindex="0">
<span class="md-ellipsis">
History
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_9">
<span class="md-nav__icon md-icon"></span>
History
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../history/traefik-migration/" class="md-nav__link">
<span class="md-ellipsis">
Traefik (abandoned 2026-05-16)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../history/traefik-migration-docker-labels/" class="md-nav__link">
<span class="md-ellipsis">
Traefik labels (abandoned)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../history/mcp-gateway-requirements/" class="md-nav__link">
<span class="md-ellipsis">
MCP gateway requirements (superseded)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../history/scrubbing-list-2026-05-17/" class="md-nav__link">
<span class="md-ellipsis">
Scrubbing list (2026-05-17)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../history/case-study/" class="md-nav__link">
<span class="md-ellipsis">
Case study
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#1-document-ingestion-lobechat-knowledge-base-mcp" class="md-nav__link">
<span class="md-ellipsis">
1. Document ingestion → LobeChat knowledge base + MCP
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#2-document-conversion-pipeline" class="md-nav__link">
<span class="md-ellipsis">
2. Document conversion pipeline
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#3-on-device-llm-arc-igpu" class="md-nav__link">
<span class="md-ellipsis">
3. On-device LLM (Arc iGPU)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#4-arcane-agents-on-nuc-central-instance-on-proxmox-lxc" class="md-nav__link">
<span class="md-ellipsis">
4. Arcane agents on NUC (central instance on Proxmox LXC)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#5-ai-memory-personalization" class="md-nav__link">
<span class="md-ellipsis">
5. AI memory / personalization
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#6-workflow-automation-upgrades" class="md-nav__link">
<span class="md-ellipsis">
6. Workflow / automation upgrades
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#7-external-services-worth-considering" class="md-nav__link">
<span class="md-ellipsis">
7. External services worth considering
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#8-observability-on-proxmox-lxc-alongside-arcane" class="md-nav__link">
<span class="md-ellipsis">
8. Observability (on Proxmox LXC, alongside Arcane)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#9-storage-s3-improvements" class="md-nav__link">
<span class="md-ellipsis">
9. Storage / S3 improvements
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#9-comfyui-mcp-async-queue-image-to-image-reference" class="md-nav__link">
<span class="md-ellipsis">
9. ComfyUI MCP — async queue + image-to-image + reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#10-litellm-custom-provider-lobechat-provider-extension" class="md-nav__link">
<span class="md-ellipsis">
10. LiteLLM custom provider / LobeChat provider extension
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#11-dependency-updates-via-renovate-bot-gitea-actions" class="md-nav__link">
<span class="md-ellipsis">
11. Dependency updates via Renovate Bot (Gitea Actions)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#12-egress-firewall-on-udm-unifi" class="md-nav__link">
<span class="md-ellipsis">
12. Egress firewall on UDM (UniFi)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#13-local-llm-on-arc-gpu-via-vllm-ollama-for-sensitive-workloads" class="md-nav__link">
<span class="md-ellipsis">
13. Local LLM on Arc GPU via vllm / ollama for sensitive workloads
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#priority-order-rough" class="md-nav__link">
<span class="md-ellipsis">
Priority order (rough)
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="stack-ideas-improvements">Stack Ideas &amp; Improvements<a class="headerlink" href="#stack-ideas-improvements" title="Permanent link">&para;</a></h1>
<p>Hardware baseline: <strong>NUC 14 Pro</strong> — Intel Core Ultra (Meteor Lake), Intel Arc iGPU
(currently used for ComfyUI / XPU image gen), no NVIDIA, UNAS for media/bulk storage.</p>
<hr />
<h2 id="1-document-ingestion-lobechat-knowledge-base-mcp">1. Document ingestion → LobeChat knowledge base + MCP<a class="headerlink" href="#1-document-ingestion-lobechat-knowledge-base-mcp" title="Permanent link">&para;</a></h2>
<p><strong>Goal</strong>: ingest PDFs, Word, PPT, XLS → searchable in LobeChat chat + accessible via MCP.
Qdrant is a nice-to-have, not a requirement (no live pipeline uses it yet).</p>
<p><strong>LobeChat already has a built-in knowledge base</strong> (<code>knowledge_base_files</code>, <code>chunks</code>,
<code>embeddings</code> tables in Postgres). The missing piece is an ingest pipeline that feeds it.</p>
<p><strong>Recommended architecture</strong>:
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a>Nextcloud folder / Paperless webhook
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a> → n8n trigger (already running)
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a> → Docling (PDF/DOCX/PPTX/XLSX → Markdown + structure)
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> → LiteLLM /v1/embeddings (Mistral-embed / codestral-embed)
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> → LobeChat knowledge base API ←— available in chat natively
<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a> → Qdrant sidecar (optional, if multi-app search needed)
</code></pre></div></p>
<p><strong>Document conversion options</strong>:</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Docker image</th>
<th>Formats</th>
<th>NUC 14 CPU fit</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Docling</strong> (IBM, 2024)</td>
<td><code>ghcr.io/ds4sd/docling</code></td>
<td>PDF, DOCX, PPTX, XLSX, HTML, Markdown</td>
<td>✅ CPU-only, 10-60s/doc</td>
</tr>
<tr>
<td><strong>MinerU</strong> (OpenDataLab)</td>
<td><code>opendatalab/mineru</code></td>
<td>PDF (layout-aware, OCR)</td>
<td>✅ CPU mode; GPU optional for speed</td>
</tr>
<tr>
<td><strong>Unstructured</strong></td>
<td><code>quay.io/unstructured-io/unstructured-api</code></td>
<td>Very broad (25+ formats)</td>
<td>✅ lighter than Docling</td>
</tr>
<tr>
<td><strong>Markitdown</strong> (already in MCP gateway)</td>
<td></td>
<td>Office + PDFs → Markdown</td>
<td>✅ ad-hoc only, not batch</td>
</tr>
</tbody>
</table>
<p><strong>Docling vs MinerU</strong>: Docling is better for structured Office/PDF with tables and
figures. MinerU (OpenDataLab) is better for pure PDF optical layout analysis (e.g.,
academic papers, scanned documents). Both run on NUC 14 CPU. Start with Docling — single
container, REST API, well-documented.</p>
<p><strong>MCP access</strong>: add a <code>knowledge-search</code> MCP tool to the gateway that calls LobeChat's
knowledge base search API. Zero new infra — LobeChat is already on <code>shared_backend</code>.</p>
<p><strong>IBM Granite embedding</strong> (granite-embedding-30m-english) — good quality, tiny (30M params),
runs CPU-only. Alternative to Mistral-embed if you want fully local embeddings. Not on
LiteLLM yet but can add as a custom provider pointing at an Ollama/IPEX-LLM instance.</p>
<hr />
<h2 id="2-document-conversion-pipeline">2. Document conversion pipeline<a class="headerlink" href="#2-document-conversion-pipeline" title="Permanent link">&para;</a></h2>
<p><strong>Problem</strong>: No systematic ingestion path from raw docs (PDF, DOCX, HTML) into
structured text for chunking/embedding.</p>
<p><strong>Tools to consider</strong>:</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Docker image</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Docling</strong> (IBM, 2024)</td>
<td><code>ghcr.io/ds4sd/docling</code></td>
<td>PDFs with complex layout (tables, columns, figures); outputs Markdown</td>
</tr>
<tr>
<td><strong>Unstructured</strong></td>
<td><code>quay.io/unstructured-io/unstructured-api</code></td>
<td>Wide format support (HTML, DOCX, PPTX, images with OCR); REST API</td>
</tr>
<tr>
<td><strong>Gotenberg</strong></td>
<td><code>gotenberg/gotenberg</code></td>
<td>HTML/Office → PDF pre-processing stage; not a text extractor</td>
</tr>
<tr>
<td><strong>Apache Tika</strong></td>
<td><code>apache/tika</code></td>
<td>Broad format support; outputs plain text; lower quality than Docling for PDFs</td>
</tr>
<tr>
<td><strong>Markitdown MCP</strong></td>
<td>already in gateway</td>
<td>Ad-hoc on-demand conversion; not suitable for batch pipelines</td>
</tr>
</tbody>
</table>
<p><strong>Recommended pipeline (n8n-orchestrated)</strong>:
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a>Nextcloud / Paperless webhook
<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a> → Gotenberg (Office → PDF)
<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a> → Docling (PDF → Markdown chunks)
<a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a> → LiteLLM /v1/embeddings (Mistral-embed)
<a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a> → Qdrant upsert
</code></pre></div></p>
<p>Docling runs CPU-only comfortably on the NUC. Unstructured is heavier but has a
managed API if the self-hosted version is too slow.</p>
<p>Paperless-ngx already OCRs documents — its full-text content is accessible via the
REST API. An n8n workflow polling <code>/api/documents/?added__gt=&lt;last_run&gt;</code> can extract
and re-embed directly, without re-running OCR.</p>
<hr />
<h2 id="3-on-device-llm-arc-igpu">3. On-device LLM (Arc iGPU)<a class="headerlink" href="#3-on-device-llm-arc-igpu" title="Permanent link">&para;</a></h2>
<p>The Arc iGPU is currently ComfyUI-only. Small language models can also run on it:</p>
<ul>
<li><strong>IPEX-LLM</strong> (Intel) + <strong>Ollama</strong> — Intel provides a patched Ollama build that uses
IPEX-LLM for Arc acceleration. Supports Phi-3.5-mini, Gemma-2B, TinyLlama.
Useful as a fast/cheap fallback when Groq/Mistral rate limits hit.</li>
<li><strong>llama.cpp with Vulkan</strong> — alternative to IPEX-LLM; no Intel-specific driver,
uses Vulkan compute. Less optimised for Arc but simpler to deploy.</li>
<li><strong>Practical constraint</strong>: Arc iGPU shares system RAM; sustained LLM inference
competes with other XPU workloads (e.g., ComfyUI). A model serving config that
pauses one workload while the other runs is needed, or deploy them on separate
CPU/GPU budgets.</li>
</ul>
<p>If a second NUC or small GPU box becomes available, this becomes the primary use case.</p>
<hr />
<h2 id="4-arcane-agents-on-nuc-central-instance-on-proxmox-lxc">4. Arcane agents on NUC (central instance on Proxmox LXC)<a class="headerlink" href="#4-arcane-agents-on-nuc-central-instance-on-proxmox-lxc" title="Permanent link">&para;</a></h2>
<p>Arcane's central server moves to a <strong>Proxmox LXC</strong> (lightweight, stays responsive even
if the Docker stack has issues). The NUC and any other Docker host runs the <strong>Arcane
agent</strong> (headless worker), which connects back to the central instance.</p>
<p><strong>Deployment</strong>:
- LXC: central Arcane server + observability stack (see §8)
- NUC (<code>.40</code>) and <code>.49</code>: <code>arcane-agent</code> (headless) in compose, connects to LXC
- Arcane agents reach Docker via either:
- <strong>TCP Docker socket + TLS certs</strong> — most secure; requires cert generation per host
- <strong>SSH Docker contexts</strong> — simpler; gateway mounts socket into agent via SSH tunnel</p>
<p><strong>Observability co-located on the LXC</strong> (see §8 — lightweight, OTEL-aware stack that
survives Docker restarts).</p>
<hr />
<h2 id="5-ai-memory-personalization">5. AI memory / personalization<a class="headerlink" href="#5-ai-memory-personalization" title="Permanent link">&para;</a></h2>
<p><strong>Mem0</strong> (<code>mem0ai/mem0</code>) — persistent user memory layer that sits in front of LLM calls.
Stores facts extracted from conversations into a vector DB (Qdrant backend supported).
Can integrate with LobeChat or as an MCP tool. Lets the AI remember preferences,
past context, and user-specific facts across sessions.</p>
<p>Alternative: <strong>Letta</strong> (formerly MemGPT) — stateful agent framework with persistent
memory; more opinionated.</p>
<hr />
<h2 id="6-workflow-automation-upgrades">6. Workflow / automation upgrades<a class="headerlink" href="#6-workflow-automation-upgrades" title="Permanent link">&para;</a></h2>
<ul>
<li><strong>n8n → AI agent nodes</strong>: n8n 1.x has native AI agent nodes (LangChain under the hood).
Can build RAG, email triage, document processing workflows visually.</li>
<li><strong>Activepieces</strong> — lighter-weight n8n alternative; good for simple integrations.
Probably not worth adding since n8n is already running.</li>
<li><strong>Temporal</strong> — durable workflow engine for long-running or retry-heavy pipelines
(e.g., large document batch processing). Overkill unless pipelines become complex.</li>
</ul>
<hr />
<h2 id="7-external-services-worth-considering">7. External services worth considering<a class="headerlink" href="#7-external-services-worth-considering" title="Permanent link">&para;</a></h2>
<table>
<thead>
<tr>
<th>Service</th>
<th>Purpose</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Backblaze B2</strong></td>
<td>Off-site backup (already in todos)</td>
<td>rclone sync from Garage; restic for PG dumps</td>
</tr>
<tr>
<td><strong>Cloudflare R2</strong></td>
<td>S3-compatible CDN-backed storage</td>
<td>Free egress; good for Lobe file serving</td>
</tr>
<tr>
<td><strong>Resend</strong></td>
<td>Transactional email</td>
<td>3K/mo free; better deliverability than self-hosted Postal</td>
</tr>
<tr>
<td><strong>ntfy.sh (cloud)</strong></td>
<td>Push notifications fallback</td>
<td>Already running self-hosted ntfy; cloud as relay</td>
</tr>
<tr>
<td><strong>Cloudflare Turnstile</strong></td>
<td>Bot protection for public endpoints</td>
<td>Free; no JS challenge</td>
</tr>
<tr>
<td><strong>Novu</strong></td>
<td>Notification orchestration</td>
<td>Multi-channel (email, push, Slack); self-hostable</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="8-observability-on-proxmox-lxc-alongside-arcane">8. Observability (on Proxmox LXC, alongside Arcane)<a class="headerlink" href="#8-observability-on-proxmox-lxc-alongside-arcane" title="Permanent link">&para;</a></h2>
<p><strong>Runs on the LXC, not the NUC</strong> — stays alive if the Docker stack misbehaves. Lightweight
enough for a 2 vCPU / 4GB LXC.</p>
<p><strong>Recommended stack</strong> (all OTEL-aware, compose-based):</p>
<table>
<thead>
<tr>
<th>Component</th>
<th>Image</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>OpenTelemetry Collector</strong></td>
<td><code>otel/opentelemetry-collector-contrib</code></td>
<td>Receives traces/metrics/logs from all services (OTLP gRPC+HTTP); fans out to backends</td>
</tr>
<tr>
<td><strong>VictoriaMetrics</strong></td>
<td><code>victoriametrics/victoria-metrics</code></td>
<td>Prometheus-compatible TSDB; scrapes NUC exporters + receives from OTEL collector; lighter than Prometheus</td>
</tr>
<tr>
<td><strong>Grafana</strong></td>
<td><code>grafana/grafana</code></td>
<td>Dashboards; datasource = VictoriaMetrics + Loki</td>
</tr>
<tr>
<td><strong>Loki</strong></td>
<td><code>grafana/loki</code></td>
<td>Log aggregation; receives from OTEL collector</td>
</tr>
<tr>
<td><strong>Uptime Kuma</strong></td>
<td><code>louislam/uptime-kuma</code></td>
<td>HTTP/TCP uptime checks for all public endpoints; alerts via ntfy</td>
</tr>
</tbody>
</table>
<p><strong>OTEL receivers</strong> from the NUC Docker stack:
- <strong>LiteLLM</strong>: native OTEL export — traces every LLM call with token counts, model, latency
- <strong>n8n</strong>: Prometheus <code>/metrics</code> endpoint
- <strong>Garage</strong>: Prometheus <code>/metrics</code>
- <strong>mcp-gateway</strong>: add <code>opentelemetry-sdk</code> instrumentation to <code>server.py</code>
- <strong>Docker host</strong>: <code>node_exporter</code> + <code>cadvisor</code> on the NUC, scraped by VictoriaMetrics</p>
<p><strong>NUC → LXC connectivity</strong>: Both are on the same LAN. OTEL collector listens on the LXC's
LAN IP (e.g., <code>192.168.1.X:4317</code> gRPC). Services push OTEL directly to it; Prometheus
pull-scraping from VictoriaMetrics goes to NUC exporters over LAN.</p>
<hr />
<h2 id="9-storage-s3-improvements">9. Storage / S3 improvements<a class="headerlink" href="#9-storage-s3-improvements" title="Permanent link">&para;</a></h2>
<ul>
<li><strong>Garage external S3</strong> is currently non-responsive (tracked in todos). Fix or
replace with <strong>MinIO</strong> (single-node, much better tooling/UI, easy migration).</li>
<li><strong>Lobe file serving via Cloudflare R2</strong>: Lobe uploads to Garage → sync to R2 →
serve from CDN. Reduces NUC egress for image-heavy sessions.</li>
<li><strong>Qdrant data on UNAS</strong>: Mount <code>qdrant_data</code> from NAS for persistence across
container re-creates (same pattern as arr-stack).</li>
</ul>
<hr />
<h2 id="9-comfyui-mcp-async-queue-image-to-image-reference">9. ComfyUI MCP — async queue + image-to-image + reference<a class="headerlink" href="#9-comfyui-mcp-async-queue-image-to-image-reference" title="Permanent link">&para;</a></h2>
<p><strong>Current problem</strong>: MCP tool blocks until the image is done (~90-290s). LLMs time out at ~60s.
The fix is a job-queue pattern:</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>generate_image(prompt) → returns {job_id, status: &quot;queued&quot;} immediately
<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>get_image_status(job_id) → returns {status, progress, image_url_when_done}
<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a>list_queue() → shows all pending/running jobs
<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a>cancel_job(job_id) → cancels a queued job (confirms with user first)
</code></pre></div>
<p>ComfyUI's own API is already async (<code>POST /prompt</code> → poll <code>/history/{id}</code>). The MCP server
just needs to expose this model instead of blocking.</p>
<p><strong>Image-to-image</strong>: new workflow <code>flux-schnell-img2img-api.json</code>. Takes an init image URL +
denoise strength. ComfyUI <code>LoadImageFromURL</code> node (or upload + <code>LoadImage</code>).</p>
<p><strong>Reference tool</strong>: <code>list_previous_images(n=5)</code> — queries ComfyUI <code>/history</code> API,
returns recent job thumbnails + prompts. User can pick one to reference or iterate from.</p>
<p><strong>Delivery to S3/Garage</strong>: on completion, upload output PNG to Garage <code>comfyui-outputs</code> bucket
→ return a permanent URL. Avoids ComfyUI's ephemeral <code>/view</code> endpoint.</p>
<hr />
<h2 id="10-litellm-custom-provider-lobechat-provider-extension">10. LiteLLM custom provider / LobeChat provider extension<a class="headerlink" href="#10-litellm-custom-provider-lobechat-provider-extension" title="Permanent link">&para;</a></h2>
<p><strong>Question</strong>: build an adapter in LiteLLM to use models via "quasi API" (non-standard
endpoints, auth, or routing)?</p>
<p><strong>LiteLLM supports custom providers</strong> via <code>custom_llm_provider</code> in config.yaml. You write
a Python class that implements <code>completion()</code> and <code>async_completion()</code>. This is the right
path for wrapping non-standard APIs (local models, proprietary endpoints, protocol bridges).</p>
<p>Example use cases:
- Wrap a Claude Max subscription via Anthropic's API (different billing model)
- Add a local model served by IPEX-LLM on the Arc iGPU
- Bridge a custom inference server that speaks a different protocol</p>
<p><strong>LobeChat provider extension</strong>: LobeChat's provider list is compiled into the app.
Adding a new provider requires rebuilding LobeChat from source (fork + add to
<code>src/config/aiModels/</code>). High effort; only worth it for a permanent/long-term provider.
For ad-hoc needs, use LiteLLM as the adapter and point LobeChat at it via the existing
<code>ai.nuclide.systems</code> OpenAI-compatible endpoint.</p>
<hr />
<h2 id="11-dependency-updates-via-renovate-bot-gitea-actions">11. Dependency updates via Renovate Bot (Gitea Actions)<a class="headerlink" href="#11-dependency-updates-via-renovate-bot-gitea-actions" title="Permanent link">&para;</a></h2>
<p>Run <strong>Renovate Bot</strong> as a Gitea Actions workflow to automatically open PRs for outdated
dependencies in MCP server repos (<code>mcp-comfyui</code>, <code>mcp-docling</code>, <code>mcp-shepard</code>,
<code>mcp-upload-artifact</code>). Targets: <code>Dockerfile</code> base image tags + <code>requirements.txt</code> /
<code>pyproject.toml</code> Python deps.</p>
<p>Renovate supports Gitea natively via <code>platform: gitea</code> in <code>renovate.json</code>. The Gitea
Actions runner (<code>ct111-runner</code>) already exists; add a scheduled workflow calling
<code>renovate/renovate</code> Docker image once daily.</p>
<hr />
<h2 id="12-egress-firewall-on-udm-unifi">12. Egress firewall on UDM (UniFi)<a class="headerlink" href="#12-egress-firewall-on-udm-unifi" title="Permanent link">&para;</a></h2>
<p>Enforce outbound allow-list on the UDM / UniFi gateway — block all non-approved egress
by default. Goals:
- Prevent exfiltration from compromised containers
- Audit unexpected outbound connections (model providers, analytics, telemetry)
- Approved: LiteLLM model provider endpoints, Jottacloud, UNAS internal, NTP, DNS</p>
<p>Implementation: UDM firewall rules (WAN_OUT) + Threat Management IDS in monitor mode first.</p>
<hr />
<h2 id="13-local-llm-on-arc-gpu-via-vllm-ollama-for-sensitive-workloads">13. Local LLM on Arc GPU via vllm / ollama for sensitive workloads<a class="headerlink" href="#13-local-llm-on-arc-gpu-via-vllm-ollama-for-sensitive-workloads" title="Permanent link">&para;</a></h2>
<p>Run a privacy-sensitive LLM locally on the Arc iGPU using <strong>vllm</strong> (with XPU/IPEX backend)
or the Intel-patched <strong>Ollama</strong> build. Use cases: document classification in Paperless
workflows, offline coding assistant, fallback when cloud rate limits hit.</p>
<p>See §3 (On-device LLM) for implementation notes. This item tracks the specific motivation
of <em>sensitive workload isolation</em> — i.e., running prompts that should not leave the LAN.</p>
<hr />
<h2 id="priority-order-rough">Priority order (rough)<a class="headerlink" href="#priority-order-rough" title="Permanent link">&para;</a></h2>
<ol>
<li><strong>ComfyUI MCP async queue</strong> — fixes timeout; unblocks img2img + reference features</li>
<li><strong>Docling container + n8n ingest pipeline</strong> — Nextcloud/Paperless → LobeChat knowledge base</li>
<li><strong>Arcane LXC + agents on NUC</strong> — when ready to migrate</li>
<li><strong>Observability LXC</strong> — OTEL collector + VictoriaMetrics + Grafana + Uptime Kuma, co-located</li>
<li><strong>Backblaze B2 off-site backup</strong> — already in todos</li>
<li><strong>On-device LLM (Arc)</strong> — depends on IPEX-LLM + Ollama Intel build stability</li>
<li><strong>Renovate Bot</strong> — low-effort automation win for MCP repos</li>
<li><strong>Egress firewall</strong> — security hygiene; plan before adding more external-facing services</li>
</ol>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"annotate": null, "base": "../..", "features": ["navigation.tabs", "navigation.sections", "navigation.expand", "navigation.top", "search.highlight", "search.suggest", "content.code.copy"], "search": "../../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../../assets/javascripts/bundle.79ae519e.min.js"></script>
</body>
</html>