关于 VPS 安装网上提供不少一键安装的脚本,但是不少服务器都不支持,会出现不少问题。我想用 openSUSE,却没有找到相关的资料。

其实安装系统挺简单的,这个暂不提,最重要的还是引导的工作。而我们要远程安装一个系统,这个同样道理的,只要考虑下怎么把我们的安装程序启动就行。

openSUSE 提供相应的教程: OpenSUSE Remote Install

接下来我们进行具体的操作。

获取基本配置

需要远程,我们得与 VPS 通网。如果可以的话,使用 Centos 目录结构更方便些。此处以 Debain 为示例。最后可以通过 VNC 查看信息,确保处理某些错误。

默认情况下,服务商已经为我们做好了这些,我们可以直接使用 SSH 远程连接上这台机器,一般的,我们需要获取到该机器现在配置的 IP 地址,我们后期需要配置该信息。同时还需要观察现有系统 boot 结构,这是我们用以启动的程序。

  1. 查看本机 IP 信息,部分服务商的网络方案不同,其 IP 配置不同,有些是和你的外网 IP 一致,有些则不然,只需要进入VPS查看就行:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    # ip addr
    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host 
           valid_lft forever preferred_lft forever
    2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
        link/ether 00:ff:ff:ff:ff:ff brd ff:ff:ff:ff:ff:ff
        altname enp0s3
        altname ens3
        inet <IPV4 ADDR> brd <IPV4 BRD> scope global eth0
           valid_lft forever preferred_lft forever
        inet6 <IPV6 ADDR> scope link 
           valid_lft forever preferred_lft forever
    

    这台 VPS 有一张名为 eth0 网卡,这里我们只需要记录 IPV4 ADDR 上的信息即可。

    routel 命令是可以直接获取我们需要的信息:

    1
    2
    3
    4
    5
    6
    7
    
    root@WHYQ:~# routel 
             target            gateway          source    proto    scope    dev tbl
           <TARGET>             <GATEWAY>      <IP >   kernel     link   eth0 
          127.0.0.0          broadcast       127.0.0.1   kernel     link     lo local
         127.0.0.0/ 8            local       127.0.0.1   kernel     host     lo local
          127.0.0.1              local       127.0.0.1   kernel     host     lo local
    127.255.255.255          broadcast       127.0.0.1   kernel     link     lo local
    

    sourceIP 的信息,gateway 网关信息,我们后面都需要用到。

  2. 查看本机启动配置。一般的,Linux 发行版都会有 boot 目录,不同的服务商处理启动的方式也有所不同:

    1
    2
    3
    4
    5
    6
    7
    8
    
    # ls /boot/ -l
    total 34388
    -rw-r--r-- 1 root root   236220 Aug  3 05:50 config-5.10.0-8-amd64
    drwxr-xr-x 5 root root     4096 Oct 29 13:49 grub
    lrwxrwxrwx 1 root root        4 Aug 18 10:32 grub2 -> grub
    -rw-r--r-- 1 root root 28139888 Aug 18 10:13 initrd.img-5.10.0-8-amd64
    -rw-r--r-- 1 root root       83 Aug  3 05:50 System.map-5.10.0-8-amd64
    -rw-r--r-- 1 root root  6821216 Aug  3 05:50 vmlinuz-5.10.0-8-amd64
    

    可以观察到 boot 目录下有内核相关的信息,其中 grubgrub2 分别是对应的启动文件,grub2 连接到 grub 配置。我本地主机的目录:

    1
    2
    3
    4
    5
    6
    
    ❯ ls /boot/
    grub/                                 initramfs-5.10.61-gentoo-x86_64.img.old*
    initramfs-5.10.61-gentoo-x86_64.img*  config-5.10.61-gentoo-x86_64.old*
    config-5.10.61-gentoo-x86_64*         System.map-5.10.61-gentoo-x86_64.old*
    System.map-5.10.61-gentoo-x86_64*     vmlinuz-5.10.61-gentoo-x86_64.old*
    vmlinuz-5.10.61-gentoo-x86_64*        EFI/
    

    还是有稍微区别的,VPS 明显是不支持 EFI 的,但那并不影响,无论是传统启动还是 EFI 启动,最终还是击中 grub 上面的配置,这个细节暂时不提。

    你也可以查看本机是否支持 EFI

    1
    2
    
    # ls /lib/firmware/efi
    ls: cannot access '/lib/firmware/efi': No such file or directory?	
    

    可以判断系统的磁盘类型是 gpt 还是 mbr,后续安装系统的使用还需要依造该类型选择的磁盘类型,否则系统可能无法正常启动,还需要自行配置 grub 的配置指向,则该虚拟机默认情况下 root 指向的是 (hd0, msdos1),是 mbr 了引导的系统。

    openSUSE 默认使用 gpt 磁盘类型,必须在后续安装的过程中修改磁盘类型,才能确保系统正确引导。

  3. 观察 grub 配置,后续需要依造现有的配置模仿改造配置程序,确保适应服务商的启动方案:

     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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    
    root@WHYQ:/boot# cat grub2/grub.cfg
    #
    # DO NOT EDIT THIS FILE
    #
    # It is automatically generated by grub-mkconfig using templates
    # from /etc/grub.d and settings from /etc/default/grub
    # 
    ## ...
       set default="0"
    set linux_gfx_mode=
    export linux_gfx_mode
    menuentry 'Debian GNU/Linux' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-/dev/vda1' {
    	load_video
    	insmod gzio
    	if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
    	insmod part_msdos
    	insmod ext2
    	echo	'Loading Linux 5.10.0-8-amd64 ...'
    	linux	/boot/vmlinuz-5.10.0-8-amd64 root=/dev/vda1 ro  net.ifnames=0 biosdevname=0 quiet
    	echo	'Loading initial ramdisk ...'
    	initrd	/boot/initrd.img-5.10.0-8-amd64
    }
    submenu 'Advanced options for Debian GNU/Linux' $menuentry_id_option 'gnulinux-advanced-/dev/vda1' {
    	menuentry 'Debian GNU/Linux, with Linux 5.10.0-8-amd64' --class debian --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-5.10.0-8-amd64-advanced-/dev/vda1' {
    		load_video
    		insmod gzio
    		if [ x$grub_platform = xxen ]; then insmod xzio; insmod lzopio; fi
    		insmod part_msdos
    		insmod ext2
    		echo	'Loading Linux 5.10.0-8-amd64 ...'
    		linux	/boot/vmlinuz-5.10.0-8-amd64 root=/dev/vda1 ro  net.ifnames=0 biosdevname=0 quiet
    		echo	'Loading initial ramdisk ...'
    		initrd	/boot/initrd.img-5.10.0-8-amd64
    	}
    }
    ## ...
    ### END /etc/grub.d/10_linux 
    ### END /etc/grub.d/41_custom ###
    

    此处保留了核心配置。查看其中的 menuentry 部分,就是需要配置内核的地方,其中 linuxinitrd 是配置启动参数和内核的地方,我们需要做的修改就在这一部分。

该文章是 21 过年左右写的,那时候该服务商的启动脚本还很坑爹,grub:1grub:2 共存,先走 grub:1 ,再走 grub:2,因为太繁杂了,当时就没有注意,直接借助 VNC 跳过了,现在的配置看起来相对正常了。原有的问题复现也没有太大意义,于是删除了。

配置安装程序

实际上就是让启动菜单引导到发行版提供的内核文件中,initramfs 中可以编译进一个小的应急系统(看发行版如何配置),这个系统直接写进内存,就可以当作安装程序来用了,理论上只有能联网,啥都能干。当然,部分服务商也提供应急系统,那就不用做任何配置,直接进系统,把文件写进系统盘,就成装系统了。

openSUSE 提供的远程安装方法中,需要下载两个文件:

1
2
3
cd /boot
wget --output-document=vmlinuz.install http://download.opensuse.org/distribution/leap/15.2/repo/oss/boot/$(uname -m)/loader/linux
wget --output-document=initrd.install http://download.opensuse.org/distribution/leap/15.2/repo/oss/boot/$(uname -m)/loader/initrd

一个小白都能比对出来,我们下的文件就是之前 grub 配置中的 linuxinitrd。这是 linux 内核相关的配置,linux 自然是内核程序,initrd 是我们前面提到的 initramfs,可以理解它能直接写进内存(实际就是 RAM 磁盘),编译过程可以给它写很多东西,看你自己的需求。如果你使用 Gentoo ,编译内核是常用的事情,initramfs 可以包含 btrfs lvm 之类的核心依赖,如果里面不写进这些东西,那么安装了该文件系统的系统就无法启动起来。当然其他发行版都可以自行编译内核和自己的 initramfs,不管出于什么目的。

下面有两个方法,请查看完再选择对应的方法。

方法一: grub 引导

openSUSE 提供的是一个用于引导安装的程序,我们可以通过内核参数来配置初始化该程序,如下(grub 配置):

1
		linux	/boot/vmlinuz-5.10.0-8-amd64 root=/dev/vda1 ro  net.ifnames=0 biosdevname=0 quiet

其他引导器也是一样的,都需要配置 linuxinitrd 两个选项,不提。

此处更新文章,打算直接使用最新版本的 openSUSE Leap。如果该文章太久远了,你可以自行通过 Get openSUSE 查看相应的版本。

Get openSUSE 中提供了不少镜像,如果需要本地安装,均可在此下载,我们需要下载的文件需要点击需要进入他们的镜像源才能找到,该页面只提供 ISO 安装盘。我们需要的是一个可以执行远程安装的 linuxinitrd

镜像源 中包含了几乎所有镜像,我们进入 15.3/repo/oss/boot/x86_64,可以对应你的系统架构进入,架构查看使用 uname -m 查看。

该处提供了几乎所有情况下可供系统启动的配置文件,openSUSEgrub 使用的主题也有,我们就不需要这么麻烦了,直接拿 linuxinitrd 来用就是了。

1
2
3
cd /boot
wget --output-document=vmlinuz.install http://download.opensuse.org/distribution/leap/15.3/repo/oss/boot/$(uname -m)/loader/linux
wget --output-document=initrd.install http://download.opensuse.org/distribution/leap/15.3/repo/oss/boot/$(uname -m)/loader/initrd

与之前一样,只是更换了版本,如果需要其他版本,更换 15.3 就行,可能镜像源的结构会发生改变,应当先通过链接查看以下结构,在将链接替换即可。

随后我们可以看到以下结构:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
root@WHYQ:/boot# ls -l
total 165192
-rw-r--r-- 1 root root    236220 Aug  3 05:50 config-5.10.0-8-amd64
drwxr-xr-x 5 root root      4096 Oct 29 13:49 grub
lrwxrwxrwx 1 root root         4 Aug 18 10:32 grub2 -> grub
-rw-r--r-- 1 root root  28139888 Aug 18 10:13 initrd.img-5.10.0-8-amd64
-rw-r--r-- 1 root root 124890780 May 24 00:22 initrd.install
-rw-r--r-- 1 root root        83 Aug  3 05:50 System.map-5.10.0-8-amd64
-rw-r--r-- 1 root root   6821216 Aug  3 05:50 vmlinuz-5.10.0-8-amd64
-rw-r--r-- 1 root root   9050048 May 24 00:22 vmlinuz.install

之后我们只要将 grub 指向到我们的 vmlinuz.installinitrd.install 即可。我们前面已经了解了 grub.cfg 的配置了,只需要替换相关的字段就行了。

1
2
3
	linux	/boot/vmlinuz-5.10.0-8-amd64 root=/dev/vda1 ro  net.ifnames=0 biosdevname=0 quiet
	...
	initrd	/boot/initrd.img-5.10.0-8-amd64

我们已经将 vmlinuzinitrd 下载到 boot 文件夹。但是我们还需要配置内核相关信息,因此直接用 sed 不大方便,我们直接编辑文件。一般系统自带 vi(不是 vim),可以用 vi 直接编辑。

但可能 vi 会提醒你:W10: Warning: Changing a readonly file

1
2
# ls -l /boot/grub/grub.cfg
-r--r--r-- 1 root root 3844 Oct 30 05:11 /boot/grub/grub.cfg

文件权限现在只有只读权限,添加即可:

1
2
3
# chmod u+w /boot/grub/grub.cfg
# ls -l /boot/grub/grub.cfg
-rw-r--r-- 1 root root 3844 Oct 30 05:11 /boot/grub/grub.cfg

u+w 是给当前用户添加可写权限,VPS 可以获取 root 权限,自然可以直接操作。(无 root就别提重装系统啦。)

1
2
3
4
5
6
7
8
9
# 将这部份信息添加到原来启动菜单前面
menuentry 'Opensuse Install' {
		insmod gzio
		set root='hd0,msdos1' # 指向 msdos1 mbr 引导
        echo    'Loading Opensuse Linux'
        linux   /boot/vmlinuz.install noapic usessh=1 sshpassword=iamfuckthepassword install=http://download.opensuse.org/distribution/leap/15.3/repo/oss/ hostip=192.168.42.123 gateway=192.168.42.1 netmask=255.255.255.0 nameserver=192.168.42.1
        echo    'Loading initial ramdisk ...'
        initrd  /boot/initrd.install
}

其中 linux 配置了不少选项:

  1. usessh=1,提供 ssh 服务,同时需要设置密码 sshpassword,此后可以使用该密码进行安装了;
  2. install 是安装源,如果不指定,登录上也会要求指定的;
  3. hostipgatewaynameserver 就是我们之前查看的信息了,nameserver 你可以看看本机原来使用的是:cat /etc/resolv.conf

hostipgateway 一定要和 ip addr 查看的一致,否则的话可能会连接不上网络,就无法打通连接了。

配置好后重置系统即可,如果有 VNC 连接可以查看重启的过程,如果没有就等一阵子重连即可。实在崩了,可以尝试通过面板重装再来。

如果你的系统还使用 grub:1 ,同理,可以这么配置:

1
2
3
4
   title Boot -- openSUSE 15.2
      root (hd0,0)
      kernel /boot/vmlinuz.install noapic usessh=1 sshpassword=iamfuckthepassword install=http://download.opensuse.org/distribution/leap/15.2/repo/oss/ hostip=192.168.42.123/24 gateway=192.168.42.1 nameserver=192.168.42.1
      initrd /boot/initrd.install

一般 VNC 登录上去可以使用,有可能程序的流程配置修改了,导致系统无法正常启动,可以参考前文提到的文档 查看最新信息。

方法二: kexec 启动

只要你的系统不是需要编译的 Gentoo 或者 LFS,例如 Debian ,直接安装 kexec-tools 就可以实现内核热启动了。

1
2
3
4
# Debian 系统
apt install -y kexec-tools

reboot # 重启系统以重载 kexec

查看 kexec 文档:

1
2
3
4
5
6
7
man kexec

EXAMPLE
       For example, if the kernel image you want to reboot to is /boot/vmlinux, the contents of /proc/cmdline is root=/dev/hda1, and the path to the initrd is /boot/ini‐
       trd, then you would use the following command to load the kernel:

              kexec -l /boot/vmlinux --append=root=/dev/hda1 --initrd=/boot/initrd

可以看到这个参数配置和我们配置 grub 是一致的,那我们照猫画虎来一波:

1
2
3
4
5
6
7
8
9
kexec -l /boot/vmlinuz.install \
 --append=ssh=1 \
 --append=sshpassword=iamfuckthepassword \
 --append=install=http://download.opensuse.org/distribution/leap/15.3/repo/oss/ \
 --append=hostip=192.168.42.123 \
 --append=gateway=192.168.42.1  \
 --append=netmask=255.255.255.0 \
 --append=nameserver=192.168.42.1 \
 --initrd=/boot/initrd.install

或者可以修改官方提供的脚本:

 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
 #!/bin/bash
 set -xe
 : ${repo:=https://download.opensuse.org/distribution/openSUSE-stable/repo/oss}
 #: ${repo:=https://download.opensuse.org/tumbleweed/repo/oss}
 : ${arch:=$(uname -m)}
 : ${vncpassword:=supercomplexpassword}
 #: ${append:=vnc=1 vncpassword=$vncpassword}
 : ${append:=ssh=1 sshpassword=$vncpassword}
 #append+=" addon=https://download.opensuse.org/update/openSUSE-stable/"
 #append+=" autoyast=https://www.zq1.de/~bernhard/linux/opensuse/autoyast.leap153.xml"
 pkgs="wget kexec-tools"
 zypper -n install $pkgs ||
   DEBIAN_FRONTEND=noninteractive apt-get -y install $pkgs ||
   dnf install -y $pkgs ||
   pacman --noconfirm -S $pkgs ||
   emerge $pkgs ||
   true
 which wget
 which kexec
 mkdir -p /dev/shm/
 mount -t tmpfs tmpfs /dev/shm
 cd /dev/shm/
 wget $repo/boot/$arch/loader/{linux,initrd}
 kexec -l linux --initrd=initrd --reset-vga --append="install=$repo $append"
 sync ; echo u > /proc/sysrq-trigger ; sync
 kexec -e

如果 IP 信息配置出错,无法联网就需要借助其他工具重启连接上主机了。而且 vmlinuzinitrd 的版本要和 install 配置的 repo 一致,否则系统会请求确定是否重启,没有连接 VNC 则很难处理这个请求,因为此时 SSH 还没有启动。

安装系统

等待安装系统完成重启,信息配置准确,则可以进入系统。

1
ssh root@<IP>

或者:

1
ssh -X root@<IP>

用以启动 X 界面,图形化安装。

如果使用终端界面,直接执行 yast.ssh 即可,此处我们直接使用终端进行安装,图形界面连接不太稳定。

1
2
3
4
0:install:~ # yast.ssh 
Starting Installer
Sampling every 5 s to /var/log/YaST2/memsample.zcat             
*** Starting YaST2 ***

<TAB> 键可以更换按钮,其他的按提示进行即可,你甚至可以切换中文界面进行安装,安装系统会自动添加依赖信息。

图形化安装界面后续就不做介绍了,openSUSE 的安装做的很友好,Enter Enter 就行了。当然,我们前面查看到了系统不支持 EFI,如果支持,你可以直接默认进行下去,不支持的话需要在分配磁盘的时候自定义修改磁盘类型为 MBR

在最后的确认安装界面当中看到:

1
  │     +  Write it into MBR of /dev/vda (do not write)                                                                        

就说明磁盘配置是正确的。具体方法可以自行搜索,这部份并不难。

配置系统

系统完成安装后,需要做一些简单的配置,也可以说是加强的配置。

首先方便自己的远程控制,可以将自己的公钥发布到 VPS 当中:

1
ssh-copy-id <user>@<ip>

之后就不需要输入密码登录的,当然也应该关闭 SSH 密码登录,这样只要你本机的私钥不泄漏,谁都进不了你的主机了。

同时,为了方便自己本机的登录,可以给 SSH Client 添加配置,使用别名进行登录:

1
2
3
4
5
6
7
vim ~/.ssh/config
# 添加下面内容
   Host <登录别名>
   	HostName <ip或地址>
   	Port <port端口>
   	User <user>
# 均可以自定义 

SSH 配置

此配置在 VPS 当中。

  1. sshd 加强配置

    登录成功之后,确保安全(最基本避免暴力破解,但要确保存有密钥的电脑不被破解),我们就可以禁止密码登录了,仅允许密钥登录与修改端口:

     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
    
    ### 服务器
    vim /etc/ssh/sshd_config
    
    # 修改部分内容
    PermitRootLogin no # 禁用root登录,可以普通用户su
    
    PasswordAuthentication no
    ChallengeResponseAuthentication no # 禁用密码登录
    
    ## 可以修改端口
    Port 22 # 保留一个可以使用的端口,测试新端口可用后再关闭原来的端口
    # 如果系统设置了apparmor或者selinux,需要同时开启对应的端口
    Port 10222 # 改成你需要的
    ## selinux
    semanage port -m -t ssh_port_t -p tcp 10222 # 开放端口给ssh
    ## apparmor 暂时找不到对应的方法
    # 可以参考https://gitlab.com/apparmor/apparmor/-/raw/master/profiles/apparmor/profiles/extras/usr.sbin.sshd
    
    ## 端口修改注意,应该提前在防火墙开通端口,否则会造成无法ssh登录的窘境
    
    # 随后重启ssh服务
    systemctl restart sshd
    # openrc使用
    rc-service sshd restart
    
    ## 完成后,不要退出当前用户,先行测试是否能够登录(避免错误设置)
    

    其中修改端口,我个人认为实用性质不大,端口扫描只是一会儿的事情,你开 22 端口还是开 20002 端口都是一样的,只要端口扫描出来,还是能够暴力登录的,因此限制好服务的安全性就好,尽量避免被暴力破解,至于被暴力的入口,那是封不死的,你只能找办法把施暴者隔离起来不理会。

  2. 确保只有某个用户可以通过ssh登录也很重要(可以生成随机名称作为ssh登录用户名,其他用户依靠su登录)。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    ### 服务器
    vim /etc/ssh/sshd_config
    
    # 限制用户访问
    AllowUsers <users>
    # 空闲时间退出(在线时间)
    ClientAliveInterval 600
    ClientAliveCountMax 0
    #- 此处设置为600s,即十分钟无操作,将用户下线;
    # 限制登录次数,认证失误一次就断开链接
    MaxAuthTries 1
    
    # 随后重启ssh服务
    systemctl restart sshd
    # openrc使用
    rc-service sshd restart
    
    ## 同样,完成后,不要退出当前用户,先行测试是否能够登录(避免错误设置)
    # 其他用户无法认证
    Received disconnect from <ip> port 22:2: Too many authentication failures
    Disconnected from <ip> port 22
    

    ``

  3. 限制 IP 登录,如果你有固定 IP ,而且只希望该 IP 登录主机,那么就更好了:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    ### 服务器
    vim /etc/ssh/sshd_config
    AllowUsers <user>@<ip>
    
    # 允许ip段
    vim /etc/hosts.allow
    sshd:<ip>:allow
    # 禁止其他ip段
    vim /etc/hosts.deny
    sshd:ALL
    
    ## 如此只有你允许的ip和用户可以登录了
    # 重启sshd即可
    

小结

其实这里总归总的只是借用了 openSUSE 的文档,重新整理之后才发现这一部分官网本来就描述的很清楚。

总而言之,对于 Linux 系统,只有你有一个系统,就能尝试将引导文件写入引导,从而跳转到另一个系统当中去,但是由于服务商提供的不同架构(VPS : 虚拟主机),虚拟主机的架构各有不同,主要做的事情是仿造现有的架构执行安装,就没有太大的问题啦。

如果你想在你现在的 Linux 下安装另外一个系统,不必要加个 U盘

  1. 观察现有的 boot 目录结构及配置文件相关;
  2. 记录现在配置的网络连接信息;
  3. 找到目标系统的 Network Install 或者是 Remote Install 的相关文件;
  4. 引导目标系统的 initrdvmlinuz;
  5. 正常系统一样安装;

其实就这么几个步骤。!