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
- Part 6: Migrating to Slackware-current - LXC-6 - cgroup2
- Browse the scripts' folder
- Changelog
lxc-my_template is a modification of the default LXC template for Slackware by Matteo Bernardini, already installed in /usr/share/lxc/templates/lxc-slackware. It mostly changes the following things (diff here):
- it switches the release from current to 15.0
- it defines the
$domainvariable - it restores the
DIALOGvariable ofslackpkgtoon, as it fortunately seems to be working again - it slightly modifies the package list
- it removes the executable flag of a few not needed services
- it installs some aliases to /etc/profile, so that they can be set when attaching the container
- it sets the google's nameservers
- it copies the nano editor config file (.nanorc) if it exists
- it removes the
LXC's options that will be imported via the /etc/lxc/lxc-common.conf file - it removes the
procandsysfsentries from the /etc/fstab file as suggested by the C.W. guide, aslxc.mount.auto = proc:mixed sys:ro cgroupwill be added in the config file.
Download lxc-my_template
wget https://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/lxc-my_template chown root:root /usr/share/lxc/templates/lxc-my_template chmod +x /usr/share/lxc/templates/lxc-my_template
Now download the slackpkg templates, i.e. the file list for Slackware 15.0. I prepared two lists:
- 15.0.template, which contains almost all required packages for a tipical
LAMPserver. This is the default template in the script that we are going to use. - my_minimal.template, mostly the Ponce's list with the addition of
nano,file,glibc-zoneinfo,opensslandca-certificates, the last two just to avoidgpgerrors when runningslackpkg.
mkdir -p /etc/slackpkg/templates wget -O /etc/slackpkg/templates/15.0.template https://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/15.0.template wget -O /etc/slackpkg/templates/my_minimal.template https://raw.githubusercontent.com/sagredo-dev/LXC-scripts/refs/heads/1.04-lxc4-cgroup1/my_minimal.template chown root:root /etc/slackpkg/templates/*
Let's see how to use the my_lxc-create script, that you already downloaded before.
The usage is simple
Usage: /usr/local/bin/my_lxc-create script takes the following options:
-n <name> Set container name to use. **Required**
-r <release> Set Slackware release to use. Default: 15.0
-s <slackpkg-template> slackpkg template (pkg list). Default: 15.0. Alternative: my_minimal
-t <lxc-template> Set lxc template to use. Default: "my_template".
Use "slackware" to load /usr/share/lxc/templates/lxc-slackware (default slackware template)
Use "download" to load /usr/share/lxc/templates/lxc-download (no net configuration will be done in this case)
-m <mirror> Set mirror to use. If not set the one specified in the lxc template will be used
-o <domain> Domain
-d Use DHCP. Ignored if -i <ip> is passed
-i <ip> IP address of the container
-g <gw> Gateway
-u <user> Set the system user that will own the container. If not declared the container will be privileged
-h Print help options and exit
At the top of the script you may want to customize the default variables
MIRROR=https://mirrors.slackware.com/slackware GW=10.0.0.1 # gateway SLACKPKG_TEMPLATE=15.0 # slackpkg template (pkg list). Alternative: my_minimal LXC_TEMPLATE=my_template # lxc template. Use "slackware" to load /usr/share/lxc/templates/lxc-slackware RELEASE=15.0 # Release DHCP=no # Put yes if you want DHCP
You can always overwrite them by passing the options to the program according to the usage shown above.
Let's see some examples. In the simplest form, my_lxc-create will build a privileged container with the default values:
my_lxc-create -n c1
Here no net has been configured, unless you have DHCP=yes in your defaults. The slackpkg template /etc/lxc/templates/15.0.template has been used, while the LXC container will be created with the /usr/share/lxc/templates/lxc-my_template.
Optionally you may want to dinamically change some parameters when running the same script. For example:
my_lxc-create -n c1 -s my_minimal -r current -d
In this case the my_minimal slackpkg template will be used to install Slackware-current (at the moment I'm writing the same template will be fine also for current). The container will have DHCP support (-d).
The same, but this time a static IP will be configured:
my_lxc-create -n c1 -s my_minimal -r current -i 10.0.0.15
Building an unprivileged container
Now let's see how to tell the same script to create an unprivileged container. It will be sufficient to pass the user who will be the owner of the container:
my_lxc-create -n c1 -i 10.0.0.15 -u user1
So, when you add user1 as the -u option, my_lxc-create understands that the container must be unprivileged and owned by the system user user1. It will run the script my_lxc-turn_into_unprivileged to convert c1 to unprivileged. That user will be created on the fly and all the dirty settings will be done for you.
Let's see what happened in the config files. First of all, you can find the id mapping in the /lxc/c1/config file:
lxc.idmap = u 0 493217 65536 lxc.idmap = g 0 493217 65536
where of course 65536 is the id range and 493217 is the first id available in the system. You will find a line like this both in /etc/subuid and in /etc/subgid
user1:493217:65536
The cgroup files /etc/cgconfig.d/user1.conf and /etc/cgrules.d/user1.conf have been created with the settings for user1. A line for user1 has been added into /etc/lxc/lxc-usernet.
The command lscgroup shows the newly configured control group user1 (as said group and userid share the same name).
lscgroup | grep user1 cpuset:/www/lxc.monitor.user1 cpuset:/www/lxc.payload.user1 cpu:/www/lxc.monitor.user1 cpu:/www/lxc.payload.user1 cpuacct:/www/lxc.monitor.user1 cpuacct:/www/lxc.payload.user1 blkio:/www/lxc.monitor.user1 blkio:/www/lxc.payload.user1 memory:/www/lxc.monitor.user1 memory:/www/lxc.payload.user1 devices:/www/lxc.monitor.user1 devices:/www/lxc.payload.user1 freezer:/www/lxc.monitor.user1 freezer:/www/lxc.payload.user1 net_cls:/www/lxc.monitor.user1 net_cls:/www/lxc.payload.user1 perf_event:/www/lxc.monitor.user1 perf_event:/www/lxc.payload.user1 net_prio:/www/lxc.monitor.user1 net_prio:/www/lxc.payload.user1 pids:/www/lxc.monitor.user1 pids:/www/lxc.payload.user1
You can check that the cgroup configuration is good by parsing your config file like this
cgconfigparser -l /etc/cgconfig.d/user1.conf
or by parsing all files in the /etc/cgconfig.d directory
cgconfigparser -L /etc/cgconfig.d
Playing with the newly created container
Put the new container UP (lxu), start a shell inside it (attach with lxa, no need to change user!) and play with it
root@host:~# lxu c1 root@host:~# lxa c1 root@c1:# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.0.0.15 netmask 255.255.255.0 broadcast 10.0.0.255 ether a6:af:8e:1d:37:3b txqueuelen 1000 (Ethernet) RX packets 60309 bytes 11387162 (10.8 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 67259 bytes 20594117 (19.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 4253 bytes 2035914 (1.9 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 4253 bytes 2035914 (1.9 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 root@c1:# ping google.com PING google.com (142.250.201.174) 56(84) bytes of data. 64 bytes from par21s23-in-f14.1e100.net (142.250.201.174): icmp_seq=1 ttl=113 time=4.35 ms 64 bytes from par21s23-in-f14.1e100.net (142.250.201.174): icmp_seq=2 ttl=113 time=4.39 ms ^C --- google.com ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 4.351/4.371/4.391/0.020 ms root@c1:# exit exit root@host:~#
List the status of your containers (lxl is a wrapper of lxc-ls)
# lxl All containers NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c1 STOPPED 0 - - - true c2 STOPPED 0 - - - false Unprivileged running containers of user user1 NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c1 RUNNING 0 - 10.0.0.15 - false
Now destroy it (my_lxc-destroy):
root@host:~# my_lxc-destroy c1 c1 container is going to be destroyed. Confirm [y/n]? [n] y LXC container c1 is stopped. Continuing. User user1 is going to be deleted. Be sure that it is not a system user like apache, mysql etc. Confirm [y/n]? [n] y Deleting user1... Destroing c1 container...
At the same time the id mapping, the net and the cgroups settings have been cleared.
Creating a systemd guest on a Slackware host
Fortunately Slackware has no systemd, so we have to face some issues when hosting a systemd guest:
# lxu -n debian -F Failed to find module 'autofs4' Failed to find module 'unix' Failed to mount cgroup at /sys/fs/cgroup/systemd: Operation not permitted [!!!!!!] Failed to mount API filesystems. Exiting PID 1...
On Slackware /sys/fs/cgroup/systemd is a symbolic link to /sys/fs/cgroup/elogind so it cannot work with systemd containers.
The trick is to setup some mounts to satisfy containers that use systemd (more info here):
[ -h /sys/fs/cgroup/systemd ] && rm -f /sys/fs/cgroup/systemd && rm -f /run/systemd mkdir -p /sys/fs/cgroup/systemd mkdir -p /run/systemd mount -t cgroup -o none,name=systemd systemd /sys/fs/cgroup/systemd 2>/dev/null mkdir -p /sys/fs/cgroup/unified mount -t cgroup2 -o rw,nosuid,nodev,noexec,relatime,nsdelegate cgroup2 /sys/fs/cgroup/unified 2>/dev/null
This can cause side effects both of host and guest, so use it at your own risk and only if you absolutely have to test a systemd container. As far as I can say, my server is stable even with those mounts. But the situation is not easily reversible, in the sense that, if I unmount those cgroup mounts, the Slackware containers won't start anymore if stopped, and a reboot is needed.
The above commands can be easily run by calling a function of the script lxcctl in this way:
lxcctl mount

