mirror of
https://github.com/community-scripts/ProxmoxVED.git
synced 2026-02-25 05:57:26 +00:00
Cleanup
This commit is contained in:
172
misc/old_misc/alpine-install.func
Normal file
172
misc/old_misc/alpine-install.func
Normal file
@@ -0,0 +1,172 @@
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: tteck (tteckster)
|
||||
# Co-Author: MickLesk
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
apk update && apk add curl >/dev/null 2>&1
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
load_functions
|
||||
|
||||
# This function enables IPv6 if it's not disabled and sets verbose mode
|
||||
verb_ip6() {
|
||||
set_std_mode # Set STD mode based on VERBOSE
|
||||
|
||||
if [ "$IPV6_METHOD" == "disable" ]; then
|
||||
msg_info "Disabling IPv6 (this may affect some services)"
|
||||
$STD sysctl -w net.ipv6.conf.all.disable_ipv6=1
|
||||
$STD sysctl -w net.ipv6.conf.default.disable_ipv6=1
|
||||
$STD sysctl -w net.ipv6.conf.lo.disable_ipv6=1
|
||||
mkdir -p /etc/sysctl.d
|
||||
$STD tee /etc/sysctl.d/99-disable-ipv6.conf >/dev/null <<EOF
|
||||
net.ipv6.conf.all.disable_ipv6 = 1
|
||||
net.ipv6.conf.default.disable_ipv6 = 1
|
||||
net.ipv6.conf.lo.disable_ipv6 = 1
|
||||
EOF
|
||||
$STD rc-update add sysctl default
|
||||
msg_ok "Disabled IPv6"
|
||||
fi
|
||||
}
|
||||
|
||||
# This function catches errors and handles them with the error handler function
|
||||
catch_errors() {
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||
}
|
||||
|
||||
# This function handles errors
|
||||
error_handler() {
|
||||
local exit_code="$?"
|
||||
local line_number="$1"
|
||||
local command="$2"
|
||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||
echo -e "\n$error_message\n"
|
||||
}
|
||||
|
||||
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
||||
setting_up_container() {
|
||||
msg_info "Setting up Container OS"
|
||||
while [ $i -gt 0 ]; do
|
||||
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" != "" ]; then
|
||||
break
|
||||
fi
|
||||
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
||||
sleep $RETRY_EVERY
|
||||
i=$((i - 1))
|
||||
done
|
||||
|
||||
if [ "$(ip addr show | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}' | cut -d'/' -f1)" = "" ]; then
|
||||
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
|
||||
echo -e "${NETWORK}Check Network Settings"
|
||||
exit 1
|
||||
fi
|
||||
msg_ok "Set up Container OS"
|
||||
msg_ok "Network Connected: ${BL}$(ip addr show | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1 | tail -n1)${CL}"
|
||||
}
|
||||
|
||||
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
||||
network_check() {
|
||||
set +e
|
||||
trap - ERR
|
||||
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
|
||||
msg_ok "Internet Connected"
|
||||
else
|
||||
msg_error "Internet NOT Connected"
|
||||
read -r -p "Would you like to continue anyway? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
||||
else
|
||||
echo -e "${NETWORK}Check Network Settings"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
RESOLVEDIP=$(getent hosts github.com | awk '{ print $1 }')
|
||||
if [[ -z "$RESOLVEDIP" ]]; then msg_error "DNS Lookup Failure"; else msg_ok "DNS Resolved github.com to ${BL}$RESOLVEDIP${CL}"; fi
|
||||
set -e
|
||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||
}
|
||||
|
||||
# This function updates the Container OS by running apt-get update and upgrade
|
||||
update_os() {
|
||||
msg_info "Updating Container OS"
|
||||
$STD apk -U upgrade
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
msg_ok "Updated Container OS"
|
||||
}
|
||||
|
||||
# This function modifies the message of the day (motd) and SSH settings
|
||||
motd_ssh() {
|
||||
echo "export TERM='xterm-256color'" >>/root/.bashrc
|
||||
IP=$(ip -4 addr show eth0 | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
|
||||
if [ -f "/etc/os-release" ]; then
|
||||
OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||
OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||
else
|
||||
OS_NAME="Alpine Linux"
|
||||
OS_VERSION="Unknown"
|
||||
fi
|
||||
|
||||
PROFILE_FILE="/etc/profile.d/00_lxc-details.sh"
|
||||
echo "echo -e \"\"" >"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${BOLD}${APPLICATION} LXC Container${CL}"\" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${GATEWAY}${YW} Provided by: ${GN}community-scripts ORG ${YW}| GitHub: ${GN}https://github.com/community-scripts/ProxmoxVE${CL}\"" >>"$PROFILE_FILE"
|
||||
echo "echo \"\"" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${OS}${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${HOSTNAME}${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${INFO}${YW} IP Address: ${GN}\$(ip -4 addr show eth0 | awk '/inet / {print \$2}' | cut -d/ -f1 | head -n 1)${CL}\"" >>"$PROFILE_FILE"
|
||||
|
||||
# Configure SSH if enabled
|
||||
if [[ "${SSH_ROOT}" == "yes" ]]; then
|
||||
# Enable sshd service
|
||||
$STD rc-update add sshd
|
||||
# Allow root login via SSH
|
||||
sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
|
||||
# Start the sshd service
|
||||
$STD /etc/init.d/sshd start
|
||||
fi
|
||||
}
|
||||
|
||||
# Validate Timezone for some LXC's
|
||||
validate_tz() {
|
||||
[[ -f "/usr/share/zoneinfo/$1" ]]
|
||||
}
|
||||
|
||||
# This function customizes the container and enables passwordless login for the root user
|
||||
customize() {
|
||||
if [[ "$PASSWORD" == "" ]]; then
|
||||
msg_info "Customizing Container"
|
||||
passwd -d root >/dev/null 2>&1
|
||||
|
||||
# Ensure agetty is available
|
||||
apk add --no-cache --force-broken-world util-linux >/dev/null 2>&1
|
||||
|
||||
# Create persistent autologin boot script
|
||||
mkdir -p /etc/local.d
|
||||
cat <<'EOF' >/etc/local.d/autologin.start
|
||||
#!/bin/sh
|
||||
sed -i 's|^tty1::respawn:.*|tty1::respawn:/sbin/agetty --autologin root --noclear tty1 38400 linux|' /etc/inittab
|
||||
kill -HUP 1
|
||||
EOF
|
||||
touch /root/.hushlogin
|
||||
|
||||
chmod +x /etc/local.d/autologin.start
|
||||
rc-update add local >/dev/null 2>&1
|
||||
|
||||
# Apply autologin immediately for current session
|
||||
/etc/local.d/autologin.start
|
||||
|
||||
msg_ok "Customized Container"
|
||||
fi
|
||||
|
||||
echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/${app}.sh)\"" >/usr/bin/update
|
||||
chmod +x /usr/bin/update
|
||||
|
||||
if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then
|
||||
mkdir -p /root/.ssh
|
||||
echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys
|
||||
chmod 700 /root/.ssh
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
fi
|
||||
}
|
||||
130
misc/old_misc/api.func
Normal file
130
misc/old_misc/api.func
Normal file
@@ -0,0 +1,130 @@
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# Author: michelroegl-brunner
|
||||
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/LICENSE
|
||||
|
||||
post_to_api() {
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$DIAGNOSTICS" = "no" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "$RANDOM_UUID" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local API_URL="http://api.community-scripts.org/upload"
|
||||
local pve_version="not found"
|
||||
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
|
||||
|
||||
JSON_PAYLOAD=$(
|
||||
cat <<EOF
|
||||
{
|
||||
"ct_type": $CT_TYPE,
|
||||
"type":"lxc",
|
||||
"disk_size": $DISK_SIZE,
|
||||
"core_count": $CORE_COUNT,
|
||||
"ram_size": $RAM_SIZE,
|
||||
"os_type": "$var_os",
|
||||
"os_version": "$var_version",
|
||||
"nsapp": "$NSAPP",
|
||||
"method": "$METHOD",
|
||||
"pve_version": "$pve_version",
|
||||
"status": "installing",
|
||||
"random_id": "$RANDOM_UUID"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
||||
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$JSON_PAYLOAD") || true
|
||||
fi
|
||||
}
|
||||
|
||||
post_to_api_vm() {
|
||||
|
||||
if [[ ! -f /usr/local/community-scripts/diagnostics ]]; then
|
||||
return
|
||||
fi
|
||||
DIAGNOSTICS=$(grep -i "^DIAGNOSTICS=" /usr/local/community-scripts/diagnostics | awk -F'=' '{print $2}')
|
||||
if ! command -v curl &>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$DIAGNOSTICS" = "no" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -z "$RANDOM_UUID" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
local API_URL="http://api.community-scripts.org/upload"
|
||||
local pve_version="not found"
|
||||
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
|
||||
|
||||
DISK_SIZE_API=${DISK_SIZE%G}
|
||||
|
||||
JSON_PAYLOAD=$(
|
||||
cat <<EOF
|
||||
{
|
||||
"ct_type": 2,
|
||||
"type":"vm",
|
||||
"disk_size": $DISK_SIZE_API,
|
||||
"core_count": $CORE_COUNT,
|
||||
"ram_size": $RAM_SIZE,
|
||||
"os_type": "$var_os",
|
||||
"os_version": "$var_version",
|
||||
"nsapp": "$NSAPP",
|
||||
"method": "$METHOD",
|
||||
"pve_version": "$pve_version",
|
||||
"status": "installing",
|
||||
"random_id": "$RANDOM_UUID"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
||||
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$JSON_PAYLOAD") || true
|
||||
fi
|
||||
}
|
||||
|
||||
POST_UPDATE_DONE=false
|
||||
post_update_to_api() {
|
||||
|
||||
if ! command -v curl &>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ "$POST_UPDATE_DONE" = true ]; then
|
||||
return 0
|
||||
fi
|
||||
local API_URL="http://api.community-scripts.org/upload/updatestatus"
|
||||
local status="${1:-failed}"
|
||||
local error="${2:-No error message}"
|
||||
|
||||
JSON_PAYLOAD=$(
|
||||
cat <<EOF
|
||||
{
|
||||
"status": "$status",
|
||||
"error": "$error",
|
||||
"random_id": "$RANDOM_UUID"
|
||||
}
|
||||
EOF
|
||||
)
|
||||
|
||||
if [[ "$DIAGNOSTICS" == "yes" ]]; then
|
||||
RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$JSON_PAYLOAD") || true
|
||||
fi
|
||||
|
||||
POST_UPDATE_DONE=true
|
||||
}
|
||||
1439
misc/old_misc/build.func
Normal file
1439
misc/old_misc/build.func
Normal file
File diff suppressed because it is too large
Load Diff
699
misc/old_misc/config-file.func
Normal file
699
misc/old_misc/config-file.func
Normal file
@@ -0,0 +1,699 @@
|
||||
config_file() {
|
||||
CONFIG_FILE="/opt/community-scripts/.settings"
|
||||
|
||||
if [[ -f "/opt/community-scripts/${NSAPP}.conf" ]]; then
|
||||
CONFIG_FILE="/opt/community-scripts/${NSAPP}.conf"
|
||||
fi
|
||||
|
||||
if CONFIG_FILE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set absolute path to config file" 8 58 "$CONFIG_FILE" --title "CONFIG FILE" 3>&1 1>&2 2>&3); then
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
echo -e "${CROSS}${RD}Config file not found, exiting script!.${CL}"
|
||||
exit
|
||||
else
|
||||
echo -e "${INFO}${BOLD}${DGN}Using config File: ${BGN}$CONFIG_FILE${CL}"
|
||||
source "$CONFIG_FILE"
|
||||
fi
|
||||
fi
|
||||
if [[ -n "${CT_ID-}" ]]; then
|
||||
if [[ "$CT_ID" =~ ^([0-9]{3,4})-([0-9]{3,4})$ ]]; then
|
||||
MIN_ID=${BASH_REMATCH[1]}
|
||||
MAX_ID=${BASH_REMATCH[2]}
|
||||
if ((MIN_ID >= MAX_ID)); then
|
||||
msg_error "Invalid Container ID range. The first number must be smaller than the second number, was ${CT_ID}"
|
||||
exit
|
||||
fi
|
||||
|
||||
LIST_OF_IDS=$(pvesh get /cluster/resources --type vm --output-format json 2>/dev/null | grep -oP '"vmid":\s*\K\d+') || true
|
||||
if [[ -n "$LIST_OF_IDS" ]]; then
|
||||
for ((ID = MIN_ID; ID <= MAX_ID; ID++)); do
|
||||
if ! grep -q "^$ID$" <<<"$LIST_OF_IDS"; then
|
||||
CT_ID=$ID
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
||||
|
||||
elif [[ "$CT_ID" =~ ^[0-9]+$ ]]; then
|
||||
LIST_OF_IDS=$(pvesh get /cluster/resources --type vm --output-format json 2>/dev/null | grep -oP '"vmid":\s*\K\d+') || true
|
||||
if [[ -n "$LIST_OF_IDS" ]]; then
|
||||
|
||||
if ! grep -q "^$CT_ID$" <<<"$LIST_OF_IDS"; then
|
||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
||||
else
|
||||
msg_error "Container ID $CT_ID already exists"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
||||
fi
|
||||
else
|
||||
msg_error "Invalid Container ID format. Needs to be 0000-9999 or 0-9999, was ${CT_ID}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if CT_ID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 "$NEXTID" --title "CONTAINER ID" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$CT_ID" ]; then
|
||||
CT_ID="$NEXTID"
|
||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
||||
else
|
||||
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}$CT_ID${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
|
||||
fi
|
||||
if [[ -n "${CT_TYPE-}" ]]; then
|
||||
if [[ "$CT_TYPE" -eq 0 ]]; then
|
||||
CT_TYPE_DESC="Privileged"
|
||||
elif [[ "$CT_TYPE" -eq 1 ]]; then
|
||||
CT_TYPE_DESC="Unprivileged"
|
||||
else
|
||||
msg_error "Unknown setting for CT_TYPE, should be 1 or 0, was ${CT_TYPE}"
|
||||
exit
|
||||
fi
|
||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
||||
else
|
||||
if CT_TYPE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
|
||||
"1" "Unprivileged" ON \
|
||||
"0" "Privileged" OFF \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [ -n "$CT_TYPE" ]; then
|
||||
CT_TYPE_DESC="Unprivileged"
|
||||
if [ "$CT_TYPE" -eq 0 ]; then
|
||||
CT_TYPE_DESC="Privileged"
|
||||
fi
|
||||
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Container Type: ${BGN}$CT_TYPE_DESC${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${PW-}" ]]; then
|
||||
if [[ "$PW" == "none" ]]; then
|
||||
PW=""
|
||||
else
|
||||
if [[ "$PW" == *" "* ]]; then
|
||||
msg_error "Password cannot be empty"
|
||||
exit
|
||||
elif [[ ${#PW} -lt 5 ]]; then
|
||||
msg_error "Password must be at least 5 characters long"
|
||||
exit
|
||||
else
|
||||
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}"
|
||||
fi
|
||||
PW="-password $PW"
|
||||
fi
|
||||
else
|
||||
while true; do
|
||||
if PW1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nSet Root Password (needed for root ssh access)" 9 58 --title "PASSWORD (leave blank for automatic login)" 3>&1 1>&2 2>&3); then
|
||||
if [[ -n "$PW1" ]]; then
|
||||
if [[ "$PW1" == *" "* ]]; then
|
||||
whiptail --msgbox "Password cannot contain spaces. Please try again." 8 58
|
||||
elif [ ${#PW1} -lt 5 ]; then
|
||||
whiptail --msgbox "Password must be at least 5 characters long. Please try again." 8 58
|
||||
else
|
||||
if PW2=$(whiptail --backtitle "Proxmox VE Helper Scripts" --passwordbox "\nVerify Root Password" 9 58 --title "PASSWORD VERIFICATION" 3>&1 1>&2 2>&3); then
|
||||
if [[ "$PW1" == "$PW2" ]]; then
|
||||
PW="-password $PW1"
|
||||
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}********${CL}"
|
||||
break
|
||||
else
|
||||
whiptail --msgbox "Passwords do not match. Please try again." 8 58
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
else
|
||||
PW1="Automatic Login"
|
||||
PW=""
|
||||
echo -e "${VERIFYPW}${BOLD}${DGN}Root Password: ${BGN}$PW1${CL}"
|
||||
break
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ -n "${HN-}" ]]; then
|
||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||
else
|
||||
if CT_NAME=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Hostname" 8 58 "$NSAPP" --title "HOSTNAME" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$CT_NAME" ]; then
|
||||
HN="$NSAPP"
|
||||
else
|
||||
HN=$(echo "${CT_NAME,,}" | tr -d ' ')
|
||||
fi
|
||||
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}$HN${CL}"
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${DISK_SIZE-}" ]]; then
|
||||
if [[ "$DISK_SIZE" =~ ^-?[0-9]+$ ]]; then
|
||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
||||
else
|
||||
msg_error "DISK_SIZE must be an integer, was ${DISK_SIZE}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if DISK_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Disk Size in GB" 8 58 "$var_disk" --title "DISK SIZE" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$DISK_SIZE" ]; then
|
||||
DISK_SIZE="$var_disk"
|
||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
||||
else
|
||||
if ! [[ $DISK_SIZE =~ $INTEGER ]]; then
|
||||
echo -e "{INFO}${HOLD}${RD} DISK SIZE MUST BE AN INTEGER NUMBER!${CL}"
|
||||
advanced_settings
|
||||
fi
|
||||
echo -e "${DISKSIZE}${BOLD}${DGN}Disk Size: ${BGN}${DISK_SIZE} GB${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${CORE_COUNT-}" ]]; then
|
||||
if [[ "$CORE_COUNT" =~ ^-?[0-9]+$ ]]; then
|
||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
|
||||
else
|
||||
msg_error "CORE_COUNT must be an integer, was ${CORE_COUNT}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if CORE_COUNT=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate CPU Cores" 8 58 "$var_cpu" --title "CORE COUNT" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$CORE_COUNT" ]; then
|
||||
CORE_COUNT="$var_cpu"
|
||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||
else
|
||||
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}$CORE_COUNT${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${RAM_SIZE-}" ]]; then
|
||||
if [[ "$RAM_SIZE" =~ ^-?[0-9]+$ ]]; then
|
||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
||||
else
|
||||
msg_error "RAM_SIZE must be an integer, was ${RAM_SIZE}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if RAM_SIZE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Allocate RAM in MiB" 8 58 "$var_ram" --title "RAM" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$RAM_SIZE" ]; then
|
||||
RAM_SIZE="$var_ram"
|
||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
||||
else
|
||||
echo -e "${RAMSIZE}${BOLD}${DGN}RAM Size: ${BGN}${RAM_SIZE} MiB${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
IFACE_FILEPATH_LIST="/etc/network/interfaces"$'\n'$(find "/etc/network/interfaces.d/" -type f)
|
||||
BRIDGES=""
|
||||
OLD_IFS=$IFS
|
||||
IFS=$'\n'
|
||||
|
||||
for iface_filepath in ${IFACE_FILEPATH_LIST}; do
|
||||
|
||||
iface_indexes_tmpfile=$(mktemp -q -u '.iface-XXXX')
|
||||
(grep -Pn '^\s*iface' "${iface_filepath}" | cut -d':' -f1 && wc -l "${iface_filepath}" | cut -d' ' -f1) | awk 'FNR==1 {line=$0; next} {print line":"$0-1; line=$0}' >"${iface_indexes_tmpfile}" || true
|
||||
|
||||
if [ -f "${iface_indexes_tmpfile}" ]; then
|
||||
|
||||
while read -r pair; do
|
||||
start=$(echo "${pair}" | cut -d':' -f1)
|
||||
end=$(echo "${pair}" | cut -d':' -f2)
|
||||
if awk "NR >= ${start} && NR <= ${end}" "${iface_filepath}" | grep -qP '^\s*(bridge[-_](ports|stp|fd|vlan-aware|vids)|ovs_type\s+OVSBridge)\b'; then
|
||||
iface_name=$(sed "${start}q;d" "${iface_filepath}" | awk '{print $2}')
|
||||
BRIDGES="${iface_name}"$'\n'"${BRIDGES}"
|
||||
fi
|
||||
|
||||
done <"${iface_indexes_tmpfile}"
|
||||
rm -f "${iface_indexes_tmpfile}"
|
||||
fi
|
||||
|
||||
done
|
||||
IFS=$OLD_IFS
|
||||
BRIDGES=$(echo "$BRIDGES" | grep -v '^\s*$' | sort | uniq)
|
||||
|
||||
if [[ -n "${BRG-}" ]]; then
|
||||
if echo "$BRIDGES" | grep -q "${BRG}"; then
|
||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||
else
|
||||
msg_error "Bridge '${BRG}' does not exist in /etc/network/interfaces or /etc/network/interfaces.d/sdn"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
BRG=$(whiptail --backtitle "Proxmox VE Helper Scripts" --menu "Select network bridge:" 15 40 6 $(echo "$BRIDGES" | awk '{print $0, "Bridge"}') 3>&1 1>&2 2>&3)
|
||||
if [ -z "$BRG" ]; then
|
||||
exit_script
|
||||
else
|
||||
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}$BRG${CL}"
|
||||
fi
|
||||
fi
|
||||
|
||||
local ip_cidr_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$'
|
||||
local ip_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$'
|
||||
|
||||
if [[ -n ${NET-} ]]; then
|
||||
if [ "$NET" == "dhcp" ]; then
|
||||
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}DHCP${CL}"
|
||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}"
|
||||
GATE=""
|
||||
elif [[ "$NET" =~ $ip_cidr_regex ]]; then
|
||||
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}"
|
||||
if [[ -n "$GATE" ]]; then
|
||||
[[ "$GATE" =~ ",gw=" ]] && GATE="${GATE##,gw=}"
|
||||
if [[ "$GATE" =~ $ip_regex ]]; then
|
||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE${CL}"
|
||||
GATE=",gw=$GATE"
|
||||
else
|
||||
msg_error "Invalid IP Address format for Gateway. Needs to be 0.0.0.0, was ${GATE}"
|
||||
exit
|
||||
fi
|
||||
|
||||
else
|
||||
while true; do
|
||||
GATE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Enter gateway IP address" 8 58 --title "Gateway IP" 3>&1 1>&2 2>&3)
|
||||
if [ -z "$GATE1" ]; then
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Gateway IP address cannot be empty" 8 58
|
||||
elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Invalid IP address format" 8 58
|
||||
else
|
||||
GATE=",gw=$GATE1"
|
||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
elif [[ "$NET" == *-* ]]; then
|
||||
IFS="-" read -r ip_start ip_end <<<"$NET"
|
||||
|
||||
if [[ ! "$ip_start" =~ $ip_cidr_regex ]] || [[ ! "$ip_end" =~ $ip_cidr_regex ]]; then
|
||||
msg_error "Invalid IP range format, was $NET should be 0.0.0.0/0-0.0.0.0/0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ip1="${ip_start%%/*}"
|
||||
ip2="${ip_end%%/*}"
|
||||
cidr="${ip_start##*/}"
|
||||
|
||||
ip_to_int() {
|
||||
local IFS=.
|
||||
read -r i1 i2 i3 i4 <<<"$1"
|
||||
echo $(((i1 << 24) + (i2 << 16) + (i3 << 8) + i4))
|
||||
}
|
||||
|
||||
int_to_ip() {
|
||||
local ip=$1
|
||||
echo "$(((ip >> 24) & 0xFF)).$(((ip >> 16) & 0xFF)).$(((ip >> 8) & 0xFF)).$((ip & 0xFF))"
|
||||
}
|
||||
|
||||
start_int=$(ip_to_int "$ip1")
|
||||
end_int=$(ip_to_int "$ip2")
|
||||
|
||||
for ((ip_int = start_int; ip_int <= end_int; ip_int++)); do
|
||||
ip=$(int_to_ip $ip_int)
|
||||
msg_info "Checking IP: $ip"
|
||||
if ! ping -c 2 -W 1 "$ip" >/dev/null 2>&1; then
|
||||
NET="$ip/$cidr"
|
||||
msg_ok "Using free IP Address: ${BGN}$NET${CL}"
|
||||
sleep 3
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$NET" == *-* ]]; then
|
||||
msg_error "No free IP found in range"
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "$GATE" ]; then
|
||||
if [[ "$GATE" =~ $ip_regex ]]; then
|
||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE${CL}"
|
||||
GATE=",gw=$GATE"
|
||||
else
|
||||
msg_error "Invalid IP Address format for Gateway. Needs to be 0.0.0.0, was ${GATE}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
while true; do
|
||||
GATE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Enter gateway IP address" 8 58 --title "Gateway IP" 3>&1 1>&2 2>&3)
|
||||
if [ -z "$GATE1" ]; then
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Gateway IP address cannot be empty" 8 58
|
||||
elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Invalid IP address format" 8 58
|
||||
else
|
||||
GATE=",gw=$GATE1"
|
||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
msg_error "Invalid IP Address format. Needs to be 0.0.0.0/0 or a range like 10.0.0.1/24-10.0.0.10/24, was ${NET}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
while true; do
|
||||
NET=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Static IPv4 CIDR Address (/24)" 8 58 dhcp --title "IP ADDRESS" 3>&1 1>&2 2>&3)
|
||||
exit_status=$?
|
||||
if [ $exit_status -eq 0 ]; then
|
||||
if [ "$NET" = "dhcp" ]; then
|
||||
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}"
|
||||
break
|
||||
else
|
||||
if [[ "$NET" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}/([0-9]|[1-2][0-9]|3[0-2])$ ]]; then
|
||||
echo -e "${NETWORK}${BOLD}${DGN}IP Address: ${BGN}$NET${CL}"
|
||||
break
|
||||
else
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "$NET is an invalid IPv4 CIDR address. Please enter a valid IPv4 CIDR address or 'dhcp'" 8 58
|
||||
fi
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
done
|
||||
if [ "$NET" != "dhcp" ]; then
|
||||
while true; do
|
||||
GATE1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Enter gateway IP address" 8 58 --title "Gateway IP" 3>&1 1>&2 2>&3)
|
||||
if [ -z "$GATE1" ]; then
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Gateway IP address cannot be empty" 8 58
|
||||
elif [[ ! "$GATE1" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox "Invalid IP address format" 8 58
|
||||
else
|
||||
GATE=",gw=$GATE1"
|
||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}$GATE1${CL}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
GATE=""
|
||||
echo -e "${GATEWAY}${BOLD}${DGN}Gateway IP Address: ${BGN}Default${CL}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$var_os" == "alpine" ]; then
|
||||
APT_CACHER=""
|
||||
APT_CACHER_IP=""
|
||||
else
|
||||
if [[ -n "${APT_CACHER_IP-}" ]]; then
|
||||
if [[ ! $APT_CACHER_IP == "none" ]]; then
|
||||
APT_CACHER="yes"
|
||||
echo -e "${NETWORK}${BOLD}${DGN}APT-CACHER IP Address: ${BGN}$APT_CACHER_IP${CL}"
|
||||
else
|
||||
APT_CACHER=""
|
||||
echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}No${CL}"
|
||||
fi
|
||||
else
|
||||
if APT_CACHER_IP=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set APT-Cacher IP (leave blank for none)" 8 58 --title "APT-Cacher IP" 3>&1 1>&2 2>&3); then
|
||||
APT_CACHER="${APT_CACHER_IP:+yes}"
|
||||
echo -e "${NETWORK}${BOLD}${DGN}APT-Cacher IP Address: ${BGN}${APT_CACHER_IP:-Default}${CL}"
|
||||
if [[ -n $APT_CACHER_IP ]]; then
|
||||
APT_CACHER_IP="none"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${MTU-}" ]]; then
|
||||
if [[ "$MTU" =~ ^-?[0-9]+$ ]]; then
|
||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU${CL}"
|
||||
MTU=",mtu=$MTU"
|
||||
else
|
||||
msg_error "MTU must be an integer, was ${MTU}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if MTU1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Interface MTU Size (leave blank for default [The MTU of your selected vmbr, default is 1500])" 8 58 --title "MTU SIZE" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$MTU1" ]; then
|
||||
MTU1="Default"
|
||||
MTU=""
|
||||
else
|
||||
MTU=",mtu=$MTU1"
|
||||
fi
|
||||
echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}$MTU1${CL}"
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$IPV6_METHOD" == "static" ]]; then
|
||||
if [[ -n "$IPV6STATIC" ]]; then
|
||||
IP6=",ip6=${IPV6STATIC}"
|
||||
echo -e "${NETWORK}${BOLD}${DGN}IPv6 Address: ${BGN}${IPV6STATIC}${CL}"
|
||||
else
|
||||
msg_error "IPV6_METHOD is set to static but IPV6STATIC is empty"
|
||||
exit
|
||||
fi
|
||||
elif [[ "$IPV6_METHOD" == "auto" ]]; then
|
||||
IP6=",ip6=auto"
|
||||
echo -e "${NETWORK}${BOLD}${DGN}IPv6 Address: ${BGN}auto${CL}"
|
||||
else
|
||||
IP6=""
|
||||
echo -e "${NETWORK}${BOLD}${DGN}IPv6 Address: ${BGN}none${CL}"
|
||||
fi
|
||||
|
||||
if [[ -n "${SD-}" ]]; then
|
||||
if [[ "$SD" == "none" ]]; then
|
||||
SD=""
|
||||
echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}Host${CL}"
|
||||
else
|
||||
# Strip prefix if present for config file storage
|
||||
local SD_VALUE="$SD"
|
||||
[[ "$SD" =~ ^-searchdomain= ]] && SD_VALUE="${SD#-searchdomain=}"
|
||||
echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}$SD_VALUE${CL}"
|
||||
SD="-searchdomain=$SD_VALUE"
|
||||
fi
|
||||
else
|
||||
if SD=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a DNS Search Domain (leave blank for HOST)" 8 58 --title "DNS Search Domain" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$SD" ]; then
|
||||
SX=Host
|
||||
SD=""
|
||||
else
|
||||
SX=$SD
|
||||
SD="-searchdomain=$SD"
|
||||
fi
|
||||
echo -e "${SEARCH}${BOLD}${DGN}DNS Search Domain: ${BGN}$SX${CL}"
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${NS-}" ]]; then
|
||||
if [[ $NS == "none" ]]; then
|
||||
NS=""
|
||||
echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}Host${CL}"
|
||||
else
|
||||
# Strip prefix if present for config file storage
|
||||
local NS_VALUE="$NS"
|
||||
[[ "$NS" =~ ^-nameserver= ]] && NS_VALUE="${NS#-nameserver=}"
|
||||
if [[ "$NS_VALUE" =~ $ip_regex ]]; then
|
||||
echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NS_VALUE${CL}"
|
||||
NS="-nameserver=$NS_VALUE"
|
||||
else
|
||||
msg_error "Invalid IP Address format for DNS Server. Needs to be 0.0.0.0, was ${NS_VALUE}"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if NX=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a DNS Server IP (leave blank for HOST)" 8 58 --title "DNS SERVER IP" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$NX" ]; then
|
||||
NX=Host
|
||||
NS=""
|
||||
else
|
||||
NS="-nameserver=$NX"
|
||||
fi
|
||||
echo -e "${NETWORK}${BOLD}${DGN}DNS Server IP Address: ${BGN}$NX${CL}"
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${MAC-}" ]]; then
|
||||
if [[ "$MAC" == "none" ]]; then
|
||||
MAC=""
|
||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}Host${CL}"
|
||||
else
|
||||
# Strip prefix if present for config file storage
|
||||
local MAC_VALUE="$MAC"
|
||||
[[ "$MAC" =~ ^,hwaddr= ]] && MAC_VALUE="${MAC#,hwaddr=}"
|
||||
if [[ "$MAC_VALUE" =~ ^([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]{2}$ ]]; then
|
||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC_VALUE${CL}"
|
||||
MAC=",hwaddr=$MAC_VALUE"
|
||||
else
|
||||
msg_error "MAC Address must be in the format xx:xx:xx:xx:xx:xx, was ${MAC_VALUE}"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if MAC1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a MAC Address(leave blank for generated MAC)" 8 58 --title "MAC ADDRESS" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$MAC1" ]; then
|
||||
MAC1="Default"
|
||||
MAC=""
|
||||
else
|
||||
MAC=",hwaddr=$MAC1"
|
||||
echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}$MAC1${CL}"
|
||||
fi
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${VLAN-}" ]]; then
|
||||
if [[ "$VLAN" == "none" ]]; then
|
||||
VLAN=""
|
||||
echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}Host${CL}"
|
||||
else
|
||||
# Strip prefix if present for config file storage
|
||||
local VLAN_VALUE="$VLAN"
|
||||
[[ "$VLAN" =~ ^,tag= ]] && VLAN_VALUE="${VLAN#,tag=}"
|
||||
if [[ "$VLAN_VALUE" =~ ^-?[0-9]+$ ]]; then
|
||||
echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}$VLAN_VALUE${CL}"
|
||||
VLAN=",tag=$VLAN_VALUE"
|
||||
else
|
||||
msg_error "VLAN must be an integer, was ${VLAN_VALUE}"
|
||||
exit
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if VLAN1=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set a Vlan(leave blank for no VLAN)" 8 58 --title "VLAN" 3>&1 1>&2 2>&3); then
|
||||
if [ -z "$VLAN1" ]; then
|
||||
VLAN1="Default"
|
||||
VLAN=""
|
||||
else
|
||||
VLAN=",tag=$VLAN1"
|
||||
fi
|
||||
echo -e "${VLANTAG}${BOLD}${DGN}Vlan: ${BGN}$VLAN1${CL}"
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${TAGS-}" ]]; then
|
||||
if [[ "$TAGS" == *"DEFAULT"* ]]; then
|
||||
TAGS="${TAGS//DEFAULT/}"
|
||||
TAGS="${TAGS//;/}"
|
||||
TAGS="$TAGS;${var_tags:-}"
|
||||
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
|
||||
fi
|
||||
else
|
||||
TAGS="community-scripts;"
|
||||
if ADV_TAGS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Custom Tags?[If you remove all, there will be no tags!]" 8 58 "${TAGS}" --title "Advanced Tags" 3>&1 1>&2 2>&3); then
|
||||
if [ -n "${ADV_TAGS}" ]; then
|
||||
ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]')
|
||||
TAGS="${ADV_TAGS}"
|
||||
else
|
||||
TAGS=";"
|
||||
fi
|
||||
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
|
||||
else
|
||||
exit_script
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${SSH-}" ]]; then
|
||||
if [[ "$SSH" == "yes" ]]; then
|
||||
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
||||
if [[ ! -z "$SSH_AUTHORIZED_KEY" ]]; then
|
||||
echo -e "${ROOTSSH}${BOLD}${DGN}SSH Authorized Key: ${BGN}********************${CL}"
|
||||
else
|
||||
echo -e "${ROOTSSH}${BOLD}${DGN}SSH Authorized Key: ${BGN}None${CL}"
|
||||
fi
|
||||
elif [[ "$SSH" == "no" ]]; then
|
||||
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
||||
else
|
||||
msg_error "SSH needs to be 'yes' or 'no', was ${SSH}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
SSH_AUTHORIZED_KEY="$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "SSH Authorized key for root (leave empty for none)" 8 58 --title "SSH Key" 3>&1 1>&2 2>&3)"
|
||||
if [[ -z "${SSH_AUTHORIZED_KEY}" ]]; then
|
||||
SSH_AUTHORIZED_KEY=""
|
||||
fi
|
||||
if [[ "$PW" == -password* || -n "$SSH_AUTHORIZED_KEY" ]]; then
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "SSH ACCESS" --yesno "Enable Root SSH Access?" 10 58); then
|
||||
SSH="yes"
|
||||
else
|
||||
SSH="no"
|
||||
fi
|
||||
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
||||
else
|
||||
SSH="no"
|
||||
echo -e "${ROOTSSH}${BOLD}${DGN}Root SSH Access: ${BGN}$SSH${CL}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$ENABLE_FUSE" ]]; then
|
||||
if [[ "$ENABLE_FUSE" == "yes" ]]; then
|
||||
echo -e "${FUSE}${BOLD}${DGN}Enable FUSE: ${BGN}Yes${CL}"
|
||||
elif [[ "$ENABLE_FUSE" == "no" ]]; then
|
||||
echo -e "${FUSE}${BOLD}${DGN}Enable FUSE: ${BGN}No${CL}"
|
||||
else
|
||||
msg_error "Enable FUSE needs to be 'yes' or 'no', was ${ENABLE_FUSE}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "FUSE" --yesno "Enable FUSE?" 10 58); then
|
||||
ENABLE_FUSE="yes"
|
||||
else
|
||||
ENABLE_FUSE="no"
|
||||
fi
|
||||
echo -e "${FUSE}${BOLD}${DGN}Enable FUSE: ${BGN}$ENABLE_FUSE${CL}"
|
||||
fi
|
||||
|
||||
if [[ -n "$ENABLE_TUN" ]]; then
|
||||
if [[ "$ENABLE_TUN" == "yes" ]]; then
|
||||
echo -e "${FUSE}${BOLD}${DGN}Enable TUN: ${BGN}Yes${CL}"
|
||||
elif [[ "$ENABLE_TUN" == "no" ]]; then
|
||||
echo -e "${FUSE}${BOLD}${DGN}Enable TUN: ${BGN}No${CL}"
|
||||
else
|
||||
msg_error "Enable TUN needs to be 'yes' or 'no', was ${ENABLE_TUN}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "TUN" --yesno "Enable TUN?" 10 58); then
|
||||
ENABLE_TUN="yes"
|
||||
else
|
||||
ENABLE_TUN="no"
|
||||
fi
|
||||
echo -e "${FUSE}${BOLD}${DGN}Enable TUN: ${BGN}$ENABLE_TUN${CL}"
|
||||
fi
|
||||
|
||||
if [[ -n "${VERBOSE-}" ]]; then
|
||||
if [[ "$VERBOSE" == "yes" ]]; then
|
||||
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERBOSE${CL}"
|
||||
elif [[ "$VERBOSE" == "no" ]]; then
|
||||
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}No${CL}"
|
||||
else
|
||||
msg_error "Verbose Mode needs to be 'yes' or 'no', was ${VERBOSE}"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
|
||||
VERBOSE="yes"
|
||||
else
|
||||
VERBOSE="no"
|
||||
fi
|
||||
echo -e "${SEARCH}${BOLD}${DGN}Verbose Mode: ${BGN}$VERBOSE${CL}"
|
||||
fi
|
||||
|
||||
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "ADVANCED SETTINGS WITH CONFIG FILE COMPLETE" --yesno "Ready to create ${APP} LXC?" 10 58); then
|
||||
echo -e "${CREATING}${BOLD}${RD}Creating a ${APP} LXC using the above settings${CL}"
|
||||
else
|
||||
clear
|
||||
header_info
|
||||
echo -e "${INFO}${HOLD} ${GN}Using Config File on node $PVEHOST_NAME${CL}"
|
||||
config_file
|
||||
fi
|
||||
}
|
||||
452
misc/old_misc/core.func
Normal file
452
misc/old_misc/core.func
Normal file
@@ -0,0 +1,452 @@
|
||||
# Copyright (c) 2021-2025 community-scripts ORG
|
||||
# License: MIT | https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/LICENSE
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Loads core utility groups once (colors, formatting, icons, defaults).
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
[[ -n "${_CORE_FUNC_LOADED:-}" ]] && return
|
||||
_CORE_FUNC_LOADED=1
|
||||
|
||||
load_functions() {
|
||||
[[ -n "${__FUNCTIONS_LOADED:-}" ]] && return
|
||||
__FUNCTIONS_LOADED=1
|
||||
color
|
||||
formatting
|
||||
icons
|
||||
default_vars
|
||||
set_std_mode
|
||||
# add more
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Error & Signal Handling – robust, universal, subshell-safe
|
||||
# ============================================================================
|
||||
|
||||
_tool_error_hint() {
|
||||
local cmd="$1"
|
||||
local code="$2"
|
||||
case "$cmd" in
|
||||
curl)
|
||||
case "$code" in
|
||||
6) echo "Curl: Could not resolve host (DNS problem)" ;;
|
||||
7) echo "Curl: Failed to connect to host (connection refused)" ;;
|
||||
22) echo "Curl: HTTP error (404/403 etc)" ;;
|
||||
28) echo "Curl: Operation timeout" ;;
|
||||
*) echo "Curl: Unknown error ($code)" ;;
|
||||
esac
|
||||
;;
|
||||
wget)
|
||||
echo "Wget failed – URL unreachable or permission denied"
|
||||
;;
|
||||
systemctl)
|
||||
echo "Systemd unit failure – check service name and permissions"
|
||||
;;
|
||||
jq)
|
||||
echo "jq parse error – malformed JSON or missing key"
|
||||
;;
|
||||
mariadb | mysql)
|
||||
echo "MySQL/MariaDB command failed – check credentials or DB"
|
||||
;;
|
||||
unzip)
|
||||
echo "unzip failed – corrupt file or missing permission"
|
||||
;;
|
||||
tar)
|
||||
echo "tar failed – invalid format or missing binary"
|
||||
;;
|
||||
node | npm | pnpm | yarn)
|
||||
echo "Node tool failed – check version compatibility or package.json"
|
||||
;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
catch_errors() {
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sets ANSI color codes used for styled terminal output.
|
||||
# ------------------------------------------------------------------------------
|
||||
color() {
|
||||
YW=$(echo "\033[33m")
|
||||
YWB=$'\e[93m'
|
||||
BL=$(echo "\033[36m")
|
||||
RD=$(echo "\033[01;31m")
|
||||
BGN=$(echo "\033[4;92m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
DGN=$(echo "\033[32m")
|
||||
CL=$(echo "\033[m")
|
||||
}
|
||||
|
||||
# Special for spinner and colorized output via printf
|
||||
color_spinner() {
|
||||
CS_YW=$'\033[33m'
|
||||
CS_YWB=$'\033[93m'
|
||||
CS_CL=$'\033[m'
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Defines formatting helpers like tab, bold, and line reset sequences.
|
||||
# ------------------------------------------------------------------------------
|
||||
formatting() {
|
||||
BFR="\\r\\033[K"
|
||||
BOLD=$(echo "\033[1m")
|
||||
HOLD=" "
|
||||
TAB=" "
|
||||
TAB3=" "
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sets symbolic icons used throughout user feedback and prompts.
|
||||
# ------------------------------------------------------------------------------
|
||||
icons() {
|
||||
CM="${TAB}✔️${TAB}"
|
||||
CROSS="${TAB}✖️${TAB}"
|
||||
DNSOK="✔️ "
|
||||
DNSFAIL="${TAB}✖️${TAB}"
|
||||
INFO="${TAB}💡${TAB}${CL}"
|
||||
OS="${TAB}🖥️${TAB}${CL}"
|
||||
OSVERSION="${TAB}🌟${TAB}${CL}"
|
||||
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
|
||||
DISKSIZE="${TAB}💾${TAB}${CL}"
|
||||
CPUCORE="${TAB}🧠${TAB}${CL}"
|
||||
RAMSIZE="${TAB}🛠️${TAB}${CL}"
|
||||
SEARCH="${TAB}🔍${TAB}${CL}"
|
||||
VERBOSE_CROPPED="🔍${TAB}"
|
||||
VERIFYPW="${TAB}🔐${TAB}${CL}"
|
||||
CONTAINERID="${TAB}🆔${TAB}${CL}"
|
||||
HOSTNAME="${TAB}🏠${TAB}${CL}"
|
||||
BRIDGE="${TAB}🌉${TAB}${CL}"
|
||||
NETWORK="${TAB}📡${TAB}${CL}"
|
||||
GATEWAY="${TAB}🌐${TAB}${CL}"
|
||||
DISABLEIPV6="${TAB}🚫${TAB}${CL}"
|
||||
DEFAULT="${TAB}⚙️${TAB}${CL}"
|
||||
MACADDRESS="${TAB}🔗${TAB}${CL}"
|
||||
VLANTAG="${TAB}🏷️${TAB}${CL}"
|
||||
ROOTSSH="${TAB}🔑${TAB}${CL}"
|
||||
CREATING="${TAB}🚀${TAB}${CL}"
|
||||
ADVANCED="${TAB}🧩${TAB}${CL}"
|
||||
FUSE="${TAB}🗂️${TAB}${CL}"
|
||||
HOURGLASS="${TAB}⏳${TAB}"
|
||||
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sets default retry and wait variables used for system actions.
|
||||
# ------------------------------------------------------------------------------
|
||||
default_vars() {
|
||||
RETRY_NUM=10
|
||||
RETRY_EVERY=3
|
||||
i=$RETRY_NUM
|
||||
#[[ "${VAR_OS:-}" == "unknown" ]]
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Sets default verbose mode for script and os execution.
|
||||
# ------------------------------------------------------------------------------
|
||||
set_std_mode() {
|
||||
if [ "${VERBOSE:-no}" = "yes" ]; then
|
||||
STD=""
|
||||
else
|
||||
STD="silent"
|
||||
fi
|
||||
}
|
||||
|
||||
# Silent execution function
|
||||
silent() {
|
||||
"$@" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Function to download & save header files
|
||||
get_header() {
|
||||
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
||||
local app_type=${APP_TYPE:-ct}
|
||||
local header_url="https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/${app_type}/headers/${app_name}"
|
||||
local local_header_path="/usr/local/community-scripts/headers/${app_type}/${app_name}"
|
||||
|
||||
mkdir -p "$(dirname "$local_header_path")"
|
||||
|
||||
if [ ! -s "$local_header_path" ]; then
|
||||
if ! curl -fsSL "$header_url" -o "$local_header_path"; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
cat "$local_header_path" 2>/dev/null || true
|
||||
}
|
||||
|
||||
header_info() {
|
||||
local app_name=$(echo "${APP,,}" | tr -d ' ')
|
||||
local header_content
|
||||
|
||||
header_content=$(get_header "$app_name") || header_content=""
|
||||
|
||||
clear
|
||||
local term_width
|
||||
term_width=$(tput cols 2>/dev/null || echo 120)
|
||||
|
||||
if [ -n "$header_content" ]; then
|
||||
echo "$header_content"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_tput() {
|
||||
if ! command -v tput >/dev/null 2>&1; then
|
||||
if grep -qi 'alpine' /etc/os-release; then
|
||||
apk add --no-cache ncurses >/dev/null 2>&1
|
||||
elif command -v apt-get >/dev/null 2>&1; then
|
||||
apt-get update -qq >/dev/null
|
||||
apt-get install -y -qq ncurses-bin >/dev/null 2>&1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
is_alpine() {
|
||||
local os_id="${var_os:-${PCT_OSTYPE:-}}"
|
||||
|
||||
if [[ -z "$os_id" && -f /etc/os-release ]]; then
|
||||
os_id="$(
|
||||
. /etc/os-release 2>/dev/null
|
||||
echo "${ID:-}"
|
||||
)"
|
||||
fi
|
||||
|
||||
[[ "$os_id" == "alpine" ]]
|
||||
}
|
||||
|
||||
is_verbose_mode() {
|
||||
local verbose="${VERBOSE:-${var_verbose:-no}}"
|
||||
local tty_status
|
||||
if [[ -t 2 ]]; then
|
||||
tty_status="interactive"
|
||||
else
|
||||
tty_status="not-a-tty"
|
||||
fi
|
||||
[[ "$verbose" != "no" || ! -t 2 ]]
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Handles specific curl error codes and displays descriptive messages.
|
||||
# ------------------------------------------------------------------------------
|
||||
__curl_err_handler() {
|
||||
local exit_code="$1"
|
||||
local target="$2"
|
||||
local curl_msg="$3"
|
||||
|
||||
case $exit_code in
|
||||
1) msg_error "Unsupported protocol: $target" ;;
|
||||
2) msg_error "Curl init failed: $target" ;;
|
||||
3) msg_error "Malformed URL: $target" ;;
|
||||
5) msg_error "Proxy resolution failed: $target" ;;
|
||||
6) msg_error "Host resolution failed: $target" ;;
|
||||
7) msg_error "Connection failed: $target" ;;
|
||||
9) msg_error "Access denied: $target" ;;
|
||||
18) msg_error "Partial file transfer: $target" ;;
|
||||
22) msg_error "HTTP error (e.g. 400/404): $target" ;;
|
||||
23) msg_error "Write error on local system: $target" ;;
|
||||
26) msg_error "Read error from local file: $target" ;;
|
||||
28) msg_error "Timeout: $target" ;;
|
||||
35) msg_error "SSL connect error: $target" ;;
|
||||
47) msg_error "Too many redirects: $target" ;;
|
||||
51) msg_error "SSL cert verify failed: $target" ;;
|
||||
52) msg_error "Empty server response: $target" ;;
|
||||
55) msg_error "Send error: $target" ;;
|
||||
56) msg_error "Receive error: $target" ;;
|
||||
60) msg_error "SSL CA not trusted: $target" ;;
|
||||
67) msg_error "Login denied by server: $target" ;;
|
||||
78) msg_error "Remote file not found (404): $target" ;;
|
||||
*) msg_error "Curl failed with code $exit_code: $target" ;;
|
||||
esac
|
||||
|
||||
[[ -n "$curl_msg" ]] && printf "%s\n" "$curl_msg" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
fatal() {
|
||||
msg_error "$1"
|
||||
kill -INT $$
|
||||
}
|
||||
|
||||
spinner() {
|
||||
local chars=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
|
||||
local i=0
|
||||
while true; do
|
||||
local index=$((i++ % ${#chars[@]}))
|
||||
printf "\r\033[2K%s %b" "${CS_YWB}${chars[$index]}${CS_CL}" "${CS_YWB}${SPINNER_MSG:-}${CS_CL}"
|
||||
sleep 0.1
|
||||
done
|
||||
}
|
||||
|
||||
clear_line() {
|
||||
tput cr 2>/dev/null || echo -en "\r"
|
||||
tput el 2>/dev/null || echo -en "\033[K"
|
||||
}
|
||||
|
||||
stop_spinner() {
|
||||
local pid="${SPINNER_PID:-}"
|
||||
[[ -z "$pid" && -f /tmp/.spinner.pid ]] && pid=$(</tmp/.spinner.pid)
|
||||
|
||||
if [[ -n "$pid" && "$pid" =~ ^[0-9]+$ ]]; then
|
||||
if kill "$pid" 2>/dev/null; then
|
||||
sleep 0.05
|
||||
kill -9 "$pid" 2>/dev/null || true
|
||||
wait "$pid" 2>/dev/null || true
|
||||
fi
|
||||
rm -f /tmp/.spinner.pid
|
||||
fi
|
||||
|
||||
unset SPINNER_PID SPINNER_MSG
|
||||
stty sane 2>/dev/null || true
|
||||
}
|
||||
|
||||
msg_info() {
|
||||
local msg="$1"
|
||||
[[ -z "$msg" ]] && return
|
||||
|
||||
if ! declare -p MSG_INFO_SHOWN &>/dev/null || ! declare -A MSG_INFO_SHOWN &>/dev/null; then
|
||||
declare -gA MSG_INFO_SHOWN=()
|
||||
fi
|
||||
[[ -n "${MSG_INFO_SHOWN["$msg"]+x}" ]] && return
|
||||
MSG_INFO_SHOWN["$msg"]=1
|
||||
|
||||
stop_spinner
|
||||
SPINNER_MSG="$msg"
|
||||
|
||||
if is_verbose_mode || is_alpine; then
|
||||
local HOURGLASS="${TAB}⏳${TAB}"
|
||||
printf "\r\e[2K%s %b" "$HOURGLASS" "${YW}${msg}${CL}" >&2
|
||||
return
|
||||
fi
|
||||
|
||||
color_spinner
|
||||
spinner &
|
||||
SPINNER_PID=$!
|
||||
echo "$SPINNER_PID" >/tmp/.spinner.pid
|
||||
disown "$SPINNER_PID" 2>/dev/null || true
|
||||
}
|
||||
|
||||
msg_ok() {
|
||||
local msg="$1"
|
||||
[[ -z "$msg" ]] && return
|
||||
stop_spinner
|
||||
clear_line
|
||||
printf "%s %b\n" "$CM" "${GN}${msg}${CL}" >&2
|
||||
unset MSG_INFO_SHOWN["$msg"]
|
||||
}
|
||||
|
||||
msg_error() {
|
||||
stop_spinner
|
||||
local msg="$1"
|
||||
echo -e "${BFR:-} ${CROSS:-✖️} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
msg_warn() {
|
||||
stop_spinner
|
||||
local msg="$1"
|
||||
echo -e "${BFR:-} ${INFO:-ℹ️} ${YWB}${msg}${CL}"
|
||||
}
|
||||
|
||||
msg_custom() {
|
||||
local symbol="${1:-"[*]"}"
|
||||
local color="${2:-"\e[36m"}"
|
||||
local msg="${3:-}"
|
||||
[[ -z "$msg" ]] && return
|
||||
stop_spinner
|
||||
echo -e "${BFR:-} ${symbol} ${color}${msg}${CL:-\e[0m}"
|
||||
}
|
||||
|
||||
run_container_safe() {
|
||||
local ct="$1"
|
||||
shift
|
||||
local cmd="$*"
|
||||
|
||||
lxc-attach -n "$ct" -- bash -euo pipefail -c "
|
||||
trap 'echo Aborted in container; exit 130' SIGINT SIGTERM
|
||||
$cmd
|
||||
" || __handle_general_error "lxc-attach to CT $ct"
|
||||
}
|
||||
|
||||
cleanup_lxc() {
|
||||
msg_info "Cleaning up"
|
||||
|
||||
if is_alpine; then
|
||||
$STD apk cache clean || true
|
||||
rm -rf /var/cache/apk/*
|
||||
else
|
||||
$STD apt -y autoremove || true
|
||||
$STD apt -y autoclean || true
|
||||
$STD apt -y clean || true
|
||||
fi
|
||||
|
||||
# Clear temp artifacts (keep sockets/FIFOs; ignore errors)
|
||||
find /tmp /var/tmp -type f -name 'tmp*' -delete 2>/dev/null || true
|
||||
find /tmp /var/tmp -type f -name 'tempfile*' -delete 2>/dev/null || true
|
||||
|
||||
# Truncate writable log files silently (permission errors ignored)
|
||||
if command -v truncate >/dev/null 2>&1; then
|
||||
find /var/log -type f -writable -print0 2>/dev/null |
|
||||
xargs -0 -n1 truncate -s 0 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Node.js npm
|
||||
if command -v npm &>/dev/null; then $STD npm cache clean --force || true; fi
|
||||
# Node.js yarn
|
||||
if command -v yarn &>/dev/null; then $STD yarn cache clean || true; fi
|
||||
# Node.js pnpm
|
||||
if command -v pnpm &>/dev/null; then $STD pnpm store prune || true; fi
|
||||
# Go
|
||||
if command -v go &>/dev/null; then $STD go clean -cache -modcache || true; fi
|
||||
# Rust cargo
|
||||
if command -v cargo &>/dev/null; then $STD cargo clean || true; fi
|
||||
# Ruby gem
|
||||
if command -v gem &>/dev/null; then $STD gem cleanup || true; fi
|
||||
# Composer (PHP)
|
||||
if command -v composer &>/dev/null; then $STD composer clear-cache || true; fi
|
||||
|
||||
if command -v journalctl &>/dev/null; then
|
||||
$STD journalctl --vacuum-time=10m || true
|
||||
fi
|
||||
msg_ok "Cleaned"
|
||||
}
|
||||
|
||||
check_or_create_swap() {
|
||||
msg_info "Checking for active swap"
|
||||
|
||||
if swapon --noheadings --show | grep -q 'swap'; then
|
||||
msg_ok "Swap is active"
|
||||
return 0
|
||||
fi
|
||||
|
||||
msg_error "No active swap detected"
|
||||
|
||||
read -p "Do you want to create a swap file? [y/N]: " create_swap
|
||||
create_swap="${create_swap,,}" # to lowercase
|
||||
|
||||
if [[ "$create_swap" != "y" && "$create_swap" != "yes" ]]; then
|
||||
msg_info "Skipping swap file creation"
|
||||
return 1
|
||||
fi
|
||||
|
||||
read -p "Enter swap size in MB (e.g., 2048 for 2GB): " swap_size_mb
|
||||
if ! [[ "$swap_size_mb" =~ ^[0-9]+$ ]]; then
|
||||
msg_error "Invalid size input. Aborting."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local swap_file="/swapfile"
|
||||
|
||||
msg_info "Creating ${swap_size_mb}MB swap file at $swap_file"
|
||||
if dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" status=progress &&
|
||||
chmod 600 "$swap_file" &&
|
||||
mkswap "$swap_file" &&
|
||||
swapon "$swap_file"; then
|
||||
msg_ok "Swap file created and activated successfully"
|
||||
else
|
||||
msg_error "Failed to create or activate swap"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
trap 'stop_spinner' EXIT INT TERM
|
||||
385
misc/old_misc/create_lxc.sh
Normal file
385
misc/old_misc/create_lxc.sh
Normal file
@@ -0,0 +1,385 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright (c) 2021-2025 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# Co-Author: MickLesk
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
# This sets verbose mode if the global variable is set to "yes"
|
||||
# if [ "$VERBOSE" == "yes" ]; then set -x; fi
|
||||
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
load_functions
|
||||
#echo "(create-lxc.sh) Loaded core.func via curl"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
source <(wget -qO- https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
load_functions
|
||||
#echo "(create-lxc.sh) Loaded core.func via wget"
|
||||
fi
|
||||
|
||||
# This sets error handling options and defines the error_handler function to handle errors
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||
trap on_exit EXIT
|
||||
trap on_interrupt INT
|
||||
trap on_terminate TERM
|
||||
|
||||
function on_exit() {
|
||||
local exit_code="$?"
|
||||
[[ -n "${lockfile:-}" && -e "$lockfile" ]] && rm -f "$lockfile"
|
||||
exit "$exit_code"
|
||||
}
|
||||
|
||||
function error_handler() {
|
||||
local exit_code="$?"
|
||||
local line_number="$1"
|
||||
local command="$2"
|
||||
printf "\e[?25h"
|
||||
echo -e "\n${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}\n"
|
||||
exit "$exit_code"
|
||||
}
|
||||
|
||||
function on_interrupt() {
|
||||
echo -e "\n${RD}Interrupted by user (SIGINT)${CL}"
|
||||
exit 130
|
||||
}
|
||||
|
||||
function on_terminate() {
|
||||
echo -e "\n${RD}Terminated by signal (SIGTERM)${CL}"
|
||||
exit 143
|
||||
}
|
||||
|
||||
function exit_script() {
|
||||
clear
|
||||
printf "\e[?25h"
|
||||
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
|
||||
kill 0
|
||||
exit 1
|
||||
}
|
||||
|
||||
function check_storage_support() {
|
||||
local CONTENT="$1"
|
||||
local -a VALID_STORAGES=()
|
||||
while IFS= read -r line; do
|
||||
local STORAGE_NAME
|
||||
STORAGE_NAME=$(awk '{print $1}' <<<"$line")
|
||||
[[ -z "$STORAGE_NAME" ]] && continue
|
||||
VALID_STORAGES+=("$STORAGE_NAME")
|
||||
done < <(pvesm status -content "$CONTENT" 2>/dev/null | awk 'NR>1')
|
||||
|
||||
[[ ${#VALID_STORAGES[@]} -gt 0 ]]
|
||||
}
|
||||
|
||||
# This function selects a storage pool for a given content type (e.g., rootdir, vztmpl).
|
||||
function select_storage() {
|
||||
local CLASS=$1 CONTENT CONTENT_LABEL
|
||||
|
||||
case $CLASS in
|
||||
container)
|
||||
CONTENT='rootdir'
|
||||
CONTENT_LABEL='Container'
|
||||
;;
|
||||
template)
|
||||
CONTENT='vztmpl'
|
||||
CONTENT_LABEL='Container template'
|
||||
;;
|
||||
iso)
|
||||
CONTENT='iso'
|
||||
CONTENT_LABEL='ISO image'
|
||||
;;
|
||||
images)
|
||||
CONTENT='images'
|
||||
CONTENT_LABEL='VM Disk image'
|
||||
;;
|
||||
backup)
|
||||
CONTENT='backup'
|
||||
CONTENT_LABEL='Backup'
|
||||
;;
|
||||
snippets)
|
||||
CONTENT='snippets'
|
||||
CONTENT_LABEL='Snippets'
|
||||
;;
|
||||
*)
|
||||
msg_error "Invalid storage class '$CLASS'"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for preset STORAGE variable
|
||||
if [ "$CONTENT" = "rootdir" ] && [ -n "${STORAGE:-}" ]; then
|
||||
if pvesm status -content "$CONTENT" | awk 'NR>1 {print $1}' | grep -qx "$STORAGE"; then
|
||||
STORAGE_RESULT="$STORAGE"
|
||||
msg_info "Using preset storage: $STORAGE_RESULT for $CONTENT_LABEL"
|
||||
return 0
|
||||
else
|
||||
msg_error "Preset storage '$STORAGE' is not valid for content type '$CONTENT'."
|
||||
return 2
|
||||
fi
|
||||
fi
|
||||
|
||||
local -A STORAGE_MAP
|
||||
local -a MENU
|
||||
local COL_WIDTH=0
|
||||
|
||||
while read -r TAG TYPE _ TOTAL USED FREE _; do
|
||||
[[ -n "$TAG" && -n "$TYPE" ]] || continue
|
||||
local STORAGE_NAME="$TAG"
|
||||
local DISPLAY="${STORAGE_NAME} (${TYPE})"
|
||||
local USED_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$USED")
|
||||
local FREE_FMT=$(numfmt --to=iec --from-unit=K --format %.1f <<<"$FREE")
|
||||
local INFO="Free: ${FREE_FMT}B Used: ${USED_FMT}B"
|
||||
STORAGE_MAP["$DISPLAY"]="$STORAGE_NAME"
|
||||
MENU+=("$DISPLAY" "$INFO" "OFF")
|
||||
((${#DISPLAY} > COL_WIDTH)) && COL_WIDTH=${#DISPLAY}
|
||||
done < <(pvesm status -content "$CONTENT" | awk 'NR>1')
|
||||
|
||||
if [ ${#MENU[@]} -eq 0 ]; then
|
||||
msg_error "No storage found for content type '$CONTENT'."
|
||||
return 2
|
||||
fi
|
||||
|
||||
if [ $((${#MENU[@]} / 3)) -eq 1 ]; then
|
||||
STORAGE_RESULT="${STORAGE_MAP[${MENU[0]}]}"
|
||||
STORAGE_INFO="${MENU[1]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local WIDTH=$((COL_WIDTH + 42))
|
||||
while true; do
|
||||
local DISPLAY_SELECTED
|
||||
DISPLAY_SELECTED=$(whiptail --backtitle "Proxmox VE Helper Scripts" \
|
||||
--title "Storage Pools" \
|
||||
--radiolist "Which storage pool for ${CONTENT_LABEL,,}?\n(Spacebar to select)" \
|
||||
16 "$WIDTH" 6 "${MENU[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
# Cancel or ESC
|
||||
[[ $? -ne 0 ]] && exit_script
|
||||
|
||||
# Strip trailing whitespace or newline (important for storages like "storage (dir)")
|
||||
DISPLAY_SELECTED=$(sed 's/[[:space:]]*$//' <<<"$DISPLAY_SELECTED")
|
||||
|
||||
if [[ -z "$DISPLAY_SELECTED" || -z "${STORAGE_MAP[$DISPLAY_SELECTED]+_}" ]]; then
|
||||
whiptail --msgbox "No valid storage selected. Please try again." 8 58
|
||||
continue
|
||||
fi
|
||||
|
||||
STORAGE_RESULT="${STORAGE_MAP[$DISPLAY_SELECTED]}"
|
||||
for ((i = 0; i < ${#MENU[@]}; i += 3)); do
|
||||
if [[ "${MENU[$i]}" == "$DISPLAY_SELECTED" ]]; then
|
||||
STORAGE_INFO="${MENU[$i + 1]}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
return 0
|
||||
done
|
||||
}
|
||||
|
||||
# Test if required variables are set
|
||||
[[ "${CTID:-}" ]] || {
|
||||
msg_error "You need to set 'CTID' variable."
|
||||
exit 203
|
||||
}
|
||||
[[ "${PCT_OSTYPE:-}" ]] || {
|
||||
msg_error "You need to set 'PCT_OSTYPE' variable."
|
||||
exit 204
|
||||
}
|
||||
|
||||
# Test if ID is valid
|
||||
[ "$CTID" -ge "100" ] || {
|
||||
msg_error "ID cannot be less than 100."
|
||||
exit 205
|
||||
}
|
||||
|
||||
# Test if ID is in use
|
||||
if qm status "$CTID" &>/dev/null || pct status "$CTID" &>/dev/null; then
|
||||
echo -e "ID '$CTID' is already in use."
|
||||
unset CTID
|
||||
msg_error "Cannot use ID that is already in use."
|
||||
exit 206
|
||||
fi
|
||||
|
||||
# This checks for the presence of valid Container Storage and Template Storage locations
|
||||
if ! check_storage_support "rootdir"; then
|
||||
msg_error "No valid storage found for 'rootdir' [Container]"
|
||||
exit 1
|
||||
fi
|
||||
if ! check_storage_support "vztmpl"; then
|
||||
msg_error "No valid storage found for 'vztmpl' [Template]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
if select_storage template; then
|
||||
TEMPLATE_STORAGE="$STORAGE_RESULT"
|
||||
TEMPLATE_STORAGE_INFO="$STORAGE_INFO"
|
||||
msg_ok "Storage ${BL}$TEMPLATE_STORAGE${CL} ($TEMPLATE_STORAGE_INFO) [Template]"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
while true; do
|
||||
if select_storage container; then
|
||||
CONTAINER_STORAGE="$STORAGE_RESULT"
|
||||
CONTAINER_STORAGE_INFO="$STORAGE_INFO"
|
||||
msg_ok "Storage ${BL}$CONTAINER_STORAGE${CL} ($CONTAINER_STORAGE_INFO) [Container]"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Check free space on selected container storage
|
||||
STORAGE_FREE=$(pvesm status | awk -v s="$CONTAINER_STORAGE" '$1 == s { print $6 }')
|
||||
REQUIRED_KB=$((${PCT_DISK_SIZE:-8} * 1024 * 1024))
|
||||
if [ "$STORAGE_FREE" -lt "$REQUIRED_KB" ]; then
|
||||
msg_error "Not enough space on '$CONTAINER_STORAGE'. Needed: ${PCT_DISK_SIZE:-8}G."
|
||||
exit 214
|
||||
fi
|
||||
|
||||
# Check Cluster Quorum if in Cluster
|
||||
if [ -f /etc/pve/corosync.conf ]; then
|
||||
msg_info "Checking cluster quorum"
|
||||
if ! pvecm status | awk -F':' '/^Quorate/ { exit ($2 ~ /Yes/) ? 0 : 1 }'; then
|
||||
|
||||
msg_error "Cluster is not quorate. Start all nodes or configure quorum device (QDevice)."
|
||||
exit 210
|
||||
fi
|
||||
msg_ok "Cluster is quorate"
|
||||
fi
|
||||
|
||||
# Update LXC template list
|
||||
TEMPLATE_SEARCH="${PCT_OSTYPE}-${PCT_OSVERSION:-}"
|
||||
case "$PCT_OSTYPE" in
|
||||
debian | ubuntu)
|
||||
TEMPLATE_PATTERN="-standard_"
|
||||
;;
|
||||
alpine | fedora | rocky | centos)
|
||||
TEMPLATE_PATTERN="-default_"
|
||||
;;
|
||||
*)
|
||||
TEMPLATE_PATTERN=""
|
||||
;;
|
||||
esac
|
||||
|
||||
# 1. Check local templates first
|
||||
msg_info "Searching for template '$TEMPLATE_SEARCH'"
|
||||
mapfile -t TEMPLATES < <(
|
||||
pveam list "$TEMPLATE_STORAGE" |
|
||||
awk -v s="$TEMPLATE_SEARCH" -v p="$TEMPLATE_PATTERN" '$1 ~ s && $1 ~ p {print $1}' |
|
||||
sed 's/.*\///' | sort -t - -k 2 -V
|
||||
)
|
||||
|
||||
if [ ${#TEMPLATES[@]} -gt 0 ]; then
|
||||
TEMPLATE_SOURCE="local"
|
||||
else
|
||||
msg_info "No local template found, checking online repository"
|
||||
pveam update >/dev/null 2>&1
|
||||
mapfile -t TEMPLATES < <(
|
||||
pveam update >/dev/null 2>&1 &&
|
||||
pveam available -section system |
|
||||
sed -n "s/.*\($TEMPLATE_SEARCH.*$TEMPLATE_PATTERN.*\)/\1/p" |
|
||||
sort -t - -k 2 -V
|
||||
)
|
||||
TEMPLATE_SOURCE="online"
|
||||
fi
|
||||
|
||||
TEMPLATE="${TEMPLATES[-1]}"
|
||||
TEMPLATE_PATH="$(pvesm path $TEMPLATE_STORAGE:vztmpl/$TEMPLATE 2>/dev/null ||
|
||||
echo "/var/lib/vz/template/cache/$TEMPLATE")"
|
||||
msg_ok "Template ${BL}$TEMPLATE${CL} [$TEMPLATE_SOURCE]"
|
||||
|
||||
# 4. Validate template (exists & not corrupted)
|
||||
TEMPLATE_VALID=1
|
||||
|
||||
if [ ! -s "$TEMPLATE_PATH" ]; then
|
||||
TEMPLATE_VALID=0
|
||||
elif ! tar --use-compress-program=zstdcat -tf "$TEMPLATE_PATH" >/dev/null 2>&1; then
|
||||
TEMPLATE_VALID=0
|
||||
fi
|
||||
|
||||
if [ "$TEMPLATE_VALID" -eq 0 ]; then
|
||||
msg_warn "Template $TEMPLATE is missing or corrupted. Re-downloading."
|
||||
[[ -f "$TEMPLATE_PATH" ]] && rm -f "$TEMPLATE_PATH"
|
||||
for attempt in {1..3}; do
|
||||
msg_info "Attempt $attempt: Downloading LXC template..."
|
||||
if pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null 2>&1; then
|
||||
msg_ok "Template download successful."
|
||||
break
|
||||
fi
|
||||
if [ $attempt -eq 3 ]; then
|
||||
msg_error "Failed after 3 attempts. Please check network access or manually run:\n pveam download $TEMPLATE_STORAGE $TEMPLATE"
|
||||
exit 208
|
||||
fi
|
||||
sleep $((attempt * 5))
|
||||
done
|
||||
fi
|
||||
|
||||
msg_info "Creating LXC Container"
|
||||
# Check and fix subuid/subgid
|
||||
grep -q "root:100000:65536" /etc/subuid || echo "root:100000:65536" >>/etc/subuid
|
||||
grep -q "root:100000:65536" /etc/subgid || echo "root:100000:65536" >>/etc/subgid
|
||||
|
||||
# Combine all options
|
||||
PCT_OPTIONS=(${PCT_OPTIONS[@]:-${DEFAULT_PCT_OPTIONS[@]}})
|
||||
[[ " ${PCT_OPTIONS[@]} " =~ " -rootfs " ]] || PCT_OPTIONS+=(-rootfs "$CONTAINER_STORAGE:${PCT_DISK_SIZE:-8}")
|
||||
|
||||
# Secure creation of the LXC container with lock and template check
|
||||
lockfile="/tmp/template.${TEMPLATE}.lock"
|
||||
exec 9>"$lockfile" || {
|
||||
msg_error "Failed to create lock file '$lockfile'."
|
||||
exit 200
|
||||
}
|
||||
flock -w 60 9 || {
|
||||
msg_error "Timeout while waiting for template lock"
|
||||
exit 211
|
||||
}
|
||||
|
||||
if ! pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" "${PCT_OPTIONS[@]}" &>/dev/null; then
|
||||
msg_error "Container creation failed. Checking if template is corrupted or incomplete."
|
||||
|
||||
if [[ ! -s "$TEMPLATE_PATH" || "$(stat -c%s "$TEMPLATE_PATH")" -lt 1000000 ]]; then
|
||||
msg_error "Template file too small or missing – re-downloading."
|
||||
rm -f "$TEMPLATE_PATH"
|
||||
elif ! zstdcat "$TEMPLATE_PATH" | tar -tf - &>/dev/null; then
|
||||
msg_error "Template appears to be corrupted – re-downloading."
|
||||
rm -f "$TEMPLATE_PATH"
|
||||
else
|
||||
msg_error "Template is valid, but container creation failed. Update your whole Proxmox System (pve-container) first or check https://github.com/community-scripts/ProxmoxVE/discussions/8126"
|
||||
exit 209
|
||||
fi
|
||||
|
||||
# Retry download
|
||||
for attempt in {1..3}; do
|
||||
msg_info "Attempt $attempt: Re-downloading template..."
|
||||
if timeout 120 pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null; then
|
||||
msg_ok "Template re-download successful."
|
||||
break
|
||||
fi
|
||||
if [ "$attempt" -eq 3 ]; then
|
||||
msg_error "Three failed attempts. Aborting."
|
||||
exit 208
|
||||
fi
|
||||
sleep $((attempt * 5))
|
||||
done
|
||||
|
||||
sleep 1 # I/O-Sync-Delay
|
||||
msg_ok "Re-downloaded LXC Template"
|
||||
fi
|
||||
|
||||
if ! pct list | awk '{print $1}' | grep -qx "$CTID"; then
|
||||
msg_error "Container ID $CTID not listed in 'pct list' – unexpected failure."
|
||||
exit 215
|
||||
fi
|
||||
|
||||
if ! grep -q '^rootfs:' "/etc/pve/lxc/$CTID.conf"; then
|
||||
msg_error "RootFS entry missing in container config – storage not correctly assigned."
|
||||
exit 216
|
||||
fi
|
||||
|
||||
if grep -q '^hostname:' "/etc/pve/lxc/$CTID.conf"; then
|
||||
CT_HOSTNAME=$(grep '^hostname:' "/etc/pve/lxc/$CTID.conf" | awk '{print $2}')
|
||||
if [[ ! "$CT_HOSTNAME" =~ ^[a-z0-9-]+$ ]]; then
|
||||
msg_warn "Hostname '$CT_HOSTNAME' contains invalid characters – may cause issues with networking or DNS."
|
||||
fi
|
||||
fi
|
||||
|
||||
msg_ok "LXC Container ${BL}$CTID${CL} ${GN}was successfully created."
|
||||
217
misc/old_misc/install.func
Normal file
217
misc/old_misc/install.func
Normal file
@@ -0,0 +1,217 @@
|
||||
# Copyright (c) 2021-2025 tteck
|
||||
# Author: tteck (tteckster)
|
||||
# Co-Author: MickLesk
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
||||
apt-get update >/dev/null 2>&1
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
load_functions
|
||||
# This function enables IPv6 if it's not disabled and sets verbose mode
|
||||
verb_ip6() {
|
||||
set_std_mode # Set STD mode based on VERBOSE
|
||||
|
||||
if [ "$IPV6_METHOD" == "disable" ]; then
|
||||
msg_info "Disabling IPv6 (this may affect some services)"
|
||||
mkdir -p /etc/sysctl.d
|
||||
$STD tee /etc/sysctl.d/99-disable-ipv6.conf >/dev/null <<EOF
|
||||
# Disable IPv6 (set by community-scripts)
|
||||
net.ipv6.conf.all.disable_ipv6 = 1
|
||||
net.ipv6.conf.default.disable_ipv6 = 1
|
||||
net.ipv6.conf.lo.disable_ipv6 = 1
|
||||
EOF
|
||||
$STD sysctl -p /etc/sysctl.d/99-disable-ipv6.conf
|
||||
msg_ok "Disabled IPv6"
|
||||
fi
|
||||
}
|
||||
|
||||
# This function sets error handling options and defines the error_handler function to handle errors
|
||||
catch_errors() {
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||
}
|
||||
|
||||
# This function handles errors
|
||||
error_handler() {
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func)
|
||||
printf "\e[?25h"
|
||||
local exit_code="$?"
|
||||
local line_number="$1"
|
||||
local command="$2"
|
||||
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
||||
echo -e "\n$error_message"
|
||||
if [[ "$line_number" -eq 51 ]]; then
|
||||
echo -e "The silent function has suppressed the error, run the script with verbose mode enabled, which will provide more detailed output.\n"
|
||||
post_update_to_api "failed" "No error message, script ran in silent mode"
|
||||
else
|
||||
post_update_to_api "failed" "${command}"
|
||||
fi
|
||||
}
|
||||
|
||||
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
||||
setting_up_container() {
|
||||
msg_info "Setting up Container OS"
|
||||
for ((i = RETRY_NUM; i > 0; i--)); do
|
||||
if [ "$(hostname -I)" != "" ]; then
|
||||
break
|
||||
fi
|
||||
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
||||
sleep $RETRY_EVERY
|
||||
done
|
||||
if [ "$(hostname -I)" = "" ]; then
|
||||
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
|
||||
echo -e "${NETWORK}Check Network Settings"
|
||||
exit 1
|
||||
fi
|
||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||
systemctl disable -q --now systemd-networkd-wait-online.service
|
||||
msg_ok "Set up Container OS"
|
||||
#msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
|
||||
msg_ok "Network Connected: ${BL}$(hostname -I)"
|
||||
}
|
||||
|
||||
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
||||
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
||||
network_check() {
|
||||
set +e
|
||||
trap - ERR
|
||||
ipv4_connected=false
|
||||
ipv6_connected=false
|
||||
sleep 1
|
||||
|
||||
# Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
||||
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
|
||||
msg_ok "IPv4 Internet Connected"
|
||||
ipv4_connected=true
|
||||
else
|
||||
msg_error "IPv4 Internet Not Connected"
|
||||
fi
|
||||
|
||||
# Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
||||
if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then
|
||||
msg_ok "IPv6 Internet Connected"
|
||||
ipv6_connected=true
|
||||
else
|
||||
msg_error "IPv6 Internet Not Connected"
|
||||
fi
|
||||
|
||||
# If both IPv4 and IPv6 checks fail, prompt the user
|
||||
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
||||
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
||||
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
||||
else
|
||||
echo -e "${NETWORK}Check Network Settings"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# DNS resolution checks for GitHub-related domains (IPv4 and/or IPv6)
|
||||
GIT_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
|
||||
GIT_STATUS="Git DNS:"
|
||||
DNS_FAILED=false
|
||||
|
||||
for HOST in "${GIT_HOSTS[@]}"; do
|
||||
RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | grep -E '(^([0-9]{1,3}\.){3}[0-9]{1,3}$)|(^[a-fA-F0-9:]+$)' | head -n1)
|
||||
if [[ -z "$RESOLVEDIP" ]]; then
|
||||
GIT_STATUS+="$HOST:($DNSFAIL)"
|
||||
DNS_FAILED=true
|
||||
else
|
||||
GIT_STATUS+=" $HOST:($DNSOK)"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ "$DNS_FAILED" == true ]]; then
|
||||
fatal "$GIT_STATUS"
|
||||
else
|
||||
msg_ok "$GIT_STATUS"
|
||||
fi
|
||||
|
||||
set -e
|
||||
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
||||
}
|
||||
|
||||
# This function updates the Container OS by running apt-get update and upgrade
|
||||
update_os() {
|
||||
msg_info "Updating Container OS"
|
||||
if [[ "$CACHER" == "yes" ]]; then
|
||||
echo 'Acquire::http::Proxy-Auto-Detect "/usr/local/bin/apt-proxy-detect.sh";' >/etc/apt/apt.conf.d/00aptproxy
|
||||
cat <<EOF >/usr/local/bin/apt-proxy-detect.sh
|
||||
#!/bin/bash
|
||||
if nc -w1 -z "${CACHER_IP}" 3142; then
|
||||
echo -n "http://${CACHER_IP}:3142"
|
||||
else
|
||||
echo -n "DIRECT"
|
||||
fi
|
||||
EOF
|
||||
chmod +x /usr/local/bin/apt-proxy-detect.sh
|
||||
fi
|
||||
$STD apt-get update
|
||||
$STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade
|
||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||
msg_ok "Updated Container OS"
|
||||
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
}
|
||||
|
||||
# This function modifies the message of the day (motd) and SSH settings
|
||||
motd_ssh() {
|
||||
# Set terminal to 256-color mode
|
||||
grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >>/root/.bashrc
|
||||
|
||||
# Get OS information (Debian / Ubuntu)
|
||||
if [ -f "/etc/os-release" ]; then
|
||||
OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||
OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
|
||||
elif [ -f "/etc/debian_version" ]; then
|
||||
OS_NAME="Debian"
|
||||
OS_VERSION=$(cat /etc/debian_version)
|
||||
fi
|
||||
|
||||
PROFILE_FILE="/etc/profile.d/00_lxc-details.sh"
|
||||
echo "echo -e \"\"" >"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${BOLD}${APPLICATION} LXC Container${CL}"\" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${GATEWAY}${YW} Provided by: ${GN}community-scripts ORG ${YW}| GitHub: ${GN}https://github.com/community-scripts/ProxmoxVE${CL}\"" >>"$PROFILE_FILE"
|
||||
echo "echo \"\"" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${OS}${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${HOSTNAME}${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE"
|
||||
echo -e "echo -e \"${TAB}${INFO}${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >>"$PROFILE_FILE"
|
||||
|
||||
# Disable default MOTD scripts
|
||||
chmod -x /etc/update-motd.d/*
|
||||
|
||||
if [[ "${SSH_ROOT}" == "yes" ]]; then
|
||||
sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
|
||||
systemctl restart sshd
|
||||
fi
|
||||
}
|
||||
|
||||
# This function customizes the container by modifying the getty service and enabling auto-login for the root user
|
||||
customize() {
|
||||
if [[ "$PASSWORD" == "" ]]; then
|
||||
msg_info "Customizing Container"
|
||||
GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
|
||||
mkdir -p $(dirname $GETTY_OVERRIDE)
|
||||
cat <<EOF >$GETTY_OVERRIDE
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//')
|
||||
msg_ok "Customized Container"
|
||||
fi
|
||||
echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/${app}.sh)\"" >/usr/bin/update
|
||||
chmod +x /usr/bin/update
|
||||
|
||||
if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then
|
||||
mkdir -p /root/.ssh
|
||||
echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys
|
||||
chmod 700 /root/.ssh
|
||||
chmod 600 /root/.ssh/authorized_keys
|
||||
fi
|
||||
}
|
||||
4818
misc/old_misc/tools.func
Normal file
4818
misc/old_misc/tools.func
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user