It’s dangerous to go alone! Take this.

Bastille on FreeBSD

This document is designed to help you be successful in your use and adoption of Bastille and FreeBSD. This document begins with a brand-new FreeBSD 12.1 system deployed locally or in the cloud. Manual installation is not covered in this document.

Firstboot

Upon logging into a system for the first time it is recommended to apply any security patches available:

freebsd-update fetch install reboot

After the reboot is complete, run freebsd-update install once again.

freebsd-update install

Verify your version and patch level with freebsd-version .

freebsd-version

Tip: subscribe to this mailing list for FreeBSD security notifications (low volume). Anytime you receive an email from this list, re-run freebsd-update fetch install .

Packaging

FreeBSD provides binary packages, available in quarterly (default) and latest branches. These binary packages are built from the FreeBSD ports tree, which follows a rolling-release model. This means up-to-date packages are often available. To use the binary package manager, bootstrap it by running pkg for the first time:

[email protected]:~ # pkg bootstrap The package management tool is not yet installed on your system. Do you want to fetch and install it now? [ y/N ] : y Bootstrapping pkg from pkg+http://pkg.FreeBSD.org/FreeBSD:12:amd64/quarterly, please wait... Verifying signature with trusted certificate pkg.freebsd.org.2013102301... done [ freebsd ] Installing pkg-1.10.5_1... [ freebsd ] Extracting pkg-1.10.5_1: 100% [email protected]:~ #

Note: this bootstrapping step can be automated using the following command: env ASSUME_ALWAYS_YES=YES pkg bootstrap

Quarterly

If you take a closer look at the line of output after the bootstrap confirmation you’ll notice that the last part of the URL says quarterly :

Bootstrapping pkg … pkg.FreeBSD.org/FreeBSD:12:amd64/ quarterly , please wait…

This subscribes the host to a quarterly release cycle for binary packages. For most systems this is adequate. No changes are needed to subscribe to the quarterly repository.

Latest

To use the latest binary packages, update the pkg URL to use the latest suffix instead. A simple way to override the default settings is to create a new repository config with the updated path of latest .

Migrate to latest:

mkdir -p /usr/local/etc/pkg/repos echo 'FreeBSD: { url: ' pkg+http://pkg.FreeBSD.org/ \$\{ ABI \} /latest ', enabled: yes }' > /usr/local/etc/pkg/repos/FreeBSD.conf

Package Basics

In this section you’ll learn the basics of using the package manager, and install a few creature comforts. FreeBSD’s binary package manager works much like others you may have used.

Example

pkg install vim-console git-lite bash ca_root_nss

The above pkg install command will add the vim-console , git-lite , bash and ca_root_nss (CA certificates) from the quarterly/latest repositories. Naturally you can replace bash with zsh (or another shell of your choice).

You may also search the pkg repository for named packages. pkg search foo will match packages including foo .

Tip: Check out FreshPorts.

pkg help

You can always find help and a list of other options using pkg help .

Install Bastille

Now that you’ve had a crash course in package basics, let’s install bastille and start working with containers.

PKG

pkg install bastille

Note: as outlined above, the version of Bastille installed may differ depending on whether you’re using quarterly or latest .

PORTS

portsnap fetch auto make -C /usr/ports/sysutils/bastille install clean

GIT

git clone https://github.com/BastilleBSD/bastille.git cd bastille make install

Service Management

Services in FreeBSD are managed centrally in the /etc/rc.conf and use a syntax of name_enable=(YES|NO) . For example, to start containers automatically at boot you can set bastille_enable=YES using:

sysrc bastille_enable = YES

By default, Bastille will start all created containers at boot when enabled.

To specify a limited list of containers to start at boot, set the optional bastille_list value to the name(s) of containers to start.

sysrc bastille_list = "azkaban arkham alcatraz"

Once services have been enabled in the /etc/rc.conf , they can be managed using the service command.

service foo [ start|stop|restart ]

Bastille does not run as a service and does not need to be started as such. Enabling Bastille primarily manages containers at startup and shutdown.

Bastille Containers

Once Bastille is installed you’ll want to verify the configuration. This is where you can set the default file system (UFS or ZFS) and define the default network interface for containers.

/usr/local/etc/bastille/bastille.conf

I recommend looking at the following:

default timezone

If you’d prefer to use a local timezone for your containers you may change it here. The default is etc/UTC. Requires format America/Denver or Europe/Paris. (see /usr/share/zoneinfo )

bastille_tzdata="etc/UTC" ## default: "etc/UTC"

ZFS (optional)

If your system uses ZFS as a filesystem you can make use of that here. Set the enable option to YES and define the zpool . If either is undefined ZFS will not be used.

## ZFS options bastille_zfs_enable="" ## default: "" bastille_zfs_zpool="" ## default: ""

Networking

Bastille can be flexible about the way it handles networking. In this document we will use the more portable “loopback” network design. This can be used in the same way in the cloud or on local networks. Bastille uses this method by default.

If you’d like to use an alternate method, refer to the Bastille Networking Documentation.

There is a one-time setup requirement to configure a new bastille0 loopback interface and define firewall rules:

sysrc cloned_interfaces += lo1 sysrc ifconfig_lo1_name = "bastille0" service netif cloneup

With this in place we can create the firewall rules that will both limit access to the host system and containers, and also provide a NAT rule for the new bastille0 loopback interface to access the broader network.

Create /etc/pf.conf and use the following rules:

ext_if="vtnet0" set block-policy return scrub in on $ext_if all fragment reassemble set skip on lo table <jails> persist nat on $ext_if from <jails> to any -> ($ext_if) ## inbound to container example ## rdr pass inet proto tcp from any to any port {80, 443} -> 10.17.89.45 block in all pass out quick modulate state antispoof for $ext_if inet pass in inet proto tcp from any to any port ssh flags S/SA keep state

IMPORTANT: Update ext_if="vtnet0" with the name of your external interface as needed.

This is a sane and simple ruleset that will allow all traffic outbound and block all traffic inbound (with the exception of allowing SSH traffic in). It is also what provides external network access to the containers by way of the table and nat rule. Without those rules there is no external network access for the containers.

Finally enable and start the firewall.

Tip: Starting the firewall will disconnect any remote sessions (ie; the connection you may be using now). SSH inbound access is allowed by the new policy, simply reconnect.

sysrc pf_enable = YES service pf start

Now equipped with a robust firewall and a sane configuration you’re ready to bootstrap a release and begin creating containers!

bootstrap

To bootstrap a release for use with your container use the bootstrap sub-command.

You can optionally append the keyword update to automagically apply freebsd-update to the downloaded release.

bastille bootstrap 12.1-RELEASE update

You can now create a container using the newly bootstrapped release.

create

In order to create a container you will need to provide a unique container name, a bootstrapped release name and static IP address.

You can use any (rfc1918) private IP range for your containers. For example, unless your host IP also has a 10.x.x.x IP, it’s safe to use any address within that range.

IP options include: 10.0.0.0/8 , 172.16.0.0/12 and 192.168.0.0/16 .

Tip: container names cannot include the dot (”.") character.

Container creation should be very quick.

bastille create alcatraz 12.1-RELEASE 10.17.89.50

start

You’ll need to start the container before you can interact with it.

bastille start alcatraz

list

You can list running containers.

bastille list

console

Finally, use console for a password-less root login to the container and have a look around. You’ll find yourself in a wholly contained FreeBSD system with the ability to create unique users, install binary packages, view processes and enable and run services.

bastille console alcatraz

The root user is still (mostly) all powerful, but only within the confines of that container.

When you’re finished, log out of the container as normal with exit or ctrl-d .

stop

When you’re done testing your container you can shut it off.

bastille stop alcatraz

destroy

Lastly, destroy your lightweight container.

bastille destroy alcatraz

usage

Bastille is an open-source system for automating deployment and management of containerized applications on FreeBSD. Usage: bastille command [ALL|glob] [args] Available Commands: bootstrap Bootstrap a FreeBSD release for container base. cmd Execute arbitrary command on targeted container(s). console Console into a running container. cp cp(1) files from host to targeted container(s). create Create a new thin container or a thick container if -T|--thick option specified. destroy Destroy a stopped container or a FreeBSD release. help Help about any command htop Interactive process viewer (requires htop). list List containers, releases, templates, or logs. pkg Manipulate binary packages within targeted container(s). See pkg(8). restart Restart a running container. service Manage services within targeted containers(s). start Start a stopped container. stop Stop a running container. sysrc Safely edit rc files within targeted container(s). template Apply file templates to targeted container(s). top Display and update information about the top(1) cpu processes. update Update container base -pX release. upgrade Upgrade container release to X.Y-RELEASE. verify Compare release against a "known good" index. zfs Manage (get|set) zfs attributes on targeted container(s). Use "bastille -v|--version" for version information. Use "bastille command -h|--help" for more information about a command.

To learn more about automating containerized applications, see the Bastille Documentation.