Let’s Get Started
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
- the user on the host without
- 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
lxcand 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 both
guidfiles. 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
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 using
vimas my text editor throughout this tutorial, but you can use
nanoif 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
vethand creating a new bridge
lxcbr0. We will come back to these later.
hwaddrmay differ; you can see the default values in
gidmapping. Starts from
231072and 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
host> sudo vim /etc/lxc/lxc-usernet
Add in the following line. This means that for the user
lxc, allow up to
veth network interfaces (only
veth is supported for now) to be attached to the bridge
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.
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.
-nfor container name. This container name will automatically be used as our hostname later, so key in your domain as is.
-tfor 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
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.
- 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.