Zuletzt aktiv 1764397831

Автоматично създаване и конфигуриране на LXC контейнери

Änderung d619e6e6101848b425340250cb305111b656f90f

lxc.sh Orginalformat
1#!/bin/bash
2#
3# Proxmox LXC Container Creator v2.1
4# Автоматично създаване и конфигуриране на LXC контейнери
5# Автор: Федя Серафиев / urocibg.eu
6
7set -euo pipefail
8
9# 🌈 Цветове и Функции
10RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'; BOLD='\033[1m'
11
12print_header() {
13 clear
14 echo -e "${CYAN}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n $1\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
15}
16
17print_success() {
18 echo -e "${GREEN}$1${NC}"
19}
20
21print_error() {
22 echo -e "${RED}❌ ГРЕШКА: $1${NC}"
23}
24
25# ----------------------------------------------------------------------------------
26# 🌐 Избор на ОС Шаблон (ДИНАМИЧЕН ИЗБОР - С HTTP ЛИНК)
27# ----------------------------------------------------------------------------------
28BASE_URL="http://download.proxmox.com/images/system/"
29print_header "PROXMOX LXC СЪЗДАТЕЛ – ДИНАМИЧЕН ИЗБОР НА ШАБЛОН"
30
31print_success "Свалям списък с най-новите LXC шаблони от $BASE_URL..."
32
33# Сваляне, филтриране и сортиране на последните 10 шаблона, като изключваме almalinux
34mapfile -t ALL_TEMPLATES < <(wget -q -O - "$BASE_URL" | \
35 grep -o 'href="[^"]*\(tar\.zst\|tar\.xz\)"' | \
36 grep -v 'almalinux' | \
37 awk -F'"' '{print $2}' | \
38 sort -r | \
39 head -n 10)
40
41if [ ${#ALL_TEMPLATES[@]} -eq 0 ]; then
42 print_error "Неуспешно изтегляне на списъка с шаблони. Използвам резервен (статичен) списък."
43 # Резервен (статичен) списък
44 ALL_TEMPLATES=(
45 "debian-12-standard_12.7-1_amd64.tar.xz"
46 "ubuntu-24.04-standard_24.04-2_amd64.tar.zst"
47 "debian-11-standard_11.9-1_amd64.tar.zst"
48 "ubuntu-22.04-standard_22.04-1_amd64.tar.zst"
49 )
50fi
51
52echo -e "\n${BOLD}Избери ОС (най-новите налични шаблони):${NC}"
53
54# Показваме списъка
55i=1
56for tmpl in "${ALL_TEMPLATES[@]}"; do
57 # Форматиране на името за по-кратък и ясен изглед
58 DISPLAY_NAME=$(echo "$tmpl" | sed -E 's/(-standard|_default|(_[0-9]+\.?[0-9]*)+_amd64\.tar\.(zst|xz))//g' | tr '-' ' ' | awk '{$1=toupper(substr($1,1,1)) substr($1,2)}1')
59
60 RECOMMENDATION=""
61 if [[ "$tmpl" =~ ^debian-12 ]]; then
62 RECOMMENDATION="← Препоръчителен"
63 fi
64
65 echo -e " $i) $DISPLAY_NAME $RECOMMENDATION"
66 ((i++))
67done
68
69# Избор на шаблон
70while :; do
71 read -p "Въведи 1–$((i-1)) [1]: " os_choice
72 os_choice=${os_choice:-1}
73 if [[ "$os_choice" =~ ^[0-9]+$ ]] && (( os_choice >= 1 && os_choice < i )); then
74 TEMPLATE="${ALL_TEMPLATES[os_choice-1]}"
75 # URL за сваляне на избрания шаблон
76 URL="$BASE_URL$TEMPLATE"
77 break
78 else
79 print_error "Невалиден избор."
80 fi
81done
82
83# ----------------------------------------------------------------------------------
84# 💡 Настройки на Контейнера
85# ----------------------------------------------------------------------------------
86while :; do
87 read -p "CT ID (напр. 100): " CTID
88 if [[ $CTID =~ ^[0-9]+$ ]] && (( CTID >= 100 )); then
89 if ! pct status "$CTID" &>/dev/null; then
90 break
91 else
92 print_error "Контейнер с ID $CTID вече съществува или е зает."
93 fi
94 else
95 print_error "Невалидно CT ID. Трябва да е число >= 100."
96 fi
97done
98
99read -p "Hostname [lxc-$CTID]: " HOSTNAME; HOSTNAME=${HOSTNAME:-lxc-$CTID}
100read -p "Storage [local-lvm]: " STORAGE; STORAGE=${STORAGE:-local-lvm}
101read -p "Disk GB [20]: " DISK; DISK=${DISK:-20}
102read -p "RAM MB [4096]: " RAM; RAM=${RAM:-4096}
103read -p "CPU ядра [2]: " CORES; CORES=${CORES:-2}
104read -p "Bridge [vmbr0]: " BRIDGE; BRIDGE=${BRIDGE:-vmbr0}
105
106# 🌐 Мрежови Настройки
107IP=""; GW=""; DNS=""
108read -p "Статично IP? (y/N): " yn
109if [[ $yn =~ ^[Yy]$ ]]; then
110 read -p "IP/MASK (напр. 10.0.0.178/24): " IP
111 read -p "Gateway (Enter = без): " GW
112 DNS="1.1.1.1 8.8.8.8"
113fi
114
115# 🔑 SSH Ключ / Парола
116SSH_KEY_ARG=""
117PASSWORD_ARG=""
118KEY_TEMP_FILE=""
119
120echo -e "\n${BOLD}Избери метод за достъп (SSH ключ или парола):${NC}"
121echo " 1) Добавяне на SSH публичен ключ"
122echo " 2) Използване на root парола"
123read -p "Въведи 1 или 2 [1]: " auth_choice
124
125if [[ "${auth_choice:-1}" == "1" ]]; then
126 read -p "Път до SSH публичен ключ (Enter за директно поставяне): " keyfile
127
128 SSH_KEY_CONTENT=""
129 if [[ -f "$keyfile" ]]; then
130 SSH_KEY_CONTENT=$(cat "$keyfile")
131 print_success "Прочетен ключ от файл: $keyfile"
132 elif [[ -z "$keyfile" ]]; then
133 echo -e "${YELLOW}Моля, поставете целия си публичен SSH ключ и натиснете Enter:${NC}"
134 read SSH_KEY_CONTENT
135 if [[ -z "$SSH_KEY_CONTENT" ]]; then
136 print_error "Не е въведен SSH ключ."
137 auth_choice=2
138 fi
139 else
140 print_error "Файлът с ключ не е намерен ($keyfile)."
141 auth_choice=2
142 fi
143
144 if [[ -n "${SSH_KEY_CONTENT:-}" ]]; then
145 KEY_TEMP_FILE=$(mktemp)
146 echo "$SSH_KEY_CONTENT" > "$KEY_TEMP_FILE"
147 SSH_KEY_ARG="--ssh-public-keys $KEY_TEMP_FILE"
148 fi
149fi
150
151if [[ "${auth_choice:-1}" == "2" ]]; then
152 while :; do
153 read -s -p "Root парола: " PASSWORD; echo
154 read -s -p "Повтори парола: " p2; echo
155 if [[ "$PASSWORD" == "$p2" ]]; then
156 PASSWORD_ARG="--password \"$PASSWORD\""
157 break
158 else
159 print_error "Паролите не съвпадат. Опитай пак."
160 fi
161 done
162fi
163
164# 🔒 Привилегирован/Непривилегирован
165read -p "Непривилегирован контейнер (препоръчва се)? (Y/n): " u
166[[ $u =~ ^[Nn]$ ]] && UNPRIVILEGED=0 || UNPRIVILEGED=1
167
168# 📝 Резюме
169print_header "ПРЕГЛЕД НА НАСТРОЙКИТЕ"
170echo -e "ОС: $TEMPLATE"
171echo -e "CTID: $CTID | Hostname: $HOSTNAME"
172echo -e "Спецификации: $DISK GB / $RAM MB RAM / $CORES ядра (Swap: 0)"
173echo -e "Мрежа: $BRIDGE | IP: ${IP:-DHCP}"
174echo -e "Достъп: $([[ -n "$SSH_KEY_ARG" ]] && echo "SSH Key" || echo "Root Парола")"
175echo -e "Тип: $([[ "$UNPRIVILEGED" == "1" ]] && echo "Непривилегирован" || echo "Привилегирован")"
176
177read -p "ГОТОВО? (y/N): " ok
178[[ $ok =~ ^[Yy]$ ]] || { [[ -n "${KEY_TEMP_FILE:-}" ]] && rm "$KEY_TEMP_FILE"; exit 0; }
179
180# ⬇️ Сваляне на Шаблона
181tmpl="/var/lib/vz/template/cache/$TEMPLATE"
182if [[ ! -f "$tmpl" ]]; then
183 print_success "Свалям $TEMPLATE ..."
184 wget -q --show-progress -O "$tmpl" "$URL"
185else
186 print_success "Шаблонът $TEMPLATE вече съществува, пропускам свалянето."
187fi
188
189# ⚙️ Подготовка на Мрежата
190net="name=eth0,bridge=$BRIDGE,firewall=1"
191[[ -n "${IP:-}" ]] && net+=",ip=$IP"
192[[ -n "${GW:-}" ]] && net+=",gw=$GW"
193
194# 🏗️ Създаване на Контейнера
195print_success "Създавам контейнер $CTID ..."
196
197# Аргументи: --swap 0 и настройки за сигурност
198COMMAND="pct create \"$CTID\" \"$tmpl\" \
199 --hostname \"$HOSTNAME\" --storage \"$STORAGE\" --rootfs \"$STORAGE:$DISK\" \
200 --memory \"$RAM\" --cores \"$CORES\" --net0 \"$net\" --swap 0 \
201 --features nesting=1,keyctl=1 --onboot 1 --unprivileged \"$UNPRIVILEGED\" \
202 $SSH_KEY_ARG \
203 $PASSWORD_ARG"
204
205if ! eval "$COMMAND"; then
206 print_error "Неуспешно създаване на контейнера. Проверете настройките и логовете на Proxmox."
207 [[ -n "${KEY_TEMP_FILE:-}" ]] && rm "$KEY_TEMP_FILE"
208 exit 1
209fi
210
211# 📝 Добавяне на DNS
212[[ -n "${IP:-}" ]] && pct set "$CTID" --nameserver "$DNS"
213
214# 🚀 Стартиране и Първоначална Настройка
215print_success "Стартирам контейнер $CTID..."
216pct start "$CTID"
217
218print_success "Изчаквам и инсталирам основни пакети (около 30-50 секунди)..."
219sleep 8
220pct exec "$CTID" -- bash -c "apt update && apt upgrade -y && apt install -y sudo curl wget git nano htop net-tools qemu-guest-agent" >/dev/null 2>&1
221
222# 🥳 Край
223print_header "ГОТОВО!"
224echo -e "${GREEN}Контейнер $CTID ($HOSTNAME) е готов и работи!${NC}"
225echo -e "Влез с: ${CYAN}pct enter $CTID${NC}"
226[[ -n "$IP" ]] && echo -e "или с: ${CYAN}ssh root@$(echo $IP | cut -d/ -f1)${NC}"
227
228# 🧹 Почистване на временен файл, ако е създаден
229[[ -n "${KEY_TEMP_FILE:-}" ]] && rm "$KEY_TEMP_FILE"