Index
- Part 1: Introduction
- Part 2: Basic configuration files
- Part 3: Creating an unprivileged container on Slackware
- Part 4: Scripts overview
- Part 5: Natting example
- Browse the scripts' folder
- Changelog
Save to lxc.conf your system wide configuration settings. Put there the directory where you want to save your containers' filesystems:
cat > /etc/lxc/lxc.conf << __EOF__ lxc.lxcpath = /lxc __EOF__
In the following we will have all containers' filesystems in the /lxc folder even when they are unprivileged:
/lxc/c1 /lxc/c2
Download lxc-common.conf, which contains net
, cgroup
, cap
, mount
common settings. It will be imported in each newly created container's config file.
wget -O /etc/lxc/lxc-common.conf https://notes.sagredo.eu/files/hacks/lxc/lxc-common.conf chown root:root /etc/lxc/lxc-common.conf chmod +r /etc/lxc/lxc-common.conf
Download the LXC
bridge startup script by Christoph Willing and make it executable
wget -O /etc/rc.d/rc.lxc-bridge https://www.chriswilling.com/lxc/rc.lxc-bridge chown root:root /etc/rc.d/rc.lxc-bridge chmod +x /etc/rc.d/lxc-bridge
Consider to set your desired NAT network in rc.lxc-bridge, which defaults to 192.168.100
. Add it to your rc.local (or install it as a system service if you have systemd
):
cat >> /etc/rc.d/rc.local << __EOF__ if [ -x /etc/rc.d/rc.lxc-bridge ]; then # Starting lxc-bridge: echo "Starting lxc-bridge: /etc/rc.d/rc.lxc-bridge start" /etc/rc.d/rc.lxc-bridge start fi __EOF__
Now start the rc.lxc-bridge script and test it:
/etc/rc.d/rc.lxc-bridge start ifconfig lxcbr0 lxcbr0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500 inet 10.0.0.1 netmask 255.255.255.0 broadcast 10.0.0.255 ether fe:0e:2c:a9:5b:39 txqueuelen 1000 (Ethernet) RX packets 62514970 bytes 48884536603 (45.5 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 14084771 bytes 5271336716 (4.9 GiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
In my Slackware
15.0
the cgconfigparser
call inside rc.cgconfig is not parsing the configuration files stored into /etc/cgconfig.d, where we are going to save the configuration files, one for each user. I proposed a patch on the linuxquestions' Slackware
forum, but unfortunately I had no answer. So we have to patch that init script for the time being:
cd /etc/rc.d wget https://notes.sagredo.eu/files/hacks/lxc/rc.cgconfig.patch patch < rc.cgconfig.patch
Create the directory /etc/cgrules.d that will host our cgrules
configuration files, one for each user:
mkdir /etc/cgrules.d chown -R root:root /etc/cgrules.d
Make your libcgroup
init scripts executables:
chmod +x /etc/rc.d/rc.cgconfig /etc/rc.d/rc.cgred
rc.cgconfig and rc.cgred should now start with no errors.
/etc/rc.d/rc.cgconfig start /etc/rc.d/rc.cgred start
Both scripts will be started by your rc.S script at boot time, if you are running Slackware
. We'll see how to test the cgroup
services later on, once we have created our first unprivileged container.
Now download and compile the Serge Hallyn's uidmapshift.c program, which will be called to remap the ids of users and groups:
wget https://notes.sagredo.eu/files/hacks/lxc/uidmapshift.c cc uidmapshift.c -o /usr/local/bin/uidmapshift
Download the Serge Hallyn's lxc-container-userns-convert
shell script, which is the one who actually runs uidmapshift.
wget -O /usr/local/bin/my_lxc-container-userns-convert https://notes.sagredo.eu/files/hacks/lxc/my_lxc-container-userns-convert chown root:root /usr/local/bin/my_lxc-container-userns-convert chmod +x /usr/local/bin/my_lxc-container-userns-convert
I slightly modified this file just to use a variable which points to the conitainers' path LXC_PATH
.
Download all the other shell scripts to /usr/local/bin (we'll see them later):
cd /usr/local/bin wget https://notes.sagredo.eu/files/hacks/lxc/lxc-scripts.tar.gz tar xzf lxc-scripts.tar.gz chown root:root lx* my_lxc-* chmod +x lx* my_lxc-* chmod o-x lx* my_lxc-*
Set your default parameters inside the file my_lxc-common:
DOMAIN=mydomain.tld # default domain LXC_PATH=/lxc # where to store the LXC containers' filesystem CPUS=0-3 # number of cpu cores in the system
DOMAIN
defines the HOSTNAME
of the containers, LXC_PATH
is the path where to store the containers' filesystem (newly created containers will be copied there rather than in $HOME
/.local/share/lxc), while CPUS
is your number of CPU
cores, important when setting cgroups
. CPUS=0,3
stands for 4 cores.
The lxcctl
script that you have downloaded is a replacement of the /etc/rc.d/rc.lxc script for Slackware
users by Matteo Bernardini, modified by me in order to start both the unprivileged and the privileged default containers. So let's make it run at boot time:
mv /etc/rc.d/rc.lxc /etc/rc.d/rc.lxc.orig ln -s /usr/local/bin/lxcctl /etc/rc.d/rc.lxc cat >> /etc/rc.d/rc.local << __EOF__ if [ -x /etc/rc.d/rc.lxc ]; then # Starting lxc default containers: echo "Starting lxc default containers: /etc/rc.d/rc.lxc start" /etc/rc.d/rc.lxc start sleep 4 fi __EOF__
System files that will be modified behind the scene
Now a clarification about which system files will be modified for you when an unprivileged container c1
, owned by the system user user1
, will be created later on. You don't have to touch these files. When you destroy the container they will be modified or deleted accordingly and, if the owner of the container doesn't own any other container, that user will be deleted together with its idmap settings.
subuid
and subgid
setup
First of all the user user1
will be created if not existing yet. Then an id range will be allocated for that user/cgroup according to the files /etc/subuid and /etc/subgid:
> more /etc/subuid user1:100000:65536 > more /etc/subgid user1:100000:65536
Note that uid
and gid
share the same name user1
, just to make creation/deletion tasks easier. You may want to reserve the same range of ids if you plan to exhaust the whole uid/gid range. My script will reserve separate ranges for each user/cgroup.
cgconfig
setup
The file /etc/cgconfig.d/user1.conf will be created with the following content:
group user1 { perm { task { uid = user1; gid = nogroup; } admin { uid = user1; gid = nogroup; } } cpuset { cgroup.clone_children = 1; cpuset.mems = 0; cpuset.cpus = 0-3; } cpu {} cpuacct {} blkio {} memory { memory.use_hierarchy = 1; } devices {} freezer {} net_cls {} perf_event {} net_prio {} pids {} }
This file adds the control group named user1
and enables the ordinary user user1:nogroup
to run unprivileged containers. See man cgconfig.conf
for more details.
cgrules
setup
The file /etc/cgrules.d/user1.conf will be created with the following content:
user1 * user1/
It grants user user1
access to all controllers (*) mentioned in the control group named user1
. Look at man cgrules.conf
for more details.
lxc-usernet
setup
The user user1
will be added to the file /etc/lxc/lxc-usernet with the following content, so that user1
will have limits on network interfaces that it can create:
user1 veth lxcbr0 20