从头开始配置一台云服务器(Ubuntu 22.04 LTS)
连接到服务器
复制云服务器提供商给的同户名(通常是root
)以及ip地址(形如xxx.xxx.xxx.xxx
)。
可以使用SSH连接到服务器。
特别地,如果你使用终端命令发起SSH连接,请在自己的设备上执行以下命令(如果有需要,将root
替换为你的用户名):
1 | ssh root@xxx.xxx.xxx.xxx |
若出现类似如下提示:
1 | The authenticity of host 'xxx.xxx.xxx.xxx (xxx.xxx.xxx.xxx)' can't be established. |
输入yes
后按Enter
,再输入密码(输入时不会显示),输完按Enter
即可连接。
若出现类似如下提示:
1 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
则说明目标主机的识别密钥自上次连接发生了改动。对于自用的云服务器,发生中间人攻击事件的可能性不大,最可能的情况是你曾经重置过云服务器系统,导致新系统的主机识别密钥发生了改变。
这时只需要按照提示,复制remove with
下一行的命令并执行即可。例如在这里,应该执行以下命令:
1 | ssh-keygen -f "/home/akivili/.ssh/known_hosts" -R "xxx.xxx.xxx.xxx" |
如果客户端是Windows系统,则需要手动编辑known_hosts
文件。在PowerShell中执行以下命令以在记事本中打开该文件:
1 | notepad.exe "$env:HOMEPATH\.ssh\known_hosts" |
并删除Offending xxxxxx key in x:\xxxxx\xxxx\.ssh\known_hosts:n
中提到的第n
行。
禁用部分安全设置(可选)
停用密码复杂度策略
在一台启用了密码复杂度策略的设备上,如果有人尝试为用户设置简单密码,就会得到类似这样的报错:BAD PASSWORD: The password is a palindrome
。
设置一个复杂的密码可以一定程度上保护服务器免遭入侵,因此该步骤存在一定安全风险,建议跳过。如果你执意停用密码复杂度策略并设置简单密码,请稍后为SSH服务设置仅使用密钥登录。
使用管理员权限(root
用户或具有sudo
权限的普通用户)编辑/etc/pam.d/common-password
文件:
1 | sudo vim /etc/pam.d/common-password |
通过在多余行的行首添加#
或直接修改、删除某些行的方式,使得该文件中不以#
开头的行只有下列3行,然后保存并退出。
1 | password [success=1 default=ignore] pam_unix.so obscure yescrypt |
如果你正在设置桌面系统而不是云服务器,则optional
行(如果已经存在)也应该保留,例如GNOME桌面的钥匙串策略:
1 | password optional pam_gnome_keyring.so |
现在通过passwd
命令更改密码将没有密码复杂度要求。
禁用或卸载内置防火墙
通常情况下,云服务器提供商都会在系统之外提供额外的防火墙,也相对来说更方便操作,因此笔者的习惯是禁用系统内置的防火墙。
查看防火墙状态:
1 | sudo ufw status |
若出现Status: inactive
字样,则说明防火墙已禁用;若出现Status: active
字样,则说明防火墙已启用。
启用防火墙:
1 | sudo ufw enable |
禁用防火墙:
1 | sudo ufw disable |
卸载防火墙:
1 | sudo apt purge ufw |
禁用SELinux
SELinux是Linux系统对文件权限提供的额外一层防护,笔者的习惯是禁用该功能。
查看SELinux状态:
1 | getenforce |
若提示未安装或状态为Disabled
(已禁用)则无需后续处理。若当前状态为Enforcing
或Permissive
,修改配置文件:
1 | sudo vim /etc/selinux/config |
找到SELINUX=xxx
并修改为:
1 | SELINUX=disabled |
保存后重启设备即可生效(稍后一并重启)。
删除cloud-init服务
该服务是云服务器提供商在初始化设备时使用的自动化配置工具,现在初始化已经完成,可以执行如下命令将其彻底删除:
1 | sudo apt purge cloud-init -y && sudo rm -rf /etc/cloud /var/lib/cloud/ |
apt purge
表示同时删除包及其配置文件。
配置用户
临时使用root用户登录SSH
如果你已经使用root
用户登录,则可直接跳过此节。
如果云服务器提供了临时登录用户,并非root
,笔者建议稍后删除该临时登录用户(删除方法见下文),先使用root
用户登录,之后创建普通用户用来管理服务器。
笔者习惯使用自己创建的普通用户管理系统,而不是使用云服务器提供商预设的用户名。
执行命令设置或更改root
用户的密码:
1 | sudo passwd root |
只需要提供当前用户密码,就可直接更改root
用户的密码。
之后,执行以下命令更改SSH服务端配置,临时允许root
用户通过输入密码登录(下文会给出覆盖这一临时修改和更详细的修改SSH服务端配置方法):
1 | sudo sed -i '1i PasswordAuthentication yes\nPermitRootLogin yes' /etc/ssh/sshd_config && sudo systemctl restart sshd |
现在向服务器发起新连接,并使用root
用户登录,并不再使用服务器提供的临时登录用户,下文会给出删除这些普通用户的方法。
创建普通用户
直接使用root
用户远程管理系统是不被推荐的,因为这会导致安全性问题和潜在的文件权限问题。推荐创建一个有sudo
权限的普通用户来远程管理系统。
以下假设将要创建的用户名为akivili
。
Linux系统对大小写敏感,用户名尽量不要包括大写字母。
在Ubuntu中,推荐使用交互式命令adduser
来创建用户。确保当前用户为root
,然后分别执行创建用户和赋予用户sudo
权限的命令:
1 | adduser akivili |
在此时可以向服务器发起新连接,确保新用户可以通过SSH登录。
在此之后,请不要再使用root
用户,而是使用新创建的普通用户远程登录服务器。如果确实需要使用root
用户,请临时切换用户:
1 | su - root |
su
是切换用户命令,而命令中的横杠-
表示切换用户后一并更改终端工作目录和加载用户环境配置。省略横杠可能导致部分命令执行出错。
删除多余普通用户
部分云服务器提供商在初始化设备时会额外创建一些普通用户,可以将其删除。
通常来说,root
用户的UID是0
,系统用户的UID是1
到999
,而普通用户的UID则大于等于1000
。UID_MIN
和UID_MAX
是系统为普通用户的UID设置的上下界,前者通常为1000
,后者通常为60000
。
删除单个用户的命令如下(将xxxxxx
替换为要删除的用户名):
1 | sudo deluser xxxxxx |
要删除除当前用户以外的所有普通用户,请使用刚刚创建的普通用户(如akivili
)登录系统,并执行这行命令以删除系统的多余用户及其对应的家目录(这不会删除当前用户,多余用户指的是UID介于UID_MIN
和UID_MAX
之间的、由root
用户创建的普通用户)。
请确保直接用刚刚创建的普通用户(如akivili
)登录SSH服务器,否则:
- 如果直接使用
root
用户登录,则删除用户时会一并将刚刚创建的普通用户删除 - 如果用服务器提供商提供的其他普通用户登录SSH服务端,即使切换到了其它用户,尝试删除该临时普通用户时仍会失败
1 | awk -v UID_MIN="$(grep "^UID_MIN" /etc/login.defs | awk '{print $2}')" -v UID_MAX="$(grep "^UID_MAX" /etc/login.defs | awk '{print $2}')" -F ':' '$3 >= UID_MIN && $3 <= UID_MAX' /etc/passwd | cut -d: -f1 | xargs -I {} sudo userdel -r {} |
这条命令不会删除当前用户,也不会删除任何正在活动的用户。例如,用户akivili
通过SSH连接到了设备,即使其切换到了root
用户并执行上述命令,系统也会在尝试删除akivili
时报错并跳过:
1 | userdel: user akivili is currently used by process xxxxxx |
执行命令时可能会出现如下报错:
1 | xxxxxx mail spool (/var/mail/xxxxxx) not found |
这是提示该用户的邮件文件目录并未找到(这是因为邮件目录通常不会自动生成),忽略即可,该用户已经被成功删除了。
配置apt软件源
某些服务器提供商会将apt软件源更改,所以可以考虑重置官方默认源。之后,如果服务器主机所在地的网络状况较差,可考虑换源。
以下设置软件源的方法只对Ubuntu 22.04及以下LTS版本支持,请勿在Ubuntu 24.04及以上LTS版本中使用。
备份文件
在换源之前,首先备份当前保存软件源的文件:
1 | sudo mv /etc/apt/sources.list /etc/apt/sources.list.old |
备份文件的好处是,如果之后不小心搞砸了,还可以这样将文件恢复:
1 | sudo mv /etc/apt/sources.list.old /etc/apt/sources.list |
事实上,在/etc/apt/sources.list.d
目录下的所有后缀为.list
和.source
的文件内容也会被加入apt源中并同时生效,如果该目录包含了符合上述条件的文件,请仔细检查其中的内容,备份需要的文件,删除不需要的文件。
参考资料:Ubuntu Manpage: sources.list - List of configured APT data sources
本文将会假定此目录中没有任何文件。
列出该目录下的文件:
1 | ls /etc/apt/sources.list.d/ |
若要删除该目录下的所有文件,执行以下命令:
1 | sudo rm -rf /etc/apt/sources.list.d/* |
若要暂时禁用该目录下的所有文件,执行以下命令(只需要让文件名不以.list
或.source
结尾即可,这里添加了.disable
文本,该文本可被任意替换):
1 | sudo bash -c 'for file in /etc/apt/sources.list.d/*.{list,source}; do mv "$file" "${file}.disable"; done' |
明确系统版本代号
接下来需要明确当前Ubuntu发行版的代号,以选择合适的源。
执行以下命令,输出结果的Codename
字段即为代号:
1 | lsb_release -a |
示例输出:
1 | lucien@lava:~$ lsb_release -a |
Ubuntu 22.04 LTS系统的代号为jammy
。
以下是部分Ubuntu系统版本的代号:
系统版本 | 代号 |
---|---|
Ubuntu 16.04 | xenial |
Ubuntu 18.04 | bionic |
Ubuntu 20.04 | focal |
Ubuntu 22.04 | jammy |
重置默认源
先将软件源重置为官方默认源,再使用批量替换域名的方式完成换源。
编辑软件源文件(由于刚刚将原先的文件通过更名的方式备份,此时应该会打开一个空的新文件),并在文件中填入官方源:
1 | sudo vim /etc/apt/sources.list |
如果你已经复制了一份镜像站提供的替换文本内容,也可以直接在打开的新文件中粘贴这些内容并保存文件,跳过下文的换源
部分,即可完成换源。
Ubuntu 22.04 LTS系统官方源如下(如果你的Ubuntu系统版本并非22.04,也请继续填入,下文会介绍简易的更正方法):
1 | deb http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse |
带有deb-src
标记的是源码地址,通常不需要使用,已经使用#
注释。如有需要可以取消注释。
之后保存文件。
如果你的Ubuntu系统版本并非22.04,也即系统代号并非jammy
(例如你的系统版本为Ubuntu 20.04 LTS,其系统代号为focal
),请先确认你已保存文件,然后使用以下命令将文件中的jammy
替换为focal
(其它系统代号同理,只需要将命令中的focal
替换为你的系统代号即可):
1 | sudo sed -i 's/jammy/focal/g' /etc/apt/sources.list |
换源
以下是一些常用的镜像站及其网址:
镜像站主站名称 | 网址 |
---|---|
清华大学开源软件镜像站 | https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ |
中国科学技术大学开源软件镜像站 | https://mirrors.ustc.edu.cn/ubuntu/ |
阿里云镜像站 | https://mirrors.aliyun.com/ubuntu/ |
选择一个软件源,复制其网址,将其粘贴至以下命令的=
后面,然后执行。
1 | replace= |
例如选择更换为清华源,应执行的命令为:
1 | replace=https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ |
紧接着执行以下命令:
1 | default=http://archive.ubuntu.com/ubuntu/ && sudo sed -i "s@$default@$replace@g" /etc/apt/sources.list |
即可完成换源。
你可以执行以下命令快速查看软件源文件内容:
1 | cat /etc/apt/sources.list |
更新
执行以下命令更新源并更新所有包:
1 | sudo apt update && sudo apt upgrade |
如果弹出类似如下对话框:
1 | Which services should be restarted? |
这意味着你需要选择应该重启的服务,建议全选,方法是按键盘的上下方向键定位选项,按空格键选定或取消选定(最前面有[*]
标记即为已选定),选择完毕后按Enter
确认。
如果弹出类似如下对话框:
1 | Configuration file 'xxx' |
这意味着你手动更改过某个软件包的配置文件,但是软件包即将更新,更新后的软件包可能会用开发者提供的默认配置文件覆盖你的本地修改。建议按Enter
选择默认选项保留当前的配置文件。
更新完毕之后,通过云服务器提供商的服务器面板重启服务器。
如果一切正常,你可以执行以下命令以删除之前备份的内容:
1 | sudo rm /etc/apt/sources.list.old |
清理
执行以下命令以自动删除多余软件包:
1 | sudo apt autoremove |
反复执行以下命令直到所有软件已是最新:
1 | sudo apt update && sudo apt upgrade |
如果提示xxx has been kept back
,无特殊情况可以手动更新这些软件包:
1 | sudo apt install xxx |
配置SSH
为安全性考虑,请为SSH服务设置使用密钥登录、禁用密码并禁止root用户通过密码登录。
创建密钥
如果你当前并未拥有自己的密钥,则可以创建一个。
你并不一定要在这台服务器上创建密钥,可以在任意Linux系统中、或使用安装在Windows系统中的Git Bash
(并非预装,需要安装Git
)创建密钥。
考虑到最新的安全标准与对某些软件的兼容性,建议使用4096位的RSA
加密算法以及PEM
密钥格式。
在任意Linux系统上,执行命令(请将示例中使用的电子邮件替换为你自己的电子邮件地址,或者使用任意文本作为标识符):
1 | ssh-keygen -m PEM -t rsa -b 4096 -C "your_email@example.com" |
选择RSA
加密算法是因为其十分常见且得到了广泛支持,而-b 4096
指定了RSA
加密算法的长度位数,4096位的长度足以确保安全性;使用PEM
密钥格式是为了对部分尚未支持OPENSSH最新密钥格式的软件(如旧版本Putty)兼容。如果不考虑兼容性,则可以去掉-m PEM
且加密算法可以选择最新的ed25519
,即在创建密钥时,使用该命令:
1 | ssh-keygen -t ed25519 -C "your_email@example.com" |
系统首先会提示选择一个密钥保存位置,可以接受默认位置,按Enter
继续。
如果以前在此设备上创建过密钥并使用了默认位置和相同名称,则可能会有将旧密钥覆盖的风险。此时请手动指定一个新文件位置或文件名称。
接着,系统会提示创建密钥的密码,可以留空以不使用密码,按两次Enter
即可。
这之后,密钥就创建完成了,系统会输出私钥和公钥的保存位置(如你使用了RSA
加密算法,则默认位置分别为~/.ssh/id_rsa
和~/.ssh/id_rsa.pub
)。
示例输出:
1 | akivili@Inazuma:~$ ssh-keygen -m PEM -t rsa -b 4096 -C "xxx@xxxx.xxx" |
将公钥加入到允许列表
在服务器上,编辑授权公钥列表文件(可能需要新建):
1 | [ -d ~/.ssh ] || mkdir ~/.ssh && vim ~/.ssh/authorized_keys |
不可以用sudo
!你想要为哪位用户配置密钥登录,就切换到哪位用户进行上述操作,否则可能导致权限问题。
然后打开你的公钥文件(后缀通常是.pub
),将文件的全部内容(如果是由ssh-keygen
生成的公钥,则应该只有一行)复制,粘贴到公钥列表文件的新一行(如果该文件目前为空,则直接粘贴即可),之后保存文件。
特别地,如果之前你就是在这台远程设备上生成的密钥,或是这台设备上存储了你的公钥,可以执行以下命令快速导入公钥(将~/.ssh/id_rsa.pub
换成你的公钥路径):
1 | cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys |
修改文件权限
SSH服务对敏感文件的权限有着很高的要求,所有有关文件或目录不应被其他用户染指,只有用户本人可以读写相关文件以及读、写和执行(进入)相应目录。
依次执行以下命令:
1 | sudo chown `whoami`:`whoami` ~/.ssh |
修改SSH服务端配置
部分云服务器提供商修改了SSH服务端的配置文件,建议将其还原为默认配置文件内容,再手动修改部分设置。
以下步骤请连续完成,如果配置出错又重启了SSH服务,可能导致无法登录服务器。
先备份原SSH服务端配置文件:
1 | sudo mv /etc/ssh/sshd_config /etc/ssh/sshd_config.old |
恢复备份的方法:
1 | sudo mv /etc/ssh/sshd_config.old /etc/ssh/sshd_config |
事实上,在/etc/ssh/sshd_config.d
目录下的所有后缀为.conf
的文件内容也会并入SSH服务端配置中。如果该目录包含了符合上述条件的文件,请仔细检查其中的内容,备份需要的文件,删除不需要的文件。
如果出现配置冲突(即相同的配置项出现在了多个配置文件中),只有排在最前面的配置有效。由于在默认情况下,主配置文件/etc/ssh/sshd_config
中Include /etc/ssh/sshd_config.d/*.conf
配置项出现在最前面,所以/etc/ssh/sshd_config.d
目录中的所有配置优先于主配置文件生效,而该目录中的不同配置文件又以文件名字符串排序靠前者优先。
本文将会假定此目录中没有任何文件。
列出该目录下的文件:
1 | ls /etc/ssh/sshd_config.d/ |
若要删除该目录下的所有文件,执行以下命令:
1 | sudo rm -rf /etc/ssh/sshd_config.d/* |
若要暂时禁用该目录下的所有文件,执行以下命令(只需要让文件名不以.conf
结尾即可,这里添加了.disable
文本,该文本可被任意替换):
1 | sudo bash -c 'for file in /etc/ssh/sshd_config.d/*.conf; do mv "$file" "${file}.disable"; done' |
应用SSH服务端默认配置后,请关注被还原的部分重要配置:
- 在
22
端口侦听任意来源的连接请求 - 允许输入密码登录,但禁止使用空密码
- 允许使用密钥登录
- 禁止
root
用户通过输入密码登录
请确认你并没有使用root
用户直接登录到服务器。
编辑SSH服务端配置文件(由于刚刚将原先的文件通过更名的方式备份,此时应该会打开一个空的新文件),并在文件中填入默认配置:
1 | sudo vim /etc/ssh/sshd_config |
默认配置内容(可能需要展开以显示完整内容):
1 |
|
测试密钥登录
首先重启SSH服务端:
1 | sudo systemctl restart sshd |
尝试在客户端使用对应私钥连接服务器,注意你需要将私钥保存一份在客户端上,放在服务器端的私钥没有作用。
私钥是纯文本文件,你可以直接复制其中的全部内容并保存到客户端的一个任意命名的文本文件中。
特别地,如果之前你就是在这台远程设备上生成的密钥,或是这台设备上存储了你的私钥,可以在客户端(并非在该服务器上)执行以下命令以将私钥下载到本地客户端(将akivili@xxx.xxx.xxx.xxx
替换为你的服务器用户名和地址,~/.ssh/id_rsa
替换为私钥文件在服务器上的储存位置):
1 | scp akivili@xxx.xxx.xxx.xxx:~/.ssh/id_rsa . |
注意命令最后有个.
,表示将文件复制到客户端的当前目录。该命令可以在Linux和高版本的Windows上运行。
现在应该能跳过密码输入环节,成功登录。
特别地,如果你使用终端命令发起SSH连接,在命令后加上-i 本地私钥位置
参数即可使用密钥登录:
1 | ssh akivili@xxx.xxx.xxx.xxx -i /path/to/id_rsa |
再次修改SSH服务端配置文件
编辑配置文件:
1 | sudo vim /etc/ssh/sshd_config |
找到以下这一行(约第57行)并作相应修改以禁止使用密码登录(注意删除#
以取消注释):
确认可以通过密钥登录后再进行修改,否则可能导致无法登录系统!
1 | PasswordAuthentication no |
确认配置正确后,重启sshd
服务:
重启服务后不要关闭当前连接,而应先进行一次登录尝试,否则一旦密钥登录失败或配置出错,系统可能将无法访问!
1 | sudo systemctl restart sshd |
成功连接后,可以执行以下命令删除之前备份的配置文件:
1 | sudo rm /etc/ssh/sshd_config.old |
修改服务器主机名
主机名可以被理解为设备的标识。
观察服务器的终端命令提示符,显示在@
后面的就是主机名,也可以通过如下命令查询主机名:
1 | uname -n |
在Ubuntu系统里,主机名信息保存在/etc/hostname
中,编辑该文件,将文件内容改为新主机名,保存文件并重启系统后(稍后一并重启),就可以永久修改主机名:
1 | sudo vim /etc/hostname |
重启系统
云服务器提供商通常会在用户面板上提供重启的选项,若要重启,面板按钮是优先选项。
除此以外,也可以执行这行命令重启:
1 | sudo reboot |