diff --git a/README.md b/README.md index 38952224..0bd5d97b 100644 --- a/README.md +++ b/README.md @@ -52,50 +52,50 @@ Bastille is an open-source system for automating deployment and management of containerized applications on FreeBSD. Usage: - bastille command TARGET [args] + bastille [options(s)] command [option(s)] TARGET [args] Available Commands: - bootstrap Bootstrap a FreeBSD release for container base. - clone Clone an existing container. - cmd Execute arbitrary command on targeted container(s). - config Get or set a config value for the targeted container(s). - console Console into a running container. - convert Convert a Thin container into a Thick container. - cp cp(1) files from host or container to host or 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. - edit Edit container configuration files (advanced). - export Exports a specified container. + bootstrap Bootstrap a release for jail base. + clone Clone an existing jail. + cmd Execute arbitrary command on targeted jail(s). + config Get, set or remove a config value for the targeted jail(s). + console Console into a running jail. + convert Convert thin jail to thick jail, or convert a jail to a custom release. + cp cp(1) files from host or jail to host or targeted jail(s). + create Create a jail. + destroy Destroy a jail or release. + edit Edit jail configuration files (advanced). + export Exports a jail. help Help about any command. htop Interactive process viewer (requires htop). - import Import a specified container. + import Import a jail. jcp cp(1) files from a jail to jail(s). - limits Apply resources limits to targeted container(s). See rctl(8). - list List containers (running). - mount Mount a volume inside the targeted container(s). + limits Apply resources limits to targeted jail(s). See rctl(8). + list List jails, releases, templates etc... + mount Mount a volume inside targeted jail(s). network Add or remove interfaces from targeted jail(s). - pkg Manipulate binary packages within targeted container(s). See pkg(8). + pkg Manipulate binary packages within targeted jail(s). See pkg(8). rcp cp(1) files from a jail to host. rdr Redirect host port to container port. - rename Rename a container. - restart Restart a running container. - service Manage services within targeted container(s). + rename Rename a jail. + restart Restart a running jail. + service Manage services within targeted jail(s). setup Attempt to auto-configure network, firewall and storage on new installs. - start Start a stopped container. - stop Stop a running container. - sysrc Safely edit rc files within targeted container(s). - tags Add or remove tags to targeted container(s). - template Apply file templates to targeted container(s). + start Start a stopped jail. + stop Stop a running jail. + sysrc Safely edit rc files within targeted jail(s). + tags Add or remove tags to targeted jail(s). + template Apply file templates to targeted jail(s). top Display and update information about the top(1) cpu processes. - umount Unmount a volume from within the targeted container(s). - update Update container base -pX release. - upgrade Upgrade container release to X.Y-RELEASE. + umount Unmount a volume from targeted jail(s). + update Update jail base -pX release. + upgrade Upgrade jail 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. -Use "bastille [-c|--config FILE] command" to specify a non-default config file. +Use "bastille [-c|--config config.conf] command" to specify a non-default config file. ``` @@ -112,7 +112,7 @@ automatically. This feature is new since version 0.10.20231013. ```shell ishmael ~ # bastille setup -h -ishmael ~ # Usage: bastille setup [pf|network|zfs|vnet] +Usage: bastille setup [-p|pf|firewall] [-l|loopback] [-s|shared] [-z|zfs|storage] [-v|vnet] [-b|bridge] ``` On fresh installations it is likely safe to run `bastille setup` with no diff --git a/docs/chapters/gettingstarted.rst b/docs/chapters/gettingstarted.rst index 4645c7bc..8eb44502 100644 --- a/docs/chapters/gettingstarted.rst +++ b/docs/chapters/gettingstarted.rst @@ -4,12 +4,27 @@ Getting Started This guide is meant to get you up and running with bastille, and will show you a number of different options to create and manage your jails. -The first step is running ``bastille setup`` to try to configure bastille -initially, if you didn't during setup. Setup should only be run once. +Setup +----- + +The first command a new user should run is the ``bastille setup`` command. This +will attempt to configure the networking, storage, and firewall on your system +for use with Bastille. + +By default the setup command will configure a loopback interface, storage (ZFS if +enabled, otherwise UFS) and the pf firewall if you run it as below without any options. + +Alternatively, you can run the ``setup`` command with any of the supported options to +configure the selected option by itself. + +To see a list of available options and switches, see the ``setup`` subcommand. .. code-block:: shell ishmael ~ # bastille setup + +Bootstrapping a Release +----------------------- Then we need to bootstrap a release for bastille to use. We will use 14.2-RELEASE. @@ -17,6 +32,9 @@ Then we need to bootstrap a release for bastille to use. We will use .. code-block:: shell ishmael ~ # bastille bootstrap 14.2-RELEASE + +Creating a Jail +--------------- Next we can create our first jail. Bastille can create a few different types of jails. @@ -41,7 +59,7 @@ Only clone, thin, and thick jails can be created with ``-V`` ``-B`` and ``-M``. We will focus on thin jails for the guide. Classic/Standard Jail ---------------------- +^^^^^^^^^^^^^^^^^^^^^ .. code-block:: shell @@ -62,7 +80,7 @@ necessary to redirect the traffic. It will pass in and out normally. This will forward traffic from port 80 on the host to port 80 inside the jail. VNET Jail ---------- +^^^^^^^^^ VNET jails can use either a host interface with ``-V`` or a manually created bridge interface with ``-B``. You can also optionally set a static MAC for the @@ -82,7 +100,7 @@ The IP used for VNET jails should be an IP reachable inside your local network. You can also specify 0.0.0.0 or DHCP to use DHCP. Linux Jail ----------- +^^^^^^^^^^ Linux jails are still considered experimental, but they seem to work. First we must bootstrap a linux distro. diff --git a/docs/chapters/subcommands/create.rst b/docs/chapters/subcommands/create.rst index c12db4ba..0366f27a 100644 --- a/docs/chapters/subcommands/create.rst +++ b/docs/chapters/subcommands/create.rst @@ -5,24 +5,27 @@ Bastille create uses any available bootstrapped release to create a lightweight container system. To create a container simply provide a name, bootstrapped release and a private (rfc1918) IP address. -- name - release - ip - interface (optional) +The format is ``bastille create NAME RELEASE IP [INTERFACE]`` + +Note that the ``interface`` is optional. Bastille will use the default interface +that is configured when running the setup command. See ``bastille setup -l`` or +``bastille setup -s``. .. code-block:: shell - ishmael ~ # bastille create folsom 11.3-RELEASE 10.17.89.10 [interface] + ishmael ~ # bastille create folsom 11.3-RELEASE 10.17.89.10 [INTERFACE] RELEASE: 11.3-RELEASE. NAME: folsom. IP: 10.17.89.10. -This command will create a 11.3-RELEASE container assigning the 10.17.89.10 ip -address to the new system. +This command will create a 11.3-RELEASE jail, assigning the 10.17.89.10 ip +address to the new jail. .. code-block:: shell ishmael ~ # bastille create alcatraz 13.2-RELEASE 10.17.89.113/24 - The above code will create a jail with a /24 mask. At the time of this documentation you can only use CIDR notation, and not use a netmask 255.255.255.0 to accomplish this. @@ -33,7 +36,7 @@ ranges include: - 10.0.0.0/8 - 172.16.0.0/12 - 192.168.0.0/16 Bastille does its best to validate the submitted ip is valid. This has not been -thouroughly tested--I generally use the 10/8 range. +thouroughly tested. I generally use the 10/8 range. A couple of notes about the created jails. First, MOTD has been disabled inside of the jails because it does not give information about the jail, but about the @@ -45,7 +48,6 @@ version information about the host system instead of the jail. If you need to check the version of freebsd running on the jail use the freebsd-version command to get accurate information. - Bastille can create many different types of jails, along with many different options. See the below help output. diff --git a/docs/chapters/subcommands/setup.rst b/docs/chapters/subcommands/setup.rst index 76f668b1..311c617a 100644 --- a/docs/chapters/subcommands/setup.rst +++ b/docs/chapters/subcommands/setup.rst @@ -2,19 +2,59 @@ setup ===== The ``setup`` sub-command attempts to automatically configure a host system for -Bastille containers. This allows you to configure networking, firewall, and -storage options for a Bastille host with one command. +Bastille jails. This allows you to configure networking, firewall, storage, vnet +and bridge options for a Bastille host with one command. + +Options +------- + +Below is a list of available options that can be used with the ``setup`` command. .. code-block:: shell ishmael ~ # bastille setup -h ## display setup help - ishmael ~ # bastille setup network ## only configure loopback interface - ishmael ~ # bastille setup pf ## only configure default firewall - ishmael ~ # bastille setup zfs ## only configure ZFS storage - ishmael ~ # bastille setup vnet ## only configure VNET bridge - ishmael ~ # bastille setup ## configure all of the above + ishmael ~ # bastille setup -l ## configure loopback interface + ishmael ~ # bastille setup -s ## configure shared interface + ishmael ~ # bastille setup -p ## configure default pf firewall + ishmael ~ # bastille setup -z ## configure ZFS storage + ishmael ~ # bastille setup -v ## configure VNET + ishmael ~ # bastille setup -b ## configure bridge interface + ishmael ~ # bastille setup ## configure -l -p and -z + +The ``-l|loopback`` option will configure a loopback interface called ``bastille0`` that +will be used as a default when not specifying an interface with the ``create`` command. + +The ``-s|shared`` option will configure the interface you choose to also be used as the default +when not specifying an interface with the ``create`` command. + +Please note. You CANNOT run both a loopback and a shared interface with Bastille. Only one +should be configured. If you configure one, it will disable the other. + +The ``-l|loopback`` option is the default, and is enough for most use cases. It is simply an ``lo`` interface +that jails will get linked to on creation. It is not attached to any specific interface. This is the simplest +networking option. The ``-l|loopback`` and ``-s|shared`` options are only for cases where the ``interface`` +is not specified during the ``create`` command. If an interface is specified, these options have no effect. +Instead, the specified interface will be used. + +The ``-s|shared`` option is for cases where you want an actual interface to use with bastille as +opposed to a loopback. Jails will be linked to the shared interface on creation. + +The ``-p|pf|firewall`` option will configure the pf firewall by enabling the service and creating the +default ``pf.conf`` file. Once this is done, you can use the ``rdr`` command to forward traffic into +a jail. + +The ``-z|zfs|storage`` option will attempt to configure a pool and dataset for Bastille, but only +if ZFS in enabled on your system. + +The ``-v|vnet`` option will configure your system for use with VNET ``-V`` jails. + +The ``-b|bridge`` options will attempt to configure a bridge interface for use with bridged VNET +``-B`` jails. + +Running ``bastille setup`` without any options will attempt to auto-configure the ``-l``, ``-p`` and +``-z`` options. .. code-block:: shell ishmael ~ # bastille setup help - Usage: bastille setup [pf|network|zfs|vnet] + Usage: bastille setup [-p|pf|firewall] [-l|loopback] [-s|shared] [-z|zfs|storage] [-v|vnet] [-b|bridge] diff --git a/usr/local/share/bastille/setup.sh b/usr/local/share/bastille/setup.sh index 8cedee2d..30933f32 100644 --- a/usr/local/share/bastille/setup.sh +++ b/usr/local/share/bastille/setup.sh @@ -33,7 +33,7 @@ . /usr/local/share/bastille/common.sh usage() { - error_exit "Usage: bastille setup [pf|network|zfs|vnet]" + error_exit "Usage: bastille setup [-p|pf|firewall] [-l|loopback] [-s|shared] [-z|zfs|storage] [-v|vnet] [-b|bridge]" } # Check for too many args @@ -42,24 +42,103 @@ if [ $# -gt 1 ]; then fi # Configure bastille loopback network interface -configure_network() { - info "Configuring ${bastille_network_loopback} loopback interface" - sysrc cloned_interfaces+=lo1 - sysrc ifconfig_lo1_name="${bastille_network_loopback}" +configure_loopback_interface() { + if [ -z "$(sysrc -f ${BASTILLE_CONFIG} -n bastille_network_loopback)" ] || ! sysrc -n cloned_interfaces | grep -oq "lo1"; then + info "Configuring bastille0 loopback interface" + sysrc cloned_interfaces+=lo1 + sysrc ifconfig_lo1_name="bastille0" + info "Bringing up new interface: [bastille0]" + service netif cloneup + sysrc -f "${BASTILLE_CONFIG}" bastille_network_loopback="bastille0" + sysrc -f "${BASTILLE_CONFIG}" bastille_network_shared="" + info "Loopback interface successfully configured: [bastille0]" + else + info "Loopback interface has already been configured: [bastille0]" + fi +} - info "Bringing up new interface: ${bastille_network_loopback}" - service netif cloneup +configure_shared_interface() { + _interface_list="$(ifconfig -l)" + _interface_count=0 + if [ -z "${_interface_list}" ]; then + error_exit "Unable to detect interfaces, exiting." + fi + if [ -z "$(sysrc -f ${BASTILLE_CONFIG} -n bastille_network_shared)" ]; then + info "Attempting to configure shared interface for bastille..." + info "Listing available interfaces..." + for _if in ${_interface_list}; do + echo "[${_interface_count}] ${_if}" + _if_num="${_if_num} [${_interface_count}]${_if}" + _interface_count=$(expr ${_interface_count} + 1) + done + # shellcheck disable=SC3045 + read -p "Please select the interface you would like to use: " _interface_choice + if ! echo "${_interface_choice}" | grep -Eq "^[0-9]+$"; then + error_exit "Invalid input number, aborting!" + else + _interface_select=$(echo "${_if_num}" | grep -wo "\[${_interface_choice}\][^ ]*" | sed 's/\[.*\]//g') + fi + # Adjust bastille.conf to reflect above choices + sysrc -f "${BASTILLE_CONFIG}" bastille_network_loopback="" + sysrc cloned_interfaces-="lo1" + ifconfig bastille0 destroy 2>/dev/null + sysrc -f "${BASTILLE_CONFIG}" bastille_network_shared="${_interface_select}" + info "Shared interface successfully configured: [${_interface_select}]" + else + info "Shared interface has already been configured: [$(sysrc -f ${BASTILLE_CONFIG} -n bastille_network_shared)]" + fi + +} + +configure_bridge() { + _bridge_name="bastillebridge" + _interface_list="$(ifconfig -l)" + _interface_count=0 + if [ -z "${_interface_list}" ]; then + error_exit "Unable to detect interfaces, exiting." + fi + if ! ifconfig -g bridge | grep -oqw "${_bridge_name}"; then + info "Configuring ${_bridge_name} bridge interface..." + info "Listing available interfaces..." + for _if in ${_interface_list}; do + if ifconfig -g bridge | grep -oqw "${_if}" || ifconfig -g lo | grep -oqw "${_if}"; then + continue + else + echo "[${_interface_count}] ${_if}" + _if_num="${_if_num} [${_interface_count}]${_if}" + _interface_count=$(expr ${_interface_count} + 1) + fi + done + # shellcheck disable=SC3045 + read -p "Please select the interface to attach the bridge to: " _interface_choice + if ! echo "${_interface_choice}" | grep -Eq "^[0-9]+$"; then + error_exit "Invalid input number, aborting!" + else + _interface_select=$(echo "${_if_num}" | grep -wo "\[${_interface_choice}\][^ ]*" | sed 's/\[.*\]//g') + fi + # Create bridge and persist on reboot + ifconfig bridge0 create + ifconfig bridge0 name bastillebridge + ifconfig bastillebridge addm ${_interface_select} up + sysrc cloned_interfaces+="bridge0" + sysrc ifconfig_bridge0_name="bastillebridge" + sysrc ifconfig_bastillebridge="addm ${_interface_select} up" + + info "Bridge interface successfully configured: [${_bridge_name}]" + else + info "Bridge has alread been configured: [${_bridge_name}]" + fi } configure_vnet() { - info "Configuring bridge interface" - sysrc cloned_interfaces+=bridge1 - sysrc ifconfig_bridge1_name=bastille1 - - info "Bringing up new interface: bastille1" - service netif cloneup - - if [ ! -f /etc/devfs.rules ]; then + # Ensure jib script is in place for VNET jails + if [ ! "$(command -v jib)" ]; then + if [ -f /usr/share/examples/jails/jib ] && [ ! -f /usr/local/bin/jib ]; then + install -m 0544 /usr/share/examples/jails/jib /usr/local/bin/jib + fi + fi + # Create default VNET ruleset + if [ ! -f /etc/devfs.rules ] || ! grep -oq "bastille_vnet=13" /etc/devfs.rules; then info "Creating bastille_vnet devfs.rules" cat << EOF > /etc/devfs.rules [bastille_vnet=13] @@ -70,6 +149,8 @@ add include \$devfsrules_jail add include \$devfsrules_jail_vnet add path 'bpf*' unhide EOF + else + info "VNET has already been configured!" fi } @@ -104,7 +185,7 @@ EOF sysrc pf_enable=YES warn "pf ruleset created, please review ${bastille_pf_conf} and enable it using 'service pf start'." else - error_exit "${bastille_pf_conf} already exists. Exiting." + info "Firewall (pf) has already been configured!" fi } @@ -112,6 +193,8 @@ fi configure_zfs() { if [ ! "$(kldstat -m zfs)" ]; then info "ZFS module not loaded; skipping..." + elif sysrc -f ${BASTILLE_CONFIG} -n bastille_zfs_enable | grep -Eoq "([Y|y][E|e][S|s])"; then + info "ZFS has already been configured!" else ## attempt to determine bastille_zroot from `zpool list` bastille_zroot=$(zpool list | grep -v NAME | awk '{print $1}') @@ -128,26 +211,63 @@ configure_zfs() { # Run all base functions (w/o vnet) if no args if [ $# -eq 0 ]; then sysrc bastille_enable=YES - configure_network + configure_loopback_interface configure_pf configure_zfs fi -# Handle special-case commands first. +# Handle options. case "$1" in -help|-h|--help) - usage - ;; -pf|firewall) - configure_pf - ;; -network|loopback) - configure_network - ;; -zfs|storage) - configure_zfs - ;; -bastille1|vnet|bridge) - configure_vnet - ;; + -h|--help|help) + usage + ;; + -p|pf|firewall) + configure_pf + ;; + -l|loopback) + warn "[WARNING] Bastille only allows using either the 'loopback' or 'shared'" + warn "interface to be configured ant one time. If you continue, the 'shared'" + warn "interface will be disabled, and the 'loopback' interface will be used as default." + # shellcheck disable=SC3045 + read -p "Do you really want to continue setting up the loopback interface? [y|n]:" _answer + case "${_answer}" in + [Yy]|[Yy][Ee][Ss]) + configure_loopback_interface + ;; + [Nn]|[Nn][Oo]) + error_exit "Loopback interface setup cancelled." + ;; + *) + error_exit "Invalid selection. Please answer 'y' or 'n'" + ;; + esac + ;; + -s|shared) + warn "[WARNING] Bastille only allows using either the 'loopback' or 'shared'" + warn "interface to be configured at one time. If you continue, the 'loopback'" + warn "interface will be disabled, and the shared interface will be used as default." + # shellcheck disable=SC3045 + read -p "Do you really want to continue setting up the shared interface? [y|n]:" _answer + case "${_answer}" in + [Yy]|[Yy][Ee][Ss]) + configure_shared_interface + ;; + [Nn]|[Nn][Oo]) + error_exit "Shared interface setup cancelled." + ;; + *) + error_exit "Invalid selection. Please answer 'y' or 'n'" + ;; + esac + ;; + -z|zfs|storage) + configure_zfs + ;; + -v|vnet) + configure_vnet + ;; + -b|bridge) + configure_vnet + configure_bridge + ;; esac