Unprivileged containers in Slackware©

Part 1 - Setting up

One of the great features introduced in lxc-1.x releases is the ability to run LXC containers as an unprivileged user, rather than having to run them as root. In Part 1 of this Unprivileged containers in Slackware article, we'll discuss how to arrange the system requirements to run unprivileged containers in Slackware. In Part 2 we'll go through the steps to construct and run an unprivileged container in Slackware, while Part 3 will describe a convenient way to provide networking for the container.

Much of the information here on this page is based on Stephane Graber's Introduction to unprivileged containers, one of a series of his excellent blog posts about LXC. Although we'll be concentrating here on how to make unprivileged containers work specifically in a Slackware environment, reading Stephane's introduction is highly recommended.

The version of Slackware referenced here is the -current version which will become 14.2 (or maybe 15.0?). The reason for this is that one of the prerequisites is a version of the shadow package which includes support for subuids and subgids and this version is part of the -current Slackware version.

First, lets go through Stephane's prerequisites and how they relate to Slackware -current at the moment:

Most of the prerequisites are satisfied with relatively minor work to do and, hopefully, a lot of it may be rolled into future updates to -current and subsequent Slackware releases. Lets make a new list of what needs to be done:

  1. Enable cgmanager
  2. Enable user environment (what the modified PAM mentioned above is used for in other distros)
These items are somewhat intertwined; enabling the user environment involves using cgmanager to set up per user cgroups on all controllers.

Step 1. Enable cgmanager

A cgmanager package is part of Slackware -current. The cgmanager daemon is started at boot time by the
/etc/rc.d/rc.cgmanager script which must be executable - in a terminal, run:
    sudo chmod a+x /etc/rc.d/rc.cgmanager
The cgmanager daemon will be started at the next reboot (if not, see Potential Problems below).

Step 2. Enable user environment

This is tricky - please let me know if there is a better way to do this. The problem is that setting up per user cgroups involves the user running some cgm commands (cgm is the command interface to the cgmanager daemon which actually does the work). However the user needs root privilege to run some cgm commands; at the same time these commands cannot be run by root on the user's behalf e.g. at boot time for all users. Furthermore, we'd like this all to be done without any user intervention whenever the user logs in. We use sudo to achieve this for users in a special lxcusers group.

To enable all this, we create a script /etc/profile.d/lxcuser.sh that is run when a user logs in (or otherwise runs a login shell). This script first checks whether the user is in a special lxcusers group and, if so, sources another script we shall create at
/etc/lxc/lxc-enable-users which contains the required cgm commands. Since these commands will be run via sudo without password, we need to configure sudo so that the necessary commands are able to be run, but only by members of the lxcusers group. This configuration can be set up using visudo, which edits the /etc/sudoers file, or by placing the configuration into a file in the /etc/sudoers.d directory (man sudoers for details).

Create the configuration file /etc/sudoers.d/010_lxcusers now (as root) with the following content:
    Cmnd_Alias CGM = /usr/bin/cgm
    %lxcusers       ALL = NOPASSWD: CGM
and set its permissions:
    sudo chmod 0440 /etc/sudoers.d/010_lxcusers

This will allow members of the lxcusers group to run sudo cgm .. without entering a password. The lxcusers group is created with the command:
    sudo /usr/sbin/groupadd -g 345 lxcusers
(I've chosen 345 as the group id number but any unused number will be fine). Users can be added to this group with:
    sudo /usr/sbin/usermod -a -G lxcusers chris
(for user chris)

Create the /etc/lxc/lxc-enable-users script with the content:
    sudo cgm create all $USER >/dev/null
    sudo cgm chown all $USER $(id -u $USER) $(id -g $USER)  >/dev/null
    sudo cgm movepid all $USER $$ >/dev/null

Create the /etc/profile.d/lxcuser.sh with the content:
    group_member=$(groups | grep lxcusers)
    [ $? -eq 0 ] && . /etc/lxc/lxc-enable-users
Ensure it is executable with:
    sudo chmod a+x /etc/profile.d/lxcuser.sh

Now, assuming that the cgmanager daemon is running (after a manual start or reboot), the next time a user who is a member of the lxcusers group logs in, /etc/profile.d/lxcuser.sh will source  /etc/lxc/lxc-enable-users which is able to run the necessary cgm commands (via sudo).

Before the user is able to run an unprivileged LXC container, a subuid & subgid should be allocated to them in the /etc/subuid and /etc/subgid files. These files don't exist by default so they'll have to be created. An entry in each like:
    chris:100000:65536
(replacing chris with the designated user on your system) is a reasonable default. See man subuid, man subgid for more information.

Confirming the setup

One of the aims of this setup is to be as transparent as possible to the user i.e. it should happen automagically and without user intervention. How do we test that it has worked then? The only way to test everything (short of running some lxc commands), is to reboot, log in as the target user and run:
    . /etc/profile.d/lxcuser.sh
(note the '.'). If this completes with no errors and no requests for passwords etc., then the setup is looking good.

At this stage we're ready to create and run unprivileged containers, described in Part 2.

Potential problems

Unprivileged containers are a relatively recent capability. Some possible Slackware related issues include:


Contact

Please send any questions, comments, advice etc., to Chris Willing <chris.willing _at_