Featured image of post 我折腾 NAS 的历程(三):捡垃圾自组

我折腾 NAS 的历程(三):捡垃圾自组

本文记录了我通过自行购买配件(捡垃圾)DIY 出一台 NAS 的过程

组这台 NAS 前的事情:

理论

装机配置单

品牌型号参数购买价购买链接
CPUIntelE5-2660 v414 核 2.0GHz 规格表¥52(洋垃圾)link
内存SamsungM393A2G40DB0-CPBDDR4 2133MHz 16GB 规格表¥92(洋垃圾)link
主板华南金牌X99-4MFITX DDR4x4 SATAx3 规格表¥268link
系统盘SKHynixHFS512GDE9X084N512GB NVME¥0*
显卡NVIDIAGeForce 605规格表¥16(亮机卡)link
电源航嘉GX500500W ATX 白牌¥191.92link
机箱invasioninvasion X14盘位 ITX¥244link
CPU 散热器零下30度--¥38.7link
机箱风扇航嘉MVP1201500 RPM,支持 PWM¥75.95(三只装)link
总计¥978.57

*笔记本上拆下来的

攒机理念

目标:省钱、性能还行、体积小、静音、保留一定的可升级性、尽量一手

关于 CPU,我在CPUbenchmark上按照跑分结果在E5的一系列洋垃圾型号中从高到低翻,最后看中了 E5-2660 v4。选择它有以下几点理由:

  1. 其功耗相比与同系列其它型号较低;
  2. E5-2660 v4 为 2016 Q4 推出的,相对 v3 和 v2 要新一点;
  3. 其性价比在同型号中较高,52 元 16005 分,相较于2690 v3 的 68 元 16505 分更实惠。

CPU 定下来了之后,主板和内存也就相应的决定了。之所以主板不选二手是因为我想省点事,对于二手市场上可能遇到的众多问题我目前没有任何应对经验。而选择 ITX 是为了满足体积小的要求,毕竟宿舍里放不下太多东西。

关于系统盘,之前给笔记本升级外存的时候拆下来的原装 SSD 可以直接给它用。就算是买一个全新的也不会太贵,256GB 买个二线厂的 SSD 应该也够用了。 在装系统、进 BIOS 时显卡是必要的,作为服务器 CPU 的 E5-2660 v4 没有核心显卡,因此这里依然需要一张显卡。上淘宝一搜果然有卖亮机卡的,16 元的价格也就不用纠结值不值了,能亮就行。为了能看到视频输出我还买了一个二十多的 HDMI 采集卡以代替显示器,事实证明二十块的画质果然不行。 电源不敢买二手的,怕出问题。500W 的电源相对于目前的整机功耗明显是过剩的,但这也为以后的升级保留了余量。 最后是机箱,综合以上要求,机箱应该是体积小、轻便、便宜的多盘位 ITX 机箱,在淘宝上翻了一大圈只看到这一款同时满足这几点的。别的型号,例如蜗牛星际、御夫座、天箭座等都太贵了或者散热容量太小。两百多的机箱我觉得还是贵了点,可是也没找到更好的选择。

关于可升级性,这套配置中,CPU 可以升级为 24686 分的 E5-2699 v4(在价格降下来之后),还有三个位置可以加内存条,显卡可以升级,机箱和电源以后也能用于装游戏电脑。

实践

装机过程

装机过程中遇到的问题有四:

  1. CPU 散热器的螺丝是弯的(可能是制造问题),要用钳子扳直了才能安装;
  2. 机箱自带的硬盘笼和主板电源插槽有 2mm 左右的 overlap,装完之后硬盘笼有一点点变形。得益于硬盘架的减震机构,这个变形产生的影响不大;
  3. 主板下部的插槽和机箱风扇有冲突,前面板 USB-3 的线插不进去,但对于 NAS 而言这根线不插问题也不大;
  4. 华南金牌的这款主板的主板风扇插槽只有 3 针,不支持 PWM,直接插 MVP120 的话满转速噪音非常大。我最后用一拖三的线把所有风扇都接到了支持 PWM 的 CPU 风扇插槽上,这样就安静了很多(之后又进BIOS 调整了一下温度-转速曲线)。

操作系统

因为我最熟悉的 Linux 发行版是 Ubuntu,所以我安装了 Ubuntu 22.04.2 LTS(服务器版)。

系统盘分区如下:

1
2
3
4
5
6
Mountpoint      Start        End   Sectors   Size Type
/boot/efi        2048    2203647   2201600     1G EFI System
/             2203648  107061247 104857600    50G Linux filesystem
/home       107061248  211918847 104857600    50G Linux filesystem
/srv        211918848  958271487 746352640 355.9G Linux filesystem
swap        958271488 1000214527  41943040    20G Linux swap

测试

整机待机时 CPU 核心平均温度为 30°C,满载时为 55°C,说明散热还是有很大的余量的。服务正常运行时插座上测量到的功率在 68W 左右,CPU满载时约 140W。

使用 sysbench 的测试结果如下,和我现役的游戏本相比我觉得这个成绩还算可以接受:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
sysbench 1.0.20 (using system LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 28
Initializing random number generator from current time


Prime numbers limit: 10000

Initializing worker threads...

Threads started!

CPU speed:
    events per second: 17251.86

General statistics:
    total time:                          600.0017s
    total number of events:              10351174

Latency (ms):
         min:                                    1.22
         avg:                                    1.62
         max:                                   82.58
         95th percentile:                        1.64
         sum:                             16797418.36

Threads fairness:
    events (avg/stddev):           369684.7857/436.76
    execution time (avg/stddev):   599.9078/0.00

软件部分

Docker

最先安装的是 Docker,因为有了 Docker 之后别的应用都可以使用 Docker 镜像安装和管理。

在 Ubuntu 上安装Docker只需使用官方提供的安装脚本[1]

1
2
$ curl -fsSL https://get.docker.com -o get-docker.sh
$ sudo sh get-docker.sh

修改Docker数据位置

Docker 的数据默认储存在 /var/lib/docker 内,我想将其移到 /srv 文件系统内,操作如下:

  1. 关闭docker服务:systemctl stop docker
  2. 移动文件:sudo mv /var/lib/docker /srv/
  3. 创建符号链接(以防万一):sudo ln -s /srv/docker /var/lib/docker
  4. 修改配置文件,在/etc/docker/daemon.json内添加配置:{"data-root": "/srv/docker"}
  5. 启动docker服务:systemctl start docker

使用Docker国内镜像源

阿里云提供了免费的Docker镜像源的加速服务。为了使用该服务,需要在 https://aliyun.com 登录阿里云帐号,然后在 控制台 > 容器镜像服务 > 镜像工具 > 镜像加速器 处可以获取加速器的地址及修改镜像源的方法。

此外也有一些开放的镜像源,在/etc/docker/daemon.json内添加如下属性 [2]

1
2
3
4
5
6
7
8
{
  "registry-mirrors": [
    "https://hub-mirror.c.163.com",
    "https://ustc-edu-cn.mirror.aliyuncs.com",
    "https://ghcr.io",
    "https://mirror.baidubce.com"
  ]
}

修改后使用 systemctl restart docker 重启docker服务即可。

手动下载镜像

如果替换了镜像源之后也拉不动镜像的话,可以试试 Moby Project 提供的镜像下载脚本下载镜像:link

使用例:

1
2
3
4
5
6
7
8
9
$ wget https://raw.githubusercontent.com/moby/moby/master/contrib/download-frozen-image-v2.sh
$ bash ./download-frozen-image-v2.sh ./alpine-linux alpine:latest
Downloading 'library/alpine:latest@latest' (1 layers)...
-#O=-#      #        #
############################################## 100.0%

Download of images into './alpine-linux' complete.
Use something like the following to load the result into a Docker daemon:
  tar -cC './alpine-linux' . | docker load

这时镜像就已经保存到./alpine-linux内了,然后使用

1
2
3
$ tar -cC './alpine-linux' . | docker load
......
Loaded image: alpine:latest

即可让 docker 导入镜像。

samba

1
$ sudo apt install samba

安装后使用smbpasswd -a <username>为用户添加 samba 的访问密码,其中<username>必须为已经在 Linux 内注册的用户。

配置文件为/etc/samba/smb.conf,配置项可参考官方文档

1
2
3
4
5
6
[<share name>]
path = /path/to/folder
read only = no
browsable = yes
guest ok = no
valid users = <users>

jellyfin

jellyfin 是数字媒体管理与串流软件,它支持浏览器、Android、iOS、Android TV 等许多客户端,可以在这些客户端上便捷地观看服务端存储的内容,这也是我攒这台 NAS 的主要目的。E5-2660 v4 的性能足以支持 jellyfin 流畅编解码超高清资源(软解,不过目前看来也没有专门为这个买 GPU 的必要了)。

可以使用官方的 docker 镜像或者linuxserver.io 制作的镜像来安装 jellyfin。

为了便于我管理和配置,所有的 Docker 容器都将使用 docker compose 启动。这是 jellyfin 的docker-compose.yaml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: "2.1"
services:
  jellyfin:
    image: lscr.io/linuxserver/jellyfin:latest
    container_name: jellyfin
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
    volumes:
      - ./config:/config
      - /path/to/media:/data
    ports:
      - 8096:8096
      - 8920:8920 #optional
      - 7359:7359/udp #optional
      - 1900:1900/udp #optional
    restart: unless-stopped
    deploy:
      mode: global
      resources:
        limits:
          cpus: '20'
          memory: 8G

qbittorrent

qbittorrent 是用于 bt 下载的软件。linuxserver.io 也打包了 qbittorrent 的镜像,使用这个镜像运行即可。我的docker-compose.yaml如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
services:
  qbittorrent:
    image: lscr.io/linuxserver/qbittorrent:latest
    container_name: qbittorrent
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
      - WEBUI_PORT=4823
    volumes:
      - ./config:/config
      - ./torrents:/torrents
      - ./cache:/cache
      - /path/to/downloads:/downloads
    ports:
      - 4823:4823 # WebUI
      - 6881:6881 # 监听端口
      - 6881:6881/udp
      - 14560-14580:14560-14580 # 传出端口
      - 14560-14580:14560-14580/udp
    restart: unless-stopped
    deploy:
      mode: global
      resources:
        limits:
          cpus: '2.0'
          memory: 1G

frpc

内网穿透工具的客户端,我用的是下载量最高的镜像

coredns

DNS 服务器,因为学校的 DNS 以前崩过,所以装一个备用。官方镜像即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
services:
  coredns:
    image: coredns/coredns:latest
    container_name: coredns
    volumes:
      - ./config:/config
    command: ["-conf", "/config/Corefile"]
    restart: always
    ports:
      - 0.0.0.0:53:53
      - 0.0.0.0:53:53/udp
    deploy:
      mode: global
      resources:
        limits:
          cpus: '0.5'
          memory: 100M

53 端口可能和 ubuntu 的 systemd-resolved 服务冲突,在启动容器前需要先关闭这个服务:

1
2
$ sudo systemctl disable systemd-resolved
$ sudo systemctl stop systemd-resolved

coredns 结合 nginx/Apache 转发与一些路由器的设置就可以实现内网域名(不用记端口号了),例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
### Corefile:
......
server.local {
  hosts {
    192.168.0.xx jellyfin.server.local
  }
  log
  errors
  prometheus
}

### nginx config:
server {
       listen 80;
       server_name jellyfin.server.local;
       location / {
           proxy_pass http://127.0.0.1:8096;
       }
}

这样在局域网直接访问 http://jellyfin.server.local 就可以进入 jellyfin 的界面了。

注:关闭 systemd-resolved 服务之后在使用 KVM 时可能会遇到一些问题。

Grafana & Prometheus

GrafanaPrometheus 这两个开源软件组合在一起可以用来监控服务器状态(不过在自用的 NAS 上搞这个可能意义不大)。之前没了解过这些软件,因此这部分完全是按照教程安装的,其中 Grafana 不涉及数据收集,可以在 Docker 容器中运行。

除了这两个软件,我还安装了 node exportercadvisor,分别收集服务器系统与 Docker 容器的统计信息。

装好之后,我以 node exporter 为基础改出了这样的 dashboard:

数据库

有一些服务(例如 gitea 和自己写的爬虫)的数据是存储在数据库中的,我比较喜欢将这些数据放在同一个数据库服务端内(而非给每个有需要的应用都运行一个数据库),以便于数据的管理,同时减少系统占用。

关于关系型数据库,我使用的是 mariadb(MySQL的一个衍生版本)。关于镜像的版本,建议使用一个固定的版本号(而非 latest),因为在不同版本的 mariadb 之间迁移数据还是比较麻烦的。

关于数据库的管理端,我以前常用的是 phpmyadmin,这次想试试别的,所以使用了 官方docker镜像页 里提到的 adminer。其功能虽不如 phpmyadmin 丰富,界面也不如它美观,但是我平时会用到的基础操作(建表、查看数据、SQL 查询、导出数据)它都有,缺少的功能可以直接用 SQL 语句凑嘛~

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
services:
  db:
    image: mariadb:10.11.4
    container_name: mariadb
    restart: always
    environment:
      MARIADB_ROOT_PASSWORD: ...
    volumes:
      - ./mariadb:/var/lib/mysql
    ports:
      - 3306:3306

  adminer:
    image: adminer
    container_name: adminer
    restart: always
    ports:
      - 8080:8080

如果服务需要,也可以使用 docker 运行非关系型数据库 MongoDBredis

Minecraft 服务器 (papermc)

选了 docker hub 里搜索排名靠前的 marctv/minecraft-papermc-server

用了之后才发现,papermcSpigotMC 的分支,旨在提供原生 Minecraft 的体验。也就是说它不支持以前我在玩 Minecraft 时耳熟能详的那些 Forge 版 mod,只支持服务器端的 bukkit 插件(plugin)。好处是相比与 Forge 服务器占用更小,并且不挑客户端,只要客户端 Minecraft 版本和服务器一致就能连上。 配置好之后,使用 frpc 转发 25565 端口到公网,就可以愉快地和朋友们一起玩啦。

后台管理

在 docker-compose.yaml 中对应的 service 配置里加上

1
2
3
stdin_open: true
tty: true
container_name: mcserver

然后

1
$ docker compose up -d

之后便可以通过

1
$ docker attach mcserver

进入服务器后台,使用指令管理服务器。

配置

papermc 相比于原版服务端修复了活塞相关的一些“特性”,例如使用活塞复制物品等,并在配置文件中默认限制这些行为,导致刷地毯机/破基岩等原版可行的操作在 papermc 服务端内不可用。当然这样对于服主而言确实可以防止玩家做出越界的行为,但是对于我这种只有几个朋友在一起玩的服务器,就不需要限制这些了。关闭限制的方式很简单,修改数据目录下的paper.yml,将allow-headless-pistonsallow-permanent-block-break-exploitsallow-piston-duplication三项设置为true即可。

安装插件

Papermc 支持的插件可以在 HangerbukkitSpigotMC下载。下载对应版本的 jar 文件放到 /data/plugins 文件夹下(或者直接使用 wget/curl 下载),然后重启服务器,在启动时如果新增的插件没有报错误信息,那大概率是没问题的。

目前加了这些插件:

  • Minepacks:背包插件;
  • TreeFeller:连锁砍树;
  • worldedit:创世神插件;
  • worldguard
  • EssentialsX:正如其名,提供一些服务器的必备功能;
  • StackableItems:增加物品堆叠上限;
  • Multiverse-Core:多世界基础插件。
    • Multiverse-signportals:使用告示牌在多世界间传送;
    • OpenTerrainGenerator:创建不同类型世界的基础插件之一。
      • Skylands
      • FarFromHome
  • ViaVersion:放宽客户端版本限制;
  • LaggRemover:减少服务器卡顿;
  • BlueMap: 地图插件,提供了美观的在线3D地图;
  • UnifiedMetrics:数据收集插件,支持前述的 Prometheus。

参考资料

[2] Docker 换源 - 腾讯云开发者社区 | https://cloud.tencent.com/developer/article/1769231
使用 Hugo 构建
主题 StackJimmy 设计