December 22, 2022 Roberto Puzzanghera 0 comments
Handling LXC unprivileged containers can be quite annoying. In fact, you have to run each command as the user who owns the container and sometime define the configuration file and other parameters by means of a long command to type and remember. If you have many unprivileged containers and have to perform tasks as start/stop/attach frequently, your patience will come to an end very quickly. This is the reason why at a certain point I started to write my own wrapper scripts for the most common
LXC commands. Nothing special but it seems that nobody have published any tools to simplify the
LXC common tasks with unprivileged containers, so here is my contribute.
Let's start with some examples.
root shows all the unprivileged containers as stopped even when they are running:
root@host:~# lxc-ls --fancy NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c1 STOPPED 1 - - - true c2 STOPPED 1 - - - true c3 STOPPED 0 - - - true c4 STOPPED 1 - - - true
An output like this would be more convenient:
root@host:~# lxl # which is my lxc-ls wrapper that I'll show later on Unprivileged running containers of user user1 NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c1 RUNNING 1 - 10.0.0.1 - false Unprivileged running containers of user user2 NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c2 RUNNING 1 - 10.0.0.2 - false Unprivileged running containers of user user3 NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED c3 RUNNING 1 - 10.0.0.3 - false c4 RUNNING 0 - 10.0.0.4 - false c5 RUNNING 1 - 10.0.0.5 - false
Let's consider a few more
LXC commands. As you may have noticed,
lxc-start aborts the containers' startup sequence due to id mapping issues if you try to start an unprivileged container as
root@host:~# lxc-start -n c1 lxc-start: c1: lxccontainer.c: wait_on_daemonized_start: 867 Received container state "ABORTING" instead of "RUNNING" lxc-start: c1: tools/lxc_start.c: main: 306 The container failed to start lxc-start: c1: tools/lxc_start.c: main: 309 To get more details, run the container in foreground mode lxc-start: c1: tools/lxc_start.c: main: 311 Additional information can be obtained by setting the --logfile and --logpriority options
Also, you may have to type long commands like this to attach to a container in the proper way
sudo -u user1 lxc-attach \ -n c1 \ --keep-env \ --set-var HOSTNAME=c1.domain \ --set-var USER=root \ --set-var HOME=/ \ -- /bin/bash --rcfile /etc/profile
What if you can do it with a simple command apparently with no need to become the owner of that container? For example
root@host:~# lxu c1 # container c1 UP (container is started, its owner determined dinamically) root@host:~# lxa c1 # attaching container c1 (your env variables and /etc/profile will be passed) root@c1:/root# # inside the container c1 root@c1:/root# exit # exiting from the container c1 root@host:~# # back to the host prompt again root@host:~# lxd c1 # container c1 DOWN
Let's see an example where the creation of a container is made simple. This is how I create a
Slackware 15.0 container owned by the user
roberto (unprivileged), and with an ip address 10.0.0.22. I want to use my personal list of packages (
SLACKPKG_TEMPLATE) and also a personal
LXC template (
LXC_TEMPLATE) to perform this task:
SLACKPKG_TEMPLATE=my_15.0_template \ LXC_TEMPLATE=my_lxc_template \ RELEASE=15.0 \ my_lxc-create -n <container_name> -i 10.0.0.22 -u roberto
my_lxc-create -n <container_name> -i 10.0.0.22 -u roberto
if you set your defaults parameters inside the script. Of course, if you're not a
Slackware user, you can load the
LXC template for your distro and use this same script.
Creating a container owned by
root is even simpler. It will be sufficient not to specify any user:
my_lxc-create -n <container_name> -i 10.0.0.22
...and so on for other common
LXC commands like
I'll show also below how to install all of your containers (unprivileged included!) in the same directory, say /lxc, rather than installing each one in the owner's home directory.
My wrapper scripts will work both for privileged containers (owned by root itself) and unprivileged containers. I wrote them for my
Slackware linux distro, but I think that they can be useful for any other Linux flavors, as they can be easily adapted.
If you are a Slackware user and you are looking for unprivileged containers documentation, you should start by reading the Christoph Willing's guide. I'm very grateful to him, because without his pages I would almost certainly still be trapped in
Linux-VServer, which is not maintained anymore. The Cristoph Willing's guide explains in detail how to use
libcgroup to run unprivileged containers and it's the starting point on this topic. In the following I will assume that you are already familiar with the creation and configuration of unprivileged containers as explained there. In fact, my installation is mostly an automation of the tasks explained in that guide.
Also the Stéphane Graber's articles are a suitable reading at the beginning.
A special credit is addressed to Matteo Bernardini (Ponce) for his great support to the
Slackware community, not only concerning
apache clamav dkim dovecot ezmlm fail2ban hacks lamp letsencrypt linux linux-vserver lxc mariadb mediawiki mozilla mysql openboard owncloud patches php proftpd qmail qmail to postfix qmail-spp qmailadmin rbl roundcube rsync sieve simscan slackware solr spamassassin spf ssh ssl surbl tcprules tex ucspi-tcp vpopmail vqadmin