#!/usr/bin/env miaou-bash # CONSTANTS MIAOU_IMAGE=images:debian/13 PROJECT_SANDBOX=sandbox TEMPLATE_SANDBOX=miaou-debian13-template TEMPLATE_REFRESH_DELAY='7 days' BARE_MINIMAL=false # FUNCTIONS function usage { echo "$(basename "$0") [--bare-minimal]" } function humanize_ago { local seconds=$(($(date +%s) - $(date -d "$1" +%s))) local days=$((seconds / 86400)) local hours=$(((seconds % 86400) / 3600)) local minutes=$(((seconds % 3600) / 60)) if ((days > 365)); then echo "$((days / 365)) year(s) ago" elif ((days > 30)); then echo "$((days / 30)) month(s) ago" elif ((days > 0)); then echo "$days day(s) ago" elif ((hours > 0)); then echo "$hours hour(s) ago" elif ((minutes > 0)); then echo "$minutes minute(s) ago" else echo "$seconds second(s) ago" fi } function parse_options { while [[ $# -gt 0 ]]; do case "$1" in --help | -h) usage && exit 0 ;; --bare-minimal) BARE_MINIMAL=true ;; *) if [[ ! -v CONTAINER ]]; then CONTAINER=$1 else echo >&2 "Unknown option: $1" && usage && exit 2 fi ;; esac shift done if [[ ! -v CONTAINER ]]; then usage exit 1 fi } function mount_miaou_bash { local target="$1" local options=() [[ -v 2 ]] && options+=(--project "$2") incus "${options[@]}" config device add "$target" MIAOU-BASH disk \ source="$MIAOU_BASH_DIR" path=/opt/miaou-bash readonly=true | grep -q 'Device MIAOU-BASH added' } function assign_host_zoneinfo { local target="$1" local options=() [ -v 2 ] && options+=(--project "$2") local host_zoneinfo host_zoneinfo=$(realpath /etc/localtime) echo "assign ZONEINFO from host: $host_zoneinfo" incus exec "${options[@]}" "$target" -- bash <<-EOF ln -fs "$host_zoneinfo" /etc/localtime dpkg-reconfigure -f noninteractive tzdata 2>/dev/null EOF } function build_sandbox_project { if ! incus project show $PROJECT_SANDBOX >/dev/null; then incus project create $PROJECT_SANDBOX incus --project $PROJECT_SANDBOX profile device add default root disk path=/ pool=default incus --project $PROJECT_SANDBOX profile device add default eth0 nic name=eth0 network=incusbr0 fi } function refresh_template { if incus --project "$PROJECT_SANDBOX" info "$TEMPLATE_SANDBOX" | grep '^Status: STOPPED'; then incus --project "$PROJECT_SANDBOX" start "$TEMPLATE_SANDBOX" fi script=$( cat <&2 echo MIAOU_INCUS_ERROR: actual sandboxing project, please switch back to your 'default' project builtin exit 30 fi } function assert_unique_name { if incus info "$CONTAINER" >/dev/null 2>&1; then >&2 echo "MIAOU_INCUS_ERROR: a container named <$CONTAINER> already exists!" builtin exit 31 fi } function create { if [[ "$BARE_MINIMAL" == true ]]; then incus launch "$MIAOU_IMAGE" "$CONTAINER" add_feature_minimal_debian "$CONTAINER" assign_host_zoneinfo "$CONTAINER" else if incus --project "$PROJECT_SANDBOX" info "$TEMPLATE_SANDBOX" | grep '^Status: RUNNING'; then incus --project "$PROJECT_SANDBOX" stop "$TEMPLATE_SANDBOX" fi incus --project "$PROJECT_SANDBOX" copy --instance-only "$TEMPLATE_SANDBOX" "$CONTAINER" --target-project $(incus project get-current) incus file delete "$CONTAINER/etc/machine-id" incus config unset "$CONTAINER" volatile.eth0.hwaddr incus start "$CONTAINER" fi customize_host "$CONTAINER" } # MAIN parse_options "$@" assert_not_sandboxing assert_unique_name prepare_template_for_quick_creation create echo Success