Bastille Default Templates and Customization

Bastille templates are now fully native.

Stackable Default Templates

Bastille is an open-source system for automating deployment and management containerized applications on FreeBSD.

Bastille Default Templates

Beginning with Bastille 0.8.20210101 the Bastillefile format is now standard and the template system is fully native. This means that Bastille will use default templates to apply base configuration of all new containers.

These default templates can also be customized or extended to meet your specific needs.

In this post I will outline the Bastille template system and how it is used to configure all new containers.

Template Overview

Bastille templates are simple text files defining the automation needed to configure a container. These templates can range from simple to complex. To see a list of available templates visit BastilleBSD Templates


A Bastillefile is the “script” that is executed when a template is applied. Each template will have a unique Bastillefile.

These files can also INCLUDE other Bastillefiles. This allows you to keep the files relatively simple and organize logical components into separate templates.

The Bastillefile template syntax follows a simple format of a Bastille sub-command followed by its arguments. Inside a Bastillefile you do not need to specify a TARGET. The target is defined when applying the template.

Given these simple requirements you can execute any Bastille sub-command in any order by defining them one per line in the Bastillefile.

Simple Bastillefile Example: nginx

PKG nginx
CP usr /
SYSRC nginx_enable=YES
SERVICE nginx start
RDR 443 443

This Bastillefile would perform the following tasks:

  1. Install the nginx binary package inside the container.
  2. Recursively copy usr from the template directory into container / path.
  3. Enable the nginx service at container startup.
  4. Start the nginx service in the running container.
  5. Redirect port 443 traffic from host into container.

Assuming the required nginx configuration files were included in the usr directory (overlay), that container is now configured, enabled, running and accepting traffic.

The “UPPERCASE lowercase” format is a simple visual representation of the sub-command (UPPERCASE) and the arguments to that sub-command (lowercase).

Any Bastille sub-command that targets a container can be used within a Bastillefile.

Default Templates

As of version 0.8.20210101 Bastille ships with a handful of “default” templates. These are used to apply any default configuration to newly created containers. These “default” templates are:

  • base
  • empty
  • thick
  • thin
  • vnet

These default templates are defined in the bastille.conf like so:


+## Default Templates
+bastille_template_base="default/base"      ## default: "default/base"
+bastille_template_empty="default/empty"    ## default: "default/empty"
+bastille_template_thick="default/thick"    ## default: "default/thick"
+bastille_template_thin="default/thin"      ## default: "default/thin"
+bastille_template_vnet="default/vnet"      ## default: "default/vnet"

If upgrading from a previous release be sure these lines have been merged into your bastille.conf

These templates are included in the installation at /usr/local/share/bastille/templates/default.

The default base template is applied to all new containers. This base template is applied by way of an INCLUDE statement within the other templates.


Below is a copy of these five default templates for reference.


ARG HOST_RESOLV_CONF=/etc/resolv.conf

CMD touch /etc/rc.conf
SYSRC syslogd_flags="-ss"
SYSRC sendmail_enable="NO"
SYSRC sendmail_submit_enable="NO"
SYSRC sendmail_outbound_enable="NO"
SYSRC sendmail_msp_queue_enable="NO"
SYSRC cron_flags="-J 60"

CP "${HOST_RESOLV_CONF}" /etc/resolv.conf


ARG BASE_TEMPLATE=default/base
ARG HOST_RESOLV_CONF=/etc/resolv.conf



ARG BASE_TEMPLATE=default/base
ARG HOST_RESOLV_CONF=/etc/resolv.conf



ARG BASE_TEMPLATE=default/base
ARG HOST_RESOLV_CONF=/etc/resolv.conf



SYSRC ifconfig_${EPAIR}_name=vnet0
SYSRC ifconfig_vnet0="${IFCONFIG}"
# GATEWAY will be empty for a DHCP config. -- cwells
CMD if [ -n "${GATEWAY}" ]; then /usr/sbin/sysrc defaultrouter="${GATEWAY}"; fi


As the name implies this is an empty container. No custom configuration is defined.

Template ARG

The keen observer will notice many of the default templates use the keyword ARG to define variables. In this case:

ARG BASE_TEMPLATE=default/base
ARG HOST_RESOLV_CONF=/etc/resolv.conf

These variables can be referenced later in the template:


The above example variables would translate into:

INCLUDE default/base --arg HOST_RESOLV_CONF=/etc/resolv.conf

Additionally you can define and later RENDER these custom variables inside configuration files.

Tip: The variables ${JAIL_NAME} and ${JAIL_IP} are automatically included and can be used within container configuration files.

Example: RENDER file

PKG nginx
CP usr /
RENDER /usr/local/etc/nginx/nginx.conf

Example: RENDER directory (recursive)

PKG nginx
CP usr /
RENDER /usr/local/www

Customizing Default Templates

As you can see from the included default template examples, most configuration is done in the default/base template and the other templates INCLUDE that and (optionally) extend with additional changes.

The best way to customize the default templates is to extend them in your own custom template. These custom templates can then be configured as the defaults for your environment by updating the bastille.conf.

Note: In order to avoid having your changes clobbered with a Bastille package update it is not recommended to edit the default template(s) themselves.

Create a new template namespace at /usr/local/bastille/templates/. This new template namespace is often a username or team/project name. Within this namespace you can create new templates and extend the defaults.

Example for admin: cedwards

mkdir /usr/local/bastille/templates/cedwards/base 

From here we can extend the default/base template with our own template.

Included below is an example Bastillefile that enables outbound sendmail.


ARG HOST_RESOLV_CONF=/etc/resolv.conf

SYSRC sendmail_outbound_enable="YES"
SYSRC sendmail_msp_queue_enable="YES"

Update the bastille.conf to use cedwards/base as the new default:

bastille_template_base="cedwards/base"      ## default: "default/base"

With this configuration every new container would have default/base applied (due to the INCLUDE from cedwards/base) followed by the additional configuration in the cedwards/base template.


Bastille templates are a simple and effective way to automate container creation and management. Who knew automated configuration management could be so simple?

Customizing a default template Bastillefile will allow you to change the way every new system is configured. These defaults can be set for each main container type and can be extended using any Bastille sub-command.

Christer Edwards
Creator of Bastille

FreeBSD die-hard, software developer, author, educator, man behind BastilleBSD. I build cool stuff.