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
- Part6: Migrating to Slackware-current - LXC-6 - cgroup2
- 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://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/lxc-common.conf chown root:root /etc/lxc/lxc-common.conf chmod +r /etc/lxc/lxc-common.conf
Download the LXC bridge startup script and make it executable
wget -O /etc/rc.d/rc.lxc-bridge https://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/rc.lxc-bridge chown root:root /etc/rc.d/rc.lxc-bridge chmod +x /etc/rc.d/rc.lxc-bridge
Consider to set your desired NAT network in rc.lxc-bridge, which defaults to 10.0.0. 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://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/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://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/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://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/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://github.com/sagredo-dev/LXC-scripts/raw/refs/heads/1.04-lxc4-cgroup1/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
DOMAIN defines the HOSTNAME of the containers, while 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).
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

