Skip to content
Go back

我的赛博家园环境搭建

Published:

前言

懒惰的 SilentE 太久没输出文章,他感觉不能再这么颓废下去了,所以想要 push 自己写写东西,技术的,感悟的,都想写写。于是乎 SilentE 决定以环境搭建的文章作为开头(因为很好水) XD

系统选择

  • SER6MAX 迷你主机 (Ubuntu24)
  • 天钡 WTR PRO (Unraid)
  • 联想拯救者 R9000P (Win11)
  • MacBook (MacOS)

除了 windows 和 mac 没啥悬念外,迷你主机的系统在之前有很多尝试。

刚买的时候,我对于这个迷你主机的需求是做 Linux 开发,同时兼顾一些自建服务的运行,因此当时的选择是 Arch Linux 桌面环境,同时加了一个 DP 欺骗器让迷你主机即使关闭了显示屏幕也不会进入休眠状态。当时是我第一次接触 Arch,踩了不少的坑,不过在缝缝补补下居然勉强能用,至少开发没遇见啥问题。后来感觉 Manjaro 不错,也属于 Arch 系,所以切换到了 Manjaro 并沿用了很久。除了遇见偶尔开机不成功需要重复几次外,Manjaro 的体验可以说是没有任何问题。

不过后面感觉 linux 下的开发也没必要非得在 linux 环境下进行 XD,windows WSL / macOS 也能 linux 开发!所以桌面环境对我来说表现得不是很重要了,而又由于我的 KVM 切换器只支持两个输入,win 和 mac 已经占了,那确实也没必要再搞个桌面环境了。

然后就是看 Linux Server 的选择,一开始的选择是 PVE,装上体验了一番,感觉它的功能确实很强大,不过对于我来说操作有点繁琐了:我就想部署一些自用服务在小主机上,感觉也不会怎么用到 PVE 提供的虚拟机功能,docker 的易用性对于个人来说是大于虚拟机的。所以为了图省事,还是选择了 Ubuntu Server,问就是将懒狗精神发挥到底。

至于 NAS 的系统,感觉也没啥太多选择,在使用 Unraid 之前浅浅尝试了一下飞牛,感觉专业性目前来看确实还不太行,至于其他方面没怎么细研究也不知道具体啥情况,直接 Unraid 了。最喜欢 Unraid 的一点就是它并没有采用 raid 阵列,而是通过校验盘的方式来保证数据安全,甚至允许不加校验盘让数据裸奔。不过我到觉得无所谓,存 NAS 的数据丢就丢了呗,重要的数据肯定是多重备份的,因此我从咸鱼上低价买了两块 4T 红盘,全部都是数据盘来作为 NAS 的存储阵列。

网络

网络构成很简单,有无线网卡的机器都直接走宿舍 AP 连接校园网,NAS 的机器 WTR PRO 没有无线网卡那就走 SER 的共享网络上网,通过交换机 192.168.137.0/24 网段来做有线内网互相访问,一些敏感服务也只允许该内网网段访问。同时使用 tailscale 设置 NAS 的子路由,以便 ts 上的所有机器能够通过 SER 来访问 NAS。

以下命令能够将 wlp2s0 的网络共享给 enp1s0,记得提前开启 ipv4, ipv6 转发。

sudo iptables -t nat -A POSTROUTING -o wlp2s0 -j MASQUERADE
sudo iptables -A FORWARD -i enp1s0 -o wlp2s0 -j ACCEPT
sudo iptables -A FORWARD -i wlp2s0 -o enp1s0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo ip6tables -t nat -A POSTROUTING -o wlp2s0 -j MASQUERADE
sudo ip6tables -A FORWARD -i enp1s0 -o wlp2s0 -j ACCEPT
sudo ip6tables -A FORWARD -i wlp2s0 -o enp1s0 -m state --state RELATED,ESTABLISHED -j ACCEPT

应用服务们

daed

daed 透明代理,提供给本机以及所有共享机器一个优雅的网络环境。

万事第一步先配置好网络环境 XD。在没有网络环境下,只能 ssh 连上去把 daed 安装包扔到迷你主机上然后再 dpkg 解压安装。根据指南安装完成后设置密码后就能使用了,不过对于 2023 管理端口最好还是设置防火墙拦一下。

iptables -A INPUT -i wlp2s0 -p tcp --dport 2023 -j REJECT --reject-with tcp-reset && iptables-save

daed 有一个很用的点就是他能代理所有网卡,因此迷你主机的无线网络共享给了 NAS,只需要在 LAN 接口勾选连接内网的有线网卡,NAS 同样能够无感走这个透明代理。

Portainer CE

Portainer 主要用于查看以及可视化管理本机以及 NAS 上的所有 Docker 服务。

依照官网教程安装部署即可。

迷你主机本地的 Docker 端点连接没什么可说的,直接在 Portainer 中就能看见。这里主要说明一下其他机器的 Docker 连接,也就是 Portainer Agent。agent 端这里最简单方法就是 docker API 来实现连接。

对于具体 NAS 的 Unraid 系统来说,需要修改 /boot/config/docker.cfg 这个文件内容。

增加 DOCKER_OPTS="-H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock" 后在 web 页面重启 Docker 服务,这样就能在 Portainer 中看见 NAS 中的 Docker 服务情况。

由于这个直接开放比较危险,所以需要设个规则拒绝一下,只允许可信内网网络访问。这里只让内网有线访问,拒绝一切从无线网卡过来的 FORWARD。

iptables -A FORWARD -i wlp2s0 -p tcp --dport 2376 -j REJECT --reject-with tcp-reset && iptables-save

Tailscale

tailscale 用于组建远程大内网环境,方便自己的其他设备互相访问

依照官网教程安装即可,顺便在阿里云的北京服务器上装了一个 derp,延迟在 7ms 左右。

qBittorrent

种子下载器,用于挂 bt 下载一些感兴趣的资源。

最开始是想把 qB 直接放在 NAS 上,但是学校的 pt 站只允许 ipv6 连接,而我捣鼓半天网络硬是没把 NAS 的 ipv6 配好,所以目前是将 qB Docker 容器部署在迷你主机上,然后下载到通过 SMB 挂载的 NAS 文件系统中。

首先需要在 unraid 中开启共享文件夹,这里开启了名称为 Media 的共享文件夹,全部存在阵列上,然后小主机端使用 smb 挂载。

sudo apt install cifs-utils
sudo mount -t cifs //192.168.137.2/Media /opt/nas/media -o rw,dir_mode=0777,file_mode=0777,username=$user,password=$password

然后使用 Docker 部署 qB WebUI 版本,使用的具体版本是 nevinee/qbittorrent,对 compose 文件做了以下修改:

  • 增加 QB_USERNAMEQB_PASSWORD 环境变量指定登录用户名和密码
  • /data/downloads 映射到主机的下载目录,这里已提前将 nas 的目录通过 smb 挂载到了 /opt/nas/media
  • 使用 host network
services:
  qbittorrent:
    image: nevinee/qbittorrent
    container_name: qbittorrent
    restart: always
    tty: true
    network_mode: host
    hostname: qbitorrent
    stop_grace_period: 10m
    volumes:
      - /opt/nas/media:/data/downloads
    tmpfs:
      - /tmp
    environment:
      - WEBUI_PORT=8085   # WEBUI控制端口,可自定义
      - BT_PORT=34567     # BT监听端口,可自定义
      - PUID=1000         # 输入id -u可查询,群晖必须改
      - PGID=100          # 输入id -g可查询,群晖必须改
      - QB_USERNAME=$USERNAME
      - QB_PASSWORD=$PASSWORD

Nextcloud

Nextcloud 用于个人的一些文件存储和分享,不过感觉这个玩意比较鸡肋,正在考虑寻找替代…

这个是部署在 NAS 上的 Docker 容器,直接在 Unraid 应用市场中先部署一个 mariadb,再部署 nextcloud 即可,如果需要新增域名,需要按照提示进 Docker 容器里去改一些配置,改完保存即可。

Jellyfin

自建影音服务,用来播放一些好看的。

Jellyfin Docker 容器同样的放在了 NAS 上,这里采用了 linuxserver 提供的 Jellyfin 镜像。不过不知道为啥已经在 Docker 设置中和 Jellyfin 设置中都设置好了硬件解码,但每次转码的时候 CPU (AMD 5825U) 还是红的,而核显动都不动一下。。。

对于动漫的刮削则使用了 bangumi 插件进行增强,具体介绍可以看这篇博文

Caddy

Caddy 主要用于反代一些内网服务,套层 HTTPS 并使用内网域名/私有域名/公开域名访问。

装 caddy 主要用来做反代的,同时希望做到不同等级的访问控制。

  • *.se.local: 只允许本地 + ts net 访问,使用本地自签域名
  • *.priv.silente.app: 部分服务公开在校园网,使用 ddns + cf 域名
  • *.pub.silente.app: 部分服务允许公开访问,使用 cf tunnel

至于安装的话就没有用 Docker 了,直接裸机装了。由于我的域名服务商是 cf,所以需要用 cf dns module,可以使用 xcaddy 自行编译,参考文章

go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
xcaddy build --with github.com/caddy-dns/cloudflare

但其实似乎 caddyserver 上也能直接下载到编译好的附带 module 的二进制程序。

访问控制根据 remote_ip 来限制:

(only_for_whitelist_ip) {
	@denied {
		not remote_ip 192.168.137.1/24 127.0.0.1/8 100.64.0.0/10
		# 有线网段,本地 localhost,tailscale 网段
	}
	abort @denied
}

(only_for_whitelist_and_internal_ip) {
	@denied {
		not remote_ip 192.168.137.1/24 127.0.0.1/8 100.64.0.0/10 10.21.0.0/10 10.129.0.0/10
		# 有线网段,本地 localhost,tailscale 网段,校园网段
	}
	abort @denied
}

然后对于 ssl 证书:

  • se.local: 自签证书直接使用 llm 生成的脚本就行
#!/bin/bash
# 检查是否提供了域名参数
if [ $# -eq 0 ]; then
    echo "Usage: $0 <domain>"
    echo "Example: $0 main.se.local"
    exit 1
fi
DOMAIN="$1"
KEY_FILE="${DOMAIN}-key.pem"
CERT_FILE="${DOMAIN}-cert.pem"
# 生成自签名证书
openssl req -x509 -newkey rsa:4096 \
    -keyout "certs/$KEY_FILE" \
    -out "certs/$CERT_FILE" \
    -days 36500 \
    -nodes \
    -subj "/CN=$DOMAIN"
# 检查是否成功生成
if [ -f "certs/$KEY_FILE" ] && [ -f "certs/$CERT_FILE" ]; then
    echo "✅ 成功生成自签名证书:"
    echo "   - 私钥: $KEY_FILE"
    echo "   - 证书: $CERT_FILE"
else
    echo "❌ 证书生成失败!"
    exit 1
fi
  • *.silente.app: 引入 acme_dns cf 的 api token 就能实现自动申请 ssl 证书。
{
	acme_dns cloudflare $CF_API_TOKEN
}

End

为了让服务不那么灵车,感觉还需要做一些监控和状态检测,这个就留给未来的自己吧,至少对于目前的服务来说,挂掉的影响确实不大 hh。