You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							195 lines
						
					
					
						
							6.7 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							195 lines
						
					
					
						
							6.7 KiB
						
					
					
				
								#!/bin/bash
							 | 
						|
								
							 | 
						|
								function check_container_missing() {
							 | 
						|
								    if container_exists "$CONTAINER"; then
							 | 
						|
								        echoerr "$CONTAINER already created!"
							 | 
						|
								        exit 1
							 | 
						|
								    fi
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function usage() {
							 | 
						|
								    echo 'USAGE with options:'
							 | 
						|
								    echo -e "\t\tlxc-miaou-create <CONTAINER_NAME> -o sameuser[,nesting,ssh]"
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function check() {
							 | 
						|
								    check_container_missing || return 1
							 | 
						|
								    return 0
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function set_options() {
							 | 
						|
								    declare -a options=("$@")
							 | 
						|
								    length=${#options[@]}
							 | 
						|
								    if [[ "$length" -ne 0 ]]; then
							 | 
						|
								        if [[ "$length" -ne 2 ]]; then
							 | 
						|
								            echoerr "unrecognized options: $@" && usage && exit 30
							 | 
						|
								        else
							 | 
						|
								            prefix="${options[0]}"
							 | 
						|
								            option="${options[1]}"
							 | 
						|
								            if [[ "$prefix" == '-o' ]]; then
							 | 
						|
								                IFS=',' read -r -a options <<<"$option"
							 | 
						|
								                for i in ${options[@]}; do
							 | 
						|
								                    case "$i" in
							 | 
						|
								                    sameuser) OPTION_SAMEUSER=true ;;
							 | 
						|
								                    nesting) OPTION_NESTING=true ;;
							 | 
						|
								                    ssh) OPTION_SSH=true ;;
							 | 
						|
								                    *) echoerr "unrecognized options: $@" && usage && exit 32 ;;
							 | 
						|
								                    esac
							 | 
						|
								                done
							 | 
						|
								                # echo "OPTION_SAMEUSER=$OPTION_SAMEUSER, OPTION_NESTING=$OPTION_NESTING, OPTION_SSH=$OPTION_SSH"
							 | 
						|
								            else
							 | 
						|
								                echoerr "unrecognized options prefix: $prefix" && usage && exit 31
							 | 
						|
								            fi
							 | 
						|
								        fi
							 | 
						|
								        shift
							 | 
						|
								    fi
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								function create() {
							 | 
						|
								    local PREFIX="miaou:create"
							 | 
						|
								
							 | 
						|
								    if [[ "$OPTION_SAMEUSER" == true ]]; then
							 | 
						|
								        miaou_user=$(whoami)
							 | 
						|
								    fi
							 | 
						|
								
							 | 
						|
								    echo -n "creating new container <$CONTAINER> based on image <$CONTAINER_RELEASE>... "
							 | 
						|
								    bridge_gw=$(lxc network get lxdbr0 ipv4.address | cut -d'/' -f1)
							 | 
						|
								    packages=(git file bc bash-completion)
							 | 
						|
								    [[ "$OPTION_SSH" == true ]] && packages+=(openssh-server)
							 | 
						|
								    packages_string=$(join ', ' "${packages[@]}")
							 | 
						|
								
							 | 
						|
								    timezone=$(cat /etc/timezone)
							 | 
						|
								    debian_repo=$(grep ^deb /etc/apt/sources.list | head -n1 | cut -d '/' -f3)
							 | 
						|
								
							 | 
						|
								    user_data="$(
							 | 
						|
								        cat <<EOF
							 | 
						|
								#cloud-config
							 | 
						|
								timezone: '$timezone'
							 | 
						|
								apt:
							 | 
						|
								    preserve_sources_list: false
							 | 
						|
								    conf: |
							 | 
						|
								        Acquire::Retries "60";
							 | 
						|
								        DPkg::Lock::Timeout "60";
							 | 
						|
								    primary:
							 | 
						|
								        -   arches: [default]
							 | 
						|
								            uri: http://$debian_repo/debian
							 | 
						|
								    security:
							 | 
						|
								        -   arches: [default]
							 | 
						|
								            uri: http://$debian_repo/debian-security
							 | 
						|
								    sources_list: |
							 | 
						|
								        # generated by miaou
							 | 
						|
								        deb \$PRIMARY \$RELEASE main
							 | 
						|
								        deb \$PRIMARY \$RELEASE-updates main
							 | 
						|
								        deb \$SECURITY \$RELEASE-security main
							 | 
						|
								package_update: true
							 | 
						|
								package_upgrade: true
							 | 
						|
								package_reboot_if_required: true
							 | 
						|
								packages: [ $packages_string ]
							 | 
						|
								write_files:
							 | 
						|
								  - path: /etc/sudoers.d/10-add_TOOLBOX_to_secure_path
							 | 
						|
								    content: >
							 | 
						|
								        Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/TOOLBOX"
							 | 
						|
								runcmd: 
							 | 
						|
								  - [ systemctl, mask, systemd-hostnamed.service ]
							 | 
						|
								  - [ systemctl, disable, e2scrub_reap.service ]
							 | 
						|
								  - [ systemctl, disable, systemd-resolved.service, --now ]
							 | 
						|
								  - [ systemctl, reset-failed ]
							 | 
						|
								  - [ rm, /etc/resolv.conf]
							 | 
						|
								  - [ rm, /etc/sudoers.d/90-cloud-init-users]
							 | 
						|
								  - "echo nameserver $bridge_gw > /etc/resolv.conf"
							 | 
						|
								final_message: "Container from datasource \$datasource is finally up, after \$UPTIME seconds"
							 | 
						|
								EOF
							 | 
						|
								    )"
							 | 
						|
								
							 | 
						|
								    lxc init local:debian/$CONTAINER_RELEASE/cloud "$CONTAINER" --config user.user-data="$user_data" -q
							 | 
						|
								
							 | 
						|
								    # allow directory `SHARED` to be read-write mounted
							 | 
						|
								    lxc config set "$CONTAINER" raw.idmap "both $(id -u) 0" -q
							 | 
						|
								    mkdir -p "$HOME/LXD/SHARED/$CONTAINER"
							 | 
						|
								
							 | 
						|
								    lxc config device add "$CONTAINER" SHARED disk source="$HOME/LXD/SHARED/$CONTAINER" path=/mnt/SHARED -q
							 | 
						|
								    lxc config device add "$CONTAINER" TOOLBOX disk source=/TOOLBOX path=/TOOLBOX readonly=true -q
							 | 
						|
								    lxc config device add "$CONTAINER" MIAOU_BASH disk source=$(realpath /opt/miaou-bash) path=/opt/miaou-bash readonly=true -q
							 | 
						|
								
							 | 
						|
								    # environment variables
							 | 
						|
								    lxc config set "$CONTAINER" environment.PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/miaou-bash/tools:/TOOLBOX -q
							 | 
						|
								    lxc config set "$CONTAINER" environment.container lxc -q
							 | 
						|
								
							 | 
						|
								    if [[ "$OPTION_NESTING" == true ]]; then
							 | 
						|
								        lxc config set "$CONTAINER" security.nesting true -q
							 | 
						|
								        lxc config device add "$CONTAINER" miaou disk source=/opt/miaou path=/opt/miaou readonly=true -q
							 | 
						|
								    fi
							 | 
						|
								
							 | 
						|
								    lxc start "$CONTAINER" -q
							 | 
						|
								
							 | 
						|
								    # initializing  miaou-bash
							 | 
						|
								    lxc exec "$CONTAINER" -- /opt/miaou-bash/init.sh
							 | 
						|
								
							 | 
						|
								    # default configuration files (btm,)
							 | 
						|
								    lxc exec "$CONTAINER" -- mkdir -p /root/.config/bottom
							 | 
						|
								    lxc file push "$MIAOU_BASEDIR/templates/bottom/bottom.toml" "$CONTAINER/root/.config/bottom/bottom.toml" -q
							 | 
						|
								
							 | 
						|
								    # purge cloud-init after success
							 | 
						|
								    attempt=0
							 | 
						|
								    max_attempt=10
							 | 
						|
								    delay=0.2
							 | 
						|
								    while ! lxc exec "$CONTAINER" -- bash -c 'systemd-run -q -p After=cloud-final.service -p Type=oneshot --no-block bash -c "\
							 | 
						|
								        cloud-init status --wait &&\
							 | 
						|
								        cp /var/lib/cloud/data/status.json /root/cloud-status.json &&\
							 | 
						|
								        systemctl stop cloud-{config,final,init-local,init}.service &&\
							 | 
						|
								        systemctl disable cloud-{config,final,init-local,init}.service &&\
							 | 
						|
								        systemctl stop cloud-config.target cloud-init.target &&\
							 | 
						|
								        apt-get purge -y cloud-init &&\
							 | 
						|
								        rm -rf /var/lib/cloud && \
							 | 
						|
								        userdel -rf debian \
							 | 
						|
								        " 2>/dev/null '; do
							 | 
						|
								        attempt=$((attempt++))
							 | 
						|
								        if [[ $attempt -gt $max_attempt ]]; then
							 | 
						|
								            echoerr "systemd unavailable after $(bc <<<"$max_attempt * $delay") seconds"
							 | 
						|
								            exit 1
							 | 
						|
								        else
							 | 
						|
								            sleep $delay
							 | 
						|
								        fi
							 | 
						|
								    done
							 | 
						|
								
							 | 
						|
								    if [[ "$OPTION_SAMEUSER" == true ]]; then
							 | 
						|
								        if ! lxc exec "$CONTAINER" -- grep "$miaou_user" /etc/passwd; then
							 | 
						|
								            lxc exec "$CONTAINER" -- useradd -ms /bin/bash -G sudo "$miaou_user"
							 | 
						|
								        fi
							 | 
						|
								        if ! lxc exec "$CONTAINER" -- passwd -S "$miaou_user" | cut -d ' ' -f2 | grep -q ^P; then
							 | 
						|
								            shadow_passwd=$(load_yaml_from_expanded credential.shadow)
							 | 
						|
								            shadow_remainder=$(lxc exec "$CONTAINER" -- bash -c "grep $miaou_user /etc/shadow | cut -d':' -f3-")
							 | 
						|
								            lxc exec "$CONTAINER" -- /opt/miaou-bash/tools/append_or_replace "^$miaou_user:.*:" "$miaou_user:$shadow_passwd:$shadow_remainder" /etc/shadow >/dev/null
							 | 
						|
								        fi
							 | 
						|
								    fi
							 | 
						|
								
							 | 
						|
								    if [[ "$OPTION_SSH" == true && "$OPTION_SAMEUSER" == true ]]; then
							 | 
						|
								        #FIXME: can be fatser due to openssh-server already installed from cloud-init
							 | 
						|
								        lxc-miaou-enable-ssh "$CONTAINER" >/dev/null
							 | 
						|
								    fi
							 | 
						|
								
							 | 
						|
								    PREFIX="" echoinfo OK
							 | 
						|
								
							 | 
						|
								    echo "hint: \`lxc login $CONTAINER [--env user=<USER>]\`"
							 | 
						|
								    [[ "$OPTION_SAMEUSER" == true ]] && echo "hint: \`lxc sameuser $CONTAINER\`"
							 | 
						|
								
							 | 
						|
								    true
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								## MAIN
							 | 
						|
								. "$MIAOU_BASEDIR/lib/init.sh"
							 | 
						|
								OPTION_SAMEUSER=false
							 | 
						|
								OPTION_NESTING=false
							 | 
						|
								OPTION_SSH=false
							 | 
						|
								PREFIX="miaou"
							 | 
						|
								
							 | 
						|
								arg1_required "$@" || (usage && exit 1)
							 | 
						|
								readonly CONTAINER=$1
							 | 
						|
								readonly CONTAINER_RELEASE="bookworm"
							 | 
						|
								
							 | 
						|
								shift
							 | 
						|
								set_options "$@"
							 | 
						|
								readonly FULL_OPTIONS="$@"
							 | 
						|
								
							 | 
						|
								check
							 | 
						|
								create
							 |