diff --git a/.github/workflows/script-test.yaml b/.github/workflows/script-test.yaml
index 5c88039..b41c20e 100644
--- a/.github/workflows/script-test.yaml
+++ b/.github/workflows/script-test.yaml
@@ -12,18 +12,18 @@ on:
jobs:
run-install-script:
runs-on: pvenode
- steps:
+ steps:
- name: Checkout PR branch
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
- fetch-depth: 0
-
+ fetch-depth: 0
+
- name: Add Git safe directory
run: |
git config --global --add safe.directory /__w/ProxmoxVE/ProxmoxVE
-
+
- name: Set up GH_TOKEN
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -38,15 +38,15 @@ jobs:
echo "SCRIPT=$CHANGED_FILES" >> $GITHUB_ENV
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-
+
- name: Get scripts
id: check-install-script
run: |
ALL_FILES=()
- ADDED_FILES=()
- for FILE in ${{ env.SCRIPT }}; do
- if [[ $FILE =~ ^install/.*-install\.sh$ ]] || [[ $FILE =~ ^ct/.*\.sh$ ]]; then
+ ADDED_FILES=()
+ for FILE in ${{ env.SCRIPT }}; do
+ if [[ $FILE =~ ^install/.*-install\.sh$ ]] || [[ $FILE =~ ^ct/.*\.sh$ ]]; then
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
if [[ ! " ${ADDED_FILES[@]} " =~ " $STRIPPED_NAME " ]]; then
ALL_FILES+=("$FILE")
@@ -57,14 +57,14 @@ jobs:
ALL_FILES=$(echo "${ALL_FILES[@]}" | xargs)
echo "$ALL_FILES"
echo "ALL_FILES=$ALL_FILES" >> $GITHUB_ENV
-
+
- name: Run scripts
id: run-install
continue-on-error: true
run: |
- set +e
+ set +e
#run for each files in /ct
- for FILE in ${{ env.ALL_FILES }}; do
+ for FILE in ${{ env.ALL_FILES }}; do
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
echo "Running Test for: $STRIPPED_NAME"
if grep -E -q 'read\s+-r\s+-p\s+".*"\s+\w+' "$FILE"; then
@@ -93,7 +93,7 @@ jobs:
ERROR_MSG="No install script found for $FILE"
echo "$ERROR_MSG" > result_$STRIPPED_NAME.log
continue
- fi
+ fi
echo "Found install script for $STRIPPED_NAME"
chmod +x "$INSTALL_SCRIPT"
RUNNING_FILE=$FILE
@@ -112,13 +112,15 @@ jobs:
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-install.func
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-alpine-install.func
git checkout community-scripts/main -- .github/workflows/scripts/app-test/pr-create-lxc.sh
- chmod +x $RUNNING_FILE
+ chmod +x $RUNNING_FILE
chmod +x .github/workflows/scripts/app-test/pr-create-lxc.sh
chmod +x .github/workflows/scripts/app-test/pr-install.func
chmod +x .github/workflows/scripts/app-test/pr-alpine-install.func
chmod +x .github/workflows/scripts/app-test/pr-build.func
sed -i 's|source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)|source .github/workflows/scripts/app-test/pr-build.func|g' "$RUNNING_FILE"
echo "Executing $RUNNING_FILE"
+ export TERM=xterm-256color
+ ./$RUNNING_FILE
ERROR_MSG=$(./$RUNNING_FILE 2>&1 > /dev/null)
echo "Finished running $FILE"
if [ -n "$ERROR_MSG" ]; then
@@ -127,38 +129,38 @@ jobs:
fi
done
set -e # Restore exit-on-error
-
+
- name: Cleanup PVE Node
run: |
containers=$(pct list | tail -n +2 | awk '{print $0 " " $4}' | awk '{print $1}')
-
+
for container_id in $containers; do
status=$(pct status $container_id | awk '{print $2}')
if [[ $status == "running" ]]; then
pct stop $container_id
pct destroy $container_id
- fi
+ fi
done
-
+
- name: Post error comments
run: |
ERROR="false"
SEARCH_LINE=".github/workflows/scripts/app-test/pr-build.func: line 255:"
-
+
# Get all existing comments on the PR
- EXISTING_COMMENTS=$(gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --json comments --jq '.comments[].body')
-
+ #EXISTING_COMMENTS=$(gh pr view ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --json comments --jq '.comments[].body')
+ EXISTING_COMMENTS="NONE"
for FILE in ${{ env.ALL_FILES }}; do
STRIPPED_NAME=$(basename "$FILE" | sed 's/-install//' | sed 's/\.sh$//')
if [[ ! -f result_$STRIPPED_NAME.log ]]; then
continue
fi
ERROR_MSG=$(cat result_$STRIPPED_NAME.log)
-
+
if [ -n "$ERROR_MSG" ]; then
CLEANED_ERROR_MSG=$(echo "$ERROR_MSG" | sed "s|$SEARCH_LINE.*||")
COMMENT_BODY=":warning: The script _**$FILE**_ failed with the following message:
${CLEANED_ERROR_MSG}
"
-
+
# Check if the comment already exists
if echo "$EXISTING_COMMENTS" | grep -qF "$COMMENT_BODY"; then
echo "Skipping duplicate comment for $FILE"
@@ -171,7 +173,7 @@ jobs:
fi
fi
done
-
+
echo "ERROR=$ERROR" >> $GITHUB_ENV
-
-
+
+
diff --git a/.github/workflows/scripts/app-test/pr-build.func b/.github/workflows/scripts/app-test/pr-build.func
index 644a1ac..b44b59d 100644
--- a/.github/workflows/scripts/app-test/pr-build.func
+++ b/.github/workflows/scripts/app-test/pr-build.func
@@ -147,9 +147,9 @@ build_container() {
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if [ "$var_os" == "alpine" ]; then
- export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/workflows/scripts/app-test/pr-alpine-install.func)"
+ export FUNCTIONS_FILE_PATH="$(wget -qLO https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/workflows/scripts/app-test/pr-alpine-install.func)"
else
- export FUNCTIONS_FILE_PATH="$(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/workflows/scripts/app-test/pr-install.func)"
+ export FUNCTIONS_FILE_PATH="$(wget -qLO https://raw.githubusercontent.com/community-scripts/ProxmoxVED/main/.github/workflows/scripts/app-test/pr-install.func)"
fi
export CACHER="$APT_CACHER"
diff --git a/frontend/public/json/versions.json b/frontend/public/json/versions.json
index 0d9423a..a19e310 100644
--- a/frontend/public/json/versions.json
+++ b/frontend/public/json/versions.json
@@ -1,23 +1,188 @@
[
{
- "name": "semaphoreui/semaphore",
- "version": "v2.13.11-beta1",
- "date": "2025-04-08T10:56:42Z"
+ "name": "outline/outline",
+ "version": "v0.82.1-19",
+ "date": "2025-04-10T01:03:03Z"
},
{
- "name": "n8n-io/n8n",
- "version": "n8n@1.84.3",
- "date": "2025-03-27T11:54:33Z"
+ "name": "glanceapp/glance",
+ "version": "v0.7.10",
+ "date": "2025-04-09T23:51:06Z"
+ },
+ {
+ "name": "mongodb/mongo",
+ "version": "r8.0.5-rc2",
+ "date": "2025-04-09T22:37:52Z"
+ },
+ {
+ "name": "paperless-ngx/paperless-ngx",
+ "version": "v2.15.1",
+ "date": "2025-04-09T22:26:39Z"
},
{
"name": "fhem/fhem-mirror",
"version": "6.2",
- "date": "2025-04-08T10:34:47Z"
+ "date": "2025-04-09T20:29:25Z"
+ },
+ {
+ "name": "syncthing/syncthing",
+ "version": "v2.0.0-beta.7",
+ "date": "2025-04-09T13:41:32Z"
+ },
+ {
+ "name": "NodeBB/NodeBB",
+ "version": "v4.3.0-beta.1",
+ "date": "2025-04-09T19:06:10Z"
+ },
+ {
+ "name": "docmost/docmost",
+ "version": "v0.10.0",
+ "date": "2025-04-09T18:58:20Z"
+ },
+ {
+ "name": "Prowlarr/Prowlarr",
+ "version": "v1.33.3.5008",
+ "date": "2025-04-09T17:58:37Z"
+ },
+ {
+ "name": "jupyter/notebook",
+ "version": "v7.4.0",
+ "date": "2025-04-09T17:36:14Z"
+ },
+ {
+ "name": "MediaBrowser/Emby.Releases",
+ "version": "4.8.11.0",
+ "date": "2025-03-10T06:39:11Z"
+ },
+ {
+ "name": "Stirling-Tools/Stirling-PDF",
+ "version": "v0.45.3",
+ "date": "2025-04-09T17:17:58Z"
+ },
+ {
+ "name": "Brandawg93/PeaNUT",
+ "version": "v5.7.1",
+ "date": "2025-04-09T15:06:49Z"
+ },
+ {
+ "name": "glpi-project/glpi",
+ "version": "10.0.18",
+ "date": "2025-02-12T11:07:02Z"
+ },
+ {
+ "name": "slskd/slskd",
+ "version": "0.22.3",
+ "date": "2025-04-09T14:02:12Z"
+ },
+ {
+ "name": "HabitRPG/habitica",
+ "version": "v5.35.2",
+ "date": "2025-04-09T13:46:58Z"
+ },
+ {
+ "name": "homarr-labs/homarr",
+ "version": "v1.15.0",
+ "date": "2025-04-09T13:27:14Z"
+ },
+ {
+ "name": "zitadel/zitadel",
+ "version": "v2.69.10",
+ "date": "2025-04-09T12:16:51Z"
+ },
+ {
+ "name": "YunoHost/yunohost",
+ "version": "debian/12.0.14",
+ "date": "2025-04-09T10:09:00Z"
+ },
+ {
+ "name": "n8n-io/n8n",
+ "version": "n8n@1.86.1",
+ "date": "2025-04-09T09:20:55Z"
+ },
+ {
+ "name": "esphome/esphome",
+ "version": "2025.3.3",
+ "date": "2025-03-31T22:07:05Z"
+ },
+ {
+ "name": "runtipi/runtipi",
+ "version": "nightly",
+ "date": "2025-04-08T07:12:33Z"
+ },
+ {
+ "name": "morpheus65535/bazarr",
+ "version": "v1.5.1",
+ "date": "2025-01-01T16:15:52Z"
+ },
+ {
+ "name": "Jackett/Jackett",
+ "version": "v0.22.1751",
+ "date": "2025-04-09T06:00:36Z"
+ },
+ {
+ "name": "StarFleetCPTN/GoMFT",
+ "version": "v0.2.7",
+ "date": "2025-04-09T04:53:30Z"
+ },
+ {
+ "name": "OliveTin/OliveTin",
+ "version": "2025.4.8",
+ "date": "2025-04-08T22:02:50Z"
+ },
+ {
+ "name": "coder/code-server",
+ "version": "v4.99.1",
+ "date": "2025-04-08T21:35:21Z"
+ },
+ {
+ "name": "semaphoreui/semaphore",
+ "version": "v2.13.12",
+ "date": "2025-04-08T20:54:58Z"
+ },
+ {
+ "name": "minio/minio",
+ "version": "RELEASE.2025-04-08T15-41-24Z",
+ "date": "2025-04-08T19:51:06Z"
+ },
+ {
+ "name": "goauthentik/authentik",
+ "version": "version/2025.2.4",
+ "date": "2025-04-08T18:39:57Z"
+ },
+ {
+ "name": "keycloak/keycloak",
+ "version": "26.1.4",
+ "date": "2025-03-13T15:41:42Z"
+ },
+ {
+ "name": "influxdata/influxdb",
+ "version": "v1.12.0rc1",
+ "date": "2025-04-08T17:35:21Z"
+ },
+ {
+ "name": "jenkinsci/jenkins",
+ "version": "jenkins-2.505",
+ "date": "2025-04-08T15:46:42Z"
+ },
+ {
+ "name": "AdguardTeam/AdGuardHome",
+ "version": "v0.107.59",
+ "date": "2025-03-21T11:11:39Z"
},
{
"name": "openobserve/openobserve",
- "version": "v0.14.6-rc1",
- "date": "2025-04-08T08:50:03Z"
+ "version": "v0.14.6-rc2",
+ "date": "2025-04-08T14:42:54Z"
+ },
+ {
+ "name": "element-hq/synapse",
+ "version": "v1.128.0",
+ "date": "2025-04-08T14:27:55Z"
+ },
+ {
+ "name": "linkwarden/linkwarden",
+ "version": "v2.10.0",
+ "date": "2025-04-08T12:33:57Z"
},
{
"name": "prometheus/prometheus",
@@ -29,21 +194,6 @@
"version": "release-1.23.0rc1",
"date": "2025-04-08T06:39:46Z"
},
- {
- "name": "Jackett/Jackett",
- "version": "v0.22.1744",
- "date": "2025-04-08T06:09:14Z"
- },
- {
- "name": "StarFleetCPTN/GoMFT",
- "version": "v0.2.6",
- "date": "2025-04-08T02:23:38Z"
- },
- {
- "name": "coder/code-server",
- "version": "v4.99.0",
- "date": "2025-04-08T00:55:36Z"
- },
{
"name": "pelican-dev/panel",
"version": "v1.0.0-beta19",
@@ -59,11 +209,6 @@
"version": "1.2.32",
"date": "2025-04-07T20:01:09Z"
},
- {
- "name": "NodeBB/NodeBB",
- "version": "v4.2.0",
- "date": "2025-03-19T18:34:01Z"
- },
{
"name": "go-gitea/gitea",
"version": "v1.23.7",
@@ -79,16 +224,6 @@
"version": "coverity-w15-4.12.0",
"date": "2025-04-07T17:50:14Z"
},
- {
- "name": "keycloak/keycloak",
- "version": "26.1.4",
- "date": "2025-03-13T15:41:42Z"
- },
- {
- "name": "Brandawg93/PeaNUT",
- "version": "v5.7.0",
- "date": "2025-04-07T16:14:10Z"
- },
{
"name": "thomiceli/opengist",
"version": "v1.10.0",
@@ -109,11 +244,6 @@
"version": "pmm-6401-v1.115.0",
"date": "2025-04-07T11:15:53Z"
},
- {
- "name": "syncthing/syncthing",
- "version": "v1.29.4",
- "date": "2025-04-01T08:45:07Z"
- },
{
"name": "fallenbagel/jellyseerr",
"version": "preview-back-to-axios",
@@ -144,11 +274,6 @@
"version": "server/public/v0.1.11",
"date": "2025-03-28T14:04:31Z"
},
- {
- "name": "morpheus65535/bazarr",
- "version": "v1.5.1",
- "date": "2025-01-01T16:15:52Z"
- },
{
"name": "open-webui/open-webui",
"version": "v0.6.2",
@@ -184,11 +309,6 @@
"version": "1.5.34",
"date": "2025-03-27T16:17:38Z"
},
- {
- "name": "runtipi/runtipi",
- "version": "v3.10.0",
- "date": "2025-03-15T14:38:16Z"
- },
{
"name": "stackblitz-labs/bolt.diy",
"version": "v0.0.7-hf1",
@@ -199,11 +319,6 @@
"version": "v1.19.7",
"date": "2025-04-06T14:22:44Z"
},
- {
- "name": "Prowlarr/Prowlarr",
- "version": "v1.32.2.4987",
- "date": "2025-03-16T09:41:37Z"
- },
{
"name": "Radarr/Radarr",
"version": "v5.21.1.9799",
@@ -289,16 +404,6 @@
"version": "2.2.1",
"date": "2025-04-04T20:15:48Z"
},
- {
- "name": "YunoHost/yunohost",
- "version": "debian/12.0.13",
- "date": "2025-04-04T20:05:45Z"
- },
- {
- "name": "homarr-labs/homarr",
- "version": "v1.14.0",
- "date": "2025-04-04T19:15:59Z"
- },
{
"name": "Athou/commafeed",
"version": "5.7.0",
@@ -324,36 +429,16 @@
"version": "0.49.12",
"date": "2025-04-04T07:31:08Z"
},
- {
- "name": "minio/minio",
- "version": "RELEASE.2025-04-03T14-56-28Z",
- "date": "2025-04-03T19:08:18Z"
- },
{
"name": "OctoPrint/OctoPrint",
"version": "1.10.3",
"date": "2024-11-05T09:20:50Z"
},
- {
- "name": "jupyter/notebook",
- "version": "@jupyter-notebook/ui-components@7.4.0-rc.0",
- "date": "2025-04-03T06:49:38Z"
- },
{
"name": "rabbitmq/rabbitmq-server",
"version": "v4.0.8",
"date": "2025-04-03T05:11:15Z"
},
- {
- "name": "HabitRPG/habitica",
- "version": "v5.35.1",
- "date": "2025-04-02T21:49:00Z"
- },
- {
- "name": "zitadel/zitadel",
- "version": "v2.63.9",
- "date": "2025-03-31T12:47:21Z"
- },
{
"name": "BookStackApp/BookStack",
"version": "v25.02.2",
@@ -364,11 +449,6 @@
"version": "2025.4.0",
"date": "2025-04-02T15:38:53Z"
},
- {
- "name": "jenkinsci/jenkins",
- "version": "jenkins-2.503",
- "date": "2025-04-02T15:12:13Z"
- },
{
"name": "hargata/lubelog",
"version": "v1.4.6",
@@ -384,16 +464,6 @@
"version": "v2.31.0",
"date": "2025-04-01T18:12:45Z"
},
- {
- "name": "influxdata/influxdb",
- "version": "v3.0.0-0.beta.3",
- "date": "2025-04-01T15:34:30Z"
- },
- {
- "name": "element-hq/synapse",
- "version": "v1.127.1",
- "date": "2025-03-26T21:44:28Z"
- },
{
"name": "theonedev/onedev",
"version": "v11.8.6",
@@ -409,59 +479,9 @@
"version": "v4.0.2",
"date": "2025-04-01T04:51:05Z"
},
- {
- "name": "outline/outline",
- "version": "v0.82.1-18",
- "date": "2025-03-31T23:12:40Z"
- },
- {
- "name": "esphome/esphome",
- "version": "2025.3.3",
- "date": "2025-03-31T22:07:05Z"
- },
{
"name": "Kometa-Team/Kometa",
"version": "v2.2.0",
"date": "2025-03-31T21:31:48Z"
- },
- {
- "name": "traefik/traefik",
- "version": "v3.3.5",
- "date": "2025-03-31T08:55:12Z"
- },
- {
- "name": "home-assistant/operating-system",
- "version": "15.1",
- "date": "2025-03-31T13:42:20Z"
- },
- {
- "name": "documenso/documenso",
- "version": "v1.10.0-rc.4",
- "date": "2025-03-31T09:02:22Z"
- },
- {
- "name": "MediaBrowser/Emby.Releases",
- "version": "4.8.11.0",
- "date": "2025-03-10T06:39:11Z"
- },
- {
- "name": "louislam/dockge",
- "version": "1.5.0",
- "date": "2025-03-30T17:42:59Z"
- },
- {
- "name": "pi-hole/pi-hole",
- "version": "v6.0.6",
- "date": "2025-03-30T16:59:06Z"
- },
- {
- "name": "Part-DB/Part-DB-server",
- "version": "v1.17.0",
- "date": "2025-03-30T14:21:53Z"
- },
- {
- "name": "openhab/openhab-core",
- "version": "4.3.4",
- "date": "2025-03-30T13:32:38Z"
}
]
diff --git a/misc/build.func b/misc/build.func
index 162f36b..c8fe690 100644
--- a/misc/build.func
+++ b/misc/build.func
@@ -196,7 +196,7 @@ root_check() {
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
pve_check() {
- if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
+ if ! pveversion | grep -Eq "pve-manager/8\.[1-9](\.[0-9]+)*"; then
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."
diff --git a/tools/addon/add-iptag.sh b/tools/addon/add-iptag.sh
index 55f23d2..1a394c6 100644
--- a/tools/addon/add-iptag.sh
+++ b/tools/addon/add-iptag.sh
@@ -8,12 +8,12 @@
function header_info {
clear
cat <<"EOF"
- ___ ____ _____
-|_ _| _ \ _ |_ _|_ _ __ _
- | || |_) (_) | |/ _` |/ _` |
- | || __/ _ | | (_| | (_| |
-|___|_| (_) |_|\__,_|\__, |
- |___/
+ ___ ____ _____
+|_ _| _ \ _ |_ _|_ _ __ _
+ | || |_) (_) | |/ _` |/ _` |
+ | || __/ _ | | (_| | (_| |
+|___|_| (_) |_|\__,_|\__, |
+ |___/
EOF
}
@@ -40,7 +40,7 @@ catch_errors() {
# This function is called when an error occurs. It receives the exit code, line number, and command that caused the error, and displays an error message.
error_handler() {
- if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
+ if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
kill $SPINNER_PID >/dev/null
fi
printf "\e[?25h"
@@ -77,7 +77,7 @@ msg_info() {
# This function displays a success message with a green color.
msg_ok() {
- if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
+ if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
kill $SPINNER_PID >/dev/null
fi
printf "\e[?25h"
@@ -87,7 +87,7 @@ msg_ok() {
# This function displays a error message with a red color.
msg_error() {
- if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
+ if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
kill $SPINNER_PID >/dev/null
fi
printf "\e[?25h"
@@ -108,7 +108,7 @@ check_service_exists() {
migrate_config() {
local old_config="/opt/lxc-iptag"
local new_config="/opt/iptag/iptag.conf"
-
+
if [[ -f "$old_config" ]]; then
msg_info "Migrating configuration from old path"
if cp "$old_config" "$new_config" &>/dev/null; then
@@ -124,15 +124,15 @@ migrate_config() {
update_installation() {
msg_info "Updating IP-Tag Scripts"
systemctl stop iptag.service &>/dev/null
-
+
# Create directory if it doesn't exist
if [[ ! -d "/opt/iptag" ]]; then
mkdir -p /opt/iptag
fi
-
+
# Migrate config if needed
migrate_config
-
+
# Update main script
cat <<'EOF' >/opt/iptag/iptag
#!/bin/bash
@@ -157,19 +157,19 @@ ip_to_int() {
ip_in_cidr() {
local ip="$1"
local cidr="$2"
-
+
# Use ipcalc with the -c option (check), which returns 0 if the IP is in the network
if ipcalc -c "$ip" "$cidr" >/dev/null 2>&1; then
# Get network address and mask from CIDR
local network prefix
network=$(echo "$cidr" | cut -d/ -f1)
prefix=$(echo "$cidr" | cut -d/ -f2)
-
+
# Check if IP is in the network
local ip_a ip_b ip_c ip_d net_a net_b net_c net_d
IFS=. read -r ip_a ip_b ip_c ip_d <<< "$ip"
IFS=. read -r net_a net_b net_c net_d <<< "$network"
-
+
# Check octets match based on prefix length
local result=0
if (( prefix >= 8 )); then
@@ -181,10 +181,10 @@ ip_in_cidr() {
if (( prefix >= 24 )); then
[[ "$ip_c" != "$net_c" ]] && result=1
fi
-
+
return $result
fi
-
+
return 1
}
@@ -192,7 +192,7 @@ ip_in_cidr() {
format_ip_tag() {
local ip="$1"
local format="${TAG_FORMAT:-full}"
-
+
case "$format" in
"last_octet")
echo "${ip##*.}"
@@ -210,10 +210,10 @@ format_ip_tag() {
ip_in_cidrs() {
local ip="$1"
local cidrs="$2"
-
+
# Check that cidrs is not empty
[[ -z "$cidrs" ]] && return 1
-
+
local IFS=' '
for cidr in $cidrs; do
ip_in_cidr "$ip" "$cidr" && return 0
@@ -267,14 +267,14 @@ fw_net_interface_changed() {
get_vm_ips() {
local vmid=$1
local ips=""
-
+
# Check if VM is running
qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
-
+
# Get MAC addresses from VM configuration
local macs
macs=$(qm config "$vmid" 2>/dev/null | grep -E 'net[0-9]+' | grep -o -E '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
-
+
# Look up IPs from ARP table using MAC addresses
for mac in $macs; do
local ip
@@ -283,7 +283,7 @@ get_vm_ips() {
ips+="$ip "
fi
done
-
+
echo "$ips"
}
@@ -293,7 +293,7 @@ update_tags() {
local vmid="$2"
local config_cmd="pct"
[[ "$type" == "vm" ]] && config_cmd="qm"
-
+
# Get current IPs
local current_ips_full
if [[ "$type" == "lxc" ]]; then
@@ -302,23 +302,23 @@ update_tags() {
else
current_ips_full=$(get_vm_ips "${vmid}")
fi
-
+
# Parse current tags and get valid IPs
local current_tags=()
local next_tags=()
mapfile -t current_tags < <($config_cmd config "${vmid}" 2>/dev/null | grep tags | awk '{print $2}' | sed 's/;/\n/g')
-
+
for tag in "${current_tags[@]}"; do
# Skip tag if it looks like an IP (full or partial)
if ! is_valid_ipv4 "${tag}" && ! [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
next_tags+=("${tag}")
fi
done
-
+
# Add valid IPs to tags
local added_ips=()
local skipped_ips=()
-
+
for ip in ${current_ips_full}; do
if is_valid_ipv4 "${ip}"; then
if ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
@@ -330,12 +330,12 @@ update_tags() {
fi
fi
done
-
+
# Log only if there are changes
if [ ${#added_ips[@]} -gt 0 ]; then
echo "${type^} ${vmid}: added IP tags: ${added_ips[*]}"
fi
-
+
# Update if changed
if [[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]]; then
$config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
@@ -346,7 +346,7 @@ update_tags() {
check_status_changed() {
local type="$1"
local current_status
-
+
case "$type" in
"lxc")
current_status=$(pct list 2>/dev/null | grep -v VMID)
@@ -371,7 +371,7 @@ check_status_changed() {
update_all_tags() {
local type="$1"
local vmid_list=""
-
+
if [[ "$type" == "lxc" ]]; then
# Redirect stderr to /dev/null to suppress AppArmor messages
vmid_list=$(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')
@@ -380,7 +380,7 @@ update_all_tags() {
vmid_list=$(qm list 2>/dev/null | grep -v VMID | awk '{print $1}')
echo "Found $(echo "$vmid_list" | wc -w) virtual machines"
fi
-
+
for vmid in $vmid_list; do
update_tags "$type" "$vmid"
done
@@ -388,7 +388,7 @@ update_all_tags() {
check() {
current_time=$(date +%s)
-
+
# Check LXC status
time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
@@ -400,7 +400,7 @@ check() {
last_update_lxc_time=${current_time}
fi
fi
-
+
# Check VM status
time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
@@ -412,7 +412,7 @@ check() {
last_update_vm_time=${current_time}
fi
fi
-
+
# Check network interface changes
time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
@@ -426,7 +426,7 @@ check() {
last_update_vm_time=${current_time}
fi
fi
-
+
# Force update if needed
for type in "lxc" "vm"; do
local last_update_var="last_update_${type}_time"
@@ -457,7 +457,7 @@ main() {
main
EOF
chmod +x /opt/iptag/iptag
-
+
# Update service file
cat </lib/systemd/system/iptag.service
[Unit]
@@ -472,7 +472,7 @@ Restart=always
[Install]
WantedBy=multi-user.target
EOF
-
+
systemctl daemon-reload &>/dev/null
systemctl enable -q --now iptag.service &>/dev/null
msg_ok "Updated IP-Tag Scripts"
@@ -483,17 +483,17 @@ if check_service_exists; then
while true; do
read -p "IP-Tag service is already installed. Do you want to update it? (y/n): " yn
case $yn in
- [Yy]*)
- update_installation
- exit 0
- ;;
- [Nn]*)
- msg_error "Installation cancelled."
- exit 0
- ;;
- *)
- msg_error "Please answer yes or no."
- ;;
+ [Yy]*)
+ update_installation
+ exit 0
+ ;;
+ [Nn]*)
+ msg_error "Installation cancelled."
+ exit 0
+ ;;
+ *)
+ msg_error "Please answer yes or no."
+ ;;
esac
done
fi
@@ -501,20 +501,20 @@ fi
while true; do
read -p "This will install ${APP} on ${hostname}. Proceed? (y/n): " yn
case $yn in
- [Yy]*)
- break
- ;;
- [Nn]*)
- msg_error "Installation cancelled."
- exit
- ;;
- *)
- msg_error "Please answer yes or no."
- ;;
+ [Yy]*)
+ break
+ ;;
+ [Nn]*)
+ msg_error "Installation cancelled."
+ exit
+ ;;
+ *)
+ msg_error "Please answer yes or no."
+ ;;
esac
done
-if ! pveversion | grep -Eq "pve-manager/8\.[0-3](\.[0-9]+)*"; then
+if ! pveversion | grep -Eq "pve-manager/8\.[0-4](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
msg_error "⚠️ Requires Proxmox Virtual Environment Version 8.0 or later."
msg_error "Exiting..."
@@ -596,19 +596,19 @@ ip_to_int() {
ip_in_cidr() {
local ip="$1"
local cidr="$2"
-
+
# Use ipcalc with the -c option (check), which returns 0 if the IP is in the network
if ipcalc -c "$ip" "$cidr" >/dev/null 2>&1; then
# Get network address and mask from CIDR
local network prefix
network=$(echo "$cidr" | cut -d/ -f1)
prefix=$(echo "$cidr" | cut -d/ -f2)
-
+
# Check if IP is in the network
local ip_a ip_b ip_c ip_d net_a net_b net_c net_d
IFS=. read -r ip_a ip_b ip_c ip_d <<< "$ip"
IFS=. read -r net_a net_b net_c net_d <<< "$network"
-
+
# Check octets match based on prefix length
local result=0
if (( prefix >= 8 )); then
@@ -620,10 +620,10 @@ ip_in_cidr() {
if (( prefix >= 24 )); then
[[ "$ip_c" != "$net_c" ]] && result=1
fi
-
+
return $result
fi
-
+
return 1
}
@@ -631,7 +631,7 @@ ip_in_cidr() {
format_ip_tag() {
local ip="$1"
local format="${TAG_FORMAT:-full}"
-
+
case "$format" in
"last_octet")
echo "${ip##*.}"
@@ -649,10 +649,10 @@ format_ip_tag() {
ip_in_cidrs() {
local ip="$1"
local cidrs="$2"
-
+
# Check that cidrs is not empty
[[ -z "$cidrs" ]] && return 1
-
+
local IFS=' '
for cidr in $cidrs; do
ip_in_cidr "$ip" "$cidr" && return 0
@@ -706,14 +706,14 @@ fw_net_interface_changed() {
get_vm_ips() {
local vmid=$1
local ips=""
-
+
# Check if VM is running
qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
-
+
# Get MAC addresses from VM configuration
local macs
macs=$(qm config "$vmid" 2>/dev/null | grep -E 'net[0-9]+' | grep -o -E '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
-
+
# Look up IPs from ARP table using MAC addresses
for mac in $macs; do
local ip
@@ -722,7 +722,7 @@ get_vm_ips() {
ips+="$ip "
fi
done
-
+
echo "$ips"
}
@@ -732,7 +732,7 @@ update_tags() {
local vmid="$2"
local config_cmd="pct"
[[ "$type" == "vm" ]] && config_cmd="qm"
-
+
# Get current IPs
local current_ips_full
if [[ "$type" == "lxc" ]]; then
@@ -741,23 +741,23 @@ update_tags() {
else
current_ips_full=$(get_vm_ips "${vmid}")
fi
-
+
# Parse current tags and get valid IPs
local current_tags=()
local next_tags=()
mapfile -t current_tags < <($config_cmd config "${vmid}" 2>/dev/null | grep tags | awk '{print $2}' | sed 's/;/\n/g')
-
+
for tag in "${current_tags[@]}"; do
# Skip tag if it looks like an IP (full or partial)
if ! is_valid_ipv4 "${tag}" && ! [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
next_tags+=("${tag}")
fi
done
-
+
# Add valid IPs to tags
local added_ips=()
local skipped_ips=()
-
+
for ip in ${current_ips_full}; do
if is_valid_ipv4 "${ip}"; then
if ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
@@ -769,12 +769,12 @@ update_tags() {
fi
fi
done
-
+
# Log only if there are changes
if [ ${#added_ips[@]} -gt 0 ]; then
echo "${type^} ${vmid}: added IP tags: ${added_ips[*]}"
fi
-
+
# Update if changed
if [[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]]; then
$config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
@@ -785,7 +785,7 @@ update_tags() {
check_status_changed() {
local type="$1"
local current_status
-
+
case "$type" in
"lxc")
current_status=$(pct list 2>/dev/null | grep -v VMID)
@@ -808,7 +808,7 @@ check_status_changed() {
check() {
current_time=$(date +%s)
-
+
# Check LXC status
time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
@@ -820,7 +820,7 @@ check() {
last_update_lxc_time=${current_time}
fi
fi
-
+
# Check VM status
time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
@@ -832,7 +832,7 @@ check() {
last_update_vm_time=${current_time}
fi
fi
-
+
# Check network interface changes
time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
@@ -846,7 +846,7 @@ check() {
last_update_vm_time=${current_time}
fi
fi
-
+
# Force update if needed
for type in "lxc" "vm"; do
local last_update_var="last_update_${type}_time"