mirror of
				https://github.com/community-scripts/ProxmoxVE.git
				synced 2025-11-04 02:12:49 +00:00 
			
		
		
		
	Compare commits
	
		
			100 Commits
		
	
	
		
			2025-06-09
			...
			2025-06-17
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					654508eb94 | ||
| 
						 | 
					acfb9d6ea1 | ||
| 
						 | 
					0d56db2d3d | ||
| 
						 | 
					4a1ae51446 | ||
| 
						 | 
					6520b7f4d4 | ||
| 
						 | 
					48da94f77a | ||
| 
						 | 
					2ea372f034 | ||
| 
						 | 
					5773459a39 | ||
| 
						 | 
					40f083ea40 | ||
| 
						 | 
					219a7853e1 | ||
| 
						 | 
					6d1d903345 | ||
| 
						 | 
					ef9ca48477 | ||
| 
						 | 
					8ac24981a6 | ||
| 
						 | 
					7e046d830d | ||
| 
						 | 
					1691fafcc1 | ||
| 
						 | 
					4400cd2b97 | ||
| 
						 | 
					795fe72768 | ||
| 
						 | 
					6d7d15ce46 | ||
| 
						 | 
					a648b9abc4 | ||
| 
						 | 
					4057fadfe0 | ||
| 
						 | 
					9b700195e4 | ||
| 
						 | 
					906a0a0fbc | ||
| 
						 | 
					8df55a03f4 | ||
| 
						 | 
					8241ed932d | ||
| 
						 | 
					0b3c645ffb | ||
| 
						 | 
					0c17402efc | ||
| 
						 | 
					ccad7a2cd8 | ||
| 
						 | 
					15772d8802 | ||
| 
						 | 
					c7e0faa33b | ||
| 
						 | 
					13b1c684ee | ||
| 
						 | 
					5e649d7cb1 | ||
| 
						 | 
					ec8a8b1908 | ||
| 
						 | 
					d850dde4ef | ||
| 
						 | 
					fb4075ac12 | ||
| 
						 | 
					8576463522 | ||
| 
						 | 
					2a4353fa13 | ||
| 
						 | 
					d21cbf1d40 | ||
| 
						 | 
					e97c96d0bb | ||
| 
						 | 
					04dab68e17 | ||
| 
						 | 
					b001687f5c | ||
| 
						 | 
					9f26e25126 | ||
| 
						 | 
					5671d8e957 | ||
| 
						 | 
					0bf641f02c | ||
| 
						 | 
					7fc39a442b | ||
| 
						 | 
					6e1ee7d16e | ||
| 
						 | 
					5ee48aba1e | ||
| 
						 | 
					e6c21811bb | ||
| 
						 | 
					142fea21bd | ||
| 
						 | 
					df43101b4e | ||
| 
						 | 
					3044a774c2 | ||
| 
						 | 
					65e4c027b8 | ||
| 
						 | 
					dabfb57173 | ||
| 
						 | 
					63dfc2bd7b | ||
| 
						 | 
					89399ef421 | ||
| 
						 | 
					d9474c3dd6 | ||
| 
						 | 
					f5a5e4854c | ||
| 
						 | 
					632e823749 | ||
| 
						 | 
					a128f3c43d | ||
| 
						 | 
					9c90699ca2 | ||
| 
						 | 
					f6f6ca6bac | ||
| 
						 | 
					b6d0b1ae6a | ||
| 
						 | 
					93906db2d1 | ||
| 
						 | 
					4ab71ccf00 | ||
| 
						 | 
					e058badee6 | ||
| 
						 | 
					74c6df5aa6 | ||
| 
						 | 
					c2484b7c60 | ||
| 
						 | 
					b064127323 | ||
| 
						 | 
					138f90f09c | ||
| 
						 | 
					84469e2b5b | ||
| 
						 | 
					a164d259e0 | ||
| 
						 | 
					34aa360920 | ||
| 
						 | 
					f0dde5a42d | ||
| 
						 | 
					e0ccc1a0af | ||
| 
						 | 
					4fa7483d8b | ||
| 
						 | 
					cd835c6791 | ||
| 
						 | 
					abf233c94f | ||
| 
						 | 
					edd4fb3cc2 | ||
| 
						 | 
					d97620a390 | ||
| 
						 | 
					c2c5159a2d | ||
| 
						 | 
					46d9f85f5e | ||
| 
						 | 
					ba7ec5aa68 | ||
| 
						 | 
					dd4c556959 | ||
| 
						 | 
					0e63437154 | ||
| 
						 | 
					0769320146 | ||
| 
						 | 
					d6da26c640 | ||
| 
						 | 
					d9facc0e62 | ||
| 
						 | 
					31e0b5fae3 | ||
| 
						 | 
					b0bd2f4804 | ||
| 
						 | 
					3aefe199f7 | ||
| 
						 | 
					677008c779 | ||
| 
						 | 
					b8ba409e5c | ||
| 
						 | 
					7cf8300b47 | ||
| 
						 | 
					77fb5ea516 | ||
| 
						 | 
					e92dfe1b2b | ||
| 
						 | 
					61bfa16645 | ||
| 
						 | 
					84c295a10b | ||
| 
						 | 
					ed834bf424 | ||
| 
						 | 
					b1f8992933 | ||
| 
						 | 
					201f7c4651 | ||
| 
						 | 
					2574e41ee8 | 
							
								
								
									
										123
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -14,8 +14,131 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
 | 
			
		||||
All LXC instances created using this repository come pre-installed with Midnight Commander, which is a command-line tool (`mc`) that offers a user-friendly file and directory management interface for the terminal environment.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## 2025-06-18
 | 
			
		||||
 | 
			
		||||
## 2025-06-17
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - gitea-mirror: increase build ressources  [@CrazyWolf13](https://github.com/CrazyWolf13) ([#5235](https://github.com/community-scripts/ProxmoxVE/pull/5235))
 | 
			
		||||
    - Immich: ensure in proper working dir when updating [@vhsdream](https://github.com/vhsdream) ([#5227](https://github.com/community-scripts/ProxmoxVE/pull/5227))
 | 
			
		||||
    - Update IP-Tag [@DesertGamer](https://github.com/DesertGamer) ([#5226](https://github.com/community-scripts/ProxmoxVE/pull/5226))
 | 
			
		||||
    - trilium: fix update function after db changes folder [@tjcomserv](https://github.com/tjcomserv) ([#5207](https://github.com/community-scripts/ProxmoxVE/pull/5207))
 | 
			
		||||
 | 
			
		||||
  - #### ✨ New Features
 | 
			
		||||
 | 
			
		||||
    - LibreTranslate: Add .env for easier configuration [@tremor021](https://github.com/tremor021) ([#5216](https://github.com/community-scripts/ProxmoxVE/pull/5216))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - #### 📝 Script Information
 | 
			
		||||
 | 
			
		||||
    - IPTag: Better explanation [@MickLesk](https://github.com/MickLesk) ([#5213](https://github.com/community-scripts/ProxmoxVE/pull/5213))
 | 
			
		||||
 | 
			
		||||
## 2025-06-16
 | 
			
		||||
 | 
			
		||||
### 🆕 New Scripts
 | 
			
		||||
 | 
			
		||||
  - Intel NIC offload Fix by @rcastley [@MickLesk](https://github.com/MickLesk) ([#5155](https://github.com/community-scripts/ProxmoxVE/pull/5155))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - [core] Move install_php() from VED to main [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#5182](https://github.com/community-scripts/ProxmoxVE/pull/5182))
 | 
			
		||||
- Firefly: Add Data Importer to LXC [@tremor021](https://github.com/tremor021) ([#5159](https://github.com/community-scripts/ProxmoxVE/pull/5159))
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - Wastebin: Fix missing dependencies [@tremor021](https://github.com/tremor021) ([#5185](https://github.com/community-scripts/ProxmoxVE/pull/5185))
 | 
			
		||||
    - Kasm: Storing Creds Fix [@omiinaya](https://github.com/omiinaya) ([#5162](https://github.com/community-scripts/ProxmoxVE/pull/5162))
 | 
			
		||||
 | 
			
		||||
  - #### ✨ New Features
 | 
			
		||||
 | 
			
		||||
    - add optional Cloud-init support to Debian VM script  [@koendiender](https://github.com/koendiender) ([#5137](https://github.com/community-scripts/ProxmoxVE/pull/5137))
 | 
			
		||||
 | 
			
		||||
  - #### 🔧 Refactor
 | 
			
		||||
 | 
			
		||||
    - Refactor: 2FAuth [@tremor021](https://github.com/tremor021) ([#5184](https://github.com/community-scripts/ProxmoxVE/pull/5184))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - Refactor layout and component styles for improved responsiveness [@BramSuurdje](https://github.com/BramSuurdje) ([#5195](https://github.com/community-scripts/ProxmoxVE/pull/5195))
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - Refactor ScriptItem and ConfigFile components to conditionally render config file location. Update ConfigFile to accept configPath prop instead of item. [@BramSuurdje](https://github.com/BramSuurdje) ([#5197](https://github.com/community-scripts/ProxmoxVE/pull/5197))
 | 
			
		||||
    - Update default image asset in the public directory and update api route to only search for files that end with .json [@BramSuurdje](https://github.com/BramSuurdje) ([#5179](https://github.com/community-scripts/ProxmoxVE/pull/5179))
 | 
			
		||||
 | 
			
		||||
  - #### ✨ New Features
 | 
			
		||||
 | 
			
		||||
    - Update default image asset in the public directory [@BramSuurdje](https://github.com/BramSuurdje) ([#5189](https://github.com/community-scripts/ProxmoxVE/pull/5189))
 | 
			
		||||
 | 
			
		||||
## 2025-06-15
 | 
			
		||||
 | 
			
		||||
### 🆕 New Scripts
 | 
			
		||||
 | 
			
		||||
  - LibreTranslate ([#5154](https://github.com/community-scripts/ProxmoxVE/pull/5154))
 | 
			
		||||
 | 
			
		||||
## 2025-06-14
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - [core] Update install_mariadb func [@tremor021](https://github.com/tremor021) ([#5138](https://github.com/community-scripts/ProxmoxVE/pull/5138))
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - flowiseai: set NodeJS to Version 20 [@MickLesk](https://github.com/MickLesk) ([#5130](https://github.com/community-scripts/ProxmoxVE/pull/5130))
 | 
			
		||||
    - Update dolibarr-install.sh - Get largest version number [@tjcomserv](https://github.com/tjcomserv) ([#5127](https://github.com/community-scripts/ProxmoxVE/pull/5127))
 | 
			
		||||
 | 
			
		||||
## 2025-06-13
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - Zigbee2MQTT: Fix missing directory [@tremor021](https://github.com/tremor021) ([#5120](https://github.com/community-scripts/ProxmoxVE/pull/5120))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - #### 📝 Script Information
 | 
			
		||||
 | 
			
		||||
    - Umbrel OS: Fix bad disk size shown on website [@tremor021](https://github.com/tremor021) ([#5125](https://github.com/community-scripts/ProxmoxVE/pull/5125))
 | 
			
		||||
 | 
			
		||||
## 2025-06-12
 | 
			
		||||
 | 
			
		||||
### 🆕 New Scripts
 | 
			
		||||
 | 
			
		||||
  - Manage my Damn Life ([#5100](https://github.com/community-scripts/ProxmoxVE/pull/5100))
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - Kasm: Increase Ressources & Hint for Fuse / Swap [@MickLesk](https://github.com/MickLesk) ([#5112](https://github.com/community-scripts/ProxmoxVE/pull/5112))
 | 
			
		||||
 | 
			
		||||
## 2025-06-11
 | 
			
		||||
 | 
			
		||||
## 2025-06-10
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 | 
			
		||||
  - #### 🐞 Bug Fixes
 | 
			
		||||
 | 
			
		||||
    - Element Synapse: switched from development to production mode and fixed update [@Frankmaaan](https://github.com/Frankmaaan) ([#5066](https://github.com/community-scripts/ProxmoxVE/pull/5066))
 | 
			
		||||
    - Tinyauth: Fix creation of service file [@tremor021](https://github.com/tremor021) ([#5090](https://github.com/community-scripts/ProxmoxVE/pull/5090))
 | 
			
		||||
    - Dolibarr: Fix typo in SQL command [@tremor021](https://github.com/tremor021) ([#5091](https://github.com/community-scripts/ProxmoxVE/pull/5091))
 | 
			
		||||
 | 
			
		||||
### 🧰 Maintenance
 | 
			
		||||
 | 
			
		||||
  - #### 📡 API
 | 
			
		||||
 | 
			
		||||
    - [core] Prevent API form sending Data when disabled [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#5080](https://github.com/community-scripts/ProxmoxVE/pull/5080))
 | 
			
		||||
 | 
			
		||||
### 🌐 Website
 | 
			
		||||
 | 
			
		||||
  - #### 📝 Script Information
 | 
			
		||||
 | 
			
		||||
    - Immich: Update JSON [@vhsdream](https://github.com/vhsdream) ([#5085](https://github.com/community-scripts/ProxmoxVE/pull/5085))
 | 
			
		||||
 | 
			
		||||
## 2025-06-09
 | 
			
		||||
 | 
			
		||||
### 🚀 Updated Scripts
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										25
									
								
								ct/2fauth.sh
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								ct/2fauth.sh
									
									
									
									
									
								
							@@ -24,21 +24,16 @@ function update_script() {
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
 | 
			
		||||
  # Check if installation is present | -f for file, -d for folder
 | 
			
		||||
  if [[ ! -d "/opt/2fauth" ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Crawling the new version and checking whether an update is required
 | 
			
		||||
  RELEASE=$(curl -fsSL https://api.github.com/repos/Bubka/2FAuth/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
  if [[ "${RELEASE}" != "$(cat /opt/2fauth_version.txt)" ]] || [[ ! -f /opt/2fauth_version.txt ]]; then
 | 
			
		||||
    msg_info "Updating $APP to ${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
    $STD apt-get -y upgrade
 | 
			
		||||
 | 
			
		||||
    # Creating Backup
 | 
			
		||||
    msg_info "Creating Backup"
 | 
			
		||||
    mv "/opt/2fauth" "/opt/2fauth-backup"
 | 
			
		||||
    if ! dpkg -l | grep -q 'php8.3'; then
 | 
			
		||||
@@ -46,37 +41,24 @@ function update_script() {
 | 
			
		||||
    fi
 | 
			
		||||
    msg_ok "Backup Created"
 | 
			
		||||
 | 
			
		||||
    # Upgrade PHP
 | 
			
		||||
    if ! dpkg -l | grep -q 'php8.3'; then
 | 
			
		||||
      $STD apt-get install -y \
 | 
			
		||||
        lsb-release \
 | 
			
		||||
        gpg
 | 
			
		||||
      curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/deb.sury.org-php.gpg
 | 
			
		||||
      echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" >/etc/apt/sources.list.d/php.list
 | 
			
		||||
      $STD apt-get update
 | 
			
		||||
      $STD apt-get install -y php8.3-{bcmath,common,ctype,curl,fileinfo,fpm,gd,mbstring,mysql,xml,cli,intl}
 | 
			
		||||
        gnupg2
 | 
			
		||||
      PHP_VERSION="8.3" PHP_MODULE="common,ctype,fileinfo,fpm,mysql,cli" install_php
 | 
			
		||||
      sed -i 's/php8.2/php8.3/g' /etc/nginx/conf.d/2fauth.conf
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    # Execute Update
 | 
			
		||||
    curl -fsSL -o "${RELEASE}.zip" "https://github.com/Bubka/2FAuth/archive/refs/tags/${RELEASE}.zip"
 | 
			
		||||
    $STD unzip "${RELEASE}.zip"
 | 
			
		||||
    mv "2FAuth-${RELEASE//v/}/" "/opt/2fauth"
 | 
			
		||||
    fetch_and_deploy_gh_release "Bubka/2FAuth"
 | 
			
		||||
    mv "/opt/2fauth-backup/.env" "/opt/2fauth/.env"
 | 
			
		||||
    mv "/opt/2fauth-backup/storage" "/opt/2fauth/storage"
 | 
			
		||||
    cd "/opt/2fauth" || return
 | 
			
		||||
 | 
			
		||||
    chown -R www-data: "/opt/2fauth"
 | 
			
		||||
    chmod -R 755 "/opt/2fauth"
 | 
			
		||||
 | 
			
		||||
    export COMPOSER_ALLOW_SUPERUSER=1
 | 
			
		||||
    $STD composer install --no-dev --prefer-source
 | 
			
		||||
 | 
			
		||||
    php artisan 2fauth:install
 | 
			
		||||
 | 
			
		||||
    $STD systemctl restart nginx
 | 
			
		||||
 | 
			
		||||
    # Cleaning up
 | 
			
		||||
    msg_info "Cleaning Up"
 | 
			
		||||
    rm -rf "v${RELEASE}.zip"
 | 
			
		||||
    if dpkg -l | grep -q 'php8.2'; then
 | 
			
		||||
@@ -86,7 +68,6 @@ function update_script() {
 | 
			
		||||
    $STD apt-get -y autoclean
 | 
			
		||||
    msg_ok "Cleanup Completed"
 | 
			
		||||
 | 
			
		||||
    # Last Action
 | 
			
		||||
    echo "${RELEASE}" >/opt/2fauth_version.txt
 | 
			
		||||
    msg_ok "Updated $APP to ${RELEASE}"
 | 
			
		||||
  else
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ function update_script() {
 | 
			
		||||
  $STD apt-get -y upgrade
 | 
			
		||||
  msg_ok "Updated $APP LXC"
 | 
			
		||||
 | 
			
		||||
  if [[ -f /systemd/system/synapse-admin.service ]]; then
 | 
			
		||||
  if [[ -f /etc/systemd/system/synapse-admin.service ]]; then
 | 
			
		||||
    msg_info "Updating Synapse-Admin"
 | 
			
		||||
    RELEASE=$(curl -fsSL https://api.github.com/repos/etkecc/synapse-admin/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
 | 
			
		||||
@@ -58,7 +58,16 @@ function update_script() {
 | 
			
		||||
      curl -fsSL "https://github.com/etkecc/synapse-admin/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
 | 
			
		||||
      tar xzf "$temp_file" -C /opt/synapse-admin --strip-components=1
 | 
			
		||||
      cd /opt/synapse-admin
 | 
			
		||||
      $STD yarn global add serve
 | 
			
		||||
      $STD yarn install --ignore-engines
 | 
			
		||||
      $STD yarn build
 | 
			
		||||
      mv ./dist ../ && \
 | 
			
		||||
        rm -rf * && \
 | 
			
		||||
        mv ../dist ./
 | 
			
		||||
      if [[ -z $(grep "ExecStart=/usr/local/bin/serve" /etc/systemd/system/synapse-admin.service) ]]; then
 | 
			
		||||
        sed -i 's|^ExecStart=.*|ExecStart=/usr/local/bin/serve -s dist -l 5173|' /etc/systemd/system/synapse-admin.service
 | 
			
		||||
        systemctl reenable synapse-admin
 | 
			
		||||
      fi
 | 
			
		||||
      systemctl start synapse-admin
 | 
			
		||||
      echo "${RELEASE}" >/opt/"${APP}"_version.txt
 | 
			
		||||
      rm -f "$temp_file"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
#!/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: quantumryuu
 | 
			
		||||
# Author: quantumryuu | Co-Author: Slaviša Arežina (tremor021)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://firefly-iii.org/
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,9 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
 | 
			
		||||
 | 
			
		||||
APP="gitea-mirror"
 | 
			
		||||
var_tags="${var_tags:-mirror;gitea}"
 | 
			
		||||
var_cpu="${var_cpu:-1}"
 | 
			
		||||
var_ram="${var_ram:-1024}"
 | 
			
		||||
var_disk="${var_disk:-5}"
 | 
			
		||||
var_cpu="${var_cpu:-2}"
 | 
			
		||||
var_ram="${var_ram:-2048}"
 | 
			
		||||
var_disk="${var_disk:-6}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-12}"
 | 
			
		||||
var_unprivileged="${var_unprivileged:-1}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/libretranslate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/libretranslate
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    __    _ __            ______                      __      __     
 | 
			
		||||
   / /   (_) /_  ________/_  __/________ _____  _____/ /___ _/ /____ 
 | 
			
		||||
  / /   / / __ \/ ___/ _ \/ / / ___/ __ `/ __ \/ ___/ / __ `/ __/ _ \
 | 
			
		||||
 / /___/ / /_/ / /  /  __/ / / /  / /_/ / / / (__  ) / /_/ / /_/  __/
 | 
			
		||||
/_____/_/_.___/_/   \___/_/ /_/   \__,_/_/ /_/____/_/\__,_/\__/\___/ 
 | 
			
		||||
                                                                     
 | 
			
		||||
							
								
								
									
										6
									
								
								ct/headers/managemydamnlife
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ct/headers/managemydamnlife
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    __  ___                                __  ___         ____                           __    _ ____   
 | 
			
		||||
   /  |/  /___ _____  ____ _____ ____     /  |/  /_  __   / __ \____ _____ ___  ____     / /   (_) __/__ 
 | 
			
		||||
  / /|_/ / __ `/ __ \/ __ `/ __ `/ _ \   / /|_/ / / / /  / / / / __ `/ __ `__ \/ __ \   / /   / / /_/ _ \
 | 
			
		||||
 / /  / / /_/ / / / / /_/ / /_/ /  __/  / /  / / /_/ /  / /_/ / /_/ / / / / / / / / /  / /___/ / __/  __/
 | 
			
		||||
/_/  /_/\__,_/_/ /_/\__,_/\__, /\___/  /_/  /_/\__, /  /_____/\__,_/_/ /_/ /_/_/ /_/  /_____/_/_/  \___/ 
 | 
			
		||||
                         /____/               /____/                                                     
 | 
			
		||||
@@ -30,6 +30,7 @@ function update_script() {
 | 
			
		||||
  STAGING_DIR=/opt/staging
 | 
			
		||||
  BASE_DIR=${STAGING_DIR}/base-images
 | 
			
		||||
  SOURCE_DIR=${STAGING_DIR}/image-source
 | 
			
		||||
  cd /root
 | 
			
		||||
  if [[ -f ~/.intel_version ]]; then
 | 
			
		||||
    curl -fsSLO https://raw.githubusercontent.com/immich-app/immich/refs/heads/main/machine-learning/Dockerfile
 | 
			
		||||
    readarray -t INTEL_URLS < <(sed -n "/intel/p" ./Dockerfile | awk '{print $3}')
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
 | 
			
		||||
APP="Kasm"
 | 
			
		||||
var_tags="${var_tags:-os}"
 | 
			
		||||
var_cpu="${var_cpu:-2}"
 | 
			
		||||
var_ram="${var_ram:-4192}"
 | 
			
		||||
var_ram="${var_ram:-8192}"
 | 
			
		||||
var_disk="${var_disk:-30}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-12}"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								ct/libretranslate.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								ct/libretranslate.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
source <(curl -s https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Slaviša Arežina (tremor021)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/LibreTranslate/LibreTranslate
 | 
			
		||||
 | 
			
		||||
APP="LibreTranslate"
 | 
			
		||||
var_tags="${var_tags:-Arr}"
 | 
			
		||||
var_cpu="${var_cpu:-2}"
 | 
			
		||||
var_ram="${var_ram:-2048}"
 | 
			
		||||
var_disk="${var_disk:-20}"
 | 
			
		||||
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 [[ ! -d /opt/libretranslate ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
  RELEASE=$(curl -s https://api.github.com/repos/LibreTranslate/LibreTranslate/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
  if [[ "${RELEASE}" != "$(cat $HOME/.libretranslate)" ]] || [[ ! -f $HOME/.libretranslate ]]; then
 | 
			
		||||
    msg_info "Stopping $APP"
 | 
			
		||||
    systemctl stop libretranslate
 | 
			
		||||
    msg_ok "Stopped $APP"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating $APP to ${RELEASE}"
 | 
			
		||||
    cd /opt/libretranslate
 | 
			
		||||
    source .venv/bin/activate
 | 
			
		||||
    $STD pip install -U libretranslate
 | 
			
		||||
    msg_ok "Updated $APP to ${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting $APP"
 | 
			
		||||
    systemctl start libretranslate
 | 
			
		||||
    msg_ok "Started $APP"
 | 
			
		||||
 | 
			
		||||
    msg_ok "Update Successful"
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at ${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}:5000${CL}"
 | 
			
		||||
							
								
								
									
										78
									
								
								ct/managemydamnlife.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								ct/managemydamnlife.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
#!/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://github.com/intri-in/manage-my-damn-life-nextjs
 | 
			
		||||
 | 
			
		||||
APP="Manage My Damn Life"
 | 
			
		||||
var_tags="${var_tags:-calendar;tasks}"
 | 
			
		||||
var_cpu="${var_cpu:-2}"
 | 
			
		||||
var_ram="${var_ram:-2048}"
 | 
			
		||||
var_disk="${var_disk:-6}"
 | 
			
		||||
var_os="${var_os:-debian}"
 | 
			
		||||
var_version="${var_version:-12}"
 | 
			
		||||
var_unprivileged="${var_unprivileged:-1}"
 | 
			
		||||
 | 
			
		||||
header_info "$APP"
 | 
			
		||||
variables
 | 
			
		||||
color
 | 
			
		||||
catch_errors
 | 
			
		||||
 | 
			
		||||
function update_script() {
 | 
			
		||||
  header_info
 | 
			
		||||
  check_container_storage
 | 
			
		||||
  check_container_resources
 | 
			
		||||
 | 
			
		||||
  if [[ ! -d /opt/mmdl ]]; then
 | 
			
		||||
    msg_error "No ${APP} Installation Found!"
 | 
			
		||||
    exit
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  RELEASE=$(curl -fsSL https://api.github.com/repos/intri-in/manage-my-damn-life-nextjs/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
  if [[ "${RELEASE}" != "$(cat /opt/mmdl_version.txt)" ]] || [[ ! -f /opt/mmdl_version.txt ]]; then
 | 
			
		||||
    msg_info "Stopping $APP"
 | 
			
		||||
    systemctl stop mmdl
 | 
			
		||||
    msg_ok "Stopped $APP"
 | 
			
		||||
 | 
			
		||||
    msg_info "Creating Backup"
 | 
			
		||||
    cp /opt/mmdl/.env /opt/mmdl.env
 | 
			
		||||
    msg_ok "Backup Created"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating $APP to v${RELEASE}"
 | 
			
		||||
    curl -fsSLO "https://github.com/intri-in/manage-my-damn-life-nextjs/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
    rm -r /opt/mmdl
 | 
			
		||||
    unzip -q v"$RELEASE".zip
 | 
			
		||||
    mv manage-my-damn-life-nextjs-"$RELEASE"/ /opt/mmdl
 | 
			
		||||
    mv /opt/mmdl.env /opt/mmdl/.env
 | 
			
		||||
    cd /opt/mmdl
 | 
			
		||||
    $STD npm install
 | 
			
		||||
    $STD npm run migrate
 | 
			
		||||
    $STD npm run build
 | 
			
		||||
    msg_ok "Updated $APP to v${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting $APP"
 | 
			
		||||
    systemctl start mmdl
 | 
			
		||||
    msg_ok "Started $APP"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning Up"
 | 
			
		||||
    rm -f ~/v"$RELEASE".zip
 | 
			
		||||
    msg_ok "Cleanup Completed"
 | 
			
		||||
 | 
			
		||||
    # Last Action
 | 
			
		||||
    echo "$RELEASE" >/opt/mmdl_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}"
 | 
			
		||||
@@ -29,38 +29,55 @@ function update_script() {
 | 
			
		||||
  fi
 | 
			
		||||
  if [[ ! -f /opt/${APP}_version.txt ]]; then touch /opt/${APP}_version.txt; fi
 | 
			
		||||
  RELEASE=$(curl -fsSL https://api.github.com/repos/TriliumNext/Notes/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
  if [[ "v${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
 | 
			
		||||
    msg_info "Stopping ${APP}"
 | 
			
		||||
    systemctl stop trilium
 | 
			
		||||
    sleep 1
 | 
			
		||||
    msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Updating to ${RELEASE}"
 | 
			
		||||
    mkdir -p /opt/trilium_backup
 | 
			
		||||
    mv /opt/trilium/db /opt/trilium_backup/
 | 
			
		||||
    rm -rf /opt/trilium
 | 
			
		||||
    cd /tmp
 | 
			
		||||
    curl -fsSL "https://github.com/TriliumNext/Notes/releases/download/v${RELEASE}/TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz" -o $(basename "https://github.com/TriliumNext/Notes/releases/download/v${RELEASE}/TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz")
 | 
			
		||||
    tar -xf TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz
 | 
			
		||||
    mv TriliumNextNotes-Server-$RELEASE-linux-x64 /opt/trilium
 | 
			
		||||
    cp -r /opt/trilium_backup/db /opt/trilium/
 | 
			
		||||
    echo "v${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
    msg_ok "Updated to ${RELEASE}"
 | 
			
		||||
 | 
			
		||||
    msg_info "Cleaning up"
 | 
			
		||||
    rm -rf /tmp/TriliumNextNotes-Server-${RELEASE}-linux-x64.tar.xz
 | 
			
		||||
    rm -rf /opt/trilium_backup
 | 
			
		||||
    msg_ok "Cleaned"
 | 
			
		||||
 | 
			
		||||
    msg_info "Starting ${APP}"
 | 
			
		||||
    systemctl start trilium
 | 
			
		||||
    sleep 1
 | 
			
		||||
    msg_ok "Started ${APP}"
 | 
			
		||||
    msg_ok "Updated Successfully"
 | 
			
		||||
 if [[ "v${RELEASE}" != "$(cat /opt/${APP}_version.txt 2>/dev/null)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
 | 
			
		||||
 
 | 
			
		||||
  if [[ -d /opt/trilium/db ]]; then
 | 
			
		||||
    DB_PATH="/opt/trilium/db"
 | 
			
		||||
    DB_RESTORE_PATH="/opt/trilium/db"
 | 
			
		||||
  elif [[ -d /opt/trilium/assets/db ]]; then
 | 
			
		||||
    DB_PATH="/opt/trilium/assets/db"
 | 
			
		||||
    DB_RESTORE_PATH="/opt/trilium/assets/db"
 | 
			
		||||
  else
 | 
			
		||||
    msg_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
   msg_error "Database not found in either /opt/trilium/db or /opt/trilium/assets/db"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
  exit
 | 
			
		||||
 | 
			
		||||
  msg_info "Stopping ${APP}"
 | 
			
		||||
  systemctl stop trilium
 | 
			
		||||
  sleep 1
 | 
			
		||||
  msg_ok "Stopped ${APP}"
 | 
			
		||||
 | 
			
		||||
  msg_info "Updating to ${RELEASE}"
 | 
			
		||||
  mkdir -p /opt/trilium_backup
 | 
			
		||||
  cp -r "${DB_PATH}" /opt/trilium_backup/
 | 
			
		||||
  rm -rf /opt/trilium
 | 
			
		||||
  cd /tmp
 | 
			
		||||
  curl -fsSL "https://github.com/TriliumNext/Notes/releases/download/v${RELEASE}/TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz" -o "TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz"
 | 
			
		||||
  tar -xf "TriliumNextNotes-Server-v${RELEASE}-linux-x64.tar.xz"
 | 
			
		||||
  mv "TriliumNextNotes-Server-${RELEASE}-linux-x64" /opt/trilium
 | 
			
		||||
 | 
			
		||||
  # Restore database
 | 
			
		||||
  mkdir -p "$(dirname "${DB_RESTORE_PATH}")"
 | 
			
		||||
  cp -r /opt/trilium_backup/$(basename "${DB_PATH}") "${DB_RESTORE_PATH}"
 | 
			
		||||
 | 
			
		||||
  echo "v${RELEASE}" >/opt/${APP}_version.txt
 | 
			
		||||
  msg_ok "Updated to ${RELEASE}"
 | 
			
		||||
 | 
			
		||||
  msg_info "Cleaning up"
 | 
			
		||||
  rm -rf "/tmp/TriliumNextNotes-Server-${RELEASE}-linux-x64.tar.xz"
 | 
			
		||||
  rm -rf /opt/trilium_backup
 | 
			
		||||
  msg_ok "Cleaned"
 | 
			
		||||
 | 
			
		||||
  msg_info "Starting ${APP}"
 | 
			
		||||
  systemctl start trilium
 | 
			
		||||
  sleep 1
 | 
			
		||||
  msg_ok "Started ${APP}"
 | 
			
		||||
  msg_ok "Updated Successfully"
 | 
			
		||||
else
 | 
			
		||||
  msg_ok "No update required. ${APP} is already at ${RELEASE}"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
exit
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
start
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 120 KiB  | 
@@ -1,23 +1,23 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Proxmox VE LXC IP-Tag",
 | 
			
		||||
  "slug": "add-lxc-iptag",
 | 
			
		||||
  "name": "Proxmox VE LXC Tag",
 | 
			
		||||
  "slug": "add-iptag",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    1
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2024-12-16",
 | 
			
		||||
  "date_created": "2025-06-16",
 | 
			
		||||
  "type": "pve",
 | 
			
		||||
  "updateable": false,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": null,
 | 
			
		||||
  "documentation": null,
 | 
			
		||||
  "website": null,
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/proxmox.webp",
 | 
			
		||||
  "config_path": "/opt/lxc-iptag/iptag.conf",
 | 
			
		||||
  "description": "This script automatically adds IP address as tags to LXC containers using a Systemd service. The service also updates the tags if a LXC IP address is changed.",
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/svg/proxmox.svg",
 | 
			
		||||
  "config_path": "/opt/iptag/iptag.conf",
 | 
			
		||||
  "description": "This script automatically adds IP address as tags to LXC containers or VM's using a systemd service. The service also updates the tags if a LXC/VM IP address is changed.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "tools/pve/add-lxc-iptag.sh",
 | 
			
		||||
      "script": "tools/pve/add-iptag.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": null,
 | 
			
		||||
        "ram": null,
 | 
			
		||||
@@ -36,6 +36,10 @@
 | 
			
		||||
      "text": "Execute within the Proxmox shell",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Configuration: `nano /opt/iptag/iptag.conf`. iptag.service must be restarted after change.",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "The Proxmox Node must contain ipcalc and net-tools. `apt-get install -y ipcalc net-tools`",
 | 
			
		||||
      "type": "warning"
 | 
			
		||||
@@ -32,6 +32,10 @@
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Data Importer is at `http://<LXC_IP>/dataimporter/`",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Database credentials: `cat ~/firefly.creds`",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
 
 | 
			
		||||
@@ -19,9 +19,9 @@
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/gitea-mirror.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 1,
 | 
			
		||||
        "ram": 1024,
 | 
			
		||||
        "hdd": 5,
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 2048,
 | 
			
		||||
        "hdd": 6,
 | 
			
		||||
        "os": "Debian",
 | 
			
		||||
        "version": "12"
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -33,15 +33,15 @@
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "During installation, HW-accelerated machine-learning (with OpenVINO) is an available option. This also allows for HW-accelerated transcoding, but it must be enabled in Video Transcoding Settings",
 | 
			
		||||
      "text": "During installation, you will be prompted with the option to install Intel OpenVINO for hardware-accelerated machine-learning. If you opt in, increase your LXC RAM after installation, as OpenVINO is memory-intensive",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "If using OpenVINO HW machine-learning, increase RAM because OpenVINO is memory-intensive",
 | 
			
		||||
      "text": "HW-accelerated video transcoding is supported, but must be enabled in Immich Settings",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "To change upload location, edit 'IMMICH_MEDIA_LOCATION' in `/opt/immich/.env`",
 | 
			
		||||
      "text": "To change upload location, edit 'IMMICH_MEDIA_LOCATION' in `/opt/immich/.env`, and create the symlink 'upload' in /opt/immich/app & /opt/immich/app/machine-learning to your new upload location",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
      "script": "ct/kasm.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 4096,
 | 
			
		||||
        "ram": 8192,
 | 
			
		||||
        "hdd": 50,
 | 
			
		||||
        "os": "Debian",
 | 
			
		||||
        "version": "12"
 | 
			
		||||
@@ -36,6 +36,10 @@
 | 
			
		||||
      "text": "WARNING: Installation sources scripts outside of Community Scripts repo. Please check the source before installing.",
 | 
			
		||||
      "type": "warning"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Kasm needs swap (on Proxmox host) and activated FUSE to be installed successfully!",
 | 
			
		||||
      "type": "warning"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Show password: `cat ~/kasm.creds`",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										44
									
								
								frontend/public/json/libretranslate.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								frontend/public/json/libretranslate.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "LibreTranslate",
 | 
			
		||||
  "slug": "libretranslate",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    0
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-06-15",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": 5000,
 | 
			
		||||
  "documentation": "https://github.com/LibreTranslate/LibreTranslate?tab=readme-ov-file#settings--flags",
 | 
			
		||||
  "website": "https://libretranslate.com/",
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/libretranslate.webp",
 | 
			
		||||
  "config_path": "",
 | 
			
		||||
  "description": "Free and Open Source Machine Translation API, entirely self-hosted. Unlike other APIs, it doesn't rely on proprietary providers such as Google or Azure to perform translations. Instead, its translation engine is powered by the open source Argos Translate library.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/libretranslate.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 2048,
 | 
			
		||||
        "hdd": 20,
 | 
			
		||||
        "os": "debian",
 | 
			
		||||
        "version": "12"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "During the installation, application will download language models used for translation. Depending on how fast your internet/host is, this can take 5-10 minutes.",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "text": "At every boot of LXC, application will look for updates for language models installed. This can prolong the startup of the LXC.",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								frontend/public/json/managemydamnlife.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								frontend/public/json/managemydamnlife.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "Manage My Damn Life",
 | 
			
		||||
  "slug": "managemydamnlife",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    0
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-06-12",
 | 
			
		||||
  "type": "ct",
 | 
			
		||||
  "updateable": true,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": 3000,
 | 
			
		||||
  "documentation": "https://manage-my-damn-life-nextjs.readthedocs.io/en/latest/",
 | 
			
		||||
  "config_path": "/opt/mmdl/.env",
 | 
			
		||||
  "website": "https://github.com/intri-in/manage-my-damn-life-nextjs",
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/manage-my-damn-life.webp",
 | 
			
		||||
  "description": "Manage My Damn Life (MMDL) is a self-hosted front end for managing your CalDAV tasks and calendars.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "ct/managemydamnlife.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 2048,
 | 
			
		||||
        "hdd": 6,
 | 
			
		||||
        "os": "Debian",
 | 
			
		||||
        "version": "12"
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": []
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								frontend/public/json/nic-offloading-fix.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								frontend/public/json/nic-offloading-fix.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "NIC Offloading Fix",
 | 
			
		||||
  "slug": "nic-offloading-fix",
 | 
			
		||||
  "categories": [
 | 
			
		||||
    1
 | 
			
		||||
  ],
 | 
			
		||||
  "date_created": "2025-05-25",
 | 
			
		||||
  "type": "pve",
 | 
			
		||||
  "updateable": false,
 | 
			
		||||
  "privileged": false,
 | 
			
		||||
  "interface_port": null,
 | 
			
		||||
  "documentation": null,
 | 
			
		||||
  "config_path": "",
 | 
			
		||||
  "website": null,
 | 
			
		||||
  "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/proxmox.webp",
 | 
			
		||||
  "description": "This script automates the process of disabling network interface card (NIC) offloading features specifically for Intel e1000e network interfaces on Linux systems.",
 | 
			
		||||
  "install_methods": [
 | 
			
		||||
    {
 | 
			
		||||
      "type": "default",
 | 
			
		||||
      "script": "tools/pve/nic-offloading-fix.sh",
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": null,
 | 
			
		||||
        "ram": null,
 | 
			
		||||
        "hdd": null,
 | 
			
		||||
        "os": null,
 | 
			
		||||
        "version": null
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ],
 | 
			
		||||
  "default_credentials": {
 | 
			
		||||
    "username": null,
 | 
			
		||||
    "password": null
 | 
			
		||||
  },
 | 
			
		||||
  "notes": [
 | 
			
		||||
    {
 | 
			
		||||
      "text": "Execute within the Proxmox shell",
 | 
			
		||||
      "type": "info"
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
      "resources": {
 | 
			
		||||
        "cpu": 2,
 | 
			
		||||
        "ram": 4096,
 | 
			
		||||
        "hdd": 20,
 | 
			
		||||
        "hdd": 32,
 | 
			
		||||
        "os": "debian",
 | 
			
		||||
        "version": "12"
 | 
			
		||||
      }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,383 @@
 | 
			
		||||
[
 | 
			
		||||
  {
 | 
			
		||||
    "name": "grafana/grafana",
 | 
			
		||||
    "version": "v11.5.6",
 | 
			
		||||
    "date": "2025-06-17T22:00:40Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jenkinsci/jenkins",
 | 
			
		||||
    "version": "jenkins-2.515",
 | 
			
		||||
    "date": "2025-06-17T19:17:56Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "coder/code-server",
 | 
			
		||||
    "version": "v4.100.3",
 | 
			
		||||
    "date": "2025-06-03T21:06:41Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "HabitRPG/habitica",
 | 
			
		||||
    "version": "v5.36.6",
 | 
			
		||||
    "date": "2025-06-17T18:12:31Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "fallenbagel/jellyseerr",
 | 
			
		||||
    "version": "v2.6.0",
 | 
			
		||||
    "date": "2025-06-09T23:28:38Z"
 | 
			
		||||
    "version": "preview-sort-userlist",
 | 
			
		||||
    "date": "2025-06-17T18:02:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ollama/ollama",
 | 
			
		||||
    "version": "v0.9.2",
 | 
			
		||||
    "date": "2025-06-17T17:51:43Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "msgbyte/tianji",
 | 
			
		||||
    "version": "v1.21.16",
 | 
			
		||||
    "date": "2025-06-17T16:25:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "BookStackApp/BookStack",
 | 
			
		||||
    "version": "v25.05.1",
 | 
			
		||||
    "date": "2025-06-17T14:38:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "element-hq/synapse",
 | 
			
		||||
    "version": "v1.132.0",
 | 
			
		||||
    "date": "2025-06-17T13:49:30Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "cloudflare/cloudflared",
 | 
			
		||||
    "version": "2025.6.1",
 | 
			
		||||
    "date": "2025-06-17T12:45:39Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "sabnzbd/sabnzbd",
 | 
			
		||||
    "version": "4.5.1",
 | 
			
		||||
    "date": "2025-04-11T09:57:47Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "crowdsecurity/crowdsec",
 | 
			
		||||
    "version": "v1.6.9",
 | 
			
		||||
    "date": "2025-06-17T11:54:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "glpi-project/glpi",
 | 
			
		||||
    "version": "10.0.18",
 | 
			
		||||
    "date": "2025-02-12T11:07:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mattermost/mattermost",
 | 
			
		||||
    "version": "v10.9.1",
 | 
			
		||||
    "date": "2025-06-17T07:06:51Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "morpheus65535/bazarr",
 | 
			
		||||
    "version": "v1.5.2",
 | 
			
		||||
    "date": "2025-05-11T16:40:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Jackett/Jackett",
 | 
			
		||||
    "version": "v0.22.2024",
 | 
			
		||||
    "date": "2025-06-17T05:51:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "donaldzou/WGDashboard",
 | 
			
		||||
    "version": "v4.2.4",
 | 
			
		||||
    "date": "2025-06-17T05:37:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "webmin/webmin",
 | 
			
		||||
    "version": "2.402",
 | 
			
		||||
    "date": "2025-06-17T05:20:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "keycloak/keycloak",
 | 
			
		||||
    "version": "26.2.5",
 | 
			
		||||
    "date": "2025-05-28T06:49:43Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "kimai/kimai",
 | 
			
		||||
    "version": "2.36.1",
 | 
			
		||||
    "date": "2025-06-16T19:20:54Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "bunkerity/bunkerweb",
 | 
			
		||||
    "version": "testing",
 | 
			
		||||
    "date": "2025-06-16T18:10:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "goauthentik/authentik",
 | 
			
		||||
    "version": "version/2025.6.2",
 | 
			
		||||
    "date": "2025-06-16T17:54:39Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "runtipi/runtipi",
 | 
			
		||||
    "version": "nightly",
 | 
			
		||||
    "date": "2025-06-16T17:35:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "NodeBB/NodeBB",
 | 
			
		||||
    "version": "v2.8.20",
 | 
			
		||||
    "date": "2025-06-16T17:03:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "emqx/emqx",
 | 
			
		||||
    "version": "e5.9.1-alpha.1",
 | 
			
		||||
    "date": "2025-06-16T15:34:01Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "open-webui/open-webui",
 | 
			
		||||
    "version": "v0.6.15",
 | 
			
		||||
    "date": "2025-06-16T14:34:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "grokability/snipe-it",
 | 
			
		||||
    "version": "v8.1.16",
 | 
			
		||||
    "date": "2025-06-16T13:49:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "clusterzx/paperless-ai",
 | 
			
		||||
    "version": "v3.0.5",
 | 
			
		||||
    "date": "2025-06-16T13:25:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "n8n-io/n8n",
 | 
			
		||||
    "version": "n8n@1.95.3",
 | 
			
		||||
    "date": "2025-06-03T11:09:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Graylog2/graylog2-server",
 | 
			
		||||
    "version": "6.3.0-rc.1",
 | 
			
		||||
    "date": "2025-06-16T11:28:08Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/operating-system",
 | 
			
		||||
    "version": "15.2",
 | 
			
		||||
    "date": "2025-04-14T15:37:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "moghtech/komodo",
 | 
			
		||||
    "version": "v1.18.3",
 | 
			
		||||
    "date": "2025-06-16T07:03:46Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "esphome/esphome",
 | 
			
		||||
    "version": "2025.5.2",
 | 
			
		||||
    "date": "2025-06-03T08:45:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "firefly-iii/firefly-iii",
 | 
			
		||||
    "version": "v6.2.17",
 | 
			
		||||
    "date": "2025-06-11T12:07:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jellyfin/jellyfin",
 | 
			
		||||
    "version": "v10.10.7",
 | 
			
		||||
    "date": "2025-04-05T19:14:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "crafty-controller/crafty-4",
 | 
			
		||||
    "version": "v4.4.11",
 | 
			
		||||
    "date": "2025-06-15T21:41:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TriliumNext/Notes",
 | 
			
		||||
    "version": "v0.95.0",
 | 
			
		||||
    "date": "2025-06-15T21:12:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "karakeep-app/karakeep",
 | 
			
		||||
    "version": "cli/v0.25.0",
 | 
			
		||||
    "date": "2025-06-15T17:48:29Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "tobychui/zoraxy",
 | 
			
		||||
    "version": "v3.1.9",
 | 
			
		||||
    "date": "2025-03-01T02:24:33Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "syncthing/syncthing",
 | 
			
		||||
    "version": "2.0.0-rc.19",
 | 
			
		||||
    "date": "2025-06-02T17:56:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Prowlarr/Prowlarr",
 | 
			
		||||
    "version": "v1.37.0.5076",
 | 
			
		||||
    "date": "2025-06-04T11:04:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Readarr/Readarr",
 | 
			
		||||
    "version": "v2.0.0.4645",
 | 
			
		||||
    "date": "2017-03-07T18:56:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Lidarr/Lidarr",
 | 
			
		||||
    "version": "v2.12.4.4658",
 | 
			
		||||
    "date": "2025-06-09T17:27:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Radarr/Radarr",
 | 
			
		||||
    "version": "v5.26.2.10099",
 | 
			
		||||
    "date": "2025-06-11T20:10:39Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "traccar/traccar",
 | 
			
		||||
    "version": "v6.7.3",
 | 
			
		||||
    "date": "2025-06-15T05:46:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "hyperion-project/hyperion.ng",
 | 
			
		||||
    "version": "2.1.1",
 | 
			
		||||
    "date": "2025-06-14T17:45:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "advplyr/audiobookshelf",
 | 
			
		||||
    "version": "v2.25.1",
 | 
			
		||||
    "date": "2025-06-14T23:32:15Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "nzbgetcom/nzbget",
 | 
			
		||||
    "version": "v25.0",
 | 
			
		||||
    "date": "2025-05-12T09:12:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "theonedev/onedev",
 | 
			
		||||
    "version": "v11.11.0",
 | 
			
		||||
    "date": "2025-06-14T13:23:36Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "semaphoreui/semaphore",
 | 
			
		||||
    "version": "v2.15.0",
 | 
			
		||||
    "date": "2025-06-14T10:48:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "FlareSolverr/FlareSolverr",
 | 
			
		||||
    "version": "v3.3.25",
 | 
			
		||||
    "date": "2025-06-14T02:52:44Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/core",
 | 
			
		||||
    "version": "2025.6.1",
 | 
			
		||||
    "date": "2025-06-13T20:16:18Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "homarr-labs/homarr",
 | 
			
		||||
    "version": "v1.24.0",
 | 
			
		||||
    "date": "2025-06-13T19:15:36Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Luligu/matterbridge",
 | 
			
		||||
    "version": "3.0.6",
 | 
			
		||||
    "date": "2025-06-13T15:02:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "wazuh/wazuh",
 | 
			
		||||
    "version": "coverity-w25-4.13.0",
 | 
			
		||||
    "date": "2025-06-13T13:58:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "FlowiseAI/Flowise",
 | 
			
		||||
    "version": "flowise@3.0.2",
 | 
			
		||||
    "date": "2025-06-12T22:48:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "leiweibau/Pi.Alert",
 | 
			
		||||
    "version": "v2025-06-12",
 | 
			
		||||
    "date": "2025-06-12T20:59:47Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Checkmk/checkmk",
 | 
			
		||||
    "version": "v2.3.0p34",
 | 
			
		||||
    "date": "2025-06-12T12:15:44Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "docker/compose",
 | 
			
		||||
    "version": "v2.37.1",
 | 
			
		||||
    "date": "2025-06-12T09:00:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "redis/redis",
 | 
			
		||||
    "version": "8.2-m01-int2",
 | 
			
		||||
    "date": "2025-06-12T08:52:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "zitadel/zitadel",
 | 
			
		||||
    "version": "v3.3.0",
 | 
			
		||||
    "date": "2025-06-12T06:54:48Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "documenso/documenso",
 | 
			
		||||
    "version": "v1.12.0-rc.4",
 | 
			
		||||
    "date": "2025-06-12T00:27:41Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TandoorRecipes/recipes",
 | 
			
		||||
    "version": "2.0.0-alpha-4",
 | 
			
		||||
    "date": "2025-05-14T05:01:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "MediaBrowser/Emby.Releases",
 | 
			
		||||
    "version": "4.8.11.0",
 | 
			
		||||
    "date": "2025-03-10T06:39:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "dgtlmoon/changedetection.io",
 | 
			
		||||
    "version": "0.50.3",
 | 
			
		||||
    "date": "2025-06-11T15:19:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "autobrr/autobrr",
 | 
			
		||||
    "version": "v1.63.1",
 | 
			
		||||
    "date": "2025-06-11T11:05:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "zabbix/zabbix",
 | 
			
		||||
    "version": "7.2.8rc1",
 | 
			
		||||
    "date": "2025-06-11T06:50:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "openobserve/openobserve",
 | 
			
		||||
    "version": "v0.15.0-rc2",
 | 
			
		||||
    "date": "2025-06-11T04:29:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "node-red/node-red",
 | 
			
		||||
    "version": "4.1.0-beta.1",
 | 
			
		||||
    "date": "2025-06-10T15:47:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "AdguardTeam/AdGuardHome",
 | 
			
		||||
    "version": "v0.107.62",
 | 
			
		||||
    "date": "2025-05-27T12:10:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "OctoPrint/OctoPrint",
 | 
			
		||||
    "version": "1.11.2",
 | 
			
		||||
    "date": "2025-06-10T11:07:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "VictoriaMetrics/VictoriaMetrics",
 | 
			
		||||
    "version": "v1.110.11",
 | 
			
		||||
    "date": "2025-06-10T10:00:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "glanceapp/glance",
 | 
			
		||||
    "version": "v0.8.4",
 | 
			
		||||
    "date": "2025-06-10T07:57:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "go-gitea/gitea",
 | 
			
		||||
    "version": "v1.24.0",
 | 
			
		||||
    "date": "2025-06-10T02:00:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Sonarr/Sonarr",
 | 
			
		||||
    "version": "v4.0.14.2939",
 | 
			
		||||
    "date": "2025-03-17T19:12:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "cross-seed/cross-seed",
 | 
			
		||||
    "version": "v6.12.6",
 | 
			
		||||
    "date": "2025-05-28T00:13:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "tailscale/tailscale",
 | 
			
		||||
@@ -19,16 +394,6 @@
 | 
			
		||||
    "version": "v0.28.3",
 | 
			
		||||
    "date": "2025-06-09T18:11:46Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Lidarr/Lidarr",
 | 
			
		||||
    "version": "v2.12.4.4658",
 | 
			
		||||
    "date": "2025-06-09T17:27:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ollama/ollama",
 | 
			
		||||
    "version": "v0.9.1-ci3",
 | 
			
		||||
    "date": "2025-06-07T16:12:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Brandawg93/PeaNUT",
 | 
			
		||||
    "version": "v5.8.0",
 | 
			
		||||
@@ -39,181 +404,61 @@
 | 
			
		||||
    "version": "v3.3.0",
 | 
			
		||||
    "date": "2025-06-09T15:58:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "NodeBB/NodeBB",
 | 
			
		||||
    "version": "v2.8.19",
 | 
			
		||||
    "date": "2025-06-09T15:32:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "seanmorley15/AdventureLog",
 | 
			
		||||
    "version": "v0.10.0",
 | 
			
		||||
    "date": "2025-06-09T13:37:07Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "crowdsecurity/crowdsec",
 | 
			
		||||
    "version": "v1.6.8",
 | 
			
		||||
    "date": "2025-03-25T13:33:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "VictoriaMetrics/VictoriaMetrics",
 | 
			
		||||
    "version": "pmm-6401-v1.119.0",
 | 
			
		||||
    "date": "2025-06-09T12:26:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "nzbgetcom/nzbget",
 | 
			
		||||
    "version": "v25.0",
 | 
			
		||||
    "date": "2025-05-12T09:12:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Checkmk/checkmk",
 | 
			
		||||
    "version": "v2.4.0p4-rc1",
 | 
			
		||||
    "date": "2025-06-09T09:27:36Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "silverbulletmd/silverbullet",
 | 
			
		||||
    "version": "0.10.4",
 | 
			
		||||
    "date": "2025-02-25T18:13:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "morpheus65535/bazarr",
 | 
			
		||||
    "version": "v1.5.2",
 | 
			
		||||
    "date": "2025-05-11T16:40:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Jackett/Jackett",
 | 
			
		||||
    "version": "v0.22.2002",
 | 
			
		||||
    "date": "2025-06-09T05:54:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "firefly-iii/firefly-iii",
 | 
			
		||||
    "version": "develop-20250609.1",
 | 
			
		||||
    "date": "2025-06-09T03:59:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "neo4j/neo4j",
 | 
			
		||||
    "version": "5.26.8",
 | 
			
		||||
    "date": "2025-06-08T22:50:58Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "karakeep-app/karakeep",
 | 
			
		||||
    "version": "ios/v1.7.0-1",
 | 
			
		||||
    "date": "2025-06-08T22:02:33Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "msgbyte/tianji",
 | 
			
		||||
    "version": "v1.21.11",
 | 
			
		||||
    "date": "2025-06-08T16:49:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Luligu/matterbridge",
 | 
			
		||||
    "version": "3.0.5",
 | 
			
		||||
    "date": "2025-06-08T15:53:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Forceu/Gokapi",
 | 
			
		||||
    "version": "v2.0.1",
 | 
			
		||||
    "date": "2025-06-08T14:40:24Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "redis/redis",
 | 
			
		||||
    "version": "8.2-m01-int",
 | 
			
		||||
    "date": "2025-06-08T13:48:51Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Readarr/Readarr",
 | 
			
		||||
    "version": "v2.0.0.4645",
 | 
			
		||||
    "date": "2017-03-07T18:56:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Radarr/Radarr",
 | 
			
		||||
    "version": "v5.25.0.10024",
 | 
			
		||||
    "date": "2025-05-26T21:58:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "matze/wastebin",
 | 
			
		||||
    "version": "3.2.0",
 | 
			
		||||
    "date": "2025-06-07T21:33:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "cross-seed/cross-seed",
 | 
			
		||||
    "version": "v6.12.6",
 | 
			
		||||
    "date": "2025-05-28T00:13:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jellyfin/jellyfin",
 | 
			
		||||
    "version": "v10.10.7",
 | 
			
		||||
    "date": "2025-04-05T19:14:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jordan-dalby/ByteStash",
 | 
			
		||||
    "version": "v1.5.8",
 | 
			
		||||
    "date": "2025-06-07T11:39:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "syncthing/syncthing",
 | 
			
		||||
    "version": "2.0.0-rc.19",
 | 
			
		||||
    "date": "2025-06-02T17:56:25Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "evcc-io/evcc",
 | 
			
		||||
    "version": "0.204.2",
 | 
			
		||||
    "date": "2025-06-07T11:38:28Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TriliumNext/Notes",
 | 
			
		||||
    "version": "v0.94.1",
 | 
			
		||||
    "date": "2025-06-07T10:32:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "homebridge/homebridge",
 | 
			
		||||
    "version": "v1.10.0",
 | 
			
		||||
    "date": "2025-06-07T08:31:48Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "moghtech/komodo",
 | 
			
		||||
    "version": "v1.18.1",
 | 
			
		||||
    "date": "2025-06-07T06:25:20Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "OliveTin/OliveTin",
 | 
			
		||||
    "version": "2025.6.6",
 | 
			
		||||
    "date": "2025-06-06T21:39:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "homarr-labs/homarr",
 | 
			
		||||
    "version": "v1.23.0",
 | 
			
		||||
    "date": "2025-06-06T19:16:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "diced/zipline",
 | 
			
		||||
    "version": "v4.1.2",
 | 
			
		||||
    "date": "2025-06-06T17:44:58Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "keycloak/keycloak",
 | 
			
		||||
    "version": "26.2.5",
 | 
			
		||||
    "date": "2025-05-28T06:49:43Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "documenso/documenso",
 | 
			
		||||
    "version": "v1.12.0-rc.2",
 | 
			
		||||
    "date": "2025-06-06T16:25:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "goauthentik/authentik",
 | 
			
		||||
    "version": "version/2025.6.1",
 | 
			
		||||
    "date": "2025-06-06T15:28:21Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ioBroker/ioBroker",
 | 
			
		||||
    "version": "2025-05-31",
 | 
			
		||||
    "date": "2025-06-06T14:50:56Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "bunkerity/bunkerweb",
 | 
			
		||||
    "version": "v1.6.1",
 | 
			
		||||
    "date": "2025-03-15T17:29:17Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "juanfont/headscale",
 | 
			
		||||
    "version": "v0.26.1",
 | 
			
		||||
@@ -239,41 +484,16 @@
 | 
			
		||||
    "version": "1.6.14",
 | 
			
		||||
    "date": "2025-06-05T16:40:52Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "emqx/emqx",
 | 
			
		||||
    "version": "e5.10.0-rc.1",
 | 
			
		||||
    "date": "2025-06-05T16:11:30Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "docker/compose",
 | 
			
		||||
    "version": "v2.37.0",
 | 
			
		||||
    "date": "2025-06-05T15:11:49Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "theonedev/onedev",
 | 
			
		||||
    "version": "v11.10.3",
 | 
			
		||||
    "date": "2025-06-05T14:31:58Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "pi-hole/pi-hole",
 | 
			
		||||
    "version": "v6.1.2",
 | 
			
		||||
    "date": "2025-06-05T11:32:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mattermost/mattermost",
 | 
			
		||||
    "version": "server/public/v0.1.14",
 | 
			
		||||
    "date": "2025-05-29T15:35:16Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "MariaDB/server",
 | 
			
		||||
    "version": "mariadb-11.8.2",
 | 
			
		||||
    "date": "2025-06-04T13:35:16Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "donaldzou/WGDashboard",
 | 
			
		||||
    "version": "v4.2.3",
 | 
			
		||||
    "date": "2025-05-07T15:35:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "actualbudget/actual",
 | 
			
		||||
    "version": "v25.6.1",
 | 
			
		||||
@@ -284,91 +504,16 @@
 | 
			
		||||
    "version": "v4.1.1",
 | 
			
		||||
    "date": "2025-06-04T19:10:05Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "FlareSolverr/FlareSolverr",
 | 
			
		||||
    "version": "v3.3.24",
 | 
			
		||||
    "date": "2025-06-04T18:02:30Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "cockpit-project/cockpit",
 | 
			
		||||
    "version": "340",
 | 
			
		||||
    "date": "2025-06-04T16:41:44Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "openobserve/openobserve",
 | 
			
		||||
    "version": "v0.15.0-rc1",
 | 
			
		||||
    "date": "2025-06-04T15:12:56Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "n8n-io/n8n",
 | 
			
		||||
    "version": "n8n@1.95.3",
 | 
			
		||||
    "date": "2025-06-03T11:09:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Graylog2/graylog2-server",
 | 
			
		||||
    "version": "6.1.12",
 | 
			
		||||
    "date": "2025-06-04T12:48:55Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Prowlarr/Prowlarr",
 | 
			
		||||
    "version": "v1.37.0.5076",
 | 
			
		||||
    "date": "2025-06-04T11:04:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "zabbix/zabbix",
 | 
			
		||||
    "version": "7.4.0rc1",
 | 
			
		||||
    "date": "2025-06-04T09:06:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/core",
 | 
			
		||||
    "version": "2025.5.3",
 | 
			
		||||
    "date": "2025-05-23T15:10:33Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "glpi-project/glpi",
 | 
			
		||||
    "version": "10.0.18",
 | 
			
		||||
    "date": "2025-02-12T11:07:02Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "louislam/uptime-kuma",
 | 
			
		||||
    "version": "2.0.0-beta.2-temp",
 | 
			
		||||
    "date": "2025-03-28T08:45:58Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "webmin/webmin",
 | 
			
		||||
    "version": "2.401",
 | 
			
		||||
    "date": "2025-06-04T02:53:03Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "coder/code-server",
 | 
			
		||||
    "version": "v4.100.3",
 | 
			
		||||
    "date": "2025-06-03T21:06:41Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "runtipi/runtipi",
 | 
			
		||||
    "version": "v4.2.1",
 | 
			
		||||
    "date": "2025-06-03T20:04:28Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jenkinsci/jenkins",
 | 
			
		||||
    "version": "jenkins-2.513",
 | 
			
		||||
    "date": "2025-06-03T17:53:03Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "dgtlmoon/changedetection.io",
 | 
			
		||||
    "version": "0.50.2",
 | 
			
		||||
    "date": "2025-06-03T14:29:07Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "element-hq/synapse",
 | 
			
		||||
    "version": "v1.131.0",
 | 
			
		||||
    "date": "2025-06-03T14:13:00Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "zitadel/zitadel",
 | 
			
		||||
    "version": "v2.71.12",
 | 
			
		||||
    "date": "2025-06-03T14:11:41Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "influxdata/influxdb",
 | 
			
		||||
    "version": "v1.12.1rc3",
 | 
			
		||||
@@ -379,31 +524,11 @@
 | 
			
		||||
    "version": "v0.9.0",
 | 
			
		||||
    "date": "2025-06-03T11:49:40Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "esphome/esphome",
 | 
			
		||||
    "version": "2025.5.2",
 | 
			
		||||
    "date": "2025-06-03T08:45:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "FreshRSS/FreshRSS",
 | 
			
		||||
    "version": "1.26.3",
 | 
			
		||||
    "date": "2025-06-02T22:00:14Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "TandoorRecipes/recipes",
 | 
			
		||||
    "version": "2.0.0-alpha-4",
 | 
			
		||||
    "date": "2025-05-14T05:01:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "grokability/snipe-it",
 | 
			
		||||
    "version": "v8.1.15",
 | 
			
		||||
    "date": "2025-06-02T17:38:24Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "wazuh/wazuh",
 | 
			
		||||
    "version": "coverity-w23-4.13.0",
 | 
			
		||||
    "date": "2025-05-30T15:39:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "inventree/InvenTree",
 | 
			
		||||
    "version": "0.17.13",
 | 
			
		||||
@@ -414,16 +539,6 @@
 | 
			
		||||
    "version": "v0.24.4",
 | 
			
		||||
    "date": "2025-06-02T02:49:05Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "advplyr/audiobookshelf",
 | 
			
		||||
    "version": "v2.24.0",
 | 
			
		||||
    "date": "2025-06-01T21:38:08Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "traccar/traccar",
 | 
			
		||||
    "version": "v6.7.2",
 | 
			
		||||
    "date": "2025-06-01T20:40:00Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "gethomepage/homepage",
 | 
			
		||||
    "version": "v1.3.2",
 | 
			
		||||
@@ -434,21 +549,11 @@
 | 
			
		||||
    "version": "2.4.0",
 | 
			
		||||
    "date": "2025-06-01T18:08:44Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "kimai/kimai",
 | 
			
		||||
    "version": "2.35.1",
 | 
			
		||||
    "date": "2025-05-31T15:05:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "prometheus/prometheus",
 | 
			
		||||
    "version": "v3.4.1",
 | 
			
		||||
    "date": "2025-05-31T13:45:40Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "BookStackApp/BookStack",
 | 
			
		||||
    "version": "v25.05",
 | 
			
		||||
    "date": "2025-05-31T13:36:23Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "blakeblackshear/frigate",
 | 
			
		||||
    "version": "v0.14.1",
 | 
			
		||||
@@ -464,11 +569,6 @@
 | 
			
		||||
    "version": "v2.12.0",
 | 
			
		||||
    "date": "2025-05-30T00:26:27Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "open-webui/open-webui",
 | 
			
		||||
    "version": "v0.6.13",
 | 
			
		||||
    "date": "2025-05-29T21:37:38Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "gristlabs/grist-core",
 | 
			
		||||
    "version": "v1.6.0",
 | 
			
		||||
@@ -479,16 +579,6 @@
 | 
			
		||||
    "version": "v0.56.1",
 | 
			
		||||
    "date": "2025-05-29T19:09:16Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "HabitRPG/habitica",
 | 
			
		||||
    "version": "v5.36.5",
 | 
			
		||||
    "date": "2025-05-29T17:06:01Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "FlowiseAI/Flowise",
 | 
			
		||||
    "version": "flowise@3.0.1",
 | 
			
		||||
    "date": "2025-05-29T17:00:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "readeck/readeck",
 | 
			
		||||
    "version": "0.19.2",
 | 
			
		||||
@@ -539,26 +629,11 @@
 | 
			
		||||
    "version": "v3.4.1",
 | 
			
		||||
    "date": "2025-05-27T12:53:58Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "AdguardTeam/AdGuardHome",
 | 
			
		||||
    "version": "v0.107.62",
 | 
			
		||||
    "date": "2025-05-27T12:10:19Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "semaphoreui/semaphore",
 | 
			
		||||
    "version": "v2.14.12",
 | 
			
		||||
    "date": "2025-05-27T03:58:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "dani-garcia/vaultwarden",
 | 
			
		||||
    "version": "1.34.1",
 | 
			
		||||
    "date": "2025-05-26T21:40:54Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "MediaBrowser/Emby.Releases",
 | 
			
		||||
    "version": "4.8.11.0",
 | 
			
		||||
    "date": "2025-03-10T06:39:11Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "jupyter/notebook",
 | 
			
		||||
    "version": "v7.4.3",
 | 
			
		||||
@@ -589,31 +664,16 @@
 | 
			
		||||
    "version": "v2.0.113",
 | 
			
		||||
    "date": "2025-05-23T01:47:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "grafana/grafana",
 | 
			
		||||
    "version": "v11.2.10",
 | 
			
		||||
    "date": "2025-05-22T23:50:45Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "0xERR0R/blocky",
 | 
			
		||||
    "version": "v0.26.2",
 | 
			
		||||
    "date": "2025-05-22T05:24:42Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "tobychui/zoraxy",
 | 
			
		||||
    "version": "v3.1.9",
 | 
			
		||||
    "date": "2025-03-01T02:24:33Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "apache/tika",
 | 
			
		||||
    "version": "3.2.0-rc2",
 | 
			
		||||
    "date": "2025-05-21T20:09:07Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "clusterzx/paperless-ai",
 | 
			
		||||
    "version": "v3.0.4",
 | 
			
		||||
    "date": "2025-05-21T19:03:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "ipfs/kubo",
 | 
			
		||||
    "version": "v0.35.0",
 | 
			
		||||
@@ -624,16 +684,6 @@
 | 
			
		||||
    "version": "v0.46.2",
 | 
			
		||||
    "date": "2025-05-20T11:21:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "crafty-controller/crafty-4",
 | 
			
		||||
    "version": "v4.4.9",
 | 
			
		||||
    "date": "2025-05-20T00:08:29Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "glanceapp/glance",
 | 
			
		||||
    "version": "v0.8.3",
 | 
			
		||||
    "date": "2025-05-19T20:45:10Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Part-DB/Part-DB-server",
 | 
			
		||||
    "version": "v1.17.1",
 | 
			
		||||
@@ -675,9 +725,9 @@
 | 
			
		||||
    "date": "2025-05-16T04:31:05Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "cloudflare/cloudflared",
 | 
			
		||||
    "version": "2025.5.0",
 | 
			
		||||
    "date": "2025-05-15T17:09:50Z"
 | 
			
		||||
    "name": "Dolibarr/dolibarr",
 | 
			
		||||
    "version": "18.0.7",
 | 
			
		||||
    "date": "2025-05-15T08:24:30Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Ombi-app/Ombi",
 | 
			
		||||
@@ -689,21 +739,6 @@
 | 
			
		||||
    "version": "0.42.1",
 | 
			
		||||
    "date": "2020-06-07T07:27:04Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "OctoPrint/OctoPrint",
 | 
			
		||||
    "version": "1.11.1",
 | 
			
		||||
    "date": "2025-05-13T13:32:07Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "go-gitea/gitea",
 | 
			
		||||
    "version": "v1.23.8",
 | 
			
		||||
    "date": "2025-05-12T22:40:50Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "leiweibau/Pi.Alert",
 | 
			
		||||
    "version": "v2025-05-11",
 | 
			
		||||
    "date": "2025-05-12T19:14:57Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "stackblitz-labs/bolt.diy",
 | 
			
		||||
    "version": "1.0.0",
 | 
			
		||||
@@ -749,11 +784,6 @@
 | 
			
		||||
    "version": "v2.10.2",
 | 
			
		||||
    "date": "2025-05-06T03:12:53Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "autobrr/autobrr",
 | 
			
		||||
    "version": "v1.62.0",
 | 
			
		||||
    "date": "2025-05-05T20:35:18Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "postgres/postgres",
 | 
			
		||||
    "version": "REL_13_21",
 | 
			
		||||
@@ -884,11 +914,6 @@
 | 
			
		||||
    "version": "0.22.5",
 | 
			
		||||
    "date": "2025-04-15T02:52:26Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "home-assistant/operating-system",
 | 
			
		||||
    "version": "15.2",
 | 
			
		||||
    "date": "2025-04-14T15:37:12Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Tautulli/Tautulli",
 | 
			
		||||
    "version": "v2.15.2",
 | 
			
		||||
@@ -904,21 +929,11 @@
 | 
			
		||||
    "version": "v5.5.2",
 | 
			
		||||
    "date": "2025-04-11T22:00:06Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "sabnzbd/sabnzbd",
 | 
			
		||||
    "version": "4.5.1",
 | 
			
		||||
    "date": "2025-04-11T09:57:47Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "thomiceli/opengist",
 | 
			
		||||
    "version": "v1.10.0",
 | 
			
		||||
    "date": "2025-04-07T14:32:15Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Dolibarr/dolibarr",
 | 
			
		||||
    "version": "21.0.1",
 | 
			
		||||
    "date": "2025-04-06T19:22:59Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "azukaar/Cosmos-Server",
 | 
			
		||||
    "version": "v0.18.4",
 | 
			
		||||
@@ -994,11 +1009,6 @@
 | 
			
		||||
    "version": "v0.22.1",
 | 
			
		||||
    "date": "2025-03-18T21:01:22Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "Sonarr/Sonarr",
 | 
			
		||||
    "version": "v4.0.14.2939",
 | 
			
		||||
    "date": "2025-03-17T19:12:37Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "transmission/transmission",
 | 
			
		||||
    "version": "4.0.1-beta.1",
 | 
			
		||||
@@ -1074,11 +1084,6 @@
 | 
			
		||||
    "version": "v7.4.1",
 | 
			
		||||
    "date": "2025-02-15T20:54:00Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "node-red/node-red",
 | 
			
		||||
    "version": "4.0.9",
 | 
			
		||||
    "date": "2025-02-14T17:10:20Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "mayswind/AriaNg",
 | 
			
		||||
    "version": "1.3.10",
 | 
			
		||||
@@ -1234,11 +1239,6 @@
 | 
			
		||||
    "version": "v4.4.3",
 | 
			
		||||
    "date": "2024-04-06T12:24:35Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "hyperion-project/hyperion.ng",
 | 
			
		||||
    "version": "2.0.16",
 | 
			
		||||
    "date": "2024-01-18T16:11:07Z"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "name": "deepch/RTSPtoWeb",
 | 
			
		||||
    "version": "v2.4.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,11 @@ const getMetadata = async () => {
 | 
			
		||||
 | 
			
		||||
const getScripts = async () => {
 | 
			
		||||
  const filePaths = (await fs.readdir(jsonDir))
 | 
			
		||||
    .filter((fileName) => fileName !== metadataFileName && fileName !== versionFileName)
 | 
			
		||||
    .filter((fileName) => 
 | 
			
		||||
      fileName.endsWith(".json") && 
 | 
			
		||||
      fileName !== metadataFileName && 
 | 
			
		||||
      fileName !== versionFileName
 | 
			
		||||
    )
 | 
			
		||||
    .map((fileName) => path.resolve(jsonDir, fileName));
 | 
			
		||||
 | 
			
		||||
  const scripts = await Promise.all(
 | 
			
		||||
 
 | 
			
		||||
@@ -104,7 +104,7 @@ export default function RootLayout({
 | 
			
		||||
            <Navbar />
 | 
			
		||||
            <div className="flex min-h-screen flex-col justify-center">
 | 
			
		||||
              <div className="flex w-full justify-center">
 | 
			
		||||
                <div className="w-full max-w-7xl ">
 | 
			
		||||
                <div className="w-full max-w-[1440px] ">
 | 
			
		||||
                  <QueryProvider>
 | 
			
		||||
                    <NuqsAdapter>{children}</NuqsAdapter>
 | 
			
		||||
                  </QueryProvider>
 | 
			
		||||
 
 | 
			
		||||
@@ -56,7 +56,7 @@ export default function ScriptAccordion({
 | 
			
		||||
      value={expandedItem}
 | 
			
		||||
      onValueChange={handleAccordionChange}
 | 
			
		||||
      collapsible
 | 
			
		||||
      className="overflow-y-scroll max-h-[calc(100vh-225px)] overflow-x-hidden mt-3 p-2"
 | 
			
		||||
      className="overflow-y-scroll max-h-[calc(100vh-225px)] overflow-x-hidden p-2"
 | 
			
		||||
    >
 | 
			
		||||
      {items.map((category) => (
 | 
			
		||||
        <AccordionItem
 | 
			
		||||
 
 | 
			
		||||
@@ -15,12 +15,12 @@ import { ResourceDisplay } from "./ResourceDisplay";
 | 
			
		||||
import { getDisplayValueFromType } from "./ScriptInfoBlocks";
 | 
			
		||||
import Alerts from "./ScriptItems/Alerts";
 | 
			
		||||
import Buttons from "./ScriptItems/Buttons";
 | 
			
		||||
import ConfigFile from "./ScriptItems/ConfigFile";
 | 
			
		||||
import DefaultPassword from "./ScriptItems/DefaultPassword";
 | 
			
		||||
import Description from "./ScriptItems/Description";
 | 
			
		||||
import InstallCommand from "./ScriptItems/InstallCommand";
 | 
			
		||||
import InterFaces from "./ScriptItems/InterFaces";
 | 
			
		||||
import Tooltips from "./ScriptItems/Tooltips";
 | 
			
		||||
import ConfigFile from "./ScriptItems/ConfigFile";
 | 
			
		||||
 | 
			
		||||
interface ScriptItemProps {
 | 
			
		||||
  item: Script;
 | 
			
		||||
@@ -120,7 +120,7 @@ export function ScriptItem({ item, setSelectedScript }: ScriptItemProps) {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="w-full max-w-5xl mx-auto">
 | 
			
		||||
    <div className="w-full mx-auto">
 | 
			
		||||
      <div className="flex w-full flex-col">
 | 
			
		||||
        <div className="mb-3 flex items-center justify-between">
 | 
			
		||||
          <h2 className="text-2xl font-semibold tracking-tight text-foreground/90">Selected Script</h2>
 | 
			
		||||
@@ -132,7 +132,7 @@ export function ScriptItem({ item, setSelectedScript }: ScriptItemProps) {
 | 
			
		||||
          </button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div className="rounded-xl border border-border/40 bg-gradient-to-b from-card/30 to-background/50 backdrop-blur-sm shadow-sm">
 | 
			
		||||
        <div className="rounded-xl border border-border bg-gradient-to-b from-card/30 to-background/50 backdrop-blur-sm shadow-sm">
 | 
			
		||||
          <div className="p-6 space-y-6">
 | 
			
		||||
            <Suspense fallback={<div className="animate-pulse h-32 bg-accent/20 rounded-xl" />}>
 | 
			
		||||
              <ScriptHeader item={item} />
 | 
			
		||||
@@ -152,16 +152,18 @@ export function ScriptItem({ item, setSelectedScript }: ScriptItemProps) {
 | 
			
		||||
              <div className="">
 | 
			
		||||
                <InstallCommand item={item} />
 | 
			
		||||
              </div>
 | 
			
		||||
              <Separator />
 | 
			
		||||
              <div className="flex gap-3 px-4 py-2 bg-accent/25">
 | 
			
		||||
                <h2 className="text-lg font-semibold">
 | 
			
		||||
                  Location of config file
 | 
			
		||||
                </h2>
 | 
			
		||||
              </div>
 | 
			
		||||
              <Separator />
 | 
			
		||||
              <div className="">
 | 
			
		||||
                <ConfigFile item={item} />
 | 
			
		||||
              </div>
 | 
			
		||||
              {item.config_path && (
 | 
			
		||||
                <>
 | 
			
		||||
                  <Separator />
 | 
			
		||||
                  <div className="flex gap-3 px-4 py-2 bg-accent/25">
 | 
			
		||||
                    <h2 className="text-lg font-semibold">Location of config file</h2>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <Separator />
 | 
			
		||||
                  <div className="">
 | 
			
		||||
                    <ConfigFile configPath={item.config_path} />
 | 
			
		||||
                  </div>
 | 
			
		||||
                </>
 | 
			
		||||
              )}
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <DefaultPassword item={item} />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,9 @@
 | 
			
		||||
import ConfigCopyButton from "@/components/ui/config-copy-button";
 | 
			
		||||
import { Script } from "@/lib/types";
 | 
			
		||||
 | 
			
		||||
export default function ConfigFile({ item }: { item: Script }) {
 | 
			
		||||
export default function ConfigFile({ configPath }: { configPath: string }) {
 | 
			
		||||
  return (
 | 
			
		||||
    <div className="px-4 pb-4">
 | 
			
		||||
      <ConfigCopyButton>{item.config_path ? item.config_path : "No config path set"}</ConfigCopyButton>
 | 
			
		||||
      <ConfigCopyButton>{configPath}</ConfigCopyButton>
 | 
			
		||||
    </div>
 | 
			
		||||
  );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ const Sidebar = ({
 | 
			
		||||
	}, [] as Script[]);
 | 
			
		||||
 | 
			
		||||
	return (
 | 
			
		||||
		<div className="flex min-w-72 flex-col sm:max-w-72">
 | 
			
		||||
		<div className="flex min-w-[350px] flex-col sm:max-w-[350px]">
 | 
			
		||||
			<div className="flex items-end justify-between pb-4">
 | 
			
		||||
				<h1 className="text-xl font-bold">Categories</h1>
 | 
			
		||||
				<p className="text-xs italic text-muted-foreground">
 | 
			
		||||
@@ -40,4 +40,4 @@ const Sidebar = ({
 | 
			
		||||
	);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default Sidebar;
 | 
			
		||||
export default Sidebar;
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ function ScriptContent() {
 | 
			
		||||
            setSelectedScript={setSelectedScript}
 | 
			
		||||
          />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div className="mx-7 w-full sm:mx-0 sm:ml-7">
 | 
			
		||||
        <div className="mx-4 w-full sm:mx-0 sm:ml-4">
 | 
			
		||||
          {selectedScript && item ? (
 | 
			
		||||
            <ScriptItem item={item} setSelectedScript={setSelectedScript} />
 | 
			
		||||
          ) : (
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@ function Navbar() {
 | 
			
		||||
						isScrolled ? "glass border-b bg-background/50" : ""
 | 
			
		||||
					}`}
 | 
			
		||||
				>
 | 
			
		||||
					<div className="flex h-20 w-full max-w-7xl items-center justify-between sm:flex-row">
 | 
			
		||||
					<div className="flex h-20 w-full max-w-[1440px] items-center justify-between sm:flex-row">
 | 
			
		||||
						<Link
 | 
			
		||||
							href={"/"}
 | 
			
		||||
							className="flex cursor-pointer w-full justify-center sm:justify-start flex-row-reverse items-center gap-2 font-semibold sm:flex-row"
 | 
			
		||||
 
 | 
			
		||||
@@ -15,17 +15,12 @@ update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Dependencies"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  lsb-release
 | 
			
		||||
curl -fsSL https://packages.sury.org/php/apt.gpg | gpg --dearmor -o /usr/share/keyrings/deb.sury.org-php.gpg
 | 
			
		||||
echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" >/etc/apt/sources.list.d/php.list
 | 
			
		||||
$STD apt-get update
 | 
			
		||||
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  nginx \
 | 
			
		||||
  composer \
 | 
			
		||||
  php8.3-{bcmath,common,ctype,curl,fileinfo,fpm,gd,intl,mbstring,mysql,xml,cli}
 | 
			
		||||
  lsb-release \
 | 
			
		||||
  nginx
 | 
			
		||||
msg_ok "Installed Dependencies"
 | 
			
		||||
 | 
			
		||||
PHP_VERSION="8.3" PHP_MODULE="common,ctype,fileinfo,fpm,mysql,cli" install_php
 | 
			
		||||
install_composer
 | 
			
		||||
install_mariadb
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Database"
 | 
			
		||||
@@ -43,16 +38,12 @@ $STD mariadb -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUS
 | 
			
		||||
} >>~/2FAuth.creds
 | 
			
		||||
msg_ok "Set up Database"
 | 
			
		||||
 | 
			
		||||
msg_info "Setup 2FAuth"
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/Bubka/2FAuth/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
curl -fsSL "https://github.com/Bubka/2FAuth/archive/refs/tags/${RELEASE}.zip" -o "${RELEASE}.zip"
 | 
			
		||||
$STD unzip "${RELEASE}.zip"
 | 
			
		||||
mv "2FAuth-${RELEASE//v/}/" /opt/2fauth
 | 
			
		||||
fetch_and_deploy_gh_release "Bubka/2FAuth"
 | 
			
		||||
 | 
			
		||||
cd "/opt/2fauth" || return
 | 
			
		||||
msg_info "Setup 2FAuth"
 | 
			
		||||
cd /opt/2fauth
 | 
			
		||||
cp .env.example .env
 | 
			
		||||
IPADDRESS=$(hostname -I | awk '{print $1}')
 | 
			
		||||
 | 
			
		||||
sed -i -e "s|^APP_URL=.*|APP_URL=http://$IPADDRESS|" \
 | 
			
		||||
  -e "s|^DB_CONNECTION=$|DB_CONNECTION=mysql|" \
 | 
			
		||||
  -e "s|^DB_DATABASE=$|DB_DATABASE=$DB_NAME|" \
 | 
			
		||||
@@ -60,22 +51,16 @@ sed -i -e "s|^APP_URL=.*|APP_URL=http://$IPADDRESS|" \
 | 
			
		||||
  -e "s|^DB_PORT=$|DB_PORT=3306|" \
 | 
			
		||||
  -e "s|^DB_USERNAME=$|DB_USERNAME=$DB_USER|" \
 | 
			
		||||
  -e "s|^DB_PASSWORD=$|DB_PASSWORD=$DB_PASS|" .env
 | 
			
		||||
 | 
			
		||||
export COMPOSER_ALLOW_SUPERUSER=1
 | 
			
		||||
$STD composer update --no-plugins --no-scripts
 | 
			
		||||
$STD composer install --no-dev --prefer-source --no-plugins --no-scripts
 | 
			
		||||
 | 
			
		||||
$STD php artisan key:generate --force
 | 
			
		||||
 | 
			
		||||
$STD php artisan migrate:refresh
 | 
			
		||||
$STD php artisan passport:install -q -n
 | 
			
		||||
$STD php artisan storage:link
 | 
			
		||||
$STD php artisan config:cache
 | 
			
		||||
 | 
			
		||||
chown -R www-data: /opt/2fauth
 | 
			
		||||
chmod -R 755 /opt/2fauth
 | 
			
		||||
 | 
			
		||||
echo "${RELEASE}" >"/opt/2fauth_version.txt"
 | 
			
		||||
msg_ok "Setup 2fauth"
 | 
			
		||||
 | 
			
		||||
msg_info "Configure Service"
 | 
			
		||||
@@ -107,7 +92,6 @@ server {
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
systemctl reload nginx
 | 
			
		||||
msg_ok "Configured Service"
 | 
			
		||||
 | 
			
		||||
@@ -115,7 +99,6 @@ motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -f "/opt/v${RELEASE}.zip"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,7 @@ EOF
 | 
			
		||||
 | 
			
		||||
sed -i -e 's/\$/\$\$/g' /opt/tinyauth/.env
 | 
			
		||||
 | 
			
		||||
cat <<EOF >/etc/init.d/tinyauth
 | 
			
		||||
cat <<'EOF' >/etc/init.d/tinyauth
 | 
			
		||||
#!/sbin/openrc-run
 | 
			
		||||
description="Tinyauth Service"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,8 @@ network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Alpine-Zigbee2MQTT"
 | 
			
		||||
mkdir -p /root/.z2m /etc/zigbee2mqtt
 | 
			
		||||
$STD apk add zigbee2mqtt
 | 
			
		||||
mkdir -p /root/.z2m
 | 
			
		||||
ln -s /etc/zigbee2mqtt/ /root/.z2m
 | 
			
		||||
chown -R root:root /etc/zigbee2mqtt /root/.z2m
 | 
			
		||||
sed -i -e 's/#datadir="\/var\/lib\/zigbee2mqtt"/datadir="\/etc\/zigbee2mqtt"/' -e 's/#command_user="zigbee2mqtt"/command_user="root"/' /etc/conf.d/zigbee2mqtt
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ install_mariadb
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Database"
 | 
			
		||||
ROOT_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
$STD mariadb -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$ROOT_PASS'); flush privileges;"
 | 
			
		||||
$STD mariadb -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY '$ROOT_PASS'; flush privileges;"
 | 
			
		||||
{
 | 
			
		||||
  echo "Dolibarr DB Credentials"
 | 
			
		||||
  echo "MariaDB Root Password: $ROOT_PASS"
 | 
			
		||||
@@ -32,7 +32,7 @@ msg_ok "Set up database"
 | 
			
		||||
 | 
			
		||||
msg_info "Setup Dolibarr"
 | 
			
		||||
BASE="https://sourceforge.net/projects/dolibarr/files/Dolibarr%20installer%20for%20Debian-Ubuntu%20(DoliDeb)/"
 | 
			
		||||
RELEASE=$(curl -fsSL "$BASE" | grep -oP '(?<=/Dolibarr%20installer%20for%20Debian-Ubuntu%20%28DoliDeb%29/)[^/"]+' | head -n1)
 | 
			
		||||
RELEASE=$(curl -fsSL "$BASE" | grep -oP '(?<=/Dolibarr%20installer%20for%20Debian-Ubuntu%20%28DoliDeb%29/)\d+(\.\d+)+(?=/)' | sort -V | tail -n1)
 | 
			
		||||
FILE=$(curl -fsSL "${BASE}${RELEASE}/" | grep -oP 'dolibarr_[^"]+_all.deb' | head -n1)
 | 
			
		||||
curl -fsSL "https://netcologne.dl.sourceforge.net/project/dolibarr/Dolibarr%20installer%20for%20Debian-Ubuntu%20(DoliDeb)/${RELEASE}/${FILE}?viasf=1" -o ""$FILE""
 | 
			
		||||
echo "dolibarr dolibarr/reconfigure-webserver multiselect apache2" | debconf-set-selections
 | 
			
		||||
 
 | 
			
		||||
@@ -54,7 +54,12 @@ RELEASE=$(curl -fsSL https://api.github.com/repos/etkecc/synapse-admin/releases/
 | 
			
		||||
curl -fsSL "https://github.com/etkecc/synapse-admin/archive/refs/tags/v${RELEASE}.tar.gz" -o "$temp_file"
 | 
			
		||||
tar xzf "$temp_file" -C /opt/synapse-admin --strip-components=1
 | 
			
		||||
cd /opt/synapse-admin
 | 
			
		||||
$STD yarn global add serve
 | 
			
		||||
$STD yarn install --ignore-engines
 | 
			
		||||
$STD yarn build
 | 
			
		||||
mv ./dist ../ && \
 | 
			
		||||
  rm -rf * && \
 | 
			
		||||
  mv ../dist ./
 | 
			
		||||
msg_ok "Installed Element Synapse"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
@@ -67,7 +72,7 @@ Requires=matrix-synapse.service
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
WorkingDirectory=/opt/synapse-admin
 | 
			
		||||
ExecStart=/usr/bin/yarn start --host
 | 
			
		||||
ExecStart=/usr/local/bin/serve -s dist -l 5173
 | 
			
		||||
Restart=always
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: quantumryuu
 | 
			
		||||
# Author: quantumryuu | Co-Author: Slaviša Arežina (tremor021)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://firefly-iii.org/
 | 
			
		||||
 | 
			
		||||
@@ -30,7 +30,6 @@ msg_info "Setting up database"
 | 
			
		||||
DB_NAME=firefly
 | 
			
		||||
DB_USER=firefly
 | 
			
		||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
MYSQL_VERSION=$(mariadb --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
 | 
			
		||||
$STD mariadb -u root -e "CREATE DATABASE $DB_NAME;"
 | 
			
		||||
$STD mariadb -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
 | 
			
		||||
mariadb -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
 | 
			
		||||
@@ -43,6 +42,7 @@ mariadb -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRI
 | 
			
		||||
msg_ok "Set up database"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Firefly III (Patience)"
 | 
			
		||||
LOCAL_IP=$(hostname -I | awk '{print $1}')
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/firefly-iii/firefly-iii/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4)}')
 | 
			
		||||
cd /opt
 | 
			
		||||
curl -fsSL "https://github.com/firefly-iii/firefly-iii/releases/download/v${RELEASE}/FireflyIII-v${RELEASE}.tar.gz" -o "FireflyIII-v${RELEASE}.tar.gz"
 | 
			
		||||
@@ -61,6 +61,14 @@ $STD php artisan firefly:upgrade-database
 | 
			
		||||
$STD php artisan firefly:correct-database
 | 
			
		||||
$STD php artisan firefly:report-integrity
 | 
			
		||||
$STD php artisan firefly:laravel-passport-keys
 | 
			
		||||
IMPORTER_RELEASE=$(curl -fsSL https://api.github.com/repos/firefly-iii/data-importer/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4)}')
 | 
			
		||||
mkdir -p /opt/firefly/dataimporter
 | 
			
		||||
cd /opt
 | 
			
		||||
curl -fsSL "https://github.com/firefly-iii/data-importer/releases/download/v${IMPORTER_RELEASE}/DataImporter-v${IMPORTER_RELEASE}.tar.gz" -o "DataImporter-v${IMPORTER_RELEASE}.tar.gz"
 | 
			
		||||
tar -xzf "DataImporter-v${IMPORTER_RELEASE}.tar.gz" -C /opt/firefly/dataimporter
 | 
			
		||||
cp /opt/firefly/dataimporter/.env.example /opt/firefly/dataimporter/.env
 | 
			
		||||
sed -i "s#FIREFLY_III_URL=#FIREFLY_III_URL=http://${LOCAL_IP}#g" /opt/firefly/dataimporter/.env
 | 
			
		||||
chown -R www-data:www-data /opt/firefly
 | 
			
		||||
echo "${RELEASE}" >"/opt/${APPLICATION}_version.txt"
 | 
			
		||||
msg_ok "Installed Firefly III"
 | 
			
		||||
 | 
			
		||||
@@ -75,7 +83,18 @@ cat <<EOF >/etc/apache2/sites-available/firefly.conf
 | 
			
		||||
        AllowOverride All
 | 
			
		||||
        Require all granted
 | 
			
		||||
    </Directory>
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  Alias /dataimporter/ /opt/firefly/dataimporter/public/
 | 
			
		||||
 | 
			
		||||
    <Directory /opt/firefly/dataimporter/public/>
 | 
			
		||||
        Options Indexes FollowSymLinks
 | 
			
		||||
        AllowOverride All
 | 
			
		||||
        Require all granted
 | 
			
		||||
    </Directory>
 | 
			
		||||
    <FilesMatch \.php$>
 | 
			
		||||
        SetHandler application/x-httpd-php
 | 
			
		||||
    </FilesMatch>
 | 
			
		||||
 | 
			
		||||
    ErrorLog /var/log/apache2/error.log
 | 
			
		||||
    CustomLog /var/log/apache2/access.log combined
 | 
			
		||||
 | 
			
		||||
@@ -93,7 +112,8 @@ motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -rf /opt/FireflyIII-v${RELEASE}.tar.gz
 | 
			
		||||
rm -rf "/opt/FireflyIII-v${RELEASE}.tar.gz"
 | 
			
		||||
rm -rf "/opt/DataImporter-v${IMPORTER_RELEASE}.tar.gz"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
NODE_VERSION="22" install_node_and_modules
 | 
			
		||||
NODE_VERSION="20" install_node_and_modules
 | 
			
		||||
 | 
			
		||||
msg_info "Installing FlowiseAI (Patience)"
 | 
			
		||||
$STD npm install -g flowise \
 | 
			
		||||
 
 | 
			
		||||
@@ -16,17 +16,25 @@ update_os
 | 
			
		||||
msg_info "Installing Kasm Workspaces"
 | 
			
		||||
KASM_VERSION=$(curl -fsSL 'https://www.kasmweb.com/downloads' | grep -o 'https://kasm-static-content.s3.amazonaws.com/kasm_release_[^"]*\.tar\.gz' | head -n 1 | sed -E 's/.*release_(.*)\.tar\.gz/\1/')
 | 
			
		||||
curl -fsSL -o "/opt/kasm_release_${KASM_VERSION}.tar.gz" "https://kasm-static-content.s3.amazonaws.com/kasm_release_${KASM_VERSION}.tar.gz"
 | 
			
		||||
tar -xf "/opt/kasm_release_${KASM_VERSION}.tar.gz" -C /opt
 | 
			
		||||
printf 'y\ny\ny\n4\n' | bash /opt/kasm_release/install.sh
 | 
			
		||||
touch ~/kasm-install.output
 | 
			
		||||
sed -n '/Kasm UI Login Credentials/,$p' ~/kasm-install.output >~/kasm.creds
 | 
			
		||||
 | 
			
		||||
cd /opt
 | 
			
		||||
tar -xf "kasm_release_${KASM_VERSION}.tar.gz"
 | 
			
		||||
chmod +x /opt/kasm_release/install.sh
 | 
			
		||||
printf 'y\ny\ny\n4\n' | bash /opt/kasm_release/install.sh > ~/kasm-install.output 2>&1
 | 
			
		||||
cat ~/kasm-install.output | grep -A 20 -i "credentials\|login\|password\|admin" | sed '1i Kasm-Workspaces-Credentials' >~/kasm.creds
 | 
			
		||||
 | 
			
		||||
msg_ok "Installed Kasm Workspaces"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Displaying Kasm Credentials"
 | 
			
		||||
cat ~/kasm.creds
 | 
			
		||||
msg_ok "Kasm Credentials displayed"
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD rm -f "/opt/kasm_release_${KASM_VERSION}.tar.gz"
 | 
			
		||||
rm -f /opt/kasm_release_${KASM_VERSION}.tar.gz
 | 
			
		||||
rm -f ~/kasm-install.output
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										81
									
								
								install/libretranslate-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								install/libretranslate-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: Slaviša Arežina (tremor021)
 | 
			
		||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/LibreTranslate/LibreTranslate
 | 
			
		||||
 | 
			
		||||
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 --no-install-recommends \
 | 
			
		||||
  pkg-config \
 | 
			
		||||
  gcc \
 | 
			
		||||
  g++ \
 | 
			
		||||
  libicu-dev
 | 
			
		||||
msg_ok "Installed dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Setup Python3"
 | 
			
		||||
$STD apt-get install -y \
 | 
			
		||||
  python3-pip \
 | 
			
		||||
  python3-dev \
 | 
			
		||||
  python3-icu
 | 
			
		||||
msg_ok "Setup Python3"
 | 
			
		||||
 | 
			
		||||
setup_uv
 | 
			
		||||
fetch_and_deploy_gh_release "LibreTranslate/LibreTranslate"
 | 
			
		||||
 | 
			
		||||
msg_info "Setup LibreTranslate (Patience)"
 | 
			
		||||
cd /opt/libretranslate
 | 
			
		||||
$STD uv venv .venv
 | 
			
		||||
$STD source .venv/bin/activate
 | 
			
		||||
$STD uv pip install --upgrade pip setuptools
 | 
			
		||||
$STD uv pip install Babel==2.12.1
 | 
			
		||||
$STD .venv/bin/python scripts/compile_locales.py
 | 
			
		||||
$STD uv pip install torch==2.2.0 --extra-index-url https://download.pytorch.org/whl/cpu
 | 
			
		||||
$STD uv pip install "numpy<2"
 | 
			
		||||
$STD uv pip install .
 | 
			
		||||
$STD uv pip install libretranslate
 | 
			
		||||
$STD .venv/bin/python scripts/install_models.py
 | 
			
		||||
 | 
			
		||||
cat <<EOF >/opt/libretranslate/.env
 | 
			
		||||
LT_PORT=5000
 | 
			
		||||
EOF
 | 
			
		||||
msg_ok "Installed LibreTranslate"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF >/etc/systemd/system/libretranslate.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=LibreTranslate
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
User=root
 | 
			
		||||
Type=idle
 | 
			
		||||
Restart=always
 | 
			
		||||
Environment="PATH=/usr/local/lib/python3.11/dist-packages/libretranslate"
 | 
			
		||||
EnvironmentFile=/opt/libretranslate/.env
 | 
			
		||||
ExecStart=/opt/libretranslate/.venv/bin/python3 /opt/libretranslate/.venv/bin/libretranslate --host * --update-models
 | 
			
		||||
ExecReload=/bin/kill -s HUP
 | 
			
		||||
KillMode=mixed
 | 
			
		||||
TimeoutStopSec=1
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
systemctl enable -q --now libretranslate
 | 
			
		||||
msg_ok "Created Service"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
							
								
								
									
										84
									
								
								install/managemydamnlife-install.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								install/managemydamnlife-install.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
#!/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://github.com/intri-in/manage-my-damn-life-nextjs
 | 
			
		||||
 | 
			
		||||
source /dev/stdin <<<"$FUNCTIONS_FILE_PATH"
 | 
			
		||||
color
 | 
			
		||||
verb_ip6
 | 
			
		||||
catch_errors
 | 
			
		||||
setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
NODE_VERSION="20" install_node_and_modules
 | 
			
		||||
MYSQL_VERSION="8.0" install_mysql
 | 
			
		||||
 | 
			
		||||
msg_info "Setting up Database"
 | 
			
		||||
DB_NAME="mmdl"
 | 
			
		||||
DB_USER="mmdl"
 | 
			
		||||
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
 | 
			
		||||
$STD mysql -u root -e "CREATE DATABASE $DB_NAME;"
 | 
			
		||||
$STD mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED by '$DB_PASS';"
 | 
			
		||||
$STD mysql -u root -e "GRANT ALL ON $DB_NAME.* TO '$DB_USER'@'localhost'; FLUSH PRIVILEGES;"
 | 
			
		||||
{
 | 
			
		||||
  echo "Manage My Damn Life Credentials"
 | 
			
		||||
  echo "Database User: $DB_USER"
 | 
			
		||||
  echo "Database Password: $DB_PASS"
 | 
			
		||||
  echo "Database Name: $DB_NAME"
 | 
			
		||||
} >>~/mmdl.creds
 | 
			
		||||
msg_ok "Set up Database"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing ${APPLICATION}"
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/intri-in/manage-my-damn-life-nextjs/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
 | 
			
		||||
curl -fsSLO "https://github.com/intri-in/manage-my-damn-life-nextjs/archive/refs/tags/v${RELEASE}.zip"
 | 
			
		||||
unzip -q v"$RELEASE".zip
 | 
			
		||||
mv manage-my-damn-life-nextjs-"$RELEASE"/ /opt/mmdl
 | 
			
		||||
cp /opt/mmdl/sample.env.local /opt/mmdl/.env
 | 
			
		||||
 | 
			
		||||
sed -i -e 's|db|localhost|' \
 | 
			
		||||
  -e "s|myuser|${DB_USER}|" \
 | 
			
		||||
  -e "s|mypassword|${DB_PASS}|" \
 | 
			
		||||
  -e 's|5433|3306|' \
 | 
			
		||||
  -e 's|DB_DIALECT=postgres|DB_DIALECT=mysql|' \
 | 
			
		||||
  -e "s|sample_install_mmdm|${DB_NAME}|" \
 | 
			
		||||
  -e "s|=PASSWORD|=$(openssl rand -base64 40 | tr -dc 'a-zA-Z0-9' | head -c40)|" \
 | 
			
		||||
  /opt/mmdl/.env
 | 
			
		||||
 | 
			
		||||
cd /opt/mmdl
 | 
			
		||||
export NEXT_TELEMETRY_DISABLE=1
 | 
			
		||||
export CI="true"
 | 
			
		||||
$STD npm install
 | 
			
		||||
$STD npm run migrate
 | 
			
		||||
$STD npm run build
 | 
			
		||||
echo "${RELEASE}" >/opt/mmdl_version.txt
 | 
			
		||||
msg_ok "Installed ${APPLICATION}"
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
cat <<EOF >/etc/systemd/system/mmdl.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=${APPLICATION} Service
 | 
			
		||||
After=network.target mysql.service
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
WorkingDirectory=/opt/mmdl
 | 
			
		||||
EnvironmentFile=/opt/mmdl/.env
 | 
			
		||||
ExecStart=/usr/bin/npm run start
 | 
			
		||||
Restart=on-abnormal
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
systemctl enable -q --now mmdl
 | 
			
		||||
msg_ok "Created Service"
 | 
			
		||||
 | 
			
		||||
motd_ssh
 | 
			
		||||
customize
 | 
			
		||||
 | 
			
		||||
msg_info "Cleaning up"
 | 
			
		||||
rm -f ~/v${RELEASE}.zip
 | 
			
		||||
$STD apt-get -y autoremove
 | 
			
		||||
$STD apt-get -y autoclean
 | 
			
		||||
msg_ok "Cleaned"
 | 
			
		||||
@@ -13,6 +13,10 @@ setting_up_container
 | 
			
		||||
network_check
 | 
			
		||||
update_os
 | 
			
		||||
 | 
			
		||||
msg_info "Installing dependencies"
 | 
			
		||||
$STD apt-get install -y zstd
 | 
			
		||||
msg_ok "Installed dependencies"
 | 
			
		||||
 | 
			
		||||
msg_info "Installing Wastebin"
 | 
			
		||||
temp_file=$(mktemp)
 | 
			
		||||
RELEASE=$(curl -fsSL https://api.github.com/repos/matze/wastebin/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
 | 
			
		||||
 
 | 
			
		||||
@@ -39,9 +39,11 @@ post_to_api() {
 | 
			
		||||
EOF
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
  RESPONSE=$(curl -fsSL -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
 | 
			
		||||
  if [[ "$DIAGNOSTICS" == "yes" ]]; then
 | 
			
		||||
    RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
 | 
			
		||||
    -H "Content-Type: application/json" \
 | 
			
		||||
    -d "$JSON_PAYLOAD") || true
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
post_to_api_vm() {
 | 
			
		||||
@@ -87,9 +89,11 @@ post_to_api_vm() {
 | 
			
		||||
EOF
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
  RESPONSE=$(curl -fsSL -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
 | 
			
		||||
  if [[ "$DIAGNOSTICS" == "yes" ]]; then
 | 
			
		||||
    RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
 | 
			
		||||
    -H "Content-Type: application/json" \
 | 
			
		||||
    -d "$JSON_PAYLOAD") || true
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
POST_UPDATE_DONE=false
 | 
			
		||||
@@ -115,9 +119,11 @@ post_update_to_api() {
 | 
			
		||||
EOF
 | 
			
		||||
)
 | 
			
		||||
   
 | 
			
		||||
  RESPONSE=$(curl -fsSL -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
 | 
			
		||||
  if [[ "$DIAGNOSTICS" == "yes" ]]; then
 | 
			
		||||
    RESPONSE=$(curl -s -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
 | 
			
		||||
    -H "Content-Type: application/json" \
 | 
			
		||||
    -d "$JSON_PAYLOAD") || true
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  POST_UPDATE_DONE=true
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1090,6 +1090,8 @@ build_container() {
 | 
			
		||||
  else
 | 
			
		||||
    export FUNCTIONS_FILE_PATH="$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func)"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  export DIAGNOSTICS="$DIAGNOSTICS"
 | 
			
		||||
  export RANDOM_UUID="$RANDOM_UUID"
 | 
			
		||||
  export CACHER="$APT_CACHER"
 | 
			
		||||
  export CACHER_IP="$APT_CACHER_IP"
 | 
			
		||||
 
 | 
			
		||||
@@ -77,7 +77,7 @@ error_handler() {
 | 
			
		||||
  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"
 | 
			
		||||
  if [[ "$line_number" -eq 50 ]]; then
 | 
			
		||||
  if [[ "$line_number" -eq 51 ]]; then
 | 
			
		||||
    echo -e "The silent function has suppressed the error, run the script with verbose mode enabled, which will provide more detailed output.\n"
 | 
			
		||||
    post_update_to_api "failed" "No error message, script ran in silent mode"
 | 
			
		||||
  else
 | 
			
		||||
 
 | 
			
		||||
@@ -227,6 +227,7 @@ install_mariadb() {
 | 
			
		||||
  local MARIADB_VERSION="${MARIADB_VERSION:-latest}"
 | 
			
		||||
  local DISTRO_CODENAME
 | 
			
		||||
  DISTRO_CODENAME="$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)"
 | 
			
		||||
  CURRENT_OS="$(awk -F= '/^ID=/{print $2}' /etc/os-release)"
 | 
			
		||||
 | 
			
		||||
  # grab dynamic latest LTS version
 | 
			
		||||
  if [[ "$MARIADB_VERSION" == "latest" ]]; then
 | 
			
		||||
@@ -270,7 +271,7 @@ install_mariadb() {
 | 
			
		||||
  curl -fsSL "https://mariadb.org/mariadb_release_signing_key.asc" |
 | 
			
		||||
    gpg --dearmor -o /etc/apt/trusted.gpg.d/mariadb.gpg
 | 
			
		||||
 | 
			
		||||
  echo "deb [signed-by=/etc/apt/trusted.gpg.d/mariadb.gpg] http://mirror.mariadb.org/repo/${MARIADB_VERSION}/debian ${DISTRO_CODENAME} main" \
 | 
			
		||||
  echo "deb [signed-by=/etc/apt/trusted.gpg.d/mariadb.gpg] http://mirror.mariadb.org/repo/${MARIADB_VERSION}/${CURRENT_OS} ${DISTRO_CODENAME} main" \
 | 
			
		||||
    >/etc/apt/sources.list.d/mariadb.list
 | 
			
		||||
 | 
			
		||||
  $STD apt-get update
 | 
			
		||||
@@ -379,45 +380,44 @@ install_php() {
 | 
			
		||||
  # Deduplicate modules
 | 
			
		||||
  COMBINED_MODULES=$(echo "$COMBINED_MODULES" | tr ',' '\n' | awk '!seen[$0]++' | paste -sd, -)
 | 
			
		||||
 | 
			
		||||
  local CURRENT_PHP
 | 
			
		||||
  local CURRENT_PHP=""
 | 
			
		||||
  if command -v php >/dev/null 2>&1; then
 | 
			
		||||
    CURRENT_PHP=$(php -v 2>/dev/null | awk '/^PHP/{print $2}' | cut -d. -f1,2)
 | 
			
		||||
  else
 | 
			
		||||
    CURRENT_PHP=""
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [[ -z "$CURRENT_PHP" ]]; then
 | 
			
		||||
    msg_info "Setup PHP $PHP_VERSION"
 | 
			
		||||
    msg_info "No PHP found, setting up PHP $PHP_VERSION"
 | 
			
		||||
  elif [[ "$CURRENT_PHP" != "$PHP_VERSION" ]]; then
 | 
			
		||||
    msg_info "PHP $CURRENT_PHP detected, migrating to PHP $PHP_VERSION"
 | 
			
		||||
    if [[ ! -f /etc/apt/sources.list.d/php.list ]]; then
 | 
			
		||||
      $STD curl -fsSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
 | 
			
		||||
      $STD dpkg -i /tmp/debsuryorg-archive-keyring.deb
 | 
			
		||||
      echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ ${DISTRO_CODENAME} main" \
 | 
			
		||||
        >/etc/apt/sources.list.d/php.list
 | 
			
		||||
      $STD apt-get update
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    $STD apt-get purge -y "php${CURRENT_PHP//./}"* || true
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Ensure Sury repo is available
 | 
			
		||||
  if [[ ! -f /etc/apt/sources.list.d/php.list ]]; then
 | 
			
		||||
    $STD curl -fsSLo /tmp/debsuryorg-archive-keyring.deb https://packages.sury.org/debsuryorg-archive-keyring.deb
 | 
			
		||||
    $STD dpkg -i /tmp/debsuryorg-archive-keyring.deb
 | 
			
		||||
    echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ ${DISTRO_CODENAME} main" \
 | 
			
		||||
      >/etc/apt/sources.list.d/php.list
 | 
			
		||||
    $STD apt-get update
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  local MODULE_LIST="php${PHP_VERSION}"
 | 
			
		||||
  IFS=',' read -ra MODULES <<<"$COMBINED_MODULES"
 | 
			
		||||
  for mod in "${MODULES[@]}"; do
 | 
			
		||||
    MODULE_LIST+=" php${PHP_VERSION}-${mod}"
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  if [[ "$PHP_FPM" == "YES" ]]; then
 | 
			
		||||
    MODULE_LIST+=" php${PHP_VERSION}-fpm"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [[ "$PHP_APACHE" == "YES" ]]; then
 | 
			
		||||
    # Optionally disable old Apache PHP module
 | 
			
		||||
  if [[ "$PHP_APACHE" == "YES" ]] && [[ -n "$CURRENT_PHP" ]]; then
 | 
			
		||||
    if [[ -f /etc/apache2/mods-enabled/php${CURRENT_PHP}.load ]]; then
 | 
			
		||||
      $STD a2dismod php${CURRENT_PHP} || true
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if [[ "$PHP_FPM" == "YES" ]]; then
 | 
			
		||||
  if [[ "$PHP_FPM" == "YES" ]] && [[ -n "$CURRENT_PHP" ]]; then
 | 
			
		||||
    $STD systemctl stop php${CURRENT_PHP}-fpm || true
 | 
			
		||||
    $STD systemctl disable php${CURRENT_PHP}-fpm || true
 | 
			
		||||
  fi
 | 
			
		||||
@@ -435,8 +435,7 @@ install_php() {
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Patch all relevant php.ini files
 | 
			
		||||
  local PHP_INI_PATHS=()
 | 
			
		||||
  PHP_INI_PATHS+=("/etc/php/${PHP_VERSION}/cli/php.ini")
 | 
			
		||||
  local PHP_INI_PATHS=("/etc/php/${PHP_VERSION}/cli/php.ini")
 | 
			
		||||
  [[ "$PHP_FPM" == "YES" ]] && PHP_INI_PATHS+=("/etc/php/${PHP_VERSION}/fpm/php.ini")
 | 
			
		||||
  [[ "$PHP_APACHE" == "YES" ]] && PHP_INI_PATHS+=("/etc/php/${PHP_VERSION}/apache2/php.ini")
 | 
			
		||||
 | 
			
		||||
@@ -451,7 +450,6 @@ install_php() {
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# ------------------------------------------------------------------------------
 | 
			
		||||
# Installs or updates Composer globally.
 | 
			
		||||
#
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								tools/headers/add-iptag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								tools/headers/add-iptag
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
    ________      ______           
 | 
			
		||||
   /  _/ __ \    /_  __/___ _____ _
 | 
			
		||||
   / // /_/ /_____/ / / __ `/ __ `/
 | 
			
		||||
 _/ // ____/_____/ / / /_/ / /_/ / 
 | 
			
		||||
/___/_/         /_/  \__,_/\__, /  
 | 
			
		||||
                          /____/   
 | 
			
		||||
@@ -1,6 +0,0 @@
 | 
			
		||||
    __   _  ________   ________      ______           
 | 
			
		||||
   / /  | |/ / ____/  /  _/ __ \    /_  __/___ _____ _
 | 
			
		||||
  / /   |   / /       / // /_/ /_____/ / / __ `/ __ `/
 | 
			
		||||
 / /___/   / /___   _/ // ____/_____/ / / /_/ / /_/ / 
 | 
			
		||||
/_____/_/|_\____/  /___/_/         /_/  \__,_/\__, /  
 | 
			
		||||
                                             /____/   
 | 
			
		||||
@@ -531,302 +531,260 @@ if [[ ! -f /opt/iptag/iptag ]]; then
 | 
			
		||||
  cat <<'EOF' >/opt/iptag/iptag
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
# =============== CONFIGURATION =============== #
 | 
			
		||||
CONFIG_FILE="/opt/iptag/iptag.conf"
 | 
			
		||||
readonly CONFIG_FILE="/opt/iptag/iptag.conf"
 | 
			
		||||
readonly DEFAULT_TAG_FORMAT="full"
 | 
			
		||||
readonly DEFAULT_CHECK_INTERVAL=60
 | 
			
		||||
 | 
			
		||||
# Load the configuration file if it exists
 | 
			
		||||
if [ -f "$CONFIG_FILE" ]; then
 | 
			
		||||
  # shellcheck source=./iptag.conf
 | 
			
		||||
  source "$CONFIG_FILE"
 | 
			
		||||
    # shellcheck source=./iptag.conf
 | 
			
		||||
    source "$CONFIG_FILE"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Convert IP to integer for comparison
 | 
			
		||||
ip_to_int() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  local a b c d
 | 
			
		||||
  IFS=. read -r a b c d <<< "${ip}"
 | 
			
		||||
  echo "$((a << 24 | b << 16 | c << 8 | d))"
 | 
			
		||||
    local ip="$1"
 | 
			
		||||
    local a b c d
 | 
			
		||||
    IFS=. read -r a b c d <<< "${ip}"
 | 
			
		||||
    echo "$((a << 24 | b << 16 | c << 8 | d))"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if IP is in CIDR
 | 
			
		||||
ip_in_cidr() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  local cidr="$2"
 | 
			
		||||
    local ip="$1" cidr="$2"
 | 
			
		||||
    ipcalc -c "$ip" "$cidr" >/dev/null 2>&1 || return 1
 | 
			
		||||
 | 
			
		||||
  # Use ipcalc with the -c option (check), which returns 0 if the IP is in the network
 | 
			
		||||
  if ipcalc -c "$ip" "$cidr" >/dev/null 2>&1; then
 | 
			
		||||
    # Get network address and mask from CIDR
 | 
			
		||||
    local network prefix
 | 
			
		||||
    local network prefix ip_parts net_parts
 | 
			
		||||
    network=$(echo "$cidr" | cut -d/ -f1)
 | 
			
		||||
    prefix=$(echo "$cidr" | cut -d/ -f2)
 | 
			
		||||
    IFS=. read -r -a ip_parts <<< "$ip"
 | 
			
		||||
    IFS=. read -r -a net_parts <<< "$network"
 | 
			
		||||
 | 
			
		||||
    # Check if IP is in the network
 | 
			
		||||
    local ip_a ip_b ip_c ip_d net_a net_b net_c net_d
 | 
			
		||||
    IFS=. read -r ip_a ip_b ip_c ip_d <<< "$ip"
 | 
			
		||||
    IFS=. read -r net_a net_b net_c net_d <<< "$network"
 | 
			
		||||
 | 
			
		||||
    # Check octets match based on prefix length
 | 
			
		||||
    local result=0
 | 
			
		||||
    if (( prefix >= 8 )); then
 | 
			
		||||
      [[ "$ip_a" != "$net_a" ]] && result=1
 | 
			
		||||
    fi
 | 
			
		||||
    if (( prefix >= 16 )); then
 | 
			
		||||
      [[ "$ip_b" != "$net_b" ]] && result=1
 | 
			
		||||
    fi
 | 
			
		||||
    if (( prefix >= 24 )); then
 | 
			
		||||
      [[ "$ip_c" != "$net_c" ]] && result=1
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    return $result
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  return 1
 | 
			
		||||
    case $prefix in
 | 
			
		||||
        8)  [[ "${ip_parts[0]}" == "${net_parts[0]}" ]] ;;
 | 
			
		||||
        16) [[ "${ip_parts[0]}.${ip_parts[1]}" == "${net_parts[0]}.${net_parts[1]}" ]] ;;
 | 
			
		||||
        24) [[ "${ip_parts[0]}.${ip_parts[1]}.${ip_parts[2]}" == "${net_parts[0]}.${net_parts[1]}.${net_parts[2]}" ]] ;;
 | 
			
		||||
        32) [[ "$ip" == "$network" ]] ;;
 | 
			
		||||
        *)  return 1 ;;
 | 
			
		||||
    esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Format IP address according to the configuration
 | 
			
		||||
format_ip_tag() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  local format="${TAG_FORMAT:-full}"
 | 
			
		||||
    local ip="$1"
 | 
			
		||||
    local format="${TAG_FORMAT:-$DEFAULT_TAG_FORMAT}"
 | 
			
		||||
 | 
			
		||||
  case "$format" in
 | 
			
		||||
    "last_octet")
 | 
			
		||||
      echo "${ip##*.}"
 | 
			
		||||
      ;;
 | 
			
		||||
    "last_two_octets")
 | 
			
		||||
      echo "${ip#*.*.}"
 | 
			
		||||
      ;;
 | 
			
		||||
    *)
 | 
			
		||||
      echo "$ip"
 | 
			
		||||
      ;;
 | 
			
		||||
  esac
 | 
			
		||||
    case "$format" in
 | 
			
		||||
        "last_octet")     echo "${ip##*.}" ;;
 | 
			
		||||
        "last_two_octets") echo "${ip#*.*.}" ;;
 | 
			
		||||
        *)               echo "$ip" ;;
 | 
			
		||||
    esac
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if IP is in any CIDRs
 | 
			
		||||
ip_in_cidrs() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  local cidrs="$2"
 | 
			
		||||
 | 
			
		||||
  # Check that cidrs is not empty
 | 
			
		||||
  [[ -z "$cidrs" ]] && return 1
 | 
			
		||||
 | 
			
		||||
  local IFS=' '
 | 
			
		||||
  for cidr in $cidrs; do
 | 
			
		||||
    ip_in_cidr "$ip" "$cidr" && return 0
 | 
			
		||||
  done
 | 
			
		||||
  return 1
 | 
			
		||||
    local ip="$1" cidrs="$2"
 | 
			
		||||
    [[ -z "$cidrs" ]] && return 1
 | 
			
		||||
    local IFS=' '
 | 
			
		||||
    for cidr in $cidrs; do 
 | 
			
		||||
        ip_in_cidr "$ip" "$cidr" && return 0
 | 
			
		||||
    done
 | 
			
		||||
    return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if IP is valid
 | 
			
		||||
is_valid_ipv4() {
 | 
			
		||||
  local ip="$1"
 | 
			
		||||
  [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
 | 
			
		||||
  local IFS='.'
 | 
			
		||||
  read -ra parts <<< "$ip"
 | 
			
		||||
  for part in "${parts[@]}"; do
 | 
			
		||||
    [[ "$part" =~ ^[0-9]+$ ]] && ((part >= 0 && part <= 255)) || return 1
 | 
			
		||||
  done
 | 
			
		||||
  return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
lxc_status_changed() {
 | 
			
		||||
  current_lxc_status=$(pct list 2>/dev/null)
 | 
			
		||||
  if [ "${last_lxc_status}" == "${current_lxc_status}" ]; then
 | 
			
		||||
    return 1
 | 
			
		||||
  else
 | 
			
		||||
    last_lxc_status="${current_lxc_status}"
 | 
			
		||||
    local ip="$1"
 | 
			
		||||
    [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
 | 
			
		||||
    
 | 
			
		||||
    local IFS='.' parts
 | 
			
		||||
    read -ra parts <<< "$ip"
 | 
			
		||||
    for part in "${parts[@]}"; do
 | 
			
		||||
        (( part >= 0 && part <= 255 )) || return 1
 | 
			
		||||
    done
 | 
			
		||||
    return 0
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vm_status_changed() {
 | 
			
		||||
  current_vm_status=$(qm list 2>/dev/null)
 | 
			
		||||
  if [ "${last_vm_status}" == "${current_vm_status}" ]; then
 | 
			
		||||
    return 1
 | 
			
		||||
  else
 | 
			
		||||
    last_vm_status="${current_vm_status}"
 | 
			
		||||
    return 0
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fw_net_interface_changed() {
 | 
			
		||||
  current_net_interface=$(ifconfig | grep "^fw")
 | 
			
		||||
  if [ "${last_net_interface}" == "${current_net_interface}" ]; then
 | 
			
		||||
    return 1
 | 
			
		||||
  else
 | 
			
		||||
    last_net_interface="${current_net_interface}"
 | 
			
		||||
    return 0
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Get VM IPs using MAC addresses and ARP table
 | 
			
		||||
get_vm_ips() {
 | 
			
		||||
  local vmid=$1
 | 
			
		||||
  local ips=""
 | 
			
		||||
    local vmid=$1 ips="" macs found_ip=false
 | 
			
		||||
    qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
 | 
			
		||||
 | 
			
		||||
  # Check if VM is running
 | 
			
		||||
  qm status "$vmid" 2>/dev/null | grep -q "status: running" || return
 | 
			
		||||
    macs=$(qm config "$vmid" 2>/dev/null | grep -E 'net[0-9]+' | grep -oE '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
 | 
			
		||||
    [[ -z "$macs" ]] && return
 | 
			
		||||
 | 
			
		||||
  # Get MAC addresses from VM configuration
 | 
			
		||||
  local macs
 | 
			
		||||
  macs=$(qm config "$vmid" 2>/dev/null | grep -E 'net[0-9]+' | grep -o -E '[a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}')
 | 
			
		||||
    for mac in $macs; do
 | 
			
		||||
        local ip
 | 
			
		||||
        ip=$(arp -an 2>/dev/null | grep -i "$mac" | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}')
 | 
			
		||||
        [[ -n "$ip" ]] && { ips+="$ip "; found_ip=true; }
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
  # Look up IPs from ARP table using MAC addresses
 | 
			
		||||
  for mac in $macs; do
 | 
			
		||||
    local ip
 | 
			
		||||
    ip=$(arp -an 2>/dev/null | grep -i "$mac" | grep -o -E '([0-9]{1,3}\.){3}[0-9]{1,3}')
 | 
			
		||||
    if [ -n "$ip" ]; then
 | 
			
		||||
      ips+="$ip "
 | 
			
		||||
    if ! $found_ip; then
 | 
			
		||||
        local agent_ip
 | 
			
		||||
        agent_ip=$(qm agent "$vmid" network-get-interfaces 2>/dev/null | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' || true)
 | 
			
		||||
        [[ -n "$agent_ip" ]] && ips+="$agent_ip "
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
 | 
			
		||||
  echo "$ips"
 | 
			
		||||
    echo "${ips% }"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Update tags for container or VM
 | 
			
		||||
update_tags() {
 | 
			
		||||
  local type="$1"
 | 
			
		||||
  local vmid="$2"
 | 
			
		||||
  local config_cmd="pct"
 | 
			
		||||
  [[ "$type" == "vm" ]] && config_cmd="qm"
 | 
			
		||||
    local type="$1" vmid="$2" config_cmd="pct"
 | 
			
		||||
    [[ "$type" == "vm" ]] && config_cmd="qm"
 | 
			
		||||
 | 
			
		||||
  # Get current IPs
 | 
			
		||||
  local current_ips_full
 | 
			
		||||
  if [[ "$type" == "lxc" ]]; then
 | 
			
		||||
    # Redirect error output to suppress AppArmor warnings
 | 
			
		||||
    current_ips_full=$(lxc-info -n "${vmid}" -i 2>/dev/null | grep -E "^IP:" | awk '{print $2}')
 | 
			
		||||
  else
 | 
			
		||||
    current_ips_full=$(get_vm_ips "${vmid}")
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Parse current tags and get valid IPs
 | 
			
		||||
  local current_tags=()
 | 
			
		||||
  local next_tags=()
 | 
			
		||||
  mapfile -t current_tags < <($config_cmd config "${vmid}" 2>/dev/null | grep tags | awk '{print $2}' | sed 's/;/\n/g')
 | 
			
		||||
 | 
			
		||||
  for tag in "${current_tags[@]}"; do
 | 
			
		||||
    # Skip tag if it looks like an IP (full or partial)
 | 
			
		||||
    if ! is_valid_ipv4 "${tag}" && ! [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
 | 
			
		||||
      next_tags+=("${tag}")
 | 
			
		||||
    local current_ips_full
 | 
			
		||||
    if [[ "$type" == "lxc" ]]; then
 | 
			
		||||
        current_ips_full=$(lxc-info -n "${vmid}" -i 2>/dev/null | grep -E "^IP:" | awk '{print $2}')
 | 
			
		||||
    else
 | 
			
		||||
        current_ips_full=$(get_vm_ips "${vmid}")
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
    [[ -z "$current_ips_full" ]] && return
 | 
			
		||||
 | 
			
		||||
  # Add valid IPs to tags
 | 
			
		||||
  local added_ips=()
 | 
			
		||||
  local skipped_ips=()
 | 
			
		||||
    local current_tags=() next_tags=() current_ip_tags=()
 | 
			
		||||
    mapfile -t current_tags < <($config_cmd config "${vmid}" 2>/dev/null | grep tags | awk '{print $2}' | sed 's/;/\n/g')
 | 
			
		||||
 | 
			
		||||
  for ip in ${current_ips_full}; do
 | 
			
		||||
    if is_valid_ipv4 "${ip}"; then
 | 
			
		||||
      if ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
 | 
			
		||||
        local formatted_ip=$(format_ip_tag "$ip")
 | 
			
		||||
        next_tags+=("${formatted_ip}")
 | 
			
		||||
        added_ips+=("${formatted_ip}")
 | 
			
		||||
      else
 | 
			
		||||
        skipped_ips+=("${ip}")
 | 
			
		||||
      fi
 | 
			
		||||
    # Separate IP and non-IP tags
 | 
			
		||||
    for tag in "${current_tags[@]}"; do
 | 
			
		||||
        if is_valid_ipv4 "${tag}" || [[ "$tag" =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
 | 
			
		||||
            current_ip_tags+=("${tag}")
 | 
			
		||||
        else
 | 
			
		||||
            next_tags+=("${tag}")
 | 
			
		||||
        fi
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    local formatted_ips=() needs_update=false added_ips=()
 | 
			
		||||
    for ip in ${current_ips_full}; do
 | 
			
		||||
        if is_valid_ipv4 "$ip" && ip_in_cidrs "$ip" "${CIDR_LIST[*]}"; then
 | 
			
		||||
            local formatted_ip=$(format_ip_tag "$ip")
 | 
			
		||||
            formatted_ips+=("$formatted_ip")
 | 
			
		||||
            if [[ ! " ${current_ip_tags[*]} " =~ " ${formatted_ip} " ]]; then
 | 
			
		||||
                needs_update=true
 | 
			
		||||
                added_ips+=("$formatted_ip")
 | 
			
		||||
                next_tags+=("$formatted_ip")
 | 
			
		||||
            fi
 | 
			
		||||
        fi
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    [[ ${#formatted_ips[@]} -eq 0 ]] && return
 | 
			
		||||
 | 
			
		||||
    # Add existing IP tags that are still valid
 | 
			
		||||
    for tag in "${current_ip_tags[@]}"; do
 | 
			
		||||
        if [[ " ${formatted_ips[*]} " =~ " ${tag} " ]]; then
 | 
			
		||||
            if [[ ! " ${next_tags[*]} " =~ " ${tag} " ]]; then
 | 
			
		||||
                next_tags+=("$tag")
 | 
			
		||||
            fi
 | 
			
		||||
        fi
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    if [[ "$needs_update" == true ]]; then
 | 
			
		||||
        echo "${type^} ${vmid}: adding IP tags: ${added_ips[*]}"
 | 
			
		||||
        $config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  # Log only if there are changes
 | 
			
		||||
  if [ ${#added_ips[@]} -gt 0 ]; then
 | 
			
		||||
    echo "${type^} ${vmid}: added IP tags: ${added_ips[*]}"
 | 
			
		||||
  fi
 | 
			
		||||
# Update all instances of specified type
 | 
			
		||||
update_all_tags() {
 | 
			
		||||
    local type="$1" list_cmd="pct" vmids count=0
 | 
			
		||||
    [[ "$type" == "vm" ]] && list_cmd="qm"
 | 
			
		||||
    
 | 
			
		||||
    vmids=$($list_cmd list 2>/dev/null | grep -v VMID | awk '{print $1}')
 | 
			
		||||
    for vmid in $vmids; do ((count++)); done
 | 
			
		||||
    
 | 
			
		||||
    echo "Found ${count} running ${type}s"
 | 
			
		||||
    [[ $count -eq 0 ]] && return
 | 
			
		||||
 | 
			
		||||
  # Update if changed
 | 
			
		||||
  if [[ "$(IFS=';'; echo "${current_tags[*]}")" != "$(IFS=';'; echo "${next_tags[*]}")" ]]; then
 | 
			
		||||
    $config_cmd set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")" &>/dev/null
 | 
			
		||||
  fi
 | 
			
		||||
    for vmid in $vmids; do 
 | 
			
		||||
        update_tags "$type" "$vmid"
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if status changed
 | 
			
		||||
check_status_changed() {
 | 
			
		||||
  local type="$1"
 | 
			
		||||
  local current_status
 | 
			
		||||
 | 
			
		||||
  case "$type" in
 | 
			
		||||
    "lxc")
 | 
			
		||||
      current_status=$(pct list 2>/dev/null | grep -v VMID)
 | 
			
		||||
      [[ "${last_lxc_status}" == "${current_status}" ]] && return 1
 | 
			
		||||
      last_lxc_status="${current_status}"
 | 
			
		||||
      ;;
 | 
			
		||||
    "vm")
 | 
			
		||||
      current_status=$(qm list 2>/dev/null | grep -v VMID)
 | 
			
		||||
      [[ "${last_vm_status}" == "${current_status}" ]] && return 1
 | 
			
		||||
      last_vm_status="${current_status}"
 | 
			
		||||
      ;;
 | 
			
		||||
    "fw")
 | 
			
		||||
      current_status=$(ifconfig 2>/dev/null | grep "^fw")
 | 
			
		||||
      [[ "${last_net_interface}" == "${current_status}" ]] && return 1
 | 
			
		||||
      last_net_interface="${current_status}"
 | 
			
		||||
      ;;
 | 
			
		||||
  esac
 | 
			
		||||
  return 0
 | 
			
		||||
    local type="$1" current
 | 
			
		||||
    case "$type" in
 | 
			
		||||
        "lxc") current=$(pct list 2>/dev/null | grep -v VMID) ;;
 | 
			
		||||
        "vm")  current=$(qm list 2>/dev/null | grep -v VMID) ;;
 | 
			
		||||
        "fw")  current=$(ifconfig 2>/dev/null | grep "^fw") ;;
 | 
			
		||||
    esac
 | 
			
		||||
    local last_var="last_${type}_status"
 | 
			
		||||
    [[ "${!last_var}" == "$current" ]] && return 1
 | 
			
		||||
    eval "$last_var='$current'"
 | 
			
		||||
    return 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Main check function
 | 
			
		||||
check() {
 | 
			
		||||
  current_time=$(date +%s)
 | 
			
		||||
    local current_time changes_detected=false
 | 
			
		||||
    current_time=$(date +%s)
 | 
			
		||||
 | 
			
		||||
  # Check LXC status
 | 
			
		||||
  time_since_last_lxc_status_check=$((current_time - last_lxc_status_check_time))
 | 
			
		||||
  if [[ "${LXC_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
 | 
			
		||||
    && [[ "${time_since_last_lxc_status_check}" -ge "${LXC_STATUS_CHECK_INTERVAL}" ]]; then
 | 
			
		||||
    echo "Checking LXC status..."
 | 
			
		||||
    last_lxc_status_check_time=${current_time}
 | 
			
		||||
    if check_status_changed "lxc"; then
 | 
			
		||||
      update_all_tags "lxc"
 | 
			
		||||
      last_update_lxc_time=${current_time}
 | 
			
		||||
    # Check LXC status
 | 
			
		||||
    local time_since_last_lxc_check=$((current_time - last_lxc_status_check_time))
 | 
			
		||||
    if [[ "${LXC_STATUS_CHECK_INTERVAL:-60}" -gt 0 ]] && \
 | 
			
		||||
       [[ "${time_since_last_lxc_check}" -ge "${LXC_STATUS_CHECK_INTERVAL:-60}" ]]; then
 | 
			
		||||
        echo "Checking LXC status..."
 | 
			
		||||
        last_lxc_status_check_time=${current_time}
 | 
			
		||||
        if check_status_changed "lxc"; then
 | 
			
		||||
            changes_detected=true
 | 
			
		||||
            update_all_tags "lxc"
 | 
			
		||||
            last_update_lxc_time=${current_time}
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Check VM status
 | 
			
		||||
  time_since_last_vm_status_check=$((current_time - last_vm_status_check_time))
 | 
			
		||||
  if [[ "${VM_STATUS_CHECK_INTERVAL}" -gt 0 ]] \
 | 
			
		||||
    && [[ "${time_since_last_vm_status_check}" -ge "${VM_STATUS_CHECK_INTERVAL}" ]]; then
 | 
			
		||||
    echo "Checking VM status..."
 | 
			
		||||
    last_vm_status_check_time=${current_time}
 | 
			
		||||
    if check_status_changed "vm"; then
 | 
			
		||||
      update_all_tags "vm"
 | 
			
		||||
      last_update_vm_time=${current_time}
 | 
			
		||||
    # Check VM status
 | 
			
		||||
    local time_since_last_vm_check=$((current_time - last_vm_status_check_time))
 | 
			
		||||
    if [[ "${VM_STATUS_CHECK_INTERVAL:-60}" -gt 0 ]] && \
 | 
			
		||||
       [[ "${time_since_last_vm_check}" -ge "${VM_STATUS_CHECK_INTERVAL:-60}" ]]; then
 | 
			
		||||
        echo "Checking VM status..."
 | 
			
		||||
        last_vm_status_check_time=${current_time}
 | 
			
		||||
        if check_status_changed "vm"; then
 | 
			
		||||
            changes_detected=true
 | 
			
		||||
            update_all_tags "vm"
 | 
			
		||||
            last_update_vm_time=${current_time}
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Check network interface changes
 | 
			
		||||
  time_since_last_fw_net_interface_check=$((current_time - last_fw_net_interface_check_time))
 | 
			
		||||
  if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL}" -gt 0 ]] \
 | 
			
		||||
    && [[ "${time_since_last_fw_net_interface_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL}" ]]; then
 | 
			
		||||
    echo "Checking network interfaces..."
 | 
			
		||||
    last_fw_net_interface_check_time=${current_time}
 | 
			
		||||
    if check_status_changed "fw"; then
 | 
			
		||||
      update_all_tags "lxc"
 | 
			
		||||
      update_all_tags "vm"
 | 
			
		||||
      last_update_lxc_time=${current_time}
 | 
			
		||||
      last_update_vm_time=${current_time}
 | 
			
		||||
    # Check network interface changes
 | 
			
		||||
    local time_since_last_fw_check=$((current_time - last_fw_net_interface_check_time))
 | 
			
		||||
    if [[ "${FW_NET_INTERFACE_CHECK_INTERVAL:-60}" -gt 0 ]] && \
 | 
			
		||||
       [[ "${time_since_last_fw_check}" -ge "${FW_NET_INTERFACE_CHECK_INTERVAL:-60}" ]]; then
 | 
			
		||||
        echo "Checking network interfaces..."
 | 
			
		||||
        last_fw_net_interface_check_time=${current_time}
 | 
			
		||||
        if check_status_changed "fw"; then
 | 
			
		||||
            changes_detected=true
 | 
			
		||||
            update_all_tags "lxc"
 | 
			
		||||
            update_all_tags "vm"
 | 
			
		||||
            last_update_lxc_time=${current_time}
 | 
			
		||||
            last_update_vm_time=${current_time}
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  # Force update if needed
 | 
			
		||||
  for type in "lxc" "vm"; do
 | 
			
		||||
    local last_update_var="last_update_${type}_time"
 | 
			
		||||
    local time_since_last_update=$((current_time - ${!last_update_var}))
 | 
			
		||||
    if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
 | 
			
		||||
      echo "Force updating ${type} tags..."
 | 
			
		||||
      update_all_tags "$type"
 | 
			
		||||
      eval "${last_update_var}=${current_time}"
 | 
			
		||||
    fi
 | 
			
		||||
  done
 | 
			
		||||
    # Force update if needed
 | 
			
		||||
    for type in "lxc" "vm"; do
 | 
			
		||||
        local last_update_var="last_update_${type}_time"
 | 
			
		||||
        local time_since_last_update=$((current_time - ${!last_update_var}))
 | 
			
		||||
        if [[ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL:-1800} ]]; then
 | 
			
		||||
            echo "Force updating ${type} tags..."
 | 
			
		||||
            changes_detected=true
 | 
			
		||||
            update_all_tags "$type"
 | 
			
		||||
            eval "${last_update_var}=${current_time}"
 | 
			
		||||
        fi
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    $changes_detected || echo "No changes detected in system status"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Initialize time variables
 | 
			
		||||
last_lxc_status_check_time=0
 | 
			
		||||
last_vm_status_check_time=0
 | 
			
		||||
last_fw_net_interface_check_time=0
 | 
			
		||||
last_update_lxc_time=0
 | 
			
		||||
last_update_vm_time=0
 | 
			
		||||
declare -g last_lxc_status="" last_vm_status="" last_fw_status=""
 | 
			
		||||
declare -g last_lxc_status_check_time=0 last_vm_status_check_time=0 last_fw_net_interface_check_time=0
 | 
			
		||||
declare -g last_update_lxc_time=0 last_update_vm_time=0
 | 
			
		||||
 | 
			
		||||
# main: Set the IP tags for all LXC containers and VMs
 | 
			
		||||
# Main loop
 | 
			
		||||
main() {
 | 
			
		||||
  while true; do
 | 
			
		||||
    check
 | 
			
		||||
    sleep "${LOOP_INTERVAL}"
 | 
			
		||||
  done
 | 
			
		||||
    while true; do
 | 
			
		||||
        check
 | 
			
		||||
        sleep "${LOOP_INTERVAL:-$DEFAULT_CHECK_INTERVAL}"
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
main
 | 
			
		||||
@@ -1,357 +0,0 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Copyright (c) 2021-2025 community-scripts ORG
 | 
			
		||||
# Author: MickLesk (Canbiz)
 | 
			
		||||
# License: MIT
 | 
			
		||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
 | 
			
		||||
# Source: https://github.com/gitsang/lxc-iptag
 | 
			
		||||
 | 
			
		||||
function header_info {
 | 
			
		||||
  clear
 | 
			
		||||
  cat <<"EOF"
 | 
			
		||||
    __   _  ________   ________      ______           
 | 
			
		||||
   / /  | |/ / ____/  /  _/ __ \    /_  __/___ _____ _
 | 
			
		||||
  / /   |   / /       / // /_/ /_____/ / / __ `/ __ `/
 | 
			
		||||
 / /___/   / /___   _/ // ____/_____/ / / /_/ / /_/ / 
 | 
			
		||||
/_____/_/|_\____/  /___/_/         /_/  \__,_/\__, /  
 | 
			
		||||
                                             /____/   
 | 
			
		||||
EOF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
clear
 | 
			
		||||
header_info
 | 
			
		||||
APP="LXC 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}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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/lxc-iptag
 | 
			
		||||
msg_ok "Setup IP-Tag Scripts"
 | 
			
		||||
 | 
			
		||||
msg_info "Setup Default Config"
 | 
			
		||||
if [[ ! -f /opt/lxc-iptag/iptag.conf ]]; then
 | 
			
		||||
  cat <<EOF >/opt/lxc-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
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
# Interval settings (in seconds)
 | 
			
		||||
LOOP_INTERVAL=60
 | 
			
		||||
FW_NET_INTERFACE_CHECK_INTERVAL=60
 | 
			
		||||
LXC_STATUS_CHECK_INTERVAL=-1
 | 
			
		||||
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/lxc-iptag/iptag ]]; then
 | 
			
		||||
  cat <<'EOF' >/opt/lxc-iptag/iptag
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
# =============== CONFIGURATION =============== #
 | 
			
		||||
 | 
			
		||||
CONFIG_FILE="/opt/lxc-iptag/iptag.conf"
 | 
			
		||||
 | 
			
		||||
# Load the configuration file if it exists
 | 
			
		||||
if [ -f "$CONFIG_FILE" ]; then
 | 
			
		||||
  # shellcheck source=./lxc-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}"
 | 
			
		||||
 | 
			
		||||
  ip_int=$(ip_to_int "${ip}")
 | 
			
		||||
  netmask_int=$(ip_to_int "$(ipcalc -b "${cidr}" | grep Broadcast | awk '{print $2}')")
 | 
			
		||||
  masked_ip_int=$(( "${ip_int}" & "${netmask_int}" ))
 | 
			
		||||
  [[ ${ip_int} -eq ${masked_ip_int} ]] && return 0 || return 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Check if IP is in any CIDRs
 | 
			
		||||
ip_in_cidrs() {
 | 
			
		||||
  local ip="${1}"
 | 
			
		||||
  local cidrs=()
 | 
			
		||||
 | 
			
		||||
  mapfile -t cidrs < <(echo "${2}" | tr ' ' '\n')
 | 
			
		||||
  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
 | 
			
		||||
  local regex="^([0-9]{1,3}\.){3}[0-9]{1,3}$"
 | 
			
		||||
 | 
			
		||||
  if [[ $ip =~ $regex ]]; then
 | 
			
		||||
    IFS='.' read -r -a parts <<< "$ip"
 | 
			
		||||
    for part in "${parts[@]}"; do
 | 
			
		||||
      if ! [[ $part =~ ^[0-9]+$ ]] || ((part < 0 || part > 255)); then
 | 
			
		||||
        return 1
 | 
			
		||||
      fi
 | 
			
		||||
    done
 | 
			
		||||
    return 0
 | 
			
		||||
  else
 | 
			
		||||
    return 1
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# =============== MAIN =============== #
 | 
			
		||||
 | 
			
		||||
update_lxc_iptags() {
 | 
			
		||||
  vmid_list=$(pct list 2>/dev/null | grep -v VMID | awk '{print $1}')
 | 
			
		||||
  for vmid in ${vmid_list}; do
 | 
			
		||||
    last_tagged_ips=()
 | 
			
		||||
    current_valid_ips=()
 | 
			
		||||
    next_tags=()
 | 
			
		||||
 | 
			
		||||
    # Parse current tags
 | 
			
		||||
    mapfile -t current_tags < <(pct config "${vmid}" | grep tags | awk '{print $2}' | sed 's/;/\n/g')
 | 
			
		||||
    for current_tag in "${current_tags[@]}"; do
 | 
			
		||||
      if is_valid_ipv4 "${current_tag}"; then
 | 
			
		||||
        last_tagged_ips+=("${current_tag}")
 | 
			
		||||
        continue
 | 
			
		||||
      fi
 | 
			
		||||
      next_tags+=("${current_tag}")
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    # Get current IPs
 | 
			
		||||
    current_ips_full=$(lxc-info -n "${vmid}" -i | awk '{print $2}')
 | 
			
		||||
    for ip in ${current_ips_full}; do
 | 
			
		||||
      if is_valid_ipv4 "${ip}" && ip_in_cidrs "${ip}" "${CIDR_LIST[*]}"; then
 | 
			
		||||
        current_valid_ips+=("${ip}")
 | 
			
		||||
        next_tags+=("${ip}")
 | 
			
		||||
      fi
 | 
			
		||||
    done
 | 
			
		||||
 | 
			
		||||
    # Skip if no ip change
 | 
			
		||||
    if [[ "$(echo "${last_tagged_ips[@]}" | tr ' ' '\n' | sort -u)" == "$(echo "${current_valid_ips[@]}" | tr ' ' '\n' | sort -u)" ]]; then
 | 
			
		||||
      echo "Skipping ${vmid} cause ip no changes"
 | 
			
		||||
      continue
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    # Set tags
 | 
			
		||||
    echo "Setting ${vmid} tags from ${current_tags[*]} to ${next_tags[*]}"
 | 
			
		||||
    pct set "${vmid}" -tags "$(IFS=';'; echo "${next_tags[*]}")"
 | 
			
		||||
  done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check() {
 | 
			
		||||
  current_time=$(date +%s)
 | 
			
		||||
 | 
			
		||||
  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 "${STATUS_CHECK_INTERVAL}" ]]; then
 | 
			
		||||
    echo "Checking lxc status..."
 | 
			
		||||
    last_lxc_status_check_time=${current_time}
 | 
			
		||||
    if lxc_status_changed; then
 | 
			
		||||
      update_lxc_iptags
 | 
			
		||||
      last_update_time=${current_time}
 | 
			
		||||
      return
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  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 fw net interface..."
 | 
			
		||||
    last_fw_net_interface_check_time=${current_time}
 | 
			
		||||
    if fw_net_interface_changed; then
 | 
			
		||||
      update_lxc_iptags
 | 
			
		||||
      last_update_time=${current_time}
 | 
			
		||||
      return
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  time_since_last_update=$((current_time - last_update_time))
 | 
			
		||||
  if [ ${time_since_last_update} -ge ${FORCE_UPDATE_INTERVAL} ]; then
 | 
			
		||||
    echo "Force updating lxc iptags..."
 | 
			
		||||
    update_lxc_iptags
 | 
			
		||||
    last_update_time=${current_time}
 | 
			
		||||
    return
 | 
			
		||||
  fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# main: Set the IP tags for all LXC containers
 | 
			
		||||
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/lxc-iptag/iptag
 | 
			
		||||
 | 
			
		||||
msg_info "Creating Service"
 | 
			
		||||
if [[ ! -f /lib/systemd/system/iptag.service ]]; then
 | 
			
		||||
  cat <<EOF >/lib/systemd/system/iptag.service
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=LXC IP-Tag service
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=simple
 | 
			
		||||
ExecStart=/opt/lxc-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"
 | 
			
		||||
							
								
								
									
										227
									
								
								tools/pve/nic-offloading-fix.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								tools/pve/nic-offloading-fix.sh
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,227 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
# Creates a systemd service to disable NIC offloading features for Intel e1000e interfaces
 | 
			
		||||
# Author: rcastley
 | 
			
		||||
# License: MIT
 | 
			
		||||
 | 
			
		||||
YW=$(echo "\033[33m")
 | 
			
		||||
YWB=$'\e[93m'
 | 
			
		||||
BL=$(echo "\033[36m")
 | 
			
		||||
RD=$(echo "\033[01;31m")
 | 
			
		||||
BGN=$(echo "\033[4;92m")
 | 
			
		||||
GN=$(echo "\033[1;92m")
 | 
			
		||||
DGN=$(echo "\033[32m")
 | 
			
		||||
CL=$(echo "\033[m")
 | 
			
		||||
TAB="  "
 | 
			
		||||
CM="${TAB}✔️${TAB}"
 | 
			
		||||
CROSS="${TAB}✖️${TAB}"
 | 
			
		||||
INFO="${TAB}ℹ️${TAB}${CL}"
 | 
			
		||||
WARN="${TAB}⚠️${TAB}${CL}"
 | 
			
		||||
 | 
			
		||||
function header_info {
 | 
			
		||||
  clear
 | 
			
		||||
  cat <<"EOF"
 | 
			
		||||
 | 
			
		||||
    _   ____________   ____  __________                ___                ____  _            __    __
 | 
			
		||||
   / | / /  _/ ____/  / __ \/ __/ __/ /___  ____ _____/ (_)___  ____ _   / __ \(_)________ _/ /_  / /__  _____
 | 
			
		||||
  /  |/ // // /      / / / / /_/ /_/ / __ \/ __ `/ __  / / __ \/ __ `/  / / / / / ___/ __ `/ __ \/ / _ \/ ___/
 | 
			
		||||
 / /|  // // /___   / /_/ / __/ __/ / /_/ / /_/ / /_/ / / / / / /_/ /  / /_/ / (__  ) /_/ / /_/ / /  __/ /
 | 
			
		||||
/_/ |_/___/\____/   \____/_/ /_/ /_/\____/\__,_/\__,_/_/_/ /_/\__, /  /_____/_/____/\__,_/_.___/_/\___/_/
 | 
			
		||||
                                                             /____/
 | 
			
		||||
 | 
			
		||||
EOF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
header_info
 | 
			
		||||
 | 
			
		||||
function msg_info() { echo -e "${INFO} ${YW}${1}...${CL}"; }
 | 
			
		||||
function msg_ok() { echo -e "${CM} ${GN}${1}${CL}"; }
 | 
			
		||||
function msg_error() { echo -e "${CROSS} ${RD}${1}${CL}"; }
 | 
			
		||||
function msg_warn() { echo -e "${WARN} ${YWB}${1}"; }
 | 
			
		||||
 | 
			
		||||
# Check for root privileges
 | 
			
		||||
if [ "$(id -u)" -ne 0 ]; then
 | 
			
		||||
    msg_error "Error: This script must be run as root."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if ! command -v ethtool >/dev/null 2>&1; then
 | 
			
		||||
    msg_info "Installing ethtool"
 | 
			
		||||
    apt-get update &>/dev/null
 | 
			
		||||
    apt-get install -y ethtool &>/dev/null || { msg_error "Failed to install ethtool. Exiting."; exit 1; }
 | 
			
		||||
    msg_ok "ethtool installed successfully"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Get list of network interfaces using Intel e1000e driver
 | 
			
		||||
INTERFACES=()
 | 
			
		||||
COUNT=0
 | 
			
		||||
 | 
			
		||||
msg_info "Searching for Intel e1000e interfaces"
 | 
			
		||||
 | 
			
		||||
for device in /sys/class/net/*; do
 | 
			
		||||
    interface="$(basename "$device")"  # or adjust the rest of the usages below, as mostly you'll use the path anyway
 | 
			
		||||
    # Skip loopback interface and virtual interfaces
 | 
			
		||||
    if [[ "$interface" != "lo" ]] && [[ ! "$interface" =~ ^(tap|fwbr|veth|vmbr|bonding_masters) ]]; then
 | 
			
		||||
        # Check if the interface uses the e1000e driver
 | 
			
		||||
        driver=$(basename $(readlink -f /sys/class/net/$interface/device/driver 2>/dev/null) 2>/dev/null)
 | 
			
		||||
 | 
			
		||||
        if [[ "$driver" == "e1000e" ]]; then
 | 
			
		||||
            # Get MAC address for additional identification
 | 
			
		||||
            mac=$(cat /sys/class/net/$interface/address 2>/dev/null)
 | 
			
		||||
            INTERFACES+=("$interface" "Intel e1000e NIC ($mac)")
 | 
			
		||||
            ((COUNT++))
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Check if any Intel e1000e interfaces were found
 | 
			
		||||
if [ ${#INTERFACES[@]} -eq 0 ]; then
 | 
			
		||||
    whiptail --title "Error" --msgbox "No Intel e1000e network interfaces found!" 10 60
 | 
			
		||||
    msg_error "No Intel e1000e network interfaces found! Exiting."
 | 
			
		||||
    exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
msg_ok "Found ${BL}$COUNT${GN} Intel e1000e interfaces"
 | 
			
		||||
 | 
			
		||||
# Create a checklist for interface selection with all interfaces initially checked
 | 
			
		||||
INTERFACES_CHECKLIST=()
 | 
			
		||||
for ((i=0; i<${#INTERFACES[@]}; i+=2)); do
 | 
			
		||||
    INTERFACES_CHECKLIST+=("${INTERFACES[i]}" "${INTERFACES[i+1]}" "ON")
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Show interface selection checklist
 | 
			
		||||
SELECTED_INTERFACES=$(whiptail --backtitle "Intel e1000e NIC Offloading Disabler" --title "Network Interfaces" \
 | 
			
		||||
                    --separate-output --checklist "Select Intel e1000e network interfaces\n(Space to toggle, Enter to confirm):" 15 80 6 \
 | 
			
		||||
                    "${INTERFACES_CHECKLIST[@]}" 3>&1 1>&2 2>&3)
 | 
			
		||||
 | 
			
		||||
exitstatus=$?
 | 
			
		||||
if [ $exitstatus != 0 ]; then
 | 
			
		||||
    msg_info "User canceled. Exiting."
 | 
			
		||||
    exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Check if any interfaces were selected
 | 
			
		||||
if [ -z "$SELECTED_INTERFACES" ]; then
 | 
			
		||||
    msg_error "No interfaces selected. Exiting."
 | 
			
		||||
    exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Convert the selected interfaces into an array
 | 
			
		||||
readarray -t INTERFACE_ARRAY <<< "$SELECTED_INTERFACES"
 | 
			
		||||
 | 
			
		||||
# Show the number of selected interfaces
 | 
			
		||||
INTERFACE_COUNT=${#INTERFACE_ARRAY[@]}
 | 
			
		||||
 | 
			
		||||
# Print selected interfaces
 | 
			
		||||
for iface in "${INTERFACE_ARRAY[@]}"; do
 | 
			
		||||
    msg_ok "Selected interface: ${BL}$iface${CL}"
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Ask for confirmation with the list of selected interfaces
 | 
			
		||||
CONFIRMATION_MSG="You have selected the following interface(s):\n\n"
 | 
			
		||||
for iface in "${INTERFACE_ARRAY[@]}"; do
 | 
			
		||||
    SPEED=$(cat /sys/class/net/$iface/speed 2>/dev/null)
 | 
			
		||||
    MAC=$(cat /sys/class/net/$iface/address 2>/dev/null)
 | 
			
		||||
    CONFIRMATION_MSG+="- $iface (MAC: $MAC, Speed: ${SPEED}Mbps)\n"
 | 
			
		||||
done
 | 
			
		||||
CONFIRMATION_MSG+="\nThis will create systemd service(s) to disable offloading features.\n\nProceed?"
 | 
			
		||||
 | 
			
		||||
if ! whiptail --backtitle "Intel e1000e NIC Offloading Disabler" --title "Confirmation" \
 | 
			
		||||
    --yesno "$CONFIRMATION_MSG" 20 80; then
 | 
			
		||||
    msg_info "User canceled. Exiting."
 | 
			
		||||
    exit 0
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
# Loop through all selected interfaces and create services for each
 | 
			
		||||
for SELECTED_INTERFACE in "${INTERFACE_ARRAY[@]}"; do
 | 
			
		||||
    # Create service name for this interface
 | 
			
		||||
    SERVICE_NAME="disable-nic-offload-$SELECTED_INTERFACE.service"
 | 
			
		||||
    SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME"
 | 
			
		||||
 | 
			
		||||
    # Create the service file with e1000e specific optimizations
 | 
			
		||||
    msg_info "Creating systemd service for interface: ${BL}$SELECTED_INTERFACE${YW}"
 | 
			
		||||
 | 
			
		||||
    # Start with the common part of the service file
 | 
			
		||||
    cat > "$SERVICE_PATH" << EOF
 | 
			
		||||
[Unit]
 | 
			
		||||
Description=Disable NIC offloading for Intel e1000e interface $SELECTED_INTERFACE
 | 
			
		||||
After=network.target
 | 
			
		||||
 | 
			
		||||
[Service]
 | 
			
		||||
Type=oneshot
 | 
			
		||||
# Disable all offloading features for Intel e1000e
 | 
			
		||||
ExecStart=/sbin/ethtool -K $SELECTED_INTERFACE gso off gro off tso off tx off rx off rxvlan off txvlan off sg off
 | 
			
		||||
RemainAfterExit=true
 | 
			
		||||
 | 
			
		||||
[Install]
 | 
			
		||||
WantedBy=multi-user.target
 | 
			
		||||
EOF
 | 
			
		||||
 | 
			
		||||
    # Check if service file was created successfully
 | 
			
		||||
    if [ ! -f "$SERVICE_PATH" ]; then
 | 
			
		||||
        whiptail --title "Error" --msgbox "Failed to create service file for $SELECTED_INTERFACE!" 10 50
 | 
			
		||||
        msg_error "Failed to create service file for $SELECTED_INTERFACE! Skipping to next interface."
 | 
			
		||||
        continue
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    # Configure this service
 | 
			
		||||
    {
 | 
			
		||||
        echo "25"; sleep 0.2
 | 
			
		||||
        # Reload systemd to recognize the new service
 | 
			
		||||
        systemctl daemon-reload
 | 
			
		||||
        echo "50"; sleep 0.2
 | 
			
		||||
        # Start the service
 | 
			
		||||
        systemctl start "$SERVICE_NAME"
 | 
			
		||||
        echo "75"; sleep 0.2
 | 
			
		||||
        # Enable the service to start on boot
 | 
			
		||||
        systemctl enable "$SERVICE_NAME"
 | 
			
		||||
        echo "100"; sleep 0.2
 | 
			
		||||
    } | whiptail --backtitle "Intel e1000e NIC Offloading Disabler" --gauge "Configuring service for $SELECTED_INTERFACE..." 10 80 0
 | 
			
		||||
 | 
			
		||||
    # Individual service status
 | 
			
		||||
    if systemctl is-active --quiet "$SERVICE_NAME"; then
 | 
			
		||||
        SERVICE_STATUS="Active"
 | 
			
		||||
    else
 | 
			
		||||
        SERVICE_STATUS="Inactive"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if systemctl is-enabled --quiet "$SERVICE_NAME"; then
 | 
			
		||||
        BOOT_STATUS="Enabled"
 | 
			
		||||
    else
 | 
			
		||||
        BOOT_STATUS="Disabled"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    # Show individual service results
 | 
			
		||||
    msg_ok "Service for ${BL}$SELECTED_INTERFACE${GN} created and enabled!"
 | 
			
		||||
    msg_info "${TAB}Service: ${BL}$SERVICE_NAME${YW}"
 | 
			
		||||
    msg_info "${TAB}Status: ${BL}$SERVICE_STATUS${YW}"
 | 
			
		||||
    msg_info "${TAB}Start on boot: ${BL}$BOOT_STATUS${YW}"
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Prepare summary of all interfaces
 | 
			
		||||
SUMMARY_MSG="Services created successfully!\n\n"
 | 
			
		||||
SUMMARY_MSG+="Configured Interfaces:\n"
 | 
			
		||||
 | 
			
		||||
for iface in "${INTERFACE_ARRAY[@]}"; do
 | 
			
		||||
    SERVICE_NAME="disable-nic-offload-$iface.service"
 | 
			
		||||
    if systemctl is-active --quiet "$SERVICE_NAME"; then
 | 
			
		||||
        SVC_STATUS="Active"
 | 
			
		||||
    else
 | 
			
		||||
        SVC_STATUS="Inactive"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    if systemctl is-enabled --quiet "$SERVICE_NAME"; then
 | 
			
		||||
        BOOT_SVC_STATUS="Enabled"
 | 
			
		||||
    else
 | 
			
		||||
        BOOT_SVC_STATUS="Disabled"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    SUMMARY_MSG+="- $iface: $SVC_STATUS, Boot: $BOOT_SVC_STATUS\n"
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
# Show summary results
 | 
			
		||||
whiptail --backtitle "Intel e1000e NIC Offloading Disabler" --title "Success" --msgbox "$SUMMARY_MSG" 20 80
 | 
			
		||||
 | 
			
		||||
msg_ok "Intel e1000e optimization complete for ${#INTERFACE_ARRAY[@]} interface(s)!"
 | 
			
		||||
 | 
			
		||||
exit 0
 | 
			
		||||
@@ -57,6 +57,7 @@ MACADDRESS="${TAB}🔗${TAB}${CL}"
 | 
			
		||||
VLANTAG="${TAB}🏷️${TAB}${CL}"
 | 
			
		||||
CREATING="${TAB}🚀${TAB}${CL}"
 | 
			
		||||
ADVANCED="${TAB}🧩${TAB}${CL}"
 | 
			
		||||
CLOUD="${TAB}☁️${TAB}${CL}"
 | 
			
		||||
 | 
			
		||||
THIN="discard=on,ssd=1,"
 | 
			
		||||
set -e
 | 
			
		||||
@@ -191,6 +192,7 @@ function default_settings() {
 | 
			
		||||
  VLAN=""
 | 
			
		||||
  MTU=""
 | 
			
		||||
  START_VM="yes"
 | 
			
		||||
  CLOUD_INIT="no"
 | 
			
		||||
  METHOD="default"
 | 
			
		||||
  echo -e "${CONTAINERID}${BOLD}${DGN}Virtual Machine ID: ${BGN}${VMID}${CL}"
 | 
			
		||||
  echo -e "${CONTAINERTYPE}${BOLD}${DGN}Machine Type: ${BGN}i440fx${CL}"
 | 
			
		||||
@@ -204,6 +206,7 @@ function default_settings() {
 | 
			
		||||
  echo -e "${MACADDRESS}${BOLD}${DGN}MAC Address: ${BGN}${MAC}${CL}"
 | 
			
		||||
  echo -e "${VLANTAG}${BOLD}${DGN}VLAN: ${BGN}Default${CL}"
 | 
			
		||||
  echo -e "${DEFAULT}${BOLD}${DGN}Interface MTU Size: ${BGN}Default${CL}"
 | 
			
		||||
  echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}"
 | 
			
		||||
  echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
 | 
			
		||||
  echo -e "${CREATING}${BOLD}${DGN}Creating a Debian 12 VM using the above default settings${CL}"
 | 
			
		||||
}
 | 
			
		||||
@@ -373,6 +376,14 @@ function advanced_settings() {
 | 
			
		||||
    exit-script
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "CLOUD-INIT" --yesno "Configure the VM with Cloud-init?" --defaultno 10 58); then
 | 
			
		||||
    echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}yes${CL}"
 | 
			
		||||
    CLOUD_INIT="yes"
 | 
			
		||||
  else
 | 
			
		||||
    echo -e "${CLOUD}${BOLD}${DGN}Configure Cloud-init: ${BGN}no${CL}"
 | 
			
		||||
    CLOUD_INIT="no"
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
  if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "START VIRTUAL MACHINE" --yesno "Start VM when completed?" 10 58); then
 | 
			
		||||
    echo -e "${GATEWAY}${BOLD}${DGN}Start VM when completed: ${BGN}yes${CL}"
 | 
			
		||||
    START_VM="yes"
 | 
			
		||||
@@ -439,7 +450,11 @@ fi
 | 
			
		||||
msg_ok "Using ${CL}${BL}$STORAGE${CL} ${GN}for Storage Location."
 | 
			
		||||
msg_ok "Virtual Machine ID is ${CL}${BL}$VMID${CL}."
 | 
			
		||||
msg_info "Retrieving the URL for the Debian 12 Qcow2 Disk Image"
 | 
			
		||||
URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2
 | 
			
		||||
if [ "$CLOUD_INIT" == "yes" ]; then
 | 
			
		||||
  URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2
 | 
			
		||||
else
 | 
			
		||||
  URL=https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2
 | 
			
		||||
fi
 | 
			
		||||
sleep 2
 | 
			
		||||
msg_ok "${CL}${BL}${URL}${CL}"
 | 
			
		||||
curl -f#SL -o "$(basename "$URL")" "$URL"
 | 
			
		||||
@@ -474,11 +489,20 @@ qm create $VMID -agent 1${MACHINE} -tablet 0 -localtime 1 -bios ovmf${CPU_TYPE}
 | 
			
		||||
  -name $HN -tags community-script -net0 virtio,bridge=$BRG,macaddr=$MAC$VLAN$MTU -onboot 1 -ostype l26 -scsihw virtio-scsi-pci
 | 
			
		||||
pvesm alloc $STORAGE $VMID $DISK0 4M 1>&/dev/null
 | 
			
		||||
qm importdisk $VMID ${FILE} $STORAGE ${DISK_IMPORT:-} 1>&/dev/null
 | 
			
		||||
qm set $VMID \
 | 
			
		||||
  -efidisk0 ${DISK0_REF}${FORMAT} \
 | 
			
		||||
  -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
 | 
			
		||||
  -boot order=scsi0 \
 | 
			
		||||
  -serial0 socket >/dev/null
 | 
			
		||||
if [ "$CLOUD_INIT" == "yes" ]; then
 | 
			
		||||
  qm set $VMID \
 | 
			
		||||
    -efidisk0 ${DISK0_REF}${FORMAT} \
 | 
			
		||||
    -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
 | 
			
		||||
    -scsi1 ${STORAGE}:cloudinit \
 | 
			
		||||
    -boot order=scsi0 \
 | 
			
		||||
    -serial0 socket >/dev/null
 | 
			
		||||
else
 | 
			
		||||
  qm set $VMID \
 | 
			
		||||
    -efidisk0 ${DISK0_REF}${FORMAT} \
 | 
			
		||||
    -scsi0 ${DISK1_REF},${DISK_CACHE}${THIN}size=${DISK_SIZE} \
 | 
			
		||||
    -boot order=scsi0 \
 | 
			
		||||
    -serial0 socket >/dev/null
 | 
			
		||||
fi
 | 
			
		||||
DESCRIPTION=$(
 | 
			
		||||
  cat <<EOF
 | 
			
		||||
<div align='center'>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user