Compare commits

..

5 Commits

Author SHA1 Message Date
CanbiZ
6f358d7e5d Add PostGIS extension check to Reitti update_script
Automatically enable PostGIS extension on existing installations if missing.
Checks if extension is already enabled before attempting to create it.

Fixes existing Reitti installations that were created before PostGIS was
added to the initial setup (commit b6312b87d).

Users no longer need to manually run 'CREATE EXTENSION postgis;'
2026-01-05 15:15:59 +01:00
CanbiZ
e44a8e8af8 Add idempotency check for Debian 13 certbot fix
Only apply certbot-dns-multi fix if not already installed.
Checks pip list for certbot-dns-multi before installing golang deps.

Prevents unnecessary reinstallation on repeated update runs.
2026-01-05 15:00:25 +01:00
CanbiZ
b42f9fabe1 Fix NPM API health issues on Debian 13 with certbot-dns-multi
On Debian 13 Trixie, NPM shows 'API isn't healthy' after upgrade.
Install certbot-dns-multi with golang dependencies to fix this.

Changes:
- Install golang, build-essential, git on Debian 13
- Install setuptools-golang==2.9.0 in certbot venv
- Set CGO_ENABLED=1 and GO111MODULE=on for pip install
- Install certbot-dns-multi with --no-build-isolation flag
- Applied to both fresh install and update_script()

Credit: @i4mr000t and @CrazyWolf13
Source: https://v64.tech/t/nginx-proxy-manager-dnschallenge-ipv64-debian-13-fail/4177/7
Fixes: #7489 - NPM Web UI broken after Debian 13 upgrade
2026-01-05 14:59:30 +01:00
CanbiZ
259f14b8e9 Fix openresty suite mapping for Debian 13
Openresty doesn't have trixie packages yet, only bookworm.
Map trixie and sid to use bookworm packages which are compatible.

Available openresty suites: bookworm, bullseye, buster, stretch, jessie
Fixes 404 errors when installing/updating on Debian 13 Trixie
2026-01-05 14:57:40 +01:00
CanbiZ
0fb5fc5ce0 Fix Nginx Proxy Manager for Debian 13 Trixie
- Detect Debian version dynamically from /etc/os-release
- Replace hardcoded 'bookworm' with VERSION_CODENAME in openresty sources
- Fixes both install and update_script() functions
- Ensures openresty repository matches container's Debian version

Fixes: Nginx Proxy Manager update fails on Debian 13 with 404 errors
Previously: Only worked on Debian 12 Bookworm due to hardcoded suite name
2026-01-05 14:56:49 +01:00
14 changed files with 357 additions and 477 deletions

View File

@@ -10,36 +10,14 @@
> [!CAUTION]
Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit the project's popularity for potentially malicious purposes.
## 2026-01-06
## 2026-01-05
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- reitti: add postgis extension to PostgreSQL DB setup [@MickLesk](https://github.com/MickLesk) ([#10555](https://github.com/community-scripts/ProxmoxVE/pull/10555))
- openWRT: separate disk attachment and resizing in VM setup [@MickLesk](https://github.com/MickLesk) ([#10557](https://github.com/community-scripts/ProxmoxVE/pull/10557))
- paperless-ai: Set TMPDIR for pip to use disk during install [@MickLesk](https://github.com/MickLesk) ([#10559](https://github.com/community-scripts/ProxmoxVE/pull/10559))
- #### 🔧 Refactor
- Refactor: Monica [@tremor021](https://github.com/tremor021) ([#10552](https://github.com/community-scripts/ProxmoxVE/pull/10552))
- Upgrade Wazuh LXC Container to Debian 13 [@heinemannj](https://github.com/heinemannj) ([#10551](https://github.com/community-scripts/ProxmoxVE/pull/10551))
- Upgrade evcc LXC to Debian 13 [@heinemannj](https://github.com/heinemannj) ([#10548](https://github.com/community-scripts/ProxmoxVE/pull/10548))
### 💾 Core
- #### 🔧 Refactor
- Harden setup_hwaccel for old Intel GPUs [@MickLesk](https://github.com/MickLesk) ([#10556](https://github.com/community-scripts/ProxmoxVE/pull/10556))
### 🧰 Tools
- #### 🔧 Refactor
- Refactor: IP-Tag (Multiple IP / Performance / Execution Time) [@MickLesk](https://github.com/MickLesk) ([#10558](https://github.com/community-scripts/ProxmoxVE/pull/10558))
## 2026-01-04
### 🚀 Updated Scripts

View File

@@ -27,14 +27,9 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
setup_mariadb
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
# Fix for previous versions not having cronjob
if ! grep -Fq 'php /opt/monica/artisan schedule:run' /etc/crontab; then
echo '* * * * * root php /opt/monica/artisan schedule:run >> /dev/null 2>&1' >>/etc/crontab
fi
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
if check_for_gh_release "monica" "monicahq/monica"; then
msg_info "Stopping Service"

View File

@@ -157,18 +157,39 @@ EOF
[ -f /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg ] && rm -f /etc/apt/trusted.gpg.d/openresty-archive-keyring.gpg
[ -f /etc/apt/sources.list.d/openresty.list ] && rm -f /etc/apt/sources.list.d/openresty.list
[ ! -f /etc/apt/trusted.gpg.d/openresty.gpg ] && curl -fsSL https://openresty.org/package/pubkey.gpg | gpg --dearmor --yes -o /etc/apt/trusted.gpg.d/openresty.gpg
[ ! -f /etc/apt/sources.list.d/openresty.sources ] && cat <<'EOF' >/etc/apt/sources.list.d/openresty.sources
if [ ! -f /etc/apt/sources.list.d/openresty.sources ]; then
DEBIAN_VERSION=$(grep -E '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2)
# Openresty only has bookworm, not trixie - map newer versions to bookworm
case "$DEBIAN_VERSION" in
trixie|sid) OPENRESTY_SUITE="bookworm" ;;
*) OPENRESTY_SUITE="$DEBIAN_VERSION" ;;
esac
cat <<EOF >/etc/apt/sources.list.d/openresty.sources
Types: deb
URIs: http://openresty.org/package/debian/
Suites: bookworm
Suites: ${OPENRESTY_SUITE}
Components: openresty
Signed-By: /etc/apt/trusted.gpg.d/openresty.gpg
EOF
fi
$STD apt update
$STD apt -y install openresty
if [ -d /opt/certbot ]; then
$STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel
$STD /opt/certbot/bin/pip install --upgrade certbot certbot-dns-cloudflare
# Fix for Debian 13 Trixie - certbot-dns-multi needed to prevent "API isn't healthy" error
if [[ $(grep -E '^VERSION_ID=' /etc/os-release) == *"13"* ]]; then
if ! /opt/certbot/bin/pip list 2>/dev/null | grep -q certbot-dns-multi; then
msg_info "Applying Debian 13 Certbot Fix"
$STD apt-get install -y golang build-essential git
$STD /opt/certbot/bin/pip install --no-cache-dir setuptools-golang==2.9.0
export CGO_ENABLED=1
export GO111MODULE=on
$STD /opt/certbot/bin/pip install --no-build-isolation --no-cache-dir certbot-dns-multi
msg_ok "Applied Debian 13 Certbot Fix"
fi
fi
fi
msg_ok "Updated Certbot"

View File

@@ -30,9 +30,9 @@ function update_script() {
# Enable PostGIS extension if not already enabled
if systemctl is-active --quiet postgresql; then
if ! sudo -u postgres psql -d reitti_db -tAc "SELECT 1 FROM pg_extension WHERE extname='postgis'" 2>/dev/null | grep -q 1; then
if ! sudo -u postgres psql -d reitti -tAc "SELECT 1 FROM pg_extension WHERE extname='postgis'" 2>/dev/null | grep -q 1; then
msg_info "Enabling PostGIS extension"
sudo -u postgres psql -d reitti_db -c "CREATE EXTENSION IF NOT EXISTS postgis;" &>/dev/null
sudo -u postgres psql -d reitti -c "CREATE EXTENSION IF NOT EXISTS postgis;" &>/dev/null
msg_ok "Enabled PostGIS extension"
fi
fi

View File

@@ -11,7 +11,7 @@ var_cpu="${var_cpu:-4}"
var_ram="${var_ram:-4096}"
var_disk="${var_disk:-25}"
var_os="${var_os:-debian}"
var_version="${var_version:-13}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"
header_info "$APP"
@@ -27,10 +27,10 @@ function update_script() {
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating Wazuh LXC"
$STD apt update
$STD apt upgrade -y
msg_ok "Updated Wazuh LXC"
msg_info "Updating ${APP} LXC"
$STD apt-get update
$STD apt-get -y upgrade
msg_ok "Updated ${APP} LXC"
msg_ok "Updated successfully!"
exit
}

View File

@@ -1,64 +1,4 @@
[
{
"name": "chrisbenincasa/tunarr",
"version": "v1.1.0-dev.2",
"date": "2026-01-05T21:58:55Z"
},
{
"name": "ZoeyVid/NPMplus",
"version": "2025-05-07-r1",
"date": "2025-05-07T12:18:42Z"
},
{
"name": "livebook-dev/livebook",
"version": "nightly",
"date": "2026-01-05T18:49:45Z"
},
{
"name": "VictoriaMetrics/VictoriaMetrics",
"version": "pmm-6401-v1.133.0",
"date": "2026-01-05T18:31:47Z"
},
{
"name": "zitadel/zitadel",
"version": "v4.8.1",
"date": "2026-01-05T18:12:51Z"
},
{
"name": "leiweibau/Pi.Alert",
"version": "v2026-01-04",
"date": "2026-01-05T17:52:56Z"
},
{
"name": "msgbyte/tianji",
"version": "v1.31.2",
"date": "2026-01-05T17:26:50Z"
},
{
"name": "fosrl/pangolin",
"version": "1.14.1-s.1",
"date": "2026-01-05T16:31:29Z"
},
{
"name": "home-assistant/core",
"version": "2025.12.5",
"date": "2025-12-29T12:55:22Z"
},
{
"name": "n8n-io/n8n",
"version": "n8n@2.2.3",
"date": "2026-01-05T15:11:22Z"
},
{
"name": "Infisical/infisical",
"version": "v0.155.0",
"date": "2026-01-05T15:04:03Z"
},
{
"name": "keycloak/keycloak",
"version": "26.4.7",
"date": "2025-12-01T08:14:11Z"
},
{
"name": "theonedev/onedev",
"version": "v14.0.2",
@@ -69,11 +9,6 @@
"version": "v11.1.2",
"date": "2025-12-17T09:26:24Z"
},
{
"name": "metabase/metabase",
"version": "v0.57.x",
"date": "2026-01-05T10:22:27Z"
},
{
"name": "maxdorninger/MediaManager",
"version": "v1.12.1",
@@ -159,6 +94,11 @@
"version": "1.15.2",
"date": "2026-01-04T13:04:02Z"
},
{
"name": "chrisbenincasa/tunarr",
"version": "v1.0.13",
"date": "2026-01-04T12:59:19Z"
},
{
"name": "tobychui/zoraxy",
"version": "v3.3.1-rc1",
@@ -179,6 +119,11 @@
"version": "2.228.0",
"date": "2026-01-03T16:38:36Z"
},
{
"name": "ZoeyVid/NPMplus",
"version": "2025-05-07-r1",
"date": "2025-05-07T12:18:42Z"
},
{
"name": "homarr-labs/homarr",
"version": "v1.49.1",
@@ -219,10 +164,15 @@
"version": "3.4.6",
"date": "2026-01-02T22:20:47Z"
},
{
"name": "keycloak/keycloak",
"version": "26.4.7",
"date": "2025-12-01T08:14:11Z"
},
{
"name": "mealie-recipes/mealie",
"version": "v3.9.2",
"date": "2026-01-02T19:40:19Z"
"date": "2026-01-02T19:40:09Z"
},
{
"name": "Dokploy/dokploy",
@@ -234,11 +184,26 @@
"version": "v1.15.4",
"date": "2026-01-02T16:20:33Z"
},
{
"name": "metabase/metabase",
"version": "v0.57.x",
"date": "2026-01-02T15:44:38Z"
},
{
"name": "livebook-dev/livebook",
"version": "v0.18.2",
"date": "2025-12-15T19:17:42Z"
},
{
"name": "gotify/server",
"version": "v2.8.0",
"date": "2026-01-02T11:56:16Z"
},
{
"name": "n8n-io/n8n",
"version": "n8n@2.1.5",
"date": "2026-01-02T09:10:15Z"
},
{
"name": "alexta69/metube",
"version": "2026.01.02",
@@ -269,6 +234,11 @@
"version": "2.2.2",
"date": "2025-12-31T16:53:34Z"
},
{
"name": "home-assistant/core",
"version": "2025.12.5",
"date": "2025-12-29T12:55:22Z"
},
{
"name": "emqx/emqx",
"version": "e5.8.9",
@@ -324,6 +294,11 @@
"version": "1.35.1",
"date": "2025-12-30T14:21:05Z"
},
{
"name": "zitadel/zitadel",
"version": "v4.8.0",
"date": "2025-12-30T12:16:28Z"
},
{
"name": "openobserve/openobserve",
"version": "v0.40.0",
@@ -344,6 +319,11 @@
"version": "v5.11.2",
"date": "2025-12-29T21:09:41Z"
},
{
"name": "msgbyte/tianji",
"version": "v1.31.1",
"date": "2025-12-29T16:50:03Z"
},
{
"name": "traefik/traefik",
"version": "v3.6.6",
@@ -439,6 +419,11 @@
"version": "5.2.5",
"date": "2025-12-25T09:23:10Z"
},
{
"name": "fosrl/pangolin",
"version": "1.14.1",
"date": "2025-12-24T21:33:56Z"
},
{
"name": "FreshRSS/FreshRSS",
"version": "1.28.0",
@@ -779,6 +764,11 @@
"version": "353.1",
"date": "2025-12-15T10:29:34Z"
},
{
"name": "VictoriaMetrics/VictoriaMetrics",
"version": "pmm-6401-v1.132.0",
"date": "2025-12-15T09:38:46Z"
},
{
"name": "Prowlarr/Prowlarr",
"version": "v2.3.0.5236",
@@ -829,6 +819,11 @@
"version": "v4.4.0",
"date": "2025-12-13T22:49:07Z"
},
{
"name": "leiweibau/Pi.Alert",
"version": "v2025-12-14",
"date": "2025-12-13T16:39:17Z"
},
{
"name": "WGDashboard/WGDashboard",
"version": "v4.3.1",
@@ -889,6 +884,11 @@
"version": "9.0.1",
"date": "2025-12-09T18:13:25Z"
},
{
"name": "Infisical/infisical",
"version": "v0.154.6",
"date": "2025-12-09T16:36:25Z"
},
{
"name": "element-hq/synapse",
"version": "v1.144.0",

View File

@@ -23,7 +23,7 @@
"ram": 4096,
"hdd": 25,
"os": "debian",
"version": "13"
"version": "12"
}
}
],

View File

@@ -16,8 +16,23 @@ update_os
PHP_VERSION="8.2" PHP_APACHE="YES" PHP_MODULE="dom,gmp,iconv,mysqli,pdo-mysql,redis,tokenizer" setup_php
setup_composer
setup_mariadb
MARIADB_DB_NAME="monica" MARIADB_DB_USER="monica" setup_mariadb_db
NODE_VERSION="22" NODE_MODULE="yarn@latest" setup_nodejs
msg_info "Setting up MariaDB"
DB_NAME=monica
DB_USER=monica
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
$STD mariadb -u root -e "CREATE DATABASE $DB_NAME;"
$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
$STD mariadb -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
{
echo "monica-Credentials"
echo "monica Database User: $DB_USER"
echo "monica Database Password: $DB_PASS"
echo "monica Database Name: $DB_NAME"
} >>~/monica.creds
msg_ok "Set up MariaDB"
fetch_and_deploy_gh_release "monica" "monicahq/monica" "prebuild" "latest" "/opt/monica" "monica-v*.tar.bz2"
msg_info "Configuring monica"
@@ -36,7 +51,6 @@ $STD php artisan key:generate
$STD php artisan setup:production --email=admin@helper-scripts.com --password=helper-scripts.com --force
chown -R www-data:www-data /opt/monica
chmod -R 775 /opt/monica/storage
echo "* * * * * root php /opt/monica/artisan schedule:run >> /dev/null 2>&1" >>/etc/crontab
msg_ok "Configured monica"
msg_info "Creating Service"

View File

@@ -36,15 +36,35 @@ msg_info "Setting up Certbot"
$STD python3 -m venv /opt/certbot
$STD /opt/certbot/bin/pip install --upgrade pip setuptools wheel
$STD /opt/certbot/bin/pip install certbot certbot-dns-cloudflare
# Fix for Debian 13 Trixie - certbot-dns-multi needed to prevent "API isn't healthy" error
if [[ $(grep -E '^VERSION_ID=' /etc/os-release) == *"13"* ]]; then
if ! /opt/certbot/bin/pip list 2>/dev/null | grep -q certbot-dns-multi; then
msg_info "Applying Debian 13 Certbot Fix"
$STD apt-get install -y golang build-essential git
$STD /opt/certbot/bin/pip install --no-cache-dir setuptools-golang==2.9.0
export CGO_ENABLED=1
export GO111MODULE=on
$STD /opt/certbot/bin/pip install --no-build-isolation --no-cache-dir certbot-dns-multi
msg_ok "Applied Debian 13 Certbot Fix"
fi
fi
ln -sf /opt/certbot/bin/certbot /usr/local/bin/certbot
msg_ok "Set up Certbot"
msg_info "Installing Openresty"
curl -fsSL "https://openresty.org/package/pubkey.gpg" | gpg --dearmor -o /etc/apt/trusted.gpg.d/openresty.gpg
cat <<'EOF' >/etc/apt/sources.list.d/openresty.sources
DEBIAN_VERSION=$(grep -E '^VERSION_CODENAME=' /etc/os-release | cut -d'=' -f2)
# Openresty only has bookworm, not trixie - map newer versions to bookworm
case "$DEBIAN_VERSION" in
trixie|sid) OPENRESTY_SUITE="bookworm" ;;
*) OPENRESTY_SUITE="$DEBIAN_VERSION" ;;
esac
cat <<EOF >/etc/apt/sources.list.d/openresty.sources
Types: deb
URIs: http://openresty.org/package/debian/
Suites: bookworm
Suites: ${OPENRESTY_SUITE}
Components: openresty
Signed-By: /etc/apt/trusted.gpg.d/openresty.gpg
EOF

View File

@@ -37,12 +37,8 @@ msg_info "Setup Paperless-AI"
cd /opt/paperless-ai
$STD python3 -m venv /opt/paperless-ai/venv
source /opt/paperless-ai/venv/bin/activate
# TMPDIR to use container disk instead of tmpfs for large pip downloads (https://github.com/community-scripts/ProxmoxVE/issues/10338)
export TMPDIR=/opt/paperless-ai/tmp
mkdir -p "$TMPDIR"
$STD pip install --upgrade pip
$STD pip install --no-cache-dir -r requirements.txt
rm -rf "$TMPDIR"
mkdir -p data/chromadb
$STD npm ci --only=production
mkdir -p /opt/paperless-ai/data

View File

@@ -24,7 +24,7 @@ msg_ok "Installed Dependencies"
JAVA_VERSION="25" setup_java
PG_VERSION="17" PG_MODULES="postgis" setup_postgresql
PG_DB_NAME="reitti_db" PG_DB_USER="reitti" PG_DB_EXTENSIONS="postgis" setup_postgresql_db
PG_DB_NAME="reitti_db" PG_DB_USER="reitti" setup_postgresql_db
msg_info "Configuring RabbitMQ"
RABBIT_USER="reitti"

View File

@@ -2571,12 +2571,6 @@ function setup_gs() {
# - Some things are fetched from intel repositories due to not being in debian repositories.
# ------------------------------------------------------------------------------
function setup_hwaccel() {
# Check if user explicitly disabled GPU in advanced settings
if [[ "${var_gpu:-no}" == "no" ]]; then
msg_info "GPU acceleration disabled by user (var_gpu=no) - skipping setup"
return 0
fi
# Check if GPU passthrough is enabled (device nodes must exist)
# /dev/dri = Intel iGPU, AMD GPU (open-source drivers)
# /dev/nvidia* = NVIDIA proprietary drivers
@@ -2589,14 +2583,14 @@ function setup_hwaccel() {
msg_info "Setup Hardware Acceleration"
if ! command -v lspci &>/dev/null; then
if ! $STD apt -y update; then
msg_warn "Failed to update package list - skipping hardware acceleration setup"
return 0
fi
if ! $STD apt -y install pciutils; then
msg_warn "Failed to install pciutils - skipping hardware acceleration setup"
return 0
fi
$STD apt -y update || {
msg_error "Failed to update package list"
return 1
}
$STD apt -y install pciutils || {
msg_error "Failed to install pciutils"
return 1
}
fi
# Detect GPU vendor (Intel, AMD, NVIDIA)
@@ -2628,76 +2622,34 @@ function setup_hwaccel() {
case "$gpu_vendor" in
Intel)
# Detect Intel GPU generation for driver selection
# Gen 9+ (Skylake 2015 and newer): UHD, Iris, Arc - benefit from latest drivers
# Gen 7-8 (Haswell 2013-Broadwell 2014): HD 4xxx-5xxx - use repo drivers only
# Gen 6 and older (Sandy Bridge 2011 and earlier): HD 2xxx-3xxx - basic repo support
# Gen 9+ (Skylake and newer) benefit from non-free drivers
local intel_gen=""
local use_repo_only=false
local needs_nonfree=false
# Detect older Intel GPUs (Gen 6-8: HD 2xxx through HD 5xxx series)
# These should ONLY use repository packages, not latest GitHub releases
if echo "$gpu_info" | grep -Ei 'HD Graphics [2-5][0-9]{3}' &>/dev/null; then
use_repo_only=true
intel_gen="gen6-8"
msg_info "Detected older Intel GPU (HD 2000-5999) - using stable repository drivers only"
# Detect newer Intel GPUs (Gen 9+: HD 6xxx+, UHD, Iris, Arc)
elif echo "$gpu_info" | grep -Ei 'HD Graphics [6-9][0-9]{2,3}|UHD Graphics|Iris|Arc|DG[12]' &>/dev/null; then
# Check for specific Intel GPU models that need non-free drivers
if echo "$gpu_info" | grep -Ei 'HD Graphics [56][0-9]{2}|UHD Graphics|Iris|Arc|DG[12]' &>/dev/null; then
needs_nonfree=true
intel_gen="gen9+"
msg_info "Detected newer Intel GPU (Gen 9+) - installing latest drivers"
else
# Unknown Intel GPU - play it safe with repo only
use_repo_only=true
intel_gen="unknown"
msg_warn "Unknown Intel GPU detected - using stable repository drivers only"
fi
if [[ "$os_id" == "ubuntu" ]]; then
# Ubuntu: Use packages from Ubuntu repos
if ! $STD apt -y install \
$STD apt -y install \
va-driver-all \
ocl-icd-libopencl1 \
intel-opencl-icd \
vainfo \
intel-gpu-tools; then
msg_warn "Failed to install Intel GPU dependencies - skipping hardware acceleration"
return 0
fi
# Try newer packages that may not be available on all versions
$STD apt -y install intel-opencl-icd 2>/dev/null || msg_warn "intel-opencl-icd not available, skipping"
$STD apt -y install libmfx-gen1.2 2>/dev/null || msg_warn "libmfx-gen1.2 not available, skipping"
$STD apt -y install intel-media-va-driver 2>/dev/null || msg_warn "intel-media-va-driver not available, skipping"
libmfx-gen1.2 \
intel-gpu-tools || {
msg_error "Failed to install Intel GPU dependencies"
return 1
}
# Try to install intel-media-va-driver for newer GPUs
$STD apt -y install intel-media-va-driver 2>/dev/null || true
elif [[ "$os_id" == "debian" ]]; then
# For older GPUs or when we want repo-only packages
if [[ "$use_repo_only" == true ]]; then
msg_info "Installing Intel GPU drivers from Debian repositories"
# Fix any broken packages first
$STD apt --fix-broken install -y 2>/dev/null || true
# Install base VA-API and tools (these should always work)
if ! $STD apt -y install \
va-driver-all \
i965-va-driver \
vainfo \
intel-gpu-tools \
ocl-icd-libopencl1; then
msg_warn "Failed to install base Intel GPU support - skipping hardware acceleration"
return 0
fi
# Try to install additional packages that might help but aren't critical
$STD apt -y install mesa-va-drivers 2>/dev/null || msg_warn "mesa-va-drivers not available"
# Skip intel-opencl-icd on Debian 12 (Bookworm) - causes dependency issues with old GPUs
if [[ "$os_codename" != "bookworm" ]]; then
$STD apt -y install intel-opencl-icd 2>/dev/null || msg_warn "OpenCL support not available from repositories"
fi
msg_ok "Installed Intel GPU drivers from Debian repositories (stable)"
# For newer GPUs, try non-free drivers first, then fallback
elif [[ "$needs_nonfree" == true ]]; then
# Debian: Check version and install appropriate drivers
if [[ "$needs_nonfree" == true ]]; then
# Add non-free repo for intel-media-va-driver-non-free
if [[ "$os_codename" == "bookworm" ]]; then
# Debian 12 Bookworm
@@ -2710,37 +2662,16 @@ Components: non-free non-free-firmware
EOF
$STD apt update
fi
# Fetch Intel IGC packages from GitHub - not available in Debian 12 repos
# intel-opencl-icd and libigdgmm12 are available, so we install those via apt
msg_info "Installing Intel IGC packages from GitHub releases"
fetch_and_deploy_gh_release "intel-igc-core" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core_*_amd64.deb" || {
msg_warn "Failed to deploy Intel IGC core"
}
fetch_and_deploy_gh_release "intel-graphics-compiler" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-graphics-compiler_*_amd64.deb" || {
msg_warn "Failed to deploy Intel graphics compiler"
}
fetch_and_deploy_gh_release "intel-igc-opencl" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl_*_amd64.deb" || {
msg_warn "Failed to deploy Intel IGC OpenCL"
}
# Try installing non-free drivers for newer Intel GPUs
if $STD apt -y install \
$STD apt -y install \
intel-media-va-driver-non-free \
intel-opencl-icd \
libigdgmm12 \
ocl-icd-libopencl1 \
intel-opencl-icd \
vainfo \
libmfx-gen1.2 \
intel-gpu-tools; then
msg_ok "Installed Intel non-free drivers for Gen 9+ GPU"
else
msg_warn "Non-free driver install failed, falling back to repository drivers"
use_repo_only=true
fi
intel-gpu-tools || {
msg_warn "Non-free driver install failed, falling back to open drivers"
needs_nonfree=false
}
elif [[ "$os_codename" == "trixie" || "$os_codename" == "sid" ]]; then
# Debian 13 Trixie / Sid
@@ -2758,88 +2689,62 @@ Components: non-free non-free-firmware
EOF
$STD apt update
fi
# Fetch Intel packages from GitHub - not available in Debian 13 repos
# libigdgmm12 is available in trixie, but intel-opencl-icd is missing
msg_info "Installing Intel packages from GitHub releases"
fetch_and_deploy_gh_release "intel-igc-core" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core_*_amd64.deb" || {
msg_warn "Failed to deploy Intel IGC core"
}
fetch_and_deploy_gh_release "intel-graphics-compiler" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-graphics-compiler_*_amd64.deb" || {
msg_warn "Failed to deploy Intel graphics compiler"
}
fetch_and_deploy_gh_release "intel-igc-opencl" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl_*_amd64.deb" || {
msg_warn "Failed to deploy Intel IGC OpenCL"
}
fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || {
msg_warn "Failed to deploy Intel OpenCL ICD (missing from trixie repos)"
}
# Try installing packages for Debian 13
if $STD apt -y install \
$STD apt -y install \
intel-media-va-driver-non-free \
libigdgmm12 \
ocl-icd-libopencl1 \
mesa-opencl-icd \
mesa-va-drivers \
libvpl2 \
vainfo \
libmfx-gen1.2 \
intel-gpu-tools 2>/dev/null; then
msg_ok "Installed Intel drivers for Gen 9+ GPU (Debian 13)"
else
msg_warn "Advanced driver install failed, falling back to repository drivers"
use_repo_only=true
fi
else
# Unknown Debian version - use repo only
use_repo_only=true
intel-gpu-tools 2>/dev/null || {
msg_warn "Non-free driver install failed, falling back to open drivers"
needs_nonfree=false
}
fi
fi
# Fallback: If we set use_repo_only during error handling above
if [[ "$use_repo_only" == true && "$needs_nonfree" == true ]]; then
msg_info "Installing fallback Intel GPU drivers from repositories"
# Fallback to open drivers or older Intel GPUs
if [[ "$needs_nonfree" == false ]]; then
# Fetch latest Intel drivers from GitHub for Debian
fetch_and_deploy_gh_release "intel-igc-core" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-core-2_*_amd64.deb" || {
msg_warn "Failed to deploy Intel IGC core 2"
}
fetch_and_deploy_gh_release "intel-igc-opencl" "intel/intel-graphics-compiler" "binary" "latest" "" "intel-igc-opencl-2_*_amd64.deb" || {
msg_warn "Failed to deploy Intel IGC OpenCL 2"
}
fetch_and_deploy_gh_release "libigdgmm12" "intel/compute-runtime" "binary" "latest" "" "libigdgmm12_*_amd64.deb" || {
msg_warn "Failed to deploy Intel GDGMM12"
}
fetch_and_deploy_gh_release "intel-opencl-icd" "intel/compute-runtime" "binary" "latest" "" "intel-opencl-icd_*_amd64.deb" || {
msg_warn "Failed to deploy Intel OpenCL ICD"
}
# Fix any broken packages from failed install attempts
$STD apt --fix-broken install -y 2>/dev/null || true
$STD apt -y autoremove 2>/dev/null || true
# Remove any partially installed packages that are causing issues
dpkg -l | grep -E 'intel-igc|libigdgmm|intel-opencl-icd' | awk '{print $2}' | xargs -r dpkg --purge 2>/dev/null || true
# Clean install of stable repository packages
if ! $STD apt -y install \
$STD apt -y install \
va-driver-all \
i965-va-driver \
ocl-icd-libopencl1 \
mesa-opencl-icd \
mesa-va-drivers \
vainfo \
intel-gpu-tools; then
msg_warn "Failed to install fallback Intel GPU dependencies - skipping hardware acceleration"
return 0
fi
msg_ok "Installed fallback Intel GPU drivers from repositories"
intel-gpu-tools || {
msg_error "Failed to install Intel GPU dependencies"
return 1
}
fi
fi
;;
AMD)
if ! $STD apt -y install \
$STD apt -y install \
mesa-va-drivers \
mesa-vdpau-drivers \
mesa-opencl-icd \
ocl-icd-libopencl1 \
vainfo \
clinfo 2>/dev/null; then
msg_warn "Failed to install AMD GPU dependencies - skipping hardware acceleration"
return 0
fi
clinfo 2>/dev/null || {
msg_error "Failed to install AMD GPU dependencies"
return 1
}
# For AMD GPUs, firmware-amd-graphics requires non-free repositories
if [[ "$os_id" == "debian" ]]; then
@@ -2914,33 +2819,19 @@ EOF
# Set permissions for /dev/dri (only in privileged containers and if /dev/dri exists)
if [[ "$in_ct" == "0" && -d /dev/dri ]]; then
# Verify /dev/dri contains actual device nodes
if ls /dev/dri/card* /dev/dri/renderD* &>/dev/null; then
chgrp video /dev/dri 2>/dev/null || true
chmod 755 /dev/dri 2>/dev/null || true
chmod 660 /dev/dri/* 2>/dev/null || true
$STD adduser "$(id -u -n)" video 2>/dev/null || true
$STD adduser "$(id -u -n)" render 2>/dev/null || true
chgrp video /dev/dri 2>/dev/null || true
chmod 755 /dev/dri 2>/dev/null || true
chmod 660 /dev/dri/* 2>/dev/null || true
$STD adduser "$(id -u -n)" video 2>/dev/null || true
$STD adduser "$(id -u -n)" render 2>/dev/null || true
# Sync GID for video/render groups between host and container
local host_video_gid host_render_gid
host_video_gid=$(getent group video | cut -d: -f3)
host_render_gid=$(getent group render | cut -d: -f3)
if [[ -n "$host_video_gid" && -n "$host_render_gid" ]]; then
sed -i "s/^video:x:[0-9]*:/video:x:$host_video_gid:/" /etc/group 2>/dev/null || true
sed -i "s/^render:x:[0-9]*:/render:x:$host_render_gid:/" /etc/group 2>/dev/null || true
fi
# Basic GPU functionality test
if command -v vainfo &>/dev/null; then
if vainfo &>/dev/null; then
msg_info "GPU hardware acceleration verified and working"
else
msg_warn "GPU drivers installed but vainfo test failed - check host GPU passthrough configuration"
fi
fi
else
msg_warn "/dev/dri exists but contains no device nodes - GPU passthrough may not be configured correctly"
# Sync GID for video/render groups between host and container
local host_video_gid host_render_gid
host_video_gid=$(getent group video | cut -d: -f3)
host_render_gid=$(getent group render | cut -d: -f3)
if [[ -n "$host_video_gid" && -n "$host_render_gid" ]]; then
sed -i "s/^video:x:[0-9]*:/video:x:$host_video_gid:/" /etc/group 2>/dev/null || true
sed -i "s/^render:x:[0-9]*:/render:x:$host_render_gid:/" /etc/group 2>/dev/null || true
fi
fi
@@ -3373,12 +3264,12 @@ setup_mariadb() {
# Configure tmpfiles.d to ensure /run/mysqld directory is created on boot
# This fixes the issue where MariaDB fails to start after container reboot
msg_info "Configuring MariaDB runtime directory persistence"
# Create tmpfiles.d configuration with error handling
if ! printf '# Ensure /run/mysqld directory exists with correct permissions for MariaDB\nd /run/mysqld 0755 mysql mysql -\n' >/etc/tmpfiles.d/mariadb.conf; then
if ! printf '# Ensure /run/mysqld directory exists with correct permissions for MariaDB\nd /run/mysqld 0755 mysql mysql -\n' > /etc/tmpfiles.d/mariadb.conf; then
msg_warn "Failed to create /etc/tmpfiles.d/mariadb.conf - runtime directory may not persist on reboot"
fi
# Create the directory now if it doesn't exist
# Verify mysql user exists before attempting ownership change
if [[ ! -d /run/mysqld ]]; then
@@ -3392,7 +3283,7 @@ setup_mariadb() {
msg_warn "mysql user not found - directory created with correct permissions but ownership not set"
fi
fi
msg_ok "Configured MariaDB runtime directory persistence"
cache_installed_version "mariadb" "$MARIADB_VERSION"

View File

@@ -57,7 +57,7 @@ spinner() {
local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
local spin_i=0
local interval=0.1
trap 'exit 0' TERM INT
printf "\e[?25l" 2>/dev/null
@@ -107,6 +107,7 @@ migrate_config() {
fi
}
# Update existing installation
update_installation() {
msg_info "Updating IP-Tag Scripts"
@@ -178,7 +179,7 @@ EOF
systemctl daemon-reload &>/dev/null
systemctl enable -q --now iptag.service &>/dev/null
msg_ok "Updated IP-Tag Scripts"
# Show configuration information after update
show_post_install_info
}
@@ -186,7 +187,7 @@ EOF
# Install only command without service
install_command_only() {
msg_info "Installing IP-Tag Command Only"
# Create directory if it doesn't exist
if [[ ! -d "/opt/iptag" ]]; then
mkdir -p /opt/iptag
@@ -206,15 +207,15 @@ install_command_only() {
echo -e "\n${YW}Configuration file already exists.${CL}"
read -p "Do you want to reconfigure tag format? (y/n): " reconfigure
case $reconfigure in
[Yy]*)
interactive_config_setup_command
msg_info "Updating Configuration"
generate_config >/opt/iptag/iptag.conf
msg_ok "Updated configuration file"
;;
*)
msg_ok "Keeping existing configuration file"
;;
[Yy]*)
interactive_config_setup_command
msg_info "Updating Configuration"
generate_config >/opt/iptag/iptag.conf
msg_ok "Updated configuration file"
;;
*)
msg_ok "Keeping existing configuration file"
;;
esac
fi
@@ -239,7 +240,7 @@ exec "$SCRIPT_FILE"
EOF
chmod +x /usr/local/bin/iptag-run
msg_ok "Created iptag-run command"
msg_ok "IP-Tag Command installed successfully! Use 'iptag-run' to run manually."
}
@@ -247,14 +248,14 @@ EOF
show_post_install_info() {
stop_spinner
echo -e "\n${YW}=== Next Steps ===${CL}"
# Show usage information
if command -v iptag-run >/dev/null 2>&1; then
echo -e "${YW}Run IP tagging manually: ${GN}iptag-run${CL}"
echo -e "${YW}Add to cron for scheduled execution if needed${CL}"
echo -e ""
fi
echo -e "${RD}IMPORTANT: Configure your network subnets!${CL}"
echo -e ""
echo -e "${YW}Configuration file: ${GN}/opt/iptag/iptag.conf${CL}"
@@ -273,37 +274,37 @@ show_post_install_info() {
# Interactive configuration setup for command-only (TAG_FORMAT only)
interactive_config_setup_command() {
echo -e "\n${YW}=== Configuration Setup ===${CL}"
# TAG_FORMAT configuration
echo -e "\n${YW}Select tag format:${CL}"
echo -e "${GN}1)${CL} last_two_octets - Show last two octets (e.g., 0.100) [Default]"
echo -e "${GN}2)${CL} last_octet - Show only last octet (e.g., 100)"
echo -e "${GN}3)${CL} full - Show full IP address (e.g., 192.168.0.100)"
while true; do
read -p "Enter your choice (1-3) [1]: " tag_choice
case ${tag_choice:-1} in
1)
TAG_FORMAT="last_two_octets"
echo -e "${GN}✓ Selected: last_two_octets${CL}"
break
;;
2)
TAG_FORMAT="last_octet"
echo -e "${GN}✓ Selected: last_octet${CL}"
break
;;
3)
TAG_FORMAT="full"
echo -e "${GN}✓ Selected: full${CL}"
break
;;
*)
echo -e "${RD}Please enter 1, 2, or 3.${CL}"
;;
1)
TAG_FORMAT="last_two_octets"
echo -e "${GN}✓ Selected: last_two_octets${CL}"
break
;;
2)
TAG_FORMAT="last_octet"
echo -e "${GN}✓ Selected: last_octet${CL}"
break
;;
3)
TAG_FORMAT="full"
echo -e "${GN}✓ Selected: full${CL}"
break
;;
*)
echo -e "${RD}Please enter 1, 2, or 3.${CL}"
;;
esac
done
# Set default LOOP_INTERVAL for command mode
LOOP_INTERVAL=300
}
@@ -311,46 +312,46 @@ interactive_config_setup_command() {
# Interactive configuration setup for service (TAG_FORMAT + LOOP_INTERVAL)
interactive_config_setup() {
echo -e "\n${YW}=== Configuration Setup ===${CL}"
# TAG_FORMAT configuration
echo -e "\n${YW}Select tag format:${CL}"
echo -e "${GN}1)${CL} last_two_octets - Show last two octets (e.g., 0.100) [Default]"
echo -e "${GN}2)${CL} last_octet - Show only last octet (e.g., 100)"
echo -e "${GN}3)${CL} full - Show full IP address (e.g., 192.168.0.100)"
while true; do
read -p "Enter your choice (1-3) [1]: " tag_choice
case ${tag_choice:-1} in
1)
TAG_FORMAT="last_two_octets"
echo -e "${GN}✓ Selected: last_two_octets${CL}"
break
;;
2)
TAG_FORMAT="last_octet"
echo -e "${GN}✓ Selected: last_octet${CL}"
break
;;
3)
TAG_FORMAT="full"
echo -e "${GN}✓ Selected: full${CL}"
break
;;
*)
echo -e "${RD}Please enter 1, 2, or 3.${CL}"
;;
1)
TAG_FORMAT="last_two_octets"
echo -e "${GN}✓ Selected: last_two_octets${CL}"
break
;;
2)
TAG_FORMAT="last_octet"
echo -e "${GN}✓ Selected: last_octet${CL}"
break
;;
3)
TAG_FORMAT="full"
echo -e "${GN}✓ Selected: full${CL}"
break
;;
*)
echo -e "${RD}Please enter 1, 2, or 3.${CL}"
;;
esac
done
# LOOP_INTERVAL configuration
echo -e "\n${YW}Set check interval (in seconds):${CL}"
echo -e "${YW}Default: 300 seconds (5 minutes)${CL}"
echo -e "${YW}Recommended range: 300-3600 seconds${CL}"
while true; do
read -p "Enter interval in seconds [300]: " interval_input
interval_input=${interval_input:-300}
if [[ $interval_input =~ ^[0-9]+$ ]] && [ $interval_input -ge 300 ] && [ $interval_input -le 7200 ]; then
LOOP_INTERVAL=$interval_input
echo -e "${GN}✓ Selected: ${LOOP_INTERVAL} seconds${CL}"
@@ -645,40 +646,21 @@ get_vm_ips() {
echo "$unique_ips"
}
# Cache for configs to avoid repeated reads
declare -A CONFIG_CACHE
declare -A IP_CACHE
# Update tags for container or VM
update_tags() {
local type="$1" vmid="$2"
local current_ips_full
local current_tags_raw=""
# Get IPs with caching
local cache_key="${type}_${vmid}"
if [[ -n "${IP_CACHE[$cache_key]:-}" ]]; then
current_ips_full="${IP_CACHE[$cache_key]}"
debug_log "$type $vmid: using cached IPs"
else
if [[ "$type" == "lxc" ]]; then
current_ips_full=$(get_lxc_ips "${vmid}")
else
current_ips_full=$(get_vm_ips "${vmid}")
fi
IP_CACHE[$cache_key]="$current_ips_full"
fi
# Get current tags (optimized file reading)
if [[ "$type" == "lxc" ]]; then
local config_file="/etc/pve/lxc/${vmid}.conf"
if [[ -f "$config_file" ]]; then
current_tags_raw=$(grep "^tags:" "$config_file" 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//')
fi
current_ips_full=$(get_lxc_ips "${vmid}")
while IFS= read -r line; do
[[ "$line" == tags:* ]] && current_tags_raw="${line#tags: }" && break
done < <(pct config "$vmid" 2>/dev/null)
else
current_ips_full=$(get_vm_ips "${vmid}")
local vm_config="/etc/pve/qemu-server/${vmid}.conf"
if [[ -f "$vm_config" ]]; then
current_tags_raw=$(grep "^tags:" "$vm_config" 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//')
local current_tags_raw=$(grep "^tags:" "$vm_config" 2>/dev/null | cut -d: -f2 | sed 's/^[[:space:]]*//')
fi
fi
@@ -836,15 +818,11 @@ update_tags() {
update_all_tags() {
local type="$1" vmids count=0
# Get list of all containers/VMs
if [[ "$type" == "lxc" ]]; then
vmids=($(pct list 2>/dev/null | grep -v VMID | awk '{print $1}'))
else
# More efficient: direct file listing instead of ls+sed
vmids=()
for conf in /etc/pve/qemu-server/*.conf 2>/dev/null; do
[[ -f "$conf" ]] && vmids+=("${conf##*/}" | sed 's/\.conf$//')
done
local all_vm_configs=($(ls /etc/pve/qemu-server/*.conf 2>/dev/null | sed 's/.*\/\([0-9]*\)\.conf/\1/' | sort -n))
vmids=("${all_vm_configs[@]}")
fi
count=${#vmids[@]}
@@ -852,16 +830,14 @@ update_all_tags() {
# Display processing header with color
if [[ "$type" == "lxc" ]]; then
log_info "Processing ${WHITE}${count}${NC} LXC container(s)"
log_info "Processing ${WHITE}${count}${NC} LXC container(s) sequentially"
else
log_info "Processing ${WHITE}${count}${NC} virtual machine(s)"
log_info "Processing ${WHITE}${count}${NC} virtual machine(s) sequentially"
fi
# Process each VM/LXC container
local processed=0
# Process each VM/LXC container sequentially
for vmid in "${vmids[@]}"; do
update_tags "$type" "$vmid"
((processed++))
done
# Add completion message
@@ -872,25 +848,32 @@ update_all_tags() {
fi
}
# Check if status changed
check_status_changed() {
local type="$1" current
case "$type" in
"lxc") current=$(pct list 2>/dev/null | grep -v VMID) ;;
"vm") current=$(ls -la /etc/pve/qemu-server/*.conf 2>/dev/null) ;;
"fw") current=$(ip link show type bridge 2>/dev/null) ;;
esac
local last_var="last_${type}_status"
[[ "${!last_var}" == "$current" ]] && return 1
eval "$last_var='$current'"
return 0
}
# Main check function
check() {
local start_time=$(date +%s)
local current_time=$(date +%s)
# Simple periodic check - always update both LXC and VM every loop
log_info "Starting periodic check"
# Clear caches before each run
CONFIG_CACHE=()
IP_CACHE=()
# Update LXC containers
update_all_tags "lxc"
# Update VMs
update_all_tags "vm"
local end_time=$(date +%s)
local duration=$((end_time - start_time))
log_success "Check completed in ${WHITE}${duration}${NC} seconds"
}
# Main loop
@@ -934,54 +917,40 @@ get_lxc_ips() {
local ips=""
# Method 1: Check Proxmox config for ALL static IPs (multiple interfaces)
# Method 1: Check Proxmox config for static IP
local pve_lxc_config="/etc/pve/lxc/${vmid}.conf"
if [[ -f "$pve_lxc_config" ]]; then
local static_ips=$(grep -E "^net[0-9]+:" "$pve_lxc_config" 2>/dev/null | grep -oE 'ip=([0-9]{1,3}\.){3}[0-9]{1,3}' | cut -d'=' -f2)
if [[ -n "$static_ips" ]]; then
while IFS= read -r ip; do
if [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
debug_log "lxc $vmid: found static IP $ip in config"
ips="${ips}${ips:+ }${ip}"
fi
done <<< "$static_ips"
local static_ip=$(grep -E "^net[0-9]+:" "$pve_lxc_config" 2>/dev/null | grep -oE 'ip=([0-9]{1,3}\.){3}[0-9]{1,3}' | cut -d'=' -f2 | head -1)
if [[ -n "$static_ip" && "$static_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
debug_log "lxc $vmid: found static IP $static_ip in config"
ips="$static_ip"
fi
fi
# Method 2: ARP table lookup for ALL MAC addresses if no static IPs found
# Method 2: ARP table lookup if no static IP
if [[ -z "$ips" && -f "$pve_lxc_config" ]]; then
local mac_addrs=$(grep -Eo 'hwaddr=([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}' "$pve_lxc_config" | cut -d'=' -f2)
if [[ -n "$mac_addrs" ]]; then
while IFS= read -r mac_addr; do
[[ -z "$mac_addr" ]] && continue
local arp_ip=$(ip neighbor show | grep -i "$mac_addr" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1)
if [[ -n "$arp_ip" && "$arp_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
debug_log "lxc $vmid: found IP $arp_ip via ARP table for MAC $mac_addr"
ips="${ips}${ips:+ }${arp_ip}"
fi
done <<< "$mac_addrs"
local mac_addr=$(grep -Eo 'hwaddr=([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}' "$pve_lxc_config" | head -1 | cut -d'=' -f2)
if [[ -n "$mac_addr" ]]; then
local bridge_name=$(grep -Eo 'bridge=[^,]+' "$pve_lxc_config" | head -1 | cut -d'=' -f2)
local arp_ip=$(ip neighbor show | grep "$mac_addr" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -1)
if [[ -n "$arp_ip" && "$arp_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
debug_log "lxc $vmid: found IP $arp_ip via ARP table"
ips="$arp_ip"
fi
fi
fi
# Method 3: Direct container command to get ALL IPs if previous methods failed
# Method 3: Direct container command if ARP failed
if [[ -z "$ips" ]]; then
local container_ips=$(timeout 5s pct exec "$vmid" -- ip -4 addr show 2>/dev/null | grep -oE 'inet ([0-9]{1,3}\.){3}[0-9]{1,3}' | awk '{print $2}' | grep -v '127.0.0.1')
if [[ -n "$container_ips" ]]; then
while IFS= read -r ip; do
if is_valid_ipv4 "$ip"; then
debug_log "lxc $vmid: found IP $ip via pct exec"
ips="${ips}${ips:+ }${ip}"
fi
done <<< "$container_ips"
local container_ip=$(timeout 5s pct exec "$vmid" -- ip -4 addr show 2>/dev/null | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | grep -v '127.0.0.1' | head -1)
if [[ -n "$container_ip" ]] && is_valid_ipv4 "$container_ip"; then
debug_log "lxc $vmid: found IP $container_ip via pct exec"
ips="$container_ip"
fi
fi
# Remove duplicates and clean up
local unique_ips=$(echo "$ips" | tr ' ' '\n' | sort -u | tr '\n' ' ')
unique_ips="${unique_ips% }"
debug_log "lxc $vmid: final IPs: '$unique_ips'"
echo "$unique_ips"
debug_log "lxc $vmid: final IPs: '$ips'"
echo "$ips"
}
main
@@ -998,28 +967,28 @@ echo -e "${RD}4)${CL} Cancel"
while true; do
read -p "Enter your choice (1-4): " choice
case $choice in
1)
INSTALL_MODE="service"
echo -e "${GN}✓ Selected: Service installation${CL}"
break
;;
2)
INSTALL_MODE="command"
echo -e "${GN}✓ Selected: Command-only installation${CL}"
break
;;
3)
echo -e "${GN}✓ Selected: Update installation${CL}"
update_installation
exit 0
;;
4)
msg_error "Action cancelled."
exit 0
;;
*)
msg_error "Please enter 1, 2, 3, or 4."
;;
1)
INSTALL_MODE="service"
echo -e "${GN}✓ Selected: Service installation${CL}"
break
;;
2)
INSTALL_MODE="command"
echo -e "${GN}✓ Selected: Command-only installation${CL}"
break
;;
3)
echo -e "${GN}✓ Selected: Update installation${CL}"
update_installation
exit 0
;;
4)
msg_error "Action cancelled."
exit 0
;;
*)
msg_error "Please enter 1, 2, 3, or 4."
;;
esac
done
@@ -1074,15 +1043,15 @@ if [[ "$INSTALL_MODE" == "service" ]]; then
echo -e "\n${YW}Configuration file already exists.${CL}"
read -p "Do you want to reconfigure tag format and loop interval? (y/n): " reconfigure
case $reconfigure in
[Yy]*)
interactive_config_setup
msg_info "Updating Configuration"
generate_config >/opt/iptag/iptag.conf
msg_ok "Updated configuration file"
;;
*)
msg_ok "Keeping existing configuration file"
;;
[Yy]*)
interactive_config_setup
msg_info "Updating Configuration"
generate_config >/opt/iptag/iptag.conf
msg_ok "Updated configuration file"
;;
*)
msg_ok "Keeping existing configuration file"
;;
esac
fi
@@ -1114,21 +1083,21 @@ exec "$SCRIPT_FILE"
EOF
chmod +x /usr/local/bin/iptag-run
msg_ok "Created iptag-run command"
echo -e "\n${GN}${APP} service installation completed successfully! ${CL}"
echo -e "${YW}The service is now running automatically.${CL}"
echo -e "${YW}You can also run it manually with: ${GN}iptag-run${CL}\n"
# Show configuration information
show_post_install_info
elif [[ "$INSTALL_MODE" == "command" ]]; then
# Command-only installation
install_command_only
stop_spinner
echo -e "\n${GN}${APP} command installation completed successfully! ${CL}"
# Show configuration information
show_post_install_info
fi

View File

@@ -552,14 +552,10 @@ fi
qm set "$VMID" \
-efidisk0 "${STORAGE}:0,efitype=4m,size=4M" \
-scsi0 "${DISK_REF}" \
-scsi0 "${DISK_REF},size=${DISK_SIZE}" \
-boot order=scsi0 \
-tags community-script >/dev/null
msg_ok "Attached disk"
msg_info "Resizing disk to ${DISK_SIZE}"
qm disk resize "$VMID" scsi0 "${DISK_SIZE}" >/dev/null
msg_ok "Resized disk to ${DISK_SIZE}"
msg_ok "Attached disk (${DISK_SIZE})"
DESCRIPTION=$(
cat <<EOF