mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2025-07-02 03:57:37 +00:00
Compare commits
57 Commits
intel_nic_
...
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 |
64
CHANGELOG.md
64
CHANGELOG.md
@ -14,8 +14,72 @@ 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
|
||||
|
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
|
||||
|
@ -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 @@
|
||||
__ _ __ ______ __ __
|
||||
/ / (_) /_ ________/_ __/________ _____ _____/ /___ _/ /____
|
||||
/ / / / __ \/ ___/ _ \/ / / ___/ __ `/ __ \/ ___/ / __ `/ __/ _ \
|
||||
/ /___/ / /_/ / / / __/ / / / / /_/ / / / (__ ) / /_/ / /_/ __/
|
||||
/_____/_/_.___/_/ \___/_/ /_/ \__,_/_/ /_/____/_/\__,_/\__/\___/
|
||||
|
@ -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}')
|
||||
|
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}"
|
@ -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"
|
||||
}
|
||||
|
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"
|
||||
}
|
||||
]
|
||||
}
|
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"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,4 +1,199 @@
|
||||
[
|
||||
{
|
||||
"name": "grafana/grafana",
|
||||
"version": "v11.5.6",
|
||||
"date": "2025-06-17T22:00:40Z"
|
||||
},
|
||||
{
|
||||
"name": "jenkinsci/jenkins",
|
||||
"version": "jenkins-2.515",
|
||||
"date": "2025-06-17T19:17:56Z"
|
||||
},
|
||||
{
|
||||
"name": "coder/code-server",
|
||||
"version": "v4.100.3",
|
||||
"date": "2025-06-03T21:06:41Z"
|
||||
},
|
||||
{
|
||||
"name": "HabitRPG/habitica",
|
||||
"version": "v5.36.6",
|
||||
"date": "2025-06-17T18:12:31Z"
|
||||
},
|
||||
{
|
||||
"name": "fallenbagel/jellyseerr",
|
||||
"version": "preview-sort-userlist",
|
||||
"date": "2025-06-17T18:02:25Z"
|
||||
},
|
||||
{
|
||||
"name": "ollama/ollama",
|
||||
"version": "v0.9.2",
|
||||
"date": "2025-06-17T17:51:43Z"
|
||||
},
|
||||
{
|
||||
"name": "msgbyte/tianji",
|
||||
"version": "v1.21.16",
|
||||
"date": "2025-06-17T16:25:53Z"
|
||||
},
|
||||
{
|
||||
"name": "BookStackApp/BookStack",
|
||||
"version": "v25.05.1",
|
||||
"date": "2025-06-17T14:38:04Z"
|
||||
},
|
||||
{
|
||||
"name": "element-hq/synapse",
|
||||
"version": "v1.132.0",
|
||||
"date": "2025-06-17T13:49:30Z"
|
||||
},
|
||||
{
|
||||
"name": "cloudflare/cloudflared",
|
||||
"version": "2025.6.1",
|
||||
"date": "2025-06-17T12:45:39Z"
|
||||
},
|
||||
{
|
||||
"name": "sabnzbd/sabnzbd",
|
||||
"version": "4.5.1",
|
||||
"date": "2025-04-11T09:57:47Z"
|
||||
},
|
||||
{
|
||||
"name": "crowdsecurity/crowdsec",
|
||||
"version": "v1.6.9",
|
||||
"date": "2025-06-17T11:54:50Z"
|
||||
},
|
||||
{
|
||||
"name": "glpi-project/glpi",
|
||||
"version": "10.0.18",
|
||||
"date": "2025-02-12T11:07:02Z"
|
||||
},
|
||||
{
|
||||
"name": "mattermost/mattermost",
|
||||
"version": "v10.9.1",
|
||||
"date": "2025-06-17T07:06:51Z"
|
||||
},
|
||||
{
|
||||
"name": "morpheus65535/bazarr",
|
||||
"version": "v1.5.2",
|
||||
"date": "2025-05-11T16:40:55Z"
|
||||
},
|
||||
{
|
||||
"name": "Jackett/Jackett",
|
||||
"version": "v0.22.2024",
|
||||
"date": "2025-06-17T05:51:55Z"
|
||||
},
|
||||
{
|
||||
"name": "donaldzou/WGDashboard",
|
||||
"version": "v4.2.4",
|
||||
"date": "2025-06-17T05:37:06Z"
|
||||
},
|
||||
{
|
||||
"name": "webmin/webmin",
|
||||
"version": "2.402",
|
||||
"date": "2025-06-17T05:20:42Z"
|
||||
},
|
||||
{
|
||||
"name": "keycloak/keycloak",
|
||||
"version": "26.2.5",
|
||||
"date": "2025-05-28T06:49:43Z"
|
||||
},
|
||||
{
|
||||
"name": "kimai/kimai",
|
||||
"version": "2.36.1",
|
||||
"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",
|
||||
@ -24,11 +219,6 @@
|
||||
"version": "v5.26.2.10099",
|
||||
"date": "2025-06-11T20:10:39Z"
|
||||
},
|
||||
{
|
||||
"name": "Jackett/Jackett",
|
||||
"version": "v0.22.2017",
|
||||
"date": "2025-06-15T05:54:05Z"
|
||||
},
|
||||
{
|
||||
"name": "traccar/traccar",
|
||||
"version": "v6.7.3",
|
||||
@ -49,16 +239,6 @@
|
||||
"version": "v25.0",
|
||||
"date": "2025-05-12T09:12:04Z"
|
||||
},
|
||||
{
|
||||
"name": "bunkerity/bunkerweb",
|
||||
"version": "v1.6.2-rc5",
|
||||
"date": "2025-06-14T16:44:14Z"
|
||||
},
|
||||
{
|
||||
"name": "ollama/ollama",
|
||||
"version": "v0.9.1-rc1",
|
||||
"date": "2025-06-12T21:18:54Z"
|
||||
},
|
||||
{
|
||||
"name": "theonedev/onedev",
|
||||
"version": "v11.11.0",
|
||||
@ -69,26 +249,11 @@
|
||||
"version": "v2.15.0",
|
||||
"date": "2025-06-14T10:48:57Z"
|
||||
},
|
||||
{
|
||||
"name": "firefly-iii/firefly-iii",
|
||||
"version": "v6.2.17",
|
||||
"date": "2025-06-11T12:07:38Z"
|
||||
},
|
||||
{
|
||||
"name": "runtipi/runtipi",
|
||||
"version": "v4.2.1",
|
||||
"date": "2025-06-03T20:04:28Z"
|
||||
},
|
||||
{
|
||||
"name": "FlareSolverr/FlareSolverr",
|
||||
"version": "v3.3.25",
|
||||
"date": "2025-06-14T02:52:44Z"
|
||||
},
|
||||
{
|
||||
"name": "keycloak/keycloak",
|
||||
"version": "26.2.5",
|
||||
"date": "2025-05-28T06:49:43Z"
|
||||
},
|
||||
{
|
||||
"name": "home-assistant/core",
|
||||
"version": "2025.6.1",
|
||||
@ -105,19 +270,9 @@
|
||||
"date": "2025-06-13T15:02:37Z"
|
||||
},
|
||||
{
|
||||
"name": "jenkinsci/jenkins",
|
||||
"version": "jenkins-2.514",
|
||||
"date": "2025-06-10T14:27:57Z"
|
||||
},
|
||||
{
|
||||
"name": "grafana/grafana",
|
||||
"version": "v12.0.1+security-01",
|
||||
"date": "2025-06-13T04:15:18Z"
|
||||
},
|
||||
{
|
||||
"name": "msgbyte/tianji",
|
||||
"version": "v1.21.13",
|
||||
"date": "2025-06-13T04:11:30Z"
|
||||
"name": "wazuh/wazuh",
|
||||
"version": "coverity-w25-4.13.0",
|
||||
"date": "2025-06-13T13:58:23Z"
|
||||
},
|
||||
{
|
||||
"name": "FlowiseAI/Flowise",
|
||||
@ -134,11 +289,6 @@
|
||||
"version": "v2.3.0p34",
|
||||
"date": "2025-06-12T12:15:44Z"
|
||||
},
|
||||
{
|
||||
"name": "n8n-io/n8n",
|
||||
"version": "n8n@1.95.3",
|
||||
"date": "2025-06-03T11:09:42Z"
|
||||
},
|
||||
{
|
||||
"name": "docker/compose",
|
||||
"version": "v2.37.1",
|
||||
@ -154,11 +304,6 @@
|
||||
"version": "v3.3.0",
|
||||
"date": "2025-06-12T06:54:48Z"
|
||||
},
|
||||
{
|
||||
"name": "morpheus65535/bazarr",
|
||||
"version": "v1.5.2",
|
||||
"date": "2025-05-11T16:40:55Z"
|
||||
},
|
||||
{
|
||||
"name": "documenso/documenso",
|
||||
"version": "v1.12.0-rc.4",
|
||||
@ -169,51 +314,21 @@
|
||||
"version": "2.0.0-alpha-4",
|
||||
"date": "2025-05-14T05:01:45Z"
|
||||
},
|
||||
{
|
||||
"name": "esphome/esphome",
|
||||
"version": "2025.5.2",
|
||||
"date": "2025-06-03T08:45:14Z"
|
||||
},
|
||||
{
|
||||
"name": "MediaBrowser/Emby.Releases",
|
||||
"version": "4.8.11.0",
|
||||
"date": "2025-03-10T06:39:11Z"
|
||||
},
|
||||
{
|
||||
"name": "crowdsecurity/crowdsec",
|
||||
"version": "v1.6.8",
|
||||
"date": "2025-03-25T13:33:10Z"
|
||||
},
|
||||
{
|
||||
"name": "dgtlmoon/changedetection.io",
|
||||
"version": "0.50.3",
|
||||
"date": "2025-06-11T15:19:52Z"
|
||||
},
|
||||
{
|
||||
"name": "kimai/kimai",
|
||||
"version": "2.36.0",
|
||||
"date": "2025-06-11T12:31:07Z"
|
||||
},
|
||||
{
|
||||
"name": "cloudflare/cloudflared",
|
||||
"version": "2025.6.0",
|
||||
"date": "2025-06-11T11:13:21Z"
|
||||
},
|
||||
{
|
||||
"name": "autobrr/autobrr",
|
||||
"version": "v1.63.1",
|
||||
"date": "2025-06-11T11:05:42Z"
|
||||
},
|
||||
{
|
||||
"name": "fallenbagel/jellyseerr",
|
||||
"version": "preview-forceipv4-axios",
|
||||
"date": "2025-06-11T09:16:40Z"
|
||||
},
|
||||
{
|
||||
"name": "wazuh/wazuh",
|
||||
"version": "coverity-w24-4.13.0",
|
||||
"date": "2025-06-11T04:04:55Z"
|
||||
},
|
||||
{
|
||||
"name": "zabbix/zabbix",
|
||||
"version": "7.2.8rc1",
|
||||
@ -224,16 +339,6 @@
|
||||
"version": "v0.15.0-rc2",
|
||||
"date": "2025-06-11T04:29:22Z"
|
||||
},
|
||||
{
|
||||
"name": "mattermost/mattermost",
|
||||
"version": "server/public/v0.1.15",
|
||||
"date": "2025-06-11T03:56:25Z"
|
||||
},
|
||||
{
|
||||
"name": "emqx/emqx",
|
||||
"version": "e5.10.0",
|
||||
"date": "2025-06-10T16:03:18Z"
|
||||
},
|
||||
{
|
||||
"name": "node-red/node-red",
|
||||
"version": "4.1.0-beta.1",
|
||||
@ -244,21 +349,6 @@
|
||||
"version": "v0.107.62",
|
||||
"date": "2025-05-27T12:10:19Z"
|
||||
},
|
||||
{
|
||||
"name": "open-webui/open-webui",
|
||||
"version": "v0.6.14",
|
||||
"date": "2025-06-10T14:18:04Z"
|
||||
},
|
||||
{
|
||||
"name": "element-hq/synapse",
|
||||
"version": "v1.131.0",
|
||||
"date": "2025-06-03T14:13:00Z"
|
||||
},
|
||||
{
|
||||
"name": "Graylog2/graylog2-server",
|
||||
"version": "6.3.0-beta.5",
|
||||
"date": "2025-06-10T11:19:42Z"
|
||||
},
|
||||
{
|
||||
"name": "OctoPrint/OctoPrint",
|
||||
"version": "1.11.2",
|
||||
@ -314,11 +404,6 @@
|
||||
"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",
|
||||
@ -334,11 +419,6 @@
|
||||
"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": "Forceu/Gokapi",
|
||||
"version": "v2.0.1",
|
||||
@ -349,11 +429,6 @@
|
||||
"version": "3.2.0",
|
||||
"date": "2025-06-07T21:33:22Z"
|
||||
},
|
||||
{
|
||||
"name": "jellyfin/jellyfin",
|
||||
"version": "v10.10.7",
|
||||
"date": "2025-04-05T19:14:59Z"
|
||||
},
|
||||
{
|
||||
"name": "jordan-dalby/ByteStash",
|
||||
"version": "v1.5.8",
|
||||
@ -364,21 +439,11 @@
|
||||
"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",
|
||||
@ -389,11 +454,6 @@
|
||||
"version": "v4.1.2",
|
||||
"date": "2025-06-06T17:44:58Z"
|
||||
},
|
||||
{
|
||||
"name": "goauthentik/authentik",
|
||||
"version": "version/2025.6.1",
|
||||
"date": "2025-06-06T15:28:21Z"
|
||||
},
|
||||
{
|
||||
"name": "ioBroker/ioBroker",
|
||||
"version": "2025-05-31",
|
||||
@ -434,11 +494,6 @@
|
||||
"version": "mariadb-11.8.2",
|
||||
"date": "2025-06-04T13:35:16Z"
|
||||
},
|
||||
{
|
||||
"name": "donaldzou/WGDashboard",
|
||||
"version": "v4.2.3",
|
||||
"date": "2025-05-07T15:35:04Z"
|
||||
},
|
||||
{
|
||||
"name": "actualbudget/actual",
|
||||
"version": "v25.6.1",
|
||||
@ -454,26 +509,11 @@
|
||||
"version": "340",
|
||||
"date": "2025-06-04T16:41:44Z"
|
||||
},
|
||||
{
|
||||
"name": "glpi-project/glpi",
|
||||
"version": "10.0.18",
|
||||
"date": "2025-02-12T11:07:02Z"
|
||||
},
|
||||
{
|
||||
"name": "louislam/uptime-kuma",
|
||||
"version": "2.0.0-beta.2-temp",
|
||||
"date": "2025-03-28T08:45:58Z"
|
||||
},
|
||||
{
|
||||
"name": "webmin/webmin",
|
||||
"version": "2.401",
|
||||
"date": "2025-06-04T02:53:03Z"
|
||||
},
|
||||
{
|
||||
"name": "coder/code-server",
|
||||
"version": "v4.100.3",
|
||||
"date": "2025-06-03T21:06:41Z"
|
||||
},
|
||||
{
|
||||
"name": "influxdata/influxdb",
|
||||
"version": "v1.12.1rc3",
|
||||
@ -489,11 +529,6 @@
|
||||
"version": "1.26.3",
|
||||
"date": "2025-06-02T22:00:14Z"
|
||||
},
|
||||
{
|
||||
"name": "grokability/snipe-it",
|
||||
"version": "v8.1.15",
|
||||
"date": "2025-06-02T17:38:24Z"
|
||||
},
|
||||
{
|
||||
"name": "inventree/InvenTree",
|
||||
"version": "0.17.13",
|
||||
@ -519,11 +554,6 @@
|
||||
"version": "v3.4.1",
|
||||
"date": "2025-05-31T13:45:40Z"
|
||||
},
|
||||
{
|
||||
"name": "BookStackApp/BookStack",
|
||||
"version": "v25.05",
|
||||
"date": "2025-05-31T13:36:23Z"
|
||||
},
|
||||
{
|
||||
"name": "blakeblackshear/frigate",
|
||||
"version": "v0.14.1",
|
||||
@ -549,11 +579,6 @@
|
||||
"version": "v0.56.1",
|
||||
"date": "2025-05-29T19:09:16Z"
|
||||
},
|
||||
{
|
||||
"name": "HabitRPG/habitica",
|
||||
"version": "v5.36.5",
|
||||
"date": "2025-05-29T17:06:01Z"
|
||||
},
|
||||
{
|
||||
"name": "readeck/readeck",
|
||||
"version": "0.19.2",
|
||||
@ -644,21 +669,11 @@
|
||||
"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",
|
||||
@ -669,11 +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": "Part-DB/Part-DB-server",
|
||||
"version": "v1.17.1",
|
||||
@ -904,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",
|
||||
@ -924,11 +929,6 @@
|
||||
"version": "v5.5.2",
|
||||
"date": "2025-04-11T22:00:06Z"
|
||||
},
|
||||
{
|
||||
"name": "sabnzbd/sabnzbd",
|
||||
"version": "4.5.1",
|
||||
"date": "2025-04-11T09:57:47Z"
|
||||
},
|
||||
{
|
||||
"name": "thomiceli/opengist",
|
||||
"version": "v1.10.0",
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
@ -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) }')
|
||||
|
@ -380,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
|
||||
@ -436,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")
|
||||
|
||||
@ -452,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