* update core.func * Add advanced container features and IP range scanning Introduces support for scanning and assigning the first free IP from a user-specified range, and expands advanced LXC container settings to include GPU passthrough, TUN/TAP, nesting, keyctl, mknod, timezone, protection, and APT cacher options. Refactors advanced_settings wizard to support these new features, updates variable handling and defaults, and improves summary and output formatting. Also enhances SSH key configuration, storage/template validation, and GPU passthrough logic. * update install.func * Enhance hardware acceleration and MariaDB setup Refactors and expands the hardware acceleration setup to support multiple GPU types (Intel, AMD, NVIDIA), adds user selection for GPU configuration, and improves driver installation logic for Debian and Ubuntu. Adds runtime directory persistence for MariaDB using tmpfiles.d to ensure /run/mysqld exists after reboot. Includes minor robustness improvements and error handling throughout the script. * Update error-handler.func * Update copyright years to 2026 in core scripts Updated the copyright year from 2025 to 2026 in alpine-install.func, api.func, and cloud-init.func to reflect the new year. No functional changes were made.
193 lines
6.3 KiB
Plaintext
193 lines
6.3 KiB
Plaintext
# Copyright (c) 2021-2026 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 "$(dirname "${BASH_SOURCE[0]}")/core.func"
|
|
source "$(dirname "${BASH_SOURCE[0]}")/error-handler.func"
|
|
load_functions
|
|
catch_errors
|
|
|
|
# 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
|
|
}
|
|
|
|
set -Eeuo pipefail
|
|
trap 'error_handler $? $LINENO "$BASH_COMMAND"' ERR
|
|
trap on_exit EXIT
|
|
trap on_interrupt INT
|
|
trap on_terminate TERM
|
|
|
|
error_handler() {
|
|
local exit_code="$1"
|
|
local line_number="$2"
|
|
local command="$3"
|
|
|
|
if [[ "$exit_code" -eq 0 ]]; then
|
|
return 0
|
|
fi
|
|
|
|
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"
|
|
}
|
|
|
|
on_exit() {
|
|
local exit_code="$?"
|
|
[[ -n "${lockfile:-}" && -e "$lockfile" ]] && rm -f "$lockfile"
|
|
exit "$exit_code"
|
|
}
|
|
|
|
on_interrupt() {
|
|
echo -e "\n${RD}Interrupted by user (SIGINT)${CL}"
|
|
exit 130
|
|
}
|
|
|
|
on_terminate() {
|
|
echo -e "\n${RD}Terminated by signal (SIGTERM)${CL}"
|
|
exit 143
|
|
}
|
|
|
|
# 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
|
|
ipv4_status="${GN}✔${CL} IPv4"
|
|
else
|
|
ipv4_status="${RD}✖${CL} IPv4"
|
|
read -r -p "Internet NOT connected. 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 "Internet: ${ipv4_status} DNS Failed"
|
|
else
|
|
msg_ok "Internet: ${ipv4_status} DNS: ${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 "$(dirname "${BASH_SOURCE[0]}")/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
|
|
|
|
} |