How to install LXD container under KVM or Xen virtual machine

Posted on in Categories , , , last updated January 23, 2017

For security and ease of admin, I want to install LXD on my cloud server either powered by XEN or KVM. How do I install LXD on Ubuntu Linux server powered by KVM virtualization technology?

You can implement the Linux container (LXD/LXC) to partition a your cloud server. Both cloud server, its files, and resources are only given the access to the right services such as Apache, Nginx, MySQL, Proxy, Memcached and so on. Canonical’s LXD is a pure-container hypervisor that runs unmodified Linux operating systems and applications with VM-style operations at incredible speed and density. In this quick tutorial you will learn how to install the latest stable version of LXD container under KVM cloud server hosted at Linode for security mechanism on Ubuntu Linux 16.04.xx LTS server.

Lxd on Ubuntu VM powered by XEN or KVM

Step 1 – Configure PPA

To install the latest upstream release, use a PPA as follows. Type the apt command or apt-get command as follows to install software-properties-common:
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ubuntu-lxc/lxd-stable

Sample outputs:

 This PPA contains the latest stable release of LXD as well as the latest stable version of any of its dependencies.
 More info: https://launchpad.net/~ubuntu-lxc/+archive/ubuntu/lxd-stable
Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmpgjzialhs/secring.gpg' created
gpg: keyring `/tmp/tmpgjzialhs/pubring.gpg' created
gpg: requesting key 7635B973 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmpgjzialhs/trustdb.gpg: trustdb created
gpg: key 7635B973: public key "Launchpad PPA for Ubuntu LXC team" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK

Update your system:
$ sudo apt-get update
$ sudo apt-get dist-upgrade

Sample outputs:

Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
The following packages will be upgraded:
  libseccomp2
1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Need to get 36.9 kB of archives.
After this operation, 28.7 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu xenial/main amd64 libseccomp2 amd64 2.3.1-2ubuntu2~ubuntu16.04.1~ppa1 [36.9 kB]
Fetched 36.9 kB in 0s (79.1 kB/s)      
(Reading database ... 29837 files and directories currently installed.)
Preparing to unpack .../libseccomp2_2.3.1-2ubuntu2~ubuntu16.04.1~ppa1_amd64.deb ...
Unpacking libseccomp2:amd64 (2.3.1-2ubuntu2~ubuntu16.04.1~ppa1) over (2.2.3-3ubuntu3) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Setting up libseccomp2:amd64 (2.3.1-2ubuntu2~ubuntu16.04.1~ppa1) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...

Step 2 – Install lxd

Type the following apt command or apt-get command:
$ sudo apt-get install lxd
OR
$ sudo apt install lxd
Sample outputs:

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  acl dns-root-data dnsmasq-base ebtables liblxc1 liblzo2-2 libnetfilter-conntrack3 lxc-common lxcfs lxd-client squashfs-tools uidmap
Suggested packages:
  criu lxd-tools
The following NEW packages will be installed:
  acl dns-root-data dnsmasq-base ebtables liblxc1 liblzo2-2 libnetfilter-conntrack3 lxc-common lxcfs lxd lxd-client squashfs-tools uidmap
0 upgraded, 13 newly installed, 0 to remove and 0 not upgraded.
Need to get 5,708 kB of archives.
After this operation, 24.2 MB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://mirrors.linode.com/ubuntu xenial/main amd64 liblzo2-2 amd64 2.08-1.2 [48.7 kB]
Get:2 http://mirrors.linode.com/ubuntu xenial/main amd64 acl amd64 2.2.52-3 [38.0 kB]
Get:3 http://mirrors.linode.com/ubuntu xenial/main amd64 dns-root-data all 2015052300+h+1 [15.0 kB]
Get:4 http://mirrors.linode.com/ubuntu xenial/main amd64 libnetfilter-conntrack3 amd64 1.0.5-1 [36.6 kB]
Get:5 http://mirrors.linode.com/ubuntu xenial-updates/main amd64 dnsmasq-base amd64 2.75-1ubuntu0.16.04.1 [294 kB]
Get:6 http://mirrors.linode.com/ubuntu xenial/main amd64 ebtables amd64 2.0.10.4-3.4ubuntu1 [79.6 kB]
Get:7 http://mirrors.linode.com/ubuntu xenial/main amd64 squashfs-tools amd64 1:4.3-3ubuntu2 [105 kB]
Get:8 http://mirrors.linode.com/ubuntu xenial/main amd64 uidmap amd64 1:4.2-3.1ubuntu5 [65.9 kB]
Get:9 http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu xenial/main amd64 lxc-common amd64 2.0.6-0ubuntu5~ubuntu16.04.1~ppa1 [77.2 kB]
Get:10 http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu xenial/main amd64 liblxc1 amd64 2.0.6-0ubuntu5~ubuntu16.04.1~ppa1 [252 kB]
Get:11 http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu xenial/main amd64 lxcfs amd64 2.0.5-0ubuntu2~ubuntu16.04.1~ppa1 [42.8 kB]
Get:12 http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu xenial/main amd64 lxd-client amd64 2.7-0ubuntu2~ubuntu16.04.1~ppa1 [1,923 kB]
Get:13 http://ppa.launchpad.net/ubuntu-lxc/lxd-stable/ubuntu xenial/main amd64 lxd amd64 2.7-0ubuntu2~ubuntu16.04.1~ppa1 [2,730 kB]
Fetched 5,708 kB in 3s (1,448 kB/s)
Selecting previously unselected package liblzo2-2:amd64.
(Reading database ... 29837 files and directories currently installed.)
Preparing to unpack .../liblzo2-2_2.08-1.2_amd64.deb ...
Unpacking liblzo2-2:amd64 (2.08-1.2) ...
Selecting previously unselected package acl.
Preparing to unpack .../acl_2.2.52-3_amd64.deb ...
Unpacking acl (2.2.52-3) ...
Selecting previously unselected package dns-root-data.
Preparing to unpack .../dns-root-data_2015052300+h+1_all.deb ...
Unpacking dns-root-data (2015052300+h+1) ...
Selecting previously unselected package libnetfilter-conntrack3:amd64.
Preparing to unpack .../libnetfilter-conntrack3_1.0.5-1_amd64.deb ...
Unpacking libnetfilter-conntrack3:amd64 (1.0.5-1) ...
Selecting previously unselected package dnsmasq-base.
Preparing to unpack .../dnsmasq-base_2.75-1ubuntu0.16.04.1_amd64.deb ...
Unpacking dnsmasq-base (2.75-1ubuntu0.16.04.1) ...
Selecting previously unselected package ebtables.
Preparing to unpack .../ebtables_2.0.10.4-3.4ubuntu1_amd64.deb ...
Unpacking ebtables (2.0.10.4-3.4ubuntu1) ...
Selecting previously unselected package lxc-common.
Preparing to unpack .../lxc-common_2.0.6-0ubuntu5~ubuntu16.04.1~ppa1_amd64.deb ...
Unpacking lxc-common (2.0.6-0ubuntu5~ubuntu16.04.1~ppa1) ...
Selecting previously unselected package liblxc1.
Preparing to unpack .../liblxc1_2.0.6-0ubuntu5~ubuntu16.04.1~ppa1_amd64.deb ...
Unpacking liblxc1 (2.0.6-0ubuntu5~ubuntu16.04.1~ppa1) ...
Selecting previously unselected package lxcfs.
Preparing to unpack .../lxcfs_2.0.5-0ubuntu2~ubuntu16.04.1~ppa1_amd64.deb ...
Unpacking lxcfs (2.0.5-0ubuntu2~ubuntu16.04.1~ppa1) ...
Selecting previously unselected package lxd-client.
Preparing to unpack .../lxd-client_2.7-0ubuntu2~ubuntu16.04.1~ppa1_amd64.deb ...
Unpacking lxd-client (2.7-0ubuntu2~ubuntu16.04.1~ppa1) ...
Selecting previously unselected package squashfs-tools.
Preparing to unpack .../squashfs-tools_1%3a4.3-3ubuntu2_amd64.deb ...
Unpacking squashfs-tools (1:4.3-3ubuntu2) ...
Selecting previously unselected package uidmap.
Preparing to unpack .../uidmap_1%3a4.2-3.1ubuntu5_amd64.deb ...
Unpacking uidmap (1:4.2-3.1ubuntu5) ...
Selecting previously unselected package lxd.
Preparing to unpack .../lxd_2.7-0ubuntu2~ubuntu16.04.1~ppa1_amd64.deb ...
Adding system user `lxd' (UID 111) ...
Adding new user `lxd' (UID 111) with group `nogroup' ...
Creating home directory `/var/lib/lxd/' ...
Adding group `lxd' (GID 118) ...
Done.
Unpacking lxd (2.7-0ubuntu2~ubuntu16.04.1~ppa1) ...
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Processing triggers for dbus (1.10.6-1ubuntu3.3) ...
Processing triggers for systemd (229-4ubuntu16) ...
Processing triggers for ureadahead (0.100.0-19) ...
Setting up liblzo2-2:amd64 (2.08-1.2) ...
Setting up acl (2.2.52-3) ...
Setting up dns-root-data (2015052300+h+1) ...
Setting up libnetfilter-conntrack3:amd64 (1.0.5-1) ...
Setting up dnsmasq-base (2.75-1ubuntu0.16.04.1) ...
Setting up ebtables (2.0.10.4-3.4ubuntu1) ...
update-rc.d: warning: start and stop actions are no longer supported; falling back to defaults
Setting up lxcfs (2.0.5-0ubuntu2~ubuntu16.04.1~ppa1) ...
Setting up lxd-client (2.7-0ubuntu2~ubuntu16.04.1~ppa1) ...
Setting up squashfs-tools (1:4.3-3ubuntu2) ...
Setting up uidmap (1:4.2-3.1ubuntu5) ...
Setting up liblxc1 (2.0.6-0ubuntu5~ubuntu16.04.1~ppa1) ...
Setting up lxd (2.7-0ubuntu2~ubuntu16.04.1~ppa1) ...
Setting up lxd dnsmasq configuration.
 
To go through the initial LXD configuration, run: lxd init
 
Setting up lxc-common (2.0.6-0ubuntu5~ubuntu16.04.1~ppa1) ...
Processing triggers for libc-bin (2.23-0ubuntu5) ...
Processing triggers for dbus (1.10.6-1ubuntu3.3) ...
Processing triggers for systemd (229-4ubuntu16) ...
Processing triggers for ureadahead (0.100.0-19) ...

Step 3 – Add user account for lxd

Type the following command to add a user named vivek, run:
$ sudo adduser vivek
Make sure vivek is part of a secondary group named lxd group, enter:
$ sudo usermod -a -G lxd vivek
Verify it, run the id command as follows:
$ id vivek
Sample outputs:

uid=1002(vivek) gid=1002(vivek) groups=1002(vivek),118(lxd)

Step 4 – Configure lxd

To go through the initial LXD configuration, run:
$ sudo lxd init
Sample outputs:

Step 5 -Creating and using your first container

First login as vivek user:
$ ssh [email protected]
OR
$ su - vivek
Verify that the lxc client is talking to the LXD daemon:
$ lxc list
Sample outputs:

+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

The syntax is as follows to create your first container:

lxc launch images:{distro}/{version}/{arch} {container-name-here}

To list all available images for various Linux distro, run:
$ lxc image list images:
To create a CentOS Linux v7.x container:
$ lxc launch images:centos/7/amd64 my-cenots
Sample outputs:

Creating my-cenots
Retrieving image: 100% (16.80MB/s)
Starting my-cenots

To create a Ubuntu Linux 16.4 LTS container:
$ lxc launch images:ubuntu/xenial/amd64 my-ubuntu
Sample outputs:

Animated gif.01: Lxc creating your VM
Animated gif.01: Lxc creating your VM

Step 6 – Login to your first container

Type the following command:
$ lxc exec my-centos bash
$ lxc exec my-ubuntu bash

You can now update your container or install needed software.

Step 6 – Lock down root user

You do not need root user or default user such as ubuntu/centos created in your container:
$ lxc exec my-ubuntu bash
Lock down root account access, run:
# passwd -l root
Delete unwanted user account using the userdel command, run:
# userdel -r ubuntu

Step 7 – Basic Linux containers management commands

Let us see important commands to manage your containers.

Start a container

$ lxc start containerName

Stop a container

$ lxc stop containerName

Restart a container

$ lxc restart containerName

Delete a container

$ lxc delete containerName

Get info about running container

$ lxc info containerName

Run the specified command in a container

$ lxc exec containerName command1
$ lxc exec containerName command1 opt1
$ lxc exec containerName date
$ lxc exec containerName -- command1 -arg1 -arg2
$ lxc exec my-cenots -- yum update -y

Create a read-only snapshot of a container

$ lxc snapshot containerName snapShotName
$ lxc snapshot my-cenots snap0
$ lxc info my-cenots

Restore a container’s state to a previous snapshot

$ lxc restore containerName snapShotName
$ lxc restore my-cenots snap0
$ lxc info my-cenots
$ lxc exec my-cenots bash

I recommend that you let built-in DHCP assign a static IP to LXD container/VM based on name or MAC address for ease of management including talking with each other. I suggest that you setup LAMP stack as follows:
$ lxc launch images:ubuntu/xenial/amd64 db1
$ lxc launch images:ubuntu/xenial/amd64 nginx1
$ lxc launch images:ubuntu/xenial/amd64 apache-php1
$ lxc launch images:ubuntu/xenial/amd64 memcached

Once LXC VM up and running. Log into each container and setup services i.e. install Apache and PHP on apache-php1 VM. Use Nginx (or any other proxy server) or iptables on your cloud server to redirect traffic to port 80/443 from your public IP address to container service.

And there you have it. LXD container/VM is running for each service such as a web server, MySQL, Memcached, Proxy and so on. All of your services are running on separate LXD vm instance. Naturally, this limits the number of other services that can be cracked if an attacker can successfully exploit a software flaw in one network service.

See also

Posted by: Vivek Gite

The author is the creator of nixCraft and a seasoned sysadmin and a trainer for the Linux operating system/Unix shell scripting. He has worked with global clients and in various industries, including IT, education, defense and space research, and the nonprofit sector. Follow him on Twitter, Facebook, Google+.