Let’s Get Started
Notations
It is recommended that the LXC be instantiated by an unprivileged user, but yet certain commands can only be issued with sudo
. We will also need to interact with the container itself, which brings the total number of roles you have to play to three:
- the user on the host with
sudo
privilege - the user on the host without
sudo
privilege - the root in the container
They will be denoted respectively as follows:
host> code here
lxc> code here
root> code here
Setting up LXC
- Let us install the utilities needed to make LXC containers.
host> sudo apt update && sudo apt install lxc-utils
- Create an unprivileged user called
lxc
and switch to that user.
host> sudo adduser lxc
host> su - lxc
- Fix environmental variables. Otherwise you might have issues creating containers later.
lxc> unset XDG_RUNTIME_DIR XDG_SESSION_ID
- Find out the namespaces allowed for the user
lxc
. The wildcard in the command below will match bothsuid
andguid
files. We will map the LXC container to these regions.
lxc> cat /etc/s*id|grep $USER
lxc:231072:65536
lxc:231072:65536
From the output, we can see that both assigned suid
and guid
values start at 231072
and runs through the next 65536 integers.
- Let us set up configuration files as required by LXC before starting a container. The required file is in
~/.config/lxc/default.conf
. I am usingvim
as my text editor throughout this tutorial, but you can usenano
if you wish.
lxc> mkdir -p ~/.config/lxc/
lxc> vim ~/.config/lxc/default.conf
Add in the following lines. Notice that the syntax might be different from what you find online. I am using the latest version of LXC, v3.0.3.
- We are setting the network interface type to be
veth
and creating a new bridgelxcbr0
. We will come back to these later. - Your
hwaddr
may differ; you can see the default values in/etc/lxc/default.conf
. uid
andgid
mapping. Starts from231072
and runs for 65536 integers. Replace these with what you get from Step 4.
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
lxc.idmap = u 0 231072 65536
lxc.idmap = g 0 231072 65536
- Next, we place the limits on the network interface by changing the file in
/etc/lxc/lxc-usernet
.
host> sudo vim /etc/lxc/lxc-usernet
Add in the following line. This means that for the user lxc
, allow up to 10
veth
network interfaces (only veth
is supported for now) to be attached to the bridge lxcbr0
.
lxc veth lxcbr0 10
- Now, let us set a static IP for our container. This is necessary because our main Apache2 needs to know where to forward the requests.
host> sudo vim /etc/default/lxc-net
Key in the following. Here, we are assigning the hostname blog.warmwolf.com
to a private IP address of 10.0.3.101
. Change the hostname accordingly and choose an IP address that isn’t used. If this IP is taken, you will be assigned another IP silently.
dhcp-host=blog.warmwolf.com,10.0.3.101
Let’s make sure that the new configs are accepted by restarting the services.
host> sudo service lxc-net restart
host> sudo killall -s SIGHUP dnsmasq
- We are ready to create a container! Remember to head back to our unprivileged user.
-n
for container name. This container name will automatically be used as our hostname later, so key in your domain as is.-t
for template. We will be downloading fresh from the web.
lxc> lxc-create -n blog.warmwolf.com -t download
You will be given a list of the available distros. You will be asked to choose the distribution, release and architecture. I am going with the same setup as my host. Choose the wrong architecture and your container will not start later! Here is how you can find information on your current setup.
host> uname -m
host> dpkg --print-architecture
Distribution:
ubuntu
Release:
bionic
Architecture:
amd64
A waiting time of a few cups of coffee later, the container should be successfully created!
- Let’s do a quick sanity check before starting the container. You can do one of these. The second lists all containers you may have with more information, including the IP address. (This is empty now but we can check later.)
lxc> lxc-info -n blog.warmwolf.com
lxc> lxc-ls -f
Let’s start the container! We specify the name of the container with -n
and saves a debug log file for easy troubleshooting if something goes wrong.
lxc> lxc-start -n blog.warmwolf.com --logfile $HOME/lxc_blog.log --logpriority DEBUG
The container should be started! Feel free to lxc-info
it again and verify that it is indeed RUNNING
. Again, you might not see the IP address until there is some network activity.
- Finally, let’s attach to this container so we have a shell interface.
lxc> lxc-attach -n blog.warmwolf.com
You should be granted root
without having to enter any credentials. It is now a good time to be setting a password for your root
.
root> passwd
Since your distro was freshly downloaded, it should be up-to-date. However, you can force some network activity by getting curl. We need it later to download WordPress.
root> apt update && apt install curl
Your terminal is probably taken over by this container for now. You can launch another terminal and check again with lxc-ls -f
of Step 9 and make sure the IP address is correct. Otherwise, stop the container and try another IP address (revisit Step 7). Remember to restart the network services as explained in Step 7.
Congratulations! You have created an unprivileged LXC! On the next page, we will install Apache2 in the container, and set up our main Apache2 to act as a reverse proxy.
Organisation:
- On Page 1, we start with a bit of literature so we know what we will be doing later on.
- On Page 2, we create an unprivileged LXC container.
- On Page 3, we set up Apache2, MySQL and PHP in the container. We also set up our main Apache2 as a reverse proxy to serve pages from within the container.
- On Page 4, we set up WordPress inside the container.
- On Page 5, we end with some closing thoughts.