想在外面用手机看 NAS 上的书,或者把简单书房装到手机桌面,都需要从外网用 HTTPS 访问。本文介绍速度最快的一种做法:手机直接连到家里的 NAS,不经过任何中转。
整体分四块:
- DDNS:让域名始终指向家里当前的公网 IP。绿联 NAS 自带,支持 Cloudflare。
- 证书:用 acme.sh 容器申请 Let's Encrypt 免费证书,到期前自动续签,直接写进简单书房的证书文件夹。
- 开启 HTTPS:在简单书房的设置里打开开关(1.3.0 起支持)。
- 端口转发:在路由器上把一个端口转到 NAS。
简单书房只负责「用你的证书提供 HTTPS」,不会帮你申请或续签证书。证书由下面的 acme.sh 负责。
全文以域名 book.example.com、外网端口 18443、NAS 路径 /volume1/docker/... 为例,换成你自己的即可。
先确认能不能直连
1. 家里有没有公网 IP
- 在路由器管理页看「WAN 口 IP」,再用手机连家里 Wi-Fi 打开 ip.cn 看显示的 IP。两个一致才是公网 IPv4。
- 不一致说明在运营商的大内网里,可以打电话找运营商要公网 IP(多数地区免费);或者使用 IPv6(手机流量基本都支持,需要路由器开启 IPv6 并放行 NAS)。
2. 端口:国内家庭宽带一般封了 80 和 443,要用别的端口,本文用 18443。
3. 域名:需要一个托管在 Cloudflare 上的域名(几块钱一年的就够)。只有 IP、没有域名时拿不到浏览器信任的证书,也就没法装到手机桌面。
拿不到公网 IP 的话,直连这条路走不通,可以改用 Tailscale 或 Cloudflare 隧道(速度较慢),见文末。
第一步:在 Cloudflare 准备三样东西
- API Token:右上角头像 → My Profile → API Tokens → Create Token,选模板 Edit zone DNS,Zone Resources 选
Include → Specific zone → 你的域名,创建。Token 只显示一次,是一串 40 位左右的字母数字,复制下来保存好。不要复制页面上的示例命令或链接。 - 账户 ID(Account ID):进入域名的概览页,右下角「API」一栏。
- 区域 ID(Zone ID):同一个位置,账户 ID 上面那一行。
DDNS 和申请证书用同一个 Token。三样东西都不要发给别人,也不要贴到群里或截图里。
第二步:在绿联 NAS 上设置 DDNS
打开 控制面板 → 设备连接 → 远程访问,在「方式二」里勾选 启用DDNS支持,点 新增:

| 字段 | 填什么 |
|---|---|
| DDNS服务商 | cloudflare |
| 已注册的DDNS域名 | book.example.com |
| AccessKey ID | Cloudflare 的账户 ID |
| AccessKey 密钥 | 第一步的 API Token |
| IPv4 / IPv6 | 保持「自动」 |
点「应用」后回到列表,能看到外部 IPv4(和 IPv6)就说明更新成功:

保存后再点「编辑」,AccessKey 密钥一栏显示的是一长串加密后的内容(100 多位),不是原来的 Token。后面申请证书时要用原始 Token,不要从这里复制。
关键:回到 Cloudflare 的 DNS 页面,确认 book 这条记录的代理状态是 灰色云朵(DNS only)。如果是橙色,点成灰色。橙色会让流量绕经 Cloudflare,既慢,又不支持 18443 这类端口。
第三步:用 acme.sh 申请免费证书
acme.sh 会通过 Cloudflare 验证域名、申请 Let's Encrypt 证书,并且每天检查一次,快到期时自动续签,一次配置,之后不用管。
1. 创建 acme 项目
先在文件管理里确认简单书房的数据目录下有 certs 文件夹(没有就新建一个),例如 /volume1/docker/easy-reader/certs。
然后打开 Docker → 项目 → 创建,项目名称填 acme,存放路径选 docker/acme,Compose 配置填:
services:
acme:
image: neilpang/acme.sh
container_name: acme.sh
restart: unless-stopped
command: daemon
environment:
- CF_Token=你的API令牌 # 第一步的 API Token
- CF_Zone_ID=你的区域ID # 第一步的 Zone ID
- CURL_HOME=/acme.sh # 读取 data/.curlrc(网络慢时设置超时,见下文)
volumes:
- ./data:/acme.sh # acme.sh 的数据(账号、证书)
- /volume1/docker/easy-reader/certs:/certs # 简单书房数据目录下的 certs

把第二个挂载的路径换成你自己的简单书房数据目录,点「立即部署」。
2. 在容器终端里申请证书
打开 Docker → 容器 → acme.sh → 终端,点「新增」,命令改成 /bin/sh(这个镜像里没有 bash),确定。依次执行:
# 用 Let's Encrypt(默认是 ZeroSSL,需要额外注册)
acme.sh --set-default-ca --server letsencrypt
# 申请证书;只给一个域名用就写这一个
acme.sh --issue --dns dns_cf -d book.example.com
# 安装到简单书房的证书文件夹,以后续签也会自动覆盖这两个文件
acme.sh --install-cert -d book.example.com --ecc \
--key-file /certs/privkey.pem --fullchain-file /certs/fullchain.pem
申请成功时会看到类似这样的输出:
[...] Verifying: book.example.com
[...] Success
[...] Verification finished, beginning signing.
[...] Downloading cert.
[...] Your cert is in: /acme.sh/book.example.com_ecc/book.example.com.cer
想让多个子域名共用一张证书,可以申请通配符证书:
-d '*.example.com' -d example.com,安装时-d '*.example.com'。
第四步:在简单书房里开启 HTTPS
1. 加上 HTTPS 端口映射
在简单书房的 Compose 配置里,ports 下加一行,左边是 NAS 上的端口,右边 3443 不要改,然后重新部署项目:
ports:
- "8080:3000"
- "18443:3443"
2. 打开开关
用管理员登录,进入 设置 → 系统 → HTTPS 证书,打开 启用 HTTPS。证书已在 certs 文件夹里,状态会变成「HTTPS 已开启」,并显示域名和到期时间:

(截图里是演示用的自签证书;你那里颁发者会显示 Let's Encrypt。)
以后 acme.sh 续签覆盖了证书文件,简单书房会自动换上新证书,不用重启。局域网里仍然可以用原来的 http://NAS地址:8080 访问,不受影响。
已经有现成证书(购买的或别处申请的)的,也可以不用 acme.sh:在这个卡片里直接上传
fullchain.pem和privkey.pem(私钥不能带密码),或者把这两个文件放进certs文件夹。缺点是到期要自己换,简单书房会在到期前 14 天提醒。
第五步:路由器端口转发
在路由器的「端口转发 / 虚拟服务器」里添加一条:外部端口 18443 → NAS 的局域网 IP,内部端口 18443,协议 TCP。各家路由器界面不同,找「端口转发」「虚拟服务器」「NAT」之类的菜单。
只转发这一个端口,不要把 NAS 管理页面(9999 等)暴露到外网。用 IPv6 时不需要转发,但要在路由器的 IPv6 防火墙里放行 NAS 的 18443。
验证
手机 关掉 Wi-Fi、用流量,打开 https://book.example.com:18443:地址栏显示安全锁、能正常登录就成功了。接着可以把它装到手机桌面。
在家里用 Wi-Fi 打开这个地址可能打不开,这是很多路由器不支持「从内网访问自己的公网地址」(NAT 回环),不影响外网使用。家里继续用局域网地址即可。
常见报错
申请证书时 Invalid format for Authorization header 或 invalid domain
Token 填错了:复制成了链接、示例命令,或者复制了绿联 DDNS 里加密后的密钥。回 Cloudflare 重新创建一个 Token,只复制那串 40 位左右的字母数字,前后不要有空格和引号。改完在 Docker 里重新部署 acme 项目,环境变量才会生效。Zone ID 也要确认是这个域名的(32 位)。
申请卡住好几分钟,最后报 Cannot make POST request ... error code: 28
NAS 到 Let's Encrypt 的网络时好时坏,有的请求会一直挂着,acme.sh 默认要等 5 分钟才重试。在容器终端里执行一次:
echo 'max-time = 60' > /acme.sh/.curlrc
请求超过 60 秒就放弃并自动重试(最多 20 次)。这个文件存在挂载的 data 目录里,配合 Compose 里的 CURL_HOME=/acme.sh,以后自动续签也会用到。然后重新执行申请命令。
设置页显示「证书与私钥不匹配」「证书无法用于 HTTPS」
certs 里的两个文件不是同一张证书的,重新执行一次 --install-cert。
打不开怎么办
按顺序排查:
- 域名解析:在电脑上
ping book.example.com,看解析出来的是不是家里的公网 IP;不是的话检查 DDNS 列表是否显示了外部 IP、Cloudflare 记录是否为灰色云朵。 - 端口被封:换一个端口(比如 28443),compose 映射、路由器转发和访问地址一起改。
- 设置页状态:「HTTPS 证书」里是否显示「HTTPS 已开启」。
- 证书域名:访问用的域名要和证书上的域名一致(通配符证书覆盖
xxx.example.com)。
没有公网 IP:其他办法
- Tailscale:手机和 NAS 都装 Tailscale,组成私有网络,在外面用 Tailscale 分配的地址访问。不需要公网 IP 和端口转发,但手机上要一直开着 Tailscale。
- Cloudflare 隧道:无需公网 IP,Cloudflare 提供 HTTPS;国内访问速度一般较慢。