mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-12-16 20:23:32 +01:00
Compare commits
9 Commits
fix/2fauth
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 0271dddfd5 | |||
| 5a263b5036 | |||
| 60635feeab | |||
| 7261ffe8a2 | |||
| 44ea7cecb8 | |||
| 5f6af94ca6 | |||
| 059aaac914 | |||
| 951fb3d53a | |||
| 000c8b5fc9 |
@ -20,6 +20,9 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
|
||||
- zabbix: fix repo url after change [@MickLesk](https://github.com/MickLesk) ([#10042](https://github.com/community-scripts/ProxmoxVE/pull/10042))
|
||||
- Fix: mariadb repo in update_scripts [@MickLesk](https://github.com/MickLesk) ([#10034](https://github.com/community-scripts/ProxmoxVE/pull/10034))
|
||||
- 2fauth: update PHP version from 8.3 to 8.4 in update_script [@MickLesk](https://github.com/MickLesk) ([#10035](https://github.com/community-scripts/ProxmoxVE/pull/10035))
|
||||
- pdm: add rsyslog to fix /dev/log Connection refused errors [@MickLesk](https://github.com/MickLesk) ([#10018](https://github.com/community-scripts/ProxmoxVE/pull/10018))
|
||||
- 2fauth: bump to php8.4 [@MickLesk](https://github.com/MickLesk) ([#10019](https://github.com/community-scripts/ProxmoxVE/pull/10019))
|
||||
- Miniflux: use correct systemctl to check service instead of file path [@MickLesk](https://github.com/MickLesk) ([#10024](https://github.com/community-scripts/ProxmoxVE/pull/10024))
|
||||
@ -29,6 +32,7 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- core: IP-Range-Scan Support (app.vars / default.vars) [@MickLesk](https://github.com/MickLesk) ([#10038](https://github.com/community-scripts/ProxmoxVE/pull/10038))
|
||||
- tools.func: add optional enabled parameter to setup_deb822_repo [@MickLesk](https://github.com/MickLesk) ([#10017](https://github.com/community-scripts/ProxmoxVE/pull/10017))
|
||||
- core: map Etc/* timezones to 'host' for pct compatibility [@MickLesk](https://github.com/MickLesk) ([#10020](https://github.com/community-scripts/ProxmoxVE/pull/10020))
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
if check_for_gh_release "2fauth" "Bubka/2FAuth"; then
|
||||
$STD apt update
|
||||
$STD apt -y upgrade
|
||||
|
||||
@ -20,15 +20,16 @@ color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /opt/apache-guacamole ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
msg_error "Currently we don't provide an update function for this ${APP}."
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /opt/apache-guacamole ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
msg_error "Currently we don't provide an update function for this ${APP}."
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
|
||||
@ -28,6 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
if check_for_gh_release "booklore" "booklore-app/BookLore"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop booklore
|
||||
|
||||
@ -28,6 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
if check_for_gh_release "bookstack" "BookStackApp/BookStack"; then
|
||||
msg_info "Stopping Apache2"
|
||||
systemctl stop apache2
|
||||
|
||||
@ -20,15 +20,16 @@ color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /usr/share/dolibarr ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
msg_error "To update ${APP}, use the applications web interface."
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /usr/share/dolibarr ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
msg_error "To update ${APP}, use the applications web interface."
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
@ -38,4 +39,4 @@ description
|
||||
msg_ok "Completed Successfully!\n"
|
||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
|
||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/dolibarr/install${CL}"
|
||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}/dolibarr/install${CL}"
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
|
||||
if ! grep -Fq "root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" /etc/crontab; then
|
||||
echo "0 0 * * * root /usr/bin/php /opt/domain-monitor/cron/check_domains.php" >>/etc/crontab
|
||||
|
||||
@ -28,7 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
setup_mariadb
|
||||
if check_for_gh_release "firefly" "firefly-iii/firefly-iii"; then
|
||||
systemctl stop apache2
|
||||
cp /opt/firefly/.env /opt/.env
|
||||
|
||||
@ -23,6 +23,7 @@ function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
setup_mariadb
|
||||
|
||||
NODE_VERSION="22" setup_nodejs
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
RELEASE=$(curl -fsSL https://api.github.com/repos/glpi-project/glpi/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
|
||||
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
|
||||
msg_error "Currently we don't provide an update function for this ${APP}."
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
if check_for_gh_release "hortusfox" "danielbrendel/hortusfox-web"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop apache2
|
||||
|
||||
@ -28,7 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
setup_mariadb
|
||||
if check_for_gh_release "invoiceninja" "invoiceninja/invoiceninja"; then
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop supervisor nginx php8.4-fpm
|
||||
|
||||
@ -28,6 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit 1
|
||||
fi
|
||||
setup_mariadb
|
||||
|
||||
msg_info "Updating LXC"
|
||||
$STD apt update
|
||||
|
||||
@ -30,11 +30,12 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
|
||||
PHP_VERSION="8.4" PHP_MODULE="mysql" PHP_APACHE="YES" setup_php
|
||||
setup_composer
|
||||
|
||||
if check_for_gh_release "kimai" "kimai/kimai"; then
|
||||
if check_for_gh_release "kimai" "kimai/kimai"; then
|
||||
BACKUP_DIR="/opt/kimai_backup"
|
||||
|
||||
msg_info "Stopping Apache2"
|
||||
|
||||
@ -28,7 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
setup_mariadb
|
||||
if check_for_gh_release "leantime" "Leantime/leantime"; then
|
||||
msg_info "Creating Backup"
|
||||
mariadb-dump leantime >"/opt/${APP}_db_backup_$(date +%F).sql"
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
msg_info "Updating LibreNMS"
|
||||
su librenms
|
||||
cd /opt/librenms
|
||||
|
||||
@ -20,16 +20,17 @@ color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /opt/limesurvey ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
msg_warn "Application is updated via Web Interface"
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /opt/limesurvey ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
|
||||
msg_warn "Application is updated via Web Interface"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
|
||||
@ -28,6 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
if check_for_gh_release "mmdl" "intri-in/manage-my-damn-life-nextjs"; then
|
||||
msg_info "Stopping service"
|
||||
systemctl stop mmdl
|
||||
|
||||
@ -20,18 +20,19 @@ color
|
||||
catch_errors
|
||||
|
||||
function update_script() {
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /etc/mysql/mariadb.conf.d ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
msg_info "Updating ${APP} LXC"
|
||||
$STD apt update
|
||||
$STD apt -y upgrade
|
||||
msg_ok "Updated successfully!"
|
||||
header_info
|
||||
check_container_storage
|
||||
check_container_resources
|
||||
if [[ ! -d /etc/mysql/mariadb.conf.d ]]; then
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
msg_info "Updating ${APP} LXC"
|
||||
$STD apt update
|
||||
$STD apt -y upgrade
|
||||
msg_ok "Updated successfully!"
|
||||
exit
|
||||
}
|
||||
|
||||
start
|
||||
|
||||
@ -34,7 +34,7 @@ function update_script() {
|
||||
msg_ok "Service Stopped"
|
||||
|
||||
fetch_and_deploy_gh_release "miniflux" "miniflux/v2" "binary" "latest"
|
||||
|
||||
|
||||
msg_info "Updating Miniflux"
|
||||
$STD miniflux -migrate -config-file /etc/miniflux.conf
|
||||
msg_ok "Updated Miniflux"
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
|
||||
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
|
||||
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
msg_info "Updating $APP LXC"
|
||||
$STD apt update
|
||||
$STD apt upgrade -y
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
|
||||
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
||||
if [[ "$CURRENT_PHP" != "8.3" ]]; then
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
||||
|
||||
if [[ "$CURRENT_PHP" != "8.4" ]]; then
|
||||
|
||||
@ -27,7 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
setup_mariadb
|
||||
if check_for_gh_release "phpipam" "phpipam/phpipam"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop apache2
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
if check_for_gh_release "plant-it" "MDeLuise/plant-it"; then
|
||||
msg_info "Stopping Service"
|
||||
systemctl stop plant-it
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
|
||||
if check_for_gh_release "projectsend" "projectsend/projectsend"; then
|
||||
msg_info "Stopping Service"
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
|
||||
|
||||
if [[ "$CURRENT_PHP" != "8.4" ]]; then
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
msg_info "Updating Shinobi"
|
||||
cd /opt/Shinobi
|
||||
$STD sh UPDATE.sh
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
if ! grep -q "client_max_body_size[[:space:]]\+100M;" /etc/nginx/conf.d/snipeit.conf; then
|
||||
sed -i '/index index.php;/i \ client_max_body_size 100M;' /etc/nginx/conf.d/snipeit.conf
|
||||
fi
|
||||
|
||||
@ -28,7 +28,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
setup_mariadb
|
||||
if check_for_gh_release "wallabag" "wallabag/wallabag"; then
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop nginx php8.3-fpm
|
||||
|
||||
@ -27,7 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
|
||||
setup_mariadb
|
||||
if check_for_gh_release "wavelog" "wavelog/wavelog"; then
|
||||
msg_info "Stopping Services"
|
||||
systemctl stop apache2
|
||||
|
||||
@ -27,6 +27,7 @@ function update_script() {
|
||||
msg_error "No ${APP} Installation Found!"
|
||||
exit
|
||||
fi
|
||||
setup_mariadb
|
||||
msg_error "Wordpress should be updated via the user interface."
|
||||
exit
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ function update_script() {
|
||||
|
||||
rm -Rf /etc/apt/sources.list.d/zabbix.list
|
||||
cd /tmp
|
||||
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
|
||||
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
|
||||
curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb
|
||||
$STD dpkg -i zabbix-release_latest+debian13_all.deb
|
||||
rm -rf /tmp/zabbix-release_latest+debian13_all.deb
|
||||
|
||||
@ -434,12 +434,24 @@ var_unprivileged=1 # 0=privileged, 1=unprivileged
|
||||
#### Network
|
||||
```bash
|
||||
var_brg=vmbr0 # Bridge interface
|
||||
var_net=veth # Network driver
|
||||
var_gateway=192.168.1.1 # Default gateway
|
||||
var_net=dhcp # dhcp, static IP/CIDR, or IP range (see below)
|
||||
var_gateway=192.168.1.1 # Default gateway (required for static IP)
|
||||
var_mtu=1500 # MTU size
|
||||
var_vlan=100 # VLAN ID
|
||||
```
|
||||
|
||||
#### IP Range Scanning
|
||||
|
||||
You can specify an IP range instead of a static IP. The system will ping each IP in the range and automatically assign the first free IP:
|
||||
|
||||
```bash
|
||||
# Format: START_IP/CIDR-END_IP/CIDR
|
||||
var_net=192.168.1.100/24-192.168.1.200/24
|
||||
var_gateway=192.168.1.1
|
||||
```
|
||||
|
||||
This is useful for automated deployments where you want static IPs but don't want to track which IPs are already in use.
|
||||
|
||||
#### System
|
||||
```bash
|
||||
var_hostname=pihole # Container name
|
||||
|
||||
@ -122,6 +122,31 @@ var_verbose=no \
|
||||
echo "✓ Container deployed successfully"
|
||||
```
|
||||
|
||||
### Using IP Range Scan for Automatic IP Assignment
|
||||
|
||||
Instead of manually specifying static IPs, you can define an IP range. The system will automatically ping each IP and assign the first free one:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# deploy-with-ip-scan.sh - Auto-assign first free IP from range
|
||||
|
||||
var_unprivileged=1 \
|
||||
var_cpu=4 \
|
||||
var_ram=4096 \
|
||||
var_hostname=web-server \
|
||||
var_net=192.168.1.100/24-192.168.1.150/24 \
|
||||
var_gateway=192.168.1.1 \
|
||||
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/debian.sh)"
|
||||
|
||||
# The script will:
|
||||
# 1. Ping 192.168.1.100 - if responds, skip
|
||||
# 2. Ping 192.168.1.101 - if responds, skip
|
||||
# 3. Continue until first IP that doesn't respond
|
||||
# 4. Assign that IP to the container
|
||||
```
|
||||
|
||||
> **Note**: IP range format is `START_IP/CIDR-END_IP/CIDR`. Both sides must include the same CIDR notation.
|
||||
|
||||
### Using App Defaults
|
||||
|
||||
**Step 1: Create defaults once (interactive)**
|
||||
|
||||
@ -31,7 +31,7 @@ esac
|
||||
|
||||
msg_info "Installing Zabbix $ZABBIX_VERSION"
|
||||
cd /tmp
|
||||
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/release/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
|
||||
ZABBIX_DEB_URL="https://repo.zabbix.com/zabbix/${ZABBIX_VERSION}/debian/pool/main/z/zabbix-release/zabbix-release_latest+debian13_all.deb"
|
||||
curl -fsSL "$ZABBIX_DEB_URL" -o /tmp/zabbix-release_latest+debian13_all.deb
|
||||
$STD dpkg -i /tmp/zabbix-release_latest+debian13_all.deb
|
||||
$STD apt update
|
||||
|
||||
144
misc/build.func
144
misc/build.func
@ -291,6 +291,90 @@ find_host_ssh_keys() {
|
||||
)
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# SECTION 3B: IP RANGE SCANNING
|
||||
# ==============================================================================
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ip_to_int() / int_to_ip()
|
||||
#
|
||||
# - Converts IP address to integer and vice versa for range iteration
|
||||
# ------------------------------------------------------------------------------
|
||||
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))"
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# resolve_ip_from_range()
|
||||
#
|
||||
# - Takes an IP range in format "10.0.0.1/24-10.0.0.10/24"
|
||||
# - Pings each IP in the range to find the first available one
|
||||
# - Returns the first free IP with CIDR notation
|
||||
# - Sets NET_RESOLVED to the resolved IP or empty on failure
|
||||
# ------------------------------------------------------------------------------
|
||||
resolve_ip_from_range() {
|
||||
local range="$1"
|
||||
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_start ip_end
|
||||
|
||||
# Parse range: "10.0.0.1/24-10.0.0.10/24"
|
||||
ip_start="${range%%-*}"
|
||||
ip_end="${range##*-}"
|
||||
|
||||
if [[ ! "$ip_start" =~ $ip_cidr_regex ]] || [[ ! "$ip_end" =~ $ip_cidr_regex ]]; then
|
||||
NET_RESOLVED=""
|
||||
return 1
|
||||
fi
|
||||
|
||||
local ip1="${ip_start%%/*}"
|
||||
local ip2="${ip_end%%/*}"
|
||||
local cidr="${ip_start##*/}"
|
||||
|
||||
local start_int=$(ip_to_int "$ip1")
|
||||
local end_int=$(ip_to_int "$ip2")
|
||||
|
||||
for ((ip_int = start_int; ip_int <= end_int; ip_int++)); do
|
||||
local ip=$(int_to_ip $ip_int)
|
||||
msg_info "Checking IP: $ip"
|
||||
if ! ping -c 1 -W 1 "$ip" >/dev/null 2>&1; then
|
||||
NET_RESOLVED="$ip/$cidr"
|
||||
msg_ok "Found free IP: ${BGN}$NET_RESOLVED${CL}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
NET_RESOLVED=""
|
||||
msg_error "No free IP found in range $range"
|
||||
return 1
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# is_ip_range()
|
||||
#
|
||||
# - Checks if a string is an IP range (contains - and looks like IP/CIDR)
|
||||
# - Returns 0 if it's a range, 1 otherwise
|
||||
# ------------------------------------------------------------------------------
|
||||
is_ip_range() {
|
||||
local value="$1"
|
||||
local ip_start ip_end
|
||||
if [[ "$value" == *-* ]] && [[ "$value" != "dhcp" ]]; then
|
||||
local ip_cidr_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/([0-9]{1,2})$'
|
||||
ip_start="${value%%-*}"
|
||||
ip_end="${value##*-}"
|
||||
if [[ "$ip_start" =~ $ip_cidr_regex ]] && [[ "$ip_end" =~ $ip_cidr_regex ]]; then
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# SECTION 4: STORAGE & RESOURCE MANAGEMENT
|
||||
# ==============================================================================
|
||||
@ -403,6 +487,18 @@ base_settings() {
|
||||
HN=${var_hostname:-$NSAPP}
|
||||
BRG=${var_brg:-"vmbr0"}
|
||||
NET=${var_net:-"dhcp"}
|
||||
|
||||
# Resolve IP range if NET contains a range (e.g., 192.168.1.100/24-192.168.1.200/24)
|
||||
if is_ip_range "$NET"; then
|
||||
msg_info "Scanning IP range: $NET"
|
||||
if resolve_ip_from_range "$NET"; then
|
||||
NET="$NET_RESOLVED"
|
||||
else
|
||||
msg_error "Could not find free IP in range. Falling back to DHCP."
|
||||
NET="dhcp"
|
||||
fi
|
||||
fi
|
||||
|
||||
IPV6_METHOD=${var_ipv6_method:-"none"}
|
||||
IPV6_STATIC=${var_ipv6_static:-""}
|
||||
GATE=${var_gateway:-""}
|
||||
@ -492,6 +588,12 @@ load_vars_file() {
|
||||
[[ "$var_key" != var_* ]] && continue
|
||||
_is_whitelisted "$var_key" || continue
|
||||
|
||||
# Strip inline comments (anything after unquoted #)
|
||||
# Only strip if not inside quotes
|
||||
if [[ ! "$var_val" =~ ^[\"\'] ]]; then
|
||||
var_val="${var_val%%#*}"
|
||||
fi
|
||||
|
||||
# Strip quotes
|
||||
if [[ "$var_val" =~ ^\"(.*)\"$ ]]; then
|
||||
var_val="${BASH_REMATCH[1]}"
|
||||
@ -499,6 +601,9 @@ load_vars_file() {
|
||||
var_val="${BASH_REMATCH[1]}"
|
||||
fi
|
||||
|
||||
# Trim trailing whitespace
|
||||
var_val="${var_val%"${var_val##*[![:space:]]}"}"
|
||||
|
||||
# Set variable: force mode overrides existing, otherwise only set if empty
|
||||
if [[ "$force" == "yes" ]]; then
|
||||
export "${var_key}=${var_val}"
|
||||
@ -1324,9 +1429,10 @@ advanced_settings() {
|
||||
if result=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "IPv4 CONFIGURATION" \
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--menu "\nSelect IPv4 Address Assignment:" 14 60 2 \
|
||||
--menu "\nSelect IPv4 Address Assignment:" 16 65 3 \
|
||||
"dhcp" "Automatic (DHCP, recommended)" \
|
||||
"static" "Static (manual entry)" \
|
||||
"range" "IP Range Scan (find first free IP)" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
|
||||
if [[ "$result" == "static" ]]; then
|
||||
@ -1357,6 +1463,42 @@ advanced_settings() {
|
||||
whiptail --msgbox "Invalid IPv4 CIDR format.\nExample: 192.168.1.100/24" 8 58
|
||||
fi
|
||||
fi
|
||||
elif [[ "$result" == "range" ]]; then
|
||||
# IP Range Scan
|
||||
local ip_range
|
||||
if ip_range=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "IP RANGE SCAN" \
|
||||
--ok-button "Scan" --cancel-button "Back" \
|
||||
--inputbox "\nEnter IP range to scan for free address\n(e.g. 192.168.1.100/24-192.168.1.200/24)" 12 65 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if is_ip_range "$ip_range"; then
|
||||
# Exit whiptail screen temporarily to show scan progress
|
||||
clear
|
||||
header_info
|
||||
echo -e "${INFO}${BOLD}${DGN}Scanning IP range for free address...${CL}\n"
|
||||
if resolve_ip_from_range "$ip_range"; then
|
||||
# Get gateway
|
||||
local gateway_ip
|
||||
if gateway_ip=$(whiptail --backtitle "Proxmox VE Helper Scripts [Step $STEP/$MAX_STEP]" \
|
||||
--title "GATEWAY IP" \
|
||||
--ok-button "Next" --cancel-button "Back" \
|
||||
--inputbox "\nFound free IP: $NET_RESOLVED\n\nEnter Gateway IP address" 12 58 "" \
|
||||
3>&1 1>&2 2>&3); then
|
||||
if [[ "$gateway_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
_net="$NET_RESOLVED"
|
||||
_gate=",gw=$gateway_ip"
|
||||
((STEP++))
|
||||
else
|
||||
whiptail --msgbox "Invalid Gateway IP format." 8 58
|
||||
fi
|
||||
fi
|
||||
else
|
||||
whiptail --msgbox "No free IP found in the specified range.\nAll IPs responded to ping." 10 58
|
||||
fi
|
||||
else
|
||||
whiptail --msgbox "Invalid IP range format.\n\nExample: 192.168.1.100/24-192.168.1.200/24" 10 58
|
||||
fi
|
||||
fi
|
||||
else
|
||||
_net="dhcp"
|
||||
_gate=""
|
||||
|
||||
Reference in New Issue
Block a user