过去一个学期,我一直使用 systemd-nspawn 来搭建各类开发环境。本文记录在 Archlinux 下使用 systemd-nspawn 来搭建 rcore 的开发环境。
创建 Ubuntu 20.04 环境
使用 debootstrap 创建一个 ubuntu 环境,详见 Archlinux Wiki
首先安装 debootstrap 和 ubuntu-keyring ,再使用 debootstrap 创建 ubuntu 环境,其中 <container-name> 为我的容器名称。
# cd /var/lib/machines
# debootstrap --include=dbus,systemd-container --components=main,restricted,universe,multiverse focal <container-name> repository-url
创建 root 密码
# systemd-nspawn -D /var/lib/machines/<container-name>
passwd
logout
网络配置
通过 veth 来连接 host 和 nspawn ,通过 nat 给 nspawn 提供外网访问。
nspawn 配置文件如下:
[Network]
VirtualEthernet=yes
iptables 配置:
# iptables -t nat -A POSTROUTING -s 192.168.163.192/28 -j MASQUERADE
# iptables -A FORWARD -i ve-+ -j ACCEPT
上面命令只对本次启动起作用,重启后失效。
如果使用 ufw,可以选择修改 /etc/ufw/before.rules ,以实现防火墙规则的持久化。
-
在 before.rules 第一个 commit 前插入:
-A ufw-before-forward -i ve-+ -j ACCEPT -
在 before.rules 文件最底下加入:
# allow IP masquerading from 192.168.163.192/28 *nat :POSTROUTING ACCEPT [0:0] -A POSTROUTING -s 192.168.163.192/28 -j MASQUERADE COMMIT
host 侧配置网络地址
编辑容器的 service 配置文件
# systemctl edit systemd-nspawn@<container-name>.service
添加下面3行配置,在容器启动后手动在host端添加ip地址
[Service]
ExecStartPost=/usr/bin/ip address add 192.168.163.193/28 dev ve-rcore
ExecStartPost=/usr/bin/ip link set dev ve-rcore up
启用 linux 的 ipv4 转发
# sysctl net.ipv4.ip_forward=1
如需持久化,需修改文件。ufw 用户可选择修改 /etc/ufw/sysctl.conf。
nspawn 侧网络配置
nspawn 侧选择直接使用 systemd-networkd 来进行网络配置
启用 systemd-networkd
# systemctl enable --now systemd-networkd
网络配置文件如下:
[Match]
Name=host0
[Network]
Address=192.168.163.194/28
Gateway=192.168.163.193
DNS=192.168.1.1
因为我是台式机,网络环境不会变,所以目前 dns 是固定配置为 192.168.1.1。
如果是经常移动的笔记本,可以配置为公共 dns 地址。
其他配置
如果出现 terminal type 问题和终端颜色异常,尝试在 nspawn 配置文件中配置一下容器的环境变量
[Exec]
Environment=TERM=xterm-256color
Tailscale ssh
因为我计划使用 tailscale ssh 来进行远程开发,所以在容器里面部署一下 tailscale ssh。
-
安装 tailscale,见 tailscale docs
-
启用 tailscale 的用户网络模式,容器环境下不使用 tun。修改 /etc/default/tailscaled,在 FLAGS 处加入 “–tun=userspace-networking”
-
进行正常设备认证连接到自己的 tailnet
-
修改 tailscale 的 acl ,添加 accpet 规则,默认的 check 规则在 ssh 连接时需要定期进行网页认证。
添加一个容器的专属 tag
"tagOwners": { "tag:containers": ["autogroup:admin"], }添加 ssh 的 acl 规则
{ "action": "accept", "src": ["autogroup:member"], "dst": ["tag:containers"], "users": ["autogroup:nonroot", "root"], }