Compare commits

...

16 Commits

Author SHA1 Message Date
community-scripts-pr-app[bot]
654508eb94 Update CHANGELOG.md (#5239)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-18 01:15:31 +01:00
community-scripts-pr-app[bot]
acfb9d6ea1 Update versions.json (#5238)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-18 02:14:53 +02:00
community-scripts-pr-app[bot]
0d56db2d3d Update CHANGELOG.md (#5237)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 22:06:45 +01:00
Tobias
4a1ae51446 gitea-mirror: increase build ressources (#5235) 2025-06-17 23:06:06 +02:00
community-scripts-pr-app[bot]
6520b7f4d4 Update CHANGELOG.md (#5230)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 15:57:51 +01:00
community-scripts-pr-app[bot]
48da94f77a Update CHANGELOG.md (#5229)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 15:57:35 +01:00
Chris
2ea372f034 Immich: ensure in proper working dir when updating (#5227) 2025-06-17 16:57:08 +02:00
community-scripts-pr-app[bot]
5773459a39 Update CHANGELOG.md (#5228)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 15:57:05 +01:00
Desert Gamer
40f083ea40 Resolve issue #5212 (#5226) 2025-06-17 16:56:27 +02:00
community-scripts-pr-app[bot]
219a7853e1 Update CHANGELOG.md (#5221)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 13:36:02 +01:00
TJ
6d1d903345 trilium: fix update function after db changes folder (#5207)
* Update trilium.sh

Fixed issue with db location

* Update ct/trilium.sh

Co-authored-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>

* Update trilium.sh

---------

Co-authored-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>
2025-06-17 14:35:17 +02:00
community-scripts-pr-app[bot]
ef9ca48477 Update versions.json (#5220)
Co-authored-by: GitHub Actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 14:07:50 +02:00
community-scripts-pr-app[bot]
8ac24981a6 Update CHANGELOG.md (#5219)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 13:02:31 +01:00
CanbiZ
7e046d830d IPTag: Better explanation (#5213) 2025-06-17 14:01:46 +02:00
community-scripts-pr-app[bot]
1691fafcc1 Update CHANGELOG.md (#5218)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-06-17 12:45:47 +01:00
Slaviša Arežina
4400cd2b97 Add .env (#5216) 2025-06-17 13:45:20 +02:00
9 changed files with 372 additions and 370 deletions

View File

@@ -14,8 +14,29 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment.
## 2025-06-18
## 2025-06-17
### 🚀 Updated Scripts
- #### 🐞 Bug Fixes
- gitea-mirror: increase build ressources [@CrazyWolf13](https://github.com/CrazyWolf13) ([#5235](https://github.com/community-scripts/ProxmoxVE/pull/5235))
- Immich: ensure in proper working dir when updating [@vhsdream](https://github.com/vhsdream) ([#5227](https://github.com/community-scripts/ProxmoxVE/pull/5227))
- Update IP-Tag [@DesertGamer](https://github.com/DesertGamer) ([#5226](https://github.com/community-scripts/ProxmoxVE/pull/5226))
- trilium: fix update function after db changes folder [@tjcomserv](https://github.com/tjcomserv) ([#5207](https://github.com/community-scripts/ProxmoxVE/pull/5207))
- #### ✨ New Features
- LibreTranslate: Add .env for easier configuration [@tremor021](https://github.com/tremor021) ([#5216](https://github.com/community-scripts/ProxmoxVE/pull/5216))
### 🌐 Website
- #### 📝 Script Information
- IPTag: Better explanation [@MickLesk](https://github.com/MickLesk) ([#5213](https://github.com/community-scripts/ProxmoxVE/pull/5213))
## 2025-06-16
### 🆕 New Scripts

View File

@@ -7,9 +7,9 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
APP="gitea-mirror"
var_tags="${var_tags:-mirror;gitea}"
var_cpu="${var_cpu:-1}"
var_ram="${var_ram:-1024}"
var_disk="${var_disk:-5}"
var_cpu="${var_cpu:-2}"
var_ram="${var_ram:-2048}"
var_disk="${var_disk:-6}"
var_os="${var_os:-debian}"
var_version="${var_version:-12}"
var_unprivileged="${var_unprivileged:-1}"

View File

@@ -30,6 +30,7 @@ function update_script() {
STAGING_DIR=/opt/staging
BASE_DIR=${STAGING_DIR}/base-images
SOURCE_DIR=${STAGING_DIR}/image-source
cd /root
if [[ -f ~/.intel_version ]]; then
curl -fsSLO https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile
readarray -t INTEL_URLS < <(sed -n "/intel/p" ./Dockerfile | awk '{print $3}')

View File

@@ -29,7 +29,19 @@ function update_script() {
fi
if [[ ! -f /opt/${APP}_version.txt ]]; then touch /opt/${APP}_version.txt; fi
RELEASE=$(curl -fsSL https://api.github.com/repos/TriliumNext/Notes/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
if [[ "v${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
if [[ "v${RELEASE}" != "$(cat /opt/${APP}_version.txt 2>/dev/null)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
if [[ -d /opt/trilium/db ]]; then
DB_PATH="/opt/trilium/db"
DB_RESTORE_PATH="/opt/trilium/db"
elif [[ -d /opt/trilium/assets/db ]]; then
DB_PATH="/opt/trilium/assets/db"
DB_RESTORE_PATH="/opt/trilium/assets/db"
else
msg_error "Database not found in either /opt/trilium/db or /opt/trilium/assets/db"
exit 1
fi
msg_info "Stopping ${APP}"
systemctl stop trilium
sleep 1
@@ -37,18 +49,22 @@ function update_script() {
msg_info "Updating to ${RELEASE}"
mkdir -p /opt/trilium_backup
mv /opt/trilium/db /opt/trilium_backup/
cp -r "${DB_PATH}" /opt/trilium_backup/
rm -rf /opt/trilium
cd /tmp
curl -fsSL "https://github.com/TriliumNext/Notes/releases/download/v${RELEASE}/TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz" -o $(basename "https://github.com/TriliumNext/Notes/releases/download/v${RELEASE}/TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz")
tar -xf TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz
mv TriliumNextNotes-Server-$RELEASE-linux-x64 /opt/trilium
cp -r /opt/trilium_backup/db /opt/trilium/
curl -fsSL "https://github.com/TriliumNext/Notes/releases/download/v${RELEASE}/TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz" -o "TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz"
tar -xf "TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz"
mv "TriliumNextNotes-Server-${RELEASE}-linux-x64" /opt/trilium
# Restore database
mkdir -p "$(dirname "${DB_RESTORE_PATH}")"
cp -r /opt/trilium_backup/$(basename "${DB_PATH}") "${DB_RESTORE_PATH}"
echo "v${RELEASE}" >/opt/${APP}_version.txt
msg_ok "Updated to ${RELEASE}"
msg_info "Cleaning up"
rm -rf /tmp/TriliumNextNotes-Server-${RELEASE}-linux-x64.tar.xz
rm -rf "/tmp/TriliumNextNotes-Server-${RELEASE}-linux-x64.tar.xz"
rm -rf /opt/trilium_backup
msg_ok "Cleaned"
@@ -57,10 +73,11 @@ function update_script() {
sleep 1
msg_ok "Started ${APP}"
msg_ok "Updated Successfully"
else
else
msg_ok "No update required. ${APP} is already at ${RELEASE}"
fi
exit
fi
exit
}
start

View File

@@ -1,5 +1,5 @@
{
"name": "Proxmox VE LXC IP-Tag",
"name": "Proxmox VE LXC Tag",
"slug": "add-iptag",
"categories": [
1
@@ -12,8 +12,8 @@
"documentation": null,
"website": null,
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/proxmox.svg",
"config_path": "",
"description": "This script automatically adds IP address as tags to LXC containers using a Systemd service. The service also updates the tags if a LXC IP address is changed.",
"config_path": "/opt/iptag/iptag.conf",
"description": "This script automatically adds IP address as tags to LXC containers or VM's using a systemd service. The service also updates the tags if a LXC/VM IP address is changed.",
"install_methods": [
{
"type": "default",

View File

@@ -19,9 +19,9 @@
"type": "default",
"script": "ct/gitea-mirror.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 5,
"cpu": 2,
"ram": 2048,
"hdd": 6,
"os": "Debian",
"version": "12"
}

View File

@@ -1,4 +1,99 @@
[
{
"name": "grafana/grafana",
"version": "v11.5.6",
"date": "2025-06-17T22:00:40Z"
},
{
"name": "jenkinsci/jenkins",
"version": "jenkins-2.515",
"date": "2025-06-17T19:17:56Z"
},
{
"name": "coder/code-server",
"version": "v4.100.3",
"date": "2025-06-03T21:06:41Z"
},
{
"name": "HabitRPG/habitica",
"version": "v5.36.6",
"date": "2025-06-17T18:12:31Z"
},
{
"name": "fallenbagel/jellyseerr",
"version": "preview-sort-userlist",
"date": "2025-06-17T18:02:25Z"
},
{
"name": "ollama/ollama",
"version": "v0.9.2",
"date": "2025-06-17T17:51:43Z"
},
{
"name": "msgbyte/tianji",
"version": "v1.21.16",
"date": "2025-06-17T16:25:53Z"
},
{
"name": "BookStackApp/BookStack",
"version": "v25.05.1",
"date": "2025-06-17T14:38:04Z"
},
{
"name": "element-hq/synapse",
"version": "v1.132.0",
"date": "2025-06-17T13:49:30Z"
},
{
"name": "cloudflare/cloudflared",
"version": "2025.6.1",
"date": "2025-06-17T12:45:39Z"
},
{
"name": "sabnzbd/sabnzbd",
"version": "4.5.1",
"date": "2025-04-11T09:57:47Z"
},
{
"name": "crowdsecurity/crowdsec",
"version": "v1.6.9",
"date": "2025-06-17T11:54:50Z"
},
{
"name": "glpi-project/glpi",
"version": "10.0.18",
"date": "2025-02-12T11:07:02Z"
},
{
"name": "mattermost/mattermost",
"version": "v10.9.1",
"date": "2025-06-17T07:06:51Z"
},
{
"name": "morpheus65535/bazarr",
"version": "v1.5.2",
"date": "2025-05-11T16:40:55Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.22.2024",
"date": "2025-06-17T05:51:55Z"
},
{
"name": "donaldzou/WGDashboard",
"version": "v4.2.4",
"date": "2025-06-17T05:37:06Z"
},
{
"name": "webmin/webmin",
"version": "2.402",
"date": "2025-06-17T05:20:42Z"
},
{
"name": "keycloak/keycloak",
"version": "26.2.5",
"date": "2025-05-28T06:49:43Z"
},
{
"name": "kimai/kimai",
"version": "2.36.1",
@@ -9,16 +104,16 @@
"version": "testing",
"date": "2025-06-16T18:10:42Z"
},
{
"name": "msgbyte/tianji",
"version": "v1.21.14",
"date": "2025-06-16T17:54:48Z"
},
{
"name": "goauthentik/authentik",
"version": "version/2025.6.2",
"date": "2025-06-16T17:54:39Z"
},
{
"name": "runtipi/runtipi",
"version": "nightly",
"date": "2025-06-16T17:35:17Z"
},
{
"name": "NodeBB/NodeBB",
"version": "v2.8.20",
@@ -64,11 +159,6 @@
"version": "v1.18.3",
"date": "2025-06-16T07:03:46Z"
},
{
"name": "Jackett/Jackett",
"version": "v0.22.2020",
"date": "2025-06-16T05:56:11Z"
},
{
"name": "esphome/esphome",
"version": "2025.5.2",
@@ -149,11 +239,6 @@
"version": "v25.0",
"date": "2025-05-12T09:12:04Z"
},
{
"name": "ollama/ollama",
"version": "v0.9.1-rc1",
"date": "2025-06-12T21:18:54Z"
},
{
"name": "theonedev/onedev",
"version": "v11.11.0",
@@ -164,21 +249,11 @@
"version": "v2.15.0",
"date": "2025-06-14T10:48:57Z"
},
{
"name": "runtipi/runtipi",
"version": "nightly",
"date": "2025-06-14T07:49:50Z"
},
{
"name": "FlareSolverr/FlareSolverr",
"version": "v3.3.25",
"date": "2025-06-14T02:52:44Z"
},
{
"name": "keycloak/keycloak",
"version": "26.2.5",
"date": "2025-05-28T06:49:43Z"
},
{
"name": "home-assistant/core",
"version": "2025.6.1",
@@ -195,14 +270,9 @@
"date": "2025-06-13T15:02:37Z"
},
{
"name": "jenkinsci/jenkins",
"version": "jenkins-2.514",
"date": "2025-06-10T14:27:57Z"
},
{
"name": "grafana/grafana",
"version": "v12.0.1+security-01",
"date": "2025-06-13T04:15:18Z"
"name": "wazuh/wazuh",
"version": "coverity-w25-4.13.0",
"date": "2025-06-13T13:58:23Z"
},
{
"name": "FlowiseAI/Flowise",
@@ -234,11 +304,6 @@
"version": "v3.3.0",
"date": "2025-06-12T06:54:48Z"
},
{
"name": "morpheus65535/bazarr",
"version": "v1.5.2",
"date": "2025-05-11T16:40:55Z"
},
{
"name": "documenso/documenso",
"version": "v1.12.0-rc.4",
@@ -254,36 +319,16 @@
"version": "4.8.11.0",
"date": "2025-03-10T06:39:11Z"
},
{
"name": "crowdsecurity/crowdsec",
"version": "v1.6.8",
"date": "2025-03-25T13:33:10Z"
},
{
"name": "dgtlmoon/changedetection.io",
"version": "0.50.3",
"date": "2025-06-11T15:19:52Z"
},
{
"name": "cloudflare/cloudflared",
"version": "2025.6.0",
"date": "2025-06-11T11:13:21Z"
},
{
"name": "autobrr/autobrr",
"version": "v1.63.1",
"date": "2025-06-11T11:05:42Z"
},
{
"name": "fallenbagel/jellyseerr",
"version": "preview-forceipv4-axios",
"date": "2025-06-11T09:16:40Z"
},
{
"name": "wazuh/wazuh",
"version": "coverity-w24-4.13.0",
"date": "2025-06-11T04:04:55Z"
},
{
"name": "zabbix/zabbix",
"version": "7.2.8rc1",
@@ -294,11 +339,6 @@
"version": "v0.15.0-rc2",
"date": "2025-06-11T04:29:22Z"
},
{
"name": "mattermost/mattermost",
"version": "server/public/v0.1.15",
"date": "2025-06-11T03:56:25Z"
},
{
"name": "node-red/node-red",
"version": "4.1.0-beta.1",
@@ -309,11 +349,6 @@
"version": "v0.107.62",
"date": "2025-05-27T12:10:19Z"
},
{
"name": "element-hq/synapse",
"version": "v1.131.0",
"date": "2025-06-03T14:13:00Z"
},
{
"name": "OctoPrint/OctoPrint",
"version": "1.11.2",
@@ -459,11 +494,6 @@
"version": "mariadb-11.8.2",
"date": "2025-06-04T13:35:16Z"
},
{
"name": "donaldzou/WGDashboard",
"version": "v4.2.3",
"date": "2025-05-07T15:35:04Z"
},
{
"name": "actualbudget/actual",
"version": "v25.6.1",
@@ -479,26 +509,11 @@
"version": "340",
"date": "2025-06-04T16:41:44Z"
},
{
"name": "glpi-project/glpi",
"version": "10.0.18",
"date": "2025-02-12T11:07:02Z"
},
{
"name": "louislam/uptime-kuma",
"version": "2.0.0-beta.2-temp",
"date": "2025-03-28T08:45:58Z"
},
{
"name": "webmin/webmin",
"version": "2.401",
"date": "2025-06-04T02:53:03Z"
},
{
"name": "coder/code-server",
"version": "v4.100.3",
"date": "2025-06-03T21:06:41Z"
},
{
"name": "influxdata/influxdb",
"version": "v1.12.1rc3",
@@ -539,11 +554,6 @@
"version": "v3.4.1",
"date": "2025-05-31T13:45:40Z"
},
{
"name": "BookStackApp/BookStack",
"version": "v25.05",
"date": "2025-05-31T13:36:23Z"
},
{
"name": "blakeblackshear/frigate",
"version": "v0.14.1",
@@ -569,11 +579,6 @@
"version": "v0.56.1",
"date": "2025-05-29T19:09:16Z"
},
{
"name": "HabitRPG/habitica",
"version": "v5.36.5",
"date": "2025-05-29T17:06:01Z"
},
{
"name": "readeck/readeck",
"version": "0.19.2",
@@ -924,11 +929,6 @@
"version": "v5.5.2",
"date": "2025-04-11T22:00:06Z"
},
{
"name": "sabnzbd/sabnzbd",
"version": "4.5.1",
"date": "2025-04-11T09:57:47Z"
},
{
"name": "thomiceli/opengist",
"version": "v1.10.0",

View File

@@ -43,6 +43,10 @@ $STD uv pip install "numpy<2"
$STD uv pip install .
$STD uv pip install libretranslate
$STD .venv/bin/python scripts/install_models.py
cat <<EOF >/opt/libretranslate/.env
LT_PORT=5000
EOF
msg_ok "Installed LibreTranslate"
msg_info "Creating Service"
@@ -56,6 +60,7 @@ User=root
Type=idle
Restart=always
Environment="PATH=/usr/local/lib/python3.11/dist-packages/libretranslate"
EnvironmentFile=/opt/libretranslate/.env
ExecStart=/opt/libretranslate/.venv/bin/python3 /opt/libretranslate/.venv/bin/libretranslate --host * --update-models
ExecReload=/bin/kill -s HUP
KillMode=mixed

View File

@@ -531,7 +531,9 @@ if [[ ! -f /opt/iptag/iptag ]]; then
cat <<'EOF' >/opt/iptag/iptag
#!/bin/bash
# =============== CONFIGURATION =============== #
CONFIG_FILE="/opt/iptag/iptag.conf"
readonly CONFIG_FILE="/opt/iptag/iptag.conf"
readonly DEFAULT_TAG_FORMAT="full"
readonly DEFAULT_CHECK_INTERVAL=60
# Load the configuration file if it exists
if [ -f "$CONFIG_FILE" ]; then
@@ -549,65 +551,40 @@ ip_to_int() {
# Check if IP is in CIDR
ip_in_cidr() {
local ip="$1"
local cidr="$2"
local ip="$1" cidr="$2"
ipcalc -c "$ip" "$cidr" >/dev/null 2>&1 || return 1
# 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
local network prefix ip_parts net_parts
network=$(echo "$cidr" | cut -d/ -f1)
prefix=$(echo "$cidr" | cut -d/ -f2)
IFS=. read -r -a ip_parts <<< "$ip"
IFS=. read -r -a net_parts <<< "$network"
# 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
[[ "$ip_a" != "$net_a" ]] && result=1
fi
if (( prefix >= 16 )); then
[[ "$ip_b" != "$net_b" ]] && result=1
fi
if (( prefix >= 24 )); then
[[ "$ip_c" != "$net_c" ]] && result=1
fi
return $result
fi
return 1
case $prefix in
8) [[ "${ip_parts[0]}" == "${net_parts[0]}" ]] ;;
16) [[ "${ip_parts[0]}.${ip_parts[1]}" == "${net_parts[0]}.${net_parts[1]}" ]] ;;
24) [[ "${ip_parts[0]}.${ip_parts[1]}.${ip_parts[2]}" == "${net_parts[0]}.${net_parts[1]}.${net_parts[2]}" ]] ;;
32) [[ "$ip" == "$network" ]] ;;
*) return 1 ;;
esac
}
# Format IP address according to the configuration
format_ip_tag() {
local ip="$1"
local format="${TAG_FORMAT:-full}"
local format="${TAG_FORMAT:-$DEFAULT_TAG_FORMAT}"
case "$format" in
"last_octet")
echo "${ip##*.}"
;;
"last_two_octets")
echo "${ip#*.*.}"
;;
*)
echo "$ip"
;;
"last_octet") echo "${ip##*.}" ;;
"last_two_octets") echo "${ip#*.*.}" ;;
*) echo "$ip" ;;
esac
}
# Check if IP is in any CIDRs
ip_in_cidrs() {
local ip="$1"
local cidrs="$2"
# Check that cidrs is not empty
local ip="$1" cidrs="$2"
[[ -z "$cidrs" ]] && return 1
local IFS=' '
for cidr in $cidrs; do
ip_in_cidr "$ip" "$cidr" && return 0
@@ -619,182 +596,162 @@ ip_in_cidrs() {
is_valid_ipv4() {
local ip="$1"
[[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
local IFS='.'
local IFS='.' parts
read -ra parts <<< "$ip"
for part in "${parts[@]}"; do
[[ "$part" =~ ^[0-9]+$ ]] && ((part >= 0 && part <= 255)) || return 1
(( part >= 0 && part <= 255 )) || return 1
done
return 0
}
lxc_status_changed() {
current_lxc_status=$(pct list 2>/dev/null)
if [ "${last_lxc_status}" == "${current_lxc_status}" ]; then
return 1
else
last_lxc_status="${current_lxc_status}"
return 0
fi
}
vm_status_changed() {
current_vm_status=$(qm list 2>/dev/null)
if [ "${last_vm_status}" == "${current_vm_status}" ]; then
return 1
else
last_vm_status="${current_vm_status}"
return 0
fi
}
fw_net_interface_changed() {
current_net_interface=$(ifconfig | grep "^fw")
if [ "${last_net_interface}" == "${current_net_interface}" ]; then
return 1
else
last_net_interface="${current_net_interface}"
return 0
fi
}
# Get VM IPs using MAC addresses and ARP table
get_vm_ips() {
local vmid=$1
local ips=""
# Check if VM is running
local vmid=$1 ips="" macs found_ip=false
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}')
macs=$(qm config "$vmid" 2>/dev/null | grep -E 'net[0-9]+' | grep -oE '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
[[ -z "$macs" ]] && return
# Look up IPs from ARP table using MAC addresses
for mac in $macs; do
local ip
ip=$(arp -an 2>/dev/null | grep -i "$mac" | grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}')
if [ -n "$ip" ]; then
ips+="$ip "
fi
ip=$(arp -an 2>/dev/null | grep -i "$mac" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}')
[[ -n "$ip" ]] && { ips+="$ip "; found_ip=true; }
done
echo "$ips"
if ! $found_ip; then
local agent_ip
agent_ip=$(qm agent "$vmid" network-get-interfaces 2>/dev/null | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' || true)
[[ -n "$agent_ip" ]] && ips+="$agent_ip "
fi
echo "${ips% }"
}
# Update tags for container or VM
update_tags() {
local type="$1"
local vmid="$2"
local config_cmd="pct"
local type="$1" vmid="$2" config_cmd="pct"
[[ "$type" == "vm" ]] && config_cmd="qm"
# Get current IPs
local current_ips_full
if [[ "$type" == "lxc" ]]; then
# Redirect error output to suppress AppArmor warnings
current_ips_full=$(lxc-info -n "${vmid}" -i 2>/dev/null | grep -E "^IP:" | awk '{print $2}')
else
current_ips_full=$(get_vm_ips "${vmid}")
fi
[[ -z "$current_ips_full" ]] && return
# Parse current tags and get valid IPs
local current_tags=()
local next_tags=()
local current_tags=() next_tags=() current_ip_tags=()
mapfile -t current_tags < <($config_cmd config "${vmid}" 2>/dev/null | grep tags | awk '{print $2}' | sed 's/;/\n/g')
# Separate IP and non-IP tags
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
if is_valid_ipv4 "${tag}" || [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
current_ip_tags+=("${tag}")
else
next_tags+=("${tag}")
fi
done
# Add valid IPs to tags
local added_ips=()
local skipped_ips=()
local formatted_ips=() needs_update=false added_ips=()
for ip in ${current_ips_full}; do
if is_valid_ipv4 "${ip}"; then
if ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
if is_valid_ipv4 "$ip" && ip_in_cidrs "$ip" "${CIDR_LIST[*]}"; then
local formatted_ip=$(format_ip_tag "$ip")
next_tags+=("${formatted_ip}")
added_ips+=("${formatted_ip}")
else
skipped_ips+=("${ip}")
formatted_ips+=("$formatted_ip")
if [[ ! " ${current_ip_tags[*]} " =~ " ${formatted_ip} " ]]; then
needs_update=true
added_ips+=("$formatted_ip")
next_tags+=("$formatted_ip")
fi
fi
done
# Log only if there are changes
if [ ${#added_ips[@]} -gt 0 ]; then
echo "${type^} ${vmid}: added IP tags: ${added_ips[*]}"
fi
[[ ${#formatted_ips[@]} -eq 0 ]] && return
# Update if changed
if [[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]]; then
# Add existing IP tags that are still valid
for tag in "${current_ip_tags[@]}"; do
if [[ " ${formatted_ips[*]} " =~ " ${tag} " ]]; then
if [[ ! " ${next_tags[*]} " =~ " ${tag} " ]]; then
next_tags+=("$tag")
fi
fi
done
if [[ "$needs_update" == true ]]; then
echo "${type^} ${vmid}: adding IP tags: ${added_ips[*]}"
$config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
fi
}
# Update all instances of specified type
update_all_tags() {
local type="$1" list_cmd="pct" vmids count=0
[[ "$type" == "vm" ]] && list_cmd="qm"
vmids=$($list_cmd list 2>/dev/null | grep -v VMID | awk '{print $1}')
for vmid in $vmids; do ((count++)); done
echo "Found ${count} running ${type}s"
[[ $count -eq 0 ]] && return
for vmid in $vmids; do
update_tags "$type" "$vmid"
done
}
# Check if status changed
check_status_changed() {
local type="$1"
local current_status
local type="$1" current
case "$type" in
"lxc")
current_status=$(pct list 2>/dev/null | grep -v VMID)
[[ "${last_lxc_status}" == "${current_status}" ]] && return 1
last_lxc_status="${current_status}"
;;
"vm")
current_status=$(qm list 2>/dev/null | grep -v VMID)
[[ "${last_vm_status}" == "${current_status}" ]] && return 1
last_vm_status="${current_status}"
;;
"fw")
current_status=$(ifconfig 2>/dev/null | grep "^fw")
[[ "${last_net_interface}" == "${current_status}" ]] && return 1
last_net_interface="${current_status}"
;;
"lxc") current=$(pct list 2>/dev/null | grep -v VMID) ;;
"vm") current=$(qm list 2>/dev/null | grep -v VMID) ;;
"fw") current=$(ifconfig 2>/dev/null | grep "^fw") ;;
esac
local last_var="last_${type}_status"
[[ "${!last_var}" == "$current" ]] && return 1
eval "$last_var='$current'"
return 0
}
# Main check function
check() {
local current_time changes_detected=false
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 ]] \
&& [[ "${time_since_last_lxc_status_check}" -ge "${LXC_STATUS_CHECK_INTERVAL}" ]]; then
local time_since_last_lxc_check=$((current_time - last_lxc_status_check_time))
if [[ "${LXC_STATUS_CHECK_INTERVAL:-60}" -gt 0 ]] && \
[[ "${time_since_last_lxc_check}" -ge "${LXC_STATUS_CHECK_INTERVAL:-60}" ]]; then
echo "Checking LXC status..."
last_lxc_status_check_time=${current_time}
if check_status_changed "lxc"; then
changes_detected=true
update_all_tags "lxc"
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 ]] \
&& [[ "${time_since_last_vm_status_check}" -ge "${VM_STATUS_CHECK_INTERVAL}" ]]; then
local time_since_last_vm_check=$((current_time - last_vm_status_check_time))
if [[ "${VM_STATUS_CHECK_INTERVAL:-60}" -gt 0 ]] && \
[[ "${time_since_last_vm_check}" -ge "${VM_STATUS_CHECK_INTERVAL:-60}" ]]; then
echo "Checking VM status..."
last_vm_status_check_time=${current_time}
if check_status_changed "vm"; then
changes_detected=true
update_all_tags "vm"
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 ]] \
&& [[ "${time_since_last_fw_net_interface_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL}" ]]; then
local time_since_last_fw_check=$((current_time - last_fw_net_interface_check_time))
if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL:-60}" -gt 0 ]] && \
[[ "${time_since_last_fw_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL:-60}" ]]; then
echo "Checking network interfaces..."
last_fw_net_interface_check_time=${current_time}
if check_status_changed "fw"; then
changes_detected=true
update_all_tags "lxc"
update_all_tags "vm"
last_update_lxc_time=${current_time}
@@ -806,26 +763,27 @@ check() {
for type in "lxc" "vm"; do
local last_update_var="last_update_${type}_time"
local time_since_last_update=$((current_time - ${!last_update_var}))
if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
if [[ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL:-1800} ]]; then
echo "Force updating ${type} tags..."
changes_detected=true
update_all_tags "$type"
eval "${last_update_var}=${current_time}"
fi
done
$changes_detected || echo "No changes detected in system status"
}
# Initialize time variables
last_lxc_status_check_time=0
last_vm_status_check_time=0
last_fw_net_interface_check_time=0
last_update_lxc_time=0
last_update_vm_time=0
declare -g last_lxc_status="" last_vm_status="" last_fw_status=""
declare -g last_lxc_status_check_time=0 last_vm_status_check_time=0 last_fw_net_interface_check_time=0
declare -g last_update_lxc_time=0 last_update_vm_time=0
# main: Set the IP tags for all LXC containers and VMs
# Main loop
main() {
while true; do
check
sleep "${LOOP_INTERVAL}"
sleep "${LOOP_INTERVAL:-$DEFAULT_CHECK_INTERVAL}"
done
}