Wrapper scripts for LXC unprivileged containers: overview

December 18, 2022 Roberto Puzzanghera 0 comments


This is an overview of my LXC scripts. As already said they are mostly wrappers of the LXC commands, that I wrote to execute common tasks both with privileged and unprivileged containers. All these scripts are able to guess if a container is unprivileged or not, to eventually determine its owner, and run the command accordingly with the correct syntax.


It defines common variables and functions to be imported in the following scripts.

lxu (lxc-start wrapper)

It starts a container. The usage is simple. You put UP a container in this way:

lxu <name>

If you want to pass the -F parameter to run the container in the foregroud and see the logs (you may want to do so when you have cgroups errors), use like this:

lxu -n <name> -F

lxd (lxc-stop wrapper)

It stops (puts DOWN) a running container. Usage:

lxd <name>


It's just a combination of lxd and lxu, as it simply restarts a container. Usage:

lxr <name>

lxa (lxc-attach wrapper)

It runs a command in the container. If the container is stopped it will be started, then <command> will be executed. Usage:

lxa <name> [<command>]

If <command> is not provided the /bin/bash --rcfile /etc/profile shell will be executed.

It's worth to specify what it does behind the scene. The actual default command that will be run for an unprivileged container is:

sudo -u <user> lxc-attach -n <name> \
 --keep-env \
 --set-var HOSTNAME=<name>.<domain> \
 --set-var USER=root \
 --set-var HOME=/ \
 -- /bin/bash --rcfile /etc/profile


--keep-env will keep all the host's environment variables (aventually modify it for security reasons).

After that it passes some variables that we don't want to keep with respect to the host (adjust to your needs):

--set-var HOSTNAME=<name>.<domain> which sets the HOSTNAME

--set-var USER=root the shell will know that the current user is root

--set-var HOME=/ when you type cd, the shell will know where is your home dir, / in this case, and you'll get no errors

-- /bin/bash --rcfile /etc/profile all the aliases and variables defined in /etc/profile will be loaded. Without this line, you would have a very bad prompt, and the ls command will be shown with no colours at all, for instance.

lxo (lxc-console wrapper)

It provides a console login for the specified container. Usage:

lxo <name>

lxi (lxc-info wrapper)

It queries information about a container. Usage:

lxi <name>

lxe (lxc-execute wrapper)

It runs an application inside a container. Usage:

lxe -n <name> -- command


This is a symbolic link of the /etc/rc.d/rc.lxc startup script, which is runned at boot time to launch the containers with the flag lxc.start.auto=1. It is a modification of the original script shipped with Slackware by Matteo Bernardini, but now it can start both unprivileged and privileged containers.


lxcctl start|stop|restart


This is my lxc-create wrapper script that I use to create my Slackware containers. Its usage was covered in the previous page.


Wrapper script for lxc-destroy. Usage:

my_lxc-destroy <name>


It is a modification of the original script by Serge Hallyn, that changes the lxcpath of the container, already defined in my_lxc-common.

It converts a container to use user namespaces. In particular:

  • it adds the lxc.uidmap lines to the config file
  • it shifts the uids in the rootfs by calling uidmapshift


my_lxc-container-userns-convert <name> base-uid range

For example, to make the container c1's root be uid 100000 on the host, and a have a range of 10000 ids, you would use:

my_lxc-container-userns-convert c1 100000 10000

More info at http://bazaar.launchpad.net/~serge-hallyn/+junk/nsexec/files.


It converts a privilege to an unprivileged container. In particular:

  1. It calls my_lxc-container-userns-convert to convert a container to use user namespaces;
  2. It creates the system user that will own the container if it doesn't exist yet;
  3. It configures cgroups and lxc-usernet.

This program is called by my_lxc-create in case the container to be created has to be unprivileged. You can also use it  in standalone mode if you already have a privileged container and you want to convert it to unprivileged.


Wrapper script for lxc-copy. Usage:

my_lxc-copy -n <name> -N <newname> [-R] [-i <ip> | -d] [-u <user>] [-h]

my_lxc-copy takes the following options:

 -n  <name>    Name of the source container 
 -N  <newname> Name of the new container
 -R            Rename the original container. If -R is provided the following options will be ignored.
 -d            Use DHCP 
 -i  <ip>      IP address of the container. Ignored if -d was declared 
 -u  <user>    Set the system user that will own the container. 
               <user> will be created if not existing yet. 
               If not declared the container will be owned by the user who owns the source container 
               and eventually remains privileged just like the source container. 
 -h            Print this help

You can rename a container like this:

my_lxc-copy -n <name> -N <newname> -R

my_lxc-freeze / my_lxc-unfreeze

lxc-freeze and lxc-unfreeze wrapper scripts. Usage:

my_lxc-freeze   -n <name>
my_lxc-unfreeze -n <name>


This is my LXC template for Slackware containers. It is derived from the one shipped with Slackware itself. Look at the previous page for more info.

Add a comment