Compare commits

...

46 Commits

Author SHA1 Message Date
2e2db6603e Revert "[API] update build.func (#1880)" (#1883)
This reverts commit 72335f2c4e.
2025-01-30 20:46:19 +01:00
72335f2c4e [API] update build.func (#1880) 2025-01-30 20:00:20 +01:00
a359ffc211 Update CHANGELOG.md (#1879)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-30 19:51:13 +01:00
cd4bcefa58 [API] Update build.func to set the status message correct (#1878)
* Testing

* Testing

* update /data/page.tsx

* Update page.tsx
2025-01-30 18:19:05 +01:00
a0eb173824 Update CHANGELOG.md (#1875)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-30 17:14:04 +01:00
3d42ecb152 Update /data/page.tsx (#1876) 2025-01-30 14:47:22 +01:00
0642c7e2c8 [API] Update build.func: add function to see if a script failed or not (#1874)
* [API] Update build.func: add function to see if a script failed or not

* [API] Update build.func: add function to see if a script failed or not
2025-01-30 14:37:05 +01:00
af04e933e3 Update CHANGELOG.md (#1872)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-30 14:05:42 +01:00
0dfc513a27 Update alpine-it-tools.json 2025-01-30 13:55:53 +01:00
26433efcd8 Rename it-tools.json to alpine-it-tools.json 2025-01-30 13:50:47 +01:00
343de50ef8 fix breaking ui 2025-01-30 13:48:36 +01:00
a38e9070ef add popup, table & chart 2025-01-30 13:43:24 +01:00
e2b548a7c3 update chart 2025-01-30 13:38:25 +01:00
737b18dea5 Update ApplicationChart.tsx 2025-01-30 13:30:44 +01:00
6b777a03c0 fix deps 2025-01-30 13:25:02 +01:00
d9b4778360 Update page.tsx 2025-01-30 13:21:49 +01:00
7299b77359 Create ApplicationChart.tsx 2025-01-30 13:18:24 +01:00
d3882b6818 add chart.js 2025-01-30 13:11:05 +01:00
2ef0cd0f89 Update mattermost-install.sh 2025-01-30 11:48:12 +01:00
f2eb24d527 add $STD 2025-01-30 11:43:26 +01:00
f520607d85 Update CHANGELOG.md (#1864)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-30 11:37:46 +01:00
1270d87bf8 Update .app files (#1870)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2025-01-30 11:35:35 +01:00
7f2481ea12 New Script: Mattermost (#1856)
* Create mattermost.sh, mattermost-install.sh, and mattermost.json

* Change paths in build.func install.func and mattermost.sh

This commit is for testing purposes and will be reverted before creating the pull request.

* Fixed OS in mattermost.sh and mattermost.json

* Change paths in all files

Points all files to my fork for testing.

* Added tags and fixed missing variable definition

* Fixed mattermost-install.sh

* Fixed sed command in mattermost-install.sh

* Fixed sed command in mattermost-install.sh

* Fixed broken config in mattermost-install.sh

* Revert "Change paths in all files"

This reverts commit 2f93e39233.

* Revert "Change paths in build.func install.func and mattermost.sh"

This reverts commit 084c71fbdc.

* Fixed date in mattermost.json

* Update install/mattermost-install.sh

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

* Update mattermost.json

---------

Co-authored-by: CanbiZ <47820557+MickLesk@users.noreply.github.com>
Co-authored-by: Michel Roegl-Brunner <73236783+michelroegl-brunner@users.noreply.github.com>
2025-01-30 11:34:27 +01:00
05f114ed64 Fix IT-Tools Website Entry (#1869) 2025-01-30 11:33:59 +01:00
6924a6fea4 Optimize PVE Manager Version-Check (#1866) 2025-01-30 11:26:30 +01:00
bb553ae48c Update .app files (#1865)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2025-01-30 11:02:13 +01:00
cbb18668dd initial for PR (#1862) 2025-01-30 10:55:09 +01:00
c7418171b4 Update CHANGELOG.md (#1863)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-30 08:38:23 +01:00
ed2ead9ef2 fix: remove rounded styles from command primitive (#1840) 2025-01-30 08:35:10 +01:00
e51c121af2 Update CHANGELOG.md (#1852)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-29 21:11:09 +01:00
8c4e97d6cb Update build.func (#1851) 2025-01-29 20:00:02 +01:00
1093fef23c Update CHANGELOG.md (#1850)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-29 19:49:37 +01:00
6fa540f0da Patch http Url in build.func and /data/page.tsx (#1849) 2025-01-29 19:37:45 +01:00
ca7fb9b929 Update CHANGELOG.md (#1848)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-29 19:08:37 +01:00
139f84a934 [Frontend] Add /data to show API results (#1841)
* [Frontend] Add /data to show API results

* [Frontend] Add /data to show API results

* update page.tsx

* update page.tsx

* update page.tsx

* update page.tsx
2025-01-29 19:07:31 +01:00
8bc50f4d71 Update CHANGELOG.md (#1847)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-29 18:43:59 +01:00
3fa4cf6e07 Update .app files (#1846)
Co-authored-by: GitHub Actions <github-actions[bot]@users.noreply.github.com>
2025-01-29 18:43:09 +01:00
63e3619b68 New Script: Prometheus Proxmox VE Exporter (#1805)
* New Script: Prometheus Proxmox VE Exporter

See https://github.com/prometheus-pve/prometheus-pve-exporter

* Fix formatting of config file output after installation

* Prometheus Proxmox VE Exporter: Set category 1 for Website

* Removed blank lines

* Remove `python3-dev`, as it was commented out

* Prometheus Proxmox VE Exporter: Move configuration under /opt

* Prometheus Proxmox VE Exporter: Add logo

* Change `msg_info "Updating Python3"` to `msg_info "Setup Python3"`

* Removed empty line

* Add note about Proxmox credentials into the website

* Temp: Replace GitHub URLs to test my fork

* Set correct `APP="Prometheus-PVE-Exporter"`

* Add `--root-user-action=ignore` to pip call (as root)

* Revert "Temp: Replace GitHub URLs to test my fork"

This reverts commit 2308d48376.
2025-01-29 18:41:44 +01:00
054b569e33 edit 2025-01-29 17:21:16 +01:00
cd740e52f4 Update CHANGELOG.md (#1844)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-29 15:16:47 +01:00
37c7205978 Update clean-orphaned-lvm.json 2025-01-29 15:10:37 +01:00
eb9633215c Update clean-orphaned-lvm.json (#1843) 2025-01-29 15:10:12 +01:00
85a6819760 Update CHANGELOG.md (#1839)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-29 15:08:18 +01:00
20d6162ac1 New Script: Clean Orphaned LVM (#1838)
* New Script: Clean Orphaned LVM

* Rename clean_orphaned_lvm.json to clean-orphaned-lvm.json

* Rename clean_orphaned_lvm.sh to clean-orphaned-lvm.sh
2025-01-29 14:42:28 +01:00
0dff2b3363 Update CHANGELOG.md (#1837)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-29 14:27:31 +01:00
c799e67ea5 [Diagnostic] Introduced optional lxc install diagnostics via API call (#1801)
* Update build.func

* Update build.func

* Update build.func

* Update build.func

* Update build.func

* update build.func

* update build.func

* update build.func

* update build.func

* update build.func

* update build.func

* update build.func

* update build.func
2025-01-29 14:26:23 +01:00
36 changed files with 1433 additions and 100 deletions

1
.github/FUNDING.yml vendored
View File

@ -1 +1,2 @@
ko_fi: community_scripts
github: community_scripts

View File

@ -17,6 +17,50 @@ All LXC instances created using this repository come pre-installed with Midnight
Do not break established syntax in this file, as it is automatically updated by a Github Workflow
## 2025-01-30
### Changed
### ✨ New Scripts
- New Script: IT-Tools [@nicedevil007](https://github.com/nicedevil007) ([#1862](https://github.com/community-scripts/ProxmoxVE/pull/1862))
- New Script: Mattermost [@Dracentis](https://github.com/Dracentis) ([#1856](https://github.com/community-scripts/ProxmoxVE/pull/1856))
### 🚀 Updated Scripts
- Optimize PVE Manager Version-Check [@MickLesk](https://github.com/MickLesk) ([#1866](https://github.com/community-scripts/ProxmoxVE/pull/1866))
### 🌐 Website
- [API] Update build.func to set the status message correct [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1878](https://github.com/community-scripts/ProxmoxVE/pull/1878))
- [Website] Update /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1876](https://github.com/community-scripts/ProxmoxVE/pull/1876))
- Fix IT-Tools Website Entry (Default | Alpine) [@MickLesk](https://github.com/MickLesk) ([#1869](https://github.com/community-scripts/ProxmoxVE/pull/1869))
- fix: remove rounded styles from command primitive [@steveiliop56](https://github.com/steveiliop56) ([#1840](https://github.com/community-scripts/ProxmoxVE/pull/1840))
### 🧰 Maintenance
- [API] Update build.func: add function to see if a script failed or not [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1874](https://github.com/community-scripts/ProxmoxVE/pull/1874))
## 2025-01-29
### Changed
### ✨ New Scripts
- New Script: Prometheus Proxmox VE Exporter [@andygrunwald](https://github.com/andygrunwald) ([#1805](https://github.com/community-scripts/ProxmoxVE/pull/1805))
- New Script: Clean Orphaned LVM [@MickLesk](https://github.com/MickLesk) ([#1838](https://github.com/community-scripts/ProxmoxVE/pull/1838))
### 🌐 Website
- Patch http Url to https in build.func and /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1849](https://github.com/community-scripts/ProxmoxVE/pull/1849))
- [Frontend] Add /data to show API results [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1841](https://github.com/community-scripts/ProxmoxVE/pull/1841))
- Update clean-orphaned-lvm.json [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1843](https://github.com/community-scripts/ProxmoxVE/pull/1843))
### 🧰 Maintenance
- Update build.func [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1851](https://github.com/community-scripts/ProxmoxVE/pull/1851))
- [Diagnostic] Introduced optional lxc install diagnostics via API call [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1801](https://github.com/community-scripts/ProxmoxVE/pull/1801))
## 2025-01-28
### Changed

62
ct/alpine-it-tools.sh Normal file
View File

@ -0,0 +1,62 @@
#!/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: nicedevil007 (NiceDevil)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# App Default Values
APP="Alpine-IT-Tools"
var_tags="alpine;development"
var_cpu="1"
var_ram="256"
var_disk="0.2"
var_os="alpine"
var_version="3.21"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -d /usr/share/nginx/html ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -s https://api.github.com/repos/CorentinTh/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4)
if [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]] || [[ ! -f /opt/${APP}_version.txt ]]; then
DOWNLOAD_URL="https://github.com/CorentinTh/it-tools/releases/download/${RELEASE}/it-tools-${RELEASE#v}.zip"
msg_info "Updating ${APP} LXC"
curl -fsSL -o it-tools.zip "$DOWNLOAD_URL"
mkdir -p /usr/share/nginx/html
rm -rf /usr/share/nginx/html/*
unzip -q it-tools.zip -d /tmp/it-tools
cp -r /tmp/it-tools/dist/* /usr/share/nginx/html
rm -rf /tmp/it-tools
rm -f it-tools.zip
msg_ok "Updated Successfully"
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 IP:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"

View File

@ -0,0 +1,6 @@
___ __ _ __________ ______ __
/ | / /___ (_)___ ___ / _/_ __/ /_ __/___ ____ / /____
/ /| | / / __ \/ / __ \/ _ \______ / / / /_____/ / / __ \/ __ \/ / ___/
/ ___ |/ / /_/ / / / / / __/_____// / / /_____/ / / /_/ / /_/ / (__ )
/_/ |_/_/ .___/_/_/ /_/\___/ /___/ /_/ /_/ \____/\____/_/____/
/_/

6
ct/headers/mattermost Normal file
View File

@ -0,0 +1,6 @@
__ ___ __ __ __
/ |/ /___ _/ /_/ /____ _________ ___ ____ _____/ /_
/ /|_/ / __ `/ __/ __/ _ \/ ___/ __ `__ \/ __ \/ ___/ __/
/ / / / /_/ / /_/ /_/ __/ / / / / / / / /_/ (__ ) /_
/_/ /_/\__,_/\__/\__/\___/_/ /_/ /_/ /_/\____/____/\__/

View File

@ -0,0 +1,12 @@
____ __ __ ____
/ __ \_________ ____ ___ ___ / /_/ /_ ___ __ _______ / __ \
/ /_/ / ___/ __ \/ __ `__ \/ _ \/ __/ __ \/ _ \/ / / / ___/_____/ /_/ /
/ ____/ / / /_/ / / / / / / __/ /_/ / / / __/ /_/ (__ )_____/ ____/
/_/ /_/ \____/_/ /_/ /_/\___/\__/_/ /_/\___/\__,_/____/ /_/
_ ________ ______ __
| | / / ____/ / ____/ ______ ____ _____/ /____ _____
| | / / __/______/ __/ | |/_/ __ \/ __ \/ ___/ __/ _ \/ ___/
| |/ / /__/_____/ /____> </ /_/ / /_/ / / / /_/ __/ /
|___/_____/ /_____/_/|_/ .___/\____/_/ \__/\___/_/
/_/

49
ct/mattermost.sh Normal file
View File

@ -0,0 +1,49 @@
#!/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: Kaedon Cleland-Host (dracentis)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://mattermost.com/
# App Default Values
APP="Mattermost"
var_tags="collaboration"
var_cpu="1"
var_ram="2048"
var_disk="8"
var_os="ubuntu"
var_version="24.04"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/apt/sources.list.d/mattermost.list ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Updating ${APP} LXC"
apt-get update &>/dev/null
apt-get -y upgrade &>/dev/null
msg_ok "Updated Successfully"
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}:8065${CL}"

View File

@ -0,0 +1,57 @@
#!/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: Andy Grunwald (andygrunwald)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/prometheus-pve/prometheus-pve-exporter
# App Default Values
APP="Prometheus-PVE-Exporter"
var_tags="monitoring"
var_cpu="1"
var_ram="1024"
var_disk="2"
var_os="debian"
var_version="12"
var_unprivileged="1"
# App Output & Base Settings
header_info "$APP"
base_settings
# Core
variables
color
catch_errors
function update_script() {
header_info
check_container_storage
check_container_resources
if [[ ! -f /etc/systemd/system/prometheus-pve-exporter.service ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
msg_info "Stopping ${APP}"
systemctl stop prometheus-pve-exporter
msg_ok "Stopped ${APP}"
msg_info "Updating ${APP}"
pip install prometheus-pve-exporter --upgrade --root-user-action=ignore &>/dev/null
msg_ok "Updated ${APP}"
msg_info "Starting ${APP}"
systemctl start prometheus-pve-exporter
msg_ok "Started ${APP}"
msg_ok "Updated Successfully"
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}:9221${CL}"

View File

@ -23,6 +23,8 @@
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@vercel/analytics": "^1.2.2",
"chart.js": "^4.4.1",
"chartjs-plugin-datalabels": "^2.2.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
@ -37,7 +39,9 @@
"pocketbase": "^0.21.4",
"prettier-plugin-organize-imports": "^4.1.0",
"react": "19.0.0-rc-02c0e824-20241028",
"react-chartjs-2": "^5.3.0",
"react-code-blocks": "^0.1.6",
"react-datepicker": "^7.6.0",
"react-day-picker": "8.10.1",
"react-dom": "19.0.0-rc-02c0e824-20241028",
"react-icons": "^5.1.0",
@ -1083,9 +1087,9 @@
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.8",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==",
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
"integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
"license": "MIT"
},
"node_modules/@humanfs/core": {
@ -1572,6 +1576,12 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@kurkle/color": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
"license": "MIT"
},
"node_modules/@next/env": {
"version": "15.1.3",
"resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.3.tgz",
@ -3194,7 +3204,7 @@
"version": "19.0.0-rc.1",
"resolved": "https://registry.npmjs.org/types-react/-/types-react-19.0.0-rc.1.tgz",
"integrity": "sha512-RshndUfqTW6K3STLPis8BtAYCGOkMbtvYsi90gmVNDZBXUyUc5juf2PE9LfS/JmOlUIRO8cWTS/1MTnmhjDqyQ==",
"devOptional": true,
"dev": true,
"dependencies": {
"csstype": "^3.0.2"
}
@ -3204,7 +3214,7 @@
"version": "19.0.0-rc.1",
"resolved": "https://registry.npmjs.org/types-react-dom/-/types-react-dom-19.0.0-rc.1.tgz",
"integrity": "sha512-VSLZJl8VXCD0fAWp7DUTFUDCcZ8DVXOQmjhJMD03odgeFmu14ZQJHCXeETm3BEAhJqfgJaFkLnGkQv88sRx0fQ==",
"devOptional": true,
"dev": true,
"dependencies": {
"@types/react": "*"
}
@ -4152,6 +4162,27 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/chart.js": {
"version": "4.4.7",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz",
"integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==",
"license": "MIT",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
"engines": {
"pnpm": ">=8"
}
},
"node_modules/chartjs-plugin-datalabels": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/chartjs-plugin-datalabels/-/chartjs-plugin-datalabels-2.2.0.tgz",
"integrity": "sha512-14ZU30lH7n89oq+A4bWaJPnAG8a7ZTk7dKf48YAzMvJjQtjrgg5Dpk9f+LbjCF6bpx3RAGTeL13IXpKQYyRvlw==",
"license": "MIT",
"peerDependencies": {
"chart.js": ">=3.0.0"
}
},
"node_modules/check-error": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
@ -7774,6 +7805,7 @@
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
@ -7999,6 +8031,16 @@
"node": ">=0.10.0"
}
},
"node_modules/react-chartjs-2": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.3.0.tgz",
"integrity": "sha512-UfZZFnDsERI3c3CZGxzvNJd02SHjaSJ8kgW1djn65H1KK8rehwTjyrRKOG3VTMG8wtHZ5rgAO5oTHtHi9GCCmw==",
"license": "MIT",
"peerDependencies": {
"chart.js": "^4.1.1",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-code-blocks": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/react-code-blocks/-/react-code-blocks-0.1.6.tgz",
@ -8017,6 +8059,46 @@
"react": ">=16"
}
},
"node_modules/react-datepicker": {
"version": "7.6.0",
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.6.0.tgz",
"integrity": "sha512-9cQH6Z/qa4LrGhzdc3XoHbhrxNcMi9MKjZmYgF/1MNNaJwvdSjv3Xd+jjvrEEbKEf71ZgCA3n7fQbdwd70qCRw==",
"license": "MIT",
"dependencies": {
"@floating-ui/react": "^0.27.0",
"clsx": "^2.1.1",
"date-fns": "^3.6.0"
},
"peerDependencies": {
"react": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc",
"react-dom": "^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc"
}
},
"node_modules/react-datepicker/node_modules/@floating-ui/react": {
"version": "0.27.3",
"resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.3.tgz",
"integrity": "sha512-CLHnes3ixIFFKVQDdICjel8muhFLOBdQH7fgtHNPY8UbCNqbeKZ262G7K66lGQOUQWWnYocf7ZbUsLJgGfsLHg==",
"license": "MIT",
"dependencies": {
"@floating-ui/react-dom": "^2.1.2",
"@floating-ui/utils": "^0.2.9",
"tabbable": "^6.0.0"
},
"peerDependencies": {
"react": ">=17.0.0",
"react-dom": ">=17.0.0"
}
},
"node_modules/react-datepicker/node_modules/date-fns": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
"license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/react-day-picker": {
"version": "8.10.1",
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
@ -9055,6 +9137,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/tabbable": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
"license": "MIT"
},
"node_modules/tailwind-merge": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
@ -9420,6 +9508,7 @@
"version": "5.6.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

View File

@ -34,6 +34,8 @@
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@vercel/analytics": "^1.2.2",
"chart.js": "^4.4.1",
"chartjs-plugin-datalabels": "^2.2.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"cmdk": "^1.0.0",
@ -48,7 +50,9 @@
"pocketbase": "^0.21.4",
"prettier-plugin-organize-imports": "^4.1.0",
"react": "19.0.0-rc-02c0e824-20241028",
"react-chartjs-2": "^5.3.0",
"react-code-blocks": "^0.1.6",
"react-datepicker": "^7.6.0",
"react-day-picker": "8.10.1",
"react-dom": "19.0.0-rc-02c0e824-20241028",
"react-icons": "^5.1.0",
@ -63,20 +67,20 @@
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.0.1",
"@types/node": "^22",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
"@typescript-eslint/eslint-plugin": "^8.8.1",
"@typescript-eslint/parser": "^8.8.1",
"@vitejs/plugin-react": "^4.3.4",
"eslint-config-next": "15.0.2",
"eslint": "^9.13.0",
"eslint-config-next": "15.0.2",
"jsdom": "^25.0.1",
"postcss": "^8",
"prettier-plugin-tailwindcss": "^0.6.5",
"prettier": "^3.2.5",
"prettier-plugin-tailwindcss": "^0.6.5",
"tailwindcss": "^3.4.9",
"tailwindcss-animate": "^1.0.7",
"tailwindcss-animated": "^1.1.2",
"tailwindcss": "^3.4.9",
"typescript": "^5",
"vite-tsconfig-paths": "^5.1.3",
"vitest": "^2.1.6"

View File

@ -0,0 +1,248 @@
"use client";
import React, { useEffect, useState } from "react";
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { string } from "zod";
import ApplicationChart from "../../components/ApplicationChart";
interface DataModel {
id: number;
ct_type: number;
disk_size: number;
core_count: number;
ram_size: number;
verbose: string;
os_type: string;
os_version: string;
hn: string;
disableip6: string;
ssh: string;
tags: string;
nsapp: string;
created_at: string;
method: string;
pve_version: string;
status: string;
}
const DataFetcher: React.FC = () => {
const [data, setData] = useState<DataModel[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
const [searchQuery, setSearchQuery] = useState('');
const [startDate, setStartDate] = useState<Date | null>(null);
const [endDate, setEndDate] = useState<Date | null>(null);
const [sortConfig, setSortConfig] = useState<{ key: keyof DataModel | null, direction: 'ascending' | 'descending' }>({ key: 'id', direction: 'descending' });
const [itemsPerPage, setItemsPerPage] = useState(5);
const [currentPage, setCurrentPage] = useState(1);
const [showChart, setShowChart] = useState<boolean>(false);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("https://api.htl-braunau.at/data/json");
if (!response.ok) throw new Error("Failed to fetch data: ${response.statusText}");
const result: DataModel[] = await response.json();
setData(result);
} catch (err) {
setError((err as Error).message);
} finally {
setLoading(false);
}
};
fetchData();
}, []);
const filteredData = data.filter(item => {
const matchesSearchQuery = Object.values(item).some(value =>
value.toString().toLowerCase().includes(searchQuery.toLowerCase())
);
const itemDate = new Date(item.created_at);
const matchesDateRange = (!startDate || itemDate >= startDate) && (!endDate || itemDate <= endDate);
return matchesSearchQuery && matchesDateRange;
});
const sortedData = React.useMemo(() => {
let sortableData = [...filteredData];
if (sortConfig.key !== null) {
sortableData.sort((a, b) => {
if (sortConfig.key !== null && a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
if (sortConfig.key !== null && a[sortConfig.key] > b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? 1 : -1;
}
return 0;
});
}
return sortableData;
}, [filteredData, sortConfig]);
const requestSort = (key: keyof DataModel | null) => {
let direction: 'ascending' | 'descending' = 'ascending';
if (sortConfig.key === key && sortConfig.direction === 'ascending') {
direction = 'descending';
} else if (sortConfig.key === key && sortConfig.direction === 'descending') {
direction = 'ascending';
} else {
direction = 'descending';
}
setSortConfig({ key, direction });
};
interface SortConfig {
key: keyof DataModel | null;
direction: 'ascending' | 'descending';
}
const formatDate = (dateString: string): string => {
const date = new Date(dateString);
const year = date.getFullYear();
const month = date.getMonth() + 1;
const day = date.getDate();
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const timezoneOffset = dateString.slice(-6);
return `${day}.${month}.${year} ${hours}:${minutes} ${timezoneOffset} GMT`;
};
const handleItemsPerPageChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
setItemsPerPage(Number(event.target.value));
setCurrentPage(1);
};
const paginatedData = sortedData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error}</p>;
return (
<div className="p-6 mt-20">
<h1 className="text-2xl font-bold mb-4 text-center">Created LXCs</h1>
<div className="mb-4 flex space-x-4">
<div>
<input
type="text"
placeholder="Search..."
value={searchQuery}
onChange={e => setSearchQuery(e.target.value)}
className="p-2 border"
/>
<label className="text-sm text-gray-600 mt-1 block">Search by keyword</label>
</div>
<div>
<DatePicker
selected={startDate}
onChange={date => setStartDate(date)}
selectsStart
startDate={startDate}
endDate={endDate}
placeholderText="Start date"
className="p-2 border"
/>
<label className="text-sm text-gray-600 mt-1 block">Set a start date</label>
</div>
<div>
<DatePicker
selected={endDate}
onChange={date => setEndDate(date)}
selectsEnd
startDate={startDate}
endDate={endDate}
placeholderText="End date"
className="p-2 border"
/>
<label className="text-sm text-gray-600 mt-1 block">Set a end date</label>
</div>
</div>
<ApplicationChart data={filteredData} />
<div className="mb-4 flex justify-between items-center">
<p className="text-lg font-bold">{filteredData.length} results found</p>
<select value={itemsPerPage} onChange={handleItemsPerPageChange} className="p-2 border">
<option value={25}>25</option>
<option value={50}>50</option>
<option value={100}>100</option>
<option value={200}>200</option>
</select>
</div>
<div className="overflow-x-auto">
<div className="overflow-y-auto lg:overflow-y-visible">
<table className="min-w-full table-auto border-collapse">
<thead>
<tr>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('status')}>Status</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('nsapp')}>Application</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_type')}>OS</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_version')}>OS Version</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('disk_size')}>Disk Size</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('core_count')}>Core Count</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('ram_size')}>RAM Size</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('hn')}>Hostname</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('ssh')}>SSH</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('verbose')}>Verb</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('tags')}>Tags</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('method')}>Method</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('pve_version')}>PVE Version</th>
<th className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('created_at')}>Created At</th>
</tr>
</thead>
<tbody>
{paginatedData.map((item, index) => (
<tr key={index}>
<td className="px-4 py-2 border-b">
{item.status === "done" ? (
"✔️"
) : item.status === "failed" ? (
"❌"
) : item.status === "installing" ? (
"🔄"
) : (
item.status
)}
</td>
<td className="px-4 py-2 border-b">{item.nsapp}</td>
<td className="px-4 py-2 border-b">{item.os_type}</td>
<td className="px-4 py-2 border-b">{item.os_version}</td>
<td className="px-4 py-2 border-b">{item.disk_size}</td>
<td className="px-4 py-2 border-b">{item.core_count}</td>
<td className="px-4 py-2 border-b">{item.ram_size}</td>
<td className="px-4 py-2 border-b">{item.hn}</td>
<td className="px-4 py-2 border-b">{item.ssh}</td>
<td className="px-4 py-2 border-b">{item.verbose}</td>
<td className="px-4 py-2 border-b">{item.tags.replace(/;/g, ' ')}</td>
<td className="px-4 py-2 border-b">{item.method}</td>
<td className="px-4 py-2 border-b">{item.pve_version}</td>
<td className="px-4 py-2 border-b">{formatDate(item.created_at)}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
<div className="mt-4 flex justify-between items-center">
<button
onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
disabled={currentPage === 1}
className="p-2 border"
>
Previous
</button>
<span>Page {currentPage}</span>
<button
onClick={() => setCurrentPage(prev => (prev * itemsPerPage < sortedData.length ? prev + 1 : prev))}
disabled={currentPage * itemsPerPage >= sortedData.length}
className="p-2 border"
>
Next
</button>
</div>
</div>
);
};
export default DataFetcher;

View File

@ -0,0 +1,132 @@
"use client";
import React, { useState } from "react";
import { Pie } from "react-chartjs-2";
import { Chart as ChartJS, ArcElement, Tooltip, Legend } from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import Modal from "@/components/Modal";
ChartJS.register(ArcElement, Tooltip, Legend, ChartDataLabels);
interface ApplicationChartProps {
data: { nsapp: string }[];
}
const ApplicationChart: React.FC<ApplicationChartProps> = ({ data }) => {
const [isChartOpen, setIsChartOpen] = useState(false);
const [isTableOpen, setIsTableOpen] = useState(false);
const [chartStartIndex, setChartStartIndex] = useState(0);
const [tableLimit, setTableLimit] = useState(20);
const appCounts: Record<string, number> = {};
data.forEach((item) => {
appCounts[item.nsapp] = (appCounts[item.nsapp] || 0) + 1;
});
const sortedApps = Object.entries(appCounts).sort(([, a], [, b]) => b - a);
const chartApps = sortedApps.slice(chartStartIndex, chartStartIndex + 20);
const chartData = {
labels: chartApps.map(([name]) => name),
datasets: [
{
label: "Applications",
data: chartApps.map(([, count]) => count),
backgroundColor: [
"#ff6384",
"#36a2eb",
"#ffce56",
"#4bc0c0",
"#9966ff",
"#ff9f40",
],
},
],
};
return (
<div className="mt-6 text-center">
<button
onClick={() => setIsChartOpen(true)}
className="m-2 p-2 bg-blue-500 text-white rounded"
>
📊 Open Chart
</button>
<button
onClick={() => setIsTableOpen(true)}
className="m-2 p-2 bg-green-500 text-white rounded"
>
📋 Open Table
</button>
<Modal isOpen={isChartOpen} onClose={() => setIsChartOpen(false)}>
<h2 className="text-xl font-bold text-black dark:text-white mb-4">Top Applications (Chart)</h2>
<div className="w-3/4 mx-auto">
<Pie
data={chartData}
options={{
plugins: {
legend: { display: false },
datalabels: {
color: "white",
font: { weight: "bold" },
formatter: (value, context) =>
context.chart.data.labels?.[context.dataIndex] || "",
},
},
}}
/>
</div>
<div className="flex justify-center space-x-4 mt-4">
<button
onClick={() => setChartStartIndex(Math.max(0, chartStartIndex - 20))}
disabled={chartStartIndex === 0}
className="p-2 border rounded bg-blue-500 text-white"
>
Last 20
</button>
<button
onClick={() => setChartStartIndex(chartStartIndex + 20)}
disabled={chartStartIndex + 20 >= sortedApps.length}
className="p-2 border rounded bg-blue-500 text-white"
>
Next 20
</button>
</div>
</Modal>
<Modal isOpen={isTableOpen} onClose={() => setIsTableOpen(false)}>
<h2 className="text-xl font-bold text-black dark:text-white mb-4">Application Count Table</h2>
<table className="w-full border-collapse border border-gray-600 dark:border-gray-500">
<thead>
<tr className="bg-gray-800 text-white">
<th className="p-2 border">Application</th>
<th className="p-2 border">Count</th>
</tr>
</thead>
<tbody>
{sortedApps.slice(0, tableLimit).map(([name, count]) => (
<tr key={name} className="hover:bg-gray-200 dark:hover:bg-gray-700 text-black dark:text-white">
<td className="p-2 border">{name}</td>
<td className="p-2 border">{count}</td>
</tr>
))}
</tbody>
</table>
{tableLimit < sortedApps.length && (
<div className="text-center mt-4">
<button
onClick={() => setTableLimit(tableLimit + 20)}
className="p-2 bg-green-500 text-white rounded"
>
Load More
</button>
</div>
)}
</Modal>
</div>
);
};
export default ApplicationChart;

View File

@ -0,0 +1,29 @@
"use client";
import React from "react";
interface ModalProps {
isOpen: boolean;
onClose: () => void;
children: React.ReactNode;
}
const Modal: React.FC<ModalProps> = ({ isOpen, onClose, children }) => {
if (!isOpen) return null;
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50">
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg shadow-lg w-11/12 max-w-4xl relative max-h-[90vh] overflow-y-auto">
<button
onClick={onClose}
className="absolute top-2 right-2 bg-red-500 text-white p-1 rounded"
>
</button>
{children}
</div>
</div>
);
};
export default Modal;

View File

@ -15,7 +15,7 @@ const Command = React.forwardRef<
<CommandPrimitive
ref={ref}
className={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
"flex h-full w-full flex-col overflow-hidden bg-popover text-popover-foreground",
className,
)}
{...props}

View File

@ -0,0 +1,56 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: nicedevil007 (NiceDevil)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
source /dev/stdin <<< "$FUNCTIONS_FILE_PATH"
color
verb_ip6
catch_errors
setting_up_container
network_check
update_os
msg_info "Installing Dependencies"
$STD apk add \
curl \
mc \
nginx \
unzip
msg_ok "Installed Dependencies"
msg_info "Installing IT-Tools"
RELEASE=$(curl -s https://api.github.com/repos/CorentinTh/it-tools/releases/latest | grep '"tag_name":' | cut -d '"' -f4)
DOWNLOAD_URL="https://github.com/CorentinTh/it-tools/releases/download/${RELEASE}/it-tools-${RELEASE#v}.zip"
curl -fsSL -o it-tools.zip "$DOWNLOAD_URL"
mkdir -p /usr/share/nginx/html
unzip -q it-tools.zip -d /tmp/it-tools
cp -r /tmp/it-tools/dist/* /usr/share/nginx/html
cat <<'EOF' > /etc/nginx/http.d/default.conf
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
EOF
$STD rc-update add nginx default
$STD rc-service nginx start
echo "${RELEASE}" >/opt/${APPLICATION}_version.txt
msg_ok "Installed IT-Tools"
motd_ssh
customize
msg_info "Cleaning up"
rm -rf /tmp/it-tools
rm -f it-tools.zip
$STD apk cache clean
msg_ok "Cleaned"

View File

@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Kaedon Cleland-Host (dracentis)
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
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 \
curl \
sudo \
mc \
gpg \
postgresql
msg_ok "Installed Dependencies"
msg_info "Setting up PostgreSQL"
DB_NAME=mattermost
DB_USER=mmuser
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
$STD sudo -u postgres psql -c "CREATE DATABASE $DB_NAME;"
$STD sudo -u postgres psql -c "CREATE USER $DB_USER WITH PASSWORD '$DB_PASS';"
$STD sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE $DB_NAME to $DB_USER;"
$STD sudo -u postgres psql -c "ALTER DATABASE $DB_NAME OWNER TO $DB_USER;"
$STD sudo -u postgres psql -c "GRANT USAGE, CREATE ON SCHEMA PUBLIC TO $DB_USER;"
{
echo "Mattermost Credentials"
echo "Database User: $DB_USER"
echo "Database Password: $DB_PASS"
echo "Database Name: $DB_NAME"
} >> ~/mattermost.creds
msg_ok "Set up PostgreSQL"
msg_info "Installing Mattermost"
IPADDRESS=$(hostname -I | awk '{print $1}')
curl -sL -o /usr/share/keyrings/mattermost-archive-keyring.gpg https://deb.packages.mattermost.com/pubkey.gpg
sh -c 'curl -sL https://deb.packages.mattermost.com/repo-setup.sh | sudo bash -s mattermost' >/dev/null
$STD apt-get update
$STD apt-get install -y mattermost
$STD install -C -m 600 -o mattermost -g mattermost /opt/mattermost/config/config.defaults.json /opt/mattermost/config/config.json
sed -i -e "/DataSource/c\ \"DataSource\": \"postgres://$DB_USER:$DB_PASS@localhost:5432/$DB_NAME?sslmode=disable&connect_timeout=10\"," \
-e "/SiteURL/c\ \"SiteURL\": \"http://$IPADDRESS:8065\"," /opt/mattermost/config/config.json
systemctl enable -q --now mattermost.service
msg_ok "Installed Mattermost"
motd_ssh
customize
msg_info "Cleaning up"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"

View File

@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Andy Grunwald (andygrunwald)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Source: https://github.com/prometheus-pve/prometheus-pve-exporter
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 \
curl \
sudo \
mc
msg_ok "Installed Dependencies"
msg_info "Setup Python3"
$STD apt-get install -y \
python3 \
python3-pip
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
msg_ok "Setup Python3"
msg_info "Installing Prometheus Proxmox VE Exporter"
python3 -m pip install --quiet --root-user-action=ignore prometheus-pve-exporter
mkdir -p /opt/prometheus-pve-exporter
cat <<EOF > /opt/prometheus-pve-exporter/pve.yml
default:
user: prometheus@pve
password: sEcr3T!
verify_ssl: false
EOF
msg_ok "Installed Prometheus Proxmox VE Exporter"
msg_info "Creating Service"
cat <<EOF >/etc/systemd/system/prometheus-pve-exporter.service
[Unit]
Description=Prometheus Proxmox VE Exporter
Documentation=https://github.com/znerol/prometheus-pve-exporter
After=syslog.target network.target
[Service]
User=root
Restart=always
Type=simple
ExecStart=pve_exporter \
--config.file=/opt/prometheus-pve-exporter/pve.yml \
--web.listen-address=0.0.0.0:9221
ExecReload=/bin/kill -HUP \$MAINPID
[Install]
WantedBy=multi-user.target
EOF
systemctl enable -q --now prometheus-pve-exporter
msg_ok "Created Service"
motd_ssh
customize
msg_info "Cleaning up"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"

34
json/alpine-it-tools.json Normal file
View File

@ -0,0 +1,34 @@
{
"name": "Alpine-IT-Tools",
"slug": "alpine-it-tools",
"categories": [
20
],
"date_created": "2025-01-30",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": null,
"website": "https://it-tools.tech/",
"logo": "https://raw.githubusercontent.com/CorentinTh/it-tools/08d977b8cdb7ffb76adfa18ba6eb4b73795ec814/public/safari-pinned-tab.svg",
"description": "IT-Tools is a web-based suite of utilities designed to streamline and simplify various IT tasks, providing tools for developers and system administrators to manage their workflows efficiently.",
"install_methods": [
{
"type": "default",
"script": "ct/alpine-it-tools.sh",
"resources": {
"cpu": 1,
"ram": 256,
"hdd": 0.2,
"os": "alpine",
"version": "3.21"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@ -0,0 +1,39 @@
{
"name": "Proxmox Clean Orphaned LVM",
"slug": "clean-orphaned-lvm",
"categories": [
1
],
"date_created": "2025-01-29",
"type": "misc",
"updateable": false,
"privileged": false,
"interface_port": null,
"documentation": null,
"website": null,
"logo": "https://raw.githubusercontent.com/home-assistant/brands/master/core_integrations/proxmoxve/icon.png",
"description": "This script helps Proxmox users identify and remove orphaned LVM volumes that are no longer associated with any VM or LXC container. It scans all LVM volumes, detects unused ones, and provides an interactive prompt to delete them safely. System-critical volumes like root, swap, and data are excluded to prevent accidental deletion.",
"install_methods": [
{
"type": "default",
"script": "misc/clean-orphaned-lvm.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"
}
]
}

34
json/mattermost.json Normal file
View File

@ -0,0 +1,34 @@
{
"name": "Mattermost",
"slug": "mattermost",
"categories": [
25
],
"date_created": "2025-01-30",
"type": "ct",
"updateable": false,
"privileged": false,
"interface_port": 8065,
"documentation": null,
"website": "https://mattermost.com/",
"logo": "https://avatars.githubusercontent.com/u/9828093?s=200&v=4",
"description": "Mattermost is an open source platform for secure collaboration across the entire software development lifecycle. It's written in Go and React and runs as a single Linux binary with MySQL or PostgreSQL. It has a slimilar interface and features to Slack or Discord.",
"install_methods": [
{
"type": "default",
"script": "ct/mattermost.sh",
"resources": {
"cpu": 1,
"ram": 2048,
"hdd": 8,
"os": "ubuntu",
"version": "24.04"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": []
}

View File

@ -0,0 +1,40 @@
{
"name": "Prometheus Proxmox VE Exporter",
"slug": "prometheus-proxmox-ve-exporter",
"categories": [
1,
9
],
"date_created": "2025-01-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 9221,
"documentation": "https://github.com/prometheus-pve/prometheus-pve-exporter",
"website": "https://github.com/prometheus-pve/prometheus-pve-exporter",
"logo": "https://raw.githubusercontent.com/home-assistant/brands/master/core_integrations/proxmoxve/icon.png",
"description": "An exporter that exposes information gathered from Proxmox VE node for use by the Prometheus monitoring system.",
"install_methods": [
{
"type": "default",
"script": "ct/prometheus-pve-exporter.sh",
"resources": {
"cpu": 1,
"ram": 1024,
"hdd": 2,
"os": "debian",
"version": "12"
}
}
],
"default_credentials": {
"username": null,
"password": null
},
"notes": [
{
"text": "Please adjust the Proxmox credentials in the configuration file: /opt/prometheus-pve-exporter/pve.yml",
"type": "info"
}
]
}

View File

@ -102,7 +102,7 @@ while true; do
esac
done
if ! pveversion | grep -Eq "pve-manager/8.[0-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[0-3](\.[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..."

View File

@ -1,6 +1,7 @@
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# Co-Author: michelroegl-brunner
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@ -8,7 +9,10 @@ variables() {
NSAPP=$(echo ${APP,,} | tr -d ' ') # This function sets the NSAPP variable by converting the value of the APP variable to lowercase and removing any spaces.
var_install="${NSAPP}-install" # sets the var_install variable by appending "-install" to the value of NSAPP.
INTEGER='^[0-9]+([.][0-9]+)?$' # it defines the INTEGER regular expression pattern.
PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase
PVEHOST_NAME=$(hostname) # gets the Proxmox Hostname and sets it to Uppercase
DIAGNOSTICS="yes" # sets the DIAGNOSTICS variable to "yes", used for the API call.
METHOD="default" # sets the METHOD variable to "default", used for the API call.
RANDOM_UUID="$(cat /proc/sys/kernel/random/uuid)" # generates a random UUID and sets it to the RANDOM_UUDI variable.
}
# This function sets various color variables using ANSI escape codes for formatting text in the terminal.
@ -69,6 +73,7 @@ error_handler() {
local exit_code="$?"
local line_number="$1"
local command="$2"
post_update_to_api "failed"
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"
}
@ -137,16 +142,16 @@ root_check() {
# This function checks the version of Proxmox Virtual Environment (PVE) and exits if the version is not supported.
pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."
sleep 2
exit
fi
fi
}
# When a node is running tens of containers, it's possible to exceed the kernel's cryptographic key storage allocations.
# When a node is running tens of containers, it's possible to exceed the kernel's cryptographic key storage allocations.
# These are tuneable, so verify if the currently deployment is approaching the limits, advise the user on how to tune the limits, and exit the script.
# https://cleveruptime.com/docs/files/proc-key-users | https://docs.kernel.org/security/keys/core.html
maxkeys_check() {
@ -222,11 +227,11 @@ get_current_ip() {
# Function to update the IP address in the MOTD file
update_motd_ip() {
MOTD_FILE="/etc/motd"
if [ -f "$MOTD_FILE" ]; then
# Remove existing IP Address lines to prevent duplication
sed -i '/IP Address:/d' "$MOTD_FILE"
IP=$(get_current_ip)
# Add the new IP address
echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >> "$MOTD_FILE"
@ -359,34 +364,34 @@ exit_script() {
advanced_settings() {
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Here is an instructional tip:" "To make a selection, use the Spacebar." 8 58
whiptail --backtitle "Proxmox VE Helper Scripts" --msgbox --title "Default distribution for $APP" "Default is: ${var_os} ${var_version} \n \nIf the default Linux distribution is not adhered to, script support will be discontinued. \n" 10 58
if [ "$var_os" != "alpine" ]; then
if [ "$var_os" != "alpine" ]; then
var_default_os="${var_os}"
var_os=""
while [ -z "$var_os" ]; do
if [ "$var_default_os" == "debian" ]; then
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
"debian" "" ON \
"ubuntu" "" OFF \
3>&1 1>&2 2>&3); then
if [ -n "$var_os" ]; then
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
fi
else
exit_script
if [ "$var_default_os" == "debian" ]; then
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
"debian" "" ON \
"ubuntu" "" OFF \
3>&1 1>&2 2>&3); then
if [ -n "$var_os" ]; then
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
fi
else
exit_script
fi
if [ "$var_default_os" == "ubuntu" ]; then
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
"debian" "" OFF \
"ubuntu" "" ON \
3>&1 1>&2 2>&3); then
if [ -n "$var_os" ]; then
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
fi
else
exit_script
fi
if [ "$var_default_os" == "ubuntu" ]; then
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
"debian" "" OFF \
"ubuntu" "" ON \
3>&1 1>&2 2>&3); then
if [ -n "$var_os" ]; then
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
fi
else
exit_script
fi
fi
done
fi
@ -394,7 +399,7 @@ advanced_settings() {
var_default_version="${var_version}"
var_version=""
while [ -z "$var_version" ]; do
if [ "$var_default_version" == "11" ]; then
if [ "$var_default_version" == "11" ]; then
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DEBIAN VERSION" --radiolist "Choose Version" 10 58 2 \
"11" "Bullseye" ON \
"12" "Bookworm" OFF \
@ -425,13 +430,13 @@ advanced_settings() {
var_default_version="${var_version}"
var_version=""
while [ -z "$var_version" ]; do
if [ "$var_default_version" == "20.04" ]; then
if [ "$var_default_version" == "20.04" ]; then
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
"20.04" "Focal" ON \
"22.04" "Jammy" OFF \
"24.04" "Noble" OFF \
"24.10" "Oracular" OFF \
3>&1 1>&2 2>&3); then
3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi
@ -444,7 +449,7 @@ advanced_settings() {
"22.04" "Jammy" ON \
"24.04" "Noble" OFF \
"24.10" "Oracular" OFF \
3>&1 1>&2 2>&3); then
3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi
@ -452,25 +457,25 @@ advanced_settings() {
exit_script
fi
elif [ "$var_default_version" == "24.04" ]; then
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
"20.04" "Focal" OFF \
"22.04" "Jammy" OFF \
"24.04" "Noble" ON \
"24.10" "Oracular" OFF \
3>&1 1>&2 2>&3); then
3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi
else
exit_script
fi
fi
else
if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
"20.04" "Focal" OFF \
"22.04" "Jammy" OFF \
"24.04" "Noble" OFF \
"24.10" "Oracular" ON \
3>&1 1>&2 2>&3); then
3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi
@ -485,7 +490,7 @@ advanced_settings() {
CT_DEFAULT_TYPE="${CT_TYPE}"
CT_TYPE=""
while [ -z "$CT_TYPE" ]; do
if [ "$CT_DEFAULT_TYPE" == "1" ]; then
if [ "$CT_DEFAULT_TYPE" == "1" ]; then
if CT_TYPE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
"1" "Unprivileged" ON \
"0" "Privileged" OFF \
@ -550,7 +555,6 @@ advanced_settings() {
fi
done
if CT_ID=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Container ID" 8 58 $NEXTID --title "CONTAINER ID" 3>&1 1>&2 2>&3); then
if [ -z "$CT_ID" ]; then
CT_ID="$NEXTID"
@ -741,14 +745,14 @@ advanced_settings() {
if ADV_TAGS=$(whiptail --backtitle "Proxmox VE Helper Scripts" --inputbox "Set Custom Tags?[If you remove all, there will be no tags!]" 8 58 ${TAGS} --title "Advanced Tags" 3>&1 1>&2 2>&3); then
if [ -n "${ADV_TAGS}" ]; then
ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]')
TAGS="${ADV_TAGS}"
ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]')
TAGS="${ADV_TAGS}"
else
TAGS=";"
fi
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
else
exit_script
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
else
exit_script
fi
if [[ "$PW" == -password* ]]; then
@ -771,7 +775,7 @@ advanced_settings() {
fi
else
SSH_AUTHORIZED_KEY=""
fi
fi
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
VERB="yes"
else
@ -789,6 +793,144 @@ advanced_settings() {
fi
}
post_to_api() {
local API_URL="http://api.community-scripts.org/upload"
local pve_version="not found"
pve_version=$(pveversion | awk -F'[/ ]' '{print $2}')
JSON_PAYLOAD=$(cat <<EOF
{
"ct_type": $CT_TYPE,
"disk_size": $DISK_SIZE,
"core_count": $CORE_COUNT,
"ram_size": $RAM_SIZE,
"verbose": "$VERBOSE",
"os_type": "$var_os",
"os_version": "$var_version",
"hn": "$HN",
"disableip6": "$DISABLEIP6",
"ssh": "$SSH",
"tags": "$TAGS",
"nsapp": "$NSAPP",
"method": "$METHOD",
"pve_version": "$pve_version",
"status": "installing",
"random_id": "$RANDOM_UUID"
}
EOF
)
RESPONSE=$(curl -s -o response.txt -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
if [ "$RESPONSE" -ne 201 ] && [ "$RESPONSE" -ne 302 ]; then
msg_error "API request failed with HTTP code $RESPONSE"
fi
}
POST_UPDATE_DONE=false
post_update_to_api() {
if [ "$POST_UPDATE_DONE" = true ]; then
return 0
fi
local API_URL="http://api.community-scripts.org/upload/updatestatus"
local status="${1:-}"
JSON_PAYLOAD=$(cat <<EOF
{
"status": "$status",
"random_id": "$RANDOM_UUID"
}
EOF
)
RESPONSE=$(curl -s -o response.txt -w "%{http_code}" -L -X POST "$API_URL" --post301 --post302 \
-H "Content-Type: application/json" \
-d "$JSON_PAYLOAD")
if [ "$RESPONSE" -ne 201 ] && [ "$RESPONSE" -ne 302 ]; then
msg_error "API UPDATE request failed with HTTP code $RESPONSE"
fi
POST_UPDATE_DONE=true
}
diagnostics_check(){
if ! [ -d "/usr/local/community-scripts" ]; then
mkdir -p /usr/local/community-scripts
fi
if ! [ -f "/usr/local/community-scripts/diagnostics" ]; then
if (whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS" --yesno "Send Diagnostics of LXC Installation?\n\n(This only transmits data without user data, just RAM, CPU, LXC name, ...)" 10 58); then
cat <<EOF>/usr/local/community-scripts/diagnostics
DIAGNOSTICS=yes
#This file is used to store the diagnostics settings for the Community-Scripts API.
#https://github.com/community-scripts/ProxmoxVE/discussions/1836
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
#This will disable the diagnostics feature.
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
#This will enable the diagnostics feature.
#The following information will be sent:
#"ct_type"
#"disk_size"
#"core_count"
#"ram_size"
#"verbose"
#"os_type"
#"os_version"
#"hn"
#"disableip6"
#"ssh"
#"tags"
#"nsapp"
#"method"
#"pve_version"
#If you have any concerns, please review the source code at /misc/build.func
EOF
DIAGNOSTICS="yes"
else
cat <<EOF >/usr/local/community-scripts/diagnostics
DIAGNOSTICS=no
#This file is used to store the diagnostics settings for the Community-Scripts API.
#https://github.com/community-scripts/ProxmoxVE/discussions/1836
#Your diagnostics will be sent to the Community-Scripts API for troubleshooting/statistical purposes.
#You can review the data at https://community-scripts.github.io/ProxmoxVE/data
#If you do not wish to send diagnostics, please set the variable 'DIAGNOSTICS' to "no" in /usr/local/community-scripts/diagnostics, or use the menue.
#This will disable the diagnostics feature.
#To send diagnostics, set the variable 'DIAGNOSTICS' to "yes" in /usr/local/community-scripts/diagnostics, or use the menue.
#This will enable the diagnostics feature.
#The following information will be sent:
#"ct_type"
#"disk_size"
#"core_count"
#"ram_size"
#"verbose"
#"os_type"
#"os_version"
#"hn"
#"disableip6"
#"ssh"
#"tags"
#"nsapp"
#"method"
#"pve_version"
#If you have any concerns, please review the source code at /misc/build.func
EOF
DIAGNOSTICS="no"
fi
else
DIAGNOSTICS=$(awk -F '=' '/^DIAGNOSTICS/ {print $2}' /usr/local/community-scripts/diagnostics)
fi
}
install_script() {
pve_check
shell_check
@ -796,6 +938,7 @@ install_script() {
arch_check
ssh_check
maxkeys_check
diagnostics_check
if systemctl is-active -q ping-instances.service; then
systemctl -q stop ping-instances.service
@ -804,12 +947,14 @@ install_script() {
timezone=$(cat /etc/timezone)
header_info
while true; do
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --menu "Choose an option:" \
12 50 4 \
12 50 5 \
"1" "Default Settings" \
"2" "Default Settings (with verbose)" \
"3" "Advanced Settings" \
"4" "Exit" --nocancel --default-item "1" 3>&1 1>&2 2>&3)
"4" "Diagnostic Settings" \
"5" "Exit" --nocancel --default-item "1" 3>&1 1>&2 2>&3)
if [ $? -ne 0 ]; then
echo -e "${CROSS}${RD} Menu canceled. Exiting.${CL}"
@ -817,35 +962,55 @@ install_script() {
fi
case $CHOICE in
1)
header_info
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
VERB="no"
base_settings "$VERB"
echo_default
break
;;
2)
header_info
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}"
VERB="yes"
base_settings "$VERB"
echo_default
break
;;
3)
header_info
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}"
advanced_settings
break
;;
4)
echo -e "${CROSS}${RD}Exiting.${CL}"
exit 0
;;
*)
echo -e "${CROSS}${RD}Invalid option, please try again.${CL}"
1)
header_info
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
VERB="no"
METHOD="default"
base_settings "$VERB"
echo_default
break
;;
2)
header_info
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}"
VERB="yes"
METHOD="default"
base_settings "$VERB"
echo_default
break
;;
3)
header_info
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}"
METHOD="advanced"
advanced_settings
break
;;
4)
if [[ $DIAGNOSTICS == "yes" ]]; then
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \
--yes-button "No" --no-button "Back" ; then
DIAGNOSTICS="no"
sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=no/' /usr/local/community-scripts/diagnostics
whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58
fi
else
if whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --yesno "Send Diagnostics of LXC Installation?\n\nCurrent setting: ${DIAGNOSTICS}" 10 58 \
--yes-button "Yes" --no-button "Back" ; then
DIAGNOSTICS="yes"
sed -i 's/^DIAGNOSTICS=.*/DIAGNOSTICS=yes/' /usr/local/community-scripts/diagnostics
whiptail --backtitle "Proxmox VE Helper Scripts" --title "DIAGNOSTICS SETTINGS" --msgbox "Diagnostics settings changed to ${DIAGNOSTICS}." 8 58
fi
fi
;;
5)
echo -e "${CROSS}${RD}Exiting.${CL}"
exit 0
;;
*)
echo -e "${CROSS}${RD}Invalid option, please try again.${CL}"
;;
esac
done
}
@ -911,7 +1076,7 @@ start() {
# This function collects user settings and integrates all the collected information.
build_container() {
# if [ "$VERB" == "yes" ]; then set -x; fi
# if [ "$VERB" == "yes" ]; then set -x; fi
if [ "$CT_TYPE" == "1" ]; then
FEATURES="keyctl=1,nesting=1"
@ -919,6 +1084,9 @@ build_container() {
FEATURES="nesting=1"
fi
if [[ $DIAGNOSTICS == "yes" ]]; then
post_to_api
fi
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
@ -1012,7 +1180,7 @@ EOF
msg_ok "Started LXC Container"
if [ "$var_os" == "alpine" ]; then
sleep 3
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
pct exec "$CTID" -- /bin/sh -c 'cat <<EOF >/etc/apk/repositories
http://dl-cdn.alpinelinux.org/alpine/latest-stable/main
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
EOF'
@ -1027,7 +1195,8 @@ description() {
IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
# Generate LXC Description
DESCRIPTION=$(cat <<EOF
DESCRIPTION=$(
cat <<EOF
<div align='center'>
<a href='https://Helper-Scripts.com' target='_blank' rel='noopener noreferrer'>
<img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
@ -1055,7 +1224,7 @@ description() {
</span>
</div>
EOF
)
)
# Set Description in LXC
pct set "$CTID" -description "$DESCRIPTION"
@ -1063,4 +1232,13 @@ EOF
if [[ -f /etc/systemd/system/ping-instances.service ]]; then
systemctl start ping-instances.service
fi
if [[ $DIAGNOSTICS == "yes" ]]; then
post_update_to_api
fi
}
trap 'post_update_to_api "done"' EXIT
trap 'post_update_to_api "failed"' SIGINT
trap 'post_update_to_api "failed"' SIGTERM

View File

@ -0,0 +1,83 @@
#!/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
function header_info {
clear
cat <<"EOF"
____ ________ ____ __ __ __ _ ____ ___
/ __ \_________ _ ______ ___ ____ _ __ / ____/ /__ ____ _____ / __ \_________ / /_ ____ _____ ___ ____/ / / /| | / / |/ /____
/ /_/ / ___/ __ \| |/_/ __ `__ \/ __ \| |/_/ / / / / _ \/ __ `/ __ \ / / / / ___/ __ \/ __ \/ __ `/ __ \/ _ \/ __ / / / | | / / /|_/ / ___/
/ ____/ / / /_/ /> </ / / / / / /_/ /> < / /___/ / __/ /_/ / / / / / /_/ / / / /_/ / / / / /_/ / / / / __/ /_/ / / /__| |/ / / / (__ )
/_/ /_/ \____/_/|_/_/ /_/ /_/\____/_/|_| \____/_/\___/\__,_/_/ /_/ \____/_/ / .___/_/ /_/\__,_/_/ /_/\___/\__,_/ /_____/___/_/ /_/____/
/_/
EOF
}
# Function to check for orphaned LVM volumes
function find_orphaned_lvm {
echo -e "\n🔍 Scanning for orphaned LVM volumes...\n"
orphaned_volumes=()
while read -r lv vg size; do
container_id=$(echo "$lv" | grep -oE "[0-9]+" | head -1)
# Exclude system-critical LVs
if [[ "$lv" == "data" || "$lv" == "root" || "$lv" == "swap" ]]; then
continue
fi
# Check if the ID exists as a VM or LXC container
if [ -f "/etc/pve/lxc/${container_id}.conf" ] || [ -f "/etc/pve/qemu-server/${container_id}.conf" ]; then
continue
fi
orphaned_volumes+=("$lv" "$vg" "$size")
done < <(lvs --noheadings -o lv_name,vg_name,lv_size --separator ' ' | awk '{print $1, $2, $3}')
if [ ${#orphaned_volumes[@]} -eq 0 ]; then
echo -e "✅ No orphaned LVM volumes found.\n"
exit 0
fi
# Display orphaned volumes
echo -e "❗ The following orphaned LVM volumes were found:\n"
printf "%-25s %-10s %-10s\n" "LV Name" "VG" "Size"
printf "%-25s %-10s %-10s\n" "-------------------------" "----------" "----------"
for ((i = 0; i < ${#orphaned_volumes[@]}; i+=3)); do
printf "%-25s %-10s %-10s\n" "${orphaned_volumes[i]}" "${orphaned_volumes[i+1]}" "${orphaned_volumes[i+2]}"
done
echo ""
}
# Function to delete selected volumes
function delete_orphaned_lvm {
for ((i = 0; i < ${#orphaned_volumes[@]}; i+=3)); do
lv="${orphaned_volumes[i]}"
vg="${orphaned_volumes[i+1]}"
size="${orphaned_volumes[i+2]}"
read -p "❓ Do you want to delete $lv (VG: $vg, Size: $size)? [y/N]: " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
echo -e "🗑️ Deleting $lv from $vg..."
lvremove -f "$vg/$lv"
if [ $? -eq 0 ]; then
echo -e "✅ Successfully deleted $lv.\n"
else
echo -e "❌ Failed to delete $lv.\n"
fi
else
echo -e "⚠️ Skipping $lv.\n"
fi
done
}
# Run script
header_info
find_orphaned_lvm
delete_orphaned_lvm
echo -e "✅ Cleanup process completed!\n"

View File

@ -231,7 +231,7 @@ while true; do
esac
done
if ! pveversion | grep -Eq "pve-manager/8.[0-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[0-3](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.0 or later."
echo -e "Exiting..."

View File

@ -111,7 +111,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -111,7 +111,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -91,7 +91,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -115,7 +115,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -62,7 +62,7 @@ function cleanup() {
}
TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -91,7 +91,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -157,7 +157,7 @@ function msg_error() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -91,7 +91,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -111,7 +111,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -112,7 +112,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."

View File

@ -111,7 +111,7 @@ function check_root() {
}
function pve_check() {
if ! pveversion | grep -Eq "pve-manager/8.[1-3]"; then
if ! pveversion | grep -Eq "pve-manager/8\.[1-3](\.[0-9]+)*"; then
msg_error "${CROSS}${RD}This version of Proxmox Virtual Environment is not supported"
echo -e "Requires Proxmox Virtual Environment Version 8.1 or later."
echo -e "Exiting..."