Compare commits

...

57 Commits

Author SHA1 Message Date
community-scripts-pr-app[bot]
f9b84bf5ee Update CHANGELOG.md (#1910) 2025-01-31 20:23:58 +01:00
github-actions[bot]
ccab9d1be5 Update .app files (#1911) 2025-01-31 20:23:19 +01:00
Nícolas Pastorello
58a2ece7b7 New Script: Paymenter (#1827) 2025-01-31 20:21:24 +01:00
community-scripts-pr-app[bot]
aa16f936c8 Update CHANGELOG.md (#1903)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-31 17:35:40 +01:00
Bram Suurd
c8829beddd feat: enhance DataFetcher with better UI components and add reactive data fetching intervals (#1901) (#1902) 2025-01-31 14:09:28 +01:00
community-scripts-pr-app[bot]
3adc22d837 Update CHANGELOG.md (#1897)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-31 13:20:11 +01:00
Michel Roegl-Brunner
71b1288220 [Website] Update /data/page.tsx (#1900) 2025-01-31 04:12:36 -08:00
Tobias
3c58303a9f fix: apline-it-tools missing ssh package (#1891) 2025-01-31 10:10:21 +01:00
community-scripts-pr-app[bot]
b8edf0dd68 Update CHANGELOG.md (#1893)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2025-01-31 09:41:55 +01:00
Michel Roegl-Brunner
2fa3116c9c [API] update build.func (#1894)
* [API] update build.func

* [API] update build.func
2025-01-31 09:37:51 +01:00
CanbiZ
d416ff9cfa [Fix] Change Download of Trilium after there change the tag/release logic (#1892)
* change trilium release tag after tag/dl change

* change trilium release tag after tag/dl change
2025-01-31 08:45:30 +01:00
CanbiZ
2e2db6603e Revert "[API] update build.func (#1880)" (#1883)
This reverts commit 72335f2c4e.
2025-01-30 20:46:19 +01:00
Michel Roegl-Brunner
72335f2c4e [API] update build.func (#1880) 2025-01-30 20:00:20 +01:00
community-scripts-pr-app[bot]
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
Michel Roegl-Brunner
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
community-scripts-pr-app[bot]
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
Michel Roegl-Brunner
3d42ecb152 Update /data/page.tsx (#1876) 2025-01-30 14:47:22 +01:00
Michel Roegl-Brunner
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
community-scripts-pr-app[bot]
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
CanbiZ
0dfc513a27 Update alpine-it-tools.json 2025-01-30 13:55:53 +01:00
CanbiZ
26433efcd8 Rename it-tools.json to alpine-it-tools.json 2025-01-30 13:50:47 +01:00
CanbiZ
343de50ef8 fix breaking ui 2025-01-30 13:48:36 +01:00
CanbiZ
a38e9070ef add popup, table & chart 2025-01-30 13:43:24 +01:00
CanbiZ
e2b548a7c3 update chart 2025-01-30 13:38:25 +01:00
CanbiZ
737b18dea5 Update ApplicationChart.tsx 2025-01-30 13:30:44 +01:00
CanbiZ
6b777a03c0 fix deps 2025-01-30 13:25:02 +01:00
CanbiZ
d9b4778360 Update page.tsx 2025-01-30 13:21:49 +01:00
CanbiZ
7299b77359 Create ApplicationChart.tsx 2025-01-30 13:18:24 +01:00
CanbiZ
d3882b6818 add chart.js 2025-01-30 13:11:05 +01:00
CanbiZ
2ef0cd0f89 Update mattermost-install.sh 2025-01-30 11:48:12 +01:00
CanbiZ
f2eb24d527 add $STD 2025-01-30 11:43:26 +01:00
community-scripts-pr-app[bot]
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
github-actions[bot]
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
Kaedon Cleland-Host
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
CanbiZ
05f114ed64 Fix IT-Tools Website Entry (#1869) 2025-01-30 11:33:59 +01:00
CanbiZ
6924a6fea4 Optimize PVE Manager Version-Check (#1866) 2025-01-30 11:26:30 +01:00
github-actions[bot]
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
NiceDevil
cbb18668dd initial for PR (#1862) 2025-01-30 10:55:09 +01:00
community-scripts-pr-app[bot]
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
Stavros
ed2ead9ef2 fix: remove rounded styles from command primitive (#1840) 2025-01-30 08:35:10 +01:00
community-scripts-pr-app[bot]
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
Michel Roegl-Brunner
8c4e97d6cb Update build.func (#1851) 2025-01-29 20:00:02 +01:00
community-scripts-pr-app[bot]
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
Michel Roegl-Brunner
6fa540f0da Patch http Url in build.func and /data/page.tsx (#1849) 2025-01-29 19:37:45 +01:00
community-scripts-pr-app[bot]
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
Michel Roegl-Brunner
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
community-scripts-pr-app[bot]
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
github-actions[bot]
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
Andy Grunwald
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
CanbiZ
054b569e33 edit 2025-01-29 17:21:16 +01:00
community-scripts-pr-app[bot]
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
CanbiZ
37c7205978 Update clean-orphaned-lvm.json 2025-01-29 15:10:37 +01:00
Michel Roegl-Brunner
eb9633215c Update clean-orphaned-lvm.json (#1843) 2025-01-29 15:10:12 +01:00
community-scripts-pr-app[bot]
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
CanbiZ
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
community-scripts-pr-app[bot]
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
Michel Roegl-Brunner
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
43 changed files with 1982 additions and 111 deletions

1
.github/FUNDING.yml vendored
View File

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

View File

@@ -17,6 +17,68 @@ 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-31
### Changed
### ✨ New Scripts
- New Script: Paymenter [@opastorello](https://github.com/opastorello) ([#1827](https://github.com/community-scripts/ProxmoxVE/pull/1827))
### 🚀 Updated Scripts
- [Fix] Alpine-IT-Tools, add missing ssh package for root ssh access [@CrazyWolf13](https://github.com/CrazyWolf13) ([#1891](https://github.com/community-scripts/ProxmoxVE/pull/1891))
- [Fix] Change Download of Trilium after there change the tag/release logic [@MickLesk](https://github.com/MickLesk) ([#1892](https://github.com/community-scripts/ProxmoxVE/pull/1892))
### 🌐 Website
- [Website] Enhance DataFetcher with better UI components and add reactive data fetching intervals [@BramSuurdje](https://github.com/BramSuurdje) ([#1902](https://github.com/community-scripts/ProxmoxVE/pull/1902))
- [Website] Update /data/page.tsx [@michelroegl-brunner](https://github.com/michelroegl-brunner) ([#1900](https://github.com/community-scripts/ProxmoxVE/pull/1900))
## 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 @@
__ ___ __ __ __
/ |/ /___ _/ /_/ /____ _________ ___ ____ _____/ /_
/ /|_/ / __ `/ __/ __/ _ \/ ___/ __ `__ \/ __ \/ ___/ __/
/ / / / /_/ / /_/ /_/ __/ / / / / / / / /_/ (__ ) /_
/_/ /_/\__,_/\__/\__/\___/_/ /_/ /_/ /_/\____/____/\__/

6
ct/headers/paymenter 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}"

56
ct/paymenter.sh Normal file
View File

@@ -0,0 +1,56 @@
#!/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: Nícolas Pastorello (opastorello)
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# App Default Values
APP="Paymenter"
var_tags="hosting;ecommerce;marketplace;"
var_cpu="2"
var_ram="1024"
var_disk="5"
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 [[ ! -d /opt/paymenter ]]; then
msg_error "No ${APP} Installation Found!"
exit
fi
RELEASE=$(curl -s https://api.github.com/repos/paymenter/paymenter/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
msg_info "Updating ${APP} to ${RELEASE}"
echo "${RELEASE}" >/opt/${APP}_version.txt
cd /opt/paymenter
php artisan p:upgrade --no-interaction &>/dev/null
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 URL:${CL}"
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:80${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

@@ -35,22 +35,22 @@ function update_script() {
RELEASE=$(curl -s https://api.github.com/repos/TriliumNext/Notes/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
msg_info "Stopping ${APP}"
systemctl stop trilium.service
systemctl stop trilium
sleep 1
msg_ok "Stopped ${APP}"
msg_info "Updating to ${RELEASE}"
wget -q https://github.com/TriliumNext/Notes/releases/download/${RELEASE}/TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
tar -xf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
wget -q https://github.com/TriliumNext/Notes/releases/download/${RELEASE}/TriliumNextNotes-linux-x64-${RELEASE}.tar.xz
tar -xf TriliumNextNotes-linux-x64-${RELEASE}.tar.xz
cp -r trilium-linux-x64-server/* /opt/trilium/
msg_ok "Updated to ${RELEASE}"
msg_info "Cleaning up"
rm -rf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz trilium-linux-x64-server
rm -rf TriliumNextNotes-linux-x64-${RELEASE}.tar.xz trilium-linux-x64-server
msg_ok "Cleaned"
msg_info "Starting ${APP}"
systemctl start trilium.service
systemctl start trilium
sleep 1
msg_ok "Started ${APP}"
msg_ok "Updated Successfully"

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,346 @@
"use client";
import ApplicationChart from "@/components/ApplicationChart";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { format } from "date-fns";
import { Calendar as CalendarIcon } from "lucide-react";
import React, { useCallback, useEffect, useState } from "react";
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(25);
const [currentPage, setCurrentPage] = useState(1);
const [interval, setIntervalTime] = useState<number>(10); // Default interval 10 seconds
const [reloadInterval, setReloadInterval] = useState<NodeJS.Timeout | null>(null);
const fetchData = useCallback(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);
setLoading(false);
} catch (err) {
setError((err as Error).message);
setLoading(false);
}
}, []);
useEffect(() => {
fetchData();
const storedInterval = localStorage.getItem('reloadInterval');
if (storedInterval) {
setIntervalTime(Number(storedInterval));
}
}, [fetchData]);
useEffect(() => {
let intervalId: NodeJS.Timeout | null = null;
if (interval > 0) {
intervalId = setInterval(fetchData, Math.max(interval, 10) * 1000);
localStorage.setItem('reloadInterval', interval.toString());
} else {
localStorage.removeItem('reloadInterval');
}
return () => {
if (intervalId) clearInterval(intervalId);
};
}, [interval, 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 paginatedData = sortedData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
const statusCounts = data.reduce((acc, item) => {
const status = item.status;
acc[status] = (acc[status] || 0) + 1;
return acc;
}, {} as Record<string, number>);
if (loading) return <div className="flex justify-center items-center h-screen">Loading...</div>;
if (error) return <div className="flex justify-center items-center h-screen text-red-500">Error: {error}</div>;
return (
<div className="container mx-auto p-6 pt-20 space-y-6">
<h1 className="text-3xl font-bold text-center">Created LXCs</h1>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">Search</CardTitle>
</CardHeader>
<CardContent>
<Input
placeholder="Search..."
value={searchQuery}
onChange={e => setSearchQuery(e.target.value)}
/>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">Start Date</CardTitle>
</CardHeader>
<CardContent>
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" className="w-full justify-start text-left font-normal">
<CalendarIcon className="mr-2 h-4 w-4" />
{startDate ? format(startDate, "PPP") : "Pick a date"}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={startDate || undefined}
onSelect={(date: Date | undefined) => setStartDate(date || null)}
initialFocus
/>
</PopoverContent>
</Popover>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">End Date</CardTitle>
</CardHeader>
<CardContent>
<Popover>
<PopoverTrigger asChild>
<Button variant="outline" className="w-full justify-start text-left font-normal">
<CalendarIcon className="mr-2 h-4 w-4" />
{endDate ? format(endDate, "PPP") : "Pick a date"}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar
mode="single"
selected={endDate || undefined}
onSelect={(date: Date | undefined) => setEndDate(date || null)}
initialFocus
/>
</PopoverContent>
</Popover>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2">
<CardTitle className="text-sm font-medium">Reload Interval</CardTitle>
</CardHeader>
<CardContent>
<Input
type="number"
value={interval}
onChange={e => setIntervalTime(Number(e.target.value))}
placeholder="Interval (seconds)"
/>
</CardContent>
</Card>
</div>
<ApplicationChart data={filteredData} />
<div className="flex justify-between items-center">
<p className="text-lg font-medium">{filteredData.length} results found</p>
<div className="flex gap-2 items-center">
<span>🔄 Installing: {statusCounts.installing || 0}</span>
<span> Completed: {statusCounts.done || 0}</span>
<span> Failed: {statusCounts.failed || 0}</span>
<span> Unknown: {statusCounts.unknown || 0}</span>
</div>
<Select value={itemsPerPage.toString()} onValueChange={(value) => setItemsPerPage(Number(value))}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Items per page" />
</SelectTrigger>
<SelectContent>
{[25, 50, 100, 200].map(value => (
<SelectItem key={value} value={value.toString()}>
{value} items
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('status')}>Status</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('nsapp')}>Application</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_type')}>OS</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('os_version')}>OS Version</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('disk_size')}>Disk Size</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('core_count')}>Core Count</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('ram_size')}>RAM Size</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('hn')}>Hostname</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('ssh')}>SSH</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('verbose')}>Verb</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('tags')}>Tags</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('method')}>Method</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('pve_version')}>PVE Version</TableHead>
<TableHead className="px-4 py-2 border-b cursor-pointer" onClick={() => requestSort('created_at')}>Created At</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{paginatedData.map((item, index) => (
<TableRow key={index}>
<TableCell className="px-4 py-2 border-b">{item.status === "done" ? (
"✔️"
) : item.status === "failed" ? (
"❌"
) : item.status === "installing" ? (
"🔄"
) : (
item.status
)}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.nsapp}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.os_type}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.os_version}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.disk_size}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.core_count}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.ram_size}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.hn}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.ssh}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.verbose}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.tags.replace(/;/g, ' ')}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.method}</TableCell>
<TableCell className="px-4 py-2 border-b">{item.pve_version}</TableCell>
<TableCell className="px-4 py-2 border-b">{formatDate(item.created_at)}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
<div className="flex items-center justify-center space-x-2">
<Button
variant="outline"
onClick={() => setCurrentPage(prev => Math.max(prev - 1, 1))}
disabled={currentPage === 1}
>
Previous
</Button>
<span className="text-sm">
Page {currentPage} of {Math.ceil(sortedData.length / itemsPerPage)}
</span>
<Button
variant="outline"
onClick={() => setCurrentPage(prev => (prev * itemsPerPage < sortedData.length ? prev + 1 : prev))}
disabled={currentPage * itemsPerPage >= sortedData.length}
>
Next
</Button>
</div>
</div>
);
};
export default DataFetcher;

View File

@@ -0,0 +1,193 @@
"use client";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Chart as ChartJS, ArcElement, Tooltip as ChartTooltip, Legend } from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { BarChart3, PieChart } from "lucide-react";
import React, { useState } from "react";
import { Pie } from "react-chartjs-2";
ChartJS.register(ArcElement, ChartTooltip, Legend, ChartDataLabels);
interface ApplicationChartProps {
data: { nsapp: string }[];
}
const ITEMS_PER_PAGE = 20;
const CHART_COLORS = [
"#ff6384",
"#36a2eb",
"#ffce56",
"#4bc0c0",
"#9966ff",
"#ff9f40",
"#4dc9f6",
"#f67019",
"#537bc4",
"#acc236",
"#166a8f",
"#00a950",
"#58595b",
"#8549ba",
];
export default function ApplicationChart({ data }: ApplicationChartProps) {
const [isChartOpen, setIsChartOpen] = useState(false);
const [isTableOpen, setIsTableOpen] = useState(false);
const [chartStartIndex, setChartStartIndex] = useState(0);
const [tableLimit, setTableLimit] = useState(ITEMS_PER_PAGE);
// Calculate application counts
const appCounts = data.reduce((acc, item) => {
acc[item.nsapp] = (acc[item.nsapp] || 0) + 1;
return acc;
}, {} as Record<string, number>);
const sortedApps = Object.entries(appCounts)
.sort(([, a], [, b]) => b - a);
const chartApps = sortedApps.slice(
chartStartIndex,
chartStartIndex + ITEMS_PER_PAGE
);
const chartData = {
labels: chartApps.map(([name]) => name),
datasets: [
{
data: chartApps.map(([, count]) => count),
backgroundColor: CHART_COLORS,
},
],
};
const chartOptions = {
plugins: {
legend: { display: false },
datalabels: {
color: "white",
font: { weight: "bold" as const },
formatter: (value: number, context: any) => {
const label = context.chart.data.labels?.[context.dataIndex];
return `${label}\n(${value})`;
},
},
},
responsive: true,
maintainAspectRatio: false,
};
return (
<div className="mt-6 flex justify-center gap-4">
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
onClick={() => setIsChartOpen(true)}
>
<PieChart className="h-5 w-5" />
</Button>
</TooltipTrigger>
<TooltipContent>Open Chart View</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="outline"
size="icon"
onClick={() => setIsTableOpen(true)}
>
<BarChart3 className="h-5 w-5" />
</Button>
</TooltipTrigger>
<TooltipContent>Open Table View</TooltipContent>
</Tooltip>
</TooltipProvider>
<Dialog open={isChartOpen} onOpenChange={setIsChartOpen}>
<DialogContent className="max-w-3xl">
<DialogHeader>
<DialogTitle>Applications Distribution</DialogTitle>
</DialogHeader>
<div className="h-[60vh] w-full">
<Pie data={chartData} options={chartOptions} />
</div>
<div className="flex justify-center gap-4">
<Button
variant="outline"
onClick={() => setChartStartIndex(Math.max(0, chartStartIndex - ITEMS_PER_PAGE))}
disabled={chartStartIndex === 0}
>
Previous {ITEMS_PER_PAGE}
</Button>
<Button
variant="outline"
onClick={() => setChartStartIndex(chartStartIndex + ITEMS_PER_PAGE)}
disabled={chartStartIndex + ITEMS_PER_PAGE >= sortedApps.length}
>
Next {ITEMS_PER_PAGE}
</Button>
</div>
</DialogContent>
</Dialog>
<Dialog open={isTableOpen} onOpenChange={setIsTableOpen}>
<DialogContent className="max-w-2xl">
<DialogHeader>
<DialogTitle>Applications Count</DialogTitle>
</DialogHeader>
<div className="max-h-[60vh] overflow-y-auto">
<Table>
<TableHeader>
<TableRow>
<TableHead>Application</TableHead>
<TableHead className="text-right">Count</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{sortedApps.slice(0, tableLimit).map(([name, count]) => (
<TableRow key={name}>
<TableCell>{name}</TableCell>
<TableCell className="text-right">{count}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
{tableLimit < sortedApps.length && (
<Button
variant="outline"
className="w-full"
onClick={() => setTableLimit(prev => prev + ITEMS_PER_PAGE)}
>
Load More
</Button>
)}
</DialogContent>
</Dialog>
</div>
);
}

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,120 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
))
Table.displayName = "Table"
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
))
TableHeader.displayName = "TableHeader"
const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
))
TableBody.displayName = "TableBody"
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn(
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
className
)}
{...props}
/>
))
TableFooter.displayName = "TableFooter"
const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
)}
{...props}
/>
))
TableRow.displayName = "TableRow"
const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
)}
{...props}
/>
))
TableHead.displayName = "TableHead"
const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn(
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
className
)}
{...props}
/>
))
TableCell.displayName = "TableCell"
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
))
TableCaption.displayName = "TableCaption"
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
}

View File

@@ -0,0 +1,57 @@
#!/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 \
openssh \
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,140 @@
#!/usr/bin/env bash
# Copyright (c) 2021-2025 community-scripts ORG
# Author: Nícolas Pastorello (opastorello)
# 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 \
git \
software-properties-common \
apt-transport-https \
ca-certificates \
gnupg \
php8.2 \
php8.2-{common,cli,gd,mysql,mbstring,bcmath,xml,fpm,curl,zip} \
mariadb-server \
nginx \
redis-server
$STD curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
msg_ok "Installed Dependencies"
msg_info "Installing Paymenter"
RELEASE=$(curl -s https://api.github.com/repos/paymenter/paymenter/releases/latest | grep '"tag_name"' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
echo "${RELEASE}" >/opt/${APP}_version.txt
mkdir -p /opt/paymenter
cd /opt/paymenter
wget -q "https://github.com/paymenter/paymenter/releases/download/${RELEASE}/paymenter.tar.gz"
$STD tar -xzvf paymenter.tar.gz
chmod -R 755 storage/* bootstrap/cache/
msg_ok "Installed Paymenter"
msg_info "Setting up database"
DB_NAME=paymenter
DB_USER=paymenter
DB_PASS=$(openssl rand -base64 18 | tr -dc 'a-zA-Z0-9' | head -c13)
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql mysql
mysql -u root -e "CREATE DATABASE $DB_NAME;"
mysql -u root -e "CREATE USER '$DB_USER'@'localhost' IDENTIFIED BY '$DB_PASS';"
mysql -u root -e "GRANT ALL PRIVILEGES ON $DB_NAME.* TO '$DB_USER'@'localhost' WITH GRANT OPTION;"
{
echo "Paymenter Database Credentials"
echo "Database: $DB_NAME"
echo "Username: $DB_USER"
echo "Password: $DB_PASS"
} >> ~/paymenter_db.creds
cp .env.example .env
$STD composer install --no-dev --optimize-autoloader --no-interaction
$STD php artisan key:generate --force
$STD php artisan storage:link
sed -i "s/^DB_DATABASE=.*/DB_DATABASE=${DB_NAME}/" .env
sed -i "s/^DB_USERNAME=.*/DB_USERNAME=${DB_USER}/" .env
sed -i "s/^DB_PASSWORD=.*/DB_PASSWORD=${DB_PASS}/" .env
$STD php artisan migrate --force --seed
msg_ok "Set up database"
msg_info "Creating Admin User"
$STD php artisan p:user:create <<EOF
admin@paymenter.org
paymenter
admin
paymenter
0
EOF
msg_ok "Created Admin User"
msg_info "Configuring Nginx"
cat <<EOF >/etc/nginx/sites-available/paymenter.conf
server {
listen 80;
listen [::]:80;
server_name localhost;
root /opt/paymenter/public;
index index.php;
location / {
try_files \$uri \$uri/ /index.php?\$query_string;
}
location ~ \.php\$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
EOF
ln -s /etc/nginx/sites-available/paymenter.conf /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default
$STD systemctl reload nginx
chown -R www-data:www-data /opt/paymenter/*
msg_ok "Configured Nginx"
msg_info "Setting up Cronjob"
echo "* * * * * php /opt/paymenter/artisan schedule:run >> /dev/null 2>&1" | crontab -
msg_ok "Setup Cronjob"
msg_info "Setting up Service"
cat <<EOF >/etc/systemd/system/paymenter.service
[Unit]
Description=Paymenter Queue Worker
[Service]
User=www-data
Group=www-data
Restart=always
ExecStart=/usr/bin/php /opt/paymenter/artisan queue:work
StartLimitInterval=180
StartLimitBurst=30
RestartSec=5s
[Install]
WantedBy=multi-user.target
EOF
$STD systemctl enable --now paymenter.service
msg_ok "Setup Service"
msg_info "Cleaning up"
rm -rf /opt/paymenter/paymenter.tar.gz
$STD apt-get -y autoremove
$STD apt-get -y autoclean
msg_ok "Cleaned"
motd_ssh
customize

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"

View File

@@ -22,8 +22,8 @@ msg_ok "Installed Dependencies"
RELEASE=$(curl -s https://api.github.com/repos/TriliumNext/Notes/releases/latest | grep "tag_name" | awk '{print substr($2, 2, length($2)-3) }')
msg_info "Installing TriliumNext"
wget -q https://github.com/TriliumNext/Notes/releases/download/${RELEASE}/TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
tar -xf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
wget -q https://github.com/TriliumNext/Notes/releases/download/${RELEASE}/TriliumNextNotes-linux-x64-${RELEASE}.tar.xz
tar -xf TriliumNextNotes-linux-x64-${RELEASE}.tar.xz
mv trilium-linux-x64-server /opt/trilium
msg_ok "Installed TriliumNext"
@@ -53,5 +53,5 @@ customize
msg_info "Cleaning up"
$STD apt-get -y autoremove
$STD apt-get -y autoclean
rm -rf TriliumNextNotes-${RELEASE}-server-linux-x64.tar.xz
rm -rf TriliumNextNotes-linux-x64-${RELEASE}.tar.xz
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": []
}

34
json/paymenter.json Normal file
View File

@@ -0,0 +1,34 @@
{
"name": "Paymenter",
"slug": "paymenter",
"categories": [
21
],
"date_created": "2025-01-28",
"type": "ct",
"updateable": true,
"privileged": false,
"interface_port": 80,
"documentation": "https://paymenter.org/docs",
"website": "https://paymenter.org/",
"logo": "https://avatars.githubusercontent.com/u/115177786?s=200&v=4",
"description": "Paymenter is an open source webshop solution for hosting companies. It's developed to provide an more easy way to manage your hosting company.",
"install_methods": [
{
"type": "default",
"script": "ct/paymenter.sh",
"resources": {
"cpu": 2,
"ram": 1024,
"hdd": 5,
"os":"Debian",
"version":"12"
}
}
],
"default_credentials": {
"username": "admin@paymenter.org",
"password": "paymenter"
},
"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,14 +1,17 @@
# Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster)
# Co-Author: MickLesk
# License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
# Co-Author: michelroegl-brunner
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
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.
@@ -137,13 +140,13 @@ 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.
@@ -359,34 +362,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
@@ -431,7 +434,7 @@ advanced_settings() {
"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 +447,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,12 +455,12 @@ 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
@@ -470,7 +473,7 @@ advanced_settings() {
"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
@@ -550,7 +553,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"
@@ -742,13 +744,13 @@ 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}"
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
@@ -789,6 +791,152 @@ advanced_settings() {
fi
}
post_to_api() {
if [ "$DIAGNOSTICS" = "no" ]; then
return 0
fi
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 [ "$DIAGNOSTICS" = "no" ]; then
return 0
fi
if [ "$POST_UPDATE_DONE" = true ]; then
return 0
fi
local API_URL="http://api.community-scripts.org/upload/updatestatus"
local status="${1:-failed}"
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 +944,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 +953,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 +968,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 +1082,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 +1090,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 +1186,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 +1201,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 +1230,7 @@ description() {
</span>
</div>
EOF
)
)
# Set Description in LXC
pct set "$CTID" -description "$DESCRIPTION"
@@ -1063,4 +1238,11 @@ EOF
if [[ -f /etc/systemd/system/ping-instances.service ]]; then
systemctl start ping-instances.service
fi
post_update_to_api "done"
}
trap 'post_update_to_api "failed"' 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..."