# My Homelab Is Technically the Cloud Now
**作者**: Ahmad
**日期**: 2026-05-01T03:57:34.000Z
**来源**: [https://x.com/TheAhmadOsman/status/2050062045471740303](https://x.com/TheAhmadOsman/status/2050062045471740303)
---

Someone asked me recently if I’d duplicated my local homelab into the cloud.
Not really. The more accurate answer is that I’ve built enough cloud-like infrastructure around the homelab that it now behaves like a small private cloud. Same local machines, same Proxmox nodes, same hardware, but the operating model is completely different.
Instead of a pile of dashboards, random ports, one-off VMs, and manual SSH sessions, the lab is organized around access layers, gateways, routing policy, searchable state, and compute lanes. That’s the difference between “I run some services at home” and “I have a private control plane for my own infrastructure.” Right now that control plane spans more than several dozen active Proxmox guests, LXC containers plus a handful of VMs, with workstations and dedicated LAN model appliances joining the fabric where they make sense.
This article explains the general shape of that system without publishing my real hostnames, IPs, service names, container IDs, domains, or secrets.
## How This Article Builds
This starts with the high-level idea, then walks downward through each layer until the whole private-cloud operating model is visible.
1. High-level claim: why this is still local hardware, but no longer feels like a pile of one-off homelab services.
2. Redaction model: what is real, what is anonymized, and what stays private.
3. Big picture: the full platform shape from offsite clients to VPN, DNS, service gateway, agents, state, compute, and backups.
4. Physical substrate: the Proxmox, container, VM, storage, and rollback foundation.
5. Access path: WireGuard, split/full tunnel modes, SNAT, DNS/DHCP, and firewall/ACL policy.
6. Application edge: the gateway, public/private routes, stable front doors, and human-facing apps.
7. Agent platform: model routing, generated client profiles, skill workflows, and web evidence tooling.
8. State and recovery: traces, searchable memory, app backups, parity checks, health checks, and restore drills.
9. Compute fabric: CPU lanes, GPU lanes, LAN model appliances, work placement, artifacts, and logs.
10. Synthesis: how the paths connect, why this is more than a reverse proxy, and the lesson worth copying.
## The Redaction Model
This is a public article, and it’s intentionally anonymized. The names here are role names, not my real inventory names. Product names are included only where they explain the pattern; inventory labels, addresses, domains, account names, and route names are not.

The architecture is true to the system. The identifiers are not.
## The Big Picture
The diagram I posted was meant to show the topology, not a single product.
At the top are offsite clients: laptop, phone, tablet. They enter through a WireGuard tunnel that lands on a VPN concentrator. From there traffic passes through firewall/NAT policy, private DNS/DHCP, and then into an internal service gateway.
Below that gateway are the useful planes:
- an agent and automation plane
- human-facing app surfaces
- a searchable state plane
- a compute fabric
- supporting web/evidence tools
- storage, backups, health checks, and restore workflows

That last line is the whole point.
The laptop isn’t the whole system. The phone isn’t the whole system. The browser UI isn’t the whole system. They’re clients of a private platform.
## The Physical Layer: Proxmox As The Substrate
At the foundation it’s still a normal homelab: local hardware, virtualization, containers, storage, and a LAN. In my case the Proxmox box is a workstation-class node with a couple dozen logical CPU threads, roughly 100 GiB of RAM, a few TiB of LVM-thin guest storage, and a separate pool of half a dozen spinning-rust drives merged with MergerFS and covered by SnapRAID parity. Bulk data lives on the pool; guest root disks live on LVM-thin. NFS exports make the bulk storage available to other LAN machines that need it.
I use Proxmox as the main substrate because it gives me clean operational boundaries:
- lightweight containers for narrow services
- VMs for heavier workloads or stronger isolation
- snapshots before risky changes
- direct console access when networking is broken
- storage attachment for stateful services
- a place to separate failure domains
So my answer to “should I ditch Proxmox?” is no.
Proxmox isn’t the cloud by itself; it’s the substrate. The cloud-like part is what sits above it: names, routes, gateways, tokens, generated configs, health checks, traces, backups, and job placement.
You can build this style of system on other substrates too. The important thing is that the substrate stays boring. It should run the workloads and give you rollback points. It shouldn’t be the only layer of organization.
## The Network Entry Point: WireGuard
The first real control point is the VPN edge.
When I’m away from home, I don’t want every internal tool exposed to the public internet. My laptop, phone, and tablet connect to a WireGuard endpoint that lands on a small VPN concentrator inside the homelab.
The concentrator owns peer identity, VPN address assignment, split-tunnel and full-tunnel profiles, the route between VPN clients and the LAN, and NAT behavior for traffic crossing that boundary. In my setup it’s an LXC container running WireGuard with a small dashboard for managing peers, not a heavyweight VPN appliance.
The public endpoint for remote access is just the door. The useful system starts after the handshake succeeds.
There are two main client modes, and I provision both configs per device. Then I pick which one to activate depending on where I am.
Split Tunnel vs Full Tunnel

In the real setup I also care about IPv4 and IPv6 behavior. The tunnel itself runs dual-stack internally: each peer gets both an IPv4 address and an IPv6 ULA address. But the public endpoint that devices connect to is kept IPv4-only by design, with client tooling that pins the A record if DNS drifts, because I’ve seen mobile carriers block WireGuard UDP over IPv6.
## Why SNAT Matters
Because I want to maintain the same IP Address / Identity while on VPN or at home.
SNAT means Source Network Address Translation.
The practical problem is simple: a VPN client has an address from the VPN network, while most LAN services expect traffic from the LAN. You could teach every LAN host a route back to every VPN subnet. That works, but it spreads VPN awareness everywhere.
Instead, the VPN edge translates the source address when traffic crosses from the VPN into the LAN. In my setup this goes a step further than simple MASQUERADE: each VPN peer gets mapped to its own stable LAN-side identity instead of a shared edge address. That way the LAN can still tell which physical device made the request, even through the tunnel, which helps logging and per-device policy without teaching every LAN host a route back to the VPN subnet.

That last point matters. SNAT isn’t a security model by itself. WireGuard handles encryption. Peer keys handle tunnel identity. Firewall rules and ACLs handle policy. DNS handles names. SNAT just solves the address translation problem so your devices identities are preserved locally and on VPN.
## Private DNS And DHCP: The Lab Needs Names
Once clients can enter the network, they need stable names.
This is where private DNS and DHCP become more important than people expect. Without them, every dashboard turns into “which IP was that again?” Every script gets a hard-coded address. Every migration becomes annoying. I run Pi-hole as the LAN DNS/DHCP control point. Ad blocking is a bonus; the real value is that there is one place where internal services get stable names.
In my setup, internal names represent roles:

The useful pattern is that clients depend on role names, not machine trivia. If a backend moves from one container to another, the name can stay stable. If a service gets rebuilt, clients shouldn’t need to care. If a health check runs, it targets the role.
Private DNS also ties the VPN back into the rest of the system. A remote phone or laptop on the tunnel can resolve the same private names the LAN uses. That’s what makes remote access feel native instead of bolted on.
## Firewall And ACL Policy
The firewall layer decides what the VPN clients, LAN clients, service gateways, and internal tools are allowed to reach.
In my setup, Proxmox-level firewalling is not the primary isolation layer. Most access control is enforced by the service gateway, the agent router’s token boundary, and the fact that most services simply don’t have public routes. The network boundary is real, but policy lives at the application and routing layers more than at the packet filter.
I don’t want every internal service to be equally reachable from every place. Some things are public-facing web apps behind the CDN. Some are LAN-only dashboards. Some are only for automation. Some are loopback-only behind a proxy. Some should accept traffic only from the model router or the evidence gateway.
That turns the network into role-based paths:

The important part is that the boundaries are explicit. A service being on the LAN doesn’t automatically mean it should be a public API.
## The Internal Service Gateway
After access, DNS, and firewalling, the next big piece is the internal service gateway.
Think of it as the homelab’s application edge. Some traffic is private-only. Some traffic is public. Some public traffic arrives through an upstream CDN or DNS proxy. Some traffic comes directly from the LAN. The gateway normalizes those paths and forwards to the correct backend. In my case this is Caddy running on its own VM, handling TLS termination, DNS-validated certificates through an upstream DNS provider, and the public/private route split.

The backend can move. The container can restart. The VM can be rebuilt. The client still speaks to the same front door.
For public-facing services, I also care about real client IP handling. If a request comes through an upstream proxy, the gateway should trust the right header only when it came from the right place, strip spoofed forwarded headers, and rebuild what the upstream app needs. That keeps logs and rate limits useful without letting random clients forge their identity.
## Human Apps: Dashboards, Chat, Search, And Workspaces
Above the gateway are the things I actually use:
- a homepage dashboard with system metrics
- a chat UI backed by an open-source frontend
- a dedicated RAG-style web interface for document search and retrieval
- an AI workspace UI with session management, provider switching, and skills
- operational status pages and admin tools
The important detail is that these aren’t all allowed to talk directly to everything.
For example, a human-facing RAG or chat UI shouldn’t need raw access to every model provider credential, browser automation port, embedding worker, reranker, database, and trace store. It should call narrower internal routes:

That makes the UI a client of the platform instead of a giant trusted everything-box.
This boundary isn’t just aspirational; I maintain an explicit cross-service standard that defines what each container in the agent plane is allowed to reach. The RAG UI must route model traffic through the router, document search through the router’s RAG endpoints, and web search through the search backend. It must not have direct access to the vector database, the embedding workers, the reranker, the browser automation ports, or the raw evidence cache. The chat UI, the workspace UI, and the skill dashboard each have their own allowlists. If a service needs a new internal route, it goes through a boundary review, not a quick firewall exception.
## The Agent And Automation Plane
The agent plane is the part that surprised people most.
I run a lot of AI and automation tooling, but I don’t want each tool to carry a different hand-written provider configuration. That becomes impossible to audit once you have terminal agents, editor integrations, web UIs, local model runners, hosted provider APIs, and compatibility proxies.
So the lab has an internal model routing layer and generated client profiles.
The routing layer is actually two pieces working together: a read-only settings registry that publishes generated profiles, model catalogs, and route metadata without exposing any secrets, and an authenticated router that validates machine tokens before forwarding requests to the selected backend. The registry tells clients what’s available. The router controls who’s allowed through. The registry is backed by a structured catalog with a validation pipeline and a renderer that materializes profile files for each agent client; so when a provider changes, I update the catalog input, re-render, and every client picks up the new config without anyone hand-editing a dotfile.

The backends behind the router are a mix: compatibility proxy lanes that translate API formats, LAN-only local inference on nodes/VMs that have GPUs, dedicated LAN model appliances, cloud provider routes for heavy lifting, and fallback routes for when the preferred backend is down. Each LAN machine gets its own router token, so I can revoke one machine without touching the others. The router surface isn’t just chat completions either: it also handles embeddings, reranking, RAG queries, and even Anthropic-format message translation, all through the same authenticated front door.
This is the part that makes AI tooling feel like infrastructure instead of a collection of hacks.
If a tool needs a model list, it should ask the registry or router. If a tool needs a generation route, it should use an authenticated route. If a provider changes, the generated profiles update from the source of truth instead of every client being hand-edited.
The same idea extends to agent skills. There’s a separate dashboard, its own container and LAN-only, that mines the trace corpus for candidate skills, surfaces them for review, and tracks what’s been promoted to the curated skill library. The skills themselves live in a repo, get validated before promotion, and are symlinked into each agent client’s discovery root. That way a skill isn’t a random script in someone’s home directory; it’s a versioned, tested unit that every agent client can discover.
## The Web Evidence Lane
Agents need web access, but raw web access is messy.
Search, scraping, crawling, browser automation, saved pages, and evidence cache shouldn’t be a pile of unrelated scripts on my laptop. They’re a lane in the homelab. In practice this runs on its own VM: a self-hosted search engine aggregator with several dozen configured engines, a web scraper with JavaScript rendering, a headless browser fallback for the hard cases, and an evidence gateway that sits in front of all of it, presenting a unified tool API to agents.

The cache matters. If an agent made a decision based on a page, I want a saved artifact or at least a record of what was fetched. Otherwise debugging becomes “the agent saw something on the internet,” which isn’t enough.
## The Searchable State Plane
The state plane is the memory of the system.
It collects the operational metadata that would otherwise be scattered across apps: logs, traces, agent events, tool calls, conversation metadata, job artifacts, saved web evidence, backup metadata, health check results, and restore drill evidence. In my setup this is backed by a ClickHouse instance running in its own container, with an MCP endpoint so agent clients can query it programmatically, a monitor dashboard, and near-live sync from the workstations and runtime hosts that produce agent state.

This is where the homelab starts to feel much less like a hobby dashboard collection and much more like a real platform.
The state plane is deliberately separate from the model router. Generation shouldn’t depend synchronously on the trace store being perfect. If the state plane is unavailable, clients should degrade by spooling or retrying later, not turn every model call into an outage.
The sync story matters here. Each covered workstation or runtime host runs a near-live file watcher that mirrors new session archives to the central corpus over SSH. Proxmox-side timers handle the heavier work: backing up conversation surfaces from the UI apps, syncing router proxy traces, and running parity checks that confirm the central store agrees with every source host. If the numbers diverge, the parity check fails with a specific exit code so I know whether it’s a host-unavailable gap or a confirmed drift.
## The Compute Fabric
The compute layer is where work actually runs.
My laptop is a control surface, not the only machine that should do the work. Some tasks are cheap CPU jobs. Some want a GPU. Some need a high-memory box. Some should run close to a dataset. Some should run in an isolated workspace. Some should leave behind artifacts that can be inspected later.
Let’s use my RTX 3070 VM as an example. In practice the compute fabric looks like this: a GPU-equipped VM runs local llama.cpp inference for fallback and canary lanes, dedicated LAN model appliances expose larger models through OpenAI-compatible APIs, and the router on the agent plane can direct work to whichever backend fits the job: local GPU, LAN model appliance, or cloud provider. The workspace UI on the GPU VM gives me a browser-based front end for all of it, with provider switching wired back to the router catalog so I’m not hand-editing API endpoints.

That runner selection can be implemented with simple scripts, queues, SSH, systemd services, containers, or more formal schedulers. The implementation can evolve.
The system should know where CPU work can run, where GPU work can run, where larger memory jobs fit, where artifacts belong, where logs go, how traces get captured, and how the user gets back to the result.
That’s what “every job routable” means.
## How The Pieces Connect
Here are the main paths through the system.

## Why This Is Not Just “A Reverse Proxy
A reverse proxy is only one layer.
The full system has several control planes: network access control through VPN and firewall policy, naming and discovery through private DNS, application routing through the service gateway, model and provider routing through the agent plane, evidence routing through the web tools lane, operational memory through the state plane, work placement through the compute fabric, and safety through backups, snapshots, and health checks.

That’s why the setup feels like “cloud” even though the hardware is local.
## What The Backups Are Doing In This Story
Backups aren’t a side quest. They’re part of the architecture.
Any system with gateways, generated configs, model routes, traces, and stateful apps needs a recovery story. Otherwise the platform only works until the first bad edit or disk problem.
The pattern I use is: snapshot before risky change, edit the intended live file, validate config with the same environment the service will use, reload instead of restart when possible, smoke test the actual route, capture a post-change backup, document the rollback path. I follow this workflow religiously for the gateway config: the Caddyfile gets validated against its environment file before every reload, and I keep timestamped backups of every working config so I can diff and roll back.
This matters especially for gateway config. A small typo in a central gateway can break many services. The answer isn’t fear; the answer is a boring change workflow.
Stateful services get their own backup and restore logic. The searchable state plane gets periodic restore drills to verify the backups actually work. The conversation surfaces, including chat UIs, workspace state, and agent session data, get backed up on a Proxmox-side timer and synced into the state plane as redacted snapshots. The web evidence cache, generated profiles, gateway config, and service runbooks all need to be recoverable too.
The platform is only real if it can be rebuilt.
Health checks are part of that story too. The router and the proxy lanes each have automated health endpoints that get polled on timers; every 15 minutes from the workstation, plus Proxmox-side systemd timers on the containers themselves. There are two levels: health-only checks that are safe to run as background jobs (just hitting /health endpoints), and real-client smokes that actually send prompts through the providers. The real-client smokes can spend quota and hit rate limits, so they’re deliberate operations, not automated background noise. The health-only checks feed into parity and alert scripts that tell me when a route is down before I discover it by surprise.
## Security Boundaries That Matter
The public version of the architecture hides details, but the design principles are worth saying plainly.

## The Main Lesson
The thing worth copying isn’t my exact set of services.
The thing worth copying is the shape:

You don’t need to start with all of it. In fact, you probably shouldn’t.
Start with: a virtualization or host layout you understand, private DNS, a VPN edge, a reverse proxy or internal service gateway, snapshots and backups, health checks, a central place for logs/traces, compute runners, a model/agent router if you use AI tools heavily, and web evidence tooling if agents browse or research for you.
That order keeps the foundation boring.
The agents, GPUs, browser tools, and searchable memory are much easier to trust after the network, naming, gateways, and recovery path are already sane.
## The Short Answer To “Is This The Cloud?”
It isn’t public cloud.
It isn’t infinite scale.
It isn’t a replacement for every managed service.
It’s a private cloud-like operating model running on local infrastructure.
The important part is that clients don’t need to know the whole topology. They use stable entry points. The platform handles the private backends, routes, policies, runners, traces, and recovery workflows.
That’s why my answer was:
> No, I did not duplicate my homelab to the cloud. My homelab became the cloud I use.
## 相关链接
- [Ahmad](https://x.com/TheAhmadOsman)
- [@TheAhmadOsman](https://x.com/TheAhmadOsman)
- [2.8K](https://x.com/TheAhmadOsman/status/2050062045471740303/analytics)
- [I’d duplicated my local homelab into the cloud](https://x.com/HafeezHaqq/status/2049886136060043398)
- [diagram I posted](https://x.com/TheAhmadOsman/status/2049841755789619554)
- [should I ditch Proxmox?](https://x.com/HafeezHaqq/status/2049886136060043398)
- [my setup](https://github.com/eric-tramel/moraine)
- [11:57 AM · May 1, 2026](https://x.com/TheAhmadOsman/status/2050062045471740303)
- [2,892 Views](https://x.com/TheAhmadOsman/status/2050062045471740303/analytics)
---
*导出时间: 2026/5/1 13:35:55*
---
## 中文翻译
# 我家的家庭实验室技术上现在也算云了
**作者**: Ahmad
**日期**: 2026-05-01T03:57:34.000Z
**来源**: [https://x.com/TheAhmadOsman/status/2050062045471740303](https://x.com/TheAhmadOsman/status/2050062045471740303)
---

最近有人问我,是否把本地的家庭实验室复制到了云端。
其实没有。更准确的回答是,我在家庭实验室周围构建了足够多的类似云的基础设施,以至于它现在的行为就像一个小型的私有云。同样的本地机器,同样的 Proxmox 节点,同样的硬件,但运行模式完全不同。
不再是堆砌的仪表盘、随机端口、一次性虚拟机和手动 SSH 会话,实验室现在是围绕访问层、网关、路由策略、可搜索状态和计算通道来组织的。这就是“我在家里运行一些服务”与“我拥有自己基础设施的私有控制平面”之间的区别。目前,该控制平面跨越了数十个活跃的 Proxmox 虚拟机、LXC 容器以及少量虚拟机,工作站和专用局域网模型设备也会在合适的地方接入这个网络架构。
本文将解释该系统的整体概况,不会发布我真实的主机名、IP 地址、服务名称、容器 ID、域名或密钥。
## 文章结构
本文将从高层概念开始,然后向下遍历每一层,直到整个私有云的运行模式清晰可见。
1. **高层主张**:为什么这仍然是本地硬件,但不再感觉像是一堆一次性运行的家庭实验室服务。
2. **脱敏模型**:什么是真实的,什么是匿名的,以及什么是保密的。
3. **全景图**:从异地客户端到 VPN、DNS、服务网关、代理、状态、计算和备份的完整平台形态。
4. **物理底层**:Proxmox、容器、虚拟机、存储和回滚基础。
5. **访问路径**:WireGuard、分流/全隧道模式、SNAT、DNS/DHCP 以及防火墙/ACL 策略。
6. **应用边缘**:网关、公有/私有路由、稳定的前门入口以及面向人类的应用程序。
7. **代理平台**:模型路由、生成的客户端配置文件、技能工作流以及 Web 证据工具。
8. **状态与恢复**:追踪、可搜索的内存、应用备份、奇偶校验、健康检查和恢复演练。
9. **计算架构**:CPU 通道、GPU 通道、局域网模型设备、工作放置、产物和日志。
10. **综合**:各路径如何连接,为什么这不仅仅是一个反向代理,以及值得借鉴的经验。
## 脱敏模型
这是一篇公开文章,故有意进行了匿名化处理。这里提到的名称是角色名称,而非我实际库存清单中的名称。产品名称仅在用于解释模式时才会包含;库存标签、地址、域名、账户名称和路由名称均未包含。

架构忠实于系统,但标识符不是。
## 全景图
我发布的图表旨在展示拓扑结构,而非单一产品。
顶部是异地客户端:笔记本电脑、手机、平板电脑。它们通过一个终止于家庭实验室内 VPN 集中器的 WireGuard 隧道进入。流量从那里穿过防火墙/NAT 策略、私有 DNS/DHCP,然后进入内部服务网关。
在该网关之下是有用的平面:
- 代理和自动化平面
- 面向人类的应用界面
- 可搜索的状态平面
- 计算架构
- 支持性的 Web/证据工具
- 存储、备份、健康检查和恢复工作流

最后一行才是重点。
笔记本电脑不是整个系统。手机不是整个系统。浏览器 UI 也不是整个系统。它们只是一个私有平台的客户端。
## 物理层:Proxmox 作为底层
基础层面,这仍然是一个普通的家庭实验室:本地硬件、虚拟化、容器、存储和局域网。就我而言,Proxmox 主机是一个工作站级节点,拥有几十个逻辑 CPU 线程、大约 100 GiB 的内存、几 TiB 的 LVM-thin 虚拟机存储,以及一个由半 dozen 机械硬盘组成的独立存储池,通过 MergerFS 合并并由 SnapRAID 奇偶校验保护。批量数据存储在池中;虚拟机根磁盘位于 LVM-thin 上。NFS 导出使其他需要的局域网机器可以访问批量存储。
我使用 Proxmox 作为主要底层,因为它为我提供了清晰的运维边界:
- 用于狭窄服务的轻量级容器
- 用于更重工作负载或更强隔离的虚拟机
- 危险操作前的快照
- 网络中断时的直接控制台访问
- 有状态服务的存储挂载
- 分离故障域的地方
所以,对于“我应该抛弃 Proxmox 吗?”这个问题,我的回答是否定的。
Proxmox 本身不是云;它是底层。类似云的部分位于其之上:名称、路由、网关、令牌、生成的配置、健康检查、追踪、备份和作业调度。
你也可以在其他底层上构建这种风格的系统。重要的是底层要保持“无聊”。它应该运行工作负载并提供回滚点。它不应该是唯一的组织层。
## 网络入口点:WireGuard
第一个真正的控制点是 VPN 边缘。
当我离开家时,我不希望每个内部工具都暴露在公共互联网上。我的笔记本电脑、手机和平板电脑连接到一个 WireGuard 端点,该端点落地在家庭实验室内一个小型的 VPN 集中器上。
集中器拥有对等身份、VPN 地址分配、分流隧道和全隧道配置文件、VPN 客户端与 LAN 之间的路由,以及穿过该边界的流量的 NAT 行为。在我的设置中,这是一个运行 WireGuard 的 LXC 容器,带有一个用于管理对等点的小型仪表盘,而不是一个重型 VPN 设备。
用于远程访问的公共端点仅仅是一扇门。有用的系统在握手成功之后才开始。
有两种主要的客户端模式,我为每台设备都配置了这两种。然后我会根据我所在的位置激活其中一种。
分流隧道与全隧道

在实际设置中,我还关心 IPv4 和 IPv6 的行为。隧道本身在内部运行双栈:每个对等点都会获得一个 IPv4 地址和一个 IPv6 ULA 地址。但是,设备连接的公共端点在设计上保持仅 IPv4,客户端工具会在 DNS 发生漂移时锁定 A 记录,因为我见过移动运营商通过 IPv6 阻断 WireGuard UDP 流量。
## 为什么 SNAT 很重要
因为我想在连接 VPN 或在家时保持相同的 IP 地址/身份。
SNAT 意味着源网络地址转换。
实际问题很简单:VPN 客户端拥有来自 VPN 网络的地址,而大多数 LAN 服务期望来自 LAN 的流量。你可以教每个 LAN 主机一条回到每个 VPN 子网的路由。这虽然可行,但这会让 VPN 意识扩散到各处。
相反,当流量从 VPN 穿越到 LAN 时,VPN 边缘会转换源地址。在我的设置中,这比简单的 MASQUERADE 更进一步:每个 VPN 对等点都映射到其自己稳定的 LAN 侧身份,而不是共享的边缘地址。这样,LAN 仍然可以区分是哪个物理设备发出的请求,即使是通过隧道,这有助于日志记录和每设备策略,而无需教每个 LAN 主机回到 VPN 子网的路由。

最后一点很重要。SNAT 本身不是安全模型。WireGuard 处理加密。对等密钥处理隧道身份。防火墙规则和 ACL 处理策略。DNS 处理名称。SNAT 只是解决了地址转换问题,以便你的设备身份在本地和 VPN 上都得以保留。
## 私有 DNS 和 DHCP:实验室需要名称
一旦客户端可以进入网络,它们就需要稳定的名称。
这就是私有 DNS 和 DHCP 变得比人们预期的更重要的地方。如果没有它们,每个仪表盘都会变成“那个 IP 又是多少来着?”。每个脚本都会有一个硬编码的地址。每次迁移都会变得令人恼火。我运行 Pi-hole 作为 LAN DNS/DHCP 控制点。广告拦截是附赠的;真正的价值在于内部服务在一个地方获得稳定的名称。
在我的设置中,内部名称代表角色:

有用的模式是客户端依赖于角色名称,而不是机器琐事。如果后端从一个容器移动到另一个容器,名称可以保持稳定。如果服务被重建,客户端不应该需要关心。如果运行健康检查,它针对的是角色。
私有 DNS 还将 VPN 连接回系统的其余部分。隧道上的远程手机或笔记本电脑可以解析与 LAN 相同的私有名称。这就是远程访问感觉原生而不是外挂的原因。
## 防火墙和 ACL 策略
防火墙层决定了 VPN 客户端、LAN 客户端、服务网关和内部工具被允许访问什么。
在我的设置中,Proxmox 级别的防火墙不是主要的隔离层。大多数访问控制由服务网关、代理路由器的令牌边界以及大多数服务根本没有公共路由这一事实来强制执行。网络边界是真实的,但策略更多地存在于应用和路由层,而不是数据包过滤器。
我不希望每个内部服务都能从每个地方平等地访问。有些是 CDN 后面的面向公众的 Web 应用程序。有些是仅限 LAN 的仪表盘。有些仅用于自动化。有些是代理后仅限环回的。有些应该只接受来自模型路由器或证据网关的流量。
这将网络转化为基于角色的路径:

重要的部分是边界是显式的。服务在 LAN 上并不自动意味着它应该是一个公共 API。
## 内部服务网关
在访问、DNS 和防火墙之后,下一个重要部分是内部服务网关。
把它想象成家庭实验室的应用边缘。有些流量是私有的。有些流量是公共的。有些公共流量通过上游 CDN 或 DNS 代理到达。有些流量直接来自 LAN。网关规范化这些路径并转发到正确的后端。就我而言,这是运行在自己虚拟机上的 Caddy,处理 TLS 终止、通过上游 DNS 提供商进行 DNS 验证的证书,以及公共/私有路由分离。

后端可以移动。容器可以重启。虚拟机可以重建。客户端仍然与同一个前门通信。
对于面向公众的服务,我还关心真实客户端 IP 的处理。如果请求通过上游代理传来,网关应仅在其来自正确位置时才信任正确的标头,剥离欺骗性的转发标头,并重建上游应用程序所需的内容。这使得日志和速率限制保持有用,而不会让随机客户端伪造其身份。
## 人类应用:仪表盘、聊天、搜索和工作区
在网关之上是我实际使用的东西:
- 带有系统指标的主页仪表盘
- 由开源前端支持的聊天 UI
- 用于文档搜索和检索的专用 RAG 风格 Web 界面
- 带有会话管理、提供商切换和技能的 AI 工作区 UI
- 运营状态页面和管理工具
重要的细节是,它们并不都被允许直接与所有内容对话。
例如,面向人类的 RAG 或聊天 UI 不应该需要直接访问每个模型提供商凭据、浏览器自动化端口、嵌入工作进程、重排序器、数据库和追踪存储。它应该调用更窄的内部路由:

这使得 UI 成为平台的客户端,而不是一个巨大的受信任的“万能盒”。
这个边界不仅仅是空想;我维护一个明确的跨服务标准,定义代理平面中的每个容器被允许访问什么。RAG UI 必须通过路由器路由模型流量,通过路由器的 RAG 端点路由文档搜索,并通过搜索后端路由 Web 搜索。它不得直接访问向量数据库、嵌入工作进程、重排序器、浏览器自动化端口或原始证据缓存。聊天 UI、工作区 UI 和技能仪表盘各自都有自己的允许列表。如果服务需要新的内部路由,它会经过边界审查,而不是快速的防火墙例外。
## 代理和自动化平面
代理平面是最让人们感到惊讶的部分。
我运行大量的 AI 和自动化工具,但我不希望每个工具都携带不同的手写提供商配置。一旦你拥有终端代理、编辑器集成、Web UI、本地模型运行器、托管提供商 API 和兼容性代理,这就变得无法审计。
因此,实验室有一个内部模型路由层和生成的客户端配置文件。
路由层实际上是协同工作的两个部分:一个只读设置注册表,它发布生成的配置文件、模型目录和路由元数据而不暴露任何机密;以及一个经过身份验证的路由器,它在将请求转发到选定的后端之前验证机器令牌。注册表告诉客户端什么是可用的。路由器控制谁被允许通过。注册表由结构化目录支持,该目录具有验证管道和渲染器,可为每个代理客户端具体化配置文件;因此,当提供商更改时,我更新目录输入,重新渲染,每个客户端都会获取新配置,而无需任何人手动编辑点文件。

路由器后面的后端是混合的:转换 API 格式的兼容性代理通道、具有 GPU 的节点/虚拟机上的仅局域网本地推理、专用局域网模型设备、用于重体力活的云提供商路由,以及当首选后端宕机时的回退路由。每个 LAN 机器都有自己的路由器令牌,所以我可以撤销一台机器而不影响其他机器。路由器界面不仅仅是聊天完成:它还通过同一个经过身份验证的前门处理嵌入、重排序、RAG 查询,甚至 Anthropic 格式的消息转换。
这是让 AI 工具感觉像基础设施而不是一堆 hacks 的部分。
如果工具需要模型列表,它应该询问注册表或路由器。如果工具需要生成路由,它应该使用经过身份验证的路由。如果提供商更改,生成的配置文件会从真实来源更新,而不是每个客户端都被手动编辑。
同样的想法延伸到代理技能。有一个单独的仪表盘、它自己的容器和仅限 LAN,它在追踪语料库中挖掘候选技能,将其呈现以供审查,并跟踪哪些已提升到精选技能库。技能本身位于仓库中,在提升前经过验证,并符号链接到每个代理客户端的发现根目录。这样,技能就不是某人主目录中的随机脚本;它是每个代理客户端都能发现的版本化、经过测试的单元。
## Web 证据通道
代理需要 Web 访问,但原始 Web 访问是一团糟。
搜索、抓取、爬取、浏览器自动化、保存的页面和证据缓存不应该是我笔记本电脑上一堆无关的脚本。它们是家庭实验室中的一个通道。实际上,这运行在自己的虚拟机上:一个自托管的搜索引擎聚合器,配置了几十个引擎,一个带有 JavaScript 渲染的 Web 抓取器,一个用于困难情况的无头浏览器后备,以及位于所有这些前面的证据网关,向代理呈现统一的工具 API。

缓存很重要。如果代理基于页面做出决定,我想要一个保存的产物,或者至少是获取内容的记录。