适用场景:刚装好 NAS 系统(OMV / TrueNAS / Debian + Docker),想一次性把主流家庭服务跑起来
栈:Docker Compose v2(docker compose),目录规范、权限最小化、自动更新、反代 HTTPS 一条龙
服务清单:Jellyfin(媒体库)+ qBittorrent(下载)+ Alist(网盘聚合/直链)+ Home Assistant(智能家居中枢)+ 反代(Nginx Proxy Manager / Caddy)+ 监控(Uptime Kuma)
—
0. 目录与权限约定(全文通用)
# 统一数据根目录(建议挂载在独立数据盘 / ZFS 数据集)
sudo mkdir -p /data/{media,downloads,config,backup}
sudo chown -R 1000:1000 /data/media /data/downloads /data/config # 你的日常用户 UID/GID
# Jellyfin 需要访问媒体库,qBittorrent 写下载目录,Alist 挂载网盘,Home Assistant 存配置
权限原则:容器以 PUID=1000 PGID=1000(你的用户)运行,避免 root 造成宿主机权限混乱;只有需要特权的容器(如 Home Assistant 的网络模式 host)才加 privileged: true。
—
1. 反代 + 自动 HTTPS:Nginx Proxy Manager(推荐新手)
图形化管理域名、SSL、访问控制、流量限制,零配置文件编辑。
# docker-compose.yml(片段)
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: npm
restart: unless-stopped
ports:
- "80:80"
- "443:443"
- "81:81" # 管理界面
volumes:
- /data/config/npm:/data
- /data/config/letsencrypt:/etc/letsencrypt
environment:
- TZ=Asia/Shanghai
- 首次访问
http://nas-ip:81,默认 admin@example.com / changeme,强制改密码
- 添加 Proxy Host → 填域名、转发到
http://容器名:容器端口 → 勾选 SSL → Request a new certificate → 自动申请 Let’s Encrypt 证书并续期
—
2. Jellyfin(媒体库)
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
restart: unless-stopped
network_mode: host # 硬解/DLNA 需要 host 网络;不想用 host 可改 bridge 并映射 8096
volumes:
- /data/config/jellyfin:/config
- /data/media:/media # 只读挂载媒体库
- /run/user/1000:/run/user/1000 # 硬解需要访问 /dev/dri
devices:
- /dev/dri:/dev/dri # Intel Quick Sync / AMD VCE 硬解
environment:
- TZ=Asia/Shanghai
- PUID=1000
- PGID=1000
首次配置要点:
- 向导选语言 → 创建管理员账号
- 媒体库 → 添加
/media/movies /media/tvshows /media/music → 启用 实时监控(inotify)
- 播放 → 启用硬件加速(Intel QSV / VAAPI / NVDEC)→ 测试转码
- 用户 → 为家人建非管理员账号,限制同时流数、码率
- 远程访问 → 关闭「自动端口映射」,改走 NPM 反代 + Tailscale(见第 6 篇)
—
3. qBittorrent(下载器 + 搜索插件)
services:
qbittorrent:
image: linuxserver/qbittorrent:latest
container_name: qbittorrent
restart: unless-stopped
ports:
- "6881:6881"
- "6881:6881/udp"
volumes:
- /data/config/qbittorrent:/config
- /data/downloads:/downloads
environment:
- TZ=Asia/Shanghai
- PUID=1000
- PGID=1000
- WEBUI_PORT=8080
必做配置:
- WebUI → 用户名/密码 → 勾选「使用另一个端口做 HTTPS」(不需要,NPM 已终结 SSL)
- 下载 → 默认保存路径
/downloads → 分类设置(电影/剧集/音乐/软件)
- 连接 → 关闭 UPnP/NAT-PMP(NPM + Tailscale 不需要) → 启用加密传输
- 搜索插件 → 安装
qBittorrent-Search-Plugins(GitHub 项目,一键导入 JSON)→ 启用 Jackett / Prowlarr 作为索引器(进阶)
—
4. Alist(网盘聚合 + WebDAV 直链)
services:
alist:
image: xhofe/alist:latest
container_name: alist
restart: unless-stopped
ports:
- "5244:5244"
volumes:
- /data/config/alist:/opt/alist/data
environment:
- TZ=Asia/Shanghai
核心用法:
- 登录
http://nas-ip:5244(默认 admin/admin)→ 修改密码
- 存储 → 添加:阿里云盘 / 115 / OneDrive / Google Drive / S3 / WebDAV / 本地挂载
- 设置 → 启用 WebDAV → Jellyfin 可直接挂载 Alist 的云盘为媒体库(
/media/cloud)
- 配合 qBittorrent:下载完成后用分类移动脚本(或
qbit_manage)自动整理到 /data/media,再由 Jellyfin 刮削
—
5. Home Assistant(智能家居中枢)
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
network_mode: host # 必须 host 网络才能发现 mDNS/广播设备
volumes:
- /data/config/homeassistant:/config
- /run/dbus:/run/dbus:ro # 蓝牙/系统总线
environment:
- TZ=Asia/Shanghai
privileged: true # 需访问串口/USB/Zigbee/Thread 调制解调器
首次配置:
http://nas-ip:8123 → 创建账号 → 检测设备
- 设置 → 设备与服务 → 添加集成:Zigbee2MQTT / ESPHome / Xiaomi MiIO / Shelly / Tuya / Matter / Thread
- 仪表盘 → 按房间/功能分组 → 启用「自动仪表盘」快速上手
- 外网访问 → 只走 Tailscale / WireGuard(见第 6 篇),绝不在 NPM 暴露 8123 端口
—
6. 自动更新:Watchtower(可选)
services:
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- TZ=Asia/Shanghai
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_SCHEDULE=0 3 * * * # 每天 03:00 检查更新
- WATCHTOWER_INCLUDE_RESTARTING=true
建议:核心服务(Jellyfin/HA)打标签 com.centurylinklabs.watchtower.enable=false 手动更新,边缘服务自动更新。
—
7. 完整 docker-compose.yml(汇总版)
version: "3.8"
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: npm
restart: unless-stopped
ports: ["80:80","443:443","81:81"]
volumes:
- /data/config/npm:/data
- /data/config/letsencrypt:/etc/letsencrypt
environment: [TZ=Asia/Shanghai]
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
restart: unless-stopped
network_mode: host
volumes:
- /data/config/jellyfin:/config
- /data/media:/media:ro
- /run/user/1000:/run/user/1000
devices: [/dev/dri:/dev/dri]
environment: [TZ=Asia/Shanghai,PUID=1000,PGID=1000]
qbittorrent:
image: linuxserver/qbittorrent:latest
container_name: qbittorrent
restart: unless-stopped
ports: ["6881:6881","6881:6881/udp"]
volumes:
- /data/config/qbittorrent:/config
- /data/downloads:/downloads
environment: [TZ=Asia/Shanghai,PUID=1000,PGID=1000,WEBUI_PORT=8080]
alist:
image: xhofe/alist:latest
container_name: alist
restart: unless-stopped
ports: ["5244:5244"]
volumes:
- /data/config/alist:/opt/alist/data
environment: [TZ=Asia/Shanghai]
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
restart: unless-stopped
network_mode: host
volumes:
- /data/config/homeassistant:/config
- /run/dbus:/run/dbus:ro
environment: [TZ=Asia/Shanghai]
privileged: true
watchtower:
image: containrrr/watchtower:latest
container_name: watchtower
restart: unless-stopped
volumes: [/var/run/docker.sock:/var/run/docker.sock]
environment:
- TZ=Asia/Shanghai
- WATCHTOWER_CLEANUP=true
- WATCHTOWER_SCHEDULE=0 3 * * *
- WATCHTOWER_INCLUDE_RESTARTING=true
部署:
cd /data && docker compose up -d
docker compose logs -f --tail=100
—
8. 常见坑 & 一句话解决
| 现象 | 原因 | 修正 |
| Jellyfin 硬解不生效 | 缺 /dev/dri 或驱动未装 | sudo apt install -y intel-gpu-tools vainfo → 验证 vainfo 有输出 |
qBittorrent 无法写入 /downloads | 权限不对 | sudo chown -R 1000:1000 /data/downloads |
| Alist 挂载云盘提示「Token 过期」 | 云盘授权码失效 | 重新点「添加存储」走 OAuth 流程,或手动填 refresh_token |
| HA 发现不了 Zigbee 网关 | 网络模式不是 host | 必须 network_mode: host + privileged: true |
| NPM 申请证书失败 | 80/443 端口被占用/防火墙拦截 | ss -ltnp | grep -E ":80|:443";云厂商安全组放行 80/443 |
—
9. 维护清单(贴在机柜上)
| 频率 | 动作 |
| 每天 | Watchtower 自动更新边缘服务 |
| 每周 | docker compose pull && docker compose up -d 手动更新核心服务 |
| 每月 | 检查 /data 磁盘占用、docker system df 清理无用镜像 |
| 每季度 | 导出 HA 配置快照(ha backup)、Jellyfin 元数据备份、npm 证书导出 |