mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 02:12:49 +00:00 
			
		
		
		
	Compare commits
	
		
			16 Commits
		
	
	
		
			2025-06-16
			...
			2025-06-17
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					654508eb94 | ||
| 
						 | 
					acfb9d6ea1 | ||
| 
						 | 
					0d56db2d3d | ||
| 
						 | 
					4a1ae51446 | ||
| 
						 | 
					6520b7f4d4 | ||
| 
						 | 
					48da94f77a | ||
| 
						 | 
					2ea372f034 | ||
| 
						 | 
					5773459a39 | ||
| 
						 | 
					40f083ea40 | ||
| 
						 | 
					219a7853e1 | ||
| 
						 | 
					6d1d903345 | ||
| 
						 | 
					ef9ca48477 | ||
| 
						 | 
					8ac24981a6 | ||
| 
						 | 
					7e046d830d | ||
| 
						 | 
					1691fafcc1 | ||
| 
						 | 
					4400cd2b97 | 
							
								
								
									
										21
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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}"
 | 
			
		||||
 
 | 
			
		||||
@@ -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}')
 | 
			
		||||
 
 | 
			
		||||
@@ -29,38 +29,55 @@ 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
 | 
			
		||||
    msg_info "Stopping ${APP}"
 | 
			
		||||
    systemctl stop trilium
 | 
			
		||||
    sleep 1
 | 
			
		||||
    msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating to ${RELEASE}"
 | 
			
		||||
    mkdir -p /opt/trilium_backup
 | 
			
		||||
    mv /opt/trilium/db /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/
 | 
			
		||||
    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 /opt/trilium_backup
 | 
			
		||||
    msg_ok "Cleaned"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting ${APP}"
 | 
			
		||||
    systemctl start trilium
 | 
			
		||||
    sleep 1
 | 
			
		||||
    msg_ok "Started ${APP}"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
 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_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
   msg_error "Database not found in either /opt/trilium/db or /opt/trilium/assets/db"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
  exit
 | 
			
		||||
 | 
			
		||||
  msg_info "Stopping ${APP}"
 | 
			
		||||
  systemctl stop trilium
 | 
			
		||||
  sleep 1
 | 
			
		||||
  msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
  msg_info "Updating to ${RELEASE}"
 | 
			
		||||
  mkdir -p /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 "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 /opt/trilium_backup
 | 
			
		||||
  msg_ok "Cleaned"
 | 
			
		||||
 | 
			
		||||
  msg_info "Starting ${APP}"
 | 
			
		||||
  systemctl start trilium
 | 
			
		||||
  sleep 1
 | 
			
		||||
  msg_ok "Started ${APP}"
 | 
			
		||||
  msg_ok "Updated Successfully"
 | 
			
		||||
else
 | 
			
		||||
  msg_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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"
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -531,302 +531,260 @@ 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
 | 
			
		||||
  # shellcheck source=./iptag.conf
 | 
			
		||||
  source "$CONFIG_FILE"
 | 
			
		||||
    # shellcheck source=./iptag.conf
 | 
			
		||||
    source "$CONFIG_FILE"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Convert IP to integer for comparison
 | 
			
		||||
ip_to_int() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  local a b c d
 | 
			
		||||
  IFS=. read -r a b c d <<< "${ip}"
 | 
			
		||||
  echo "$((a << 24 | b << 16 | c << 8 | d))"
 | 
			
		||||
    local ip="$1"
 | 
			
		||||
    local a b c d
 | 
			
		||||
    IFS=. read -r a b c d <<< "${ip}"
 | 
			
		||||
    echo "$((a << 24 | b << 16 | c << 8 | d))"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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 ip="$1"
 | 
			
		||||
    local format="${TAG_FORMAT:-$DEFAULT_TAG_FORMAT}"
 | 
			
		||||
 | 
			
		||||
  case "$format" in
 | 
			
		||||
    "last_octet")
 | 
			
		||||
      echo "${ip##*.}"
 | 
			
		||||
      ;;
 | 
			
		||||
    "last_two_octets")
 | 
			
		||||
      echo "${ip#*.*.}"
 | 
			
		||||
      ;;
 | 
			
		||||
    *)
 | 
			
		||||
      echo "$ip"
 | 
			
		||||
      ;;
 | 
			
		||||
  esac
 | 
			
		||||
    case "$format" in
 | 
			
		||||
        "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
 | 
			
		||||
  [[ -z "$cidrs" ]] && return 1
 | 
			
		||||
 | 
			
		||||
  local IFS=' '
 | 
			
		||||
  for cidr in $cidrs; do
 | 
			
		||||
    ip_in_cidr "$ip" "$cidr" && return 0
 | 
			
		||||
  done
 | 
			
		||||
  return 1
 | 
			
		||||
    local ip="$1" cidrs="$2"
 | 
			
		||||
    [[ -z "$cidrs" ]] && return 1
 | 
			
		||||
    local IFS=' '
 | 
			
		||||
    for cidr in $cidrs; do 
 | 
			
		||||
        ip_in_cidr "$ip" "$cidr" && return 0
 | 
			
		||||
    done
 | 
			
		||||
    return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if IP is valid
 | 
			
		||||
is_valid_ipv4() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
 | 
			
		||||
  local IFS='.'
 | 
			
		||||
  read -ra parts <<< "$ip"
 | 
			
		||||
  for part in "${parts[@]}"; do
 | 
			
		||||
    [[ "$part" =~ ^[0-9]+$ ]] && ((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}"
 | 
			
		||||
    local ip="$1"
 | 
			
		||||
    [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
 | 
			
		||||
    
 | 
			
		||||
    local IFS='.' parts
 | 
			
		||||
    read -ra parts <<< "$ip"
 | 
			
		||||
    for part in "${parts[@]}"; do
 | 
			
		||||
        (( part >= 0 && part <= 255 )) || return 1
 | 
			
		||||
    done
 | 
			
		||||
    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=""
 | 
			
		||||
    local vmid=$1 ips="" macs found_ip=false
 | 
			
		||||
    qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
 | 
			
		||||
 | 
			
		||||
  # Check if VM is running
 | 
			
		||||
  qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
  # 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}')
 | 
			
		||||
    for mac in $macs; do
 | 
			
		||||
        local ip
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
  # 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 "
 | 
			
		||||
    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
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  echo "$ips"
 | 
			
		||||
    echo "${ips% }"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Update tags for container or VM
 | 
			
		||||
update_tags() {
 | 
			
		||||
  local type="$1"
 | 
			
		||||
  local vmid="$2"
 | 
			
		||||
  local config_cmd="pct"
 | 
			
		||||
  [[ "$type" == "vm" ]] && config_cmd="qm"
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
  # 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}")
 | 
			
		||||
    local current_ips_full
 | 
			
		||||
    if [[ "$type" == "lxc" ]]; then
 | 
			
		||||
        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
 | 
			
		||||
  done
 | 
			
		||||
    [[ -z "$current_ips_full" ]] && return
 | 
			
		||||
 | 
			
		||||
  # Add valid IPs to tags
 | 
			
		||||
  local added_ips=()
 | 
			
		||||
  local skipped_ips=()
 | 
			
		||||
    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')
 | 
			
		||||
 | 
			
		||||
  for ip in ${current_ips_full}; do
 | 
			
		||||
    if is_valid_ipv4 "${ip}"; then
 | 
			
		||||
      if 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}")
 | 
			
		||||
      fi
 | 
			
		||||
    # Separate IP and non-IP tags
 | 
			
		||||
    for tag in "${current_tags[@]}"; do
 | 
			
		||||
        if is_valid_ipv4 "${tag}" || [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
 | 
			
		||||
            current_ip_tags+=("${tag}")
 | 
			
		||||
        else
 | 
			
		||||
            next_tags+=("${tag}")
 | 
			
		||||
        fi
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    local formatted_ips=() needs_update=false added_ips=()
 | 
			
		||||
    for ip in ${current_ips_full}; do
 | 
			
		||||
        if is_valid_ipv4 "$ip" && ip_in_cidrs "$ip" "${CIDR_LIST[*]}"; then
 | 
			
		||||
            local formatted_ip=$(format_ip_tag "$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
 | 
			
		||||
 | 
			
		||||
    [[ ${#formatted_ips[@]} -eq 0 ]] && return
 | 
			
		||||
 | 
			
		||||
    # 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
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  # Log only if there are changes
 | 
			
		||||
  if [ ${#added_ips[@]} -gt 0 ]; then
 | 
			
		||||
    echo "${type^} ${vmid}: added IP tags: ${added_ips[*]}"
 | 
			
		||||
  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
 | 
			
		||||
 | 
			
		||||
  # Update if changed
 | 
			
		||||
  if [[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]]; then
 | 
			
		||||
    $config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
 | 
			
		||||
  fi
 | 
			
		||||
    for vmid in $vmids; do 
 | 
			
		||||
        update_tags "$type" "$vmid"
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if status changed
 | 
			
		||||
check_status_changed() {
 | 
			
		||||
  local type="$1"
 | 
			
		||||
  local current_status
 | 
			
		||||
 | 
			
		||||
  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}"
 | 
			
		||||
      ;;
 | 
			
		||||
  esac
 | 
			
		||||
  return 0
 | 
			
		||||
    local type="$1" current
 | 
			
		||||
    case "$type" in
 | 
			
		||||
        "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() {
 | 
			
		||||
  current_time=$(date +%s)
 | 
			
		||||
    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
 | 
			
		||||
    echo "Checking LXC status..."
 | 
			
		||||
    last_lxc_status_check_time=${current_time}
 | 
			
		||||
    if check_status_changed "lxc"; then
 | 
			
		||||
      update_all_tags "lxc"
 | 
			
		||||
      last_update_lxc_time=${current_time}
 | 
			
		||||
    # Check LXC status
 | 
			
		||||
    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
 | 
			
		||||
  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
 | 
			
		||||
    echo "Checking VM status..."
 | 
			
		||||
    last_vm_status_check_time=${current_time}
 | 
			
		||||
    if check_status_changed "vm"; then
 | 
			
		||||
      update_all_tags "vm"
 | 
			
		||||
      last_update_vm_time=${current_time}
 | 
			
		||||
    # Check VM status
 | 
			
		||||
    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
 | 
			
		||||
  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
 | 
			
		||||
    echo "Checking network interfaces..."
 | 
			
		||||
    last_fw_net_interface_check_time=${current_time}
 | 
			
		||||
    if check_status_changed "fw"; then
 | 
			
		||||
      update_all_tags "lxc"
 | 
			
		||||
      update_all_tags "vm"
 | 
			
		||||
      last_update_lxc_time=${current_time}
 | 
			
		||||
      last_update_vm_time=${current_time}
 | 
			
		||||
    # Check network interface changes
 | 
			
		||||
    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}
 | 
			
		||||
            last_update_vm_time=${current_time}
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Force update if needed
 | 
			
		||||
  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
 | 
			
		||||
      echo "Force updating ${type} tags..."
 | 
			
		||||
      update_all_tags "$type"
 | 
			
		||||
      eval "${last_update_var}=${current_time}"
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
    # Force update if needed
 | 
			
		||||
    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:-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}"
 | 
			
		||||
  done
 | 
			
		||||
    while true; do
 | 
			
		||||
        check
 | 
			
		||||
        sleep "${LOOP_INTERVAL:-$DEFAULT_CHECK_INTERVAL}"
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user