Support #683
Updated by Daniel Curtis about 9 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>
* Download the packages for yaourt:
<pre>
cd /tmp
wget https://aur.archlinux.org/cgit/aur.git/snapshot/package-query.tar.gz && wget https://aur.archlinux.org/cgit/aur.git/snapshot/yaourt.tar.gz
tar xzf package-query.tar.gz
tar xzf yaourt.tar.gz
</pre>
#* Install package-query:
<pre>
cd package-query
makepkg -csi
</pre>
#* Install yaourt
<pre>
cd ../yaourt
makepkg -csi
</pre>
h2. Set Up The Network
* Install netctl:
<pre>
pacman -S netctl
</pre>
h3. 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. NAT Wireless Connection (Optional)
* 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 dnsmasq
</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
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
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 trusty
</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 trusty
</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
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
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
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?
* 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>
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>
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/