Fedora 26: Install LXD for container

This article will describe installing LXD and running containers.

Table of Contents

1 Install LXD

The following script will install LXD.

#!/bin/sh

set -e

USER_ADDED_TO_LXD_GROUP="${USER}"

# FIXME: Running LXD need this.
[ -f /etc/subuid ] && sudo mv /etc/subuid /etc/subuid.orig
[ -f /etc/subgid ] && sudo mv /etc/subgid /etc/subgid.orig
echo "root:100000:65536" | sudo tee /etc/subuid
echo "root:100000:65536" | sudo tee /etc/subgid

# LXD/LXC uses lxc-xxx pakcage.
sudo dnf install -y lxc-devel

# Install LXD/LXC.
sudo groupadd -r lxd
sudo mkdir -p /var/lib/lxd
sudo chown root:lxd /var/lib/lxd
sudo mkdir -p /var/log/lxd
sudo chown root:lxd /var/log/lxd
sudo dnf install -y git golang sqlite-devel dnsmasq squashfs-tools libacl-devel
export GOPATH=${HOME}/go
export PATH=${GOPATH}/bin/:${PATH}
go get -v -x -tags libsqlite3 \
   github.com/lxc/lxd/lxc \
   github.com/lxc/lxd/lxd
sudo cp "${GOPATH}"/bin/* /usr/bin/

# Create systemd service and socket.
cat <<EOF | sudo tee /usr/lib/systemd/system/lxd.service
[Unit]
Description=LXD - main daemon
After=network.target
Requires=network.target lxd.socket
Documentation=man:lxd(1)

[Service]
EnvironmentFile=-/etc/environment
ExecStart=/usr/bin/lxd --group lxd --logfile=/var/log/lxd/lxd.log
ExecStartPost=/usr/bin/lxd waitready --timeout=600
KillMode=process
TimeoutStartSec=600
TimeoutStopSec=40
Restart=on-failure
LimitNOFILE=infinity
LimitNPROC=infinity

[Install]
Also=lxd.socket
EOF

cat <<EOF | sudo tee /usr/lib/systemd/system/lxd.socket
[Unit]
Description=LXD - unix socket
Documentation=man:lxd(1)

[Socket]
ListenStream=/var/lib/lxd/unix.socket
SocketGroup=lxd
SocketMode=0660
Service=lxd.service

[Install]
WantedBy=sockets.target
EOF

# FIXME: LXD needs SELinux configuration like container-selinux of docker.
cat <<EOF > my-systemd.te
module my-systemd 1.0;
require {
  type init_t;
  type unconfined_service_t;
  type var_lib_t;
  class unix_stream_socket { create setopt bind listen };
  class sock_file { create setattr unlink };
}
#============= init_t ==============
allow init_t unconfined_service_t:unix_stream_socket { create setopt bind listen };
allow init_t var_lib_t:sock_file { create setattr unlink };
EOF
checkmodule -M -m -o my-systemd.mod my-systemd.te
semodule_package -m my-systemd.mod -o my-systemd.pp
sudo semodule -i my-systemd.pp
rm -f my-systemd.te my-systemd.mod my-systemd.pp

# Run LXD for initialization.
sudo systemctl --system daemon-reload
sudo systemctl enable lxd
sudo systemctl start lxd

# Initialize LXD.
cat <<EOF | sudo lxd init
yes
default
dir
no
yes
yes
lxdbr0
auto
auto
EOF

# Running container needs user_namespace.enable=1.
sudo dnf install -y grub2-tools
. /etc/default/grub
V="$GRUB_CMDLINE_LINUX user_namespace.enable=1"
sudo sed -e "s;^GRUB_CMDLINE_LINUX=.*;GRUB_CMDLINE_LINUX=\"$V\";g" \
     -i /etc/default/grub
sudo grub2-mkconfig -o /boot/grub2/grub.cfg

# Add user to lxd for running lxc command without privilege.
sudo gpasswd -a "${USER_ADDED_TO_LXD_GROUP}" lxd

# Reboot.
sudo reboot

2 Run container

This can download debian/stretch image and run it. IP address is assigned to container.

$ lxc launch images:debian/stretch debian
<snip>
$ lxc exec debian ip a s
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
4: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue
state UP group default qlen 1000
    link/ether 00:16:3e:29:1e:7d brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::216:3eff:fe29:1e7d/64 scope link tentative
       valid_lft forever preferred_lft forever