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>
Now create the bridge:
* 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
<pre>
iptables -t nat -A PREROUTING -p tcp --dport 2222 -j DNAT --to 192.168.10.200:22
</pre>
# 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>
* (Optional) 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>
#* Install ubuntu-keyring:
<pre>
yaourt ubuntu-keyring
</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>
h2. Container setup
To find all available templates that come with LXC, look in @/usr/share/lxc/templates@ directory:
<pre>
ls /usr/share/lxc/templates
</pre>
#* _Example output:_
<pre>
lxc-alpine lxc-altlinux lxc-archlinux lxc-busybox lxc-centos lxc-cirros lxc-debian lxc-download lxc-fedora lxc-gentoo lxc-openmandriva lxc-opensuse lxc-oracle lxc-plamo lxc-sshd lxc-ubuntu lxc-ubuntu-cloud
</pre>
h3. Arch Container
* Create the container:
<pre>
lxc-create -n arch.example.com -t archlinux
</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.101
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.101/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. Raspbian Container
* Copy the existing Debian LXC template:
<pre>
cp /usr/share/lxc/templates/lxc-debian /usr/share/lxc/templates/lxc-raspbian
</pre>
* Edit the Raspbian LXC template:
<pre>
nano /usr/share/lxc/templates/lxc-raspbian
</pre>
#* And modify the following parameters:
<pre>
MIRROR=${MIRROR:-http://archive.raspbian.org/raspbian}
#...
arch='armhf'
debootstrap --verbose --variant=minbase --arch=$arch --no-check-gpg
</pre>
#* *NOTE*: The MIRROR variable is set to Rasbian repositories at http://archive.raspbian.org/raspbian
#* *NOTE*: The arch variable is set to *armhf*
#* *NOTE*: The debootstrap command has the added *@--no-check-gpg argument@*
* Create the container:
<pre>
lxc-create -n raspbian.example.com -t raspbian
</pre>
* Edit the Raspbian container config file:
<pre>
nano /var/lib/lxc/raspbian.example.com/config
</pre>
#* And add/modify the following:
<pre>
lxc.network.type = veth
lxc.network.flags = up
lxc.network.link = natbr0
lxc.network.name = eth0
lxc.rootfs = /var/lib/lxc/raspbian.example.com/rootfs
lxc.utsname = raspbian.example.com
lxc.arch = armvhf
</pre>
* Start the containter:
<pre>
lxc-start -n raspbian.example.com
</pre>
* Configure the container to use systemd within lxc:
<pre>
lxc.autodev = 1
lxc.pts = 1024
lxc.kmsg = 0
lxc.hook.autodev=/var/lib/lxc/raspbian.example.com/autodev
</pre>
h2. Autostart Containers
* Autostart the Arch container:
<pre>
systemctl enable lxc@arch.example.com.service
</pre>
* Autostart the Raspbian container:
<pre>
systemctl enable lxc@raspbian.example.com.service
</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