provisioning tool for building opinionated architecture
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.

194 lines
6.5 KiB

10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
10 months ago
  1. #!/bin/bash
  2. function check_container_missing() {
  3. if container_exists "$CONTAINER"; then
  4. echoerr "$CONTAINER already created!"
  5. exit 1
  6. fi
  7. }
  8. function usage() {
  9. echo 'USAGE with options:'
  10. echo -e "\t\tlxc-miaou-create <CONTAINER_NAME> -o sameuser[,nesting,ssh]"
  11. }
  12. function check() {
  13. check_container_missing || return 1
  14. return 0
  15. }
  16. function set_options() {
  17. declare -a options=("$@")
  18. length=${#options[@]}
  19. if [[ "$length" -ne 0 ]]; then
  20. if [[ "$length" -ne 2 ]]; then
  21. echoerr "unrecognized options: $@" && usage && exit 30
  22. else
  23. prefix="${options[0]}"
  24. option="${options[1]}"
  25. if [[ "$prefix" == '-o' ]]; then
  26. IFS=',' read -r -a options <<<"$option"
  27. for i in ${options[@]}; do
  28. case "$i" in
  29. sameuser) OPTION_SAMEUSER=true ;;
  30. nesting) OPTION_NESTING=true ;;
  31. ssh) OPTION_SSH=true ;;
  32. *) echoerr "unrecognized options: $@" && usage && exit 32 ;;
  33. esac
  34. done
  35. # echo "OPTION_SAMEUSER=$OPTION_SAMEUSER, OPTION_NESTING=$OPTION_NESTING, OPTION_SSH=$OPTION_SSH"
  36. else
  37. echoerr "unrecognized options prefix: $prefix" && usage && exit 31
  38. fi
  39. fi
  40. shift
  41. fi
  42. }
  43. function create() {
  44. local PREFIX="miaou:create"
  45. if [[ "$OPTION_SAMEUSER" == true ]]; then
  46. miaou_user=$(whoami)
  47. fi
  48. echo -n "creating new container <$CONTAINER> based on image <$CONTAINER_RELEASE>... "
  49. bridge_gw=$(lxc network get lxdbr0 ipv4.address | cut -d'/' -f1)
  50. user_data="$(
  51. cat <<EOF
  52. #cloud-config
  53. timezone: 'Indian/Reunion'
  54. apt:
  55. preserve_sources_list: false
  56. conf: |
  57. Acquire::Retries "60";
  58. DPkg::Lock::Timeout "60";
  59. primary:
  60. - arches: [default]
  61. uri: http://debian.mithril.re/debian
  62. security:
  63. - arches: [default]
  64. uri: http://debian.mithril.re/debian-security
  65. sources_list: |
  66. # generated by miaou-cloud
  67. deb \$PRIMARY \$RELEASE main
  68. deb \$PRIMARY \$RELEASE-updates main
  69. deb \$SECURITY \$RELEASE-security main
  70. package_update: true
  71. package_upgrade: true
  72. package_reboot_if_required: true
  73. packages:
  74. - git
  75. - file
  76. - bc
  77. - bash-completion
  78. write_files:
  79. - path: /etc/sudoers.d/10-add_TOOLBOX_to_secure_path
  80. content: >
  81. Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/TOOLBOX"
  82. runcmd:
  83. - [ systemctl, mask, systemd-hostnamed.service ]
  84. - [ systemctl, disable, e2scrub_reap.service ]
  85. - [ systemctl, disable, systemd-resolved.service, --now ]
  86. - [ systemctl, reset-failed ]
  87. - [ rm, /etc/resolv.conf]
  88. - [ rm, /etc/sudoers.d/90-cloud-init-users]
  89. - "echo nameserver $bridge_gw > /etc/resolv.conf"
  90. final_message: "Container from datasource \$datasource is finally up, after \$UPTIME seconds"
  91. EOF
  92. )"
  93. lxc init local:debian/$CONTAINER_RELEASE/cloud "$CONTAINER" --config user.user-data="$user_data" -q
  94. # allow directory `SHARED` to be read-write mounted
  95. lxc config set "$CONTAINER" raw.idmap "both $(id -u) 0" -q
  96. mkdir -p "$HOME/LXD/SHARED/$CONTAINER"
  97. lxc config device add "$CONTAINER" SHARED disk source="$HOME/LXD/SHARED/$CONTAINER" path=/mnt/SHARED -q
  98. lxc config device add "$CONTAINER" TOOLBOX disk source=/TOOLBOX path=/TOOLBOX -q
  99. lxc config device add "$CONTAINER" MIAOU_BASH disk source=$(realpath /opt/miaou-bash) path=/opt/miaou-bash -q
  100. # environment variables
  101. lxc config set "$CONTAINER" environment.PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/miaou-bash/tools:/TOOLBOX -q
  102. lxc config set "$CONTAINER" environment.container lxc -q
  103. if [[ "$OPTION_NESTING" == true ]]; then
  104. lxc config set "$CONTAINER" security.nesting true -q
  105. lxc config device add "$CONTAINER" miaou disk source=/opt/miaou path=/opt/miaou -q
  106. fi
  107. lxc start "$CONTAINER" -q
  108. # initializing miaou-bash
  109. lxc exec "$CONTAINER" -- /opt/miaou-bash/init.sh
  110. # default configuration files (btm,)
  111. lxc exec "$CONTAINER" -- mkdir -p /root/.config/bottom
  112. lxc file push "$MIAOU_BASEDIR/templates/bottom/bottom.toml" "$CONTAINER/root/.config/bottom/bottom.toml" -q
  113. # purge cloud-init after success
  114. attempt=0
  115. max_attempt=10
  116. delay=0.2
  117. while ! lxc exec "$CONTAINER" -- bash -c 'systemd-run -q -p After=cloud-final.service -p Type=oneshot --no-block bash -c "\
  118. cloud-init status --wait &&\
  119. cp /var/lib/cloud/data/status.json /root/cloud-status.json &&\
  120. systemctl stop cloud-{config,final,init-local,init}.service &&\
  121. systemctl disable cloud-{config,final,init-local,init}.service &&\
  122. systemctl stop cloud-config.target cloud-init.target &&\
  123. apt-get purge -y cloud-init &&\
  124. rm -rf /var/lib/cloud && \
  125. userdel -rf debian \
  126. " 2>/dev/null '; do
  127. attempt=$((attempt++))
  128. if [[ $attempt -gt $max_attempt ]]; then
  129. echoerr "systemd unavailable after $(bc <<<"$max_attempt * $delay") seconds"
  130. exit 1
  131. else
  132. sleep $delay
  133. fi
  134. done
  135. if [[ "$OPTION_SAMEUSER" == true ]]; then
  136. if ! lxc exec "$CONTAINER" -- grep "$miaou_user" /etc/passwd; then
  137. lxc exec "$CONTAINER" -- useradd -ms /bin/bash -G sudo "$miaou_user"
  138. fi
  139. if ! lxc exec "$CONTAINER" -- passwd -S "$miaou_user" | cut -d ' ' -f2 | grep -q ^P; then
  140. shadow_passwd=$(load_yaml_from_expanded credential.shadow)
  141. shadow_remainder=$(lxc exec "$CONTAINER" -- bash -c "grep $miaou_user /etc/shadow | cut -d':' -f3-")
  142. lxc exec "$CONTAINER" -- /opt/miaou-bash/tools/append_or_replace "^$miaou_user:.*:" "$miaou_user:$shadow_passwd:$shadow_remainder" /etc/shadow >/dev/null
  143. fi
  144. fi
  145. if [[ "$OPTION_SSH" == true ]]; then
  146. lxc exec "$CONTAINER" -- /opt/miaou-bash/tools/idem_apt_install openssh-server
  147. fi
  148. if [[ "$OPTION_SSH" == true && "$OPTION_SAMEUSER" == true ]]; then
  149. lxc-miaou-enable-ssh "$CONTAINER"
  150. fi
  151. PREFIX="" echoinfo OK
  152. echo "hint: \`lxc login $CONTAINER [--env user=<USER>]\`"
  153. [[ "$OPTION_SAMEUSER" == true ]] && echo "hint: \`lxc sameuser $CONTAINER\`"
  154. true
  155. }
  156. ## MAIN
  157. . "$MIAOU_BASEDIR/lib/init.sh"
  158. OPTION_SAMEUSER=false
  159. OPTION_NESTING=false
  160. OPTION_SSH=false
  161. PREFIX="miaou"
  162. arg1_required "$@" || (usage && exit 1)
  163. readonly CONTAINER=$1
  164. readonly CONTAINER_RELEASE="bookworm"
  165. shift
  166. set_options "$@"
  167. readonly FULL_OPTIONS="$@"
  168. check
  169. create