LXC using unprivileged containers
Unprivileged containers provide an additional layer of isolation and security. The root user in the container is NOT the root user on the system. Apart from security benefits this also begins to pave the way for multi-tenant workloads.
Unfortunately like a lot of new LXC features they work properly only on the latest versions of Ubuntu due to dependencies. Unprivileged containers have a number of requirements, which are currently available only in Ubuntu 14.04, so users of other distributions are out of luck for now. Here is what you need.
- Kernel 3.13 +
- LXC 1.0 but 1.0.5 + preferred
- Per user cgroups support so cgmanager package required
- systemd-libs
- pam with loginuid patch
- uidmap
Ubuntu 14.04 supports all the above out of the box. This won't work on most distributions without the above. Some advanced users may have got it to work in other distributions after going through a lot of hoops, but its not trivial to get it working.
We are presuming you already have a working LXC installation in Ubuntu, if you don't please refer to the LXC installation guide. Once your LXC installation is working properly and you can create and use containers, you can move to the next step.
Install systemd-services and uidmap
sudo apt-get install systemd-services uidmap
Next you need to create LXC configuration files for your user. This is how the system LXC config files match to the user config files.
/etc/lxc/lxc.conf => ~/.config/lxc/lxc.conf /etc/lxc/default.conf => ~/.config/lxc/default.conf /var/lib/lxc => ~/.local/share/lxc /var/lib/lxcsnaps => ~/.local/share/lxcsnaps /var/cache/lxc => ~/.cache/lxc
At a minimum create the .config/lxc/default.conf, .local/share/lxc to store containers and .cache/lxc for the downloaded container templates cache in your user's home directory.
mkdir .config/lxc .local/share/lxc .cache/lxc
Now in .config/lxc create a default.conf file with the config below.
nano default.conf
lxc.network.type = veth lxc.network.link = lxcbr0 lxc.network.flags = up lxc.network.hwaddr = 00:16:3e:xx:xx:xx lxc.id_map = u 0 100000 65536 lxc.id_map = g 0 100000 65536
Notice the lxc.id_map entries. Now you need to allocate allocate additional uids & gids to your username.
sudo usermod --add-subuids 100000-165536 username sudo usermod --add-subgids 100000-165536 username
You also need to create a lxc-usernet file for unprivileged containers in /etc/lxc/lxc-usernet
sudo nano /etc/lxc/lxc-usernet
Add this bit into the lxc-usernet file. Change the username to your username.
username veth lxcbr0 10
This allows the user specified to create 10 veth interfaces
To create unprivileged containers you need to use the 'download' template type. These container OS templates are designed to support unprivileged containers. Its important to clarify at this point containers created without the download template type will not work in unprivileged mode as those container OS templates are not designed to. So let's create our first unprivileged container.
lxc-create -t download -n p1 -- -d ubuntu -r trusty -a amd64
This should create the p1 container in your user's .local/share/lxc folder. Now start the container.
lxc-start -n p1 -d
This should start the container. You can use lxc-console to enter the container. The newer lxc container OS templates do not have openssh installed by default and you need to setup openssh-server to log in to the container over ssh.
There have been some reports using lxc-ls -f to get container information or using lxc-attach to enter the container around user namespaces doesn't work. 1.0.5 + versions of the lxc packages should fix this and both these tools should work.
So now you have a container that can be deployed by users, providing all the security advantages of not running as root. Hopefully this functionality will become more easily available to users of other distributions.
Ubuntu's extension of LXC with the recent announcement of the LXD project to provide container management across LXC hosts uses unprivileged containers by default. There is a lot of focus and impetus by Ubuntu on container deployment infrastructure and making this more widely available so exciting days ahead.
Run unprivileged containers as root
Normally containers launched by root run as privileged, with this you can run unprivileged containers as root. You only need a subset of the steps above.
First allocate additional uids & gids to root
sudo usermod --add-subuids 100000-165536 root sudo usermod --add-subgids 100000-165536 root
Then edit /etc/lxc/default and append lxc.uidmap entry like below
lxc.id_map = u 0 100000 65536 lxc.id_map = g 0 100000 65536
That's it! Now any container you create as root will be an unprivileged container.
Tip: If you want to use it as a one off simply add the 2 lxc.id.map lines to the container config in /var/lib/lxc, and not /etc/lxc/default.
You may get a permission error when starting the container. In this case change the permissions on the /var/lib/lxc folder.
chmod o+x /var/lib/lxc
Remember you need to use the 'download' template when creating unprivileged containers.