diff --git a/COMPARE.md b/COMPARE.md deleted file mode 100644 index 1be6a618..00000000 --- a/COMPARE.md +++ /dev/null @@ -1,31 +0,0 @@ -# Bastille Compared to Other Jail Managers - -| Feature | BastilleBSD | Appjail | pot | ezjail | iocage | -|------------------------------------------|----------------------------------------|----------------------------------------------------------|--------------------|---------------------|-----------------------------------------| -| OCI Compliant | No | Yes | No | No | No | -| Writen In | Bourne Shell | Bourne Shell, C | Bourne Shell, Rust | Bourne Shell | Bourne Shell, Python | -| Dependencies | None | C | Rust | None | Python | -| Jail Types | clone, copy, thin, thick, empty, linux | clone, copy, tiny, thin, thick, empty, linux+debootstrap | thick | basejail | clone, basejail, template, empty, thick | -| Jail dependency | Yes | Yes | Yes | No | Yes | -| Import/Export | Yes | Yes | Yes | Yes | Yes | -| Boot Order Priorities | Yes | Yes | No | Yes using `rcorder` | Yes | -| Linux containers | Yes | Yes | No | No | Yes | -| Automation | Templates | Makejail, Initscripts, Images | Flavours, Images | Flavours | Plugins | -| Cloning | Yes | No | No | No | No | -| Package Management | Yes | No | No | No | No | -| ZFS Support | Yes | Yes | Yes | No | Yes | -| Volume management | Basic | Yes | Basic | No | Basic | -| VNET Support | Yes | Yes | Yes | No | Yes | -| IPv6 Support | Yes | Yes | Yes | Yes | Yes | -| Dual Network Stack | Yes | Yes | Yes | No | No | -| Netgraph | Yes | Yes | No | No | No | -| Dynamic Firewall | Yes | Yes | Yes | No | No | -| Dynamic DEVFS Ruleset Management | No | Yes | No | No | No | -| Resource Control | Yes | Yes | CPU and Memory | No | Legacy Only | -| CPU Sets | Yes | Yes | Yes | Yes | Yes | -| Parallel Startup | Yes | Yes (Healthcheckers, jails & NAT) | No | No | No | -| Multi-Target Commands | Yes | No | No | No | No | -| Log Management | Basic (console logs) | Yes | No | No | No | -| Copy Files Between Jails | Yes | No | No | No | No | -| Automated Jail Migration Between Servers | Yes | No | No | No | No | -| Top/Htop Support | Yes | No | No | No | No | diff --git a/README.md b/README.md index 206f991d..e77bba1e 100644 --- a/README.md +++ b/README.md @@ -59,9 +59,9 @@ name. If you did use -M when creating them, the MAC should stay the same. -Bastille Compared to Other Jail Managers -======================================== -See the [comparison table.](COMPARE.md) +Comparing Bastille to Other Jail Managers +========================================= +See [Comparing](https://bastille.readthedocs.io/en/latest/chapters/comparing.html) Installation @@ -138,7 +138,7 @@ Available Commands: rcp cp(1) files from a jail to host. rdr Redirect host port to jail port. rename Rename a jail. - restart Restart a running jail. + restart Restart a jail. service Manage services within targeted jail(s). setup Attempt to auto-configure network, firewall, storage and more... start Start a stopped jail. diff --git a/docs/chapters/comparing.rst b/docs/chapters/comparing.rst index 91aa8eff..703558c4 100644 --- a/docs/chapters/comparing.rst +++ b/docs/chapters/comparing.rst @@ -19,7 +19,7 @@ as a list of popular managers and their status on each option. | | | | Rust | | Python | +--------------+-------------+--------------+-----------+-----------+-----------+ | Dep | None | C | Rust | None | Python | -| endencies | | | | | | +|endencies | | | | | | +--------------+-------------+--------------+-----------+-----------+-----------+ | Jail | vnet, | clone, | thick | basejail | clone, | | Types | bridged | copy, | | | basejail, | @@ -33,16 +33,15 @@ as a list of popular managers and their status on each option. | Jail | Yes | Yes | Yes | No | Yes | | Dependency | | | | | | +--------------+-------------+--------------+-----------+-----------+-----------+ -| Impo | Yes | Yes | Yes | Yes | Yes | -| rt/Export | | | | | | +| Import/ | Yes | Yes | Yes | Yes | Yes | +| Export | | | | | | +--------------+-------------+--------------+-----------+-----------+-----------+ | Boot | Yes | Yes | No | Yes using | Yes | | Order | | | | 'rcorder' | | | Priorities | | | | | | +--------------+-------------+--------------+-----------+-----------+-----------+ | Linux | Yes | Yes | No | No | Yes | -| c | | | | | | -| ontainers | | | | | | +| Containers | | | | | | +--------------+-------------+--------------+-----------+-----------+-----------+ | Automation | Templates | Makejail, | Flavours, | Flavours | Plugins | | | | Initscripts, | Images | | | @@ -90,6 +89,9 @@ as a list of popular managers and their status on each option. | | | jails & | | | | | | | NAT) | | | | +--------------+-------------+--------------+-----------+-----------+-----------+ +| PkgBase | Yes | Yes | No | No | No | +| Support | | | | | | ++--------------+-------------+--------------+-----------+-----------+-----------+ | Multi-target | Yes | No | No | No | No | | Commands | | | | | | +--------------+-------------+--------------+-----------+-----------+-----------+ diff --git a/docs/chapters/configuration.rst b/docs/chapters/configuration.rst index 7212e6e2..117fb270 100644 --- a/docs/chapters/configuration.rst +++ b/docs/chapters/configuration.rst @@ -41,6 +41,24 @@ This is the default `bastille.conf` file. ## bastille_bootstrap_archives="base lib32 ports src test" bastille_bootstrap_archives="base" ## default: "base" + ## pkgbase package sets (used for FreeBSD 15+) + ## Any set with [-dbg] can be installed with debugging + ## symbols by adding '-dbg' to the package set + ## base[-dbg] - Base system + ## base-jail[-dbg] - Base system for jails + ## devel[-dbg] - Development tools + ## kernels[-dbg] - Base system kernels + ## lib32[-dbg] - 32-bit compatability libraries + ## minimal[-dbg] - Basic multi-user system + ## minimal-jail[-dbg] - Basic multi-user jail system + ## optional[-dbg] - Optional base system software + ## optional-jail[-dbg] - Optional base system software for jails + ## src - System source code + ## tests - System test suite + ## Whitespace separated list: + ## bastille_pkgbase_packages="base-jail lib32-dbg src" + bastille_pkgbase_packages="base-jail" ## default: "base-jail" + ## default timezone bastille_tzdata="" ## default: empty to use host's time zone diff --git a/docs/chapters/pkgbase.rst b/docs/chapters/pkgbase.rst new file mode 100644 index 00000000..10fd14da --- /dev/null +++ b/docs/chapters/pkgbase.rst @@ -0,0 +1,61 @@ +Pkgbase +======= + +Pkgbase is the new method for managing the base system on a FreeBSD host +or jail. It is considered experimental for 15.0-RELEASE, but will be +made the default for version 16.0-RELEASE and above. + +Bootstrap +--------- + +To bootstrap a release using pkgbase, run ``bastille bootstrap --pkgbase RELEASE``. +For version 14, it is not supported. For version 15 it is optional, but +for version 16 and above, it is the default method of bootstrapping a release. + +Update +------ + +To update a release created with pkgbase, simply run ``bastille update RELEASE`` as +you would with legacy releases. + +To update a thick jail, run ``bastille update TARGET`` as you would with legacy +releases. + +To update a thin jail, you must update the release that it is based on. + +Upgrade +------- + +Upgrading is not supported for releases. See ``bastille bootstrap RELEASE`` to +bootstrap the required release. + +Upgrading is supported for both thin and thick jails. Thin jails will have their +mount points adjusted, and you will need to run ``bastille etcupdate`` on them +when upgrading from a major release to a newer major release. For example, +15.0-RELEASE to 16.0-RELEASE. + +Converting to Pkgbase +--------------------- + +Thick jails that are running legacy releases will have to be converted to pkgbase +before attempting to upgrade to 16.0-RELEASE. This can be done in two ways. + +1. Enter the jail, fetch the ``pkgbasify`` script, and run it. + +.. code-block:: shell + + fetch https://github.com/FreeBSDFoundation/pkgbasify/raw/refs/heads/main/pkgbasify.lua + chmod +x pkgbasify.lua + ./pkgbasify.lua + +2. Fetch the ``pkgbasify`` script and run it from the host using ``--rootdir``. + +.. code-block:: shell + + fetch https://github.com/FreeBSDFoundation/pkgbasify/raw/refs/heads/main/pkgbasify.lua + chmod +x pkgbasify.lua + ./pkgbasify.lua --rootdir /usr/local/bastille/jails/TARGET/root + +Converting a release to pkgbase can be done the same way, but we recommend simply destroying +and re-bootstrapping it using pkgbase. This will not work if you are running thin jails +based on the release in question. In such a case, follow step 2 above. \ No newline at end of file diff --git a/docs/chapters/subcommands/bootstrap.rst b/docs/chapters/subcommands/bootstrap.rst index 7bfa8cf3..dd15818c 100644 --- a/docs/chapters/subcommands/bootstrap.rst +++ b/docs/chapters/subcommands/bootstrap.rst @@ -126,4 +126,5 @@ begin applying your template. Options: + -p | --pkgbase Bootstrap using pkgbase (15.0-RELEASE and above). -x | --debug Enable debug mode. \ No newline at end of file diff --git a/docs/chapters/upgrading.rst b/docs/chapters/upgrading.rst index 2c81d65e..d7e3dc5a 100644 --- a/docs/chapters/upgrading.rst +++ b/docs/chapters/upgrading.rst @@ -12,15 +12,14 @@ To keep releases updated, use ``bastille update RELEASE`` To keep thick jails updated, use ``bastille update TARGET`` ----------------------- -Minor Release Upgrades ----------------------- +Minor Release Upgrades - Legacy +------------------------------- -To upgrade Bastille jails for a minor release (ie; 13.1→13.2) you can do the +To upgrade Bastille jails for a minor release (ie; 13.1 > 13.2) you can do the following: Thick Jails ------------ +^^^^^^^^^^^ 1. Use ``bastille upgrade TARGET 13.2-RELEASE`` to upgrade the jail to 13.2-RELEASE @@ -31,7 +30,7 @@ Thick Jails 5. Upgrade complete! Thin Jails ----------- +^^^^^^^^^^ 1. Ensure the new release version is bootstrapped: ``bastille bootstrap 13.2-RELEASE`` 2. Update the release (optional): ``bastille update 13.2-RELEASE`` @@ -40,15 +39,14 @@ Thin Jails 5. Start the jail(s) 6. Upgrade complete! ----------------------- -Major Release Upgrades ----------------------- +Major Release Upgrades - Legacy +------------------------------- -To upgrade Bastille jails for a major release (ie; 12.4→13.2) you can do the +To upgrade Bastille jails for a major release (ie; 12.4 > 13.2) you can do the following: Thick Jails ------------ +^^^^^^^^^^^ 1. Use ``bastille upgrade TARGET 13.2-RELEASE`` to upgrade the jail to 13.2-RELEASE @@ -61,12 +59,11 @@ Thick Jails 6. Upgrade complete! Thin Jails ----------- +^^^^^^^^^^ -1. Ensure the new release version is bootstrapped and updated to the latest - patch release: ``bastille bootstrap 13.2-RELEASE`` +1. Ensure the new release version is bootstrapped: ``bastille bootstrap 13.2-RELEASE`` 2. Update the release: ``bastille update 13.2-RELEASE`` -3. Stop the jail(s) that are bound to the release being updated. +3. Stop the jail(s) that need to be updated. 4. Use ``bastille upgrade TARGET 13.2-RELEASE`` to automatically change the mount points to 13.2-RELEASE 5. Use ``bastille etcupdate bootstrap 13.2-RELEASE`` to bootstrap src for @@ -79,28 +76,102 @@ Thin Jails ``pkg upgrade -f`` within each jail (or ``bastille pkg ALL upgrade -f``) 10. Upgrade complete! ----------------------------------- +Minor Release Upgrades - Pkgbase +-------------------------------- + +To upgrade Bastille jails for a minor release (ie; 15.1 > 15.2) you can do the +following: + +Thick Jails +^^^^^^^^^^^ + +1. Use ``bastille upgrade TARGET 15.2-RELEASE`` to upgrade the jail to + 15.2-RELEASE +2. Reboot the jail ``bastille restart TARGET`` +3. Upgrade complete! + +Thin Jails +^^^^^^^^^^ + +1. Ensure the new release version is bootstrapped: ``bastille bootstrap --pkgbase 15.2-RELEASE`` +2. Update the release (optional): ``bastille update 15.2-RELEASE`` +3. Stop the jail(s) that need to be updated. +4. Use ``bastille upgrade TARGET 15.2-RELEASE`` to automatically change the mount points to 15.2-RELEASE +5. Start the jail(s) +6. Upgrade complete! + +Major Release Upgrades - Pkgbase +-------------------------------- + +To upgrade Bastille jails for a major release (ie; 15.5 > 16.0) you can do the +following: + +Thick Jails +^^^^^^^^^^^ + +1. Use ``bastille upgrade TARGET 16.0-RELEASE`` to upgrade the jail to + 16.0-RELEASE +2. Reboot the jail ``bastille restart TARGET`` +3. Force the reinstallation or upgrade of all installed packages (ABI change): + ``pkg upgrade -f`` within each jail (or ``bastille pkg ALL upgrade -f``) +4. Upgrade complete! + +Thin Jails +^^^^^^^^^^ + +1. Ensure the new release version is bootstrapped: ``bastille bootstrap 16.0-RELEASE`` +2. Update the release: ``bastille update 16.0-RELEASE`` +3. Stop the jail(s) that need to be updated. +4. Use ``bastille upgrade TARGET 16.0-RELEASE`` to automatically change the + mount points to 16.0-RELEASE +5. Use ``bastille etcupdate bootstrap 16.0-RELEASE`` to bootstrap src for + 16.0-RELEASE +6. Use ``bastille etcupdate TARGET update 16.0-RELEASE`` to update the contents + of /etc for 16.0-RELEASE +7. Use ``bastille etcupdate TARGET resolve`` to resolve any conflicts +8. Start the jail(s) +9. Force the reinstallation or upgrade of all installed packages (ABI change): + ``pkg upgrade -f`` within each jail (or ``bastille pkg ALL upgrade -f``) +10. Upgrade complete! + +Updating +-------- + +To keep jails updated with the latest security patches and base, +use the ``bastille update`` command. + +Thick Jails +^^^^^^^^^^^ + +Use ``bastille update TARGET`` to update the jail with the latest +patches and security updates. + +Thin Jails +^^^^^^^^^^ + +Use ``bastille update RELEASE`` to update the release that any thin jails +are based on with the latest patches and security updates. + Revert Upgrade / Downgrade Process ---------------------------------- -The downgrade process (not usually needed) is similar to the upgrade process +The downgrade process (not usually needed) is similar to the upgrade process, only in reverse. Thick Jails ------------ +^^^^^^^^^^^ Thick jails should not be downgraded and is not supported in general on FreeBSD. Thin Jails ----------- +^^^^^^^^^^ Not recommended, but you can run ``bastille upgrade TARGET 13.1-RELEASE`` to downgrade a thin jail. Make sure to run ``bastille etcupdate TARGET update 13.1-RELEASE`` to keep the contents of /etc updated with each release. -The pkg reinstallation will also need to be repeated after the jail restarts on +The pkg re-installation will also need to be repeated after the jail restarts on the previous release. ------------- Old Releases ------------ @@ -108,10 +179,10 @@ After upgrading all jails from one release to the next you may find that you now have bootstrapped a release that is no longer used. Once you've decided that you no longer need the option to revert the change you can destroy the old release. - ``bastille list releases`` to list all bootstrapped releases. ``bastille destroy X.Y-RELEASE`` to fully delete the release, including the -cache. +cache (cache is not used with pkgbase). -``bastille destroy [-c|--no-cache] X.Y-RELEASE`` to retain the cache directory. +``bastille destroy [-c|--no-cache] X.Y-RELEASE`` to retain the cache directory +(not supported when using pkgbase). diff --git a/docs/chapters/usage.rst b/docs/chapters/usage.rst index efa46b54..f047b982 100644 --- a/docs/chapters/usage.rst +++ b/docs/chapters/usage.rst @@ -35,7 +35,7 @@ Usage rcp cp(1) files from a jail to host. rdr Redirect host port to jail port. rename Rename a jail. - restart Restart a running jail. + restart Restart a jail. service Manage services within targeted jail(s). setup Attempt to auto-configure network, firewall and storage and more... start Start a stopped jail. diff --git a/docs/index.rst b/docs/index.rst index da1c60c3..3fbb8cc2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -27,6 +27,7 @@ https://docs.bastillebsd.org. chapters/zfs-support chapters/gcp chapters/migration + chapters/pkgbase copyright diff --git a/usr/local/etc/bastille/bastille.conf.sample b/usr/local/etc/bastille/bastille.conf.sample index ef4fe1f5..a39b22ae 100644 --- a/usr/local/etc/bastille/bastille.conf.sample +++ b/usr/local/etc/bastille/bastille.conf.sample @@ -23,10 +23,28 @@ bastille_sharedir="/usr/local/share/bastille" ## default ## ports - The FreeBSD ports (3rd party applications) tree ## src - The source code to the kernel + userland ## test - The FreeBSD test suite -## this is a whitespace separated list: +## Whitespace separated list: ## bastille_bootstrap_archives="base lib32 ports src test" bastille_bootstrap_archives="base" ## default: "base" +## pkgbase package sets (used for FreeBSD 15+) +## Any set with [-dbg] can be installed with debugging +## symbols by adding '-dbg' to the package set +## base[-dbg] - Base system +## base-jail[-dbg] - Base system for jails +## devel[-dbg] - Development tools +## kernels[-dbg] - Base system kernels +## lib32[-dbg] - 32-bit compatability libraries +## minimal[-dbg] - Basic multi-user system +## minimal-jail[-dbg] - Basic multi-user jail system +## optional[-dbg] - Optional base system software +## optional-jail[-dbg] - Optional base system software for jails +## src - System source code +## tests - System test suite +## Whitespace separated list: +## bastille_pkgbase_packages="base-jail lib32-dbg src" +bastille_pkgbase_packages="base-jail" ## default: "base-jail" + ## default timezone bastille_tzdata="" ## default: empty to use host's time zone diff --git a/usr/local/share/bastille/bootstrap.sh b/usr/local/share/bastille/bootstrap.sh index b6ec2c84..af3991bb 100644 --- a/usr/local/share/bastille/bootstrap.sh +++ b/usr/local/share/bastille/bootstrap.sh @@ -38,36 +38,52 @@ usage() { Options: - -x | --debug Enable debug mode. + -p | --pkgbase Bootstrap using pkgbase (15.0-RELEASE and above). + -x | --debug Enable debug mode. EOF exit 1 } -validate_release_url() { +validate_release() { + + MAJOR_VERSION=$(echo ${RELEASE} | grep -Eo '^[0-9]+') + MINOR_VERSION=$(echo ${RELEASE} | sed -E 's/^[0-9]+\.([0-9]+)-.*$/\1/') + + if [ "${PKGBASE}" -eq 1 ] && [ "${MAJOR_VERSION}" -le 14 ]; then + error_exit "[ERROR]: Pkgbase is not supported for release: ${RELEASE}" + fi + + if [ "${MAJOR_VERSION}" -ge 16 ]; then + PKGBASE=1 + fi + + if [ "${PLATFORM_OS}" != "FreeBSD" ] && [ "${PKGBASE}" -eq 1 ]; then + error_exit "[ERROR]: Pkgbase can only be used with FreeBSD releases." + fi info "\nBootstrapping release: ${RELEASE}..." ## check upstream url, else warn user if [ -n "${NAME_VERIFY}" ]; then - - RELEASE="${NAME_VERIFY}" - - info "\nFetching ${PLATFORM_OS} distfiles..." - - if ! fetch -qo /dev/null "${UPSTREAM_URL}/MANIFEST" 2>/dev/null; then - error_exit "Unable to fetch MANIFEST. See 'bootstrap urls'." - fi - # Alternate RELEASE/ARCH fetch support if [ "${OPTION}" = "--i386" ] || [ "${OPTION}" = "--32bit" ]; then ARCH="i386" RELEASE="${RELEASE}-${ARCH}" fi - bootstrap_directories - bootstrap_release - + if [ "${PKGBASE}" -eq 1 ]; then + info "\nUsing PkgBase..." + bootstrap_directories + bootstrap_pkgbase_release + elif [ "${PKGBASE}" -eq 0 ]; then + info "\nFetching ${PLATFORM_OS} distfiles..." + if ! fetch -qo /dev/null "${UPSTREAM_URL}/MANIFEST" 2>/dev/null; then + error_exit "Unable to fetch MANIFEST. See 'bootstrap urls'." + fi + bootstrap_directories + bootstrap_release + fi else usage fi @@ -194,6 +210,105 @@ bootstrap_directories() { fi } +bootstrap_pkgbase_release() { + + local abi="${PLATFORM_OS}:${MAJOR_VERSION}:${HW_MACHINE_ARCH}" + local fingerprints="${bastille_releasesdir}/${RELEASE}/usr/share/keys/pkg" + local host_fingerprintsdir="/usr/share/keys/pkg" + local release_fingerprintsdir="${bastille_releasesdir}/${RELEASE}/usr/share/keys" + if [ "${FREEBSD_BRANCH}" = "release" ]; then + local repo_name="FreeBSD-base-release-${MINOR_VERSION}" + elif [ "${FREEBSD_BRANCH}" = "current" ]; then + local repo_name="FreeBSD-base-latest" + fi + local repo_dir="${bastille_sharedir}/pkgbase" + + ## If release exists quit, else bootstrap additional packages + if [ -f "${bastille_releasesdir}/${RELEASE}/COPYRIGHT" ]; then + + ## check pkgbase package list and skip existing sets + bastille_pkgbase_packages=$(echo "${bastille_pkgbase_packages}" | sed "s/base-jail//") + + ## check if release already bootstrapped, else continue bootstrapping + if [ -z "${bastille_pkgbase_packages}" ]; then + info "\nBootstrap appears complete!" + exit 0 + else + info "\nFetching additional packages..." + fi + fi + + # Copy fingerprints into releasedir + if ! mkdir -p "${release_fingerprintsdir}"; then + error_exit "[ERROR]: Faild to create fingerprints directory." + fi + if ! cp -a "${host_fingerprintsdir}" "${release_fingerprintsdir}"; then + error_exit "[ERROR]: Failed to copy fingerprints directory." + fi + + # Ensure repo is up to date + if ! pkg --rootdir "${bastille_releasesdir}/${RELEASE}" \ + --repo-conf-dir="${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + update -r "${repo_name}"; then + error_notify "[ERROR]: Failed to update repository: ${repo_name}" + fi + + # Reset ERROR_COUNT + ERROR_COUNT="0" + + for package in ${bastille_pkgbase_packages}; do + + # Check if package set is already installed + if ! pkg --rootdir "${bastille_releasesdir}/${RELEASE}" info "FreeBSD-set-${package}" 2>/dev/null; then + # Install package set + if ! pkg --rootdir "${bastille_releasesdir}/${RELEASE}" \ + --repo-conf-dir="${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + install -r "${repo_name}" \ + freebsd-set-"${package}"; then + + ERROR_COUNT=$((ERROR_COUNT + 1)) + fi + else + error_continue "[ERROR]: Package set already installed: ${package}" + fi + done + + # Cleanup if failed + if [ "${ERROR_COUNT}" -ne "0" ]; then + ## perform cleanup only for stale/empty directories on failure + if checkyesno bastille_zfs_enable; then + if [ -n "${bastille_zfs_zpool}" ]; then + if [ ! "$(ls -A "${bastille_releasesdir}/${RELEASE}")" ]; then + zfs destroy "${bastille_zfs_zpool}/${bastille_zfs_prefix}/releases/${RELEASE}" + fi + fi + elif [ -d "${bastille_releasesdir}/${RELEASE}" ]; then + if [ ! "$(ls -A "${bastille_releasesdir}/${RELEASE}")" ]; then + rm -rf "${bastille_releasesdir:?}/${RELEASE}" + fi + fi + error_exit "[ERROR]: Bootstrap failed." + else + + # Silence motd at login + touch "${bastille_releasesdir}/${RELEASE}/root/.hushlogin" + touch "${bastille_releasesdir}/${RELEASE}/usr/share/skel/dot.hushlogin" + + # Success + info "\nBootstrap successful." + echo "See 'bastille --help' for available commands." + + fi +} + bootstrap_release() { ## if release exists quit, else bootstrap additional distfiles @@ -456,17 +571,29 @@ bootstrap_template() { } # Handle options. +PKGBASE=0 while [ "$#" -gt 0 ]; do case "${1}" in -h|--help|help) usage ;; + -p|--pkgbase) + PKGBASE=1 + shift + ;; -x|--debug) enable_debug shift ;; -*) - error_exit "[ERROR]: Unknown Option: \"${1}\"" + for _opt in $(echo ${1} | sed 's/-//g' | fold -w1); do + case ${_opt} in + p) PKGBASE=1 ;; + x) enable_debug ;; + *) error_exit "[ERROR]: Unknown Option: \"${1}\"" ;; + esac + done + shift ;; *) break @@ -538,34 +665,36 @@ fi [ -n "${BASTILLE_URL_MIDNIGHTBSD}" ] && bastille_url_midnightbsd="${BASTILLE_URL_MIDNIGHTBSD}" ## Filter sane release names -case "${1}" in +case "${RELEASE}" in [2-4].[0-9]*) ## check for MidnightBSD releases name NAME_VERIFY=$(echo "${RELEASE}") UPSTREAM_URL="${bastille_url_midnightbsd}${HW_MACHINE_ARCH}/${NAME_VERIFY}" PLATFORM_OS="MidnightBSD" - validate_release_url + validate_release ;; *-CURRENT|*-current) ## check for FreeBSD releases name NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})\.[0-9](-CURRENT)$' | tr '[:lower:]' '[:upper:]') UPSTREAM_URL=$(echo "${bastille_url_freebsd}${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_VERIFY}" | sed 's/releases/snapshots/') PLATFORM_OS="FreeBSD" - validate_release_url + FREEBSD_BRANCH="current" + validate_release ;; *-RELEASE|*-release|*-RC[1-9]|*-rc[1-9]|*-BETA[1-9]) ## check for FreeBSD releases name NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([0-9]{1,2})\.[0-9](-RELEASE|-RC[1-9]|-BETA[1-9])$' | tr '[:lower:]' '[:upper:]') UPSTREAM_URL="${bastille_url_freebsd}${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_VERIFY}" PLATFORM_OS="FreeBSD" - validate_release_url + FREEBSD_BRANCH="release" + validate_release ;; *-stable-LAST|*-STABLE-last|*-stable-last|*-STABLE-LAST) ## check for HardenedBSD releases name(previous infrastructure, keep for reference) NAME_VERIFY=$(echo "${RELEASE}" | grep -iwE '^([1-9]{2,2})(-stable-last)$' | sed 's/STABLE/stable/g' | sed 's/last/LAST/g') UPSTREAM_URL="${bastille_url_hardenedbsd}${HW_MACHINE}/${HW_MACHINE_ARCH}/hardenedbsd-${NAME_VERIFY}" PLATFORM_OS="HardenedBSD" - validate_release_url + validate_release ;; *-stable-build-[0-9]*|*-STABLE-BUILD-[0-9]*) ## check for HardenedBSD(specific stable build releases) @@ -574,7 +703,7 @@ case "${1}" in NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/[0-9]\{1,2\}-stable-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_BUILD}" PLATFORM_OS="HardenedBSD" - validate_release_url + validate_release ;; *-stable-build-latest|*-stable-BUILD-LATEST|*-STABLE-BUILD-LATEST) ## check for HardenedBSD(latest stable build release) @@ -583,7 +712,7 @@ case "${1}" in NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/[0-9]\{1,2\}-stable-BUILD-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/installer/${NAME_BUILD}" PLATFORM_OS="HardenedBSD" - validate_release_url + validate_release ;; current-build-[0-9]*|CURRENT-BUILD-[0-9]*) ## check for HardenedBSD(specific current build releases) @@ -592,7 +721,7 @@ case "${1}" in NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/current-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/${NAME_BUILD}" PLATFORM_OS="HardenedBSD" - validate_release_url + validate_release ;; current-build-latest|current-BUILD-LATEST|CURRENT-BUILD-LATEST) ## check for HardenedBSD(latest current build release) @@ -601,7 +730,7 @@ case "${1}" in NAME_BUILD=$(echo "${NAME_VERIFY}" | sed 's/current-BUILD-//g') UPSTREAM_URL="${bastille_url_hardenedbsd}${NAME_RELEASE}/${HW_MACHINE}/${HW_MACHINE_ARCH}/installer/${NAME_BUILD}" PLATFORM_OS="HardenedBSD" - validate_release_url + validate_release ;; http?://*/*/*) BASTILLE_TEMPLATE_URL=${1} @@ -671,10 +800,10 @@ case "${1}" in ;; esac -case "${OPTION}" in - update) - bastille update "${RELEASE}" - ;; -esac - -echo +if [ "${PKGBASE}" -eq 0 ]; then + case "${OPTION}" in + update) + bastille update "${RELEASE}" + ;; + esac +fi \ No newline at end of file diff --git a/usr/local/share/bastille/etcupdate.sh b/usr/local/share/bastille/etcupdate.sh index ac86d985..4d85f2bd 100644 --- a/usr/local/share/bastille/etcupdate.sh +++ b/usr/local/share/bastille/etcupdate.sh @@ -43,84 +43,124 @@ EOF exit 1 } +bootstrap_etc_release_pkgbase() { + + local release="${1}" + local release_dir="${bastille_releasesdir}/${release}" + local abi="FreeBSD:${MAJOR_VERSION}:${HW_MACHINE_ARCH}" + local fingerprints="${release_dir}/usr/share/keys/pkg" + if [ "${FREEBSD_BRANCH}" = "release" ]; then + local repo_name="FreeBSD-base-release-${MINOR_VERSION}" + elif [ "${FREEBSD_BRANCH}" = "current" ]; then + local repo_name="FreeBSD-base-latest" + fi + local repo_dir="${bastille_sharedir}/pkgbase" + + if [ -d "${release_dir}" ]; then + # Update repo (pkgbase) + if ! pkg --rootdir "${release_dir}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + update -r "${repo_name}"; then + error_exit "[ERROR]: Failed to update pkg repo: ${repo_name}" + fi + # Install FreeBSD-set-src + if ! pkg --rootdir "${release_dir}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + install -r "${repo_name}" \ + freebsd-set-src; then + error_exit "[ERROR]: Failed to install package set: FreeBSD-set-src" + fi + else + error_exit "[ERROR]: Release not found: ${release}" + fi +} + bootstrap_etc_release() { - local _release="${1}" - local _current="$(sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives | awk -F': ' '{print $2}')" + local release="${1}" + local current="$(sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives | awk -F': ' '{print $2}')" - if [ ! -f "${bastille_cachedir}/${_release}/src.txz" ]; then - sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives=src - if ! bastille bootstrap "${_release}" > /dev/null; then - sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" - error_exit "[ERROR]: Failed to bootstrap etcupdate: ${_release}" + if [ ! -f "${bastille_cachedir}/${release}/src.txz" ]; then + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="src" + if ! bastille bootstrap "${release}" > /dev/null; then + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${current}" + error_exit "[ERROR]: Failed to bootstrap etcupdate: ${release}" else - sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${_current}" + sysrc -f /usr/local/etc/bastille/bastille.conf bastille_bootstrap_archives="${current}" fi fi } bootstrap_etc_tarball() { - local _release="${1}" + local release="${1}" - if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then + if [ ! -f ${bastille_cachedir}/${release}.tbz2 ]; then info "\nBuilding tarball, please wait..." - if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then - error_exit "[ERROR]: Failed to build etcupdate tarball \"${_release}.tbz2\"" + if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${release}/usr/src ${bastille_cachedir}/${release}.tbz2; then + error_exit "[ERROR]: Failed to build etcupdate tarball \"${release}.tbz2\"" else - info "\nEtcupdate bootstrap complete: ${_release}" + info "\nEtcupdate bootstrap complete: ${release}" fi - elif [ -f ${bastille_cachedir}/${_release}.tbz2 ] && [ "${FORCE}" -eq 1 ]; then - rm -f "${bastille_cachedir}/${_release}.tbz2" + elif [ -f ${bastille_cachedir}/${release}.tbz2 ] && [ "${FORCE}" -eq 1 ]; then + rm -f "${bastille_cachedir}/${release}.tbz2" info "\nBuilding tarball, please wait..." - if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${_release}/usr/src ${bastille_cachedir}/${_release}.tbz2; then - error_exit "[ERROR]: Failed to build etcupdate tarball: ${_release}.tbz2" + if ! etcupdate build -d /tmp/etcupdate -s ${bastille_releasesdir}/${release}/usr/src ${bastille_cachedir}/${release}.tbz2; then + error_exit "[ERROR]: Failed to build etcupdate tarball: ${release}.tbz2" else - info "\nEtcupdate bootstrap complete: ${_release}" + info "\nEtcupdate bootstrap complete: ${release}" fi else - info "\nEtcupdate release has already been prepared for application: ${_release}" + info "\nEtcupdate release has already been prepared for application: ${release}" fi } diff_review() { - local _jail="${1}" + local jail="${1}" if [ "${DRY_RUN}" -eq 1 ]; then error_exit "[ERROR]: diff mode does not support [-d|--dryrun]" fi echo "Running: etcupdate --diff mode" - etcupdate diff -D "${bastille_jailsdir}/${_jail}/root" + etcupdate diff -D "${bastille_jailsdir}/${jail}/root" } resolve_conflicts() { - local _jail="${1}" + local jail="${1}" if [ "${DRY_RUN}" -eq 1 ]; then error_exit "[ERROR]: resolve mode does not support [-d|--dryrun]" fi echo "Running: etcupdate resolve" - etcupdate resolve -D "${bastille_jailsdir}/${_jail}/root" + etcupdate resolve -D "${bastille_jailsdir}/${jail}/root" } update_jail_etc() { - local _jail="${1}" - local _release="${2}" + local jail="${1}" + local release="${2}" - if [ ! -f ${bastille_cachedir}/${_release}.tbz2 ]; then + if [ ! -f ${bastille_cachedir}/${release}.tbz2 ]; then error_exit "[ERROR]: Please run 'bastille etcupdate bootstrap RELEASE' first." fi if [ "${DRY_RUN}" -eq 1 ]; then echo "Running: etcupdate update --dry-run" - etcupdate -n -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 + etcupdate -n -D "${bastille_jailsdir}/${jail}/root" -t ${bastille_cachedir}/${release}.tbz2 else echo "Running: etcupdate update" - etcupdate -D "${bastille_jailsdir}/${_jail}/root" -t ${bastille_cachedir}/${_release}.tbz2 + etcupdate -D "${bastille_jailsdir}/${jail}/root" -t ${bastille_cachedir}/${release}.tbz2 fi } @@ -173,9 +213,28 @@ while [ "$#" -gt 0 ]; do usage else RELEASE="${2}" + # Validate PKGBASE or non-PKGBASE + HW_MACHINE_ARCH=$(sysctl hw.machine_arch | awk '{ print $2 }') + MINOR_VERSION=$(echo ${RELEASE} | sed -E 's/^[0-9]+\.([0-9]+)-.*$/\1/') + MAJOR_VERSION=$(echo ${RELEASE} | grep -Eo '^[0-9]+') + if echo "${NEW_RELEASE}" | grep -oq "\-CURRENT"; then + FREEBSD_BRANCH="current" + else + FREEBSD_BRANCH="release" + fi info "\nAttempting to bootstrap etcupdate release: ${RELEASE}..." - bootstrap_etc_release "${RELEASE}" - bootstrap_etc_tarball "${RELEASE}" + if [ "${MAJOR_VERSION}" -ge 16 ] || pkg -r "${bastille_releasesdir}/${RELEASE}" which /usr/bin/uname >/dev/null 2>&1; then + PKGBASE=1 + else + PKGBASE=0 + fi + if [ "${PKGBASE}" -eq 1 ]; then + bootstrap_etc_release_pkgbase "${RELEASE}" + bootstrap_etc_tarball "${RELEASE}" + else + bootstrap_etc_release "${RELEASE}" + bootstrap_etc_tarball "${RELEASE}" + fi shift "$#" fi ;; @@ -211,6 +270,4 @@ while [ "$#" -gt 0 ]; do esac ;; esac -done - -echo \ No newline at end of file +done \ No newline at end of file diff --git a/usr/local/share/bastille/pkgbase/FreeBSD-base.conf b/usr/local/share/bastille/pkgbase/FreeBSD-base.conf new file mode 100644 index 00000000..26c62044 --- /dev/null +++ b/usr/local/share/bastille/pkgbase/FreeBSD-base.conf @@ -0,0 +1,56 @@ +FreeBSD-base-latest: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_latest", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} +FreeBSD-base-weekly: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_weekly", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} +FreeBSD-base-release-0: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_release_0", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} +FreeBSD-base-release-1: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_release_1", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} +FreeBSD-base-release-2: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_release_2", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} +FreeBSD-base-release-3: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_release_3", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} +FreeBSD-base-release-4: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_release_4", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} +FreeBSD-base-release-5: { + url: "pkg+https://pkg.FreeBSD.org/${ABI}/base_release_5", + mirror_type: "srv", + signature_type: "fingerprints", + fingerprints: "/usr/share/keys/pkg", + enabled: yes +} \ No newline at end of file diff --git a/usr/local/share/bastille/update.sh b/usr/local/share/bastille/update.sh index 9f5e258a..59490f53 100644 --- a/usr/local/share/bastille/update.sh +++ b/usr/local/share/bastille/update.sh @@ -87,6 +87,7 @@ while [ "$#" -gt 0 ]; do done TARGET="${1}" +PKGBASE=0 bastille_root_check @@ -98,13 +99,6 @@ if freebsd-version | grep -qi HBSD; then error_exit "[ERROR]: Not yet supported on HardenedBSD." fi -# Check for alternate/unsupported archs -arch_check() { - if echo "${TARGET}" | grep -w "[0-9]\{1,2\}\.[0-9]\-RELEASE\-i386"; then - ARCH_I386="1" - fi -} - jail_check() { # Check if the jail is thick and is running @@ -124,14 +118,72 @@ jail_check() { error_notify "[ERROR]: ${TARGET} is not a thick container." error_exit "See 'bastille update RELEASE' to update thin jails." fi + + # Validate update method + CURRENT_VERSION="$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null)" + MINOR_VERSION=$(echo ${CURRENT_VERSION} | sed -E 's/^[0-9]+\.([0-9]+)-.*$/\1/') + MAJOR_VERSION=$(echo ${CURRENT_VERSION} | grep -Eo '^[0-9]+') + if echo "${CURRENT_VERSION}" | grep -oq "\-CURRENT"; then + FREEBSD_BRANCH="current" + else + FREEBSD_BRANCH="release" + fi + if [ -z "${CURRENT_VERSION}" ]; then + error_exit "[ERROR]: Can't determine '${TARGET}' version." + fi + if [ "${MAJOR_VERSION}" -ge 16 ] || pkg -r "${bastille_jailsdir}/${TARGET}/root" which /usr/bin/uname > /dev/null 2>&1; then + PKGBASE=1 + fi +} + +jail_update_pkgbase() { + + local jailpath="${bastille_jailsdir}/${TARGET}/root" + local abi="FreeBSD:${MAJOR_VERSION}:${HW_MACHINE_ARCH}" + local fingerprints="${jailpath}/usr/share/keys/pkg" + if [ "${FREEBSD_BRANCH}" = "release" ]; then + local repo_name="FreeBSD-base-release-${MINOR_VERSION}" + elif [ "${FREEBSD_BRANCH}" = "current" ]; then + local repo_name="FreeBSD-base-latest" + fi + local repo_dir="${bastille_sharedir}/pkgbase" + + # Update jail + if [ -d "${jailpath}" ]; then + # Update repo (pkgbase) + if ! pkg --rootdir "${jailpath}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + update -r "${repo_name}"; then + error_exit "[ERROR]: Failed to update pkg repo: ${repo_name}" + fi + # Update jail + if ! pkg --rootdir "${jailpath}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + upgrade -r "${repo_name}"; then + error_exit "[ERROR]: Failed to upgrade jail: ${TARGET}" + fi + # Update release version (including patch level) + NEW_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) + bastille config ${TARGET} set osrelease ${NEW_VERSION} + else + error_exit "[ERROR]: Jail not found: ${TARGET}" + fi } jail_update() { - local _jailname="${1}" - local _jailpath="${bastille_jailsdir}/${TARGET}/root" - local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf" - local _workdir="${_jailpath}/var/db/freebsd-update" + local jailname="${TARGET}" + local jailpath="${bastille_jailsdir}/${TARGET}/root" + local freebsd_update_conf="${jailpath}/etc/freebsd-update.conf" + local work_dir="${jailpath}/var/db/freebsd-update" # Update a thick container if [ -d "${bastille_jailsdir}/${TARGET}" ]; then @@ -141,43 +193,105 @@ jail_update() { else env PAGER="/bin/cat" freebsd-update ${OPTION} \ --not-running-from-cron \ - -j "${_jailname}" \ - -d "${_workdir}" \ - -f "${_freebsd_update_conf}" \ + -j "${jailname}" \ + -d "${work_dir}" \ + -f "${freebsd_update_conf}" \ fetch env PAGER="/bin/cat" freebsd-update ${OPTION} \ --not-running-from-cron \ - -j "${_jailname}" \ - -d "${_workdir}" \ - -f "${_freebsd_update_conf}" \ + -j "${jailname}" \ + -d "${work_dir}" \ + -f "${freebsd_update_conf}" \ install fi + # Update release version (including patch level) + NEW_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) + bastille config ${TARGET} set osrelease ${NEW_VERSION} + fi +} + +release_check() { + + if echo "${TARGET}" | grep -w "[0-9]\{1,2\}\.[0-9]\-RELEASE\-i386"; then + ARCH_I386="1" + fi + + # Validate update method + MINOR_VERSION=$(echo ${TARGET} | sed -E 's/^[0-9]+\.([0-9]+)-.*$/\1/') + MAJOR_VERSION=$(echo ${TARGET} | grep -Eo '^[0-9]+') + if echo "${TARGET}" | grep -oq "\-CURRENT"; then + FREEBSD_BRANCH="current" + else + FREEBSD_BRANCH="release" + fi + if [ "${MAJOR_VERSION}" -ge 16 ] || pkg -r "${bastille_releasesdir}/${TARGET}" which /usr/bin/uname > /dev/null 2>&1; then + PKGBASE=1 + fi +} + +release_update_pkgbase() { + + local release_dir="${bastille_releasesdir}/${TARGET}" + local abi="FreeBSD:${MAJOR_VERSION}:${HW_MACHINE_ARCH}" + local fingerprints="${release_dir}/usr/share/keys/pkg" + if [ "${FREEBSD_BRANCH}" = "release" ]; then + local repo_name="FreeBSD-base-release-${MINOR_VERSION}" + elif [ "${FREEBSD_BRANCH}" = "current" ]; then + local repo_name="FreeBSD-base-latest" + fi + local repo_dir="${bastille_sharedir}/pkgbase" + + # Update a release base (affects child containers) + if [ -d "${release_dir}" ]; then + # Update repo (pkgbase) + if ! pkg --rootdir "${release_dir}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + update -r "${repo_name}"; then + error_exit "[ERROR]: Failed to update pkg repo: ${repo_name}" + fi + # Update release (pkgbase) + if ! pkg --rootdir "${release_dir}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + upgrade -r "${repo_name}"; then + error_exit "[ERROR]: Failed to upgrade release: ${TARGET}" + fi + else + error_notify "[ERROR]: Release not found: ${TARGET}" + error_exit "See 'bastille bootstrap RELEASE'" fi } release_update() { - local _releasepath="${bastille_releasesdir}/${TARGET}" - local _freebsd_update_conf="${_releasepath}/etc/freebsd-update.conf" - local _workdir="${_releasepath}/var/db/freebsd-update" + local release_dir="${bastille_releasesdir}/${TARGET}" + local freebsd_update_conf="${release_dir}/etc/freebsd-update.conf" + local work_dir="${release_dir}/var/db/freebsd-update" # Update a release base(affects child containers) - if [ -d "${_releasepath}" ]; then + if [ -d "${release_dir}" ]; then TARGET_TRIM="${TARGET}" if [ -n "${ARCH_I386}" ]; then TARGET_TRIM=$(echo "${TARGET}" | sed 's/-i386//') fi env PAGER="/bin/cat" freebsd-update ${OPTION} \ --not-running-from-cron \ - -b "${_releasepath}" \ - -d "${_workdir}" \ - -f "${_freebsd_update_conf}" \ + -b "${release_dir}" \ + -d "${work_dir}" \ + -f "${freebsd_update_conf}" \ fetch --currently-running "${TARGET_TRIM}" env PAGER="/bin/cat" freebsd-update ${OPTION} \ --not-running-from-cron \ - -b "${_releasepath}" \ - -d "${_workdir}" \ - -f "${_freebsd_update_conf}" \ + -b "${release_dir}" \ + -d "${work_dir}" \ + -f "${freebsd_update_conf}" \ install --currently-running "${TARGET_TRIM}" else error_exit "[ERROR]: ${TARGET} not found. See 'bastille bootstrap RELEASE'." @@ -187,9 +301,9 @@ release_update() { template_update() { # Update a template - _template_path=${bastille_templatesdir}/${BASTILLE_TEMPLATE} + template_path=${bastille_templatesdir}/${BASTILLE_TEMPLATE} - if [ -d $_template_path ]; then + if [ -d ${template_path} ]; then info "\n[${BASTILLE_TEMPLATE}]:" if ! git -C $_template_path pull; then error_exit "[ERROR]: ${BASTILLE_TEMPLATE} update unsuccessful." @@ -203,36 +317,48 @@ template_update() { templates_update() { # Update all templates - _updated_templates=0 + updated_templates=0 + if [ -d ${bastille_templatesdir} ]; then # shellcheck disable=SC2045 - for _template_path in $(ls -d ${bastille_templatesdir}/*/*); do - if [ -d $_template_path/.git ]; then - BASTILLE_TEMPLATE=$(echo "$_template_path" | awk -F / '{ print $(NF-1) "/" $NF }') + for template_path in $(ls -d ${bastille_templatesdir}/*/*); do + if [ -d $template_path/.git ]; then + BASTILLE_TEMPLATE=$(echo "$template_path" | awk -F / '{ print $(NF-1) "/" $NF }') template_update - - _updated_templates=$((_updated_templates+1)) + updated_templates=$((updated_templates+1)) fi done fi - if [ "$_updated_templates" -ne "0" ]; then - info "\n$_updated_templates templates updated." + # Verify template updates + if [ "$updated_templates" -ne "0" ]; then + info "\n$updated_templates templates updated." else error_exit "[ERROR]: No templates found. See 'bastille bootstrap'." fi } +# Set needed variables for pkgbase +HW_MACHINE_ARCH=$(sysctl hw.machine_arch | awk '{ print $2 }') + # Check what we should update if [ "${TARGET}" = 'TEMPLATES' ]; then templates_update elif echo "${TARGET}" | grep -Eq '^[A-Za-z0-9_-]+/[A-Za-z0-9_-]+$'; then BASTILLE_TEMPLATE="${TARGET}" template_update -elif echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-RELEASE"; then - arch_check - release_update +elif echo "${TARGET}" | grep -q "[0-9]\{2\}.[0-9]-\(RELEASE\|CURRENT\)"; then + release_check + if [ "${PKGBASE}" -eq 1 ]; then + release_update_pkgbase + else + release_update + fi else jail_check - jail_update "${TARGET}" + if [ "${PKGBASE}" -eq 1 ]; then + jail_update_pkgbase + else + jail_update + fi fi \ No newline at end of file diff --git a/usr/local/share/bastille/upgrade.sh b/usr/local/share/bastille/upgrade.sh index 314a23b9..333844b0 100644 --- a/usr/local/share/bastille/upgrade.sh +++ b/usr/local/share/bastille/upgrade.sh @@ -88,7 +88,7 @@ if [ $# -lt 2 ] || [ $# -gt 3 ]; then fi TARGET="${1}" -NEWRELEASE="${2}" +NEW_RELEASE="${2}" bastille_root_check set_target_single "${TARGET}" @@ -104,13 +104,11 @@ fi thick_jail_check() { - local _jail="${1}" - # Validate jail state - check_target_is_running "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - bastille start "${_jail}" + check_target_is_running "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then + bastille start "${TARGET}" else - info "\n[${_jail}]:" + info "\n[${TARGET}]:" error_notify "Jail is not running." error_exit "Use [-a|--auto] to auto-start the jail." fi @@ -118,13 +116,11 @@ thick_jail_check() { thin_jail_check() { - local _jail="${1}" - # Validate jail state - check_target_is_stopped "${_jail}" || if [ "${AUTO}" -eq 1 ]; then - bastille stop "${_jail}" + check_target_is_stopped "${TARGET}" || if [ "${AUTO}" -eq 1 ]; then + bastille stop "${TARGET}" else - info "\n[${_jail}]:" + info "\n[${TARGET}]:" error_notify "Jail is running." error_exit "Use [-a|--auto] to auto-stop the jail." fi @@ -132,108 +128,181 @@ thin_jail_check() { release_check() { - local _release="${1}" - # Validate the release - if ! echo "${_release}" | grep -q "[0-9]\{2\}.[0-9]-[RELEASE,BETA,RC]"; then - error_exit "[ERROR]: ${_release} is not a valid release." + if ! echo "${NEW_RELEASE}" | grep -q "[0-9]\{2\}.[0-9]-[RELEASE,BETA,RC]"; then + error_exit "[ERROR]: ${NEW_RELEASE} is not a valid release." fi - # Exit if NEWRELEASE doesn't exist + # Exit if NEW_RELEASE doesn't exist if [ "${THIN_JAIL}" -eq 1 ]; then - if [ ! -d "${bastille_releasesdir}/${_release}" ]; then - error_notify "[ERROR]: Release not found: ${_release}" - error_exit "See 'bastille bootstrap ${_release} to bootstrap the release." + if [ ! -d "${bastille_releasesdir}/${NEW_RELEASE}" ]; then + error_notify "[ERROR]: Release not found: ${NEW_RELEASE}" + error_exit "See 'bastille bootstrap ${NEW_RELEASE} to bootstrap the release." fi fi } +jail_upgrade_pkgbase() { + + # Only thick jails should be targetted here + local jailpath="${bastille_jailsdir}/${TARGET}/root" + local abi="FreeBSD:${NEW_MAJOR_VERSION}:${HW_MACHINE_ARCH}" + local fingerprints="${jailpath}/usr/share/keys/pkg" + if [ "${FREEBSD_BRANCH}" = "release" ]; then + local repo_name="FreeBSD-base-release-${NEW_MINOR_VERSION}" + elif [ "${FREEBSD_BRANCH}" = "current" ]; then + local repo_name="FreeBSD-base-latest" + fi + local repo_dir="${bastille_sharedir}/pkgbase" + + info "\n[${TARGET}]:" + + if [ "${OLD_RELEASE}" = "${NEW_RELEASE}" ]; then + error_notify "[ERROR]: Jail is already running '${NEW_RELEASE}'" + error_notify "See 'bastille update TARGET' to update jail." + fi + + # Upgrade jail with pkgbase (thick only) + if [ -d "${jailpath}" ]; then + # Update repo (pkgbase) + if ! pkg --rootdir "${jailpath}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + update -r "${repo_name}"; then + error_exit "[ERROR]: Failed to update pkg repo: ${repo_name}" + fi + # Update jail + if ! pkg --rootdir "${jailpath}" \ + --repo-conf-dir "${repo_dir}" \ + -o IGNORE_OSVERSION="yes" \ + -o ABI="${abi}" \ + -o ASSUME_ALWAYS_YES="yes" \ + -o FINGERPRINTS="${fingerprints}" \ + upgrade -r "${repo_name}"; then + error_exit "[ERROR]: Failed to upgrade jail: ${TARGET}" + fi + # Update release version (including patch level) + NEW_VERSION=$(/usr/sbin/jexec -l "${TARGET}" freebsd-version 2>/dev/null) + bastille config ${TARGET} set osrelease ${NEW_VERSION} + else + error_exit "[ERROR]: Jail not found: ${TARGET}" + fi + info "\nUpgraded ${TARGET}: ${OLD_RELEASE} -> ${NEW_RELEASE}" +} + jail_upgrade() { - local _jailname="${1}" + info "\n[${TARGET}]:" - if [ "${THIN_JAIL}" -eq 1 ]; then - local _oldrelease="$(bastille config ${_jailname} get osrelease)" - else - local _oldrelease="$(jexec -l ${_jailname} freebsd-version)" - fi - local _newrelease="${2}" - local _jailpath="${bastille_jailsdir}/${_jailname}/root" - local _workdir="${_jailpath}/var/db/freebsd-update" - local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf" + local jailpath="${bastille_jailsdir}/${TARGET}/root" + local work_dir="${jailpath}/var/db/freebsd-update" + local freebsd_update_conf="${jailpath}/etc/freebsd-update.conf" # Upgrade a thin jail - if grep -qw "${bastille_jailsdir}/${_jailname}/root/.bastille" "${bastille_jailsdir}/${_jailname}/fstab"; then - if [ "${_oldrelease}" = "not set" ]; then - _oldrelease="$(grep "${bastille_releasesdir}.*\.bastille.*nullfs.*" "${bastille_jailsdir}/${_jailname}/fstab" | awk -F"/releases/" '{print $2}' | awk '{print $1}')" - fi - local _newrelease="${NEWRELEASE}" + if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then # Update "osrelease" entry inside fstab - sed -i '' "/.bastille/ s|${_oldrelease}|${_newrelease}|g" "${bastille_jailsdir}/${_jailname}/fstab" + sed -i '' "/.bastille/ s|${OLD_RELEASE}|${NEW_RELEASE}|g" "${bastille_jailsdir}/${TARGET}/fstab" # Update "osrelease" inside jail.conf using 'bastille config' - bastille config ${_jailname} set osrelease ${_newrelease} + bastille config ${TARGET} set osrelease ${NEW_RELEASE} # Start jail if AUTO=1 if [ "${AUTO}" -eq 1 ]; then - bastille start "${_jailname}" + bastille start "${TARGET}" fi - info "\nUpgraded ${_jailname}: ${_oldrelease} -> ${_newrelease}" - echo "See 'bastille etcupdate TARGET' to update /etc/rc.conf" + info "\nUpgraded ${TARGET}: ${OLD_RELEASE} -> ${NEW_RELEASE}" + echo "See 'bastille etcupdate TARGET' to update /etc" else # Upgrade a thick jail env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \ - --currently-running "${_oldrelease}" \ - -j "${_jailname}" \ - -d "${_workdir}" \ - -f "${_freebsd_update_conf}" \ - -r "${_newrelease}" upgrade + --currently-running "${OLD_RELEASE}" \ + -j "${TARGET}" \ + -d "${work_dir}" \ + -f "${freebsd_update_conf}" \ + -r "${NEW_RELEASE}" upgrade # Update "osrelease" inside jail.conf using 'bastille config' - bastille config ${_jailname} set osrelease ${_newrelease} - warn "Please run 'bastille upgrade ${_jailname} install', restart the jail, then run 'bastille upgrade ${_jailname} install' again to finish installing updates." + bastille config ${TARGET} set osrelease ${NEW_RELEASE} + warn "Please run 'bastille upgrade ${TARGET} install', restart the jail, then run 'bastille upgrade ${TARGET} install' again to finish installing updates." fi } jail_updates_install() { - local _jailname="${1}" - local _jailpath="${bastille_jailsdir}/${_jailname}/root" - local _workdir="${_jailpath}/var/db/freebsd-update" - local _freebsd_update_conf="${_jailpath}/etc/freebsd-update.conf" + local jailpath="${bastille_jailsdir}/${TARGET}/root" + local work_dir="${jailpath}/var/db/freebsd-update" + local freebsd_update_conf="${jailpath}/etc/freebsd-update.conf" + + info "\n[${TARGET}]:" # Finish installing upgrade on a thick container - if [ -d "${bastille_jailsdir}/${_jailname}" ]; then + if [ -d "${jailpath}" ]; then env PAGER="/bin/cat" freebsd-update ${OPTION} --not-running-from-cron \ - -j "${_jailname}" \ - -d "${_workdir}" \ - -f "${_freebsd_update_conf}" \ + -j "${TARGET}" \ + -d "${work_dir}" \ + -f "${freebsd_update_conf}" \ install else - error_exit "[ERROR]: ${_jailname} not found. See 'bastille bootstrap RELEASE'." + error_exit "[ERROR]: ${TARGET} not found. See 'bastille bootstrap RELEASE'." fi } -# Check if jail is thick or thin +# Set needed variables THIN_JAIL=0 +PKGBASE=0 +HW_MACHINE_ARCH=$(sysctl hw.machine_arch | awk '{ print $2 }') + +# Validate jail type (thick/thin) if grep -qw "${bastille_jailsdir}/${TARGET}/root/.bastille" "${bastille_jailsdir}/${TARGET}/fstab"; then THIN_JAIL=1 fi # Check what we should upgrade -if [ "${NEWRELEASE}" = "install" ]; then +if [ "${NEW_RELEASE}" = "install" ]; then if [ "${THIN_JAIL}" -eq 1 ]; then thin_jail_check "${TARGET}" else thick_jail_check "${TARGET}" fi - info "\n[${TARGET}]:" jail_updates_install "${TARGET}" else - release_check "${NEWRELEASE}" + release_check if [ "${THIN_JAIL}" -eq 1 ]; then thin_jail_check "${TARGET}" else thick_jail_check "${TARGET}" fi - info "\n[${TARGET}]:" - jail_upgrade "${TARGET}" "${NEWRELEASE}" + OLD_RELEASE="$(${bastille_jailsdir}/${TARGET}/root/bin/freebsd-version)" + if [ -z "${OLD_RELEASE}" ]; then + OLD_RELEASE="$(bastille config ${TARGET} get osrelease)" + fi + OLD_MINOR_VERSION=$(echo ${OLD_RELEASE} | sed -E 's/^[0-9]+\.([0-9]+)-.*$/\1/') + OLD_MAJOR_VERSION=$(echo ${OLD_RELEASE} | grep -Eo '^[0-9]+') + NEW_MINOR_VERSION=$(echo ${NEW_RELEASE} | sed -E 's/^[0-9]+\.([0-9]+)-.*$/\1/') + NEW_MAJOR_VERSION=$(echo ${NEW_RELEASE} | grep -Eo '^[0-9]+') + # Check if jail is already running NEW_RELEASE + if [ "${OLD_MAJOR_VERSION}.${OLD_MINOR_VERSION}" = "${NEW_MAJOR_VERSION}.${NEW_MINOR_VERSION}" ]; then + error_notify "[ERROR]: Jail is already running '${NEW_RELEASE}' release." + if [ "${THIN_JAIL}" -eq 1 ]; then + error_exit "See 'bastille update RELEASE' to update the release." + else + error_exit "See 'bastille update TARGET' to update the jail." + fi + fi + # Validate PKGBASE or non-PKGBASE + if echo "${NEW_RELEASE}" | grep -oq "\-CURRENT"; then + FREEBSD_BRANCH="current" + else + FREEBSD_BRANCH="release" + fi + if [ "${NEW_MAJOR_VERSION}" -ge 16 ] || pkg -r "${bastille_jailsdir}/${TARGET}/root" which /usr/bin/uname > /dev/null 2>&1; then + PKGBASE=1 + fi + # Validate THIN_JAIL+PKGBASE + if [ "${PKGBASE}" -eq 1 ] && [ "${THIN_JAIL}" -eq 0 ]; then + jail_upgrade_pkgbase + else + jail_upgrade + fi fi