·约 10 分钟阅读·DeepSeek

2026 年我到底自托管了什么:一套 awin-x 的自托管栈

这是我在 2026 年真正在跑的自托管栈:一台公网 VPS 作为唯一入口(nginx、自动证书、多个虚拟主机),背后是一张私有 overlay 网络,加上自建 Git 服务、基于日志的统计、文件同步、密码库和邮件。每一项都附上诚实的「显存 / 精力 / 省心」备注,也列了我坚决不自托管的几样东西,以及新手第一天千万别碰什么。

self-hostinghomelabdevopsnginx

总有人问我到底自托管了什么,而诚实的答案不是一份四十个容器的清单。真正的答案是: 门口有一台公网 VPS,背后是一张私有 overlay 网络,再加几个各自配得上它那点内存的服务。 这就是我 2026 年在跑的那套自托管栈,本质上是一个「一台机器加一张 mesh」的 homelab——以及同样重要的那样东西:我明明能自托管、却坚决不做的少数几项。

「我自托管了什么」这类文章,要么是别人根本复现不了的仪表盘截图,要么是一篇宣言。这篇 想写中间那版:每个服务到底是干什么的、大概要花多少、以及知道现在这些之后我还会不会再装 一遍。我不写精确的版本号——它们一周就过期。真正要紧的是这套东西的形状。

整套形状:门口一台机器,背后一张 overlay

整套设计归结为一条规则:只有一台机器有公网端口。 其余一切只能通过一张私有 overlay 访问。

             公网
              │  :80 / :443
       ┌──────▼───────┐
       │    TOWER     │   nginx · 自动证书 · 多个虚拟主机
       │   (公网机)  │   systemd 单元 · 一个 IP · 一个定时器
       └──────┬───────┘
              │  私有 overlay(EasyTier,10.144.144.0/24)
     ┌────────┼──────────────────┐
     ▼        ▼                  ▼
  Gitea    开发机           文件同步 / 密码库
(Git 服务) (编辑)      (对等节点,无公网端口)

TOWER 是唯一暴露在互联网上的东西。nginx 终结 TLS 并按主机名路由;它背后每个应用都绑定 到 127.0.0.1,而不是 0.0.0.0。就这一条规则,让这套栈的其余部分可以安心运行:Git 服务、 同步对等节点、密码库——没有任何一个给扫描器留下可以找到的开放端口。

我到底自托管了什么

每一项都给同样的三条备注:为什么跑它、大概花多少内存和精力、以及值不值得。体量我 故意说得模糊——「很小」「几百 MB」——因为你的数字会不一样,我的每次重启都在变。

nginx 作为入口,自动签发证书

一个 nginx 实例终结 TLS,并按 server_name 路由。每个站点在 sites-available 里有自己的 文件,用符号链接启用,所以新增站点从不需要改动已有站点。证书来自 ACME(certbot 或 lego), 由 systemd 定时器续期——开机签发、每天续两次、只有真变了才 reload。

  • 为什么: 它既是入口,也是所有自托管服务的反向代理。一个进程、一种配置格式、 一个加 header 的地方。
  • 体量: 极小,几十 MB,是这台机器上最便宜的东西。精力是前置的:一个下午学会, 之后加一个 vhost 就是复制粘贴。
  • 值吗? 值,无条件地值。这是整个清单里最没有争议的一项。

这套模式连同 systemd 单元,都写在 不用 Docker 的自托管里了。

一张私有 overlay,而不是开放端口

TOWER 背后没有经典的 hub-and-spoke VPN。我跑的是一张 mesh overlay(EasyTier):一个网络 就是一个名字加一个密钥,节点活在同一个扁平 L3 子网里,每一对节点都尽量打通直连的 P2P 路径,只有在 NAT 拒绝时才回落到中继。

  • 为什么: 它把「开个端口然后祈祷」变成「加入这张私有网络」。Gitea、开发机和同步 对等节点彼此之间、以及与 TOWER 之间都能通信,且没有任何公网监听。
  • 体量: 每个节点都很小;花一个下午调对之后就基本隐形。代价在于那个密钥就是整道 边界——它泄露,整张 overlay 就全开了,所以请像对待 SSH 私钥一样对待它。
  • 值吗? 值,而且正是它让清单里其余的东西都变得省心。完整流程在 用 EasyTier 搭建私有 mesh VPN。

自建的 Git 服务

源码、issue 和 webhook 都放在 overlay 上的 Gitea,而不是公网。正是这一环让这个博客能自己 构建自己:一次 push 落地,webhook 经 overlay 触发,TOWER 拉取并部署。

  • 为什么: 我要让仓库和 CI 触发点留在自己的信任边界之内,而不是跑在别人的 runner 上。
  • 体量: 用 SQLite 时几百 MB,日常几乎不用管。
  • 值吗? 值——但前提是有一份离开这台机器的备份:SQLite 数据库加上仓库,定时导出 并发往异地。

读日志、而不是读人的统计

我不装 JavaScript 追踪脚本,而是在同一份 nginx access 日志上跑一个小型服务端分析器。它只 看得到请求、路径、来路和大致地域,关于你什么都没有——页面里没有脚本,浏览器里没有 cookie。

  • 为什么: 我只需要一个答案——哪篇话题把一个陌生人带了进来——别的都不要。这个答案 不需要追踪任何人。
  • 体量: 几 MB;精力几乎为零;永远不需要 cookie 提示条。
  • 值吗? 值。交换条件是得诚实承认它是什么:粗糙、日志形状、对任何客户端侧的东西 都是盲的。

文件同步,点对点

Syncthing,设备之间通过 overlay 直接同步,中间没有中心服务器——笔记、配置、截图,偶尔还有 大文件。

  • 为什么: 这是我能找到的、让我自己三台机器上的某个文件夹保持一致的最不折腾的办法。
  • 体量: 每个节点几百 MB;精力很低。
  • 值吗? 值,但要付一笔诚实的税:冲突文件。两台设备离线各改一份,你就会拿到一个 有争议的副本,得像成年人一样去解决它,而不是假装它没发生。

密码与密钥管理

一个自建的、兼容 Bitwarden 的密码库(Vaultwarden)负责密码;机器密钥则用更轻的方案:以 age/SOPS 加密后进 Git,绝不在仓库里放明文 .env。

  • 为什么: 我的密码数据库不该依赖一个我没法自托管的厂商账号;我的服务也不该从一个 git add -A 就能泄露的文件里读密钥。
  • 体量: 密码库本身很小,运行它的精力也低——真正的精力在备份上。
  • 值吗? 值,但前提是你有一份加密的异地副本,并且亲手做过一次恢复演练。一个有 未经验证备份的密码库,是你给自己挖的坑。

邮件:自托管信箱,而非信誉

邮件是我描述得最谨慎的一个。我为自己的域名自托管 IMAP、submission 和 webmail,信箱本身 在 overlay 上。我不自托管的是发信信誉:出站走中继。

  • 为什么: 我要自己的归档和别名躺在自己的磁盘上。我不想用一个 IP 加一个周末去对抗 Gmail 的垃圾邮件启发式规则。
  • 体量: 是本清单里最重的一项——几百 MB 的进程,加上只会越涨越大的磁盘。
  • 值吗? 说实话:只有当邮件是你真心喜欢的爱好时才值。它是我运行的东西里精力最高、 最脆弱的一件,也是我第一个愿意砍掉的。

整套栈放在一张表里

服务作用大致体量值吗?
nginx入口、TLS、虚拟主机路由几十 MB值,永远
EasyTier overlay私有 L3 mesh,无开放端口每节点很小值,基础
GiteaGit、issue、webhook几百 MB值,前提是异地备份
日志统计无 cookie 的流量洞察几 MB值,便宜
Syncthing点对点文件同步几百 MB值,注意冲突
Vaultwarden密码库很小(外加备份)只在你演练过恢复时才值
信箱IMAP / submission / webmail几百 MB只在你享受它时才值

我坚决不自托管的东西

自托管是一场赌注:赌你能把某样东西跑得比付费服务更可靠。对博客和 Git 服务来说,这场赌注 很划算;但对少数几样东西,它是一笔烂赌注,把它们点出来比再写一篇教程更有用。

  • 权威 DNS。 托管,不自建。这是最让我害怕的一项:DNS 一挂,整套栈会同时从互联网上 消失——站点、邮件、证书续期全都没了。正确的解法(分布在不止一个地方的冗余域名服务器) 恰恰是一台机器做不到的。别让你唯一的故障域,正好是解析其他一切的那个东西。
  • 异地备份。 机器不能做自己的备份。遵守 3-2-1:三份副本、两种介质,其中一份在异地 且不自托管,放在另一家供应商、用另一套凭据。一份活在它所保护的那台机器上的备份不算 备份,它只是一份等着陪葬的拷贝。
  • 出站邮件信誉。 VPS 商给的新 IP 没有信誉,而信誉不是能安装出来的东西。我的邮件从 中继发出;我只负责信箱。
  • 对象存储与静态资源的 CDN。 一台机器只有一条上行链路。把大文件从读者所在的地方送出 去,是一个已经被解决、几乎免费的问题,我没有理由再糟糕地重造一遍。
  • 任何失败模式是「把自己锁在外面」的东西。 比如用一个公网身份提供方管我全部数字生活。 它一挂,或者我把自己锁了,我就失去了那个本可以用来修它的工具的访问权。

这五项的规律是一样的:我自托管最坏结果是「某个服务挂一晚」的东西;我不自托管最坏结果是 「我根本恢复不了」的东西。

新手第一天不该碰什么

如果你 2026 年正准备起一个 homelab,最大的诱惑是一口气全装上。新手被坑得最惨的服务 是可以预判的:

  1. 邮件。 不是第一天,也不是第九十天。收件那侧很挑剔,发件那侧是你没有的信誉,失败 模式还是静默丢信。
  2. 任何存着不可替代数据唯一副本的东西。 照片归档、密码库、文档仓库。先把一份验证过的 异地备份做出来,然后再搬数据。
  3. 开放的 DNS 解析器或开放邮件中继。 这是「安静的周末项目」变成「滥用投诉生成器」的 方式。
  4. 把每个管理面板直接怼到公网上。 服务要么绑 loopback,要么放到 overlay 后面, 而不是绑在你公网 IP 的 8080 端口上。
  5. 在一次成功恢复之前先装上十个服务。 你从没恢复过的备份是愿望,不是计划。

从最无聊的一对开始:nginx、一个静态站点、以及一份真的会续期的自动证书。 确认续期定时器 确实跑过了。然后加一个服务到 overlay 后面,确认你能备份它、恢复它,再考虑下一个。

我在公网机上守住的两条规矩

两个习惯,靠操作系统而不是靠记性来执行。第一,只有必须公开的端口才公开:

# TOWER:互联网只能碰到 SSH 和 Web,别的都碰不到。
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp
ufw allow 80,443/tcp
ufw enable

第二,每个应用都绑 loopback,只有 nginx 面向世界:

# /etc/systemd/system/notes-api.service(节选)
[Service]
User=svc-notes
Environment=HOST=127.0.0.1
Environment=PORT=9001
Restart=on-failure
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict

两条合起来意味着:nginx 后面任何一个服务出漏洞,都不自动等于一个公网漏洞。这套栈的其余部分 ——单元、定时器和锁文件——都在 这个博客如何发布它自己里。

一句话总结

这套自托管栈能成立,是因为它很小、且被刻意做得不完整:一个公网入口、一张私有网络、 一组我能备份、能恢复、也能讲清楚的服务——再加一份很短的清单,列出我宁愿花钱让别人跑、 因为它们的失败模式比账单更糟的东西。

想看更深的机制:mesh 在 EasyTier 实战记录里,入口在 不用 Docker 的自托管里,而把它们串起来的那条 流水线在这个博客如何发布它自己里。