我的第一台 NAS 都有些什么

Published
June 26, 2024
Updated
Last updated June 26, 2024
Description
我第一台 NAS 的折腾笔记
Progress
Under Correction
Author
Feng Kaiyu

缘起

我对 NAS 的需求主要是存储的需求——我手里有很多照片需要整理和存储,并提供容灾备份(我很喜欢
immich
immich-appUpdated Jun 29, 2024
这个项目)。除此之外,由于我对 Linux/Docker/服务器都有比较多的折腾经验,因此也时常会燃起“折腾一套 homelab” 的想法。
因此趁着毕业季,我从同学的手里入手了一个“DIY”的 NAS,重点的硬件参数如下:
  • CPU:i3-10100
  • 内存:16G
  • 存储空间:512 SSD + 4 个 4T HDD
之所以需要超出一般消费级 NAS 的内存和 CPU,是因为我对 Docker 有强需求,需要给未来的可能需求留出硬件性能。
notion image

使用 NixOS 作为操作系统

最近一段时间,由于对 NixOS 提出的“reproducible, declarative and reliable”比较感兴趣;且对其他 NAS 操作系统并没有更多的了解和偏好,因此选用了 NixOS。
装机过程在此不多赘述,值得注意的是,NixOS 的 Graphical ISO image 貌似必须联网才能使用,否则会在安装界面卡住。
由于对快照没有特殊要求,且为了降低运维复杂度,这次我没有使用 Btrfs。我将整个 SSD 挂载在了根目录,并将其余的机械硬盘以 LVM 的方式组成了两个逻辑卷(并挂载到了 /data 下),作为资源的实际存储和备份盘。
NixOS 在配置过程中可以用下面两个网站做辅助:
  • 可以方便搜索 packages 和 options。
  • 有一套面向新手的教程,便于快速开始使用 NixOS 、flakes、home-manager。

Self-host 软件

Docker mirror

由于此时 Docker Registry 在我所在的地区无法访问了,因此使用 Cloudflares 的 Workers 弄了个镜像,比如
cloudflare-docker-proxy
ciiiiiUpdated Jun 29, 2024
。网上有很多教程,不在此赘述。

Reverse Proxy 与 DNS

Caddy 在易用性上全面超越了 Traefik,因此本 NAS 使用 Caddy 作为反代。具体仓库是:
caddy-docker-proxy
lucaslorentzUpdated Jun 29, 2024
,利用这个仓库,我们仅通过配置 docker compose label 就可以非常方便地将流量从 Caddy 转发到实际的容器端口上。
我的域名的服务商就是 Cloudflare,因此我可以通过 Caddy 提供的 为我的域名和 wildcard 域名自动签发证书。一个简单的配置如下:
services: caddy: # 注意这里要替换成带有 provider 的镜像 image: lucaslorentz/caddy-docker-proxy:ci-alpine container_name: caddy ports: - 80:80 - 443:443 environment: - CADDY_INGRESS_NETWORKS=caddy networks: - caddy labels: caddy_1: '*.nas.example.com nas.example.com' caddy_1.tls.dns: "cloudflare $CLOUDFLARES_API_KEY" # 用于为 homepage 提供 Admin API caddy_2: ":12019" caddy_2.reverse_proxy: "localhost:2019" caddy_2.reverse_proxy.header_up: Host localhost:2019 caddy_3.admin: ":2019" volumes: - /var/run/docker.sock:/var/run/docker.sock - caddy_data:/data - ./config:/config/caddy restart: unless-stopped networks: caddy: external: true volumes: caddy_data: {}
对于某个服务则可以直接通过 label 指定:
version: '3.7' services: whoami: image: traefik/whoami networks: - caddy labels: caddy: '*.nas.example.com nas.example.com' caddy.1_@whoami: 'host whoami.nas.example.com' caddy.1_handle: '@whoami' caddy.1_handle.reverse_proxy: "{{upstreams 80}}" networks: caddy: external: true

Immich

immich
immich-appUpdated Jun 29, 2024
用来存放我的照片。
除了注意增加 caddy 所需的 label 以外,还需注意将存储卷挂载到我们之前组的 LVM (HDD)上面。
由于性能原因,我没有在 NAS 上启用机器学习的镜像。而是在我这台(有独显的)笔记本上不定期的启用 docker,然后让 NAS 上的 immich 定时使用机器学习服务。
在批量导入照片的时候,我发现 immich 在 Windows 底下还有一些 bug,顺手修了一下。
在导入相册之前,还需要针对现有的照片视频资源进行预处理,它们主要包括:
  • 由于之前拍摄的视频几乎都是 .MOV 的,采用 H265 的方式进行压制。(没有选择 H264 的主要原因是,H265 可以进一步提高空间利用率)。
  • 对于 DJI 录制的极高码率的 .MP4 视频,也再次进行压制(甚至 crf 可以调更大一些)。
需要注意的是,ffmpeg 在使用时要使用 -map_metadata 0 来保证新视频保留了真正的录制时间。

Jellyfin

用于存放影视资源。目前还没有配置 *arr 周边服务。
为了方便从笔记本传输一些影视资源,我又额外配置了 Samba 并挂载到了笔记本上。

Nextcloud 从入门到劝退

曾经 host 过 nextcloud,对其印象还是比较好的。但是这次 NAS 上我最终决定放弃 nextcloud,原因如下:
  • Nextcloud All in One,整体做的比较奇怪,实际上是采用了类似 docker in docker 的方案,导致很多配置是黑盒的。
  • Nextcloud 的性能没有我想象得那么好,并且比较吃资源。
  • 我对网盘其实没有太多需求,本质上只是需要一个可视化的资源管理器。
因此最终我选用 作为替代。

Tailscale

由于没有公网 IP,因此想要在外网访问 NAS 的时候,我通过 来解决隧道问题。
由于 Tailscale 会为各个设备自动分配新的 IP,导致一般情况下域名解析失效,因此此时难题是:怎么保证使用 Tailscale 时,能同样通过域名找到我的服务?
首先,Tailscale 自带的 MagicDNS 是无法使用的,因为其既不能自定义域名、也没有 wildcard 解析、更没法进行 DNS Callenge。
好在,Tailscale 提供了自定义 DNS 服务器的能力:
notion image
因此我选择在 NAS 上使用 自建了一个 DNS,然后按照 Tailscale 的 IP 对域名进行解析。这样就能保证内外网的域名解析是一致的了。

备份策略

本来想使用
borg
borgbackupUpdated Jun 28, 2024
进行备份的,但是偶然发现
restic
resticUpdated Jun 29, 2024
、更加直观,因此选择了后者。
根据两地三副本的策略,在 NAS 上我通过 restic &
resticprofile
creativeprojectsUpdated Jun 29, 2024
定时备份,并会定期将备份 copy 到另一个移动硬盘(也可以考虑云盘)上。
硬盘的完整性目前手动通过 SMART 进行检测。