mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 10:22:50 +00:00 
			
		
		
		
	Compare commits
	
		
			26 Commits
		
	
	
		
			2025-04-16
			...
			2025-04-22
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					46ca78abc8 | ||
| 
						 | 
					933539ca7c | ||
| 
						 | 
					2c46695b72 | ||
| 
						 | 
					f46c3005b3 | ||
| 
						 | 
					bad84322ee | ||
| 
						 | 
					3b12c0ca62 | ||
| 
						 | 
					2583c110d2 | ||
| 
						 | 
					22c960c99c | ||
| 
						 | 
					fcb674b755 | ||
| 
						 | 
					0373324653 | ||
| 
						 | 
					3297df1d50 | ||
| 
						 | 
					80f1330a75 | ||
| 
						 | 
					05fda7e56a | ||
| 
						 | 
					73a42eaaae | ||
| 
						 | 
					1ae420eef5 | ||
| 
						 | 
					96fc1ea91d | ||
| 
						 | 
					432c6837e7 | ||
| 
						 | 
					2450baffc0 | ||
| 
						 | 
					4be3bca2e3 | ||
| 
						 | 
					1f93341311 | ||
| 
						 | 
					5723abb81f | ||
| 
						 | 
					5cfeb8a0bc | ||
| 
						 | 
					8cf9658efb | ||
| 
						 | 
					5dcb75a121 | ||
| 
						 | 
					3c909cabb6 | ||
| 
						 | 
					85a5bf2a55 | 
							
								
								
									
										51
									
								
								.github/workflows/close-ttek-issues.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								.github/workflows/close-ttek-issues.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
			
		||||
name: Auto-Close tteck Issues
 | 
			
		||||
on:
 | 
			
		||||
  issues:
 | 
			
		||||
    types: [opened]
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  close_tteck_issues:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Auto-close if tteck script detected
 | 
			
		||||
        uses: actions/github-script@v7
 | 
			
		||||
        with:
 | 
			
		||||
          script: |
 | 
			
		||||
            const issue = context.payload.issue;
 | 
			
		||||
            const content = `${issue.title}\n${issue.body}`;
 | 
			
		||||
            const issueNumber = issue.number;
 | 
			
		||||
 | 
			
		||||
            // Check for tteck script mention
 | 
			
		||||
            if (content.includes("tteck") || content.includes("tteck/Proxmox")) {
 | 
			
		||||
              const message = `Hello, it looks like you are referencing the **old tteck repo**.
 | 
			
		||||
 | 
			
		||||
            This repository is no longer used for active scripts.
 | 
			
		||||
            **Please update your bookmarks** and use: [https://helper-scripts.com](https://helper-scripts.com)
 | 
			
		||||
                    
 | 
			
		||||
            Also make sure your Bash command starts with:
 | 
			
		||||
            \`\`\`bash
 | 
			
		||||
            bash <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/...)
 | 
			
		||||
            \`\`\`
 | 
			
		||||
            
 | 
			
		||||
            This issue is being closed automatically.`;
 | 
			
		||||
 | 
			
		||||
              await github.rest.issues.createComment({
 | 
			
		||||
                ...context.repo,
 | 
			
		||||
                issue_number: issueNumber,
 | 
			
		||||
                body: message
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              // Optionally apply a label like "not planned"
 | 
			
		||||
              await github.rest.issues.addLabels({
 | 
			
		||||
                ...context.repo,
 | 
			
		||||
                issue_number: issueNumber,
 | 
			
		||||
                labels: ["not planned"]
 | 
			
		||||
              });
 | 
			
		||||
 | 
			
		||||
              // Close the issue
 | 
			
		||||
              await github.rest.issues.update({
 | 
			
		||||
                ...context.repo,
 | 
			
		||||
                issue_number: issueNumber,
 | 
			
		||||
                state: "closed"
 | 
			
		||||
              });
 | 
			
		||||
            }
 | 
			
		||||
							
								
								
									
										71
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -14,6 +14,77 @@ 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-04-22
 | 
			
		||||
 | 
			
		||||
### 🆕 New Scripts
 | 
			
		||||
 | 
			
		||||
  - reactive-resume ([#3980](https://github.com/community-scripts/ProxmoxVE/pull/3980))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - wger: Fix a bug in update procedure and general code maintenance [@tremor021](https://github.com/tremor021) ([#3974](https://github.com/community-scripts/ProxmoxVE/pull/3974))
 | 
			
		||||
 | 
			
		||||
### 🧰 Maintenance
 | 
			
		||||
 | 
			
		||||
  - #### 📂 Github
 | 
			
		||||
 | 
			
		||||
    - Add workflow to close ttek Repo relatate issues [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#3981](https://github.com/community-scripts/ProxmoxVE/pull/3981))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - Fix Turnkey Source Link in Button Component [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#3978](https://github.com/community-scripts/ProxmoxVE/pull/3978))
 | 
			
		||||
 | 
			
		||||
  - #### 📝 Script Information
 | 
			
		||||
 | 
			
		||||
    - qBittorrent: Update web page [@tremor021](https://github.com/tremor021) ([#3969](https://github.com/community-scripts/ProxmoxVE/pull/3969))
 | 
			
		||||
 | 
			
		||||
## 2025-04-19
 | 
			
		||||
 | 
			
		||||
### 🆕 New Scripts
 | 
			
		||||
 | 
			
		||||
  - LXC Iptag [@DesertGamer](https://github.com/DesertGamer) ([#3531](https://github.com/community-scripts/ProxmoxVE/pull/3531))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - seelf: Add missing gpg dependency [@tremor021](https://github.com/tremor021) ([#3953](https://github.com/community-scripts/ProxmoxVE/pull/3953))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - #### 📝 Script Information
 | 
			
		||||
 | 
			
		||||
    - Tailscale: Clarify tailscale script instruction on website [@tremor021](https://github.com/tremor021) ([#3952](https://github.com/community-scripts/ProxmoxVE/pull/3952))
 | 
			
		||||
 | 
			
		||||
## 2025-04-18
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - Changedetection: Increase connection timeout for older systems [@tremor021](https://github.com/tremor021) ([#3935](https://github.com/community-scripts/ProxmoxVE/pull/3935))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - #### 📝 Script Information
 | 
			
		||||
 | 
			
		||||
    - VaultWarden: Update json with additonal information [@uSlackr](https://github.com/uSlackr) ([#3929](https://github.com/community-scripts/ProxmoxVE/pull/3929))
 | 
			
		||||
 | 
			
		||||
## 2025-04-17
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - fix minor grammatical error in several scripts [@jordanpatton](https://github.com/jordanpatton) ([#3921](https://github.com/community-scripts/ProxmoxVE/pull/3921))
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - PeaNUT: Fix tar command [@tremor021](https://github.com/tremor021) ([#3925](https://github.com/community-scripts/ProxmoxVE/pull/3925))
 | 
			
		||||
    - GoMFT: Fix install and update process (final time) [@tremor021](https://github.com/tremor021) ([#3922](https://github.com/community-scripts/ProxmoxVE/pull/3922))
 | 
			
		||||
 | 
			
		||||
## 2025-04-15
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 
 | 
			
		||||
@@ -147,7 +147,7 @@ function select_storage() {
 | 
			
		||||
    local STORAGE
 | 
			
		||||
    while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
      STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
        "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
        "Which storage pool would you like to use for the ${CONTENT_LABEL,,}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
        16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
        "${MENU[@]}" 3>&1 1>&2 2>&3) || {
 | 
			
		||||
        msg_error "Menu aborted."
 | 
			
		||||
 
 | 
			
		||||
@@ -51,11 +51,8 @@ function update_script() {
 | 
			
		||||
    tar -xzf "$temp_file"
 | 
			
		||||
    cp -rf "GoMFT-${RELEASE}"/* /opt/gomft/
 | 
			
		||||
    cd /opt/gomft
 | 
			
		||||
    rm -rf /opt/gomft/node_modules
 | 
			
		||||
    $STD npm ci
 | 
			
		||||
    $STD node build.js
 | 
			
		||||
    $STD go mod download
 | 
			
		||||
    $STD go get -u github.com/a-h/templ
 | 
			
		||||
    $STD npm install
 | 
			
		||||
    $STD npm run build
 | 
			
		||||
    $STD "$HOME"/go/bin/templ generate
 | 
			
		||||
    export CGO_ENABLED=1
 | 
			
		||||
    export GOOS=linux
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/reactive-resume
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/reactive-resume
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    ____                  __  _                  ____                               
 | 
			
		||||
   / __ \___  ____ ______/ /_(_)   _____        / __ \___  _______  ______ ___  ___ 
 | 
			
		||||
  / /_/ / _ \/ __ `/ ___/ __/ / | / / _ \______/ /_/ / _ \/ ___/ / / / __ `__ \/ _ \
 | 
			
		||||
 / _, _/  __/ /_/ / /__/ /_/ /| |/ /  __/_____/ _, _/  __(__  ) /_/ / / / / / /  __/
 | 
			
		||||
/_/ |_|\___/\__,_/\___/\__/_/ |___/\___/     /_/ |_|\___/____/\__,_/_/ /_/ /_/\___/ 
 | 
			
		||||
                                                                                    
 | 
			
		||||
@@ -32,7 +32,7 @@ function update_script() {
 | 
			
		||||
    msg_info "Updating $APP to ${RELEASE}"
 | 
			
		||||
    systemctl stop peanut
 | 
			
		||||
    curl -fsSL "https://api.github.com/repos/Brandawg93/PeaNUT/tarball/${RELEASE}" -o "peanut.tar.gz"
 | 
			
		||||
    tar -xzf peanut.tar.gz -C /opt/peanut --strip-components
 | 
			
		||||
    tar -xzf peanut.tar.gz -C /opt/peanut --strip-components=1
 | 
			
		||||
    rm peanut.tar.gz
 | 
			
		||||
    cd /opt/peanut
 | 
			
		||||
    $STD pnpm i
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										106
									
								
								ct/reactive-resume.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								ct/reactive-resume.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,106 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: vhsdream
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://rxresu.me
 | 
			
		||||
 | 
			
		||||
APP="Reactive-Resume"
 | 
			
		||||
var_tags="${var_tags:-documents}"
 | 
			
		||||
var_cpu="${var_cpu:-2}"
 | 
			
		||||
var_ram="${var_ram:-3072}"
 | 
			
		||||
var_disk="${var_disk:-8}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-12}"
 | 
			
		||||
var_unprivileged="${var_unprivileged:-1}"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
 | 
			
		||||
    if [[ ! -f /etc/systemd/system/Reactive-Resume.service ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    RELEASE=$(curl -fsSL https://api.github.com/repos/AmruthPillai/Reactive-Resume/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
    if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
 | 
			
		||||
        msg_info "Stopping services"
 | 
			
		||||
        systemctl stop Reactive-Resume
 | 
			
		||||
        msg_ok "Stopped services"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating $APP to v${RELEASE}"
 | 
			
		||||
        cp /opt/${APP}/.env /opt/rxresume.env
 | 
			
		||||
        res_tmp=$(mktemp)
 | 
			
		||||
        rm -rf /opt/${APP}
 | 
			
		||||
        curl -fsSL "https://github.com/AmruthPillai/Reactive-Resume/archive/refs/tags/v${RELEASE}.zip" -O $res_tmp
 | 
			
		||||
        unzip -q $res_tmp
 | 
			
		||||
        mv ${APP}-${RELEASE}/ /opt/${APP}
 | 
			
		||||
        cd /opt/${APP}
 | 
			
		||||
        export PUPPETEER_SKIP_DOWNLOAD="true"
 | 
			
		||||
        export NEXT_TELEMETRY_DISABLED=1
 | 
			
		||||
        export CI="true"
 | 
			
		||||
        export NODE_ENV="production"
 | 
			
		||||
        $STD pnpm install --frozen-lockfile
 | 
			
		||||
        $STD pnpm run build
 | 
			
		||||
        $STD pnpm run prisma:generate
 | 
			
		||||
        mv /opt/rxresume.env /opt/${APP}/.env
 | 
			
		||||
        msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating Minio"
 | 
			
		||||
        systemctl stop minio
 | 
			
		||||
        cd /tmp
 | 
			
		||||
        curl -fsSL https://dl.min.io/server/minio/release/linux-amd64/minio.deb -o minio.deb
 | 
			
		||||
        $STD dpkg -i minio.deb
 | 
			
		||||
        msg_ok "Updated Minio"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating Browserless (Patience)"
 | 
			
		||||
        systemctl stop browserless
 | 
			
		||||
        cp /opt/browserless/.env /opt/browserless.env
 | 
			
		||||
        rm -rf browserless
 | 
			
		||||
        brwsr_tmp=$(mktemp)
 | 
			
		||||
        TAG=$(curl -fsSL https://api.github.com/repos/browserless/browserless/tags?per_page=1 | grep "name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
        curl -fsSL https://github.com/browserless/browserless/archive/refs/tags/v${TAG}.zip -O $brwsr_tmp
 | 
			
		||||
        unzip -q $brwsr_tmp
 | 
			
		||||
        mv browserless-${TAG}/ /opt/browserless
 | 
			
		||||
        cd /opt/browserless
 | 
			
		||||
        $STD npm install
 | 
			
		||||
        rm -rf src/routes/{chrome,edge,firefox,webkit}
 | 
			
		||||
        $STD node_modules/playwright-core/cli.js install --with-deps chromium
 | 
			
		||||
        $STD npm run build
 | 
			
		||||
        $STD npm run build:function
 | 
			
		||||
        $STD npm prune production
 | 
			
		||||
        mv /opt/browserless.env /opt/browserless/.env
 | 
			
		||||
        msg_ok "Updated Browserless"
 | 
			
		||||
 | 
			
		||||
        msg_info "Restarting services"
 | 
			
		||||
        systemctl start minio Reactive-Resume browserless
 | 
			
		||||
        msg_ok "Restarted services"
 | 
			
		||||
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -f /tmp/minio.deb
 | 
			
		||||
        rm -f $brwsr_tmp
 | 
			
		||||
        rm -f $res_tmp
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
 | 
			
		||||
        echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
        msg_ok "Update Successful"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
    exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
build_container
 | 
			
		||||
description
 | 
			
		||||
 | 
			
		||||
msg_ok "Completed Successfully!\n"
 | 
			
		||||
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
 | 
			
		||||
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
 | 
			
		||||
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"
 | 
			
		||||
							
								
								
									
										77
									
								
								ct/wger.sh
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								ct/wger.sh
									
									
									
									
									
								
							@@ -20,46 +20,45 @@ color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
    header_info
 | 
			
		||||
    check_container_storage
 | 
			
		||||
    check_container_resources
 | 
			
		||||
    if [[ ! -d /home/wger ]]; then
 | 
			
		||||
        msg_error "No ${APP} Installation Found!"
 | 
			
		||||
        exit
 | 
			
		||||
    fi
 | 
			
		||||
    RELEASE=$(curl -fsSL https://api.github.com/repos/wger-project/wger/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3)}')
 | 
			
		||||
    if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
 | 
			
		||||
        msg_info "Stopping $APP"
 | 
			
		||||
        systemctl stop wger
 | 
			
		||||
        msg_ok "Stopped $APP"
 | 
			
		||||
 | 
			
		||||
        msg_info "Updating $APP to v${RELEASE}"
 | 
			
		||||
        temp_file=$(mktemp)
 | 
			
		||||
        cd $temp_file
 | 
			
		||||
curl -fsSL "https://github.com/wger-project/wger/archive/refs/tags/$RELEASE.tar.gz" -o "$temp_file"
 | 
			
		||||
        tar xzf $temp_file
 | 
			
		||||
        cp -rf wger-$RELEASE/* /home/wger/src
 | 
			
		||||
        cd /home/wger/src
 | 
			
		||||
        python3 manage.py migrate &>/dev/null
 | 
			
		||||
        yarn install &>/dev/null
 | 
			
		||||
        yarn build:css:sass &>/dev/null
 | 
			
		||||
        python3 manage.py collectstatic --noinput &>/dev/null
 | 
			
		||||
        echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
        msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
        msg_info "Starting $APP"
 | 
			
		||||
        systemctl start wger
 | 
			
		||||
        msg_ok "Started $APP"
 | 
			
		||||
 | 
			
		||||
        msg_info "Cleaning Up"
 | 
			
		||||
        rm -rf $temp_file
 | 
			
		||||
        msg_ok "Cleanup Completed"
 | 
			
		||||
 | 
			
		||||
        msg_ok "Update Successful"
 | 
			
		||||
    else
 | 
			
		||||
        msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
    fi
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
  if [[ ! -d /home/wger ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -fsSL https://api.github.com/repos/wger-project/wger/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3)}')
 | 
			
		||||
  if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
 | 
			
		||||
    msg_info "Stopping $APP"
 | 
			
		||||
    systemctl stop wger
 | 
			
		||||
    msg_ok "Stopped $APP"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating $APP to v${RELEASE}"
 | 
			
		||||
    temp_file=$(mktemp)
 | 
			
		||||
    curl -fsSL "https://github.com/wger-project/wger/archive/refs/tags/$RELEASE.tar.gz" -o "$temp_file"
 | 
			
		||||
    tar xzf "$temp_file"
 | 
			
		||||
    cp -rf wger-"$RELEASE"/* /home/wger/src
 | 
			
		||||
    cd /home/wger/src
 | 
			
		||||
    python3 manage.py migrate &>/dev/null
 | 
			
		||||
    yarn install &>/dev/null
 | 
			
		||||
    yarn build:css:sass &>/dev/null
 | 
			
		||||
    python3 manage.py collectstatic --noinput &>/dev/null
 | 
			
		||||
    echo "${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting $APP"
 | 
			
		||||
    systemctl start wger
 | 
			
		||||
    msg_ok "Started $APP"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning Up"
 | 
			
		||||
    rm -rf "$temp_file"
 | 
			
		||||
    msg_ok "Cleanup Completed"
 | 
			
		||||
 | 
			
		||||
    msg_ok "Update Successful"
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at v${RELEASE}"
 | 
			
		||||
  fi
 | 
			
		||||
  exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,9 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Tailscale",
 | 
			
		||||
  "slug": "add-tailscale-lxc",
 | 
			
		||||
  "categories": [1],
 | 
			
		||||
  "categories": [
 | 
			
		||||
    1
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2024-05-02",
 | 
			
		||||
  "type": "addon",
 | 
			
		||||
  "updateable": false,
 | 
			
		||||
@@ -38,7 +40,7 @@
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Execute within the Proxmox shell",
 | 
			
		||||
      "text": "Execute within the Proxmox host shell",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,34 +1,34 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "qBittorrent",
 | 
			
		||||
    "slug": "qbittorrent",
 | 
			
		||||
    "categories": [
 | 
			
		||||
        11
 | 
			
		||||
    ],
 | 
			
		||||
    "date_created": "2024-05-02",
 | 
			
		||||
    "type": "ct",
 | 
			
		||||
    "updateable": false,
 | 
			
		||||
    "privileged": false,
 | 
			
		||||
    "interface_port": 8090,
 | 
			
		||||
    "documentation": null,
 | 
			
		||||
    "website": "https://www.qbittorrent.org/",
 | 
			
		||||
    "logo": "https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/svg/qbittorrent.svg",
 | 
			
		||||
    "description": "qBittorrent offers a user-friendly interface that allows users to search for and download torrent files easily. It also supports magnet links, which allow users to start downloading files without the need for a torrent file.",
 | 
			
		||||
    "install_methods": [
 | 
			
		||||
        {
 | 
			
		||||
            "type": "default",
 | 
			
		||||
            "script": "ct/qbittorrent.sh",
 | 
			
		||||
            "resources": {
 | 
			
		||||
                "cpu": 2,
 | 
			
		||||
                "ram": 2048,
 | 
			
		||||
                "hdd": 8,
 | 
			
		||||
                "os": "debian",
 | 
			
		||||
                "version": "12"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    ],
 | 
			
		||||
    "default_credentials": {
 | 
			
		||||
        "username": "admin",
 | 
			
		||||
        "password": "changeme"
 | 
			
		||||
    },
 | 
			
		||||
    "notes": []
 | 
			
		||||
  "name": "qBittorrent",
 | 
			
		||||
  "slug": "qbittorrent",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    11
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2024-05-02",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": 8090,
 | 
			
		||||
  "documentation": "https://github.com/qbittorrent/qBittorrent/wiki/",
 | 
			
		||||
  "website": "https://www.qbittorrent.org/",
 | 
			
		||||
  "logo": "https://raw.githubusercontent.com/selfhst/icons/refs/heads/main/svg/qbittorrent.svg",
 | 
			
		||||
  "description": "qBittorrent offers a user-friendly interface that allows users to search for and download torrent files easily. It also supports magnet links, which allow users to start downloading files without the need for a torrent file.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/qbittorrent.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 2048,
 | 
			
		||||
        "hdd": 8,
 | 
			
		||||
        "os": "debian",
 | 
			
		||||
        "version": "12"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": "admin",
 | 
			
		||||
    "password": "changeme"
 | 
			
		||||
  },
 | 
			
		||||
  "notes": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								frontend/public/json/reactive-resume.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								frontend/public/json/reactive-resume.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Reactive Resume",
 | 
			
		||||
  "slug": "reactive-resume",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    12
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-04-22",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": 3000,
 | 
			
		||||
  "documentation": "https://docs.rxresu.me/",
 | 
			
		||||
  "website": "https://rxresu.me",
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/png/reactive-resume-light.png",
 | 
			
		||||
  "description": "A one-of-a-kind resume builder that keeps your privacy in mind. Completely secure, customizable, portable, open-source and free forever.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/reactive-resume.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 3072,
 | 
			
		||||
        "hdd": 8,
 | 
			
		||||
        "os": "Debian",
 | 
			
		||||
        "version": "12"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": []
 | 
			
		||||
}
 | 
			
		||||
@@ -43,7 +43,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "notes": [
 | 
			
		||||
        {
 | 
			
		||||
            "text": "Vaultwarden needs to be behind a proxy (Nginx Proxy Manager) to obtain HTTPS and to allow clients to connect.",
 | 
			
		||||
            "text": "Vaultwarden needs to be behind a proxy (Nginx Proxy Manager, Caddy, etc) to obtain HTTPS and to allow clients to connect. If you try to open the web page directly on the new container, the web site will not load",
 | 
			
		||||
            "type": "warning"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,12 @@
 | 
			
		||||
  {
 | 
			
		||||
    "name": "fhem/fhem-mirror",
 | 
			
		||||
    "version": "6.2",
 | 
			
		||||
    "date": "2025-04-15T10:34:54Z"
 | 
			
		||||
    "date": "2025-04-22T10:34:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "OctoPrint/OctoPrint",
 | 
			
		||||
    "version": "1.11.0",
 | 
			
		||||
    "date": "2025-04-22T09:33:46Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "n8n-io/n8n",
 | 
			
		||||
@@ -10,19 +15,334 @@
 | 
			
		||||
    "date": "2025-04-09T09:20:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "wazuh/wazuh",
 | 
			
		||||
    "version": "coverity-w16-4.12.0",
 | 
			
		||||
    "date": "2025-04-15T08:25:08Z"
 | 
			
		||||
    "name": "zabbix/zabbix",
 | 
			
		||||
    "version": "6.0.40",
 | 
			
		||||
    "date": "2025-04-22T08:43:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Checkmk/checkmk",
 | 
			
		||||
    "version": "v2.4.0b6-rc1",
 | 
			
		||||
    "date": "2025-04-22T08:12:24Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "nzbgetcom/nzbget",
 | 
			
		||||
    "version": "v24.8",
 | 
			
		||||
    "date": "2025-03-18T07:33:51Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "openobserve/openobserve",
 | 
			
		||||
    "version": "v0.14.6-rc5",
 | 
			
		||||
    "date": "2025-04-22T06:50:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mattermost/mattermost",
 | 
			
		||||
    "version": "v10.6.2",
 | 
			
		||||
    "date": "2025-04-15T08:14:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "morpheus65535/bazarr",
 | 
			
		||||
    "version": "v1.5.1",
 | 
			
		||||
    "date": "2025-01-01T16:15:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "firefly-iii/firefly-iii",
 | 
			
		||||
    "version": "v6.2.12",
 | 
			
		||||
    "date": "2025-04-20T19:22:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Jackett/Jackett",
 | 
			
		||||
    "version": "v0.22.1778",
 | 
			
		||||
    "date": "2025-04-15T06:26:21Z"
 | 
			
		||||
    "version": "v0.22.1809",
 | 
			
		||||
    "date": "2025-04-22T05:55:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "monicahq/monica",
 | 
			
		||||
    "version": "v4.1.2",
 | 
			
		||||
    "date": "2024-05-04T08:06:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "OliveTin/OliveTin",
 | 
			
		||||
    "version": "2025.4.21",
 | 
			
		||||
    "date": "2025-04-21T19:16:09Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Suwayomi/Suwayomi-Server",
 | 
			
		||||
    "version": "v2.0.1727",
 | 
			
		||||
    "date": "2025-04-21T17:53:05Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TasmoAdmin/TasmoAdmin",
 | 
			
		||||
    "version": "v4.3.0",
 | 
			
		||||
    "date": "2025-04-21T17:44:40Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "emqx/emqx",
 | 
			
		||||
    "version": "e5.9.0-beta.4",
 | 
			
		||||
    "date": "2025-04-21T17:08:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "runtipi/runtipi",
 | 
			
		||||
    "version": "v3.10.0-beta.9",
 | 
			
		||||
    "date": "2025-04-17T11:46:08Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "AdguardTeam/AdGuardHome",
 | 
			
		||||
    "version": "v0.107.60",
 | 
			
		||||
    "date": "2025-04-14T11:46:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "keycloak/keycloak",
 | 
			
		||||
    "version": "26.2.0",
 | 
			
		||||
    "date": "2025-04-11T12:48:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "cross-seed/cross-seed",
 | 
			
		||||
    "version": "v6.11.2",
 | 
			
		||||
    "date": "2025-02-26T14:54:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Prowlarr/Prowlarr",
 | 
			
		||||
    "version": "v1.34.1.5021",
 | 
			
		||||
    "date": "2025-04-20T19:29:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "semaphoreui/semaphore",
 | 
			
		||||
    "version": "v2.13.14",
 | 
			
		||||
    "date": "2025-04-19T20:39:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pocket-id/pocket-id",
 | 
			
		||||
    "version": "v0.49.0",
 | 
			
		||||
    "date": "2025-04-20T18:03:03Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "YunoHost/yunohost",
 | 
			
		||||
    "version": "debian/12.0.14",
 | 
			
		||||
    "date": "2025-04-09T10:09:00Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Kareadita/Kavita",
 | 
			
		||||
    "version": "v0.8.6.2",
 | 
			
		||||
    "date": "2025-04-20T16:55:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "openhab/openhab-core",
 | 
			
		||||
    "version": "5.0.0.M2",
 | 
			
		||||
    "date": "2025-04-20T13:16:29Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pocketbase/pocketbase",
 | 
			
		||||
    "version": "v0.27.1",
 | 
			
		||||
    "date": "2025-04-20T11:26:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "karakeep-app/karakeep",
 | 
			
		||||
    "version": "extension/v1.2.5",
 | 
			
		||||
    "date": "2025-04-20T10:19:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "MediaBrowser/Emby.Releases",
 | 
			
		||||
    "version": "4.8.11.0",
 | 
			
		||||
    "date": "2025-03-10T06:39:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Readarr/Readarr",
 | 
			
		||||
    "version": "v2.0.0.4645",
 | 
			
		||||
    "date": "2017-03-07T18:56:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Radarr/Radarr",
 | 
			
		||||
    "version": "v5.21.1.9799",
 | 
			
		||||
    "date": "2025-03-24T15:52:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "paperless-ngx/paperless-ngx",
 | 
			
		||||
    "version": "v2.15.3",
 | 
			
		||||
    "date": "2025-04-19T23:02:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ellite/Wallos",
 | 
			
		||||
    "version": "v2.52.0",
 | 
			
		||||
    "date": "2025-04-19T20:36:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "msgbyte/tianji",
 | 
			
		||||
    "version": "v1.20.7",
 | 
			
		||||
    "date": "2025-04-19T20:35:09Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "theonedev/onedev",
 | 
			
		||||
    "version": "v11.8.7",
 | 
			
		||||
    "date": "2025-04-19T11:19:29Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/core",
 | 
			
		||||
    "version": "2025.4.3",
 | 
			
		||||
    "date": "2025-04-19T10:23:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "moghtech/komodo",
 | 
			
		||||
    "version": "v1.17.2",
 | 
			
		||||
    "date": "2025-04-19T06:56:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ollama/ollama",
 | 
			
		||||
    "version": "v0.6.6-rc1",
 | 
			
		||||
    "date": "2025-04-17T01:56:29Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "caddyserver/caddy",
 | 
			
		||||
    "version": "v2.10.0",
 | 
			
		||||
    "date": "2025-04-18T20:46:28Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "homarr-labs/homarr",
 | 
			
		||||
    "version": "v1.17.0",
 | 
			
		||||
    "date": "2025-04-18T19:14:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Paymenter/Paymenter",
 | 
			
		||||
    "version": "v1.0.4",
 | 
			
		||||
    "date": "2025-04-18T16:08:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "prometheus/prometheus",
 | 
			
		||||
    "version": "v3.3.0",
 | 
			
		||||
    "date": "2025-04-18T13:46:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "dgtlmoon/changedetection.io",
 | 
			
		||||
    "version": "0.49.15",
 | 
			
		||||
    "date": "2025-04-18T12:58:26Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "traefik/traefik",
 | 
			
		||||
    "version": "v3.3.6",
 | 
			
		||||
    "date": "2025-04-18T09:28:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TandoorRecipes/recipes",
 | 
			
		||||
    "version": "1.5.34",
 | 
			
		||||
    "date": "2025-03-27T16:17:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Luligu/matterbridge",
 | 
			
		||||
    "version": "2.2.9",
 | 
			
		||||
    "date": "2025-04-18T10:05:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "HabitRPG/habitica",
 | 
			
		||||
    "version": "v5.35.4",
 | 
			
		||||
    "date": "2025-04-17T21:18:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "tailscale/tailscale",
 | 
			
		||||
    "version": "v1.82.5",
 | 
			
		||||
    "date": "2025-04-17T20:59:15Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TriliumNext/Notes",
 | 
			
		||||
    "version": "v0.93.0",
 | 
			
		||||
    "date": "2025-04-17T20:05:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "coder/code-server",
 | 
			
		||||
    "version": "v4.99.3",
 | 
			
		||||
    "date": "2025-04-17T18:33:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "VictoriaMetrics/VictoriaMetrics",
 | 
			
		||||
    "version": "v1.19.0-victorialogs",
 | 
			
		||||
    "date": "2025-04-17T18:26:31Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "duplicati/duplicati",
 | 
			
		||||
    "version": "v2.1.0.116-2.1.0.116_canary_2025-04-17",
 | 
			
		||||
    "date": "2025-04-17T17:52:31Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "benzino77/tasmocompiler",
 | 
			
		||||
    "version": "v12.6.1",
 | 
			
		||||
    "date": "2025-04-17T17:35:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "docker/compose",
 | 
			
		||||
    "version": "v2.35.1",
 | 
			
		||||
    "date": "2025-04-17T14:29:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "influxdata/influxdb",
 | 
			
		||||
    "version": "v3.0.1",
 | 
			
		||||
    "date": "2025-04-17T14:06:09Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "documenso/documenso",
 | 
			
		||||
    "version": "v1.10.0-rc.5",
 | 
			
		||||
    "date": "2025-04-17T13:01:43Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "prometheus-pve/prometheus-pve-exporter",
 | 
			
		||||
    "version": "v3.5.3",
 | 
			
		||||
    "date": "2025-04-17T10:40:47Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "IceWhaleTech/CasaOS",
 | 
			
		||||
    "version": "v0.4.15",
 | 
			
		||||
    "date": "2024-12-19T03:19:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "esphome/esphome",
 | 
			
		||||
    "version": "2025.4.0",
 | 
			
		||||
    "date": "2025-04-17T00:55:34Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "docmost/docmost",
 | 
			
		||||
    "version": "v0.10.2",
 | 
			
		||||
    "date": "2025-04-16T20:43:40Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "forgejo/forgejo",
 | 
			
		||||
    "version": "v11.0.0",
 | 
			
		||||
    "date": "2025-04-16T19:25:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "element-hq/synapse",
 | 
			
		||||
    "version": "v1.129.0rc1",
 | 
			
		||||
    "date": "2025-04-16T15:18:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jenkinsci/jenkins",
 | 
			
		||||
    "version": "jenkins-2.506",
 | 
			
		||||
    "date": "2025-04-15T15:40:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "wazuh/wazuh",
 | 
			
		||||
    "version": "coverity-w17-4.12.0",
 | 
			
		||||
    "date": "2025-04-16T11:20:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "icereed/paperless-gpt",
 | 
			
		||||
    "version": "v0.15.0",
 | 
			
		||||
    "date": "2025-04-16T03:58:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "rabbitmq/rabbitmq-server",
 | 
			
		||||
    "version": "v4.1.0",
 | 
			
		||||
    "date": "2025-04-15T16:18:29Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Brandawg93/PeaNUT",
 | 
			
		||||
    "version": "v5.7.2",
 | 
			
		||||
    "date": "2025-04-15T15:44:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "WordPress/WordPress",
 | 
			
		||||
    "version": "6.8",
 | 
			
		||||
    "date": "2025-04-15T15:41:16Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Stirling-Tools/Stirling-PDF",
 | 
			
		||||
    "version": "v0.45.6",
 | 
			
		||||
    "date": "2025-04-15T14:16:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "slskd/slskd",
 | 
			
		||||
@@ -34,91 +354,21 @@
 | 
			
		||||
    "version": "v0.14.1",
 | 
			
		||||
    "date": "2024-08-29T22:32:51Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "esphome/esphome",
 | 
			
		||||
    "version": "2025.3.3",
 | 
			
		||||
    "date": "2025-03-31T22:07:05Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "moghtech/komodo",
 | 
			
		||||
    "version": "v1.17.1",
 | 
			
		||||
    "date": "2025-04-14T22:35:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "influxdata/influxdb",
 | 
			
		||||
    "version": "v3.0.0",
 | 
			
		||||
    "date": "2025-04-14T22:16:28Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Kareadita/Kavita",
 | 
			
		||||
    "version": "v0.8.6",
 | 
			
		||||
    "date": "2025-04-14T22:09:30Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "keycloak/keycloak",
 | 
			
		||||
    "version": "26.2.0",
 | 
			
		||||
    "date": "2025-04-11T12:48:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "paperless-ngx/paperless-ngx",
 | 
			
		||||
    "version": "v2.15.2",
 | 
			
		||||
    "date": "2025-04-14T20:48:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "semaphoreui/semaphore",
 | 
			
		||||
    "version": "v2.13.13",
 | 
			
		||||
    "date": "2025-04-11T10:15:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "netbox-community/netbox",
 | 
			
		||||
    "version": "v4.2.7",
 | 
			
		||||
    "date": "2025-04-10T20:08:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "duplicati/duplicati",
 | 
			
		||||
    "version": "v2.1.0.115-2.1.0.115_canary_2025-04-14",
 | 
			
		||||
    "date": "2025-04-14T18:03:36Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "OliveTin/OliveTin",
 | 
			
		||||
    "version": "2025.4.14",
 | 
			
		||||
    "date": "2025-04-14T16:53:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "msgbyte/tianji",
 | 
			
		||||
    "version": "v1.20.0",
 | 
			
		||||
    "date": "2025-04-14T16:19:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/operating-system",
 | 
			
		||||
    "version": "15.2",
 | 
			
		||||
    "date": "2025-04-14T15:37:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Checkmk/checkmk",
 | 
			
		||||
    "version": "v2.4.0b5-rc1",
 | 
			
		||||
    "date": "2025-04-14T15:29:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "stackblitz-labs/bolt.diy",
 | 
			
		||||
    "version": "v0.0.7-hf1",
 | 
			
		||||
    "date": "2025-03-10T20:49:39Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "zabbix/zabbix",
 | 
			
		||||
    "version": "7.2.6rc1",
 | 
			
		||||
    "date": "2025-04-14T15:00:15Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "rabbitmq/rabbitmq-server",
 | 
			
		||||
    "version": "v4.0.9",
 | 
			
		||||
    "date": "2025-04-14T14:40:34Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "AdguardTeam/AdGuardHome",
 | 
			
		||||
    "version": "v0.107.60",
 | 
			
		||||
    "date": "2025-04-14T11:46:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Graylog2/graylog2-server",
 | 
			
		||||
    "version": "6.2.0-rc.1",
 | 
			
		||||
@@ -129,11 +379,6 @@
 | 
			
		||||
    "version": "v1.12.0",
 | 
			
		||||
    "date": "2025-04-14T10:36:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Stirling-Tools/Stirling-PDF",
 | 
			
		||||
    "version": "v0.45.5",
 | 
			
		||||
    "date": "2025-04-14T09:57:39Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "open-webui/open-webui",
 | 
			
		||||
    "version": "v0.6.5",
 | 
			
		||||
@@ -149,26 +394,11 @@
 | 
			
		||||
    "version": "0.203.1",
 | 
			
		||||
    "date": "2025-04-14T07:23:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "morpheus65535/bazarr",
 | 
			
		||||
    "version": "v1.5.1",
 | 
			
		||||
    "date": "2025-01-01T16:15:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "firefly-iii/firefly-iii",
 | 
			
		||||
    "version": "v6.2.10",
 | 
			
		||||
    "date": "2025-03-22T13:02:26Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "glanceapp/glance",
 | 
			
		||||
    "version": "v0.7.12",
 | 
			
		||||
    "date": "2025-04-14T00:16:15Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ellite/Wallos",
 | 
			
		||||
    "version": "v2.49.1",
 | 
			
		||||
    "date": "2025-04-13T22:36:24Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "rogerfar/rdt-client",
 | 
			
		||||
    "version": "v2.0.108",
 | 
			
		||||
@@ -184,21 +414,6 @@
 | 
			
		||||
    "version": "v4.47.1",
 | 
			
		||||
    "date": "2025-01-05T21:14:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pocket-id/pocket-id",
 | 
			
		||||
    "version": "v0.46.0",
 | 
			
		||||
    "date": "2025-04-13T18:31:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "runtipi/runtipi",
 | 
			
		||||
    "version": "v3.10.0",
 | 
			
		||||
    "date": "2025-03-15T14:38:16Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "karakeep-app/karakeep",
 | 
			
		||||
    "version": "mcp/v0.23.4",
 | 
			
		||||
    "date": "2025-04-13T14:09:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "syncthing/syncthing",
 | 
			
		||||
    "version": "v2.0.0-beta.9",
 | 
			
		||||
@@ -214,21 +429,6 @@
 | 
			
		||||
    "version": "v2.10.3.4602",
 | 
			
		||||
    "date": "2025-03-23T11:00:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Readarr/Readarr",
 | 
			
		||||
    "version": "v2.0.0.4645",
 | 
			
		||||
    "date": "2017-03-07T18:56:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Prowlarr/Prowlarr",
 | 
			
		||||
    "version": "v1.33.3.5008",
 | 
			
		||||
    "date": "2025-04-09T17:58:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Radarr/Radarr",
 | 
			
		||||
    "version": "v5.21.1.9799",
 | 
			
		||||
    "date": "2025-03-24T15:52:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Tautulli/Tautulli",
 | 
			
		||||
    "version": "v2.15.2",
 | 
			
		||||
@@ -239,16 +439,6 @@
 | 
			
		||||
    "version": "v0.2.11",
 | 
			
		||||
    "date": "2025-04-12T21:13:08Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "MediaBrowser/Emby.Releases",
 | 
			
		||||
    "version": "4.8.11.0",
 | 
			
		||||
    "date": "2025-03-10T06:39:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/core",
 | 
			
		||||
    "version": "2025.4.2",
 | 
			
		||||
    "date": "2025-04-12T09:46:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "readeck/readeck",
 | 
			
		||||
    "version": "0.18.0",
 | 
			
		||||
@@ -259,46 +449,11 @@
 | 
			
		||||
    "version": "v5.5.2",
 | 
			
		||||
    "date": "2025-04-11T22:00:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "homarr-labs/homarr",
 | 
			
		||||
    "version": "v1.16.0",
 | 
			
		||||
    "date": "2025-04-11T19:15:24Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "tailscale/tailscale",
 | 
			
		||||
    "version": "v1.82.4",
 | 
			
		||||
    "date": "2025-04-11T17:58:09Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "coder/code-server",
 | 
			
		||||
    "version": "v4.99.2",
 | 
			
		||||
    "date": "2025-04-11T17:57:47Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TriliumNext/Notes",
 | 
			
		||||
    "version": "v0.0.0",
 | 
			
		||||
    "date": "2025-04-11T14:18:00Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "emqx/emqx",
 | 
			
		||||
    "version": "e5.9.0-beta.3",
 | 
			
		||||
    "date": "2025-04-11T14:17:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "NLnetLabs/unbound",
 | 
			
		||||
    "version": "release-1.23.0rc2",
 | 
			
		||||
    "date": "2025-04-11T13:24:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "docmost/docmost",
 | 
			
		||||
    "version": "v0.10.1",
 | 
			
		||||
    "date": "2025-04-11T12:42:08Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "dgtlmoon/changedetection.io",
 | 
			
		||||
    "version": "0.49.13",
 | 
			
		||||
    "date": "2025-04-11T11:48:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "sabnzbd/sabnzbd",
 | 
			
		||||
    "version": "4.5.1",
 | 
			
		||||
@@ -309,16 +464,6 @@
 | 
			
		||||
    "version": "v0.83.0",
 | 
			
		||||
    "date": "2025-04-11T03:53:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "openobserve/openobserve",
 | 
			
		||||
    "version": "v0.14.6-rc3",
 | 
			
		||||
    "date": "2025-04-11T03:08:28Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Luligu/matterbridge",
 | 
			
		||||
    "version": "2.2.8",
 | 
			
		||||
    "date": "2025-04-10T20:30:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "gristlabs/grist-core",
 | 
			
		||||
    "version": "v1.5.1",
 | 
			
		||||
@@ -329,26 +474,11 @@
 | 
			
		||||
    "version": "cassandra-5.0.4",
 | 
			
		||||
    "date": "2025-04-10T16:32:00Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "VictoriaMetrics/VictoriaMetrics",
 | 
			
		||||
    "version": "v1.18.0-victorialogs",
 | 
			
		||||
    "date": "2025-04-10T15:05:20Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "NodeBB/NodeBB",
 | 
			
		||||
    "version": "v4.2.1",
 | 
			
		||||
    "date": "2025-04-10T14:03:47Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Paymenter/Paymenter",
 | 
			
		||||
    "version": "v1.0.3",
 | 
			
		||||
    "date": "2025-04-10T13:57:39Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "docker/compose",
 | 
			
		||||
    "version": "v2.35.0",
 | 
			
		||||
    "date": "2025-04-10T13:45:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mongodb/mongo",
 | 
			
		||||
    "version": "r8.0.5-rc2",
 | 
			
		||||
@@ -359,31 +489,16 @@
 | 
			
		||||
    "version": "v7.4.0",
 | 
			
		||||
    "date": "2025-04-09T17:36:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "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": "HabitRPG/habitica",
 | 
			
		||||
    "version": "v5.35.2",
 | 
			
		||||
    "date": "2025-04-09T13:46:58Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "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": "minio/minio",
 | 
			
		||||
    "version": "RELEASE.2025-04-08T15-41-24Z",
 | 
			
		||||
@@ -394,26 +509,11 @@
 | 
			
		||||
    "version": "version/2025.2.4",
 | 
			
		||||
    "date": "2025-04-08T18:39:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jenkinsci/jenkins",
 | 
			
		||||
    "version": "jenkins-2.505",
 | 
			
		||||
    "date": "2025-04-08T15:46:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "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",
 | 
			
		||||
    "version": "v0.303.0-rc.1",
 | 
			
		||||
    "date": "2025-04-07T04:39:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pelican-dev/panel",
 | 
			
		||||
    "version": "v1.0.0-beta19",
 | 
			
		||||
@@ -449,11 +549,6 @@
 | 
			
		||||
    "version": "8.0-rc1-int2",
 | 
			
		||||
    "date": "2025-04-02T19:05:08Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "nzbgetcom/nzbget",
 | 
			
		||||
    "version": "v24.8",
 | 
			
		||||
    "date": "2025-03-18T07:33:51Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Dolibarr/dolibarr",
 | 
			
		||||
    "version": "21.0.1",
 | 
			
		||||
@@ -469,11 +564,6 @@
 | 
			
		||||
    "version": "2.0.3",
 | 
			
		||||
    "date": "2025-04-06T17:35:41Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TandoorRecipes/recipes",
 | 
			
		||||
    "version": "1.5.34",
 | 
			
		||||
    "date": "2025-03-27T16:17:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TechnitiumSoftware/DnsServer",
 | 
			
		||||
    "version": "v13.5.0",
 | 
			
		||||
@@ -489,11 +579,6 @@
 | 
			
		||||
    "version": "0.17.10",
 | 
			
		||||
    "date": "2025-04-06T05:31:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ollama/ollama",
 | 
			
		||||
    "version": "v0.6.5",
 | 
			
		||||
    "date": "2025-04-06T00:15:39Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jellyfin/jellyfin",
 | 
			
		||||
    "version": "v10.10.7",
 | 
			
		||||
@@ -539,21 +624,11 @@
 | 
			
		||||
    "version": "5.7.0",
 | 
			
		||||
    "date": "2025-04-04T18:10:16Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "icereed/paperless-gpt",
 | 
			
		||||
    "version": "v0.14.4",
 | 
			
		||||
    "date": "2025-04-04T14:18:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "apache/tomcat",
 | 
			
		||||
    "version": "9.0.104",
 | 
			
		||||
    "date": "2025-04-04T12:58:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "OctoPrint/OctoPrint",
 | 
			
		||||
    "version": "1.10.3",
 | 
			
		||||
    "date": "2024-11-05T09:20:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "BookStackApp/BookStack",
 | 
			
		||||
    "version": "v25.02.2",
 | 
			
		||||
@@ -579,11 +654,6 @@
 | 
			
		||||
    "version": "v2.31.0",
 | 
			
		||||
    "date": "2025-04-01T18:12:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "theonedev/onedev",
 | 
			
		||||
    "version": "v11.8.6",
 | 
			
		||||
    "date": "2025-04-01T13:52:03Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "neo4j/neo4j",
 | 
			
		||||
    "version": "5.26.5",
 | 
			
		||||
@@ -600,14 +670,9 @@
 | 
			
		||||
    "date": "2025-03-31T21:31:48Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "traefik/traefik",
 | 
			
		||||
    "version": "v3.3.5",
 | 
			
		||||
    "date": "2025-03-31T08:55:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "documenso/documenso",
 | 
			
		||||
    "version": "v1.10.0-rc.4",
 | 
			
		||||
    "date": "2025-03-31T09:02:22Z"
 | 
			
		||||
    "name": "mysql/mysql-server",
 | 
			
		||||
    "version": "mysql-cluster-9.3.0",
 | 
			
		||||
    "date": "2025-03-31T07:42:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "louislam/dockge",
 | 
			
		||||
@@ -624,16 +689,6 @@
 | 
			
		||||
    "version": "v1.17.0",
 | 
			
		||||
    "date": "2025-03-30T14:21:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "openhab/openhab-core",
 | 
			
		||||
    "version": "4.3.4",
 | 
			
		||||
    "date": "2025-03-30T13:32:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pocketbase/pocketbase",
 | 
			
		||||
    "version": "v0.26.6",
 | 
			
		||||
    "date": "2025-03-30T08:02:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "aceberg/WatchYourLAN",
 | 
			
		||||
    "version": "2.1.2-alpine",
 | 
			
		||||
@@ -654,11 +709,6 @@
 | 
			
		||||
    "version": "v1.6.1",
 | 
			
		||||
    "date": "2025-03-15T17:29:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TasmoAdmin/TasmoAdmin",
 | 
			
		||||
    "version": "v4.2.3",
 | 
			
		||||
    "date": "2025-02-09T23:07:48Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "grocy/grocy",
 | 
			
		||||
    "version": "v4.5.0",
 | 
			
		||||
@@ -689,11 +739,6 @@
 | 
			
		||||
    "version": "2025.2",
 | 
			
		||||
    "date": "2025-03-27T19:21:13Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "forgejo/forgejo",
 | 
			
		||||
    "version": "v12.0.0-dev",
 | 
			
		||||
    "date": "2025-03-26T09:58:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "sct/overseerr",
 | 
			
		||||
    "version": "v1.34.0",
 | 
			
		||||
@@ -724,11 +769,6 @@
 | 
			
		||||
    "version": "v1.6.8",
 | 
			
		||||
    "date": "2025-03-25T13:33:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "caddyserver/caddy",
 | 
			
		||||
    "version": "v2.9.1",
 | 
			
		||||
    "date": "2025-01-08T15:22:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ZoeyVid/NPMplus",
 | 
			
		||||
    "version": "2025-03-24-r2",
 | 
			
		||||
@@ -885,7 +925,7 @@
 | 
			
		||||
    "date": "2025-03-05T21:41:29Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "snipe/snipe-it",
 | 
			
		||||
    "name": "grokability/snipe-it",
 | 
			
		||||
    "version": "v8.0.4",
 | 
			
		||||
    "date": "2025-03-05T17:12:03Z"
 | 
			
		||||
  },
 | 
			
		||||
@@ -909,11 +949,6 @@
 | 
			
		||||
    "version": "v1.5.7",
 | 
			
		||||
    "date": "2025-02-27T20:04:08Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "cross-seed/cross-seed",
 | 
			
		||||
    "version": "v6.11.2",
 | 
			
		||||
    "date": "2025-02-26T14:54:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "silverbulletmd/silverbullet",
 | 
			
		||||
    "version": "0.10.4",
 | 
			
		||||
@@ -924,11 +959,6 @@
 | 
			
		||||
    "version": "v0.25.1",
 | 
			
		||||
    "date": "2025-02-25T17:30:48Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "benzino77/tasmocompiler",
 | 
			
		||||
    "version": "v12.5.0",
 | 
			
		||||
    "date": "2025-02-25T14:55:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "schlagmichdoch/PairDrop",
 | 
			
		||||
    "version": "v1.11.2",
 | 
			
		||||
@@ -949,11 +979,6 @@
 | 
			
		||||
    "version": "v1.1.05",
 | 
			
		||||
    "date": "2025-02-24T11:53:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "prometheus-pve/prometheus-pve-exporter",
 | 
			
		||||
    "version": "v3.5.2",
 | 
			
		||||
    "date": "2025-02-18T16:43:41Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "typesense/typesense",
 | 
			
		||||
    "version": "v28.0",
 | 
			
		||||
@@ -994,11 +1019,6 @@
 | 
			
		||||
    "version": "mariadb-11.7.2",
 | 
			
		||||
    "date": "2025-02-13T04:13:46Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "WordPress/WordPress",
 | 
			
		||||
    "version": "6.7.2",
 | 
			
		||||
    "date": "2025-02-11T16:13:18Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "homebridge/homebridge",
 | 
			
		||||
    "version": "v1.9.0",
 | 
			
		||||
@@ -1079,16 +1099,6 @@
 | 
			
		||||
    "version": "v0.24.6",
 | 
			
		||||
    "date": "2024-12-22T20:24:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "IceWhaleTech/CasaOS",
 | 
			
		||||
    "version": "v0.4.15",
 | 
			
		||||
    "date": "2024-12-19T03:19:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mysql/mysql-server",
 | 
			
		||||
    "version": "mysql-cluster-7.6.33",
 | 
			
		||||
    "date": "2024-12-16T11:55:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ArchiveBox/ArchiveBox",
 | 
			
		||||
    "version": "v0.7.3",
 | 
			
		||||
@@ -1184,11 +1194,6 @@
 | 
			
		||||
    "version": "v3.3.21",
 | 
			
		||||
    "date": "2024-06-26T01:14:46Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Suwayomi/Suwayomi-Server",
 | 
			
		||||
    "version": "v1.1.1",
 | 
			
		||||
    "date": "2024-06-15T17:23:48Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Forceu/barcodebuddy",
 | 
			
		||||
    "version": "v1.8.1.8",
 | 
			
		||||
@@ -1224,11 +1229,6 @@
 | 
			
		||||
    "version": "1.0.0",
 | 
			
		||||
    "date": "2024-05-05T02:01:51Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "monicahq/monica",
 | 
			
		||||
    "version": "v4.1.2",
 | 
			
		||||
    "date": "2024-05-04T08:06:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "thelounge/thelounge-deb",
 | 
			
		||||
    "version": "v4.4.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,8 @@ const generateSourceUrl = (slug: string, type: string) => {
 | 
			
		||||
      return `${baseUrl}/tools/pve/${slug}.sh`;
 | 
			
		||||
    case "addon":
 | 
			
		||||
      return `${baseUrl}/tools/addon/${slug}.sh`;
 | 
			
		||||
    case "turnkey":
 | 
			
		||||
      return `${baseUrl}/turnkey/${slug}.sh`;
 | 
			
		||||
    default:
 | 
			
		||||
      return `${baseUrl}/ct/${slug}.sh`; // fallback for "ct"
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -137,6 +137,7 @@ cat <<EOF >/etc/systemd/system/browserless.service
 | 
			
		||||
Description=browserless service
 | 
			
		||||
After=network.target
 | 
			
		||||
[Service]
 | 
			
		||||
Environment=CONNECTION_TIMEOUT=60000
 | 
			
		||||
WorkingDirectory=/opt/browserless
 | 
			
		||||
ExecStart=/opt/browserless/scripts/start.sh
 | 
			
		||||
SyslogIdentifier=browserless
 | 
			
		||||
 
 | 
			
		||||
@@ -47,19 +47,13 @@ msg_ok "Installed Node.js"
 | 
			
		||||
msg_info "Setup ${APPLICATION} (Patience)"
 | 
			
		||||
temp_file=$(mktemp)
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/StarFleetCPTN/GoMFT/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
curl -fsSL "https://github.com/StarFleetCPTN/GoMFT/archive/refs/tags/v${RELEASE}.tar.gz" -o $temp_file
 | 
			
		||||
tar -xzf $temp_file
 | 
			
		||||
mv GoMFT-${RELEASE}/ /opt/gomft
 | 
			
		||||
curl -fsSL "https://github.com/StarFleetCPTN/GoMFT/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
 | 
			
		||||
tar -xzf "$temp_file"
 | 
			
		||||
mv GoMFT-"${RELEASE}"/ /opt/gomft
 | 
			
		||||
cd /opt/gomft
 | 
			
		||||
$STD npm ci
 | 
			
		||||
$STD node build.js
 | 
			
		||||
$STD go mod download
 | 
			
		||||
$STD go install github.com/a-h/templ/cmd/templ@latest
 | 
			
		||||
$STD go get -u github.com/a-h/templ
 | 
			
		||||
$STD $HOME/go/bin/templ generate
 | 
			
		||||
export CGO_ENABLED=1
 | 
			
		||||
export GOOS=linux
 | 
			
		||||
$STD go build -o gomft
 | 
			
		||||
$STD "$HOME"/go/bin/templ generate
 | 
			
		||||
$STD go build -o gomft main.go
 | 
			
		||||
chmod +x /opt/gomft/gomft
 | 
			
		||||
JWT_SECRET_KEY=$(openssl rand -base64 24 | tr -d '/+=')
 | 
			
		||||
 | 
			
		||||
@@ -83,7 +77,7 @@ EMAIL_USERNAME=smtp_username
 | 
			
		||||
EMAIL_PASSWORD=smtp_password
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
 | 
			
		||||
echo "${RELEASE}" >/opt/"${APPLICATION}"_version.txt
 | 
			
		||||
msg_ok "Setup ${APPLICATION}"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
@@ -109,7 +103,7 @@ motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -f $temp_file
 | 
			
		||||
rm -f "$temp_file"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ msg_info "Installing Peanut"
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/Brandawg93/PeaNUT/releases/latest | grep '"tag_name":' | cut -d'"' -f4)
 | 
			
		||||
curl -fsSL "https://api.github.com/repos/Brandawg93/PeaNUT/tarball/${RELEASE}" -o "peanut.tar.gz"
 | 
			
		||||
mkdir -p /opt/peanut
 | 
			
		||||
tar -xzf peanut.tar.gz -C /opt/peanut --strip-components 1
 | 
			
		||||
tar -xzf peanut.tar.gz -C /opt/peanut --strip-components=1
 | 
			
		||||
rm peanut.tar.gz
 | 
			
		||||
cd /opt/peanut
 | 
			
		||||
$STD npm install -g pnpm
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										190
									
								
								install/reactive-resume-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								install/reactive-resume-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,190 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: vhsdream
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://rxresu.me
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
 | 
			
		||||
color
 | 
			
		||||
verb_ip6
 | 
			
		||||
catch_errors
 | 
			
		||||
setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
    gnupg \
 | 
			
		||||
    unzip \
 | 
			
		||||
    postgresql-common
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Additional Dependencies"
 | 
			
		||||
mkdir -p /etc/apt/keyrings
 | 
			
		||||
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
 | 
			
		||||
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_22.x nodistro main" >/etc/apt/sources.list.d/nodesource.list
 | 
			
		||||
echo "YES" | /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh &>/dev/null
 | 
			
		||||
$STD apt-get install -y postgresql-16 nodejs
 | 
			
		||||
cd /tmp
 | 
			
		||||
curl -fsSL https://dl.min.io/server/minio/release/linux-amd64/minio.deb -o minio.deb
 | 
			
		||||
$STD dpkg -i minio.deb
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Database"
 | 
			
		||||
DB_USER="rxresume"
 | 
			
		||||
DB_NAME="rxresume"
 | 
			
		||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_PASS';"
 | 
			
		||||
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME WITH OWNER $DB_USER ENCODING 'UTF8' TEMPLATE template0;"
 | 
			
		||||
$STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME to $DB_USER;"
 | 
			
		||||
$STD sudo -u postgres psql -c "ALTER USER $DB_USER WITH SUPERUSER;"
 | 
			
		||||
msg_ok "Set up Database"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing ${APPLICATION}"
 | 
			
		||||
MINIO_PASS=$(openssl rand -base64 48)
 | 
			
		||||
ACCESS_TOKEN=$(openssl rand -base64 48)
 | 
			
		||||
REFRESH_TOKEN=$(openssl rand -base64 48)
 | 
			
		||||
CHROME_TOKEN=$(openssl rand -hex 32)
 | 
			
		||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
 | 
			
		||||
TAG=$(curl -fsSL https://api.github.com/repos/browserless/browserless/tags?per_page=1 | grep "name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/AmruthPillai/Reactive-Resume/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
curl -fsSL "https://github.com/AmruthPillai/Reactive-Resume/archive/refs/tags/v${RELEASE}.zip" -o v${RELEASE}.zip
 | 
			
		||||
unzip -q v${RELEASE}.zip
 | 
			
		||||
mv ${APPLICATION}-${RELEASE}/ /opt/${APPLICATION}
 | 
			
		||||
cd /opt/${APPLICATION}
 | 
			
		||||
corepack enable
 | 
			
		||||
export CI="true"
 | 
			
		||||
export PUPPETEER_SKIP_DOWNLOAD="true"
 | 
			
		||||
export NODE_ENV="production"
 | 
			
		||||
export NEXT_TELEMETRY_DISABLED=1
 | 
			
		||||
$STD pnpm install --frozen-lockfile
 | 
			
		||||
$STD pnpm run build
 | 
			
		||||
$STD pnpm install --prod --frozen-lockfile
 | 
			
		||||
$STD pnpm run prisma:generate
 | 
			
		||||
msg_ok "Installed ${APPLICATION}"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Browserless (Patience)"
 | 
			
		||||
cd /tmp
 | 
			
		||||
curl -fsSL https://github.com/browserless/browserless/archive/refs/tags/v${TAG}.zip -o v${TAG}.zip
 | 
			
		||||
unzip -q v${TAG}.zip
 | 
			
		||||
mv browserless-${TAG} /opt/browserless
 | 
			
		||||
cd /opt/browserless
 | 
			
		||||
$STD npm install
 | 
			
		||||
rm -rf src/routes/{chrome,edge,firefox,webkit}
 | 
			
		||||
$STD node_modules/playwright-core/cli.js install --with-deps chromium
 | 
			
		||||
$STD npm run build
 | 
			
		||||
$STD npm run build:function
 | 
			
		||||
$STD npm prune production
 | 
			
		||||
msg_ok "Installed Browserless"
 | 
			
		||||
 | 
			
		||||
msg_info "Configuring applications"
 | 
			
		||||
mkdir -p /opt/minio
 | 
			
		||||
cat <<EOF >/opt/minio/.env
 | 
			
		||||
MINIO_ROOT_USER="storageadmin"
 | 
			
		||||
MINIO_ROOT_PASSWORD="${MINIO_PASS}"
 | 
			
		||||
MINIO_VOLUMES=/opt/minio
 | 
			
		||||
MINIO_OPTS="--address :9000 --console-address 127.0.0.1:9001"
 | 
			
		||||
EOF
 | 
			
		||||
cat <<EOF >/opt/${APPLICATION}/.env
 | 
			
		||||
NODE_ENV=production
 | 
			
		||||
PORT=3000
 | 
			
		||||
PUBLIC_URL=http://${LOCAL_IP}:3000
 | 
			
		||||
STORAGE_URL=http://${LOCAL_IP}:9000/rxresume
 | 
			
		||||
DATABASE_URL=postgresql://${DB_USER}:${DB_PASS}@localhost:5432/${DB_NAME}?schema=public
 | 
			
		||||
ACCESS_TOKEN_SECRET=${ACCESS_TOKEN}
 | 
			
		||||
REFRESH_TOKEN_SECRET=${REFRESH_TOKEN}
 | 
			
		||||
CHROME_PORT=8080
 | 
			
		||||
CHROME_TOKEN=${CHROME_TOKEN}
 | 
			
		||||
CHROME_URL=ws://localhost:8080
 | 
			
		||||
CHROME_IGNORE_HTTPS_ERRORS=true
 | 
			
		||||
MAIL_FROM=noreply@locahost
 | 
			
		||||
# SMTP_URL=smtp://username:password@smtp.server.mail:587 #
 | 
			
		||||
STORAGE_ENDPOINT=localhost
 | 
			
		||||
STORAGE_PORT=9000
 | 
			
		||||
STORAGE_REGION=us-east-1
 | 
			
		||||
STORAGE_BUCKET=rxresume
 | 
			
		||||
STORAGE_ACCESS_KEY=storageadmin
 | 
			
		||||
STORAGE_SECRET_KEY=${MINIO_PASS}
 | 
			
		||||
STORAGE_USE_SSL=false
 | 
			
		||||
STORAGE_SKIP_BUCKET_CHECK=false
 | 
			
		||||
 | 
			
		||||
# GitHub (OAuth, Optional)
 | 
			
		||||
# GITHUB_CLIENT_ID=
 | 
			
		||||
# GITHUB_CLIENT_SECRET=
 | 
			
		||||
# GITHUB_CALLBACK_URL=http://localhost:5173/api/auth/github/callback
 | 
			
		||||
 | 
			
		||||
# Google (OAuth, Optional)
 | 
			
		||||
# GOOGLE_CLIENT_ID=
 | 
			
		||||
# GOOGLE_CLIENT_SECRET=
 | 
			
		||||
# GOOGLE_CALLBACK_URL=http://localhost:5173/api/auth/google/callback
 | 
			
		||||
EOF
 | 
			
		||||
cat <<EOF >/opt/browserless/.env
 | 
			
		||||
DEBUG=browserless*,-**:verbose
 | 
			
		||||
HOST=localhost
 | 
			
		||||
PORT=8080
 | 
			
		||||
TOKEN=${CHROME_TOKEN}
 | 
			
		||||
EOF
 | 
			
		||||
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
 | 
			
		||||
{
 | 
			
		||||
    echo "${APPLICATION} Credentials"
 | 
			
		||||
    echo "Database User: $DB_USER"
 | 
			
		||||
    echo "Database Password: $DB_PASS"
 | 
			
		||||
    echo "Database Name: $DB_NAME"
 | 
			
		||||
    echo "Minio Root Password: ${MINIO_PASS}"
 | 
			
		||||
} >>~/${APPLICATION}.creds
 | 
			
		||||
msg_ok "Configured applications"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Services"
 | 
			
		||||
mkdir -p /etc/systemd/system/minio.service.d/
 | 
			
		||||
cat <<EOF >/etc/systemd/system/minio.service.d/override.conf
 | 
			
		||||
[Service]
 | 
			
		||||
User=root
 | 
			
		||||
Group=root
 | 
			
		||||
WorkingDirectory=/usr/local/bin
 | 
			
		||||
EnvironmentFile=/opt/minio/.env
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
cat <<EOF >/etc/systemd/system/${APPLICATION}.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=${APPLICATION} Service
 | 
			
		||||
After=network.target postgresql.service minio.service
 | 
			
		||||
Wants=postgresql.service minio.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
WorkingDirectory=/opt/${APPLICATION}
 | 
			
		||||
EnvironmentFile=/opt/${APPLICATION}/.env
 | 
			
		||||
ExecStart=/usr/bin/pnpm run start
 | 
			
		||||
Restart=always
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
cat <<EOF >/etc/systemd/system/browserless.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Browserless service
 | 
			
		||||
After=network.target ${APPLICATION}.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
WorkingDirectory=/opt/browserless
 | 
			
		||||
EnvironmentFile=/opt/browserless/.env
 | 
			
		||||
ExecStart=/usr/bin/npm run start
 | 
			
		||||
Restart=unless-stopped
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
systemctl daemon-reload
 | 
			
		||||
systemctl enable -q --now minio.service ${APPLICATION}.service browserless.service
 | 
			
		||||
msg_ok "Created Services"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -f /tmp/v${RELEASE}.zip
 | 
			
		||||
rm -f /tmp/v${TAG}.zip
 | 
			
		||||
rm -f /tmp/minio.deb
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -16,7 +16,8 @@ update_os
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  make \
 | 
			
		||||
  gcc
 | 
			
		||||
  gcc \
 | 
			
		||||
  gpg
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Golang"
 | 
			
		||||
@@ -43,8 +44,8 @@ msg_ok "Installed Node.js"
 | 
			
		||||
msg_info "Setting up seelf. Patience"
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/YuukanOO/seelf/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
curl -fsSL "https://github.com/YuukanOO/seelf/archive/refs/tags/v${RELEASE}.tar.gz" -o $(basename "https://github.com/YuukanOO/seelf/archive/refs/tags/v${RELEASE}.tar.gz")
 | 
			
		||||
tar -xzf v${RELEASE}.tar.gz
 | 
			
		||||
mv seelf-${RELEASE}/ /opt/seelf
 | 
			
		||||
tar -xzf v"${RELEASE}".tar.gz
 | 
			
		||||
mv seelf-"${RELEASE}"/ /opt/seelf
 | 
			
		||||
cd /opt/seelf
 | 
			
		||||
$STD make build
 | 
			
		||||
PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
@@ -84,8 +85,8 @@ customize
 | 
			
		||||
 | 
			
		||||
# Cleanup
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -f ~/v${RELEASE}.tar.gz
 | 
			
		||||
rm -f $temp_file
 | 
			
		||||
rm -f ~/v"${RELEASE}".tar.gz
 | 
			
		||||
rm -f "$temp_file"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 
 | 
			
		||||
@@ -15,10 +15,10 @@ update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
    git \
 | 
			
		||||
    gnupg \
 | 
			
		||||
    apache2 \
 | 
			
		||||
    libapache2-mod-wsgi-py3
 | 
			
		||||
  git \
 | 
			
		||||
  gnupg \
 | 
			
		||||
  apache2 \
 | 
			
		||||
  libapache2-mod-wsgi-py3
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Python"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										867
									
								
								misc/add-iptag.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										867
									
								
								misc/add-iptag.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,867 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: MickLesk (Canbiz) && Desert_Gamer
 | 
			
		||||
# License: MIT
 | 
			
		||||
# Source: https://github.com/gitsang/iptag
 | 
			
		||||
 | 
			
		||||
function header_info {
 | 
			
		||||
  clear
 | 
			
		||||
  cat <<"EOF"
 | 
			
		||||
 ___ ____     _____
 | 
			
		||||
|_ _|  _ \ _ |_   _|_ _  __ _
 | 
			
		||||
 | || |_) (_)  | |/ _` |/ _` |
 | 
			
		||||
 | ||  __/ _   | | (_| | (_| |
 | 
			
		||||
|___|_|   (_)  |_|\__,_|\__, |
 | 
			
		||||
                        |___/
 | 
			
		||||
EOF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
clear
 | 
			
		||||
header_info
 | 
			
		||||
APP="IP-Tag"
 | 
			
		||||
hostname=$(hostname)
 | 
			
		||||
 | 
			
		||||
# Farbvariablen
 | 
			
		||||
YW=$(echo "\033[33m")
 | 
			
		||||
GN=$(echo "\033[1;92m")
 | 
			
		||||
RD=$(echo "\033[01;31m")
 | 
			
		||||
CL=$(echo "\033[m")
 | 
			
		||||
BFR="\\r\\033[K"
 | 
			
		||||
HOLD=" "
 | 
			
		||||
CM=" ✔️ ${CL}"
 | 
			
		||||
CROSS=" ✖️ ${CL}"
 | 
			
		||||
 | 
			
		||||
# This function enables error handling in the script by setting options and defining a trap for the ERR signal.
 | 
			
		||||
catch_errors() {
 | 
			
		||||
  set -Eeuo pipefail
 | 
			
		||||
  trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
    kill $SPINNER_PID >/dev/null
 | 
			
		||||
  fi
 | 
			
		||||
  printf "\e[?25h"
 | 
			
		||||
  local exit_code="$?"
 | 
			
		||||
  local line_number="$1"
 | 
			
		||||
  local command="$2"
 | 
			
		||||
  local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
 | 
			
		||||
  echo -e "\n$error_message\n"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function displays a spinner.
 | 
			
		||||
spinner() {
 | 
			
		||||
  local frames=('⠋' '⠙' '⠹' '⠸' '⠼' '⠴' '⠦' '⠧' '⠇' '⠏')
 | 
			
		||||
  local spin_i=0
 | 
			
		||||
  local interval=0.1
 | 
			
		||||
  printf "\e[?25l"
 | 
			
		||||
 | 
			
		||||
  local color="${YWB}"
 | 
			
		||||
 | 
			
		||||
  while true; do
 | 
			
		||||
    printf "\r ${color}%s${CL}" "${frames[spin_i]}"
 | 
			
		||||
    spin_i=$(((spin_i + 1) % ${#frames[@]}))
 | 
			
		||||
    sleep "$interval"
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function displays an informational message with a yellow color.
 | 
			
		||||
msg_info() {
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -ne "${TAB}${YW}${HOLD}${msg}${HOLD}"
 | 
			
		||||
  spinner &
 | 
			
		||||
  SPINNER_PID=$!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function displays a success message with a green color.
 | 
			
		||||
msg_ok() {
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
 | 
			
		||||
    kill $SPINNER_PID >/dev/null
 | 
			
		||||
  fi
 | 
			
		||||
  printf "\e[?25h"
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${BFR}${CM}${GN}${msg}${CL}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# This function displays a error message with a red color.
 | 
			
		||||
msg_error() {
 | 
			
		||||
  if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then
 | 
			
		||||
    kill $SPINNER_PID >/dev/null
 | 
			
		||||
  fi
 | 
			
		||||
  printf "\e[?25h"
 | 
			
		||||
  local msg="$1"
 | 
			
		||||
  echo -e "${BFR}${CROSS}${RD}${msg}${CL}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if service exists
 | 
			
		||||
check_service_exists() {
 | 
			
		||||
  if systemctl is-active --quiet iptag.service; then
 | 
			
		||||
    return 0
 | 
			
		||||
  else
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Migrate configuration from old path to new
 | 
			
		||||
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
 | 
			
		||||
      rm -rf "$old_config" &>/dev/null
 | 
			
		||||
      msg_ok "Configuration migrated and old config removed"
 | 
			
		||||
    else
 | 
			
		||||
      msg_error "Failed to migrate configuration"
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Update existing installation
 | 
			
		||||
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
 | 
			
		||||
# =============== CONFIGURATION =============== #
 | 
			
		||||
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"
 | 
			
		||||
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))"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if IP is in CIDR
 | 
			
		||||
ip_in_cidr() {
 | 
			
		||||
    local ip="$1" cidr="$2"
 | 
			
		||||
    ipcalc -c "$ip" "$cidr" >/dev/null 2>&1 || return 1
 | 
			
		||||
 | 
			
		||||
    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"
 | 
			
		||||
 | 
			
		||||
    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:-$DEFAULT_TAG_FORMAT}"
 | 
			
		||||
 | 
			
		||||
    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" 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='.' parts
 | 
			
		||||
    read -ra parts <<< "$ip"
 | 
			
		||||
    for part in "${parts[@]}"; do
 | 
			
		||||
        (( 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 ips="" macs found_ip=false
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
update_tags() {
 | 
			
		||||
    local type="$1" vmid="$2" config_cmd="pct"
 | 
			
		||||
    [[ "$type" == "vm" ]] && config_cmd="qm"
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
    [[ -z "$current_ips_full" ]] && return
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
        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
 | 
			
		||||
    elif [[ ${#current_ip_tags[@]} -gt 0 ]]; then
 | 
			
		||||
        echo "${type^} ${vmid}: IP tags already set: ${current_ip_tags[*]}"
 | 
			
		||||
    else
 | 
			
		||||
        echo "${type^} ${vmid}: setting initial IP tags: ${formatted_ips[*]}"
 | 
			
		||||
        $config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${formatted_ips[*]}")" &>/dev/null
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if status changed
 | 
			
		||||
check_status() {
 | 
			
		||||
    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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Update all instances
 | 
			
		||||
update_all() {
 | 
			
		||||
    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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Main check function
 | 
			
		||||
check() {
 | 
			
		||||
    local current_time changes_detected=false
 | 
			
		||||
    current_time=$(date +%s)
 | 
			
		||||
 | 
			
		||||
    for type in "lxc" "vm"; do
 | 
			
		||||
        local interval_var="${type^^}_STATUS_CHECK_INTERVAL"
 | 
			
		||||
        local last_check_var="last_${type}_check_time"
 | 
			
		||||
        local last_update_var="last_update_${type}_time"
 | 
			
		||||
        
 | 
			
		||||
        if [[ "${!interval_var}" -gt 0 ]] && (( current_time - ${!last_check_var} >= ${!interval_var} )); then
 | 
			
		||||
            echo "Checking ${type^^} status..."
 | 
			
		||||
            eval "${last_check_var}=\$current_time"
 | 
			
		||||
            if check_status "$type"; then
 | 
			
		||||
                changes_detected=true
 | 
			
		||||
                update_all "$type"
 | 
			
		||||
                eval "${last_update_var}=\$current_time"
 | 
			
		||||
            fi
 | 
			
		||||
        fi
 | 
			
		||||
 | 
			
		||||
        if (( current_time - ${!last_update_var} >= FORCE_UPDATE_INTERVAL )); then
 | 
			
		||||
            echo "Force updating ${type} tags..."
 | 
			
		||||
            changes_detected=true
 | 
			
		||||
            update_all "$type"
 | 
			
		||||
            eval "${last_update_var}=\$current_time"
 | 
			
		||||
        fi
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] && \
 | 
			
		||||
       (( current_time - last_fw_check_time >= FW_NET_INTERFACE_CHECK_INTERVAL )); then
 | 
			
		||||
        echo "Checking network interfaces..."
 | 
			
		||||
        last_fw_check_time=$current_time
 | 
			
		||||
        if check_status "fw"; then
 | 
			
		||||
            changes_detected=true
 | 
			
		||||
            update_all "lxc"
 | 
			
		||||
            update_all "vm"
 | 
			
		||||
            last_update_lxc_time=$current_time
 | 
			
		||||
            last_update_vm_time=$current_time
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    $changes_detected || echo "No changes detected in system status"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Initialize time variables
 | 
			
		||||
declare -g last_lxc_status="" last_vm_status="" last_fw_status=""
 | 
			
		||||
declare -g last_lxc_check_time=0 last_vm_check_time=0 last_fw_check_time=0
 | 
			
		||||
declare -g last_update_lxc_time=0 last_update_vm_time=0
 | 
			
		||||
 | 
			
		||||
# Main loop
 | 
			
		||||
main() {
 | 
			
		||||
    while true; do
 | 
			
		||||
        check
 | 
			
		||||
        sleep "${LOOP_INTERVAL:-$DEFAULT_CHECK_INTERVAL}"
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main
 | 
			
		||||
EOF
 | 
			
		||||
  chmod +x /opt/iptag/iptag
 | 
			
		||||
 | 
			
		||||
  # Update service file
 | 
			
		||||
  cat <<EOF >/lib/systemd/system/iptag.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=IP-Tag service
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
ExecStart=/opt/iptag/iptag
 | 
			
		||||
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"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Main installation process
 | 
			
		||||
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."
 | 
			
		||||
      ;;
 | 
			
		||||
    esac
 | 
			
		||||
  done
 | 
			
		||||
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."
 | 
			
		||||
    ;;
 | 
			
		||||
  esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
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..."
 | 
			
		||||
  sleep 2
 | 
			
		||||
  exit
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
FILE_PATH="/usr/local/bin/iptag"
 | 
			
		||||
if [[ -f "$FILE_PATH" ]]; then
 | 
			
		||||
  msg_info "The file already exists: '$FILE_PATH'. Skipping installation."
 | 
			
		||||
  exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
apt-get update &>/dev/null
 | 
			
		||||
apt-get install -y ipcalc net-tools &>/dev/null
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up IP-Tag Scripts"
 | 
			
		||||
mkdir -p /opt/iptag
 | 
			
		||||
msg_ok "Setup IP-Tag Scripts"
 | 
			
		||||
 | 
			
		||||
# Migrate config if needed
 | 
			
		||||
migrate_config
 | 
			
		||||
 | 
			
		||||
msg_info "Setup Default Config"
 | 
			
		||||
if [[ ! -f /opt/iptag/iptag.conf ]]; then
 | 
			
		||||
  cat <<EOF >/opt/iptag/iptag.conf
 | 
			
		||||
# Configuration file for LXC IP tagging
 | 
			
		||||
 | 
			
		||||
# List of allowed CIDRs
 | 
			
		||||
CIDR_LIST=(
 | 
			
		||||
  192.168.0.0/16
 | 
			
		||||
  172.16.0.0/12
 | 
			
		||||
  10.0.0.0/8
 | 
			
		||||
  100.64.0.0/10
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Tag format options:
 | 
			
		||||
# - "full": full IP address (e.g., 192.168.0.100)
 | 
			
		||||
# - "last_octet": only the last octet (e.g., 100)
 | 
			
		||||
# - "last_two_octets": last two octets (e.g., 0.100)
 | 
			
		||||
TAG_FORMAT="full"
 | 
			
		||||
 | 
			
		||||
# Interval settings (in seconds)
 | 
			
		||||
LOOP_INTERVAL=60
 | 
			
		||||
VM_STATUS_CHECK_INTERVAL=60
 | 
			
		||||
FW_NET_INTERFACE_CHECK_INTERVAL=60
 | 
			
		||||
LXC_STATUS_CHECK_INTERVAL=60
 | 
			
		||||
FORCE_UPDATE_INTERVAL=1800
 | 
			
		||||
EOF
 | 
			
		||||
  msg_ok "Setup default config"
 | 
			
		||||
else
 | 
			
		||||
  msg_ok "Default config already exists"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
msg_info "Setup Main Function"
 | 
			
		||||
if [[ ! -f /opt/iptag/iptag ]]; then
 | 
			
		||||
  cat <<'EOF' >/opt/iptag/iptag
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
# =============== CONFIGURATION =============== #
 | 
			
		||||
CONFIG_FILE="/opt/iptag/iptag.conf"
 | 
			
		||||
 | 
			
		||||
# Load the configuration file if it exists
 | 
			
		||||
if [ -f "$CONFIG_FILE" ]; then
 | 
			
		||||
  # 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))"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if IP is in CIDR
 | 
			
		||||
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
 | 
			
		||||
      [[ "$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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Format IP address according to the configuration
 | 
			
		||||
format_ip_tag() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  local format="${TAG_FORMAT:-full}"
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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}"
 | 
			
		||||
    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
 | 
			
		||||
  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
 | 
			
		||||
    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
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  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"
 | 
			
		||||
 | 
			
		||||
  # 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}")
 | 
			
		||||
    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
 | 
			
		||||
        local formatted_ip=$(format_ip_tag "$ip")
 | 
			
		||||
        next_tags+=("${formatted_ip}")
 | 
			
		||||
        added_ips+=("${formatted_ip}")
 | 
			
		||||
      else
 | 
			
		||||
        skipped_ips+=("${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
 | 
			
		||||
 | 
			
		||||
  # 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 ]] \
 | 
			
		||||
    && [[ "${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}
 | 
			
		||||
    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}
 | 
			
		||||
    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}
 | 
			
		||||
    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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
 | 
			
		||||
# main: Set the IP tags for all LXC containers and VMs
 | 
			
		||||
main() {
 | 
			
		||||
  while true; do
 | 
			
		||||
    check
 | 
			
		||||
    sleep "${LOOP_INTERVAL}"
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main
 | 
			
		||||
EOF
 | 
			
		||||
  msg_ok "Setup Main Function"
 | 
			
		||||
else
 | 
			
		||||
  msg_ok "Main Function already exists"
 | 
			
		||||
fi
 | 
			
		||||
chmod +x /opt/iptag/iptag
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
if [[ ! -f /lib/systemd/system/iptag.service ]]; then
 | 
			
		||||
  cat <<EOF >/lib/systemd/system/iptag.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=IP-Tag service
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
ExecStart=/opt/iptag/iptag
 | 
			
		||||
Restart=always
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
  msg_ok "Created Service"
 | 
			
		||||
else
 | 
			
		||||
  msg_ok "Service already exists."
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
msg_ok "Setup IP-Tag Scripts"
 | 
			
		||||
 | 
			
		||||
msg_info "Starting Service"
 | 
			
		||||
systemctl daemon-reload &>/dev/null
 | 
			
		||||
systemctl enable -q --now iptag.service &>/dev/null
 | 
			
		||||
msg_ok "Started Service"
 | 
			
		||||
SPINNER_PID=""
 | 
			
		||||
echo -e "\n${APP} installation completed successfully! ${CL}\n"
 | 
			
		||||
@@ -133,7 +133,7 @@ function select_storage() {
 | 
			
		||||
    local STORAGE
 | 
			
		||||
    while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
      STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
        "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\n\n" \
 | 
			
		||||
        "Which storage pool would you like to use for the ${CONTENT_LABEL,,}?\n\n" \
 | 
			
		||||
        16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
        "${MENU[@]}" 3>&1 1>&2 2>&3) || die "Menu aborted."
 | 
			
		||||
    done
 | 
			
		||||
 
 | 
			
		||||
@@ -154,7 +154,7 @@ function select_storage() {
 | 
			
		||||
    local STORAGE
 | 
			
		||||
    while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
      STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
        "Which storage pool you would like to use for the ${CONTENT_LABEL,,}?\n\n" \
 | 
			
		||||
        "Which storage pool would you like to use for the ${CONTENT_LABEL,,}?\n\n" \
 | 
			
		||||
        16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
        "${MENU[@]}" 3>&1 1>&2 2>&3) || die "Menu aborted."
 | 
			
		||||
    done
 | 
			
		||||
 
 | 
			
		||||
@@ -413,7 +413,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -414,7 +414,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -377,7 +377,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -417,7 +417,7 @@ else
 | 
			
		||||
    if [ -n "$SPINNER_PID" ] && ps -p $SPINNER_PID >/dev/null; then kill $SPINNER_PID >/dev/null; fi
 | 
			
		||||
    printf "\e[?25h"
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -241,7 +241,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for the Mikrotik RouterOS CHR VM?\n\n" \
 | 
			
		||||
      "Which storage pool would you like to use for the Mikrotik RouterOS CHR VM?\n\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -378,7 +378,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -438,7 +438,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for the OpenWrt VM?\n\n" \
 | 
			
		||||
      "Which storage pool would you like to use for the OpenWrt VM?\n\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -516,7 +516,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -378,7 +378,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -285,7 +285,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for the HAOS VM?\n\n" \
 | 
			
		||||
      "Which storage pool would you like to use for the HAOS VM?\n\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -412,7 +412,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -412,7 +412,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
@@ -412,7 +412,7 @@ elif [ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]; then
 | 
			
		||||
else
 | 
			
		||||
  while [ -z "${STORAGE:+x}" ]; do
 | 
			
		||||
    STORAGE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Storage Pools" --radiolist \
 | 
			
		||||
      "Which storage pool you would like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      "Which storage pool would you like to use for ${HN}?\nTo make a selection, use the Spacebar.\n" \
 | 
			
		||||
      16 $(($MSG_MAX_LENGTH + 23)) 6 \
 | 
			
		||||
      "${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
  done
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user