一般Linux服务器部署及优化指北

你拿到了一台Linux服务器,可能是从VPS厂商购入的,可能是你自己搭建的Homelab,也有可能是某个好心的同学送你的,你对Linux可能有一定了解,但你可能会感觉到一丝不安,觉得在对这台服务器大展身手之前,要先对系统做些“优化”。
其实与Windows不同,大部分Linux发行版本身在作为服务器使用的时候,已经基本上能做到“开箱即用”了。相比Windows到手后需要关闭一堆东西再打开一堆东西的操作,我认为对Linux的调优主要是安全性和功能性上的。当然,Linux系统也为我们提供了十分丰富的定制化选项,你也可以根据自己的使用场景定制化自己的系统。
本文涉及到的优化并不会局限于某一使用场景,而且与网上大部分“一键优化”脚本不同,本文除了提供一系列优化指南之外,还会尽可能解释这样做的理由,同时,还会强调一些有所变化/不再适用的配置,因此如果你曾经配置过Linux,也可以来读一读。
如果你有其他的优化妙招,欢迎在评论区分享。

写到一半发现似乎有点太啰嗦了本篇文章似乎带有一定科普性质,因此你可能不需要Linux基础也能读懂本文。

系统

Debian ? Ubuntu ? Other ?

完成付款/组装之后,你大概率首先要从一大堆花花绿绿的Linux发行版中挑一个作为你的服务器系统。一般而言你有两类选择:Red Hat系和Debian系。其中Red Hat系包含了商业化版本RHEL和社区化版本CentOS,而Debian系则有Debian和基于Debian开发的Ubuntu。
先说Red Hat系,其中的CentOS在相当长的一段时间内曾经是十分热门的选择,因为其与商业化的上游发行版本RHEL完全兼容,并且由社区驱动,开源且免费,这意味着使用CentOS可以在不需要向Red Hat付费的情况下,享受到RHEL的稳定与丰富的软件包。正因如此,国内外部分大厂也一度采用CentOS。但是在2020年年末,Red Hat宣布对CentOS进行重大调整,其单方面终止了对CentOS的开发并转而支持定位为RHEL上游发行版的CentOS Stream。这样一来CentOS的所有优势都不复存在了,因此在CentOS 7在2024年终止支持后,曾经红极一时的CentOS逐渐式微。
由于迁移问题,如今依然有部分开发者和小厂在使用着CentOS,这当然是不推荐的,毕竟这款操作系统已经EOL,随时可能有安全漏洞。对于RHEL,虽然其推出了针对个人开发者非商业化使用的免费许可证,但我认为完全没有必要使用,毕竟接下来要介绍的Debian系在生态和稳定性上都与RHEL几乎无异,为什么大费周章地去注册并获取密钥呢。
说到Debian系,恐怕最出名的发行版就是Ubuntu了,笔者疫情期间首次尝试Linux的时候,安装的第一个发行版就是Ubuntu,也在自家的旧电脑上安装过Ubuntu Server作为Homelab。但我目前完全不推荐Ubuntu,原因很简单,面对巨大的使用量,Ubuntu背后的商业公司——Canonical,开始动起了歪心思,从Ubuntu 20.04开始,它们:

  • 在SSH登录后打印的motd信息以及Debian系通用的包管理器apt中,加入了Ubuntu Pro的广告
  • 强行推广自行开发的软件包格式snap,与使用deb打包的软件不同,snap程序会将所需要的所有依赖打包在一起,这使得其体积巨大且启动速度极慢。并且在Ubuntu Desktop上,Canonical已经将部分软件从原先的deb格式换为了snap包。
  • 更让人难以接受的是,在倡导自由开放的Linux中,Canonical为用户卸载snap设置了重重阻碍。在通过apt卸载snap实用程序后,在不经过特别配置的情况下,使用apt update指令的时候会再次将snap安装回来。

与Ubuntu正相反,其上游发行版——Debian的开发完全由社区驱动,系统镜像中没有商业化的部分,而且占用的资源更少,又兼具稳定性和生态丰富度。


总而言之,其简洁,快速,稳定的特性,使得我在包括Homelab在内的所有服务器上全部安装了Debian操作系统——当然,我也推荐你使用Debian,尤其是在你曾经使用过Ubuntu,对Debian系已经有一定了解的情况下,如果不是的话,就让Debian成为你第一个使用的Linux发行版吧!
本文也将使用最新的Debian 13系统作为示例,不过除了换源一节之外,其他的操作都是通用的,大可放心。

DD ?

你可能会在各大论坛见过各式各样的“DD脚本”,这个名字来源于Linux系统自带的dd指令,其可以对文件进行读取,写入和转换等操作,由于Linux“一切皆文件”的设计理念,dd也可以对块设备进行操作,例如删除磁盘分区或是刷写镜像。而“DD脚本”做的事与重装类似,其会从官方镜像源下载对应的镜像,使用dd指令刷写磁盘,并配置用户名密码等信息。
许多优化系统的教程一上来就会推荐你去dd(也就是重装)一份“纯净”的系统,这样真的有必要吗?笔者认为,如果你购入的VPS本身未提供最新版本的Linux发行版镜像(例如Debian 13或Ubuntu 24.04),在安装完厂商提供的系统后,确实可以考虑使用这些脚本重装为最新版本的系统,以获取更新的软件包和更长时间的系统更新。但如果厂商已经提供了最新版本的系统镜像,再使用这些脚本重装系统就显得没有那么必要了。对于各大云厂商的机器,则完全不推荐使用这些脚本重装,因为大厂提供的镜像很可能会包含一些优化(例如会将镜像源替换为内网地址以加速访问并节省出入站流量),使用脚本重装可能会导致一些问题。即使在部分情况下确要重装系统,也建议通过厂商提供的控制台进行。

换源

无论是aptdnf,还是pipnpm,在中国大陆使用任何包管理器,除非你能容忍<100kbps的下载速度以及时不时的阻断,首先应该考虑的一件事就是——换源。如果你的VPS来自于各大云厂商或位于境外,那你可以跳过这一步。此外,如果你的VPS来自于云厂商,那你大概率也可以跳过这一步,原因如上所述,厂商应该已经帮你换好源了。
对于Debian系的系统,长久以来,系统软件源的配置文件位于/etc/apt/sources.list中,但自从Debian 11开始,Debian官方引入了一种更易读的格式:DEB 822,这种格式在Debian 13中成为了推荐格式,官方亦表示原先的sources.list格式将会在将来的版本中废弃,所以建议在换源的时候使用DEB 822格式。
关于镜像源的选择,最有名的应该就是清华大学TUNA协会提供的镜像了,无论是服务质量还是源的丰富度上TUNA镜像都是遥遥领先,不过可能是用的人太多的原因,TUNA的镜像时常不能跑满笔者家中的带宽。其实镜像源的选择还有很多,例如我同样比较喜欢的中科大镜像。对于南方的朋友,我更推荐南方科技大学镜像站,虽然源的数量较少,但延迟更低,速度更快。
选好了镜像源,接下来就是写入文件了,根据最新的DEB 822格式规范,系统软件源的配置应该位于/etc/apt/sources.list.d/debian.sources,以南科大的镜像源为例,用你喜欢的文本编辑器打开这个文件,向其中写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
Types: deb
URIs: https://mirrors.sustech.edu.cn/debian/
Suites: trixie trixie-updates
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

Types: deb
URIs: https://mirrors.sustech.edu.cn/debian-security/
Suites: trixie-security
Components: main contrib non-free non-free-firmware
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
TXT

这等效于旧有的格式:

1
2
3
4
5
deb https://mirrors.sustech.edu.cn/debian/ trixie main contrib non-free non-free-firmware

deb https://mirrors.sustech.edu.cn/debian/ trixie-updates main contrib non-free non-free-firmware

deb https://mirrors.sustech.edu.cn/debian-security trixie-security main contrib non-free non-free-firmware
TXT

然后执行sudo apt update刷新软件包缓存即可
顺带一提,如果你仍有部分配置文件为原先的sources.list格式,可通过apt modernize-sources指令将其转换为最新的DEB 822格式。

用户

普通用户

拿到VPS后,如果你发现系统内只有root用户,那么就需要手动创建一个普通用户作日常使用。原因很简单,根据最小权限原则,普通的指令应该使用非特权账户执行,这样可以降低手误输入错误指令时破坏系统的概率。同时,部分软件也会主动拒绝以root用户运行。如果你已经使用普通用户登录系统,可跳过这一小节。
方法很简单,直接在终端输入以下指令即可,将$USERNAME替换为你想起的用户名:

1
sudo adduser $USERNAME
BASH

会提示输入密码和其他信息,除密码外其他信息回车跳过即可
之后需要将用户加入sudo组以使用sudo进行提权

1
sudo adduser $USERNAME sudo
BASH

adduser指令是对系统自带指令useraddusermod的包装,相较后者更加友好,其等效于这两条指令:

1
2
sudo useradd -m -G sudo -s /bin/bash $USERNAME
sudo passwd $USERNAME
BASH

密钥对

创建完普通用户后,接下来需要创建用于SSH登录的密钥对,如果你的VPS来自云厂商,那你可能在设定服务器的时候已经下载了生成的私钥,可以跳过这一小节。
同样很简单,在终端中输入以下指令,一路回车确认即可:

1
ssh-keygen
BASH

完成之后,你应该能在~/.ssh下见到两个文件:id_ed25519id_ed25519.pub,前者为私钥,后者为公钥,我们需要先将公钥文件写入同目录下的authorized_keys文件中,SSH会按行读取作为密钥对验证中的公钥值:

1
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
BASH

然后将私钥文件复制到本地即可。

SSH

默认情况下,SSH服务端使用的是22端口,并且允许使用用户密码登录,这可能会导致大量的扫描与密码爆破,因此我们可以修改SSH服务端的配置文件增强安全性。
SSH默认的配置文件位于/etc/ssh/sshd_config,但不建议直接修改这个文件,因为随着OpenSSH版本的更新,默认配置文件可能会发生变化,导致在更新软件包的时候需要手动解决冲突。而SSH在读取默认配置文件之前,会先按字典顺序读取/etc/ssh/sshd_config.d/目录中以.conf为后缀的文件,对于重复设置的值,会使用首个获取到的值。因此更好的做法是:将配置文件放在/etc/ssh/sshd_config.d/中,并以00开头命名配置文件,这样就能让我们的配置拥有最高优先级了。
具体到落实上,在终端输入以下指令,注意将$PORT替换为任意大于1024的高位端口:

1
2
3
4
5
6
7
8
9
sudo tee /etc/ssh/sshd_config.d/00-override.conf >/dev/null << 'EOF'
Port $PORT
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
PrintLastLog yes
ClientAliveInterval 30
ClientAliveCountMax 3
EOF
BASH

前几行配置都很好理解,分别是设置端口,禁止root用户登录,以及禁止使用密码登录。PrintLastLog会在登录SSH之后打印上一次登录的时间与IP地址。而最后两项就比较有意思了:SSH使用TCP长连接与服务端保持持久连接,而部分运营商和/或厂商的防火墙和NAT设备可能会限制闲置的TCP长连接,将一段时间(通常是数分钟)内未发送任何数据包的长连接直接掐断,因此部分耗时较长又没有输出的指令(例如复制大量文件)可能会被中断。这两行配置就是用于解决这个问题的,其含义是:客户端会在未收到来自服务端数据之后,每隔30秒通过SSH向服务端发送一次心跳包以尽可能地保持连接,在三次未收到来自服务端的反馈后就认为连接已断开。

部分教程可能会设置以下项:

1
TCPKeepAlive yes
TXT

这样设置谈不上错误,但几乎没用,首先这个值默认就是yes,其次这个值设置的是TCP Keep-Alive心跳包的发送与否,这本身没有任何问题,TCP心跳包也确实可以用来保持TCP长连接。问题就在于,这个心跳包的发送间隔由内核参数net.ipv4.tcp_keepalive_time定义,至少在Debian系上,其默认值为:

1
2
$ sysctl net.ipv4.tcp_keepalive_time
net.ipv4.tcp_keepalive_time = 7200
BASH

整整2个小时!等内核的TCP协议栈开始发送心跳包,中间设备早就把长连接断开了,黄花菜都凉了。

完成之后,可以使用sudo sshd -t测试当前配置,若没有输出则代表配置正确。
接下来,重载sshd服务

1
sudo systemctl reload sshd
BASH

在客户端开启一个新窗口,测试是否能用私钥连接至服务端

1
ssh -i /path/to/your/private/key $USERNAME@$IP
BASH

更进一步地,你还可以用sudo sshd -T查看目前SSH服务端正在使用的配置。
最后,每次都要打这么一长串指令才能连接到服务端实在是麻烦,除了使用各种第三方客户端外,也可以在客户端创建~/.ssh/config文件以简化操作,在其中写入以下内容:

1
2
3
4
5
Host $NICKNAME
HostName $IP
User $USERNAME
Port $PORT
IdentityFile /path/to/your/private/key
TXT

根据你的实际情况修改这些参数,之后就可以用ssh $NICKNAME连接至服务端了。

防火墙

UFW

防火墙的重要性应该不必多说,当我们不小心让仅供本地访问的,没有鉴权的服务监听在0.0.0.0上的时候,防火墙就是最后一道防线。在Linux上,对所有网络流量进行管理的程序叫iptables,不过这个程序功能过于强大与复杂,因此我们选择基于iptables,但更加简洁易于配置的防火墙程序ufwUncomplicated FireWall)
如果你使用的是云厂商的VPS,那么也可以跳过这一节,因为云厂商一般都配有更细粒度的网络管理面板,可自行在网页上调整出入站规则。
UFW已经包含在官方软件源内,如果系统内没有预装,首先通过apt安装:

1
2
sudo apt install ufw
sudo ufw status
BASH

目前防火墙应该处于inactive状态,UFW的默认策略是放行全部出站流量+拦截全部入站流量,所以在启用防火墙之前,我们需要将SSH使用的端口添加到入站白名单中(不然就把自己档在外面了),将$PORT替换为你的SSH端口:

1
sudo ufw allow $PORT/tcp
BASH

注意不要执行sudo ufw allow ssh,只会放行22端口的流量

随后可以执行

1
sudo ufw status
BASH

查看防火墙状态与添加的规则,正确的话即可激活防火墙,立即生效:

1
sudo ufw enable
BASH

UFW不能为Docker容器映射出来的端口提供防护,原因是UFW在iptables创建的规则位于Docker创建的规则之下。对于Docker容器,最佳实践是将映射出来的端口显式绑定在127.0.0.1,如-p 127.0.0.1:3389:3389

Fail2ban ?

相当一部分教程还会推荐安装Fail2ban这个软件包用于防止对SSH服务进行暴力破解,有必要吗?
首先要说明Fail2ban的原理:作为一款第三方软件,Fail2ban其实是靠读取日志实现其功能的。以SSH为例,Fail2ban会读取SSH日志中有关登录失败的条目,并封禁其中记录的IP地址
对应到SSH服务端这一防护场景,考虑到我们在之前已经启用了密钥认证并完全关闭了密码认证,这意味着攻击者无论如何尝试都不可能暴力破解。虽然我们依然会在SSH的日志当中看到源源不断的认证失败记录,但不会对我们造成任何影响。


所以,在启用密钥对认证的情况下,完全没必要针对SSH配置Fail2ban
但这并不意味着Fail2ban就一无是处了,如果你的主机上配置了其他服务,例如Postfix, Dovecot等通过用户名+密码认证的服务,Fail2ban还是能有效识别并封禁暴力破解的尝试的(在正确配置日志的情况下),并且除了内置的一系列服务,你还可以通过手写正则表达式为自己的服务创建封禁规则。所以,是否安装Fail2ban还是要看具体的情况。

网速优化

BBR

由Google开发的,赫赫有名的拥塞控制算法,相较Linux内核默认的算法CUBIC,可以提供更加优秀的带宽与延迟。
调整这个值需要使用系统自带的程序sysctl,以往的做法是:将需要调整的值写入/etc/sysctl.conf,再使用sysctl -p加载配置文件。
但是,自从Debian 13开始,sysctl不再读取这个文件了,其默认配置文件放在/usr/lib/sysctl.d/50-default.conf,我们不需要动这个文件,根据sysctl的man page,其还会从以下这几个地方读取配置:

1
2
3
4
5
/etc/sysctl.d/*.conf
/run/sysctl.d/*.conf
/usr/local/lib/sysctl.d/*.conf
/usr/lib/sysctl.d/*.conf
/lib/sysctl.d/*.conf
TXT

sysctl会从所有这些目录中收集配置文件,然后对它们按文件名进行统一的字典序排序,再依次加载其中的设置。若出现同名文件,则使用目录优先级更高的文件替代优先级低的文件。如果同一个参数被多次设置,则后加载的值会覆盖前面的值。也就是说,与SSH服务端的配置相反,我们应该将配置文件放在/etc/sysctl.d中,并以99开头命名配置文件,这样才能让我们的配置拥有最高优先级。(Linux,很神奇吧~)
具体到落实上,在终端输入以下指令:

1
echo "net.ipv4.tcp_congestion_control=bbr" | sudo tee /etc/sysctl.d/99-bbr.conf
BASH

之后使用sudo sysctl --system重载配置文件即可。

fq ?

细心的你可能会注意到,在网上一搜一大把的“启用BBR教程”中,一般还会附带这样一条sysctl配置:

1
net.core.default_qdisc=fq
TEXT

这行配置用于设置默认的队列调度算法,默认值为fq_codel,究竟有没有必要将这个值改为fq呢?
通过查阅2017年BBR开发者的讨论可以得知,BBR算法需要搭配TCP Pacing使用,否则可能会将“超过算法期望值”的包发送至互联网中,而fq_codel这一队列调度算法并没有实现TCP Pacing,所以在当时,BBR需要搭配fq这一算法使用。
但是!自从Linux内核版本4.13开始,内核的TCP栈增加了Pacing功能,作为在队列调度算法没有实现这项功能时的fallback,也就是说,自这个版本开始,BBR+fq_codel也能很好地工作,考虑到fq_codel相比fq额外增加的受控延迟算法,保持默认值就已经很好了。
总结一下,BBR+fq纯属历史遗留问题,net.core.default_qdisc的值无需额外设置

环境变量

Ubuntu相对Debian一个“易用”的方面在于,其镜像中预配置了一些环境变量,使得在日常使用中更加得心应手。其实,我们也可以在Debian中自行设置这些环境变量(有些甚至已经在~/.bashrc中,只是默认被注释了)
打开~/.bashrc,加入以下行:

1
2
alias ll='ls -l'
export PATH=$PATH:/sbin
BASH

其中ll可以列出目录内的文件及详细信息,在快速查看目录的时候非常有用,而第二行的意思是:将/sbin添加到当前用户的PATH环境变量中。这是Debian独有的问题:系统默认不会在普通用户的PATH环境变量中添加这一目录,导致普通用户无法使用安装在/sbin下的软件(例如ifconfig,无需root权限也可以查看网卡信息)


设置完成后登出再登录即可生效。
笔者的习惯是只添加这两个,你可以自行添加你喜欢的环境变量,也可以看看.bashrc中还有哪些被注释掉的环境变量。

常用软件

最后,根据我的使用经验,推荐一些实用的软件,前三个可以直接从软件源获取,剩下的已给出对应的Github仓库链接:

htop
TUI版的任务管理器,可展示CPU/内存/磁盘/进程等信息,相比自带的top指令更加美观易读,支持直接通过鼠标操作。

vnstat
流量统计工具,可统计入站/出站流量,并以分钟-年度的粒度展示数据,还可以通过vnstat -l展示实时流量数据。

lrzsz
直接在终端中发送与接收文件,使用Zmodem协议。与scp相比,其使用起来更为简单方便,特别是在使用跳板机或代理的情况下。(需要搭配支持Zmodem协议的终端使用)

dnslookup
好用的终端DNS查询工具,除了传统的UDP查询,还支持DoT,DoH,DoQ和DNSCrypt等类型,支持各类资源类型与附加ECS

nexttrace
一个命令行traceroute工具,与原版traceroute不同的是支持显示IP地址对应的ASN与GeoIP信息,并会在最后附上包含数据包路径的地图。

chsrc
一个用C编写的,支持为各类发行版和编程语言仓库换源的工具,支持对不同镜像源测速并自动将换源地址写入配置文件。作者甚至因为熬夜重构代码进过ICU,十分可敬。

后记

写到这里已经5500字了,我真能扯也是破了笔者文章的长度记录了。
本篇文章结合了笔者自高一以来使用Linux的经验,与查阅的相关资料写作而成。对于一些指令和配置项,我也是在写作的途中才发现其具体含义的。虽然力求普适性与正确性,但毕竟只是我的使用经验,如果你有其他的优化方式,或是有好用的工具类软件推荐,又或是发现了文章中的错漏之处,十分欢迎在评论区中指出。
其实写到这里发现买大厂的VPS还是有许多好处的,无论是提前配置好的源,还是默认生成的强密码,还是点点鼠标就能用的控制面板,都让小白用户也能以较为安全省心的方式使用服务器。(当然也失去了亲手配置系统所获得的宝贵经验)
“安全”二字最终看的还是人,设计上再多的安全考量也架不住用户本身安全意识的淡薄。哪怕配置了Fail2ban,直接暴露在公网上的弱密码MySQL实例也难逃被攻破的宿命。我认为养成安全意识首先要做到的一点是:在将不知道什么地方复制过来的指令粘贴到终端中,发现运行失败的时候,首先要做的应该是上网搜索这条指令的具体含义,而不是直接在指令前面加个sudo

注释与参考

除了已经使用超链接给出的资料以外,本文撰写过程中也参考了以下资料:
https://en.wikipedia.org/wiki/CentOS
https://zhuanlan.zhihu.com/p/511438456
https://wiki.debian.org/SourcesList#APT_sources_format
https://utcc.utoronto.ca/~cks/space/blog/sysadmin/OpenSSHConfigOrderMatters
https://serverfault.com/questions/879778/ssh-logs-i-dont-understand-maximum-authentication-attempts-exceeded
https://www.escapelife.site/posts/ec8a244b.html#!
https://en.wikipedia.org/wiki/Fail2ban
https://wiki.archlinux.org/title/Fail2ban
注:这篇ArchWiki关于Fail2ban的风险有这样一段警告:

If the attacker knows your IP address, they can send packets with a spoofed source header and get your IP address locked out of the server.

这是不准确的,因为即使攻击者能伪造带有虚假IP Header的SYN数据包,其也绝无可能收到发往这个虚假地址的SYN+ACK确认包,也就是说连接在传输层就终止了,根本就不会被位于应用层的Fail2ban捕获,因此这种攻击方式理论上无法实现。

https://github.com/systemd/systemd/issues/5090
https://groups.google.com/g/bbr-dev/c/4jL4ropdOV8
https://en.wikipedia.org/wiki/CoDel
sshd_config, sysctl的man page
感谢V2EX的@bodayw,启发了我搜索与阅读有关队列调度算法的讨论(不然这块我也糊弄过去了)


一般Linux服务器部署及优化指北
https://blog.kenxu.top/post/linux-server-optimization/
作者
Ken
发布于
2025年11月28日
许可协议