Support #683
Updated by Daniel Curtis over 8 years ago
{{>toc}} This is a simple guide for setting up and using Linux Containers on Arch Linux. h2. Prepare the Environment * Make sure the system is up to date: <pre> pacman -Syu </pre> * Install the base-devel and wget packages: <pre> pacman -S base-devel wget rsync </pre> * Install "yaourt":https://project.altservice.com/issues/509 h2. Set Up The Network * Install netctl: <pre> pacman -S netctl </pre> h3. (Net Config 1) Bridged Wired Connection * Bridge Internet-shared - This example will bridge network interface eth0 and configure a static IP for the bridge: <pre> nano /etc/netctl/lxcbridge </pre> #* And add/modify the following: <pre> Description="LXC Bridge" Interface=br0 Connection=bridge BindsToInterfaces=(eth0) IP=dhcp SkipForwardingDelay=yes </pre> * After changes are made, make sure to re-enable and restart the bridge: <pre> netctl enable lxcbridge netctl start lxcbridge </pre> * Enable IP Forwarding persist at boot: <pre> echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/40-ip-forward.conf </pre> * And also apply this iptables rule: <pre> iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE </pre> #* To make changes persist upon reboot: <pre> iptables-save > /etc/iptables/iptables.rules systemctl enable iptables systemctl start iptables </pre> h3. (Net Config 2) NAT Wireless Connection (Optional) * Install dnsmasq: <pre> pacman -S dnsmasq </pre> * Make sure that forwarding is turned on to support NAT: <pre> echo 1 > /proc/sys/net/ipv4/ip_forward </pre> * Make the previous change persistent after a reboot: <pre> echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.d/30-ipforward.conf echo 'net.ipv6.conf.default.forwarding=1' >> /etc/sysctl.d/30-ipforward.conf echo 'net.ipv6.conf.all.forwarding=1' >> /etc/sysctl.d/30-ipforward.conf </pre> * NAT Internet-shared - This example will bridge network interface eth0 and configure a static IP for the bridge: <pre> nano /etc/netctl/lxcnatbridge </pre> #* And add/modify the following: <pre> Description="LXC NAT Bridge" Interface=natbr0 Connection=bridge IP=static Address=192.168.10.200/24 DNS=192.168.1.1 SkipForwardingDelay=yes ExecUpPost="/usr/local/bin/natbr0-up" </pre> * Create the nat script: <pre> nano /usr/local/bin/natbr0-up </pre> #* And add the following: <pre> #!/bin/sh # Script to setup NAT iptables masquerade rules; and dnsmasq for DHCP and DNS. # This is the address assigned to the bridge at boot BRADDR=192.168.10.200 # DHCP IP address range for containers BRRANGE=192.168.10.201,192.168.10.250 # Configure iptables rules for NAT iptables -A FORWARD -i natbr0 -s ${BRADDR}/24 -m conntrack --ctstate NEW -j ACCEPT iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A POSTROUTING -t nat -j MASQUERADE # (Optional) Forward port 2222 to host behind NAT bridge # iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to 192.168.10.200:22 # Start dnsmasq DNS/DHCP server for the network attached to the NAT interface. dnsmasq --bind-interfaces --conf-file= --listen-address $BRADDR --except-interface lo --dhcp-range $BRRANGE --dhcp-lease-max=253 --dhcp-no-override </pre> * Make sure it is executable by doing <pre> chmod +x /usr/local/bin/natbr0-up </pre> * Start and enable the NAT bridge at boot: <pre> netctl enable lxcnatbridge netctl start lxcnatbridge </pre> * Now a container lxc.conf should read: <pre> lxc.network.type=veth lxc.network.link=natbr0 lxc.network.flags=up </pre> h2. Install LXC * Install lxc, bridge-utils, and arch-install-scripts: <pre> pacman -S lxc bridge-utils arch-install-scripts </pre> #* (_Optional_) Install extra packages for lxc: <pre> pacman -S lua lua-filesystem lua-alt-getopt </pre> * Test that the system is correctly configured <pre> lxc-checkconfig </pre> #* The output should be similar to: <pre> --- Namespaces --- Namespaces: enabled Utsname namespace: enabled Ipc namespace: enabled Pid namespace: enabled User namespace: missing Network namespace: enabled Multiple /dev/pts instances: enabled --- Control groups --- Cgroup: enabled Cgroup clone_children flag: enabled Cgroup device: enabled Cgroup sched: enabled Cgroup cpu account: enabled Cgroup memory controller: enabled Cgroup cpuset: enabled --- Misc --- Veth pair device: enabled Macvlan: enabled Vlan: enabled File capabilities: enabled </pre> h3. Arch Container * Create the container: <pre> lxc-create -n arch.example.com -t archlinux </pre> #* *NOTE*: If using btrfs, lxc can take advantage of the subvoluming btrfs provides. To use btrfs, create the container with the following command: <pre> lxc-create -n arch.example.com -t archlinux -B btrfs </pre> * Edit the Arch Linux container config file: <pre> nano /var/lib/lxc/arch.example.com/config </pre> #* And add/modify the following: <pre> lxc.network.type = veth lxc.network.flags = up lxc.network.link = br0 #lxc.network.hwaddr = lxc.network.ipv4 = 192.168.1.10/24 lxc.network.ipv4.gateway = 192.168.1.1 lxc.network.name = eth0 lxc.autodev = 1 lxc.pts = 1024 lxc.kmsg = 0 lxc.rootfs = /var/lib/lxc/arch.example.com/rootfs lxc.utsname = arch.example.com lxc.arch = armv7l </pre> * Start the Arch container: <pre> lxc-start -n arch.example.com </pre> * Open a console: <pre> lxc-attach -n arch.example.com </pre> #* And change the password: <pre> passwd </pre> * Create a wired connection: <pre> cp /etc/netctl/examples/ethernet-static /etc/netctl/wired </pre> * Edit the /etc/netctl/wired to match your needs. <pre> nano /etc/netctl/wired </pre> #* Add/modify the following: <pre> Description='Ethernet Connection' Interface=eth0 Connection=ethernet IP=static Address=('192.168.1.20/24') Gateway=('192.168.1.1') DNS=('192.168.1.1') # Required to start a network connection in a container ForceConnection=yes </pre> * Start and enable the wired connection at boot: <pre> netctl enable wired </pre> * *NOTE*: I needed to edit /etc/systemd/system/netctl\@wired.service and comment out the following in order for the netctl command to start: <pre> #BindsTo=sys-subsystem-net-devices-eth0.device #After=sys-subsystem-net-devices-eth0.device </pre> #* Then reload the systemd units: <pre> systemctl daemon-reload </pre> * While the console to the container is open, install openssh <pre> pacman -S openssh </pre> #* Start and enable openssh at boot: <pre> systemctl enable sshd.service systemctl start sshd.service </pre> h3. Debian Container * Install debootstrap from AUR: <pre> yaourt debootstrap </pre> #* Install gnupg1 for keyring verification; make sure to +edit the PKGBUILD+ and add *armv7h* to the arch parameter: <pre> gpg --keyserver pgpkeys.mit.edu --recv-keys 2071B08A33BD3F06 yaourt gnupg1 </pre> #* Install debian-archive-keyring: <pre> yaourt debian-archive-keyring </pre> * Create the container: <pre> lxc-create -n debian.example.com -t debian -- --release jessie --packages=apt-utils,wget,debian-keyring </pre> #* *NOTE*: If using btrfs, lxc can take advantage of the subvoluming btrfs provides. To use btrfs, create the container with the following command: <pre> lxc-create -n debian.example.com -t debian -B btrfs -- --release jessie --packages=apt-utils,wget,debian-keyring </pre> * Edit the Debian container config file: <pre> nano /var/lib/lxc/debian.example.com/config </pre> #* And add/modify the following: <pre> lxc.network.type = veth lxc.network.flags = up lxc.network.link = br0 lxc.network.ipv4 = 192.168.1.53/24 lxc.network.ipv4.gateway = 192.168.1.1 lxc.network.name = eth0 lxc.autodev = 1 lxc.pts = 1024 lxc.rootfs = /var/lib/lxc/debian.example.com/rootfs lxc.utsname = debian.example.com lxc.arch = armvhf </pre> * Start the containter: <pre> lxc-start -n debian.example.com </pre> #* (Optional) Attach to the container to execute commands: <pre> lxc-attach -n debian.example.com </pre> * _(Optional)_ Add the Raspbian repository on top of stock Debian repos: <pre> echo 'deb http://archive.raspbian.org/raspbian jessie main contrib non-free rpi' >> /etc/apt/sources.list.d/raspbian.list echo 'deb-src http://archive.raspbian.org/raspbian jessie main contrib non-free rpi' >> /etc/apt/sources.list.d/raspbian.list </pre> #* And add the Raspbian public signing key: <pre> wget https://archive.raspbian.org/raspbian.public.key -O - | sudo apt-key add - </pre> #* Update the apt repository cache and upgrade any necessary files: <pre> apt-get update && apt-get upgrade </pre> * _(Optional)_ Add the Wolfram Alpha repository: <pre> echo 'deb http://repository.wolfram.com/raspbian/ stable non-free' >> /etc/apt/sources.list.d/wolfram.list </pre> #* And add the Wolfram public signing key: <pre> apt-key adv —keyserver http://repository.wolfram.com/raspbian/raspbian@wolfram.com.gpg.pub-key —recv-keys 574FA74E5CBB4222 </pre> #* Update the apt repository cache and upgrade any necessary files: <pre> apt-get update && apt-get upgrade </pre> #* Install wolfram: <pre> apt-get install wolfram-engine mathelxc-create -n kali.example.com -t kali-arm -- --release sana --mirror=http://archive.kali.org/kali --security=http://security.kali.org/kali-security --packages=apt-utils,wget,debian-keyring,e2fsprogs,kali-defaults,kali-menu,parted,sudo,usbutilsmatica-fonts </pre> h3. Ubuntu Container * Install debootstrap from AUR: <pre> yaourt debootstrap </pre> #* Install ubuntu-keyring: <pre> yaourt ubuntu-keyring </pre> * Create the container: <pre> lxc-create -n ubuntu.example.com -t ubuntu - -r wily </pre> #* *NOTE*: If using btrfs, lxc can take advantage of the subvoluming btrfs provides. To use btrfs, create the container with the following command: <pre> lxc-create -n ubuntu.example.com -t ubuntu -B btrfs -- -r wily </pre> * Edit the Ubuntu container config file: <pre> nano /var/lib/lxc/ubuntu.example.com/config </pre> #* And add/modify the following: <pre> lxc.network.type = veth lxc.network.flags = up lxc.network.link = br0 lxc.network.ipv4 = 192.168.1.54/24 lxc.network.ipv4.gateway = 192.168.1.1 lxc.network.name = eth0 lxc.autodev = 1 lxc.pts = 1024 lxc.rootfs = /var/lib/lxc/ubuntu.example.com/rootfs lxc.utsname = ubuntu.example.com lxc.arch = armvhf </pre> * Start the containter: <pre> lxc-start -n ubuntu.example.com </pre> h3. Fedora Container * Create the container: <pre> lxc-create -n fedora.example.com -t fedora -- -R 23 </pre> * Edit the Fedora container config file: <pre> nano /var/lib/lxc/fedora.example.com/config </pre> #* And add/modify the following: <pre> lxc.network.type = veth lxc.network.flags = up lxc.network.link = br0 lxc.network.ipv4 = 192.168.1.55/24 lxc.network.ipv4.gateway = 192.168.1.1 lxc.network.name = eth0 lxc.autodev = 1 lxc.pts = 1024 lxc.rootfs = /var/lib/lxc/fedora.example.com/rootfs lxc.utsname = fedora.example.com lxc.arch = armvhf </pre> * Start the containter: <pre> lxc-start -n fedora.example.com </pre> h3. Kali Container * Install debootstrap from AUR: <pre> yaourt debootstrap </pre> #* Install gnupg1 for keyring verification; make sure to +edit the PKGBUILD+ and add *armv7h* to the arch parameter: <pre> gpg --keyserver pgpkeys.mit.edu --recv-keys 2071B08A33BD3F06 yaourt gnupg1 </pre> #* Install debian-archive-keyring: <pre> yaourt debian-archive-keyring </pre> * Create a sana debootstrap script from the debian jessie script: <pre> cp /usr/share/debootstrap/scripts/jessie /usr/share/debootstrap/scripts/sana </pre> * Create a kali-arm lxc template script from the debian jessie template: <pre> cp /usr/share/lxc/templates/lxc-debian /usr/share/lxc/templates/lxc-kali-arm </pre> * Edit the kali-arm lxc template: <pre> nano /usr/share/lxc/templates/lxc-kali-arm </pre> #* And modify the following: <pre> valid_releases=('squeeze' 'wheezy' 'jessie' 'stretch' 'sid' 'sana') #... packages=\ ifupdown,\ locales,\ libui-dialog-perl,\ dialog,\ isc-dhcp-client,\ netbase,\ net-tools,\ iproute,\ kali-archive-keyring,\ kali-defaults,\ kali-menu,\ openssh-server #... debootstrap --verbose --variant=minbase --arch=$arch --keyring=/usr/share/keyrings/kali-archive-keyring.gpg </pre> * Create the container: <pre> lxc-create -n kali.example.com -t kali-arm -- --release sana --mirror=http://archive.kali.org/kali --security=http://security.kali.org/kali-security --packages=apt-utils,wget,e2fsprogs,parted,sudo,usbutils </pre> #* *NOTE*: If using btrfs, lxc can take advantage of the subvoluming btrfs provides. To use btrfs, create the container with the following command: <pre> lxc-create -n kali.example.com -t kali-arm -B btrfs -- --release sana --mirror=http://archive.kali.org/kali --security=http://security.kali.org/kali-security --packages=apt-utils,wget,e2fsprogs,parted,sudo,usbutils </pre> * Edit the Kali container config file: <pre> nano /var/lib/lxc/kali.example.com/config </pre> #* And add/modify the following: <pre> lxc.network.type = veth lxc.network.flags = up lxc.network.link = br0 lxc.network.ipv4 = 192.168.1.56/24 lxc.network.ipv4.gateway = 192.168.1.1 lxc.network.name = eth0 lxc.autodev = 1 lxc.pts = 1024 lxc.rootfs = /var/lib/lxc/kali.example.com/rootfs lxc.utsname = kali.example.com lxc.arch = armvhf </pre> * Copy over the resolv config from the host: <pre> cp /etc/resolv.conf /var/lib/lxc/kali.example.com/rootfs/etc/ </pre> * Start the containter: <pre> lxc-start -n kali.example.com </pre> * Enable ssh at boot up: <pre> arch-chroot /var/lib/lxc/kali.example.com/rootfs /bin/bash /bin/systemctl enable ssh exit </pre> #* _(Optional)_ Add bob the administrative user: <pre> arch-chroot /var/lib/lxc/kali.example.com/rootfs /bin/bash /usr/sbin/adduser bob /usr/sbin/usermod -aG sudo bob exit </pre> #* Restart the container for the service to take effect: <pre> lxc-stop -n kali.example.com lxc-start -n kali.example.com </pre> * Now connect to the kali contain via ssh: <pre> ssh kali.example.com </pre> #* _(Optional)_ Install the desktop packages: <pre> apt-get install fonts-croscore fonts-crosextra-caladea fonts-crosextra-carlito gnome-theme-kali gtk3-engines-xfce kali-desktop-xfce kali-root-login lightdm network-manager network-manager-gnome xfce4 xserver-xorg-video-fbdev </pre> #* _(Optional)_ Install a few commomly used tools: <pre> apt-get install aircrack-ng ethtool hydra john libnfc-bin mfoc nmap passing-the-hash sqlmap usbutils winexe wireshark </pre> #* _(Optional)_ Install a Kali Top10 meta-package: <pre> apt-get install kali-linux-top10 </pre> #* *NOTE*: If installing the kali-linux-all, kali-linux-wireless, or kali-linux-sdr meta packages, make sure to create a modified uhd-usrp2 sysctl file before installing the packages. If this is not done, the installation process +will fail while installing+ the uhd-host package: <pre> echo '# USRP2 gigabit ethernet transport tuning' >> /etc/sysctl.d/uhd-usrp2.conf echo '#net.core.rmem_max=50000000' >> /etc/sysctl.d/uhd-usrp2.conf echo '#net.core.wmem_max=1048576' >> /etc/sysctl.d/uhd-usrp2.conf apt-get install kali-linux-sdr </pre> h2. Autostart Containers * Enable the lxc service at boot: <pre> systemctl enable lxc.service </pre> * Then add the autostart line to the containers config file: <pre> echo 'lxc.start.auto = 1' >> /var/lib/lxc/arch.example.com/config </pre> * Start the lxc service: <pre> systemctl start lxc.service </pre> h2. Device Passthru One of my use cases involves passing a serial device to a specific container. LXC makes this task simple with the @lxc-device@ command. * Pass @/dev/ttyACM0@ to the arch.example.com containers @/dev/ttyACM0@: <pre> lxc-device -n arch.example.com /dev/ttyACM0 /dev/ttyACM0 </pre> h2. Graphical Management * Install virt-manager: <pre> pacman -S virt-manager </pre> # Open virt-manager, then *Create a New Connection*. # Set the _connection type_ to *LXC*, and set the _container type_ to *Operating system container*. # Set the _OS root directory_ to *@/var/lib/lxc/arch.example.com/rootfs@*. # Set a desired CPU and RAM amount. # Set a name for the container. After the container is configured it will automatically start. h2. Shared Package Cache for Arch Containers *NOTE*: I found this trick to be incredibly useful by allowing me to update the host's packages, then use the downloaded packages to cut down on download time for updating the Arch containers; since many of the packages are the same between updates. Why download more than once if you don't have to, right? h3. Shared Per Container * Edit the arch linux container config file: <pre> nano /var/lib/lxc/arch.example.com/config </pre> #* And add the following to set the containers package cache to the host's package cache directory: <pre> # Share host package cache with this container lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0 </pre> #* *NOTE*: I needed to attach to the container and refresh the pacman database list: <pre> lxc-attach -n arch.example.com pacman -Sy exit </pre> h3. Shared With All Arch Containers * Edit the common arch linux container config file: <pre> nano /usr/share/lxc/config/archlinux.common.conf </pre> #* And add the following to set the containers package cache to the host's package cache directory: <pre> # Share host package cache with all containers lxc.mount.entry = /var/cache/pacman/pkg var/cache/pacman/pkg none bind 0 0 </pre> h2. Resources * https://s3hh.wordpress.com/2011/05/17/lxc-containers-on-a-host-with-wireless/ * https://wiki.archlinux.org/index.php?title=Linux_Containers&redirect=no * https://www.raspbian.org/RaspbianFAQ#Can_I_mix_packages_from_the_Debian_repositories_with_Raspbian.3F * https://www.raspbian.org/RaspbianRepository * https://www.raspberrypi.org/forums/viewtopic.php?f=94&t=61509 * https://github.com/andrius/build-raspbian-image/issues/1 * http://docs.kali.org/kali-on-arm/install-kali-linux-arm-raspberry-pi * http://docs.kali.org/development/kali-linux-arm-chroot * http://docs.kali.org/general-use/kali-linux-sources-list-repositories * https://forums.kali.org/showthread.php?18079-Public-key-error * https://github.com/offensive-security/kali-arm-build-scripts/blob/master/rpi2.sh * http://www.kali.org/new/kali-linux-metapackages/