新安装 Linux 上的必要操作

每次新安装完 Linux,都需要进行一些基本的配置和工具安装。可是由于这个操作比较低频,每次回忆一些细节都很费劲,还得重新搜索。

这次重装了某个服务器(CentOS 7),顺便记录下来,避免下次重复浪费时间,顺便供网友参考。

后来顺便整理了装有 Ubuntu 的测试机,追加 Ubuntu 部分。

如果涉及到国内的服务器,需要更换镜像以加速,参考 镜像清单 ,这也是一个不定时更新的清单。

确认发行版本

一般情况下,系统是自己装的,你会知道版本。但也有可能是 VPS / 云主机 直接提供了一个系统。或者隔太久没登录,忘了。

1
2
3
4
5
6
7
8
9
10
11
lsb_release -a
# 但是 lsb_release 不是所有发行版本都支持,那就试试下面的
# 仅限 redhat 系
cat /etc/redhat-release
# 仅限 cent-os
rpm -q centos-release
# 其它
cat /etc/issue
# 查看内核信息
cat /proc/version
uname -a

创建帐号

直接使用 root 进行操作,是相当危险的行为。上来应该赶紧创建一个用户,然后授予 sudo 权限。

1
2
3
4
5
6
7
8
9
# 新建用户
useradd <newuser>
# 设置密码,这个密码既不能太弱有安全风险,也不能太难记——毕竟每次 sudo 都得敲一遍。
# 个人建议想一句名言,抽取拼音或者首字母,再随机加少量符号和数字,这样既保证强度,又不太难记
passwd <newuser>
# 加入 wheel 组获得管理员权限
usermod -g wheel <newuser>
# 如果有必要,调整 sudo 设置。我一般会给 env_keep 加上 PATH。免密就算了,不是好习惯。
visudo

后续重新登录,在新用户下操作。

基本工具

默认情况下,预装的软件源和工具都比较有限,很多工具找不到,需要添加一些额外的源。

CentOS 7

EPEL repo

1
2
# 查看 https://fedoraproject.org/wiki/EPEL 换成对应的系统版本
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

常用工具

1
2
3
4
5
6
7
8
9
# 非常惊讶有些发行版本居然连 vim 都有没有
sudo yum install vim
# ssh 多路复用工具 byobu,以 tmux 或 screen 为后端
sudo yum install byobu
# 启动一下 byobu 然后退出,生成配置文件
# 将后端从 tmux 改为 screen。这纯粹个人习惯而已,按理说 tmux 更强大
vim .byobu/backend
# 再次进入 byobu,然后 Ctrl+A ,触发 escape 选项,一般选 Screen mode
# F9 设置 screen 常用选项

Ubuntu

如果服务器在国内,把软件源换成速度快一点的镜像,如阿里云 http://mirrors.aliyun.com/ 。如果直接就是阿里云的机器,换成 http://mirrors.aliyuncs.com/ 可以走内网流量。

国外的服务器就没必要折腾了。

工具安装方面,直接把命令里的 yum 换成 apt-get ,常用工具貌似不用添加额外的源。

远程作业,网络不好随时断掉,byobu 还是很必要的。

安装好之后后续操作尽量在 byobu 上完成,避免因为网络抖动引起操作中断。

启用 BBR

Google 的 TCP BBR(Bottleneck Bandwidth and Round-trip propagation time) 可以改善 TCP 的网络传输,在不同网络状况下,大约可以提高 4%~14% 的效率。

不同 TCP 拥堵控制算法之间的差别,可以参考 TCP拥堵控制 ;网络调度器则参考 Network Scheduler

怕指令有不严谨或不兼容的情况,留一个参考互相对比 一键安装最新内核并开启 BBR 脚本

1
2
# 确认内核版本 >= 4.9
uname -r

假定内核版本过低,要升级内核。

CentOS 7 升级

1
2
3
4
5
6
7
8
9
10
# 引入对应的 repo
sudo rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
sudo rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
# 安装
sudo yum --enablerepo=elrepo-kernel install kernel-ml -y
# 设置默认内核
sudo egrep ^menuentry /etc/grub2.cfg | cut -f 2 -d \'
sudo grub2-set-default 0 # default 0 表示第一个内核设置为默认运行, 选择最新内核就对了
# 重启
sudo reboot

Ubuntu 14.04

升级内核有三种方案(看到最后,不要急着动手,推荐 HWE)

  • 手动安装最新的内核

    优点是可以尝试最新的内核,缺点是依赖地狱,和无法自动获得后续更新。

    https://www.kernel.org/ 确定内核版本(选择 Stable 或者 Longterm)。

    https://kernel.ubuntu.com/~kernel-ppa/mainline/ 找到对应内核的链接。

    由于较新的内核依赖较新的 linux-base 和 lib (如 libssl 1.1.0);而手动安装 linux-base ,以及解决其他依赖问题,还不如直接升级系统版本到 16.04 或者更新的 18.04。如果因为特殊原因,只要启用 BBR 而不愿意升级系统,建议直接安装 4.9.x 的内核。

    下载对应的架构(一般是 amd64)的 deb 文件,包括两个 headers,一个 image,如果是 4.17+,还有 modules。如果有不止一套 deb 文件,在没有特殊需求情况下 选 generic (通用)。

    1
    2
    3
    4
    5
    6
    7
    # 下载
    wget linux-headers-xxx_all.deb
    wget linux-headers-xxx_amd64.deb
    wget linux-image-xxx_amd64.deb
    wget linux-modules-xxx_amd64.deb
    # 安装,注意 dpkg 不会自动解决依赖,如果出现依赖问题,要按提示手动解决
    sudo dpkg -i linux-*.deb
  • 直接升级系统版本

    为了满足某个内核(我测试时尝试了 4.19)的依赖,而一路升级系统版本(因为 16.04 的 libssl 只有 1.0.2),最后升到 18.04 发现内核已经是 4.15 了,只是为了支持 BBR 已经没有必要自己再升级内核了。

  • 安装 HWE 内核 (HardWare Enablement stack,又叫 LTS Enablement)

    详情参考 https://wiki.ubuntu.com/Kernel/LTSEnablementStack

    简单说,就是 Ubuntu 为了老系统可以支持最新的硬件和内核,为 LTS (LongTerm Support 长期支持版本)系统打包测试最新的 内核 和 关键组件(如 XServer)。区别于稳定的 GA 内核(General Availability,通用可用性),过快应用新内核可能引入一些潜在的问题,但总比自己安装未经 Ubuntu 测试的内核要强。

    对14.04 来说,就是用 apt 安装以下内容

    1
    2
    3
    4
    5
    6
    7
    8
    # xserver 及后面的包仅 Desktop 需要, Server 版不用安装
    sudo apt-get install --install-recommends \
    linux-generic-lts-xenial \
    xserver-xorg-core-lts-xenial \
    xserver-xorg-lts-xenial \
    xserver-xorg-video-all-lts-xenial \
    xserver-xorg-input-all-lts-xenial \
    libwayland-egl1-mesa-lts-xenial

无论用哪种方法,成功安装之后:

1
2
3
4
5
# 更新 grub,手动安装记得先解决掉依赖问题
sudo update-grub
# 重启
sudo reboot
# 重启成功可以考虑清理一下不用的内核

如果升级了内核,等重启完毕,再次 uname -r 确认一下,继续。

以下内容与发行版本无关

1
2
3
4
5
6
7
# 查看内核模块是否有加载 bbr
lsmod | grep bbr
# 输出以下两个值,看是不是包含 bbr
# 可用的拥堵控制算法
sysctl net.ipv4.tcp_available_congestion_control
# 当前使用的拥堵控制算法
sysctl net.ipv4.tcp_congestion_control

如果有,下面的就不用执行了

1
2
3
4
# 加载内核模块
sudo modprobe tcp_bbr
# 加入开机自动加载
echo "tcp_bbr" | sudo tee --append /etc/modules-load.d/modules.conf

到这里,内核模块(lsmod | grep bbr)和 可用算法(sysctl net.ipv4.tcp_available_congestion_control)应该已经可以看到 bbr 了,可以先检查一下。

接下来启用:

1
2
3
4
# 修改网络分组调度器,一般默认是 fq_codel 公平受控延迟,改为 fq 公平队列
sudo sysctl net.core.default_qdisc=fq
# 修改当前的拥堵控制算法
sudo sysctl net.ipv4.tcp_congestion_control=bbr

docker-ce

现在 docker 分为了 社区版(CE) 和 企业版(EE),安装的最新方式参考 https://docs.docker.com/install/linux/docker-ce/centos/

CentOS 7

同样先以 CentOS 7 为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 可能带有老版本,先卸载
sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
# 用 yum repo 安装,先安装相关工具
sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
# 添加 stable repo
sudo yum-config-manager \
--add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 安装最新版本
sudo yum install docker-ce docker-ce-cli containerd.io
# 启动服务
sudo systemctl start docker
# 测试效果
sudo docker run hello-world

Ubuntu 16.04

docker-ce 支持的 Ubuntu 最低版本是 16.04。如果太低,先要升级系统版本。

在满足系统要求之后:

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
# 先卸载可能存在的旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 安装用到的工具
sudo apt-get update
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
# 添加官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# 通过搜索指纹的后八位,确认密钥正确安装
# 完整的指纹是 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
sudo apt-key fingerprint 0EBFCD88
# 添加 apt-get 仓库,根据需要可以替换 架构,和 channel
# (除了 stable,还可以选不稳定的 nightly 和 test)
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
# 安装
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 测试效果
sudo docker run hello-world

certbot (webserver-only)

如果服务器是用作 web 服务器,那么在互联网安全化的浪潮下,用 HTTPS 基本上是个必选项,否则你的访问者会整天看到来自浏览器的警告,某些浏览器甚至会直接拒绝访问。当然 HTTPS 也通过加密保护了通信的数据安全。

启用 HTTPS 最方便的方式,就是安装一个 certbot,通过 Let’s Encrypt 来签 一个证书。并且设置一个定期任务,在证书到期时自动续签。

这里的内容可能过时,最新的指引,请参考 https://certbot.eff.org/instructions

注意在做以下操作之前,需要 先注册了域名,并且已经将域名指向了对应地址 。域名注册 以及 添加 DNS 记录,每个服务商操作有所不同,而且不难,不再展开。只记住两个关键:

  • 非商用的话,免费的 DNS 服务足以。国内有老牌的 DNSPod(已被腾讯云收购),国外有 Cloudflare。因为 Cloudflare 还是一个 CDN 供应商,还能提供免费的 CDN 服务,推荐。
  • A 记录指向 IP,CNAME 记录指向另一个域名,MX 记录指向邮箱服务。注册一个域名,可以把不同的子域名用于不同用途,但是免费的 DNS 服务商可能会限制 DNS 记录数,所以要好好规划一下。

CentOS 7 安装

首先启用 EPEL repo (上面已经提过)。

1
2
3
4
5
6
# yum-utils 在 docker-ce 也安装过
sudo yum -y install yum-utils
# 启用 optional channel
sudo yum-config-manager --enable rhui-REGION-rhel-server-extras rhui-REGION-rhel-server-optional
# 安装
sudo yum install certbot

然后以下部分,与发行版无关:

然后是获取证书

1
2
3
# 这里假定真正的 web 服务还没启动,由 certbot 启动一个临时的 webserver 来完成认证
# 如果真正的 webserver 已经运行中且不能暂停,请参考 --webroot 参数
sudo certbot certonly --standalone

整个过程会询问 邮箱,确认几个问题,询问 域名,然后 Let’s Encrypt 就会发起一个 ACME (Automatic Certificate Management Environment, 自动证书管理环境) Challenges,完成后,证书储存在

/etc/letsencrypt/live/<YOUR.DOMAIN.COM/> ,阅读里面的 README 可以看到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
This directory contains your keys and certificates.
`privkey.pem` : the private key for your certificate.
`fullchain.pem`: the certificate file used in most server software.
`chain.pem` : used for OCSP stapling in Nginx >=1.3.7.
`cert.pem` : will break many server configurations, and should not be used
without reading further documentation (see link below).
WARNING: DO NOT MOVE OR RENAME THESE FILES!
Certbot expects these files to remain in this location in order
to function properly!
We recommend not moving these files. For more information, see the Certbot
User Guide at https://certbot.eff.org/docs/using.html#where-are-my-certificates.

有什么文件,都干嘛用,注意事项都说了。注意证书有效期是 90 天,所以需要启动一个定期任务,去更新证书:

1
2
# 如果不是第一次操作,先看一下有没有相应的任务
sudo crontab -l | grep "certbot renew"

如果没有,则创建

这是 certbot 官方推荐的操作

1
echo "0 0,12 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew -q --pre-hook 'service haproxy stop' --post-hook 'service haproxy start'" | sudo tee -a /etc/crontab > /dev/null

这个任务的特点是:

  • 每天 0 时和 12 时各执行一次。
  • 调用 Python 随机休眠若干秒(random() 返回值在 [0.0,1.0),显然是为了避免扎堆)。
  • 尝试更新证书(没有用 --force-renewal 参数,如果不是接近到期是不会实际更新的)。
  • 定义了 --pre-hook--post-hook ,在更新期间停掉 haproxy,如果用的不是它,要自行修改。
  • 任务写入的是系统任务,如果想放在用户任务并以 root 执行,去掉任务里的用户(root),放在 /var/spool/cron/root

个人感觉官方这个设定过于麻烦,居然每天执行两次,而且还调用了 Python 脚本休眠最长一小时。由于不设置 --force-renewal 的情况下,只有到期前 30 天的证书会更新,所以这些任务绝大多数的执行都是无用功。我的配置如下:

1
2
3
4
# 每个月 5 号 和 20 号 的 11 时尝试更新证书
# 具体日期时分秒的数字建议大家随机改一个,避免集中对 Let's Encrypt 的服务造成压力
# 如果更新过程中需要停一下服务器,还是可以加 --pre-hook 和 --post-hook 参数
echo "0 11 5,20 * * /usr/bin/certbot renew -q" | sudo tee -a /var/spool/cron/root

当然也可以改为执行

1
sudo crontab -e

然后在打开的编辑界面,将 echo 后面的任务,单独放一行,然后 :wq 保存生效。


知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议
本文为本人原创,采用知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议进行许可。
本作品可自由复制、传播及基于本作品进行演绎创作。如有以上需要,请留言告知,在文章开头明显位置加上署名(Jayce Chant)、原链接及许可协议信息,并明确指出修改(如有),不得用于商业用途。谢谢合作。
请点击查看协议的中文摘要。