Last active
December 30, 2018 22:48
-
-
Save mathiasaerts/aa0ec400d96b3626d16ead7b8747d073 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# LXC Setup script | |
# ---------------- | |
# This script aims to set up a simple container environment with | |
# an easy to use NAT network setup. | |
# | |
# It will install LXC as container runtime and set up dnsmasq as a | |
# simple DHCP server. LXC will be configured to create unpriviledged | |
# containers by default. The script will also configure a linux | |
# bridge to which the container's network interfaces can attach. | |
# | |
# created by Mathias Aerts <mathias-aerts.net> - 2018/12/30 | |
# | |
# | |
# Requirements: | |
# | |
# - Debian based system | |
# - LXC 2.x | |
# Tested on a Debian Stretch VPS | |
# | |
# | |
# Usage: | |
# | |
# Execute this script as root. After that, follow the instructions | |
# below to set up your first container. | |
# | |
# In order to create a container, use the following commands: | |
# | |
# > lxc-create -t download -n <container name> | |
# or specify the image in the command line directly: | |
# > lxc-create -t download -n <container name> -- -d ubuntu -r xenial -a amd64 | |
# | |
# By default, dnsmasq will assign an ip address from the configured | |
# range to the container. To ensure a container is given a static ip | |
# address (using DHCP), follow the steps below: | |
# | |
# - First we need to get the configured mac address for the container | |
# > grep hwaddr /var/lib/lxc/<container name>/config | |
# | |
# - Next, we'll add an entry in the dnsmasq config /etc/dnsmasq.d/containers.conf | |
# > dhcp-host=00:16:3e:xx:xx:xx,<container name>,10.100.1.10,45m | |
# | |
# - Restart dnsmasq service before starting the container | |
# > service dnsmasq restart | |
# > lxc-start -n <container name> | |
# | |
# Stop script when an error occurs | |
set -e | |
## Variables | |
# Networking | |
NET_BRIDGE='lxcbr0' # The name of the linux bridge we'll configure | |
NET_PREFIX='10.100.2' # Prefix for the network subnet you want to use (adjust other variables accordingly) | |
NET_HOST_IP="${NET_PREFIX}.1" # An ip address in the subnet for the host itself | |
NET_SUBNET="${NET_PREFIX}.0" # The network address | |
NET_CIDR="${NET_SUBNET}/24" # The subnet in CIDR notation | |
NET_MASK='255.255.255.0' # The subnet mask, should match the subnet address and CIDR notation above | |
NET_DHCP_START="${NET_PREFIX}.2" # Start of the DHCP range | |
NET_DHCP_END="${NET_PREFIX}.254" # End of the DHCP range | |
# Packages to install | |
PACKAGES=( | |
'vim' | |
'bash-completion' | |
'lxc' | |
'dnsmasq' | |
'curl' | |
'wget' | |
'ca-certificates' | |
'openssl' | |
'debootstrap' | |
'rsync' | |
'xz-utils' | |
'gnupg' | |
'dirmngr' | |
'bridge-utils' | |
'ifupdown' | |
) | |
# User and group | |
LXC_USER='lxcu' | |
LXC_GROUP="${LXC_USER}" | |
LXC_UID_GID_OFFSET=100000 | |
# Config files | |
LXC_BASE_DIR='/var/lib/lxc' | |
NET_INTERFACES_FILE='/etc/network/interfaces' | |
LXC_DEFAULT_CONF='/etc/lxc/default.conf' | |
DNSMASQ_CONFIG_FILE='/etc/dnsmasq.d/lxc.conf' | |
## Start setup | |
# Install required packages | |
echo "* Updating package list.." | |
apt-get update >/dev/null 2>&1 | |
echo "* Installing required packages.." | |
apt-get install -y ${PACKAGES[@]} >/dev/null 2>&1 | |
# Write default LXC config | |
echo "* Writing default lxc config" | |
cat > "${LXC_DEFAULT_CONF}" <<EOF | |
# Container specific configuration | |
lxc.id_map = u 0 ${LXC_UID_GID_OFFSET} 65536 | |
lxc.id_map = g 0 ${LXC_UID_GID_OFFSET} 65536 | |
lxc.start.auto = 1 | |
lxc.start.delay = 5 | |
lxc.group = onboot | |
# Network configuration | |
lxc.network.type = veth | |
lxc.network.name = eth0 | |
lxc.network.flags = up | |
lxc.network.link = ${NET_BRIDGE} | |
lxc.network.hwaddr = 00:16:3e:xx:xx:xx | |
EOF | |
# Add group and user for lxc | |
if ! grep -qE "^${LXC_GROUP}:" /etc/group; then | |
echo "* Adding group ${LXC_GROUP}" | |
groupadd -g "${LXC_UID_GID_OFFSET}" -r "${LXC_GROUP}" | |
fi | |
if ! grep -qE "^${LXC_USER}:" /etc/passwd; then | |
echo "* Adding user ${LXC_USER}" | |
useradd -d "${LXC_BASE_DIR}" -c "LXC Unpriviledged user" -M -r -s /bin/bash -u "${LXC_UID_GID_OFFSET}" -g "${LXC_GROUP}" "${LXC_USER}" | |
fi | |
# Set up network bridge | |
if ! grep -qE "^auto ${NET_BRIDGE}" "${NET_INTERFACES_FILE}"; then | |
echo "* Adding network bridge ${NET_BRIDGE}.." | |
cat >> "${NET_INTERFACES_FILE}" <<EOF | |
auto ${NET_BRIDGE} | |
iface ${NET_BRIDGE} inet static | |
address ${NET_HOST_IP} | |
netmask ${NET_MASK} | |
bridge_ports none | |
post-up echo 1 > /proc/sys/net/ipv4/ip_forward | |
post-up iptables -t nat -A POSTROUTING -s '${NET_CIDR}' -j MASQUERADE | |
post-down iptables -t nat -D POSTROUTING -s '${NET_CIDR}' -j MASQUERADE | |
EOF | |
fi | |
# Ensure bridge interface is up | |
# Run ifdown first to make sure we start clean | |
ifdown "${NET_BRIDGE}" >/dev/null 2>&1 | |
ifup "${NET_BRIDGE}" >/dev/null 2>&1 | |
# Write DHCP config | |
if ! [[ -e "${DNSMASQ_CONFIG_FILE}" ]]; then | |
echo "* Writing dnsmasq DHCP config.." | |
cat > "${DNSMASQ_CONFIG_FILE}" <<EOF | |
interface=${NET_BRIDGE} | |
except-interface=lo | |
dhcp-range=${NET_DHCP_START},${NET_DHCP_END},${NET_MASK},12h | |
EOF | |
fi | |
# Restart dnsmasq service | |
service dnsmasq restart | |
## Finished | |
echo "* All done. Create your first container using 'lxc-create -t download -n <container name>'" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment