在 Hyper-V 下安装 ArchLinux
该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/post/2023/10/17/install-archlinux-in-hyper-v/
文章目录
本教程指导在 Windows 11 Pro 中,使用系统自带的 Hyper-V 虚拟机安装 ArchLinux,并解决代理和宿主机文件共享问题。
本文操作环境为 Windows 11 Pro 英文版系统,部分系统文案请自行转换为中文理解。
目标与难点
本文的目标是在 Windows 11 Pro + Hyper-V 环境安装 Archlinux,并保证 Archlinux 可以全面使用代理,并与主机进行文件共享。
此外,本次安装不使用 grub 等引导管理器,直接使用 UEFI 引导。
-
问题1:代理
此前在
VirtualBox
下安装客户机系统后,由于采用的是 NAT 网络,可以通过对VirtualBox
所有进程挂代理(使用Proxifier
软件),给客户机配置系统级透明代理。换成 Hyper-V 后,这一套行不通了,须配合tun2socks
来实现。 -
问题2:共享目录
在
VirtualBox
下,通过VirtualBox
的系统组件很容易实现共享目录的挂载。而在 Hyper-V 下则必须用CIFS
来实现,而且还须解决 Windows 账户口令的问题。
配置开启 Hyper-V
下载安装 Archlinux LiveCD
前往 Archlinux 官网,选择一个合适的下载源,我这里选择 aliyun
,下载其中的 archlinux-20**.**.**-x86_64.iso
文件。
创建 Hyper-V 虚拟网络
启动管理员 PowerShell 命令行终端,执行如下步骤:
-
创建一个内部交换网络
1New-VMSwitch -SwitchName "MyArchSwitch" -SwitchType Internal
执行成功后,显示应该如下:
1Name SwitchType NetAdapterInterfaceDescription 2---- ---------- ------------------------------ 3MyArchSwitch Internal
-
以 Win11 为例,进入系统设置,选择“Network & Internet / Advanced network settings”
找到你当前使用的网络,点击展开,在“More adapter options”那一栏选择 Edit。
TipsWindows 10 应该更简单,可以直接找到传统的网络管理面板,找到当前使用的网络连接,右键“属性”就能打开这个 UI。
在弹出的框里切换到 Sharing 栏,勾选第一个 Allow other user connect through this computer’s internet connection,并在下面的下拉框里选择你上面创建的 Internal Switch,然后点击保存。
Tips第二个复选框不用勾选。
-
执行
Get-NetIPAddress -InterfaceAlias "vEthernet (MyArchSwitch)"
就可以看到主机的 IPv4 地址,一般情况下应该都是192.168.137.1
。Tips下面都以
192.168.137.1/24
为例,如果你的不一样请自行调整。 -
配置 Windows 防火墙放行规则,按下
Win+S
,搜索Windows Defender Firewall with Advanced Security
,在打开的控制台界面,左侧选择Inbound Policy
,再选择右侧栏的New Rule
,在New Inbound Rule Wizard
导航里,按如下操作:- Rule Type:选择 Custom 类型的规则,下一步;
- Program:不做修改,保存选择 All Program,下一步;
- Protocol And Ports:不做修改,下一步;
- Scope:添加本地 IP 地址
192.168.137.1
,添加远程 IP 地址192.168.137.2
,下一步; - Action:不做修改,保持 Allow the connections,下一步;
- Profile:不做修改,保持三个全选,下一步;
- Name:取个名字,比如“Allowed Archlinux in Hyper-V",完成。
创建 Hyper-V 虚拟机
- 按下 Win+S,查找并打开 Hyper-V Manager (如果没有,请通过操作系统设置启用 Hyper-V)
- 选择菜单“Action / New / Virtual Machine”,启动虚拟机创建导航
- Specify Name And Location:设置虚拟机名称和存储路径
- Specify Generation:选择第二代虚拟机(Generation 2)
- Assign Memory:配置内存至少 4GiB
- Configure Networking:网络选择上面创建的 Virtual Network Switch,如 MyArchSwitch
- Connect Virtual Hard Disk:选择创建新的主硬盘,自己调节大小,不应小于 40GiB
- Install Options:选择“Install an operating system from a bootable CD/DVD-ROM”,选择上面下载的 Archlinux LiveCD 文件
- 创建完成,继续配置
配置 Hyper-V 虚拟机
-
在 Hyper-V Manager 的 Virtual Machines 列表里找到你刚刚创建的虚拟机
-
右键选择
Settings
-
选择
Security
栏,把里面的Enable Secure Boot
关掉(如有需要可以开启 TPM) -
选择
SCSI Controller
栏,添加3个 Hard Drive,名称如下:(创建时,注意磁盘文件的存储位置)- Home:用于存储
/home
目录,大小自定 - Docker:用于存储
/var/lib/docker
目录,大小自定 - Swap:用于交换分区,大小和内存大小一致即可
- 如有其他,请自行添加。
确保
SCSI Controller
下每个硬盘的 Location 分别为 0, 1, 2, 3(如果还有请按序排列),而 DVD Drive 的 Location 为 4(反正在最后) - Home:用于存储
-
选择
Firmware
栏,确保DVD Drive
在第一个启动顺序,把Network Adapter
移到最后 -
选择
Checkpoint
栏,去掉Enable checkpoints
-
点击
Apply
,然后关闭
安装虚拟机操作系统
-
右键选择你的虚拟机,选择 Connect
-
在新打开的虚拟机操作窗口里,选择
Start
,等待进入的 LiveCD -
执行命令,查看当前系统的 IP 地址
1ip addr
看看
eth0
网卡下的inet
后面的 IP 地址,也就是192.168.137.xxx
,记住这个 IP。 -
执行
curl https://www.baidu.com
,确保网络畅通 -
执行
systemctl start sshd
启动 OpenSSH 服务端,以便后面使用 SSH 连接到虚拟机里操作,方便复制粘贴等操作。 -
执行
passwd
命令,设置 LiveCD 系统里的root
用户的口令 -
从主机执行
ssh -p 22 [email protected]
通过 SSH 连接到虚拟机继续操作。 -
初始化磁盘:
1fdisk /dev/sda # 初始化主磁盘 2 3o # 创建 DOS 分区表 4 5n # 创建分区 6p # 创建一个新的主分区 71 # 第1个分区 8回车 # 直接回车 9+512M # 创建 EFI 分区 10 11n # 创建分区 12p # 创建一个新的主分区 132 # 第2个分区 14回车 # 直接回车 15回车 # 剩余部分为一个分区 16 17w # 写入分区表并推出 18 19mkfs.fat /dev/sda1 # EFI 系统分区必须是 FAT 格式 20mkfs.ext4 /dev/sda2 # 根分区 21mkfs.ext4 /dev/sdb # 整个 Home 磁盘为一个分区,给 `/home` 使用 22mkfs.ext4 /dev/sdc # 整个 Docker 磁盘为一个分区,给 `/home` 使用 23mkswap /dev/sdd # 整个 Swap 磁盘为一个交换分区 24 25mount /dev/sda2 /mnt 26 27mkdir /mnt/boot 28mkdir /mnt/home 29mkdir /mnt/var/lib/docker -p 30 31mount /dev/sda1 /mnt/boot 32mount /dev/sdb /mnt/home 33mount /dev/sdc /mnt/var/lib/docker 34 35swapon /dev/sdd
-
配置 Pacman 镜像源
使用
vim
命令打开/etc/pacman.d/mirrorlist
文件,在最前面添加一行:1Server = https://mirrors.aliyun.com/archlinux/$repo/os/$arch
Tips如果你有代理,也可以不配置这个,直接
export https_proxy=http://192.168.137.1:11111
设置你的代理加速即可。 -
开始安装系统
1pacstrap /mnt base linux linux-firmware dhcpcd openssh vim wget sudo unzip
2
3genfstab -U /mnt >> /mnt/etc/fstab
4arch-chroot /mnt
- 系统基础配置
1ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime # 设置时区
2echo 'MyXXXXX' > /etc/hostname # 设置主机名
3hwclock --systohc # 写入系统时间
4
5ln -s /usr/bin/vim /usr/bin/vi
6
7vi /etc/locale.gen # 去除注释 en_US.UTF-8 UTF-8,以及 zh_CN 开头的4个中文字符集。
8
9locale-gen # 生成语言配置
10echo 'LANG=en_US.UTF-8' > vi /etc/locale.conf # 设置默认语言
11
12passwd # 设置新系统的 root 口令
- 创建普通用户并配置 SSH
1systemctl enable sshd # 设置 SSH 服务开机启动
2
3YOUR_USER=xxxxx # 你想要的常规用户名,比如 admin?mick?sarah?
4useradd -m $YOUR_USER # 创建常规用户,先创建用户,可以保证用户的 UID 和 GID 都是 1000 O(∩_∩)O
5
6visudo # 把 %sudo ALL=(ALL:ALL) ALL 这行取消注释
7groupadd sudo
8
9usermod -aG sudo $YOUR_USER # 为常规用户设置 sudo 权限
10passwd $YOUR_USER # 为常规用户设置口令
11
12mkdir /home/$YOUR_USER/.ssh
13echo 'YOUR-SSH-Pubkey' > /home/$YOUR_USER/.ssh/authorized_keys # 设置常规用户的 SSH 登录公钥
14chmod 0700 /home/$YOUR_USER/.ssh
15chmod 0600 /home/$YOUR_USER/.ssh/authorized_keys
16chown -R $YOUR_USER:$YOUR_USER /home/$YOUR_USER/.ssh
- 网络配置
本方案将设置一个固定 IP 方便访问,此处使用 192.168.137.2
。
1pacman -S dhcpcd
2systemctl enable dhcpcd
3
4echo 'interface eth0' >> /etc/dhcpcd.conf
5echo 'static ip_address=192.168.137.2/24' >> /etc/dhcpcd.conf
6echo 'static routers=192.168.137.1' >> /etc/dhcpcd.conf
此时还可以配置一个固定的 DNS 服务器,比如使用阿里的 DNS:(但是,如果需要开启 DoT/DoH,请跳过这个配置)
1echo 'static domain_name_servers=223.5.5.5 223.6.6.6' >> /etc/dhcpcd.conf
- DoH/DoT 设置(可选)
1pacman -S dnscrypt-proxy
2systemctl enable dnscrypt-proxy
3echo 'static domain_name_servers=127.0.0.1' >> /etc/dhcpcd.conf
然后编辑 /etc/dnscrypt-proxy/dnscrypt-proxy.toml
文件,移除 server_names = [...]
那行的注释,并选择你想要的 DoT/DoH 服务器。
由于 DoT/DoH 服务器大概率被 XX 了,可能需要配置代理,那么再加一行:
1proxy = 'socks5://192.168.137.1:11111' # 你的代理服务器
- 配置 EFI
1exit # 退出到 LiveCD
2
3blkid /dev/sda2 # 获取 PARTUUID="xxxxxxxx-xx",用于下一行命令
4
5efibootmgr \
6 --disk /dev/sda \
7 --part 1 \
8 --create \
9 --label "Linux Kernel" \
10 --loader /vmlinuz-linux \
11 --verbose \
12 --unicode 'root=PARTUUID=xxxxxxxx-xx rw initrd=\initramfs-linux.img' # 替换其中的 xxxxxxxx-xx 为上一条命令里的值
13
14poweroff # 关机,然后再启动即可正式进入系统
附录
配置用户在(开机后)第一次登录时自动启动 ssh-agent
只能以普通用户身份执行,不能以 root 身份执行。
1mkdir -p ~/.config/systemd/user/
2
3cat > ~/.config/systemd/user/ssh-agent.service <<EOF
4[Unit]
5Description=SSH key agent
6
7[Service]
8Type=simple
9Environment=SSH_AUTH_SOCK=%h/.config/ssh-agent.socket
10ExecStart=/usr/bin/ssh-agent -D -a \$SSH_AUTH_SOCK
11
12[Install]
13WantedBy=default.target
14EOF
15
16echo 'export SSH_AUTH_SOCK=~/.config/ssh-agent.socket' >> ~/.bashrc
17
18systemctl --user enable --now ssh-agent.service # 重新登录即生效
记住本次开机后登录过的会话密钥,避免反复输入密钥
须结合上面的
ssh-agent
服务使用。
在 ~/.ssh/config
文件的最前面加上一行:
1AddKeysToAgent yes
优化命令行 Ctrl 键的效果
须以 root 身份执行。
编辑 /etc/inputrc
文件,在中间新增两行:
1"\C-h": backward-kill-word
2"\e[3;5~": kill-word
就可以使用 Ctrl + Delete
和 Ctrl + Backspace
删除附近词了。
重新登录生效。
切换使用 LTS 版本的 Linux 内核
须以 root 身份执行。
如果不追求最新的内核版本,可以切换到 LTS 版本,以便获得更好的稳定性。
比如下面的 CIFS 挂载 Windows 宿主机共享目录,在 Linux 6.6.1 版本中就出了问题。
1pacman -S linux-lts efibootmgr
2
3blkid /dev/sda2 # 获取 PARTUUID="xxxxxxxx-xx",用于下一行命令
4
5efibootmgr \
6 --disk /dev/sda \
7 --part 1 \
8 --create \
9 --label "Linux Kernel LTS" \
10 --loader /vmlinuz-linux-lts \
11 --verbose \
12 --unicode 'root=PARTUUID=xxxxxxxx-xx rw initrd=\initramfs-linux-lts.img' # 替换 xxxxxxxx-xx 为上一条命令中读取的 PARTUUID
13
14poweroff # 关机,然后再启动即可正式进入 LTS 版本的内核
确认无误后,可以删除掉旧的内核:
1pacman -R linux
开启 CIFS 访问主机目录
须以 root 身份执行。
- 先到 Windows 系统设置里创建一个普通用户(如
arch-guest
),设置口令登录(不要设置重设口令和口令过期时间) - 右键须分享的目录(如
D:/VMShared
),选择“属性”,进入到“分享”,选择“高级分享(Advanced Sharing)”,进入“Permissions”。 - 将“Everyone”的权限全部去除,再点击“添加(Add)”,把你新建立的用户添加进来,授予所有权限,保存。
- 回到虚拟机里,执行如下命令:
1pacman -S cifs
2
3mkdir /mnt/vmshared
4
5id $YOUR_USER # 查看你的常规用户的 UID 和 GID
6
7echo 'username=xxxxxxxxxxxx' > ~/.windows_credentials # Windows 的用户名
8echo 'password=xxxxxxxxxxxx' >> ~/.windows_credentials # Windows 的用户登录口令
9
10mount -t cifs \
11 //HOST-PC-NAME/VMShared \
12 /mnt/vmshared \
13 -o credentials=/root/.windows_credentials,ip=192.168.137.1,iocharset=utf8,file_mode=0600,dir_mode=0700,uid=1000,gid=1000
14
15ls /mnt/vmshared # 确定生效,如果没有,则根据 dmesg 日志进行排查。
16
17echo '//HOST-PC-NAME/VMShared /mnt/vmshared cifs credentials=/root/.windows_credentials,ip=192.168.137.1,iocharset=utf8,file_mode=0600,dir_mode=0700,uid=1000,gid=1000,x-systemd.automount 0 0' >> /etc/fstab # 写入到 fstab,使之在系统启动后自动挂载
配置系统级透明代理
须以 root 身份执行。
从 https://github.com/xjasonlyu/tun2socks/releases/ 找到最新稳定版,请按需替换如下 wget
命令中的 v2.5.1
版本号。
1sudo su # 切换到root
2cd ~
3
4wget https://github.com/xjasonlyu/tun2socks/releases/download/v2.5.1/tun2socks-linux-amd64-v3.zip
5unzip tun2socks-linux-amd64-v3.zip
6rm tun2socks-linux-amd64-v3.zip
7mkdir /usr/local/tun2socks/bin -p
8mv tun2socks-linux-amd64-v3 /usr/local/tun2socks/bin/tun2socks
9
10cat > /usr/local/tun2socks/bin/init.sh <<EOF
11#!/usr/bin/env bash
12ip tuntap add mode tun dev tun0
13ip addr add 10.0.0.1/16 dev tun0
14ip link set dev tun0 up
15ip route add default via 10.0.0.1 dev tun0 metric 1
16EOF
17
18chmod 0700 /usr/local/tun2socks/bin/*
19
20cat > /usr/local/tun2socks/config.yml <<EOF
21# debug / info / warning / error / silent
22loglevel: warning
23
24# URL format: [protocol://]host[:port]
25proxy: socks5://192.168.137.1:11111
26
27# URL format: [driver://]name
28device: tun://tun0
29
30# Maximum transmission unit for each packet
31mtu: 1500
32
33# Network interface to bind, Linux/macOS only
34interface: eth0
35
36# Timeout for each UDP session, default value: 60 seconds
37udp-timeout: 60s
38
39# SO_MARK socket option, Linux only
40fwmark: 0
41EOF
42
43cat > /usr/lib/systemd/system/tun2socks.service <<EOF
44[Unit]
45Description=Tun2socks
46Documentation=https://github.com/xjasonlyu/tun2socks
47After=network.target network-online.target
48
49[Service]
50Type=simple
51ExecStart=/usr/local/tun2socks/bin/tun2socks -config /usr/local/tun2socks/config.yml
52Restart=always
53
54[Install]
55WantedBy=multi-user.target
56EOF
57
58cat > /usr/lib/systemd/system/init-tun2socks.service <<EOF
59[Unit]
60Description=Init Tun2socks
61Documentation=https://github.com/xjasonlyu/tun2socks
62After=network.target network-online.target
63
64[Service]
65Type=simple
66ExecStart=/usr/local/tun2socks/bin/init.sh
67
68[Install]
69WantedBy=multi-user.target
70EOF
71
72systemctl enable --now init-tun2socks.service
73systemctl enable --now tun2socks.service
映射虚拟机端口到主机上
由于使用的是内部网络,且通过网卡分享的方式,所以虚拟机的端口是无法通过 VM-NAT 网络映射到主机上的。
此时可以使用 netsh
命令来实现端口映射,下面是操作命令,应通过管理员 PowerShell 命令行终端执行:
-
添加端口映射
下面示例将虚拟机里的
22
端口映射到主机的2222
端口上。(假定虚拟机的 IP 地址为192.168.137.2
)1netsh interface portproxy add v4tov4 listenport=2222 listenaddress=0.0.0.0 connectport=22 connectaddress=192.168.137.2
-
查看已经添加的端口映射
1netsh interface portproxy show all
这条命令的示例输出如下:
1Listen on ipv4: Connect to ipv4: 2 3Address Port Address Port 4--------------- ---------- --------------- ---------- 50.0.0.0 2222 192.168.137.2 22
-
删除已经添加的端口映射
通过指定主机端口和 IP 地址即可删除。
1netsh interface portproxy delete v4tov4 listenport=2222 listenaddress=0.0.0.0
FAQ
CIFS 无法工作怎么办?
如果在滚动更新内核到 v6.6 以后,遇到 CIFS 无法工作,且 dmesg
报如下错误
1CIFS: VFS: cifs_mount failed w/return code = -4
那么,是因为内核更新导致的问题,可以将内核降级到 v6.6 之前的版本。(可以尝试切换到 linux-lts
内核,如果它还停留在 6.1 版本,详见附录)
虚拟机重启后突然网络不通了怎么办?
-
如果开启了
tun2socks
服务,请检查代理服务器是否正常工作。 -
检查宿主机的网卡,是否和你起初配置的网卡不一致了,如果是,请关掉此前的网卡,重新在当前网卡配置网络分享给虚拟交换机。