turnkey.sh 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #!/usr/bin/env bash
  2. # Copyright (c) 2021-2023 tteck
  3. # Author: tteck (tteckster)
  4. # License: MIT
  5. # https://github.com/tteck/Proxmox/raw/main/LICENSE
  6. function header_info {
  7. clear
  8. cat <<"EOF"
  9. ______ __ __ __ _ _______
  10. /_ __/_ _________ / //_/__ __ __ / / | |/_/ ___/
  11. / / / // / __/ _ \/ ,< / -_) // / / /___> </ /__
  12. /_/ \_,_/_/ /_//_/_/|_|\__/\_, / /____/_/|_|\___/
  13. /___/
  14. EOF
  15. }
  16. set -eEuo pipefail
  17. shopt -s expand_aliases
  18. alias die='EXIT=$? LINE=$LINENO error_exit'
  19. trap die ERR
  20. function error_exit() {
  21. trap - ERR
  22. local DEFAULT='Unknown failure occured.'
  23. local REASON="\e[97m${1:-$DEFAULT}\e[39m"
  24. local FLAG="\e[91m[ERROR] \e[93m$EXIT@$LINE"
  25. msg "$FLAG $REASON" 1>&2
  26. [ ! -z ${CTID-} ] && cleanup_ctid
  27. exit $EXIT
  28. }
  29. function warn() {
  30. local REASON="\e[97m$1\e[39m"
  31. local FLAG="\e[93m[WARNING]\e[39m"
  32. msg "$FLAG $REASON"
  33. }
  34. function info() {
  35. local REASON="$1"
  36. local FLAG="\e[36m[INFO]\e[39m"
  37. msg "$FLAG $REASON"
  38. }
  39. function msg() {
  40. local TEXT="$1"
  41. echo -e "$TEXT"
  42. }
  43. function cleanup_ctid() {
  44. if pct status $CTID &>/dev/null; then
  45. if [ "$(pct status $CTID | awk '{print $2}')" == "running" ]; then
  46. pct stop $CTID
  47. fi
  48. pct destroy $CTID
  49. fi
  50. }
  51. # Stop Proxmox VE Monitor-All if running
  52. if systemctl is-active -q ping-instances.service; then
  53. systemctl stop ping-instances.service
  54. fi
  55. header_info
  56. whiptail --backtitle "Proxmox VE Helper Scripts" --title "TurnKey LXCs" --yesno "This will allow for the creation of one of the many TurnKey LXC Containers. Proceed?" 10 68 || exit
  57. TURNKEY_MENU=()
  58. MSG_MAX_LENGTH=0
  59. while read -r TAG ITEM; do
  60. OFFSET=2
  61. ((${#ITEM} + OFFSET > MSG_MAX_LENGTH)) && MSG_MAX_LENGTH=${#ITEM}+OFFSET
  62. TURNKEY_MENU+=("$TAG" "$ITEM " "OFF")
  63. done < <(
  64. cat <<EOF
  65. ansible Ansible
  66. core Core
  67. faveo-helpdesk Faveo Helpdesk
  68. fileserver File Server
  69. gallery Gallery
  70. gameserver Game Server
  71. gitea Gitea
  72. gitlab GitLab
  73. invoice-ninja Invoice Ninja
  74. mediaserver Media Server
  75. nextcloud Nextcloud
  76. observium Observium
  77. odoo Odoo
  78. openvpn OpenVPN
  79. owncloud ownCloud
  80. phpbb phpBB
  81. torrentserver Torrent Server
  82. wireguard WireGuard
  83. wordpress Wordpress
  84. zoneminder ZoneMinder
  85. EOF
  86. )
  87. turnkey=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "TurnKey LXCs" --radiolist "\nSelect a TurnKey LXC to create:\n" 16 $((MSG_MAX_LENGTH + 58)) 6 "${TURNKEY_MENU[@]}" 3>&1 1>&2 2>&3 | tr -d '"') || exit
  88. [ -z "$turnkey" ] && {
  89. whiptail --backtitle "Proxmox VE Helper Scripts" --title "No TurnKey LXC Selected" --msgbox "It appears that no TurnKey LXC container was selected" 10 68
  90. msg "Done"
  91. exit
  92. }
  93. # Setup script environment
  94. PASS="$(openssl rand -base64 8)"
  95. CTID=$(pvesh get /cluster/nextid)
  96. TEMPLATE_SEARCH="debian-11-turnkey-${turnkey}"
  97. PCT_OPTIONS="
  98. -features keyctl=1,nesting=1
  99. -hostname turnkey-${turnkey}
  100. -tags proxmox-helper-scripts
  101. -onboot 1
  102. -cores 2
  103. -memory 2048
  104. -password $PASS
  105. -net0 name=eth0,bridge=vmbr0,ip=dhcp
  106. -unprivileged 1
  107. "
  108. DEFAULT_PCT_OPTIONS=(
  109. -arch $(dpkg --print-architecture)
  110. )
  111. # Set the CONTENT and CONTENT_LABEL variables
  112. function select_storage() {
  113. local CLASS=$1
  114. local CONTENT
  115. local CONTENT_LABEL
  116. case $CLASS in
  117. container)
  118. CONTENT='rootdir'
  119. CONTENT_LABEL='Container'
  120. ;;
  121. template)
  122. CONTENT='vztmpl'
  123. CONTENT_LABEL='Container template'
  124. ;;
  125. *) false || die "Invalid storage class." ;;
  126. esac
  127. # Query all storage locations
  128. local -a MENU
  129. while read -r line; do
  130. local TAG=$(echo $line | awk '{print $1}')
  131. local TYPE=$(echo $line | awk '{printf "%-10s", $2}')
  132. local FREE=$(echo $line | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f | awk '{printf( "%9sB", $6)}')
  133. local ITEM=" Type: $TYPE Free: $FREE "
  134. local OFFSET=2
  135. if [[ $((${#ITEM} + $OFFSET)) -gt ${MSG_MAX_LENGTH:-} ]]; then
  136. local MSG_MAX_LENGTH=$((${#ITEM} + $OFFSET))
  137. fi
  138. MENU+=("$TAG" "$ITEM" "OFF")
  139. done < <(pvesm status -content $CONTENT | awk 'NR>1')
  140. # Select storage location
  141. if [ $((${#MENU[@]} / 3)) -eq 0 ]; then
  142. warn "'$CONTENT_LABEL' needs to be selected for at least one storage location."
  143. die "Unable to detect valid storage location."
  144. elif [ $((${#MENU[@]} / 3)) -eq 1 ]; then
  145. printf ${MENU[0]}
  146. else
  147. local STORAGE
  148. while [ -z "${STORAGE:+x}" ]; do
  149. STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
  150. "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\n\n" \
  151. 16 $(($MSG_MAX_LENGTH + 23)) 6 \
  152. "${MENU[@]}" 3>&1 1>&2 2>&3) || die "Menu aborted."
  153. done
  154. printf $STORAGE
  155. fi
  156. }
  157. # Get template storage
  158. TEMPLATE_STORAGE=$(select_storage template) || exit
  159. info "Using '$TEMPLATE_STORAGE' for template storage."
  160. # Get container storage
  161. CONTAINER_STORAGE=$(select_storage container) || exit
  162. info "Using '$CONTAINER_STORAGE' for container storage."
  163. # Update LXC template list
  164. msg "Updating LXC template list..."
  165. pveam update >/dev/null
  166. # Get LXC template string
  167. mapfile -t TEMPLATES < <(pveam available -section turnkeylinux | sed -n "s/.*\($TEMPLATE_SEARCH.*\)/\1/p" | sort -t - -k 2 -V)
  168. [ ${#TEMPLATES[@]} -gt 0 ] || die "Unable to find a template when searching for '$TEMPLATE_SEARCH'."
  169. TEMPLATE="${TEMPLATES[-1]}"
  170. # Download LXC template
  171. if ! pveam list $TEMPLATE_STORAGE | grep -q $TEMPLATE; then
  172. msg "Downloading LXC template (Patience)..."
  173. pveam download $TEMPLATE_STORAGE $TEMPLATE >/dev/null ||
  174. die "A problem occured while downloading the LXC template."
  175. fi
  176. # Create variable for 'pct' options
  177. PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
  178. [[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs $CONTAINER_STORAGE:${PCT_DISK_SIZE:-8})
  179. # Create LXC
  180. msg "Creating LXC container..."
  181. pct create $CTID ${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE} ${PCT_OPTIONS[@]} >/dev/null ||
  182. die "A problem occured while trying to create container."
  183. # Save password
  184. echo "TurnKey ${turnkey} password: ${PASS}" >>~/turnkey-${turnkey}.creds # file is located in the Proxmox root directory
  185. # Start container
  186. msg "Starting LXC Container..."
  187. pct start "$CTID"
  188. sleep 5
  189. # Get container IP
  190. set +e
  191. max_attempts=5
  192. attempt=1
  193. IP=""
  194. while [[ $attempt -le $max_attempts ]]; do
  195. IP=$(pct exec $CTID ip a show dev eth0 | grep -oP 'inet \K[^/]+')
  196. if [[ -n $IP ]]; then
  197. break
  198. else
  199. warn "Attempt $attempt: IP address not found. Pausing for 5 seconds..."
  200. sleep 5
  201. ((attempt++))
  202. fi
  203. done
  204. if [[ -z $IP ]]; then
  205. warn "Maximum number of attempts reached. IP address not found."
  206. IP="NOT FOUND"
  207. fi
  208. set -e
  209. # Start Proxmox VE Monitor-All if available
  210. if [[ -f /etc/systemd/system/ping-instances.service ]]; then
  211. systemctl start ping-instances.service
  212. fi
  213. # Success message
  214. header_info
  215. echo
  216. info "LXC container '$CTID' was successfully created, and its IP address is ${IP}."
  217. echo
  218. info "Proceed to the LXC console to complete the setup."
  219. echo
  220. info "login: root"
  221. info "password: $PASS"
  222. echo