Compare commits

..

17 Commits

Author SHA1 Message Date
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
12 changed files with 824 additions and 79 deletions

1
.github/FUNDING.yml vendored
View File

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

View File

@@ -17,6 +17,26 @@ 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 Do not break established syntax in this file, as it is automatically updated by a Github Workflow
## 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 ## 2025-01-28
### Changed ### Changed

View File

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

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

@@ -38,6 +38,7 @@
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"react": "19.0.0-rc-02c0e824-20241028", "react": "19.0.0-rc-02c0e824-20241028",
"react-code-blocks": "^0.1.6", "react-code-blocks": "^0.1.6",
"react-datepicker": "^7.6.0",
"react-day-picker": "8.10.1", "react-day-picker": "8.10.1",
"react-dom": "19.0.0-rc-02c0e824-20241028", "react-dom": "19.0.0-rc-02c0e824-20241028",
"react-icons": "^5.1.0", "react-icons": "^5.1.0",
@@ -1083,9 +1084,9 @@
} }
}, },
"node_modules/@floating-ui/utils": { "node_modules/@floating-ui/utils": {
"version": "0.2.8", "version": "0.2.9",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz",
"integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==", "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@humanfs/core": { "node_modules/@humanfs/core": {
@@ -8017,6 +8018,46 @@
"react": ">=16" "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": { "node_modules/react-day-picker": {
"version": "8.10.1", "version": "8.10.1",
"resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz", "resolved": "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz",
@@ -9055,6 +9096,12 @@
"dev": true, "dev": true,
"license": "MIT" "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": { "node_modules/tailwind-merge": {
"version": "2.5.4", "version": "2.5.4",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",

View File

@@ -49,6 +49,7 @@
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"react": "19.0.0-rc-02c0e824-20241028", "react": "19.0.0-rc-02c0e824-20241028",
"react-code-blocks": "^0.1.6", "react-code-blocks": "^0.1.6",
"react-datepicker": "^7.6.0",
"react-day-picker": "8.10.1", "react-day-picker": "8.10.1",
"react-dom": "19.0.0-rc-02c0e824-20241028", "react-dom": "19.0.0-rc-02c0e824-20241028",
"react-icons": "^5.1.0", "react-icons": "^5.1.0",

View File

@@ -0,0 +1,236 @@
"use client";
import React, { useEffect, useState } from "react";
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { string } from "zod";
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;
}
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);
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>
<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={5}>5</option>
<option value={10}>10</option>
<option value={20}>20</option>
<option value={50}>50</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('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.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,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

@@ -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"
}
]
}

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

@@ -1,6 +1,7 @@
# Copyright (c) 2021-2025 tteck # Copyright (c) 2021-2025 tteck
# Author: tteck (tteckster) # Author: tteck (tteckster)
# Co-Author: MickLesk # Co-Author: MickLesk
# Co-Author: michelroegl-brunner
# License: MIT # License: MIT
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE # https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
@@ -8,7 +9,9 @@ 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. 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. 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. 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.
} }
# This function sets various color variables using ANSI escape codes for formatting text in the terminal. # This function sets various color variables using ANSI escape codes for formatting text in the terminal.
@@ -143,10 +146,10 @@ pve_check() {
echo -e "Exiting..." echo -e "Exiting..."
sleep 2 sleep 2
exit 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. # 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 # https://cleveruptime.com/docs/files/proc-key-users | https://docs.kernel.org/security/keys/core.html
maxkeys_check() { maxkeys_check() {
@@ -222,11 +225,11 @@ get_current_ip() {
# Function to update the IP address in the MOTD file # Function to update the IP address in the MOTD file
update_motd_ip() { update_motd_ip() {
MOTD_FILE="/etc/motd" MOTD_FILE="/etc/motd"
if [ -f "$MOTD_FILE" ]; then if [ -f "$MOTD_FILE" ]; then
# Remove existing IP Address lines to prevent duplication # Remove existing IP Address lines to prevent duplication
sed -i '/IP Address:/d' "$MOTD_FILE" sed -i '/IP Address:/d' "$MOTD_FILE"
IP=$(get_current_ip) IP=$(get_current_ip)
# Add the new IP address # Add the new IP address
echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >> "$MOTD_FILE" echo -e "${TAB}${NETWORK}${YW} IP Address: ${GN}${IP}${CL}" >> "$MOTD_FILE"
@@ -359,34 +362,34 @@ exit_script() {
advanced_settings() { 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 "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 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_default_os="${var_os}"
var_os="" var_os=""
while [ -z "$var_os" ]; do while [ -z "$var_os" ]; do
if [ "$var_default_os" == "debian" ]; then if [ "$var_default_os" == "debian" ]; then
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \ if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
"debian" "" ON \ "debian" "" ON \
"ubuntu" "" OFF \ "ubuntu" "" OFF \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
if [ -n "$var_os" ]; then if [ -n "$var_os" ]; then
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
fi
else
exit_script
fi fi
else
exit_script
fi fi
if [ "$var_default_os" == "ubuntu" ]; then fi
if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \ if [ "$var_default_os" == "ubuntu" ]; then
"debian" "" OFF \ if var_os=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DISTRIBUTION" --radiolist "Choose Distribution" 10 58 2 \
"ubuntu" "" ON \ "debian" "" OFF \
3>&1 1>&2 2>&3); then "ubuntu" "" ON \
if [ -n "$var_os" ]; then 3>&1 1>&2 2>&3); then
echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}" if [ -n "$var_os" ]; then
fi echo -e "${OS}${BOLD}${DGN}Operating System: ${BGN}$var_os${CL}"
else
exit_script
fi fi
else
exit_script
fi fi
fi
done done
fi fi
@@ -394,7 +397,7 @@ advanced_settings() {
var_default_version="${var_version}" var_default_version="${var_version}"
var_version="" var_version=""
while [ -z "$var_version" ]; do 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 \ if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "DEBIAN VERSION" --radiolist "Choose Version" 10 58 2 \
"11" "Bullseye" ON \ "11" "Bullseye" ON \
"12" "Bookworm" OFF \ "12" "Bookworm" OFF \
@@ -425,13 +428,13 @@ advanced_settings() {
var_default_version="${var_version}" var_default_version="${var_version}"
var_version="" var_version=""
while [ -z "$var_version" ]; do 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 \ if var_version=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "UBUNTU VERSION" --radiolist "Choose Version" 10 58 4 \
"20.04" "Focal" ON \ "20.04" "Focal" ON \
"22.04" "Jammy" OFF \ "22.04" "Jammy" OFF \
"24.04" "Noble" OFF \ "24.04" "Noble" OFF \
"24.10" "Oracular" OFF \ "24.10" "Oracular" OFF \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi fi
@@ -444,7 +447,7 @@ advanced_settings() {
"22.04" "Jammy" ON \ "22.04" "Jammy" ON \
"24.04" "Noble" OFF \ "24.04" "Noble" OFF \
"24.10" "Oracular" OFF \ "24.10" "Oracular" OFF \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi fi
@@ -452,25 +455,25 @@ advanced_settings() {
exit_script exit_script
fi fi
elif [ "$var_default_version" == "24.04" ]; then 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 \ "20.04" "Focal" OFF \
"22.04" "Jammy" OFF \ "22.04" "Jammy" OFF \
"24.04" "Noble" ON \ "24.04" "Noble" ON \
"24.10" "Oracular" OFF \ "24.10" "Oracular" OFF \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi fi
else else
exit_script exit_script
fi fi
else else
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 \ "20.04" "Focal" OFF \
"22.04" "Jammy" OFF \ "22.04" "Jammy" OFF \
"24.04" "Noble" OFF \ "24.04" "Noble" OFF \
"24.10" "Oracular" ON \ "24.10" "Oracular" ON \
3>&1 1>&2 2>&3); then 3>&1 1>&2 2>&3); then
if [ -n "$var_version" ]; then if [ -n "$var_version" ]; then
echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}" echo -e "${OSVERSION}${BOLD}${DGN}Version: ${BGN}$var_version${CL}"
fi fi
@@ -485,7 +488,7 @@ advanced_settings() {
CT_DEFAULT_TYPE="${CT_TYPE}" CT_DEFAULT_TYPE="${CT_TYPE}"
CT_TYPE="" CT_TYPE=""
while [ -z "$CT_TYPE" ]; do 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 \ if CT_TYPE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "CONTAINER TYPE" --radiolist "Choose Type" 10 58 2 \
"1" "Unprivileged" ON \ "1" "Unprivileged" ON \
"0" "Privileged" OFF \ "0" "Privileged" OFF \
@@ -550,7 +553,6 @@ advanced_settings() {
fi fi
done 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 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 if [ -z "$CT_ID" ]; then
CT_ID="$NEXTID" CT_ID="$NEXTID"
@@ -741,14 +743,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 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 if [ -n "${ADV_TAGS}" ]; then
ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]') ADV_TAGS=$(echo "$ADV_TAGS" | tr -d '[:space:]')
TAGS="${ADV_TAGS}" TAGS="${ADV_TAGS}"
else else
TAGS=";" TAGS=";"
fi fi
echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}" echo -e "${NETWORK}${BOLD}${DGN}Tags: ${BGN}$TAGS${CL}"
else else
exit_script exit_script
fi fi
if [[ "$PW" == -password* ]]; then if [[ "$PW" == -password* ]]; then
@@ -771,7 +773,7 @@ advanced_settings() {
fi fi
else else
SSH_AUTHORIZED_KEY="" SSH_AUTHORIZED_KEY=""
fi fi
if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then if (whiptail --backtitle "Proxmox VE Helper Scripts" --defaultno --title "VERBOSE MODE" --yesno "Enable Verbose Mode?" 10 58); then
VERB="yes" VERB="yes"
else else
@@ -789,6 +791,116 @@ advanced_settings() {
fi 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"
}
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
}
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() { install_script() {
pve_check pve_check
shell_check shell_check
@@ -796,6 +908,7 @@ install_script() {
arch_check arch_check
ssh_check ssh_check
maxkeys_check maxkeys_check
diagnostics_check
if systemctl is-active -q ping-instances.service; then if systemctl is-active -q ping-instances.service; then
systemctl -q stop ping-instances.service systemctl -q stop ping-instances.service
@@ -804,12 +917,14 @@ install_script() {
timezone=$(cat /etc/timezone) timezone=$(cat /etc/timezone)
header_info header_info
while true; do while true; do
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --menu "Choose an option:" \ CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "SETTINGS" --menu "Choose an option:" \
12 50 4 \ 12 50 5 \
"1" "Default Settings" \ "1" "Default Settings" \
"2" "Default Settings (with verbose)" \ "2" "Default Settings (with verbose)" \
"3" "Advanced Settings" \ "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 if [ $? -ne 0 ]; then
echo -e "${CROSS}${RD} Menu canceled. Exiting.${CL}" echo -e "${CROSS}${RD} Menu canceled. Exiting.${CL}"
@@ -817,35 +932,55 @@ install_script() {
fi fi
case $CHOICE in case $CHOICE in
1) 1)
header_info header_info
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}" echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME${CL}"
VERB="no" VERB="no"
base_settings "$VERB" METHOD="default"
echo_default base_settings "$VERB"
break echo_default
;; break
2) ;;
header_info 2)
echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}" header_info
VERB="yes" echo -e "${DEFAULT}${BOLD}${BL}Using Default Settings on node $PVEHOST_NAME (${SEARCH}Verbose)${CL}"
base_settings "$VERB" VERB="yes"
echo_default METHOD="default"
break base_settings "$VERB"
;; echo_default
3) break
header_info ;;
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}" 3)
advanced_settings header_info
break echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings on node $PVEHOST_NAME${CL}"
;; METHOD="advanced"
4) advanced_settings
echo -e "${CROSS}${RD}Exiting.${CL}" break
exit 0 ;;
;; 4)
*) if [[ $DIAGNOSTICS == "yes" ]]; then
echo -e "${CROSS}${RD}Invalid option, please try again.${CL}" 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 esac
done done
} }
@@ -911,7 +1046,7 @@ start() {
# This function collects user settings and integrates all the collected information. # This function collects user settings and integrates all the collected information.
build_container() { build_container() {
# if [ "$VERB" == "yes" ]; then set -x; fi # if [ "$VERB" == "yes" ]; then set -x; fi
if [ "$CT_TYPE" == "1" ]; then if [ "$CT_TYPE" == "1" ]; then
FEATURES="keyctl=1,nesting=1" FEATURES="keyctl=1,nesting=1"
@@ -919,6 +1054,9 @@ build_container() {
FEATURES="nesting=1" FEATURES="nesting=1"
fi fi
if [[ $DIAGNOSTICS == "yes" ]]; then
post_to_api
fi
TEMP_DIR=$(mktemp -d) TEMP_DIR=$(mktemp -d)
pushd $TEMP_DIR >/dev/null pushd $TEMP_DIR >/dev/null
@@ -1012,7 +1150,7 @@ EOF
msg_ok "Started LXC Container" msg_ok "Started LXC Container"
if [ "$var_os" == "alpine" ]; then if [ "$var_os" == "alpine" ]; then
sleep 3 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/main
http://dl-cdn.alpinelinux.org/alpine/latest-stable/community http://dl-cdn.alpinelinux.org/alpine/latest-stable/community
EOF' EOF'
@@ -1027,7 +1165,8 @@ description() {
IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1) IP=$(pct exec "$CTID" ip a s dev eth0 | awk '/inet / {print $2}' | cut -d/ -f1)
# Generate LXC Description # Generate LXC Description
DESCRIPTION=$(cat <<EOF DESCRIPTION=$(
cat <<EOF
<div align='center'> <div align='center'>
<a href='https://Helper-Scripts.com' target='_blank' rel='noopener noreferrer'> <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;'/> <img src='https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/images/logo-81x112.png' alt='Logo' style='width:81px;height:112px;'/>
@@ -1055,7 +1194,7 @@ description() {
</span> </span>
</div> </div>
EOF EOF
) )
# Set Description in LXC # Set Description in LXC
pct set "$CTID" -description "$DESCRIPTION" pct set "$CTID" -description "$DESCRIPTION"

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"