Debian systemd-nspawn server
Debian systemd-nspawn server
This page shows how to configure an independent 'guest' Debian server inside whatever gnu/linux host system running. The only requisite is that the host machine must run a gnu/linux with the same arch (for instance amd64) of the guest system.
Nowadays, a easy and well documented way to do such thing using an official Debian docker image and installing the docker daemon service in the host machine. However, a solution that provides a minor overhead for disk space and memory consumption is the use of the native systemd system. Such solution is the scope of this article. Note that a more crude solution is the use of the old good friend chroot command that still perform a good job but just for filesystem isolation. A tutorial using chroot is avaliable here.
Prerequisites
To start, we need to create a minimal Debian system root folder. This can be done following the Debootstrap tutorial that generates a Debian root folder compressed in a tar.gz file. In the same tutorial there are instruction to extract and configure the Debian system root folder in the host machine.
So, move the compressed tar.gz file in the host machine and configure it following the Debootstrap tutorial itself.
Configure the 'guest' system to start at the 'host' bootstrap
Now we need to configure our host system to boot the Debian guest system at startup:
######################################## #### Configure container to start at host bootstrap export BASE_PATH=/srv export DEST_DIR=DEBIAN_buster_amd64 export CONTAINER_NAME=DEBIANGUEST # note, no dashes or hyphens allowed in the container name, # Enable the "machines" target so all of the containers we create are able to be started at boot via a service call. While the services may be started and enabled, if this target is not added the nspawn containers will not auto-boot. systemctl enable machines.target # Create a new boot systemd service systemctl enable systemd-nspawn@${CONTAINER_NAME}.service # Customize the container startup # note, the first empty ExecStart= is required mkdir -p /etc/systemd/system/systemd-nspawn@${CONTAINER_NAME}.service.d/ cat > /etc/systemd/system/systemd-nspawn@${CONTAINER_NAME}.service.d/override.conf << EOF [Service] ExecStart= ExecStart=/usr/bin/systemd-nspawn --keep-unit --boot --link-journal=try-guest --directory=${BASE_PATH}/${DEST_DIR} --machine ${CONTAINER_NAME} EOF systemctl daemon-reload # start now systemctl start systemd-nspawn@${CONTAINER_NAME}.service systemctl status systemd-nspawn@${CONTAINER_NAME}.service # enter machinectl list # to see the container name machinectl login ${CONTAINER_NAME}
Add a custom services in the 'guest' system
- script to limit requests to sshd service iptables_SSHlimit.sh
Save it and put it to work!
chmod 0750 iptables_SSHlimit.sh mv iptables_SSHlimit.sh /etc/init.d cat > /etc/systemd/system/iptables_SSHlimit.service << EOF [Unit] Description=Firewall rules to limit ssh incoming connections [Service] Type=simple RemainAfterExit=yes ExecStart=/etc/init.d/iptables_SSHlimit.sh start ExecStop=/etc/init.d/iptables_SSHlimit.sh stop [Install] # Installs a hook to use this unit file when the system boots or shuts down WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable iptables_SSHlimit.service systemctl start iptables_SSHlimit.service systemctl status iptables_SSHlimit.service
Configuring network details (to be completed)
######################################## #### HOST SIDE # setup macvlan bridge 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 9001 qdisc mq state UP group default qlen 1000 link/ether 06:00:30:b5:ad:9a brd ff:ff:ff:ff:ff:ff inet 172.31.20.253/20 brd 172.31.31.255 scope global dynamic eth0 valid_lft 2459sec preferred_lft 2459sec inet6 fe80::400:30ff:feb5:ad9a/64 scope link valid_lft forever preferred_lft forever #ip link del macvlan1 ip link add macvlan1 link eth0 type macvlan mode bridge ip addr add 10.0.0.1/24 broadcast 10.0.0.255 dev macvlan1 ip link set macvlan1 up systemd-nspawn --boot --directory=${BASE_PATH}/${DEST_DIR} --private-network --network-macvlan=macvlan1 --machine debian 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: mv-macvlan1: <BROADCAST,MULTICAST> mtu 9001 qdisc noop state DOWN group default qlen 1000 link/ether 66:4a:4f:c5:8d:4f brd ff:ff:ff:ff:ff:ff link-netnsid 0 ip addr add 10.0.0.2/24 broadcast 10.0.0.255 dev mv-macvlan1 ip link set mv-macvlan1 up ip route add default via 10.0.0.1 dev host0 # Note: use root as user, and run 'shutdown -h now' to quit ## configure the system in a second terminal ip link #1: lo: # loopback, not to use #2: enp2s0f0: # unused ethernet in this example #3: wlp3s0b1: # internet output interface in this example #26: ve-DEBIAN_stre@if2: # guest interface in this example # # set a arbitrary ip for the guest interface in the host side ip addr add 10.0.0.1/24 broadcast 10.0.0.255 dev ve-DEBIAN_stre ip link set dev ve-DEBIAN_stre up # enable the packed forward sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv6.conf.default.forwarding=1 sysctl -w net.ipv6.conf.all.forwarding=1 # configuring the forward output iptables -t nat -A POSTROUTING -o wlp3s0b1 -j MASQUERADE iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT # adding output forward for the guest interface in the host iptables -A FORWARD -i ve-DEBIAN_stre -o wlp3s0b1 -j ACCEPT ######################################## #### GUEST SIDE ip link #1: lo: # loopback, not to use #2: host0@if26: # host interface in this example # # set a arbitrary ip for the host interface in the guest side ip addr add 10.0.0.2/24 broadcast 10.0.0.255 dev host0 ip link set dev host0 up # define the host interface as default gateway ip route add default via 10.0.0.1 dev host0 # configure a name server echo nameserver 8.8.4.4 > /etc/resolv.conf ping 8.8.4.4 ########################################