This is an old revision of the document!
Table of Contents
Linux containers
Linux containers (LXC) is the Linux implementation of FreeBSD Jails.
Within a Linux container we can run a self-contained installation of Linux which will utilise the system's kernel.
This is more lightweight method of virtualisation than than offered by Xen, for example.
Install
apt-get install lxc lxc-templates bridge-utils cgroupfs-mount conntrack iptables /etc/init.d/cgroupfs-mount start
Setup
Disable lxc services, we will do this stuff manually.
init.d
/etc/init.d/lxc-net stop update-rc.d lxc-net disable /etc/init.d/lxc stop update-rc.d lxc disable killall dnsmasq
systemd
systemctl disable lxc-net.service systemctl disable lxc.service
defaults
sed -i 's/LXC_AUTO="true"/LXC_AUTO="false"/ /etc/default/lxc sed -i 's/USE_LXC_BRIDGE="true"/USE_LXC_BRIDGE="false"/ /etc/default/lxc-net
Networking
Bridge
Virtual interfaces are bridged on to the primary network interface.
auto eth0 iface eth0 inet manual auto lxcbr0 iface lxcbr0 inet static bridge_ports eth0 address 10.10.44.10 netmask 255.255.255.0 gateway 10.10.44.1
Subnet
Virtual interfaces are contained on the their own private subnet.
auto lxcbr0 iface lxcbr0 inet static pre-up brctl addbr lxcbr0 address 10.10.10.1 netmask 255.255.255.0 post-down brctl delbr lxcbr0
iptables
Example NAT tables for containers on private subnet.
#! /bin/sh PATH=/sbin:/usr/sbin:/bin:/usr/bin iptables -t filter -F iptables -t filter -X iptables -t raw -F iptables -t nat -F /usr/sbin/conntrack -F # raw:PREROUTING iptables -t raw -A PREROUTING -i lo -j NOTRACK # raw:OUTPUT iptables -t raw -A OUTPUT -o lo -j NOTRACK # filter:INPUT iptables -t filter -P INPUT ACCEPT # filter:FORWARD iptables -t filter -P FORWARD ACCEPT # filter:OUTPUT iptables -t filter -P OUTPUT ACCEPT # nat:POSTROUTING iptables -t nat -A POSTROUTING -o eth0 -s 10.10.10.0/24 -d 0/0 -j MASQUERADE sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv4.conf.all.proxy_arp=1 sysctl -w net.netfilter.nf_conntrack_max=524288 sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=7440 echo 65536 > /sys/module/nf_conntrack/parameters/hashsize echo "1024 65535" > /proc/sys/net/ipv4/ip_local_port_range exit 0
Initialise
Wheezy on IBM PC platform
lxc-create -n HOSTNAME -t debian -- -r wheezy -a amd64
Stretch on Raspberry Pi
lxc-create -n cracker -t debian -- -r stretch -a armhf
Buster/Bullseye on Raspberry Pi
Install keys
wget "https://ftp-master.debian.org/keys/release-10.asc" wget "https://ftp-master.debian.org/keys/release-11.asc" gpg --no-default-keyring --keyring /var/cache/lxc/debian/archive-key.gpg --import release-10.asc gpg --no-default-keyring --keyring /var/cache/lxc/debian/archive-key.gpg --import release-11.asc
Install buster
lxc-create -n cracker -t debian -- -r buster -a armhf
Install bullseye
lxc-create -n terminator -t debian -- -r bullseye -a armhf
Configure
/var/lib/lxc/HOSTNAME/config
Obsolete Debian template
# Template used to create this container: /usr/share/lxc/templates/lxc-debian # Parameters passed to the template: -r wheezy -a amd64 # For additional config options, please look at lxc.container.conf(5) lxc.rootfs = /var/lib/lxc/HOSTNAME/rootfs # Common configuration lxc.include = /usr/share/lxc/config/debian.common.conf # Container specific configuration lxc.mount = /var/lib/lxc/HOSTNAME/fstab lxc.utsname = HOSTNAME lxc.arch = amd64 # Network lxc.network.type = veth lxc.network.flags = up # that's the interface defined above in host's interfaces file lxc.network.link = lxcbr0 # name of network device inside the container, # defaults to eth0, you could choose a name freely lxc.network.name = lxcnet0 lxc.network.hwaddr = 00:FF:AA:00:00:01 lxc.network.veth.pair = veth1 # the ip may be set to 0.0.0.0/24 or skip this line # if you like to use a dhcp client inside the container lxc.network.ipv4 = 10.10.10.10/24 # define a gateway to have access to the internet lxc.network.ipv4.gateway = 10.10.10.1 # Autostart lxc.start.auto = 1 lxc.start.delay = 5 lxc.start.order = 100
Modern Debian template
# Template used to create this container: /usr/share/lxc/templates/lxc-debian # Parameters passed to the template: -r stretch # Template script checksum (SHA-1): 5a35ad98c578f5487dc5712a1c7d38af399be813 # For additional config options, please look at lxc.container.conf(5) # Uncomment the following line to support nesting containers: #lxc.include = /usr/share/lxc/config/nesting.conf # (Be aware this has security implications) #lxc.net.0.type = veth #lxc.net.0.hwaddr = 00:XX:XX:XX:XX:XX #lxc.net.0.link = lxcbr0 #lxc.net.0.flags = up lxc.apparmor.profile = generated lxc.apparmor.allow_nesting = 1 lxc.rootfs.path = dir:/var/lib/lxc/cheese/rootfs # Common configuration lxc.include = /usr/share/lxc/config/debian.common.conf # Container specific configuration lxc.tty.max = 4 lxc.uts.name = cheese lxc.arch = armhf lxc.pty.max = 1024 # Local network configuration lxc.net.0.type = veth lxc.net.0.flags = up lxc.net.0.link = lxcbr0 lxc.net.0.name = lxcnet0 lxc.net.0.hwaddr = XX:XX:XX:XX:XX:XX lxc.net.0.veth.pair = veth0 lxc.net.0.ipv4.address = ?/24 lxc.net.0.ipv4.gateway = ? #lxc.net.0.ipv6.address = ? #lxc.net.0.ipv6.gateway = ? # You may need the following for initial boot # # You can replace systemd by changing the lxc.init.cmd before rebooting # lxc.cgroup.devices.allow = lxc.cgroup.devices.deny = lxc.init.cmd = /lib/systemd/systemd systemd.unified_cgroup_hierarchy=1 #lxc.init.cmd = /sbin/init
Run
Run in background (now the default)
lxc-start -d -n HOSTNAME
Run in foreground (was the default)
lxc-start -F -n HOSTNAME
Attach
Attach to container and change root password.
lxc-attach -n HOSTNAME passwd root
Stop
lxc-stop -n HOSTNAME
Unprivileged containers
Root can run containers with lower privileges. First we set aside some user ids to map to the container then configure it.
This has been tested to work Ubuntu vivid and nothing else since.
When assigning a range of ids to the root user. Choose what is available, here i chose 200000 because this was free.
usermod --add-subuids 200000-265535 root usermod --add-subgids 200000-265535 root
The host configuration now needs to map the ids in its config.
lxc.id_map = u 0 200000 65536 lxc.id_map = g 0 200000 65536
The container root will be system uid 200000, and nobody in the container will be 265534, for example..
Before starting, the lcx directory needs the execute permission.
chmod +x /var/lib/lxc
Now we can start and stop the container, attach to it, etc.