Skip to content

Instantly share code, notes, and snippets.

@derekdreery
Last active August 29, 2015 14:09
Show Gist options
  • Save derekdreery/f3c6dc8cc6578eb83f87 to your computer and use it in GitHub Desktop.
Save derekdreery/f3c6dc8cc6578eb83f87 to your computer and use it in GitHub Desktop.
Systemd containers

Systemd containers

Systemd container are an easy way to create containers for isolating programs onto private networks, which I do a lot when I'm doing web development.

It's really cool - both host and container run systemd and know how to communicate, and everything just works.

This guide derrives most stuff from the arch wiki, and tries to pull it into a single set of instructions.

Alternatives

  1. If security is important, you need hardware virtualization (kvm, I believe there are non FOSS things as well.)
  2. Virtualbox is an easy way to spin up hardware virtualization through a gui
  3. OpenVZ is the solution for (apparently secure) software virtualization, and apparently they did a lot of the kernel work that made lxc/systemd containers possible. It requires a kernel patch to run.
  4. LXC is the other new container virtualization technology, which gives more control but is in my experience more difficult to set up.

Basics

Systemd-nspawn

The command to start a container in systemd is systemd-nspawn. From the man page:

systemd-nspawn may be used to run a command or OS in a light-weight namespace container. In many ways it is similar to chroot(1), but more powerful since it fully virtualizes the file system hierarchy, as well as the process tree, the various IPC subsystems and the host and domain name.

Note: All information on systemd is in man pages, and so they are the definitive source for information.

Systemd-networkd

The network specifier for systemd is called systemd-networkd. checkout the arch wiki for a good description of how systemd-networkd works. We will be using this in both the host and container.

Pacman (or debootstrap or yum or...)

We need a program to bootstrap a linux filesystem (minus kernel) into our container route. I use pacman here because I use arch linux, but the internet tells how to use the other distros.

Iptables

We use iptables to do all our routing and packet filtering. Iptables is complicated, but also very powerful. There are interfaces which provide easier configuration, but they probably hide features, definitely add a level of indirection, and I don't know how to use them.

Creating our container

This is the tl;dr bit. I'll put info that's not essential in quotes. It's trying to be newbie friendly so please say if something isn't obvious.

Bootstrap our filesystem

  • Create a folder to act as the root of our filesystem. Call the directory what you want to call your container (here I use mycontainer)
# mkdir ~/mycontainer
  • Now create the filesystem
# pacstrap -i -c -d ~/mycontainer base

Note: You may need to generate entropy before pacman will generate keys - see the internet.

Note: arch recommends installing base-devel which you will need for any kind of compiling

  • You're done! To boot into your new container, type the following to get a terminal in your new system. Login with user root (no password)
# systemd-nspawn -bD ~/mycontainer

Create a virtual network

If you're using systemd-networkd, you should already have something like

contents of "/etc/systemd/network/simple.network"

[Match]
Name=en*

[Network]
DHCP=both

and have configured it yourself, so you know what the bits mean. This will help a lot in configuring the networking for the container.

  • Configure your private network:
    • in "/etc/systemd/network/private.netdev"
[NetDev]
Name=priv0
Kind=bridge
    • in "/etc/systemd/network/private.network"
[Match]
Name=priv0

[Network]
Address=10.0.0.1/24
  • Restart systemd-networkd
systemctl restart systemd-networkd

You can use whatever network you want here, but if you overwrite something on the internet you won't be able to access it. The subnets which are reserved for LANs are 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16. It's best to use something within these. IPv6 will eliminate the need for NAT, because there will be so many addresses every person can have like a gazillion each.

We've now created our private network (the netdev bridge) and attached a virtual NIC to it (the network). We can now supply this bridge to our conatiner, which will be able to create another virtual NIC to attach to it. So we've got something like this:

               eth0 +-----------+ priv0        +------------+
  Internet ---------|  Host     |--------------| Container  |
                    +-----------+        host0 +------------+

Next we setup the container network config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment