个人私有云 NAS 部署
把一台普通电脑(Windows 或 Linux)变成家用私有云:文件能同步、照片能自动备份、影音能串流、数据在自己手里。
何时使用
- 用户想用闲置电脑/小主机做 NAS,但不知道装什么、怎么装
- 用户点名要 Nextcloud / Jellyfin / Immich / Alist / qBittorrent 这类自托管服务
- 用户已经有 Docker,需要一套能长期跑、能备份、能升级的编排
- 用户部署后遇到打不开、权限、内存、外网访问等问题
不适用:成品 NAS 的套件操作、公有云多租户部署、K8s 编排。
三条硬规矩
- 先体检再动手。没确认 Docker 能用、端口空闲、数据盘位置,就不要开始生成编排。用户机器上已经有什么(既有容器、既有数据)必须先看清。
- 不动用户已有数据。不执行
docker compose down -v、不rm -rf任何数据目录、不覆盖非本 skill 生成的 compose 与.env。需要清理时先列出清单让用户确认。 - 不擅自把服务暴露到公网。公网档必须有域名、必须提醒加固;鉴权薄弱的服务(qBittorrent、Jellyfin)直接映射公网是明确风险,要点明。
工作流
第 1 步:确认四件事(一次性问清,别来回挤牙膏)
| 要确认 | 为什么 | 默认值(用户没想法就用这个) |
|---|---|---|
| 跑在哪台机器 | 决定路径写法、权限、自启方式 | 当前这台机器 |
| 机器规格(内存) | 决定开哪些 profile,开多了会 OOM | 8GB → lite,core,media |
| 要哪些能力 | 决定 profile 组合 | 文件 + 私有云盘 |
| 数据放哪个盘、外网怎么访问 | 写进 .env,事后改要停机 |
非系统盘;外网档 lan |
用 AskUserQuestion 一次问完(最多 4 个问题),不要逐个追问。用户说"你看着办"就按默认值走,并把选择结果讲清楚。
profile 说明见 references/service-matrix.md(含按内存选组合的对照表)。
第 2 步:环境体检
python <skill>/scripts/preflight.py --profiles <profile列表> --data-root <数据盘路径>
读输出里的 [FAIL] 项先解决,[warn] 项向用户说明影响。常见阻断:没装 Docker、引擎没启动、端口被占、数据盘空间不足。
没有 Docker 时:Windows 引导装 Docker Desktop(WSL2 后端),Linux 用官方脚本。装完再回到这一步,不要跳过体检直接生成编排。
第 3 步:生成编排文件
python <skill>/scripts/gen_stack.py \
--dir <编排目录> \
--profiles lite,core,media \
--exposure lan \
--data-root <数据盘> --app-root <配置目录>
产物:docker-compose.yml、.env(自动生成数据库密码)、.env.example、caddy/Caddyfile、nas-state.json、nas-notes.md(给用户看的速查卡)。
要点:
- 端口冲突加 --auto-ports 自动顺延,或 --set PORT_XXX=新端口 单个改
- 路径含空格/中文会出问题,脚本会提示,按提示换路径
- 生成失败时看"缺变量"警告,说明模板与生成器脱节,需同步修模板
第 4 步:启动
cd <编排目录>
docker compose pull
docker compose up -d
docker compose ps
ps 里出现 Restarting 就别继续下一步,先 nasctl.py logs <服务> 定位。首次启动 Nextcloud / Immich 需要 1-3 分钟初始化,期间 502 属正常。
第 5 步:逐个初始化
按 gateway → lite → core → media → photos → download 顺序走,每个服务的具体填法和坑见 references/app-initialization.md。
三个必须提醒用户的点:
- Nextcloud 首次必须选 MariaDB,主机填 nextcloud-db,账号密码查 .env;选 SQLite 会后悔
- Immich 第一个注册的账号自动成为管理员,别让外人先注册
- qBittorrent 初始密码在容器日志里,登录后立刻改
第 6 步:外网访问(用户需要时才做)
按档位给方案,不要默认开公网:references/network-access.md
- 只在家用 →
--exposure none或lan - 出差要访问 → 优先 Tailscale 组网,零端口暴露
- 有公网 IP 且非要域名直连 →
--exposure public,必须同时讲清加固措施
第 7 步:备份与自启
python <skill>/scripts/nasctl.py backup
- 讲明"只备份
DATA_ROOT不够,数据库才是索引"这件事 - 定时任务 + 异地副本按
references/backup-and-restore.md落地 - 自启三层:Docker 服务自启 → 容器
restart: unless-stopped→ 系统账户自动登录(Windows)
第 8 步:交付
给用户的收尾必须包含:
1. 每个服务的实际访问地址(IP + 端口,有域名就带域名)
2. nas-notes.md 的位置,里面是速查卡
3. .env 要单独备份的提醒(密码在里面,丢了数据就打不开)
4. 验收清单逐条确认(见 references/app-initialization.md 末尾)
日常运维
scripts/nasctl.py 是唯一的运维入口,在编排目录下执行:
| 命令 | 用途 |
|---|---|
status |
容器状态 + 访问地址 |
up --profiles core,media |
按指定 profile 启动 |
down / restart [服务] |
停止 / 重启 |
logs <服务> --tail 200 |
看日志(排障第一入口) |
update |
拉新镜像并重建 |
backup / restore <包> |
备份配置与数据库 / 恢复 |
urls |
只打印访问地址 |
给用户解释时的口径
- 说清"数据在自己机器上"的代价:断电、硬盘坏、误删都得自己兜,所以备份不是可选项
- 不要承诺"一次部署永久省心":容器要升级、硬盘会老化、证书要续期
- 内存不够时的表现不是"变慢"而是"服务突然消失"(OOM),要提前说明
- 影音/相册是吃资源大头,机器弱就先只上文件层
参考资料
| 文件 | 什么时候读 |
|---|---|
references/service-matrix.md |
选 profile、定端口、看资源占用 |
references/app-initialization.md |
每个服务首次配置的确切步骤 |
references/network-access.md |
用户问外网访问、DDNS、内网穿透 |
references/windows-docker-desktop.md |
宿主是 Windows |
references/linux-host.md |
宿主是 Linux(挂盘、Samba、防火墙) |
references/backup-and-restore.md |
备份策略、恢复演练 |
references/troubleshooting.md |
出问题时的对照表 |
边界
- 不做版权内容的分发与获取指导(下载器只讲技术部署,不讲资源来源)
- 不代办域名备案、不做公网合规咨询
- 用户的数据恢复请求若涉及删除/覆盖,必须先列清单确认再执行