LXC container in AstLinux

Starting with AstLinux 1.3.10 it is possible to run LXC containers within AstLinux.

The containers are using the same kernel and hardware as AstLinux.

Quick Start Guide

Enable LXC Support:

  • Define LXC_BRIDGE0 in user.conf using a physical or VLAN interface (e.g. LXC_BRIDGE0=“eth3”)
  • Assign the newly created lxcbr0 to an internal interface in the Network tab
  • Reboot

Then from the CLI:

lxc-create -t download -n debian10 -- -d debian -r buster -a amd64 --no-validate
service lxc init
lxc-attach debian10
  passwd
  apt install openssh-server iputils-ping curl
  ...
  exit


Disable LXC Support:

First from the CLI:

service lxc stop
lxc-destroy debian10

If you don't want to re-enable LXC in the near future:

  • Remove LXC_BRIDGE0 in user.conf
  • Reassign where lxcbr0 was an internal interface in the Network tab to another interface
  • Reboot


Networking

There are different networking modes for LXC. We are using veth, that needs a bridge on the host (configured in user.conf) e.g.

LXC_BRIDGE0="eth3"

Tip → If you have multiple LAN interfaces defined in the Network tab, assign lxcbr0 to The DMZ Interface. In this configuration the firewall will allow any LAN Interface to access the container, but the container's network can only initiate access via the External Interface unless additional firewall rules are added.

Tip → If you run out of physical interfaces to assign to the bridge, create a VLAN, for example:

In the Network tab:

VLANS: eth3.10
The DMZ Interface: lxcbr0

In your user.conf config:

LXC_BRIDGE0="eth3.10"


Linux Container Config

Per the above “Quick Start Guide” example with the debian10 container, the default, auto-generated config looks like this:

# Template used to create this container: /usr/share/lxc/templates/lxc-download
# Parameters passed to the template: -d debian -r buster -a amd64 --no-validate
# Template script checksum (SHA-1): a37305b11025a13952335f1e0a9f26e5201a26d1
# For additional config options, please look at lxc.container.conf(5)

# Container Auto Start: 0 (no) or 1 (yes), defaults to 0
lxc.start.auto=1

# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
lxc.arch = linux64

# Container specific configuration
lxc.tty.max = 0
#lxc.cgroup.memory.limit_in_bytes = 1024M
#lxc.cgroup.cpuset.cpus = 1,3
lxc.rootfs.path = dir:/var/lib/lxc/debian10/rootfs
lxc.uts.name = debian10

# Network configuration
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.name = eth0
#lxc.net.0.ipv4.address = 192.168.101.10/24
#lxc.net.0.ipv4.gateway = auto
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:43:a5:1e

Note → The lxc.net.0.hwaddr is auto-generated with a random value.

The standard location for this config file is /var/lib/lxc/debian10/config which AstLinux symlinks to /mnt/kd/lxc/container/debian10/config

You may tweak this config file to your liking.

To determine if the container auto-starts:

# Container Auto Start: 0 (no) or 1 (yes), defaults to 0
lxc.start.auto=1

By default DHCP is enabled in the recommended base installs, but if you want to enable a static IP address, uncomment these lines:

lxc.net.0.ipv4.address = 192.168.101.10/24
lxc.net.0.ipv4.gateway = auto

and adjust the 192.168.101.10/24 network to be valid on your lxcbr0 network.

If you would like your veth interface names to be descriptive, add to the “Network configuration”

lxc.net.0.veth.pair = veth_debian10

Tip → Keep the name short, as the length is limited, also begin the name with veth.


After making a change in the config with lxc.start.auto=1, the container can be restarted with:

service lxc restart

Alternatively, if lxc.start.auto=0, you can manually start the container with:

lxc-start debian10

If you are using the Web Interface, both the Network tab and Edit tab support “Restart Linux Containers”.


Destroy All Containers

If you want to disable all LXC container support, or start fresh, from the CLI:

Warning → This action is not undoable, All LXC containers and download caches will be deleted!

service lxc stop
rm -rf /mnt/kd/lxc
service lxc init


lxc-create -t download -n debian10 -- -d debian -r buster -a amd64 --no-validate

lxc-create -t download -n debian9 -- -d debian -r stretch -a amd64 --no-validate

lxc-create -t download -n ubuntu18 -- -d ubuntu -r bionic -a amd64 --no-validate

lxc-create -t download -n centos8 -- -d centos -r 8 -a amd64 --no-validate

lxc-create -t download -n centos7 -- -d centos -r 7 -a amd64 --no-validate

Typical base installs use less than 1 GB of disk space.


Pi-hole Container Example

The Pi-hole project is a “DNS sinkhole” that protects your devices from unwanted content, without installing any client-side software.

Pi-hole is a perfect example to use with AstLinux within a LXC. Begin as with the “Quick Start Guide” but use the name pi-hole.

First, it is assumed the lxcbr0 interface is setup per the above Quick Start Guide → Enable LXC Support.

Then from the CLI:

lxc-create -t download -n pi-hole -- -d debian -r buster -a amd64 --no-validate
service lxc init
lxc-attach pi-hole
  passwd
  apt install openssh-server iputils-ping curl
  ...
  exit

Tip → Optionally you may want to also…

  apt install sudo nano

Tip → Set PermitRootLogin yes for sshd and restart sshd. Type exit to leave the container and do the rest via ssh.


Install Pi-hole:

Either with lxc-attach pi-hole or ssh root@pi-hole_ip_address

curl -sSL https://install.pi-hole.net -o pihole.sh
# Comment out the "set -e" in pihole.sh, then
bash pihole.sh

Follow the dialogs and answer the questions.

Change Pi-hole WebGUI password:

/usr/local/bin/pihole -a -p


Tip → If lighttpd is not started after the Pi-hole installation (⇒ netstat -tlp):

apt remove lighttpd
bash pihole.sh
# choose "Update"

The Pi-hole LXC container uses about 40-50 MB of RAM.


Command via a Container

There are occasions where a command might be useful within AstLinux, but it may use python, golang, etc. or is just large in comparison to the 50 MB size of the AstLinux image. A LXC container can be a handy tool to add such a command.

Below is an example how to add the lynx command line web browser. The lynx container only runs when needed.

First, it is assumed the lxcbr0 interface is setup per the above Quick Start Guide → Enable LXC Support.

Then from the CLI:

lxc-create -t download -n lynx -- -d debian -r buster -a amd64 --no-validate
service lxc restart
lxc-attach lynx
  apt install lynx ca-certificates fping
  exit

Next, stop the lynx container and keep it from automatically starting.

lxc-stop lynx
sed -i 's/^lxc.start.auto=1/lxc.start.auto=0/' /var/lib/lxc/lynx/config

Finally, create a wrapper script to start/stop the container and issue a command.

Place this script at /mnt/kd/bin/lynx and give it chmod 755 permissions.

#!/bin/sh
##
## lynx wrapper for LXC Debian 10 container
##

## generate a random uid
rand_uid=$((RANDOM % 4999 + 95000))

## Destination IP to test when container network is active
ping_ip="8.8.4.4"

trap 'printf "Abort\n" >&2; lxc-stop lynx; exit 1' INT TERM EXIT

lxc-start lynx

printf "Waiting for container network to become active... "
lxc-attach lynx -u $rand_uid -- fping -q -r15 $ping_ip
printf "OK\n"

lxc-attach lynx -u $rand_uid -- lynx "$@"

lxc-stop lynx

trap - INT TERM EXIT

exit 0

Tip → If you edit /var/lib/lxc/lynx/config and assign a manual IP address, the container starts very quickly, whereas using DHCP it takes 4-6 seconds to establish the network.

Test it!

/mnt/kd/bin/lynx https://www.astlinux-project.org


Optional

Here are few useful optional configuration options that amongst others limit the resources of the container:

lxc.environment = TERM=linux

lxc.cgroup.memory.limit_in_bytes = 512M
#lxc.cgroup.cpu.shares = 256
# Define which actual cores (e.g. 0 to 3) are allowed to use - comma separated (it's NOT the count of cores!)
lxc.cgroup.cpuset.cpus = 1,3