2025年,对绝大部分普通人来说,真的没必要折腾家用服务器。除了安装好的那一刻感到的快乐之外,剩下的就只有吃灰和浪费电而已。 但是这却是一次难得的和Linux亲密接触的机会。如果你感兴趣,那么玩玩也不错。

标题中“家用服务器”指的是什么

本文中探讨的家用服务器,指的是购买的小型主机设备(Intel NUC系列等),自己安装操作系统进行使用的服务器。不包括群晖等成品NAS设备。

用户购买小型服务器,在上面安装Linux系统,然后自己安装各类服务,自己管理端口,内存,磁盘,自己进行运维。

一般人的家用服务器无非用来做两件事:

  • 照片存储
  • 下载4K超高清无删减电影

程序员可能会多做几件事:

  • 部署自己的git私有仓库
  • 定时任务执行自定义脚本
  • 在线电子书(有些技术类电子书真的只有影印版pdf,临时想看还要下载,很麻烦)

极客玩家可能会多做几件事:

  • 部署游戏服务器私服(幻兽帕鲁等)

养宠物的朋友可能会多做几件事:

  • 将家用摄像头的录像上传到自己的服务器永久保存

以下是各种建议

建议一:一定要用Docker进行部署

既然选择了自己维护,那么你大概率下载到的都是开源的软件。而这些软件的开发人员的想法是不一样的。

有的程序员喜欢通过全局变量的方式控制软件,有的程序员只建议用特定的方式启动软件等等。

而且安装的方式也不一定是规范的。比如有的软件允许你用root安装,在没有经验的时候你可能会这么做,而有的软件在文档里强烈建议你为它的软件建立一个用户组和用户。你可能这个软件跟着文档安装在了/usr/local里,但是下一个软件可能放在/home/用户 下。而这会让未来的你一头雾水,毕竟这台服务器一般不会连上去使用。

而docker提供了一种更优雅的方案,每个软件都运行在自己的容器中,容器里有自己独立的变量和目录。然后你可以在docker-compose.yml中指定容器内端口对应的服务器端口,容器内目录对应的服务器目录等。另外,如果你运行的软件都需要用数据库,那么你可以用容器安装一个数据库,比如MySQL8,然后定义一个数据库的容器network。其他软件的容器可以访问这个network。

比如,我的gitea的docker-compose.yml内容如下:

services:
  gitea:
    image: docker.gitea.com/gitea:1.24.0
    container_name: gitea
    restart: always
    ports:
      - "13300:3000"
      - "13022:22"
    volumes:
      - /data/gitea/data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro

    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=mysql
      - GITEA__database__HOST=mysql8
      - GITEA__database__PASSWD=gitea123
      - GITEA__database__NAME=gitea
      - GITEA__database__USER=gitea

    networks:
      - mysql8_database_network

networks:
  mysql8_database_network:
    external: true

而我的MySQL8容器的docker-compose.yml内容如下:

services:
  mysql8:
    image: mysql:8.0
    container_name: mysql8
    environment:
      MYSQL_ROOT_PASSWORD: 123456 # 替换为您的root密码
    ports:
      - "53306:3306" # 将宿主机的3306端口映射到容器的3306端口
    volumes:
      - /data/mysql8/data:/var/lib/mysql # 这是关键:手动设置数据卷存储位置
    command: --lower_case_table_names=1 --default-authentication-plugin=mysql_native_password # 添加此行
    restart: always # 容器退出时总是重启
    networks:
      - database_network

networks:
  database_network:
    driver: bridge

此时,gitea是可以访问得到MySQL8容器中的MySQL软件的。

另外,容器可以定义开机自动启动,异常关闭重启等一些行为。

如果不想要了,可以直接执行rm命令删除容器,然后根据docker-compose.yml文件中设置的目录,对服务器的目录进行删除,这样就删除得非常干净。

相比起systemctl直接嵌入系统,出现一些莫名的异常情况,并且日志也不一定能很清晰地打印出来排查来看,Docker容器能够很清晰地一眼看到你在本服使用的软件。

只用一个非root用户,然后在~下,按软件分别存放docker-compose.yml 我目前是在~下,创建了一个docker-compose的目录,然后里面放置各种以软件名为目录名的目录,每个目录只有一个文件:docker-compose.yml。

这样一来,我想启动某个软件,只需要进入对应的软件目录,执行docker compose up -d 即可启动

建议二:人为定义好软件服务id,端口号区间等一些自己的服务器规则

我给自己的服务器中的各种软件都人为定义了服务id,从11开始。然后对于他们的端口,则以 服务id + 端口号后三位,组合成一个新的端口号,比如1panel默认的端口是8080,而且其服务id是11,则组合起来,开头是11,末尾取8080的末尾三位080,即可组合成端口号11080。

建议三:记录好你的操作日志

好记性不如烂笔头。

家用服务器一般不会经常登录。当我们配置完想要用的功能之后,一般是不会经常通过ssh登录上去看服务器状态。直到某个服务不太正常的时候,我们才会排查具体的问题。

时间久了,我们会遗忘到底这台服务器之前是如何配置的。诚然有了Docker,你可以通过翻阅docker-compose.yml去查看每个容器中的软件配置,但我更建议你将每一次对服务区的操作,都记录在自己的笔记中。

格式如下:

## 日期 时间
- 执行了A操作
- 执行了B操作
....

例如:

## 0615 14:00
- 配置了2T固态,挂在到 /data 下
- 所有安装行为 都使用 lin 用户
- 安装了docker和docker compose 
- 把用户lin加入 docker 用户组,例如 sudo usermod -aG docker lin
- 给NUC固定ip 10.0.0.193 (在openwrt 网络 DHCP/DNS 静态地址分配 添加 填写后 保存 然后下面还有一个保存并应用)

就像那些发布后的软件更新log记录一样,我非常建议你将每一次对家用服务器的操作进行简单的记录。这会在未来排查问题时,让你回忆起来时的路。

附:我的操作记录在文章末尾(部分数据已脱敏)

建议四:不要穿透到外网,真的没必要

当你部署好了所有软件,拥有了想要的功能,你很快就会在某一天,不在家的时候,突然想看一下家里的猫咪之前的视频;在别人家想装个杯,让别人看你自己配置的4K高清电影;或者是突然想改一下家里自己私有git上的项目代码;在外头想看一下家里的calibre-web上的某一本书的内容。

我必须要明确告知的是,这些都是伪需求。因为他们并不是刚需,并且有很多成熟的方案可以解决。

  • 一般TP-Link的摄像头都默认会保存最近一小段时间的视频回看。你一般不会看超过3天前的摄像头录像。而且你回家就能看到了
  • 看电影这个事,真要看的朋友会打开电影天堂,富哥会开会员,真没必要通过穿透看你卡得半死的4K电影
  • 如果你真的想改代码,那更好的方案是上传github private,这个服务目前早已免费。如果你的项目是git lfs存储,那你拉代码都要拉半天,不如回家操作
  • 至于看书,如果是影印版pdf,你可以在百度网盘里备上一份副本。如果是equb,你可以直接传到微信读书去。

而如果真的要穿透到外网,你还需要购买一台海外云服务器,配置frp。但是如果你的服务需要https(比如gitea这样的,它强烈要求你用https),即使你有域名,你也还是要折腾一遍Let’s encrypt的签名证书。即使你外网能用https访问,内网也还是需要再手动上传一遍签名证书,不然你内网访问还要绕一圈云服务器。(悲

综上,家用服务器就让它安静的躺在家里运行就行了。在外面就好好享受外面的户外活动,开心去玩。

建议五:不管怎么折腾,不要影响你老婆看爱奇艺

这条建议不只是家用服务器相关。程序员总有一些特殊的需要,这里不展开讲。关于那些特殊的网络配置,有时是很不稳定的。为了家庭和睦,我希望你有应急预案,让家里网络断了的时候,能有方案让你老婆继续看爱奇艺。目前的光猫上有默认的wifi,我建议你长期将其开启,这样当家人说网络不好的时候,你可以让他们先用光猫自带的wifi先过渡一下。

这里需要提到的是,我不建议给路由器刷openwrt。openwrt上如果运行过多的服务,也会加速路由器的老化。当我在家用服务器上开qbittorrent下载和上传电影后,路由器越来越卡,经常出现莫名其妙的断网。当然这也与路由器用了三年有关系。

最稳妥的方式还是买一台性能更强的r4s作为主路由,安装openwrt,利用其强大的cpu进行一些特殊的服务,然后路由器就认真做路由器。

建议六:享受你的周末,不要为了部署而部署

如果你是自己买服务器,自己装Linux系统,自己在上面安装软件的玩家,你一定不要忘记,你的周末,应该是周末。

你大概率不是公司里的运维,你可能是一个开发人员,懂一些Linux命令,会看日志,会启动Docker,会希望拥有自己私有的服务器。

但是运维是一件很苦杯的事情,你的服务器性能也不一定能满足得了你的真实需求。又或者你的服务器性能过剩而让你感到浪费。这都是非常可能的。

在做好了前五条建议的内容之后,我相信你也会有自己喜欢的家用服务器,你会提前一周找好美国好莱坞大片的种子,一周后在家里的电视里观看,还能看国内删减的内容;你会偶尔去剪出猫咪打量摄像头的可爱视频然后发到抖音;你会在服务器上翻看以前的老照片,本地存储会给你一种安全感。

但是,请你享受你的周末,没有这台服务器,你的生活还会继续。去散步,去打球,去看电影,去陪伴那些爱你的人。他们并不希望你周末对着黑框框挠头,像上班一样。

附:我的操作记录

NUC环境更新计划

为了让NUC能重新启用,并且服务于我的个人生活,我希望能榨干NUC的性能,并且将所有私人服务都有序部署到上面去。因此决定重新整理NUC的配置、用途、和扩展性。

本文将对NUC的用途进行分析,根据用途来选择操作系统及安装的底层软件,并提供有限的扩展性和优雅的管理方式。

NUC配置信息

CPU:i5-1240p 内存:16G 硬盘:512G + 2T

NUC需求

  • NextCloud 开源私有云存储和协作平台
  • Gitea 代码仓库
  • Calibre-Web 电子书
  • jellyfin + qbittorrent 4k电影

底层框架

  • 操作系统:Ubuntu Server 24.04
  • 数据库:四家数据库我都要,MySQL8.0,PostgreSql 17.4(前期docker其他功能先用mysql,postgresql后续装),Redis 8.0,ELK套装(查日志,前期可不部署)
  • 管理面板:1panel
  • frp内网穿透
  • kvm和Windows虚拟机(后续开Steam游戏使用,前期可不部署)

Docker配置

需要先定义一个Docker里的外部网络,把几个数据库都包进去。然后那些框架也要读取这个网络。

需要记录每个服务的端口,数据库类型,数据库名称。

Ubuntu用户账号和密码

  • root 123456
  • lin 123456

端口号管理

上层应用(前两位为服务id,后面为自己需要的端口,比如80,443)

服务id服务名端口号外网地址数据挂载目录数据库信息其他信息
111panel110801panel.windypath.com1panel默认http://10.0.0.193:11080/1a4e4fa3db 面板用户: 60173cd028 面板密码: 123456
12nextcloud12080nextcloud.windypath.com/data/nextcloud/html/MySQL8,账号nextcloud,密码:123456,数据库nextcloud管理员账号:admin,密码:123456
13gitea13300,13022gitea.windypath.com/data/gitea/dataMySQL8,账号gitea,密码:gitea123,数据库gitea管理员账号 JonathanLin,密码:123456
14frpc7000,7400默认(frpc 1panel内安装)默认管理员账号 admin,密码:123456,token:A_123456
15calibre15083calibre.windypath.com/data/calibre-web/无(他自己带SQLite)账号:admin, 密码:123456
16qbittorrent16080,16681/data/qbittorrent/appdata,/data/qbittorrent/downloads账号:admin, 密码:123456
17jellyfin17096,17920,17359,17900/data/jellyfin/library,TV目录:/data/qbittorrent/downloads/tvseries,电影目录:/data/qbittorrent/downloads/movie,字体目录:/data/jellyfin/fonts无(他自己自带)账号:admin,密码:123456

底层服务 (端口号以5开头,后四位为服务自己本身的端口号)

服务名端口号数据挂载目录其他信息
Mysql853306/data/mysql8/datadocker配置网络database_network

云服务器服务

雨云,公网ip 123.456.789.000

服务id服务名端口号外网地址数据挂载目录数据库信息其他信息
frps监听客户端连接:7000,仪表盘:7500,接收公网http/https:80,443123.456.789.000:7500账号:admin,密码:123456,token:A_123456

更新日志

0615 12:00

  • 安装Ubuntu Server 24.04.2

0615 14:00

  • 配置了2T固态,挂在到 /data 下
  • 所有安装行为 都使用 lin 用户
  • 安装了docker和docker compose
  • 把用户lin加入 docker 用户组,例如 sudo usermod -aG docker lin
  • 给NUC固定ip 10.0.0.193 (在openwrt 网络 DHCP/DNS 静态地址分配 添加 填写后 保存 然后下面还有一个保存并应用)

0615 14:10

用lin账号

  • 安装了git
  • 在目录下创建 ~/docker-compose目录 用来管理所有的docker-compose.yml
  • 用官方脚本安装了1panel

0615 17:42

  • 装mysql
  • 装nextcloud前,在mysql中创建了一个nextcloud的库,和账号密码,执行以下命令:
//在创建完数据库后,执行
CREATE USER 'nextcloud'@'%' IDENTIFIED BY 'your_secure_password';
GRANT ALL PRIVILEGES ON nextcloud.* TO 'nextcloud'@'%';
FLUSH PRIVILEGES;

0615 21:38

  • 安装docker compose然后让云服务器能正常通过1panel网站功能响应。
  • 用1panel的证书设置自动申请https证书。
  • 在云服务器上手动用docker安装了frps和1panel
云服务器创建frps容器命令
docker run --restart=always --network host -d -v /root/frps/frps.toml:/etc/frp/frps.toml --name frps snowdreamtech/frps
云服务器1panel信息
设置1Panel安装目录 (默认为/opt): 
[1Panel Log]: 您选择的安装路径是 /opt 
设置1Panel端口 (默认是 15446): 
[1Panel Log]: 您设置的端口是:  15446 
[1Panel Log]: 正在打开防火墙端口 15446 
Rules updated
Rules updated (v6)
Firewall not enabled (skipping reload)
设置1Panel安全入口 (默认是 25525dc70a): 
[1Panel Log]: 您设置的面板安全入口是 25525dc70a 
设置1Panel面板用户 (默认是 05d6fd27db): 
[1Panel Log]: 您设置的面板用户是 05d6fd27db 
[1Panel Log]: 设置1Panel面板密码,设置后按回车键继续 (默认是 2e0a296582):  

本地frpc配置:

serverAddr = "123.456.789.000"
serverPort = 7000

auth.method = "token"
auth.token = "A_123456"

webServer.addr = "0.0.0.0"
webServer.port = 7400
webServer.user = "admin"
webServer.password = "123456"
webServer.pprofEnable = false

# tls
#transport.tls.certFile = "/etc/frp/ssl/client.crt"
#transport.tls.keyFile = "/etc/frp/ssl/client.key"
#transport.tls.trustedCaFile = "/etc/frp/ssl/ca.crt"

[[proxies]]
name = "1panel"
type = "http"
localIP = "127.0.0.1"
localPort = 11080
subdomain = "1panel"
customDomains = ["1panel.windypath.com"]


[[proxies]]
name = "nextcloud"
type = "http"
localIP = "127.0.0.1"
localPort = 12080
subdomain = "nextcloud"
customDomains = ["nextcloud.windypath.com"]


[[proxies]]
name = "gitea"
type = "http"
localIP = "127.0.0.1"
localPort = 13300
subdomain = "gitea"
customDomains = ["gitea.windypath.com"]
  • nextcloud设置自己的https域名
  • gitea设置自己的https域名
  • 本地openclash 设置hosts 家里就不要走外网了 (更新方式:openwrt openclash 覆写设置 DNS设置 Hosts勾起来 然后写)
  • 然后把云服务器上的证书下载下来,到本地的1panel里的证书功能里导入,然后本地再配一遍反向代理。我真的佛了
  • 但是最后nextcloud登录的时候会有一个报错 是因为config/config.php 里没加 “overwriteprotocol”: “https”,
Refused to send form data to 'https://nextcloud.windypath.com/login' because it violates the following Content Security Policy directive: "form-action 'self' http://10.0.0.193:12080". 
  • TODO ssh只允许内网机器往上登录,ssh指定秘钥等;端口防火墙看要不要设置一下。

0617 21:02

在nuc上成功安装calibre-web 的docker,但是他竟然需要一个metadata.db,需要从windows装一个calibre,然后把这个文件拷过去。

0617 23:00

本地安装calibre,然后把metadata.db用winscp上传到服务器后,发现权限还是不够,执行以下命令(类似)更新权限:

chown -R 1000:1000 /path/to/your/docker/books
chmod -R 755 /path/to/your/docker/books

然后在界面上就能正常读取/books目录,加载书库了。

然后去个人设置里修改语言,然后去设置里再改,支持网页上传书籍。

现在已经可以上传书籍了,我已经把藏书全部上传。

0617 23:38

外网1panel修改证书的域名,把calibre.windypath.com添加到那一行里面

cloudflare 解析 calibre.windypath.com 指向云服务器

本地frpc配置代理,指向calibre

[[proxies]]
name = "calibre"
type = "http"
localIP = "127.0.0.1"
localPort = 15083
subdomain = "calibre"
customDomains = ["calibre.windypath.com"]

然后在外网1panel里更新证书,重新再次申请。

下载外网1panel里的证书到本地

到本地1panel填入证书内容

然后本地1panel还要设置一下网站,反向代理到127.0.0.1:15083

至此 calibre导入及外网访问,完成!!

0619 0:16

装qbittorrent

安装顺利完成,但是打开是 unauthorized。 解决办法是宿主机端口要与内网机端口映射保持一致。具体原因考虑到CSRF和映射问题,内外端口必须与WEBUI_PORT一致。(来源:https://zhuanlan.zhihu.com/p/683305383)

0619 22:16

装jellyfin,希望能把jellyfin的媒体库 目录 指向 qbittorrent的下载目录

在/data/qbittorrent/downloads目录下创建了两个目录:tvseries和movies

services:
  jellyfin:
    image: lscr.io/linuxserver/jellyfin:latest
    container_name: jellyfin
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Shanghai
    volumes:
      - /data/jellyfin/library:/config
      - /data/qbittorrent/downloads/tvseries:/data/tvshows
      - /data/qbittorrent/downloads/movies:/data/movies
    ports:
      - 17096:8096
      - 17920:8920 #optional
      - 17359:7359/udp #optional
      - 17900:1900/udp #optional
    restart: unless-stopped

安装完毕 能够读取到qbittorrent下载的电影。但是字幕需要处理

测试下来字幕还是自己找吧,字幕下载网站:https://assrt.net/

种子资源汇总:https://blog.csdn.net/wangxy_job/article/details/141610804

种子资源网 海盗湾 https://thepiratebay.org/description.php?id=30340380

现在字幕文件都是下载后,winscp到影片同级目录下,改得和影片文件名相同,加上.chn.xxx

0620 20:29

qbittorrent设置了替代速度,就是周末12:00~24:00不要下载。其余时间全速下载。

然后qbittorrent下面有个开关 可以切换下载速度限制。

0621 23:30

在内网1panel 计划任务 脚本库 增加了三个脚本,分别是查看当前下载任务,查看当前减速开关,修改当前减速开关状态。

0623 21:00

给qbittorrent增加了tracker https://trackerslist.com/#/zh 也不知道有没有变快

0624 20:58

准备给jellyfin装中文字体,我选了思源黑体。加了一个字体目录到docker里,然后删除容器重新装。

  • /data/jellyfin/fonts:/usr/share/fonts/truetype/dejavu

docker-compose.yml修改后,只需要:

修改 docker-compose.yml 文件并保存。 在 docker-compose.yml 文件所在的目录下运行 docker compose up -d。

0726 21:57

将Unity项目上传到gitea失败了,原因是有大文件

TODO:后续需要在gitea和本地都配置git lfs,支持大文件的git仓库。 这次先存到百度网盘了。