Basic configuration files

December 22, 2022 Roberto Puzzanghera 0 comments


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

In the following we will have in the /lxc folder all containers' filesystems even when they are unprivileged:


Download lxc-common.conf, which contains netcgroupcapmount common settings. It will be imported in each newly created container's config file.

wget -O /etc/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 
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 

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  netmask  broadcast 
       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
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:

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
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
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 

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

> more /etcsubgid

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

Add a comment