在VPS上自托管应用:架构、内存占用与部署优先级
使用Docker在VPS上自托管应用的决策指南。包含10+应用的真实内存占用数据、4GB和8GB方案的组合搭配,以及选择第一个应用的决策框架。
你有一台VPS。也许刚拿到手,也许已经跑了几个服务想要更进一步。不管哪种情况,问题都一样:我该跑什么,跑得下吗?
本指南回答这个问题。它涵盖自托管应用栈的架构,提供在4 vCPU/8 GB VPS上实测的内存占用数据,并给出一个决策矩阵帮你选择第一个(或下一个)应用。没有应用名称堆砌。没有理论猜测。只有数据和计划。
前提条件: 本指南假设你已经安装了Docker和反向代理。如果还没有,先阅读VPS上的Docker生产环境:会出什么问题以及如何解决在Debian 12或Ubuntu 24.04上安装Docker、Docker Compose和Caddy或Traefik。Docker Compose基础请参考[-> docker-compose-multi-service-vps]。
为什么选择VPS自托管而不是家庭实验室?
VPS提供全天候托管,带公网IPv4地址,没有CGNAT,没有电费,不需要维护硬件。服务商管理的快照负责灾难恢复。一台4 vCPU/8 GB的VPS可以轻松运行5到8个Docker应用,每月只需几欧元。你家的网络会断;VPS不会。
以下是VPS与家庭实验室在自托管方面的对比:
| 因素 | VPS | 家庭实验室 |
|---|---|---|
| 公网IP | 包含,静态 | 通常在CGNAT后面,需要隧道方案绕行 |
| 可用性 | 99.9%+ SLA,冗余供电 | 取决于ISP和电网 |
| 带宽 | 对称,通常1 Gbps+ | 非对称,上行是瓶颈 |
| 硬件维护 | 服务商的事 | 你的事。磁盘故障、风扇噪音、散热。 |
| 电费 | 包含在价格中 | 小型服务器全天运行每年20-60欧元 |
| 快照/备份 | 一键操作,服务商管理 | 自己搭建和测试备份流程 |
| 初始成本 | 约4欧元/月起 | Mini PC或NAS需200-500+欧元 |
| 物理访问 | 无,仅SSH | 完全访问。适合USB设备、ZFS阵列。 |
如果你需要本地存储(ZFS阵列、NAS)、USB硬件(Zigbee适配器、SDR接收器)或想学习裸机管理,家庭实验室是合理的选择。其他场景下,VPS起步更简单、更便宜。
CGNAT是没人警告你的家庭实验室杀手。大多数家用ISP现在使用运营商级NAT,意味着你和几十个其他用户共享一个公网IP。无法端口转发。无法接收入站连接。你的自托管应用在互联网上不可见。解决方案存在(Cloudflare Tunnels、通过VPS的WireGuard中继),但增加了复杂性和对外部服务的依赖。VPS完全绕过了这个问题:你获得专用公网IPv4,你控制DNS,入站流量直接可用。
如果两者都想要,可以用VPS作为公网入口,通过WireGuard隧道连回家庭实验室的私有服务。但对于大多数自托管应用,VPS本身就够了。
自托管应用栈是什么样的?
VPS上的自托管栈采用分层架构:反向代理在最前端,将HTTPS流量路由到应用容器。每个应用连接自己的数据库(或使用内置的SQLite)。备份层按计划创建快照。
Internet
│
▼
┌─────────────────────────────┐
│ Reverse Proxy (Caddy) │ Port 443 ← only public port
│ TLS termination + routing │
└──────┬──────┬──────┬────────┘
│ │ │
▼ ▼ ▼
┌─────┐ ┌─────┐ ┌─────┐
│App 1│ │App 2│ │App 3│ Docker containers
└──┬──┘ └──┬──┘ └──┬──┘
│ │ │
▼ ▼ ▼
┌─────┐ ┌─────┐ ┌─────┐
│ DB │ │ DB │ │SQLite│ PostgreSQL, Redis, or embedded
└─────┘ └─────┘ └─────┘
│
▼
┌─────────────────┐
│ Backup Layer │ Restic, borgmatic, or provider snapshots
│ (scheduled) │
└─────────────────┘
关键决策:
- 反向代理: Caddy自动配置TLS证书,零配置。Traefik通过Docker标签实现自动发现。两者都可以。Caddy对新手更简单。
- 数据库: 许多轻量应用(Vaultwarden、Uptime Kuma、Beszel)使用内置SQLite,不需要单独的数据库容器。较重的应用(Immich、Plausible、Gitea)需要PostgreSQL。
- 备份: 服务商快照覆盖整个磁盘。应用级备份可使用Restic或borgmatic到异地目标(S3兼容存储或第二台VPS)。
- 网络: 所有应用容器在Docker内部网络中运行。只有反向代理暴露80和443端口。应用永远不直接绑定到公网接口。
该架构的详细说明请参考VPS上的Docker生产环境:会出什么问题以及如何解决。
自托管应用实际占用多少内存?
比你想的少。大多数流行的自托管应用空闲时占用不到200 MB。例外是带机器学习功能的应用(Immich)或内置分析引擎的应用(Plausible加ClickHouse)。
以下数据是通过docker stats在Virtua Cloud 4 vCPU/8 GB VPS(Debian 12)上测量的空闲/轻度使用RSS内存。峰值代表活跃使用时的典型峰值(照片上传、文档OCR、工作流执行)。
| 应用 | 替代什么 | 空闲内存 | 峰值内存 | 月存储量 | 数据库 |
|---|---|---|---|---|---|
| Vaultwarden | Bitwarden、1Password | ~25 MB | ~50 MB | 极少 | SQLite |
| Uptime Kuma | UptimeRobot、Pingdom | ~100 MB | ~170 MB | 极少 | SQLite |
| Beszel | Datadog(基础版) | ~50 MB | ~80 MB | 极少 | 内置 |
| Gitea | GitHub(私有仓库) | ~150 MB | ~300 MB | ~50 MB/仓库 | PostgreSQL或SQLite |
| n8n | Zapier、Make | ~100 MB | ~500 MB+ | 取决于工作流 | PostgreSQL |
| Paperless-ngx | 文件柜 | ~300 MB | ~1 GB | ~5 MB/文档 | PostgreSQL + Redis |
| Nextcloud | Google Drive、Dropbox | ~250 MB | ~512 MB | 取决于文件 | PostgreSQL + Redis |
| Coolify | Vercel、Railway | ~500 MB | ~1.2 GB | 取决于部署 | PostgreSQL(内置) |
| Plausible | Google Analytics | ~400 MB | ~1.5 GB | ~100 MB/100万页面浏览 | PostgreSQL + ClickHouse |
| Immich | Google Photos | ~800 MB | ~2.5 GB | ~3 GB/1000张照片 | PostgreSQL + Redis |
关于这些数据的几点说明:
- Immich启用机器学习(人脸/物体检测)时总共需要4-6 GB。上面的数据是ML启用但空闲状态。大量照片导入时预计3-4 GB。可以禁用ML降至~400 MB,但会失去智能搜索和人脸识别。
- Plausible的内存取决于流量。ClickHouse喜欢吃内存。对于月页面浏览量低于10万的网站,上述数据成立。高流量网站需要更多。
- n8n空闲时很轻量,但大JSON负载或AI集成的复杂工作流会产生剧烈峰值。AI代理工作流每次执行可消耗200 MB+。
- Paperless-ngx在OCR时出现峰值。如果你是唯一用户,在Docker中设置
PAPERLESS_WEBSERVER_WORKERS=1可节省~150 MB。
我应该首先在VPS上自托管哪个应用?
从Vaultwarden开始。它只占25 MB内存,10分钟内部署完成,替代一个你每天都在用的付费密码管理器,而且迫使你正确配置TLS。这个TLS配置(反向代理 + DNS + 证书)是其他每个自托管应用都需要的基础。一个应用,三重收益:隐私、省钱、可复用的基础设施。
| 应用 | 隐私影响 | 安装复杂度 | 替代的SaaS | 最低内存 |
|---|---|---|---|---|
| Vaultwarden | 极高(密码) | 低(10分钟) | Bitwarden/1Password | 128 MB |
| Immich | 高(个人照片) | 中(30分钟) | Google Photos | 2 GB(含ML 4 GB) |
| Paperless-ngx | 高(证件、文档) | 中(20分钟) | 文件柜 + 扫描应用 | 512 MB |
| Plausible | 中(访客分析) | 中高(25分钟) | Google Analytics | 1 GB |
| Uptime Kuma + Beszel | 低(基础设施监控) | 低(10分钟) | UptimeRobot + Datadog | 256 MB |
| Gitea | 中(源代码) | 低(15分钟) | GitHub私有仓库 | 256 MB |
| n8n | 中(工作流数据) | 中(20分钟) | Zapier、Make | 512 MB |
| Coolify | 低(部署工具) | 中(20分钟) | Vercel、Railway | 1 GB |
隐私影响是自托管最有力的理由。你的密码、照片和扫描文档是你日常处理的最敏感数据。把它们放在别人的服务器上意味着信任对方的安全、司法管辖权和业务连续性。在你自己位于欧洲的VPS上,这些数据始终在你的掌控之下,受GDPR保护。
安装复杂度考虑了完整栈:应用容器、数据库、反向代理配置和首次备份。"低"意味着写好一个Compose文件后只需一条docker compose up -d。"中"额外需要数据库和存储卷配置。"中高"涉及多个相互依赖的服务(Plausible的ClickHouse、Immich的ML容器)。
各应用的教程请跟随本指南末尾的链接。
4 GB VPS和8 GB VPS分别能跑什么?
4 GB VPS可以运行一个扎实的个人栈。8 GB VPS能满足独立开发者或小团队的所有需求。以下数据已计入反向代理(~30 MB)、Docker开销和操作系统本身(~300-400 MB)。
4 GB VPS(约3.2 GB可用于应用)
| 组合搭配 | 空闲总内存 | 剩余空间 |
|---|---|---|
| Vaultwarden + Uptime Kuma + Beszel + Gitea | ~325 MB | ~2.9 GB |
| Vaultwarden + Paperless-ngx + Uptime Kuma | ~425 MB | ~2.8 GB |
| Vaultwarden + n8n + Beszel + Gitea | ~325 MB | ~2.9 GB |
| Vaultwarden + Nextcloud + Uptime Kuma | ~375 MB | ~2.8 GB |
这些组合为峰值使用留有充足余量。即使Paperless-ngx在OCR时飙升到1 GB,仍有足够空间。避免在4 GB上运行带ML的Immich或Plausible,除非它是唯一的应用。
8 GB VPS(约7 GB可用于应用)
| 组合搭配 | 空闲总内存 | 剩余空间 |
|---|---|---|
| Vaultwarden + Immich + Uptime Kuma + Beszel | ~975 MB | ~6 GB |
| Vaultwarden + Plausible + Gitea + Paperless-ngx + Beszel | ~925 MB | ~6 GB |
| Vaultwarden + Coolify + Uptime Kuma + n8n | ~725 MB | ~6.3 GB |
| 全部轻量应用(Vaultwarden + Gitea + Uptime Kuma + Beszel + n8n + Paperless-ngx) | ~725 MB | ~6.3 GB |
在8 GB上,你可以轻松地将带ML的Immich与三四个轻量应用一起运行。也可以运行Plausible加ClickHouse而不用担心内存压力。这是个人自托管配置的最佳平衡点。
关于峰值使用的说明: 空闲内存是你规划的依据,但峰值才是让服务器崩溃的东西。Paperless-ngx在OCR时出现峰值。Immich在ML分类照片导入时出现峰值。n8n在执行大负载工作流时出现峰值。上面的剩余空间列是你的安全边际。如果剩余空间低于1 GB,你可能会面临Linux OOM Killer在最糟糕的时刻终止某个容器。对于包含Immich或Plausible的任何栈,至少保留1.5 GB的余量。
Virtua Cloud VPS提供4 vCPU和8 GB RAM的NVMe存储方案,可查看当前计划。法兰克福机房将你的数据置于欧盟境内,受德国数据保护法管辖。
哪些自托管应用需要欧洲托管?
任何存储个人数据的应用都能从GDPR下的欧洲托管中受益。但有些应用处理的数据使管辖权问题变得紧迫。
欧盟托管高优先级:
- Vaultwarden存储你所有的密码。这里发生泄露是灾难性的。欧洲托管意味着GDPR的数据泄露通知要求适用。
- Immich保存个人照片,通常包含家庭成员的面部。面部识别数据属于GDPR第9条定义的生物识别数据。特殊类别,额外保护。
- Paperless-ngx存储扫描的身份证件、税务文件、合同。这是你拥有的最敏感的个人数据。
中等优先级:
- Plausible收集访客分析数据。它在设计上注重隐私(无Cookie、无个人数据),但数据仍然属于你的网站访客。
- Gitea可能包含专有源代码。严格来说不是个人数据,但是你想要控制的知识产权。
- n8n的工作流经常处理来自多个服务的数据。自动化层看得到一切。
较低优先级:
- Uptime Kuma / Beszel存储监控数据。除非你监控的端点包含个人数据,否则没有个人数据。
- Coolify是部署工具。它处理你的代码但不存储终端用户数据。
如果你是欧洲企业或处理欧盟公民数据,将这些应用托管在德国(或其他欧盟国家)的VPS上能简化你的GDPR合规。你控制数据。你知道它在哪里。你决定谁有权访问。
如何保持自托管应用的安全和更新?
自托管意味着你就是系统管理员。这是控制权的代价。以下是不可妥协的实践:
防火墙优先。 部署任何应用之前,配置ufw仅允许SSH(端口22)和HTTPS(端口443)。屏蔽其他所有端口。详见VPS上的Docker生产环境:会出什么问题以及如何解决。
全面启用TLS。 你的反向代理(Caddy或Traefik)负责TLS终止。每个应用都要有HTTPS。没有例外。不要想着"以后再加TLS"。Caddy自动配置Let's Encrypt证书。
更新。 每周检查容器镜像更新。拉取新镜像,重建容器:
docker compose pull
docker compose up -d
对于关键安全更新(Vaultwarden、任何面向互联网的应用),订阅项目的GitHub Releases或RSS源。Vaultwarden releases和Immich releases是很好的示例。
备份。 要测试它们。从未恢复过的备份不算备份。使用服务商快照进行全盘恢复,使用Restic或borgmatic进行应用级异地备份。用cron或systemd timer调度。每月验证一次。
密钥管理。 永远不要在docker-compose.yml中硬编码密码。使用chmod 600权限的.env文件:
openssl rand -base64 32 > /dev/null # example: generate a strong password
# docker-compose.yml
services:
app:
env_file: .env
# .env (chmod 600, owned by root)
DB_PASSWORD=<generated-password>
SECRET_KEY=<generated-key>
监控。 运行Uptime Kuma进行外部端点检查,运行Beszel监控容器级指标(每个容器的CPU、RAM、磁盘)。两者都很轻量,能在问题演变为故障之前提供可见性。参见使用Docker Compose在VPS上自建Uptime Kuma和Beszel。
日志意识。 知道你的日志在哪里。Docker容器默认将日志输出到stdout。查看方式:
docker compose logs -f --tail=50 <service-name>
对于系统级服务(原生运行的反向代理、SSH、防火墙),使用journalctl:
journalctl -u caddy -f
出了问题,先看日志。不是Stack Overflow。不是Reddit。是日志。
接下来做什么?
上面决策矩阵中的每个应用都有专门的教程,包含完整的Docker Compose配置、反向代理设置、备份和安全加固:
| 应用 | 教程 |
|---|---|
| Vaultwarden(密码) | 在VPS上使用Docker Compose自建Vaultwarden |
| Immich(照片) | 在VPS上使用Docker Compose自建Immich |
| Plausible(分析) | 使用 Docker Compose 在 VPS 上自托管 Plausible Analytics |
| Uptime Kuma + Beszel(监控) | 使用Docker Compose在VPS上自建Uptime Kuma和Beszel |
| Coolify vs Dokploy(PaaS) | Coolify vs Dokploy:哪个自托管PaaS适合你的VPS? |
| Paperless-ngx(文档) | 在VPS上使用Docker Compose自托管Paperless-ngx |
| Gitea(Git托管) | 使用Docker Compose在VPS上自托管Gitea |
如果你还没有设置Docker和反向代理,从这里开始:VPS上的Docker生产环境:会出什么问题以及如何解决。该指南涵盖Debian 12和Ubuntu 24.04,安装Docker和Compose,配置Caddy作为带自动TLS的反向代理,设置防火墙,并创建非root部署用户。本指南中的一切都建立在那个基础之上。