>

适用场景:刚装好 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,默认 [email protected] / 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 证书导出
— 感谢阅读 —

一起交流

分享你的思考,让讨论更进一步。