mirror of
https://github.com/community-scripts/ProxmoxVE.git
synced 2026-02-17 18:53:27 +01:00
Compare commits
14 Commits
add-script
...
github-act
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62a66433f2 | ||
|
|
3ce3c6f613 | ||
|
|
97652792be | ||
|
|
f07f2cb04e | ||
|
|
5f73f9d5e6 | ||
|
|
0183ae0fff | ||
|
|
32d1937a74 | ||
|
|
0a7bd20b06 | ||
|
|
c9ecb1ccca | ||
|
|
d274a269b5 | ||
|
|
cbee9d64b5 | ||
|
|
ffcda217e3 | ||
|
|
438d5d6b94 | ||
|
|
104366bc64 |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -406,6 +406,10 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
## 2026-02-17
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
- Databasus ([#12018](https://github.com/community-scripts/ProxmoxVE/pull/12018))
|
||||
|
||||
### 🚀 Updated Scripts
|
||||
|
||||
- #### 🐞 Bug Fixes
|
||||
@@ -418,6 +422,21 @@ Exercise vigilance regarding copycat or coat-tailing sites that seek to exploit
|
||||
|
||||
- core: call get_lxc_ip in start() before updates [@MickLesk](https://github.com/MickLesk) ([#12015](https://github.com/community-scripts/ProxmoxVE/pull/12015))
|
||||
|
||||
- #### ✨ New Features
|
||||
|
||||
- tools/pve: add data analytics / formatting / linting [@MickLesk](https://github.com/MickLesk) ([#12034](https://github.com/community-scripts/ProxmoxVE/pull/12034))
|
||||
- core: smart recovery for failed installs | extend exit_codes [@MickLesk](https://github.com/MickLesk) ([#11221](https://github.com/community-scripts/ProxmoxVE/pull/11221))
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- core: error-handler improvements | better exit_code handling | better tools.func source check [@MickLesk](https://github.com/MickLesk) ([#12019](https://github.com/community-scripts/ProxmoxVE/pull/12019))
|
||||
|
||||
### 🧰 Tools
|
||||
|
||||
- #### 🔧 Refactor
|
||||
|
||||
- Immich Public Proxy: centralize and fix systemd service creation [@MickLesk](https://github.com/MickLesk) ([#12025](https://github.com/community-scripts/ProxmoxVE/pull/12025))
|
||||
|
||||
## 2026-02-16
|
||||
|
||||
### 🆕 New Scripts
|
||||
|
||||
6
ct/headers/databasus
Normal file
6
ct/headers/databasus
Normal file
@@ -0,0 +1,6 @@
|
||||
____ __ __
|
||||
/ __ \____ _/ /_____ _/ /_ ____ ________ _______
|
||||
/ / / / __ `/ __/ __ `/ __ \/ __ `/ ___/ / / / ___/
|
||||
/ /_/ / /_/ / /_/ /_/ / /_/ / /_/ (__ ) /_/ (__ )
|
||||
/_____/\__,_/\__/\__,_/_.___/\__,_/____/\__,_/____/
|
||||
|
||||
@@ -1,44 +1,44 @@
|
||||
{
|
||||
"name": "Databasus",
|
||||
"slug": "databasus",
|
||||
"categories": [
|
||||
7
|
||||
],
|
||||
"date_created": "2025-01-14",
|
||||
"type": "ct",
|
||||
"updateable": true,
|
||||
"privileged": false,
|
||||
"interface_port": 80,
|
||||
"documentation": "https://github.com/databasus/databasus",
|
||||
"website": "https://github.com/databasus/databasus",
|
||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/databasus.webp",
|
||||
"config_path": "/opt/databasus/.env",
|
||||
"description": "Free, open source and self-hosted solution for automated PostgreSQL backups. With multiple storage options, notifications, scheduling, and a beautiful web interface for managing database backups across multiple PostgreSQL instances.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "ct/databasus.sh",
|
||||
"resources": {
|
||||
"cpu": 2,
|
||||
"ram": 2048,
|
||||
"hdd": 8,
|
||||
"os": "Debian",
|
||||
"version": "13"
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": "admin@localhost",
|
||||
"password": "See /root/databasus.creds"
|
||||
"name": "Databasus",
|
||||
"slug": "databasus",
|
||||
"categories": [
|
||||
7
|
||||
],
|
||||
"date_created": "2026-02-17",
|
||||
"type": "ct",
|
||||
"updateable": true,
|
||||
"privileged": false,
|
||||
"interface_port": 80,
|
||||
"documentation": "https://github.com/databasus/databasus",
|
||||
"website": "https://github.com/databasus/databasus",
|
||||
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/databasus.webp",
|
||||
"config_path": "/opt/databasus/.env",
|
||||
"description": "Free, open source and self-hosted solution for automated PostgreSQL backups. With multiple storage options, notifications, scheduling, and a beautiful web interface for managing database backups across multiple PostgreSQL instances.",
|
||||
"install_methods": [
|
||||
{
|
||||
"type": "default",
|
||||
"script": "ct/databasus.sh",
|
||||
"resources": {
|
||||
"cpu": 2,
|
||||
"ram": 2048,
|
||||
"hdd": 8,
|
||||
"os": "Debian",
|
||||
"version": "13"
|
||||
}
|
||||
}
|
||||
],
|
||||
"default_credentials": {
|
||||
"username": "admin@localhost",
|
||||
"password": "See /root/databasus.creds"
|
||||
},
|
||||
"notes": [
|
||||
{
|
||||
"text": "Supports PostgreSQL versions 12-18 with cloud and self-hosted instances",
|
||||
"type": "info"
|
||||
},
|
||||
"notes": [
|
||||
{
|
||||
"text": "Supports PostgreSQL versions 12-18 with cloud and self-hosted instances",
|
||||
"type": "info"
|
||||
},
|
||||
{
|
||||
"text": "Features: Scheduled backups, multiple storage providers, notifications, encryption",
|
||||
"type": "info"
|
||||
}
|
||||
]
|
||||
{
|
||||
"text": "Features: Scheduled backups, multiple storage providers, notifications, encryption",
|
||||
"type": "info"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"generated": "2026-02-17T06:22:06Z",
|
||||
"generated": "2026-02-17T12:14:18Z",
|
||||
"versions": [
|
||||
{
|
||||
"slug": "2fauth",
|
||||
@@ -158,9 +158,9 @@
|
||||
{
|
||||
"slug": "bookstack",
|
||||
"repo": "BookStackApp/BookStack",
|
||||
"version": "v25.12.3",
|
||||
"version": "v25.12.4",
|
||||
"pinned": false,
|
||||
"date": "2026-01-29T15:29:25Z"
|
||||
"date": "2026-02-17T11:44:48Z"
|
||||
},
|
||||
{
|
||||
"slug": "byparr",
|
||||
@@ -207,9 +207,9 @@
|
||||
{
|
||||
"slug": "comfyui",
|
||||
"repo": "comfyanonymous/ComfyUI",
|
||||
"version": "v0.13.0",
|
||||
"version": "v0.14.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-10T20:27:38Z"
|
||||
"date": "2026-02-17T06:29:10Z"
|
||||
},
|
||||
{
|
||||
"slug": "commafeed",
|
||||
@@ -253,6 +253,13 @@
|
||||
"pinned": false,
|
||||
"date": "2026-02-11T15:39:05Z"
|
||||
},
|
||||
{
|
||||
"slug": "databasus",
|
||||
"repo": "databasus/databasus",
|
||||
"version": "v3.12.2",
|
||||
"pinned": false,
|
||||
"date": "2026-02-14T22:28:59Z"
|
||||
},
|
||||
{
|
||||
"slug": "dawarich",
|
||||
"repo": "Freika/dawarich",
|
||||
@@ -550,9 +557,9 @@
|
||||
{
|
||||
"slug": "huntarr",
|
||||
"repo": "plexguide/Huntarr.io",
|
||||
"version": "9.2.4.1",
|
||||
"version": "9.3.0",
|
||||
"pinned": false,
|
||||
"date": "2026-02-12T22:17:47Z"
|
||||
"date": "2026-02-17T06:34:38Z"
|
||||
},
|
||||
{
|
||||
"slug": "immich-public-proxy",
|
||||
@@ -781,9 +788,9 @@
|
||||
{
|
||||
"slug": "mail-archiver",
|
||||
"repo": "s1t5/mail-archiver",
|
||||
"version": "2602.1",
|
||||
"version": "2602.2",
|
||||
"pinned": false,
|
||||
"date": "2026-02-11T06:23:11Z"
|
||||
"date": "2026-02-17T09:46:52Z"
|
||||
},
|
||||
{
|
||||
"slug": "managemydamnlife",
|
||||
@@ -1103,9 +1110,9 @@
|
||||
{
|
||||
"slug": "pocketbase",
|
||||
"repo": "pocketbase/pocketbase",
|
||||
"version": "v0.36.3",
|
||||
"version": "v0.36.4",
|
||||
"pinned": false,
|
||||
"date": "2026-02-13T18:38:58Z"
|
||||
"date": "2026-02-17T08:02:51Z"
|
||||
},
|
||||
{
|
||||
"slug": "pocketid",
|
||||
@@ -1481,9 +1488,9 @@
|
||||
{
|
||||
"slug": "threadfin",
|
||||
"repo": "threadfin/threadfin",
|
||||
"version": "1.2.37",
|
||||
"version": "delete",
|
||||
"pinned": false,
|
||||
"date": "2025-09-11T16:13:41Z"
|
||||
"date": ""
|
||||
},
|
||||
{
|
||||
"slug": "tianji",
|
||||
|
||||
@@ -14,6 +14,25 @@ catch_errors
|
||||
# Get LXC IP address (must be called INSIDE container, after network is up)
|
||||
get_lxc_ip
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# post_progress_to_api()
|
||||
#
|
||||
# - Lightweight progress ping from inside the container
|
||||
# - Updates the existing telemetry record status from "installing" to "configuring"
|
||||
# - Signals that the installation is actively progressing (not stuck)
|
||||
# - Fire-and-forget: never blocks or fails the script
|
||||
# - Only executes if DIAGNOSTICS=yes and RANDOM_UUID is set
|
||||
# ------------------------------------------------------------------------------
|
||||
post_progress_to_api() {
|
||||
command -v curl &>/dev/null || return 0
|
||||
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
|
||||
[[ -z "${RANDOM_UUID:-}" ]] && return 0
|
||||
|
||||
curl -fsS -m 5 -X POST "https://telemetry.community-scripts.org/telemetry" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"random_id\":\"${RANDOM_UUID}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
|
||||
}
|
||||
|
||||
# This function enables IPv6 if it's not disabled and sets verbose mode
|
||||
verb_ip6() {
|
||||
set_std_mode # Set STD mode based on VERBOSE
|
||||
@@ -53,6 +72,7 @@ setting_up_container() {
|
||||
fi
|
||||
msg_ok "Set up Container OS"
|
||||
msg_ok "Network Connected: ${BL}$(ip addr show | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1 | tail -n1)${CL}"
|
||||
post_progress_to_api
|
||||
}
|
||||
|
||||
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
||||
@@ -85,8 +105,18 @@ network_check() {
|
||||
update_os() {
|
||||
msg_info "Updating Container OS"
|
||||
$STD apk -U upgrade
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
local tools_content
|
||||
tools_content=$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func) || {
|
||||
msg_error "Failed to download tools.func"
|
||||
exit 6
|
||||
}
|
||||
source /dev/stdin <<<"$tools_content"
|
||||
if ! declare -f fetch_and_deploy_gh_release >/dev/null 2>&1; then
|
||||
msg_error "tools.func loaded but incomplete — missing expected functions"
|
||||
exit 6
|
||||
fi
|
||||
msg_ok "Updated Container OS"
|
||||
post_progress_to_api
|
||||
}
|
||||
|
||||
# This function modifies the message of the day (motd) and SSH settings
|
||||
|
||||
104
misc/api.func
104
misc/api.func
@@ -117,16 +117,17 @@ detect_repo_source
|
||||
# - Canonical source of truth for ALL exit code mappings
|
||||
# - Used by both api.func (telemetry) and error_handler.func (error display)
|
||||
# - Supports:
|
||||
# * Generic/Shell errors (1, 2, 124, 126-130, 134, 137, 139, 141, 143)
|
||||
# * curl/wget errors (6, 7, 22, 28, 35)
|
||||
# * Generic/Shell errors (1-3, 10, 124-132, 134, 137, 139, 141, 143-146)
|
||||
# * curl/wget errors (4-8, 16, 18, 22-28, 30, 32-36, 39, 44-48, 51-52, 55-57, 59, 61, 63, 75, 78-79, 92, 95)
|
||||
# * Package manager errors (APT, DPKG: 100-102, 255)
|
||||
# * BSD sysexits (64-78)
|
||||
# * Systemd/Service errors (150-154)
|
||||
# * Python/pip/uv errors (160-162)
|
||||
# * PostgreSQL errors (170-173)
|
||||
# * MySQL/MariaDB errors (180-183)
|
||||
# * MongoDB errors (190-193)
|
||||
# * Proxmox custom codes (200-231)
|
||||
# * Node.js/npm errors (243, 245-249)
|
||||
# * Node.js/npm errors (239, 243, 245-249)
|
||||
# - Returns description string for given exit code
|
||||
# ------------------------------------------------------------------------------
|
||||
explain_exit_code() {
|
||||
@@ -135,6 +136,7 @@ explain_exit_code() {
|
||||
# --- Generic / Shell ---
|
||||
1) echo "General error / Operation not permitted" ;;
|
||||
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
||||
3) echo "General syntax or argument error" ;;
|
||||
10) echo "Docker / privileged mode required (unsupported environment)" ;;
|
||||
|
||||
# --- curl / wget errors (commonly seen in downloads) ---
|
||||
@@ -142,16 +144,41 @@ explain_exit_code() {
|
||||
5) echo "curl: Could not resolve proxy" ;;
|
||||
6) echo "curl: DNS resolution failed (could not resolve host)" ;;
|
||||
7) echo "curl: Failed to connect (network unreachable / host down)" ;;
|
||||
8) echo "curl: FTP server reply error" ;;
|
||||
8) echo "curl: Server reply error (FTP/SFTP or apk untrusted key)" ;;
|
||||
16) echo "curl: HTTP/2 framing layer error" ;;
|
||||
18) echo "curl: Partial file (transfer not completed)" ;;
|
||||
22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
|
||||
23) echo "curl: Write error (disk full or permissions)" ;;
|
||||
24) echo "curl: Write to local file failed" ;;
|
||||
25) echo "curl: Upload failed" ;;
|
||||
26) echo "curl: Read error on local file (I/O)" ;;
|
||||
27) echo "curl: Out of memory (memory allocation failed)" ;;
|
||||
28) echo "curl: Operation timeout (network slow or server not responding)" ;;
|
||||
30) echo "curl: FTP port command failed" ;;
|
||||
32) echo "curl: FTP SIZE command failed" ;;
|
||||
33) echo "curl: HTTP range error" ;;
|
||||
34) echo "curl: HTTP post error" ;;
|
||||
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
|
||||
36) echo "curl: FTP bad download resume" ;;
|
||||
39) echo "curl: LDAP search failed" ;;
|
||||
44) echo "curl: Internal error (bad function call order)" ;;
|
||||
45) echo "curl: Interface error (failed to bind to specified interface)" ;;
|
||||
46) echo "curl: Bad password entered" ;;
|
||||
47) echo "curl: Too many redirects" ;;
|
||||
48) echo "curl: Unknown command line option specified" ;;
|
||||
51) echo "curl: SSL peer certificate or SSH host key verification failed" ;;
|
||||
52) echo "curl: Empty reply from server (got nothing)" ;;
|
||||
55) echo "curl: Failed sending network data" ;;
|
||||
56) echo "curl: Receive error (connection reset by peer)" ;;
|
||||
57) echo "curl: Unrecoverable poll/select error (system I/O failure)" ;;
|
||||
59) echo "curl: Couldn't use specified SSL cipher" ;;
|
||||
61) echo "curl: Bad/unrecognized transfer encoding" ;;
|
||||
63) echo "curl: Maximum file size exceeded" ;;
|
||||
75) echo "Temporary failure (retry later)" ;;
|
||||
78) echo "curl: Remote file not found (404 on FTP/file)" ;;
|
||||
79) echo "curl: SSH session error (key exchange/auth failed)" ;;
|
||||
92) echo "curl: HTTP/2 stream error (protocol violation)" ;;
|
||||
95) echo "curl: HTTP/3 layer error" ;;
|
||||
|
||||
# --- Package manager / APT / DPKG ---
|
||||
100) echo "APT: Package manager error (broken packages / dependency problems)" ;;
|
||||
@@ -175,15 +202,21 @@ explain_exit_code() {
|
||||
|
||||
# --- Common shell/system errors ---
|
||||
124) echo "Command timed out (timeout command)" ;;
|
||||
125) echo "Command failed to start (Docker daemon or execution error)" ;;
|
||||
126) echo "Command invoked cannot execute (permission problem?)" ;;
|
||||
127) echo "Command not found" ;;
|
||||
128) echo "Invalid argument to exit" ;;
|
||||
129) echo "Killed by SIGHUP (terminal closed / hangup)" ;;
|
||||
130) echo "Aborted by user (SIGINT)" ;;
|
||||
131) echo "Killed by SIGQUIT (core dumped)" ;;
|
||||
132) echo "Killed by SIGILL (illegal CPU instruction)" ;;
|
||||
134) echo "Process aborted (SIGABRT - possibly Node.js heap overflow)" ;;
|
||||
137) echo "Killed (SIGKILL / Out of memory?)" ;;
|
||||
139) echo "Segmentation fault (core dumped)" ;;
|
||||
141) echo "Broken pipe (SIGPIPE - output closed prematurely)" ;;
|
||||
143) echo "Terminated (SIGTERM)" ;;
|
||||
144) echo "Killed by signal 16 (SIGUSR1 / SIGSTKFLT)" ;;
|
||||
146) echo "Killed by signal 18 (SIGTSTP)" ;;
|
||||
|
||||
# --- Systemd / Service errors (150-154) ---
|
||||
150) echo "Systemd: Service failed to start" ;;
|
||||
@@ -191,7 +224,6 @@ explain_exit_code() {
|
||||
152) echo "Permission denied (EACCES)" ;;
|
||||
153) echo "Build/compile failed (make/gcc/cmake)" ;;
|
||||
154) echo "Node.js: Native addon build failed (node-gyp)" ;;
|
||||
|
||||
# --- Python / pip / uv (160-162) ---
|
||||
160) echo "Python: Virtualenv / uv environment missing or broken" ;;
|
||||
161) echo "Python: Dependency resolution failed" ;;
|
||||
@@ -242,7 +274,8 @@ explain_exit_code() {
|
||||
225) echo "Proxmox: No template available for OS/Version" ;;
|
||||
231) echo "Proxmox: LXC stack upgrade failed" ;;
|
||||
|
||||
# --- Node.js / npm / pnpm / yarn (243-249) ---
|
||||
# --- Node.js / npm / pnpm / yarn (239-249) ---
|
||||
239) echo "npm/Node.js: Unexpected runtime error or dependency failure" ;;
|
||||
243) echo "Node.js: Out of memory (JavaScript heap out of memory)" ;;
|
||||
245) echo "Node.js: Invalid command-line option" ;;
|
||||
246) echo "Node.js: Internal JavaScript Parse Error" ;;
|
||||
@@ -875,6 +908,9 @@ categorize_error() {
|
||||
# Network errors (curl/wget)
|
||||
6 | 7 | 22 | 35) echo "network" ;;
|
||||
|
||||
# Docker / Privileged mode required
|
||||
10) echo "config" ;;
|
||||
|
||||
# Timeout errors
|
||||
28 | 124 | 211) echo "timeout" ;;
|
||||
|
||||
@@ -949,6 +985,62 @@ get_install_duration() {
|
||||
echo $((now - INSTALL_START_TIME))
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# _telemetry_report_exit()
|
||||
#
|
||||
# - Internal handler called by EXIT trap set in init_tool_telemetry()
|
||||
# - Determines success/failure from exit code and reports via appropriate API
|
||||
# - Arguments:
|
||||
# * $1: exit_code from the script
|
||||
# ------------------------------------------------------------------------------
|
||||
_telemetry_report_exit() {
|
||||
local ec="${1:-0}"
|
||||
local status="success"
|
||||
[[ "$ec" -ne 0 ]] && status="failed"
|
||||
|
||||
# Lazy name resolution: use explicit name, fall back to $APP, then "unknown"
|
||||
local name="${TELEMETRY_TOOL_NAME:-${APP:-unknown}}"
|
||||
|
||||
if [[ "${TELEMETRY_TOOL_TYPE:-tool}" == "addon" ]]; then
|
||||
post_addon_to_api "$name" "$status" "$ec"
|
||||
else
|
||||
post_tool_to_api "$name" "$status" "$ec"
|
||||
fi
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# init_tool_telemetry()
|
||||
#
|
||||
# - One-line telemetry setup for tools/addon scripts
|
||||
# - Reads DIAGNOSTICS from /usr/local/community-scripts/diagnostics
|
||||
# - Starts install timer for duration tracking
|
||||
# - Sets EXIT trap to automatically report success/failure on script exit
|
||||
# - Arguments:
|
||||
# * $1: tool_name (optional, falls back to $APP at exit time)
|
||||
# * $2: type ("tool" for PVE host scripts, "addon" for container addons)
|
||||
# - Usage:
|
||||
# source <(curl -fsSL .../misc/api.func) 2>/dev/null || true
|
||||
# init_tool_telemetry "post-pve-install" "tool"
|
||||
# init_tool_telemetry "" "addon" # uses $APP at exit time
|
||||
# ------------------------------------------------------------------------------
|
||||
init_tool_telemetry() {
|
||||
local name="${1:-}"
|
||||
local type="${2:-tool}"
|
||||
|
||||
[[ -n "$name" ]] && TELEMETRY_TOOL_NAME="$name"
|
||||
TELEMETRY_TOOL_TYPE="$type"
|
||||
|
||||
# Read diagnostics opt-in/opt-out
|
||||
if [[ -f /usr/local/community-scripts/diagnostics ]]; then
|
||||
DIAGNOSTICS=$(grep -i "^DIAGNOSTICS=" /usr/local/community-scripts/diagnostics 2>/dev/null | awk -F'=' '{print $2}') || true
|
||||
fi
|
||||
|
||||
start_install_timer
|
||||
|
||||
# EXIT trap: automatically report telemetry when script ends
|
||||
trap '_telemetry_report_exit "$?"' EXIT
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# post_tool_to_api()
|
||||
#
|
||||
|
||||
332
misc/build.func
332
misc/build.func
@@ -297,7 +297,7 @@ validate_container_id() {
|
||||
# Falls back gracefully if pvesh unavailable or returns empty
|
||||
if command -v pvesh &>/dev/null; then
|
||||
local cluster_ids
|
||||
cluster_ids=$(pvesh get /cluster/resources --type vm --output-format json 2>/dev/null |
|
||||
cluster_ids=$(pvesh get /cluster/resources --type vm --output-format json 2>/dev/null |
|
||||
grep -oP '"vmid":\s*\K[0-9]+' 2>/dev/null || true)
|
||||
if [[ -n "$cluster_ids" ]] && echo "$cluster_ids" | grep -qw "$ctid"; then
|
||||
return 1
|
||||
@@ -4040,6 +4040,13 @@ EOF'
|
||||
|
||||
msg_ok "Customized LXC Container"
|
||||
|
||||
# Optional DNS override for retry scenarios (inside LXC, never on host)
|
||||
if [[ "${DNS_RETRY_OVERRIDE:-false}" == "true" ]]; then
|
||||
msg_info "Applying DNS retry override in LXC (8.8.8.8, 1.1.1.1)"
|
||||
pct exec "$CTID" -- bash -c "printf 'nameserver 8.8.8.8\nnameserver 1.1.1.1\n' >/etc/resolv.conf" >/dev/null 2>&1 || true
|
||||
msg_ok "DNS override applied in LXC"
|
||||
fi
|
||||
|
||||
# Install SSH keys
|
||||
install_ssh_keys_into_ct
|
||||
|
||||
@@ -4152,32 +4159,322 @@ EOF'
|
||||
|
||||
# Prompt user for cleanup with 60s timeout
|
||||
echo ""
|
||||
echo -en "${TAB}❓${TAB}${YW}Remove broken container ${CTID}? (Y/n) [auto-remove in 60s]: ${CL}"
|
||||
|
||||
# Detect error type for smart recovery options
|
||||
local is_oom=false
|
||||
local is_network_issue=false
|
||||
local is_apt_issue=false
|
||||
local is_cmd_not_found=false
|
||||
local error_explanation=""
|
||||
if declare -f explain_exit_code >/dev/null 2>&1; then
|
||||
error_explanation="$(explain_exit_code "$install_exit_code")"
|
||||
fi
|
||||
|
||||
# OOM detection: exit codes 134 (SIGABRT/heap), 137 (SIGKILL/OOM), 243 (Node.js heap)
|
||||
if [[ $install_exit_code -eq 134 || $install_exit_code -eq 137 || $install_exit_code -eq 243 ]]; then
|
||||
is_oom=true
|
||||
fi
|
||||
|
||||
# APT/DPKG detection: exit codes 100-102 (APT), 255 (DPKG with log evidence)
|
||||
case "$install_exit_code" in
|
||||
100 | 101 | 102) is_apt_issue=true ;;
|
||||
255)
|
||||
if [[ -f "$combined_log" ]] && grep -qiE 'dpkg|apt-get|apt\.conf|broken packages|unmet dependencies|E: Sub-process|E: Failed' "$combined_log"; then
|
||||
is_apt_issue=true
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Command not found detection
|
||||
if [[ $install_exit_code -eq 127 ]]; then
|
||||
is_cmd_not_found=true
|
||||
fi
|
||||
|
||||
# Network-related detection (curl/apt/git fetch failures and transient network issues)
|
||||
case "$install_exit_code" in
|
||||
6 | 7 | 22 | 28 | 35 | 52 | 56 | 57 | 75 | 78) is_network_issue=true ;;
|
||||
100)
|
||||
# APT can fail due to network (Failed to fetch)
|
||||
if [[ -f "$combined_log" ]] && grep -qiE 'Failed to fetch|Could not resolve|Connection failed|Network is unreachable|Temporary failure resolving' "$combined_log"; then
|
||||
is_network_issue=true
|
||||
fi
|
||||
;;
|
||||
128)
|
||||
if [[ -f "$combined_log" ]] && grep -qiE 'RPC failed|early EOF|fetch-pack|HTTP/2 stream|Could not resolve host|Temporary failure resolving|Failed to fetch|Connection reset|Network is unreachable' "$combined_log"; then
|
||||
is_network_issue=true
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Exit 1 subclassification: analyze logs to identify actual root cause
|
||||
# Many exit 1 errors are actually APT, OOM, network, or command-not-found issues
|
||||
if [[ $install_exit_code -eq 1 && -f "$combined_log" ]]; then
|
||||
if grep -qiE 'E: Unable to|E: Package|E: Failed to fetch|dpkg.*error|broken packages|unmet dependencies|dpkg --configure -a' "$combined_log"; then
|
||||
is_apt_issue=true
|
||||
fi
|
||||
if grep -qiE 'Cannot allocate memory|Out of memory|oom-killer|Killed process|JavaScript heap' "$combined_log"; then
|
||||
is_oom=true
|
||||
fi
|
||||
if grep -qiE 'Could not resolve|DNS|Connection refused|Network is unreachable|No route to host|Temporary failure resolving|Failed to fetch' "$combined_log"; then
|
||||
is_network_issue=true
|
||||
fi
|
||||
if grep -qiE ': command not found|No such file or directory.*/s?bin/' "$combined_log"; then
|
||||
is_cmd_not_found=true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Show error explanation if available
|
||||
if [[ -n "$error_explanation" ]]; then
|
||||
echo -e "${TAB}${RD}Error: ${error_explanation}${CL}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Show specific hints for known error types
|
||||
if [[ $install_exit_code -eq 10 ]]; then
|
||||
echo -e "${TAB}${INFO} This error usually means the container needs ${GN}privileged${CL} mode or Docker/nesting support."
|
||||
echo -e "${TAB}${INFO} Recreate with: Advanced Install → Container Type: ${GN}Privileged${CL}"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [[ $install_exit_code -eq 125 || $install_exit_code -eq 126 ]]; then
|
||||
echo -e "${TAB}${INFO} The command exists but cannot be executed. This may be a ${GN}permission${CL} issue."
|
||||
echo -e "${TAB}${INFO} If using Docker, ensure the container is ${GN}privileged${CL} or has correct permissions."
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [[ "$is_cmd_not_found" == true ]]; then
|
||||
local missing_cmd=""
|
||||
if [[ -f "$combined_log" ]]; then
|
||||
missing_cmd=$(grep -oiE '[a-zA-Z0-9_.-]+: command not found' "$combined_log" | tail -1 | sed 's/: command not found//')
|
||||
fi
|
||||
if [[ -n "$missing_cmd" ]]; then
|
||||
echo -e "${TAB}${INFO} Missing command: ${GN}${missing_cmd}${CL}"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Build recovery menu based on error type
|
||||
echo -e "${YW}What would you like to do?${CL}"
|
||||
echo ""
|
||||
echo -e " ${GN}1)${CL} Remove container and exit"
|
||||
echo -e " ${GN}2)${CL} Keep container for debugging"
|
||||
echo -e " ${GN}3)${CL} Retry with verbose mode (full rebuild)"
|
||||
|
||||
local next_option=4
|
||||
local APT_OPTION="" OOM_OPTION="" DNS_OPTION=""
|
||||
|
||||
if [[ "$is_apt_issue" == true ]]; then
|
||||
if [[ "$var_os" == "alpine" ]]; then
|
||||
echo -e " ${GN}${next_option})${CL} Repair APK state and re-run install (in-place)"
|
||||
else
|
||||
echo -e " ${GN}${next_option})${CL} Repair APT/DPKG state and re-run install (in-place)"
|
||||
fi
|
||||
APT_OPTION=$next_option
|
||||
next_option=$((next_option + 1))
|
||||
fi
|
||||
|
||||
if [[ "$is_oom" == true ]]; then
|
||||
local recovery_attempt="${RECOVERY_ATTEMPT:-0}"
|
||||
if [[ $recovery_attempt -lt 2 ]]; then
|
||||
local new_ram=$((RAM_SIZE * 2))
|
||||
local new_cpu=$((CORE_COUNT * 2))
|
||||
echo -e " ${GN}${next_option})${CL} Retry with more resources (RAM: ${RAM_SIZE}→${new_ram} MiB, CPU: ${CORE_COUNT}→${new_cpu} cores)"
|
||||
OOM_OPTION=$next_option
|
||||
next_option=$((next_option + 1))
|
||||
else
|
||||
echo -e " ${DGN}-)${CL} ${DGN}OOM retry exhausted (already retried ${recovery_attempt}x)${CL}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$is_network_issue" == true ]]; then
|
||||
echo -e " ${GN}${next_option})${CL} Retry with DNS override in LXC (8.8.8.8 / 1.1.1.1)"
|
||||
DNS_OPTION=$next_option
|
||||
next_option=$((next_option + 1))
|
||||
fi
|
||||
|
||||
local max_option=$((next_option - 1))
|
||||
|
||||
echo ""
|
||||
echo -en "${YW}Select option [1-${max_option}] (default: 1, auto-remove in 60s): ${CL}"
|
||||
|
||||
if read -t 60 -r response; then
|
||||
if [[ -z "$response" || "$response" =~ ^[Yy]$ ]]; then
|
||||
case "${response:-1}" in
|
||||
1)
|
||||
# Remove container
|
||||
echo ""
|
||||
msg_info "Removing container ${CTID}"
|
||||
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID}${CL}"
|
||||
pct stop "$CTID" &>/dev/null || true
|
||||
pct destroy "$CTID" &>/dev/null || true
|
||||
msg_ok "Container ${CTID} removed"
|
||||
elif [[ "$response" =~ ^[Nn]$ ]]; then
|
||||
echo ""
|
||||
msg_warn "Container ${CTID} kept for debugging"
|
||||
|
||||
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
||||
;;
|
||||
2)
|
||||
echo -e "\n${TAB}${YW}Container ${CTID} kept for debugging${CL}"
|
||||
# Dev mode: Setup MOTD/SSH for debugging access to broken container
|
||||
if [[ "${DEV_MODE_MOTD:-false}" == "true" ]]; then
|
||||
echo -e "${TAB}${HOLD}${DGN}Setting up MOTD and SSH for debugging...${CL}"
|
||||
if pct exec "$CTID" -- bash -c "
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func)
|
||||
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
|
||||
" >/dev/null 2>&1; then
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func)
|
||||
declare -f motd_ssh >/dev/null 2>&1 && motd_ssh || true
|
||||
" >/dev/null 2>&1; then
|
||||
local ct_ip=$(pct exec "$CTID" ip a s dev eth0 2>/dev/null | awk '/inet / {print $2}' | cut -d/ -f1)
|
||||
echo -e "${BFR}${CM}${GN}MOTD/SSH ready - SSH into container: ssh root@${ct_ip}${CL}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
exit $install_exit_code
|
||||
;;
|
||||
3)
|
||||
# Retry with verbose mode (full rebuild)
|
||||
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID} for rebuild...${CL}"
|
||||
pct stop "$CTID" &>/dev/null || true
|
||||
pct destroy "$CTID" &>/dev/null || true
|
||||
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
||||
echo ""
|
||||
# Get new container ID
|
||||
local old_ctid="$CTID"
|
||||
export CTID=$(get_valid_container_id "$CTID")
|
||||
export VERBOSE="yes"
|
||||
export var_verbose="yes"
|
||||
|
||||
# Show rebuild summary
|
||||
echo -e "${YW}Rebuilding with preserved settings:${CL}"
|
||||
echo -e " Container ID: ${old_ctid} → ${CTID}"
|
||||
echo -e " RAM: ${RAM_SIZE} MiB | CPU: ${CORE_COUNT} cores | Disk: ${DISK_SIZE} GB"
|
||||
echo -e " Network: ${NET:-dhcp} | Bridge: ${BRG:-vmbr0}"
|
||||
echo -e " Verbose: ${GN}enabled${CL}"
|
||||
echo ""
|
||||
msg_info "Restarting installation..."
|
||||
# Re-run build_container
|
||||
build_container
|
||||
return $?
|
||||
;;
|
||||
*)
|
||||
# Handle dynamic smart recovery options via named option variables
|
||||
local handled=false
|
||||
|
||||
if [[ -n "${APT_OPTION}" && "${response}" == "${APT_OPTION}" ]]; then
|
||||
# Package manager in-place repair: fix broken state and re-run install script
|
||||
handled=true
|
||||
if [[ "$var_os" == "alpine" ]]; then
|
||||
echo -e "\n${TAB}${HOLD}${YW}Repairing APK state in container ${CTID}...${CL}"
|
||||
pct exec "$CTID" -- ash -c "
|
||||
apk fix 2>/dev/null || true
|
||||
apk cache clean 2>/dev/null || true
|
||||
apk update 2>/dev/null || true
|
||||
" >/dev/null 2>&1 || true
|
||||
echo -e "${BFR}${CM}${GN}APK state repaired in container ${CTID}${CL}"
|
||||
else
|
||||
echo -e "\n${TAB}${HOLD}${YW}Repairing APT/DPKG state in container ${CTID}...${CL}"
|
||||
pct exec "$CTID" -- bash -c "
|
||||
DEBIAN_FRONTEND=noninteractive dpkg --configure -a 2>/dev/null || true
|
||||
apt-get -f install -y 2>/dev/null || true
|
||||
apt-get clean 2>/dev/null
|
||||
apt-get update 2>/dev/null || true
|
||||
" >/dev/null 2>&1 || true
|
||||
echo -e "${BFR}${CM}${GN}APT/DPKG state repaired in container ${CTID}${CL}"
|
||||
fi
|
||||
echo ""
|
||||
export VERBOSE="yes"
|
||||
export var_verbose="yes"
|
||||
|
||||
echo -e "${YW}Re-running installation in existing container ${CTID}:${CL}"
|
||||
echo -e " RAM: ${RAM_SIZE} MiB | CPU: ${CORE_COUNT} cores | Disk: ${DISK_SIZE} GB"
|
||||
echo -e " Verbose: ${GN}enabled${CL}"
|
||||
echo ""
|
||||
msg_info "Re-running installation script..."
|
||||
|
||||
# Re-run install script in existing container (don't destroy/recreate)
|
||||
set +Eeuo pipefail
|
||||
trap - ERR
|
||||
lxc-attach -n "$CTID" -- bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/install/${var_install}.sh)"
|
||||
local apt_retry_exit=$?
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
|
||||
# Check for error flag from retry
|
||||
local apt_retry_code=0
|
||||
if [[ -n "${SESSION_ID:-}" ]]; then
|
||||
local retry_error_flag="/root/.install-${SESSION_ID}.failed"
|
||||
if pct exec "$CTID" -- test -f "$retry_error_flag" 2>/dev/null; then
|
||||
apt_retry_code=$(pct exec "$CTID" -- cat "$retry_error_flag" 2>/dev/null || echo "1")
|
||||
pct exec "$CTID" -- rm -f "$retry_error_flag" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $apt_retry_code -eq 0 && $apt_retry_exit -ne 0 ]]; then
|
||||
apt_retry_code=$apt_retry_exit
|
||||
fi
|
||||
|
||||
if [[ $apt_retry_code -eq 0 ]]; then
|
||||
msg_ok "Installation completed successfully after APT repair!"
|
||||
post_update_to_api "done" "0" "force"
|
||||
return 0
|
||||
else
|
||||
msg_error "Installation still failed after APT repair (exit code: ${apt_retry_code})"
|
||||
install_exit_code=$apt_retry_code
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${OOM_OPTION}" && "${response}" == "${OOM_OPTION}" ]]; then
|
||||
# Retry with doubled resources
|
||||
handled=true
|
||||
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID} for rebuild with more resources...${CL}"
|
||||
pct stop "$CTID" &>/dev/null || true
|
||||
pct destroy "$CTID" &>/dev/null || true
|
||||
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
||||
echo ""
|
||||
local old_ctid="$CTID"
|
||||
local old_ram="$RAM_SIZE"
|
||||
local old_cpu="$CORE_COUNT"
|
||||
export CTID=$(get_valid_container_id "$CTID")
|
||||
export RAM_SIZE=$((RAM_SIZE * 2))
|
||||
export CORE_COUNT=$((CORE_COUNT * 2))
|
||||
export var_ram="$RAM_SIZE"
|
||||
export var_cpu="$CORE_COUNT"
|
||||
export VERBOSE="yes"
|
||||
export var_verbose="yes"
|
||||
export RECOVERY_ATTEMPT=$((${RECOVERY_ATTEMPT:-0} + 1))
|
||||
|
||||
echo -e "${YW}Rebuilding with increased resources (attempt ${RECOVERY_ATTEMPT}/2):${CL}"
|
||||
echo -e " Container ID: ${old_ctid} → ${CTID}"
|
||||
echo -e " RAM: ${old_ram} → ${GN}${RAM_SIZE}${CL} MiB (x2)"
|
||||
echo -e " CPU: ${old_cpu} → ${GN}${CORE_COUNT}${CL} cores (x2)"
|
||||
echo -e " Disk: ${DISK_SIZE} GB | Network: ${NET:-dhcp} | Bridge: ${BRG:-vmbr0}"
|
||||
echo -e " Verbose: ${GN}enabled${CL}"
|
||||
echo ""
|
||||
msg_info "Restarting installation..."
|
||||
build_container
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [[ -n "${DNS_OPTION}" && "${response}" == "${DNS_OPTION}" ]]; then
|
||||
# Retry with DNS override in LXC
|
||||
handled=true
|
||||
echo -e "\n${TAB}${HOLD}${YW}Removing container ${CTID} for rebuild with DNS override...${CL}"
|
||||
pct stop "$CTID" &>/dev/null || true
|
||||
pct destroy "$CTID" &>/dev/null || true
|
||||
echo -e "${BFR}${CM}${GN}Container ${CTID} removed${CL}"
|
||||
echo ""
|
||||
local old_ctid="$CTID"
|
||||
export CTID=$(get_valid_container_id "$CTID")
|
||||
export DNS_RETRY_OVERRIDE="true"
|
||||
export VERBOSE="yes"
|
||||
export var_verbose="yes"
|
||||
|
||||
echo -e "${YW}Rebuilding with DNS override in LXC:${CL}"
|
||||
echo -e " Container ID: ${old_ctid} → ${CTID}"
|
||||
echo -e " DNS: ${GN}8.8.8.8, 1.1.1.1${CL} (inside LXC only)"
|
||||
echo -e " Verbose: ${GN}enabled${CL}"
|
||||
echo ""
|
||||
msg_info "Restarting installation..."
|
||||
build_container
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [[ "$handled" == false ]]; then
|
||||
echo -e "\n${TAB}${YW}Invalid option. Container ${CTID} kept.${CL}"
|
||||
exit $install_exit_code
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# Timeout - auto-remove
|
||||
echo ""
|
||||
@@ -5267,14 +5564,15 @@ api_exit_script() {
|
||||
post_update_to_api "failed" "$exit_code"
|
||||
elif [[ "${POST_TO_API_DONE:-}" == "true" && "${POST_UPDATE_DONE:-}" != "true" ]]; then
|
||||
# Script exited with 0 but never sent a completion status
|
||||
# This catches edge cases like early returns after post_to_api()
|
||||
post_update_to_api "failed" "1"
|
||||
# exit_code=0 is never an error — report as success
|
||||
post_update_to_api "done" "0"
|
||||
fi
|
||||
}
|
||||
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
trap 'api_exit_script' EXIT
|
||||
fi
|
||||
trap 'ensure_log_on_host; post_update_to_api "failed" "$?"' ERR
|
||||
trap 'local _ec=$?; if [[ $_ec -ne 0 ]]; then ensure_log_on_host; post_update_to_api "failed" "$_ec"; fi' ERR
|
||||
trap 'ensure_log_on_host; post_update_to_api "failed" "129"; exit 129' SIGHUP
|
||||
trap 'ensure_log_on_host; post_update_to_api "failed" "130"; exit 130' SIGINT
|
||||
trap 'ensure_log_on_host; post_update_to_api "failed" "143"; exit 143' SIGTERM
|
||||
|
||||
@@ -37,21 +37,47 @@ if ! declare -f explain_exit_code &>/dev/null; then
|
||||
case "$code" in
|
||||
1) echo "General error / Operation not permitted" ;;
|
||||
2) echo "Misuse of shell builtins (e.g. syntax error)" ;;
|
||||
3) echo "General syntax or argument error" ;;
|
||||
10) echo "Docker / privileged mode required (unsupported environment)" ;;
|
||||
4) echo "curl: Feature not supported or protocol error" ;;
|
||||
5) echo "curl: Could not resolve proxy" ;;
|
||||
6) echo "curl: DNS resolution failed (could not resolve host)" ;;
|
||||
7) echo "curl: Failed to connect (network unreachable / host down)" ;;
|
||||
8) echo "curl: FTP server reply error" ;;
|
||||
8) echo "curl: Server reply error (FTP/SFTP or apk untrusted key)" ;;
|
||||
16) echo "curl: HTTP/2 framing layer error" ;;
|
||||
18) echo "curl: Partial file (transfer not completed)" ;;
|
||||
22) echo "curl: HTTP error returned (404, 429, 500+)" ;;
|
||||
23) echo "curl: Write error (disk full or permissions)" ;;
|
||||
24) echo "curl: Write to local file failed" ;;
|
||||
25) echo "curl: Upload failed" ;;
|
||||
26) echo "curl: Read error on local file (I/O)" ;;
|
||||
27) echo "curl: Out of memory (memory allocation failed)" ;;
|
||||
28) echo "curl: Operation timeout (network slow or server not responding)" ;;
|
||||
30) echo "curl: FTP port command failed" ;;
|
||||
32) echo "curl: FTP SIZE command failed" ;;
|
||||
33) echo "curl: HTTP range error" ;;
|
||||
34) echo "curl: HTTP post error" ;;
|
||||
35) echo "curl: SSL/TLS handshake failed (certificate error)" ;;
|
||||
36) echo "curl: FTP bad download resume" ;;
|
||||
39) echo "curl: LDAP search failed" ;;
|
||||
44) echo "curl: Internal error (bad function call order)" ;;
|
||||
45) echo "curl: Interface error (failed to bind to specified interface)" ;;
|
||||
46) echo "curl: Bad password entered" ;;
|
||||
47) echo "curl: Too many redirects" ;;
|
||||
48) echo "curl: Unknown command line option specified" ;;
|
||||
51) echo "curl: SSL peer certificate or SSH host key verification failed" ;;
|
||||
52) echo "curl: Empty reply from server (got nothing)" ;;
|
||||
55) echo "curl: Failed sending network data" ;;
|
||||
56) echo "curl: Receive error (connection reset by peer)" ;;
|
||||
57) echo "curl: Unrecoverable poll/select error (system I/O failure)" ;;
|
||||
59) echo "curl: Couldn't use specified SSL cipher" ;;
|
||||
61) echo "curl: Bad/unrecognized transfer encoding" ;;
|
||||
63) echo "curl: Maximum file size exceeded" ;;
|
||||
75) echo "Temporary failure (retry later)" ;;
|
||||
78) echo "curl: Remote file not found (404 on FTP/file)" ;;
|
||||
79) echo "curl: SSH session error (key exchange/auth failed)" ;;
|
||||
92) echo "curl: HTTP/2 stream error (protocol violation)" ;;
|
||||
95) echo "curl: HTTP/3 layer error" ;;
|
||||
64) echo "Usage error (wrong arguments)" ;;
|
||||
65) echo "Data format error (bad input data)" ;;
|
||||
66) echo "Input file not found (cannot open input)" ;;
|
||||
@@ -69,15 +95,21 @@ if ! declare -f explain_exit_code &>/dev/null; then
|
||||
101) echo "APT: Configuration error (bad sources.list, malformed config)" ;;
|
||||
102) echo "APT: Lock held by another process (dpkg/apt still running)" ;;
|
||||
124) echo "Command timed out (timeout command)" ;;
|
||||
125) echo "Command failed to start (Docker daemon or execution error)" ;;
|
||||
126) echo "Command invoked cannot execute (permission problem?)" ;;
|
||||
127) echo "Command not found" ;;
|
||||
128) echo "Invalid argument to exit" ;;
|
||||
130) echo "Terminated by Ctrl+C (SIGINT)" ;;
|
||||
129) echo "Killed by SIGHUP (terminal closed / hangup)" ;;
|
||||
130) echo "Aborted by user (SIGINT)" ;;
|
||||
131) echo "Killed by SIGQUIT (core dumped)" ;;
|
||||
132) echo "Killed by SIGILL (illegal CPU instruction)" ;;
|
||||
134) echo "Process aborted (SIGABRT - possibly Node.js heap overflow)" ;;
|
||||
137) echo "Killed (SIGKILL / Out of memory?)" ;;
|
||||
139) echo "Segmentation fault (core dumped)" ;;
|
||||
141) echo "Broken pipe (SIGPIPE - output closed prematurely)" ;;
|
||||
143) echo "Terminated (SIGTERM)" ;;
|
||||
144) echo "Killed by signal 16 (SIGUSR1 / SIGSTKFLT)" ;;
|
||||
146) echo "Killed by signal 18 (SIGTSTP)" ;;
|
||||
150) echo "Systemd: Service failed to start" ;;
|
||||
151) echo "Systemd: Service unit not found" ;;
|
||||
152) echo "Permission denied (EACCES)" ;;
|
||||
@@ -123,6 +155,7 @@ if ! declare -f explain_exit_code &>/dev/null; then
|
||||
224) echo "Proxmox: PBS storage is for backups only" ;;
|
||||
225) echo "Proxmox: No template available for OS/Version" ;;
|
||||
231) echo "Proxmox: LXC stack upgrade failed" ;;
|
||||
239) echo "npm/Node.js: Unexpected runtime error or dependency failure" ;;
|
||||
243) echo "Node.js: Out of memory (JavaScript heap out of memory)" ;;
|
||||
245) echo "Node.js: Invalid command-line option" ;;
|
||||
246) echo "Node.js: Internal JavaScript Parse Error" ;;
|
||||
|
||||
@@ -40,6 +40,25 @@ catch_errors
|
||||
# Get LXC IP address (must be called INSIDE container, after network is up)
|
||||
get_lxc_ip
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# post_progress_to_api()
|
||||
#
|
||||
# - Lightweight progress ping from inside the container
|
||||
# - Updates the existing telemetry record status from "installing" to "configuring"
|
||||
# - Signals that the installation is actively progressing (not stuck)
|
||||
# - Fire-and-forget: never blocks or fails the script
|
||||
# - Only executes if DIAGNOSTICS=yes and RANDOM_UUID is set
|
||||
# ------------------------------------------------------------------------------
|
||||
post_progress_to_api() {
|
||||
command -v curl &>/dev/null || return 0
|
||||
[[ "${DIAGNOSTICS:-no}" == "no" ]] && return 0
|
||||
[[ -z "${RANDOM_UUID:-}" ]] && return 0
|
||||
|
||||
curl -fsS -m 5 -X POST "https://telemetry.community-scripts.org/telemetry" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"random_id\":\"${RANDOM_UUID}\",\"type\":\"lxc\",\"nsapp\":\"${app:-unknown}\",\"status\":\"configuring\"}" &>/dev/null || true
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# SECTION 2: NETWORK & CONNECTIVITY
|
||||
# ==============================================================================
|
||||
@@ -103,6 +122,7 @@ setting_up_container() {
|
||||
msg_ok "Set up Container OS"
|
||||
#msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
|
||||
msg_ok "Network Connected: ${BL}$(hostname -I)"
|
||||
post_progress_to_api
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
@@ -206,8 +226,18 @@ EOF
|
||||
$STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade
|
||||
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
||||
msg_ok "Updated Container OS"
|
||||
post_progress_to_api
|
||||
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
local tools_content
|
||||
tools_content=$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func) || {
|
||||
msg_error "Failed to download tools.func"
|
||||
exit 6
|
||||
}
|
||||
source /dev/stdin <<<"$tools_content"
|
||||
if ! declare -f fetch_and_deploy_gh_release >/dev/null 2>&1; then
|
||||
msg_error "tools.func loaded but incomplete — missing expected functions"
|
||||
exit 6
|
||||
fi
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
|
||||
@@ -19,6 +19,11 @@ EOF
|
||||
}
|
||||
header_info
|
||||
set -e
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-netbird-lxc" "tool"
|
||||
|
||||
while true; do
|
||||
read -p "This will add NetBird to an existing LXC Container ONLY. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
|
||||
@@ -23,6 +23,10 @@ function msg_info() { echo -e " \e[1;36m➤\e[0m $1"; }
|
||||
function msg_ok() { echo -e " \e[1;32m✔\e[0m $1"; }
|
||||
function msg_error() { echo -e " \e[1;31m✖\e[0m $1"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-tailscale-lxc" "tool"
|
||||
|
||||
header_info
|
||||
|
||||
if ! command -v pveversion &>/dev/null; then
|
||||
|
||||
@@ -13,6 +13,7 @@ fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
@@ -29,6 +30,7 @@ DEFAULT_PORT=8080
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
|
||||
@@ -42,6 +42,11 @@ function msg() {
|
||||
local TEXT="$1"
|
||||
echo -e "$TEXT"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "all-templates" "tool"
|
||||
|
||||
function validate_container_id() {
|
||||
local ctid="$1"
|
||||
# Check if ID is numeric
|
||||
|
||||
@@ -28,6 +28,11 @@ HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="Coder Code Server"
|
||||
hostname="$(hostname)"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "coder-code-server" "addon"
|
||||
|
||||
set -o errexit
|
||||
set -o errtrace
|
||||
set -o nounset
|
||||
|
||||
@@ -13,11 +13,13 @@ fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -17,6 +17,11 @@ HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="CrowdSec"
|
||||
hostname="$(hostname)"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "crowdsec" "addon"
|
||||
|
||||
set -o errexit
|
||||
set -o errtrace
|
||||
set -o nounset
|
||||
|
||||
@@ -32,6 +32,10 @@ DEFAULT_PORT=8080
|
||||
SRC_DIR="/"
|
||||
TMP_BIN="/tmp/filebrowser.$$"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser-quantum" "addon"
|
||||
|
||||
# Get primary IP
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
clear
|
||||
cat <<"EOF"
|
||||
_______ __ ____
|
||||
/ ____(_) /__ / __ )_________ _ __________ _____
|
||||
/ /_ / / / _ \/ __ / ___/ __ \ | /| / / ___/ _ \/ ___/
|
||||
@@ -29,6 +29,10 @@ INSTALL_PATH="/usr/local/bin/filebrowser"
|
||||
DB_PATH="/usr/local/community-scripts/filebrowser.db"
|
||||
DEFAULT_PORT=8080
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "filebrowser" "addon"
|
||||
|
||||
# Get first non-loopback IP & Detect primary network interface dynamically
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
@@ -38,65 +42,65 @@ IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n
|
||||
|
||||
# Detect OS
|
||||
if [[ -f "/etc/alpine-release" ]]; then
|
||||
OS="Alpine"
|
||||
SERVICE_PATH="/etc/init.d/filebrowser"
|
||||
PKG_MANAGER="apk add --no-cache"
|
||||
OS="Alpine"
|
||||
SERVICE_PATH="/etc/init.d/filebrowser"
|
||||
PKG_MANAGER="apk add --no-cache"
|
||||
elif [[ -f "/etc/debian_version" ]]; then
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/filebrowser.service"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
OS="Debian"
|
||||
SERVICE_PATH="/etc/systemd/system/filebrowser.service"
|
||||
PKG_MANAGER="apt-get install -y"
|
||||
else
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 1
|
||||
echo -e "${CROSS} Unsupported OS detected. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -e "${INFO} ${YW}${msg}...${CL}"
|
||||
local msg="$1"
|
||||
echo -e "${INFO} ${YW}${msg}...${CL}"
|
||||
}
|
||||
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${CM} ${GN}${msg}${CL}"
|
||||
local msg="$1"
|
||||
echo -e "${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${CROSS} ${RD}${msg}${CL}"
|
||||
local msg="$1"
|
||||
echo -e "${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
if [ -f "$INSTALL_PATH" ]; then
|
||||
echo -e "${YW}⚠️ ${APP} is already installed.${CL}"
|
||||
read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling ${APP}"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
else
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
fi
|
||||
rm -f "$INSTALL_PATH" "$DB_PATH"
|
||||
msg_ok "${APP} has been uninstalled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
read -r -p "Would you like to update ${APP}? (y/N): " update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Updating ${APP}"
|
||||
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
msg_ok "Updated ${APP}"
|
||||
exit 0
|
||||
echo -e "${YW}⚠️ ${APP} is already installed.${CL}"
|
||||
read -r -p "Would you like to uninstall ${APP}? (y/N): " uninstall_prompt
|
||||
if [[ "${uninstall_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Uninstalling ${APP}"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
systemctl disable --now filebrowser.service &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
else
|
||||
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
rc-service filebrowser stop &>/dev/null
|
||||
rc-update del filebrowser &>/dev/null
|
||||
rm -f "$SERVICE_PATH"
|
||||
fi
|
||||
rm -f "$INSTALL_PATH" "$DB_PATH"
|
||||
msg_ok "${APP} has been uninstalled."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
read -r -p "Would you like to update ${APP}? (y/N): " update_prompt
|
||||
if [[ "${update_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Updating ${APP}"
|
||||
if ! command -v curl &>/dev/null; then $PKG_MANAGER curl &>/dev/null; fi
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
msg_ok "Updated ${APP}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${YW}⚠️ Update skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "${YW}⚠️ ${APP} is not installed.${CL}"
|
||||
@@ -105,43 +109,43 @@ PORT=${PORT:-$DEFAULT_PORT}
|
||||
|
||||
read -r -p "Would you like to install ${APP}? (y/n): " install_prompt
|
||||
if [[ "${install_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Installing ${APP} on ${OS}"
|
||||
$PKG_MANAGER wget tar curl &>/dev/null
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
msg_ok "Installed ${APP}"
|
||||
msg_info "Installing ${APP} on ${OS}"
|
||||
$PKG_MANAGER wget tar curl &>/dev/null
|
||||
curl -fsSL "https://github.com/filebrowser/filebrowser/releases/latest/download/linux-amd64-filebrowser.tar.gz" | tar -xzv -C /usr/local/bin &>/dev/null
|
||||
chmod +x "$INSTALL_PATH"
|
||||
msg_ok "Installed ${APP}"
|
||||
|
||||
msg_info "Creating FileBrowser directory"
|
||||
mkdir -p /usr/local/community-scripts
|
||||
chown root:root /usr/local/community-scripts
|
||||
chmod 755 /usr/local/community-scripts
|
||||
touch "$DB_PATH"
|
||||
chown root:root "$DB_PATH"
|
||||
chmod 644 "$DB_PATH"
|
||||
msg_ok "Directory created successfully"
|
||||
msg_info "Creating FileBrowser directory"
|
||||
mkdir -p /usr/local/community-scripts
|
||||
chown root:root /usr/local/community-scripts
|
||||
chmod 755 /usr/local/community-scripts
|
||||
touch "$DB_PATH"
|
||||
chown root:root "$DB_PATH"
|
||||
chmod 644 "$DB_PATH"
|
||||
msg_ok "Directory created successfully"
|
||||
|
||||
read -r -p "Would you like to use No Authentication? (y/N): " auth_prompt
|
||||
if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Configuring No Authentication"
|
||||
cd /usr/local/community-scripts
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config init --auth.method=noauth &>/dev/null
|
||||
filebrowser config set --auth.method=noauth &>/dev/null
|
||||
filebrowser users add ID 1 --perm.admin &>/dev/null
|
||||
msg_ok "No Authentication configured"
|
||||
else
|
||||
msg_info "Setting up default authentication"
|
||||
cd /usr/local/community-scripts
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser users add admin helper-scripts.com --perm.admin --database "$DB_PATH" &>/dev/null
|
||||
msg_ok "Default authentication configured (admin:helper-scripts.com)"
|
||||
fi
|
||||
read -r -p "Would you like to use No Authentication? (y/N): " auth_prompt
|
||||
if [[ "${auth_prompt,,}" =~ ^(y|yes)$ ]]; then
|
||||
msg_info "Configuring No Authentication"
|
||||
cd /usr/local/community-scripts
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config init --auth.method=noauth &>/dev/null
|
||||
filebrowser config set --auth.method=noauth &>/dev/null
|
||||
filebrowser users add ID 1 --perm.admin &>/dev/null
|
||||
msg_ok "No Authentication configured"
|
||||
else
|
||||
msg_info "Setting up default authentication"
|
||||
cd /usr/local/community-scripts
|
||||
filebrowser config init -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser config set -a '0.0.0.0' -p "$PORT" -d "$DB_PATH" &>/dev/null
|
||||
filebrowser users add admin helper-scripts.com --perm.admin --database "$DB_PATH" &>/dev/null
|
||||
msg_ok "Default authentication configured (admin:helper-scripts.com)"
|
||||
fi
|
||||
|
||||
msg_info "Creating service"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
cat <<EOF >"$SERVICE_PATH"
|
||||
msg_info "Creating service"
|
||||
if [[ "$OS" == "Debian" ]]; then
|
||||
cat <<EOF >"$SERVICE_PATH"
|
||||
[Unit]
|
||||
Description=Filebrowser
|
||||
After=network-online.target
|
||||
@@ -157,9 +161,9 @@ Restart=always
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl enable -q --now filebrowser
|
||||
else
|
||||
cat <<EOF >"$SERVICE_PATH"
|
||||
systemctl enable -q --now filebrowser
|
||||
else
|
||||
cat <<EOF >"$SERVICE_PATH"
|
||||
#!/sbin/openrc-run
|
||||
|
||||
command="/usr/local/bin/filebrowser"
|
||||
@@ -172,14 +176,14 @@ depend() {
|
||||
need net
|
||||
}
|
||||
EOF
|
||||
chmod +x "$SERVICE_PATH"
|
||||
rc-update add filebrowser default &>/dev/null
|
||||
rc-service filebrowser start &>/dev/null
|
||||
fi
|
||||
msg_ok "Service created successfully"
|
||||
chmod +x "$SERVICE_PATH"
|
||||
rc-update add filebrowser default &>/dev/null
|
||||
rc-service filebrowser start &>/dev/null
|
||||
fi
|
||||
msg_ok "Service created successfully"
|
||||
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}"
|
||||
echo -e "${CM} ${GN}${APP} is reachable at: ${BL}http://$IP:$PORT${CL}"
|
||||
else
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
echo -e "${YW}⚠️ Installation skipped. Exiting.${CL}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -30,6 +30,10 @@ function msg_info() { echo -e "${INFO} ${YW}$1...${CL}"; }
|
||||
function msg_ok() { echo -e "${CM} ${GN}$1${CL}"; }
|
||||
function msg_error() { echo -e "${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "glances" "addon"
|
||||
|
||||
get_lxc_ip() {
|
||||
if command -v hostname >/dev/null 2>&1 && hostname -I 2>/dev/null; then
|
||||
hostname -I | awk '{print $1}'
|
||||
|
||||
@@ -13,6 +13,7 @@ fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
@@ -29,6 +30,7 @@ DEFAULT_PORT=3000
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
@@ -104,6 +106,10 @@ function update() {
|
||||
$STD npm run build
|
||||
msg_ok "Built ${APP}"
|
||||
|
||||
msg_info "Updating service"
|
||||
create_service
|
||||
msg_ok "Updated service"
|
||||
|
||||
msg_info "Starting service"
|
||||
systemctl start immich-proxy
|
||||
msg_ok "Started service"
|
||||
@@ -112,6 +118,27 @@ function update() {
|
||||
fi
|
||||
}
|
||||
|
||||
function create_service() {
|
||||
cat <<EOF >"$SERVICE_PATH"
|
||||
[Unit]
|
||||
Description=Immich Public Proxy
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=${INSTALL_PATH}/app
|
||||
EnvironmentFile=${CONFIG_PATH}/.env
|
||||
ExecStart=/usr/bin/node ${INSTALL_PATH}/app/dist/index.js
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
systemctl daemon-reload
|
||||
}
|
||||
|
||||
# ==============================================================================
|
||||
# INSTALL
|
||||
# ==============================================================================
|
||||
@@ -173,23 +200,7 @@ EOF
|
||||
msg_ok "Created configuration"
|
||||
|
||||
msg_info "Creating service"
|
||||
cat <<EOF >"$SERVICE_PATH"
|
||||
[Unit]
|
||||
Description=Immich Public Proxy
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=${INSTALL_PATH}
|
||||
EnvironmentFile=${CONFIG_PATH}/.env
|
||||
ExecStart=/usr/bin/node ${INSTALL_PATH}/app/server.js
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
create_service
|
||||
systemctl enable -q --now immich-proxy
|
||||
msg_ok "Created and started service"
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
@@ -29,6 +30,7 @@ DEFAULT_PORT=3000
|
||||
|
||||
# Initialize all core functions (colors, formatting, icons, STD mode)
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# HEADER
|
||||
|
||||
@@ -26,6 +26,11 @@ BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
silent() { "$@" >/dev/null 2>&1; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "netdata" "tool"
|
||||
|
||||
set -e
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
@@ -13,11 +13,13 @@ fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -27,6 +27,11 @@ HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
APP="OliveTin"
|
||||
hostname="$(hostname)"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "olivetin" "addon"
|
||||
|
||||
set-e
|
||||
header_info
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ APP="phpMyAdmin"
|
||||
INSTALL_DIR_DEBIAN="/var/www/html/phpMyAdmin"
|
||||
INSTALL_DIR_ALPINE="/usr/share/phpmyadmin"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "phpmyadmin" "addon"
|
||||
|
||||
IFACE=$(ip -4 route | awk '/default/ {print $5; exit}')
|
||||
IP=$(ip -4 addr show "$IFACE" | awk '/inet / {print $2}' | cut -d/ -f1 | head -n 1)
|
||||
[[ -z "$IP" ]] && IP=$(hostname -I | awk '{print $1}')
|
||||
|
||||
@@ -13,11 +13,13 @@ fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -28,6 +28,11 @@ function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pyenv" "addon"
|
||||
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
msg_error "Can't Install on Proxmox "
|
||||
exit
|
||||
|
||||
@@ -13,11 +13,13 @@ fi
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/tools.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/error_handler.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
|
||||
# Enable error handling
|
||||
set -Eeuo pipefail
|
||||
trap 'error_handler' ERR
|
||||
load_functions
|
||||
init_tool_telemetry "" "addon"
|
||||
|
||||
# ==============================================================================
|
||||
# CONFIGURATION
|
||||
|
||||
@@ -36,6 +36,10 @@ msg_ok() {
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "webmin" "addon"
|
||||
|
||||
header_info
|
||||
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Webmin Installer" --yesno "This Will Install Webmin on this LXC Container. Proceed?" 10 58
|
||||
|
||||
@@ -31,6 +31,10 @@ HOLD=" "
|
||||
CM="${GN}✓${CL} "
|
||||
CROSS="${RD}✗${CL} "
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "add-iptag" "tool"
|
||||
|
||||
# Stop any running spinner
|
||||
stop_spinner() {
|
||||
if [ -n "$SPINNER_PID" ] && kill -0 "$SPINNER_PID" 2>/dev/null; then
|
||||
|
||||
@@ -22,6 +22,10 @@ CM='\xE2\x9C\x94\033'
|
||||
GN="\033[1;92m"
|
||||
CL="\033[m"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "clean-lxcs" "tool"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
clear
|
||||
cat <<"EOF"
|
||||
____ ________ ____ __ __ __ _ ____ ___
|
||||
/ __ \_________ _ ______ ___ ____ _ __ / ____/ /__ ____ _____ / __ \_________ / /_ ____ _____ ___ ____/ / / /| | / / |/ /____
|
||||
/ /_/ / ___/ __ \| |/_/ __ `__ \/ __ \| |/_/ / / / / _ \/ __ `/ __ \ / / / / ___/ __ \/ __ \/ __ `/ __ \/ _ \/ __ / / / | | / / /|_/ / ___/
|
||||
@@ -16,62 +16,66 @@ function header_info {
|
||||
EOF
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "clean-orphaned-lvm" "tool"
|
||||
|
||||
# Function to check for orphaned LVM volumes
|
||||
function find_orphaned_lvm {
|
||||
echo -e "\n🔍 Scanning for orphaned LVM volumes...\n"
|
||||
echo -e "\n🔍 Scanning for orphaned LVM volumes...\n"
|
||||
|
||||
orphaned_volumes=()
|
||||
while read -r lv vg size seg_type; do
|
||||
# Exclude system-critical LVs and Ceph OSDs
|
||||
if [[ "$lv" == "data" || "$lv" == "root" || "$lv" == "swap" || "$lv" =~ ^osd-block- ]]; then
|
||||
continue
|
||||
fi
|
||||
orphaned_volumes=()
|
||||
while read -r lv vg size seg_type; do
|
||||
# Exclude system-critical LVs and Ceph OSDs
|
||||
if [[ "$lv" == "data" || "$lv" == "root" || "$lv" == "swap" || "$lv" =~ ^osd-block- ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Exclude thin pools (any name)
|
||||
if [[ "$seg_type" == "thin-pool" ]]; then
|
||||
continue
|
||||
fi
|
||||
# Exclude thin pools (any name)
|
||||
if [[ "$seg_type" == "thin-pool" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
container_id=$(echo "$lv" | grep -oE "[0-9]+" | head -1)
|
||||
# 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
|
||||
container_id=$(echo "$lv" | grep -oE "[0-9]+" | head -1)
|
||||
# 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,seg_type --separator ' ' 2>/dev/null | awk '{print $1, $2, $3, $4}')
|
||||
orphaned_volumes+=("$lv" "$vg" "$size")
|
||||
done < <(lvs --noheadings -o lv_name,vg_name,lv_size,seg_type --separator ' ' 2>/dev/null | awk '{print $1, $2, $3, $4}')
|
||||
|
||||
# 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" "-------------------------" "----------" "----------"
|
||||
# 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 ""
|
||||
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]}"
|
||||
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
|
||||
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
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
clear
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
echo -e "⚠️ Can't Run from the Proxmox Shell"
|
||||
exit
|
||||
echo -e "⚠️ Can't Run from the Proxmox Shell"
|
||||
exit
|
||||
fi
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
@@ -23,16 +23,16 @@ CM="${GN}✓${CL}"
|
||||
CROSS="${RD}✗${CL}"
|
||||
APP="Home Assistant Container"
|
||||
while true; do
|
||||
read -p "This will restore ${APP} from a backup. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
read -p "This will restore ${APP} from a backup. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
clear
|
||||
function header_info {
|
||||
cat <<"EOF"
|
||||
cat <<"EOF"
|
||||
__ __ ___ _ __ __
|
||||
/ / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_
|
||||
/ /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/
|
||||
@@ -44,35 +44,39 @@ EOF
|
||||
|
||||
header_info
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "container-restore" "tool"
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
if [ -z "$(ls -A /var/lib/docker/volumes/hass_config/_data/backups/)" ]; then
|
||||
msg_error "No backups found! \n"
|
||||
exit 1
|
||||
msg_error "No backups found! \n"
|
||||
exit 1
|
||||
fi
|
||||
DIR=/var/lib/docker/volumes/hass_config/_data/restore
|
||||
if [ -d "$DIR" ]; then
|
||||
msg_ok "Restore Directory Exists."
|
||||
msg_ok "Restore Directory Exists."
|
||||
else
|
||||
mkdir -p /var/lib/docker/volumes/hass_config/_data/restore
|
||||
msg_ok "Created Restore Directory."
|
||||
mkdir -p /var/lib/docker/volumes/hass_config/_data/restore
|
||||
msg_ok "Created Restore Directory."
|
||||
fi
|
||||
cd /var/lib/docker/volumes/hass_config/_data/backups/
|
||||
PS3="Please enter your choice: "
|
||||
files="$(ls -A .)"
|
||||
select filename in ${files}; do
|
||||
msg_ok "You selected ${BL}${filename}${CL}"
|
||||
break
|
||||
msg_ok "You selected ${BL}${filename}${CL}"
|
||||
break
|
||||
done
|
||||
msg_info "Stopping Home Assistant"
|
||||
docker stop homeassistant &>/dev/null
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
clear
|
||||
if command -v pveversion >/dev/null 2>&1; then
|
||||
echo -e "⚠️ Can't Run from the Proxmox Shell"
|
||||
exit
|
||||
echo -e "⚠️ Can't Run from the Proxmox Shell"
|
||||
exit
|
||||
fi
|
||||
YW=$(echo "\033[33m")
|
||||
BL=$(echo "\033[36m")
|
||||
@@ -23,16 +23,16 @@ CM="${GN}✓${CL}"
|
||||
CROSS="${RD}✗${CL}"
|
||||
APP="Home Assistant Core"
|
||||
while true; do
|
||||
read -p "This will restore ${APP} from a backup. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
read -p "This will restore ${APP} from a backup. Proceed(y/n)?" yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
clear
|
||||
function header_info {
|
||||
cat <<"EOF"
|
||||
cat <<"EOF"
|
||||
__ __ ___ _ __ __ ______
|
||||
/ / / /___ ____ ___ ___ / | __________(_)____/ /_____ _____ / /_ / ____/___ ________
|
||||
/ /_/ / __ \/ __ `__ \/ _ \ / /| | / ___/ ___/ / ___/ __/ __ `/ __ \/ __/ / / / __ \/ ___/ _ \
|
||||
@@ -44,35 +44,39 @@ EOF
|
||||
|
||||
header_info
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "core-restore" "tool"
|
||||
|
||||
function msg_info() {
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
local msg="$1"
|
||||
echo -ne " ${HOLD} ${YW}${msg}..."
|
||||
}
|
||||
function msg_ok() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CM} ${GN}${msg}${CL}"
|
||||
}
|
||||
function msg_error() {
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
local msg="$1"
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
if [ -z "$(ls -A /root/.homeassistant/backups/)" ]; then
|
||||
msg_error "No backups found! \n"
|
||||
exit 1
|
||||
msg_error "No backups found! \n"
|
||||
exit 1
|
||||
fi
|
||||
DIR=/root/.homeassistant/restore
|
||||
if [ -d "$DIR" ]; then
|
||||
msg_ok "Restore Directory Exists."
|
||||
msg_ok "Restore Directory Exists."
|
||||
else
|
||||
mkdir -p /root/.homeassistant/restore
|
||||
msg_ok "Created Restore Directory."
|
||||
mkdir -p /root/.homeassistant/restore
|
||||
msg_ok "Created Restore Directory."
|
||||
fi
|
||||
cd /root/.homeassistant/backups/
|
||||
PS3="Please enter your choice: "
|
||||
files="$(ls -A .)"
|
||||
select filename in ${files}; do
|
||||
msg_ok "You selected ${BL}${filename}${CL}"
|
||||
break
|
||||
msg_ok "You selected ${BL}${filename}${CL}"
|
||||
break
|
||||
done
|
||||
msg_info "Stopping Home Assistant"
|
||||
sudo service homeassistant stop
|
||||
|
||||
@@ -22,6 +22,11 @@ RD=$(echo "\033[01;31m")
|
||||
CM='\xE2\x9C\x94\033'
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "execute-lxcs" "tool"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Proxmox VE LXC Execute" --yesno "This will execute a command inside selected LXC Containers. Proceed?" 10 58
|
||||
@@ -40,7 +45,6 @@ if [ $? -ne 0 ]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
read -r -p "Enter here command for inside the containers: " custom_command
|
||||
|
||||
header_info
|
||||
@@ -50,12 +54,11 @@ function execute_in() {
|
||||
container=$1
|
||||
name=$(pct exec "$container" hostname)
|
||||
echo -e "${BL}[Info]${GN} Execute inside${BL} ${name}${GN} with output: ${CL}"
|
||||
if ! pct exec "$container" -- bash -c "command ${custom_command} >/dev/null 2>&1"
|
||||
then
|
||||
echo -e "${BL}[Info]${GN} Skipping ${name} ${RD}$container has no command: ${custom_command}"
|
||||
else
|
||||
pct exec "$container" -- bash -c "${custom_command}" | tee
|
||||
fi
|
||||
if ! pct exec "$container" -- bash -c "command ${custom_command} >/dev/null 2>&1"; then
|
||||
echo -e "${BL}[Info]${GN} Skipping ${name} ${RD}$container has no command: ${custom_command}"
|
||||
else
|
||||
pct exec "$container" -- bash -c "${custom_command}" | tee
|
||||
fi
|
||||
}
|
||||
|
||||
for container in $(pct list | awk '{if(NR>1) print $1}'); do
|
||||
|
||||
@@ -15,6 +15,11 @@ function header_info {
|
||||
/___/ /_/ /_/
|
||||
EOF
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "frigate-support" "tool"
|
||||
|
||||
header_info
|
||||
while true; do
|
||||
read -p "This will Prepare a LXC Container for Frigate. Proceed (y/n)?" yn
|
||||
|
||||
@@ -19,6 +19,10 @@ RD="\033[01;31m"
|
||||
GN="\033[1;92m"
|
||||
CL="\033[m"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "fstrim" "tool"
|
||||
|
||||
LOGFILE="/var/log/fstrim.log"
|
||||
touch "$LOGFILE"
|
||||
chmod 600 "$LOGFILE"
|
||||
|
||||
@@ -16,6 +16,10 @@ function header_info {
|
||||
EOF
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "host-backup" "tool"
|
||||
|
||||
# Function to perform backup
|
||||
function perform_backup {
|
||||
local BACKUP_PATH
|
||||
|
||||
@@ -29,6 +29,11 @@ BFR="\\r\\033[K"
|
||||
HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
set -e
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "hw-acceleration" "tool"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
function msg_info() {
|
||||
|
||||
@@ -22,6 +22,10 @@ GN="\033[1;92m"
|
||||
RD="\033[01;31m"
|
||||
CL="\033[m"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "kernel-clean" "tool"
|
||||
|
||||
# Detect current kernel
|
||||
current_kernel=$(uname -r)
|
||||
available_kernels=$(dpkg --list | grep 'kernel-.*-pve' | awk '{print $2}' | grep -v "$current_kernel" | sort -V)
|
||||
|
||||
@@ -25,6 +25,11 @@ HOLD="-"
|
||||
CM="${GN}✓${CL}"
|
||||
current_kernel=$(uname -r)
|
||||
available_kernels=$(dpkg --list | grep 'kernel-.*-pve' | awk '{print substr($2, 16, length($2)-22)}')
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "kernel-pin" "tool"
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() {
|
||||
|
||||
@@ -38,6 +38,10 @@ CL=$(echo "\033[m")
|
||||
TAB=" "
|
||||
CM="${TAB}✔️${TAB}${CL}"
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "lxc-delete" "tool"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Proxmox VE LXC Deletion" --yesno "This will delete LXC containers. Proceed?" 10 58
|
||||
|
||||
@@ -29,6 +29,10 @@ msg_info() { echo -ne " ${HOLD} ${YW}$1..."; }
|
||||
msg_ok() { echo -e "${BFR} ${CM} ${GN}$1${CL}"; }
|
||||
msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "microcode" "tool"
|
||||
|
||||
header_info
|
||||
current_microcode=$(journalctl -k | grep -i 'microcode: Current revision:' | grep -oP 'Current revision: \K0x[0-9a-f]+')
|
||||
[ -z "$current_microcode" ] && current_microcode="Not found."
|
||||
|
||||
@@ -15,6 +15,10 @@ cat <<"EOF"
|
||||
|
||||
EOF
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "monitor-all" "tool"
|
||||
|
||||
add() {
|
||||
echo -e "\n IMPORTANT: Tag-Based Monitoring Enabled"
|
||||
echo "Only VMs and containers with the tag 'mon-restart' will be automatically restarted by this service."
|
||||
@@ -28,9 +32,9 @@ add() {
|
||||
while true; do
|
||||
read -p "This script will add Monitor All to Proxmox VE. Proceed (y/n)? " yn
|
||||
case $yn in
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
[Yy]*) break ;;
|
||||
[Nn]*) exit ;;
|
||||
*) echo "Please answer yes or no." ;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -175,5 +179,8 @@ CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "Monitor-All f
|
||||
case $CHOICE in
|
||||
"Add") add ;;
|
||||
"Remove") remove ;;
|
||||
*) echo "Exiting..."; exit 0 ;;
|
||||
*)
|
||||
echo "Exiting..."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -19,8 +19,8 @@ INFO="${TAB}ℹ️${TAB}${CL}"
|
||||
WARN="${TAB}⚠️${TAB}${CL}"
|
||||
|
||||
function header_info {
|
||||
clear
|
||||
cat <<"EOF"
|
||||
clear
|
||||
cat <<"EOF"
|
||||
|
||||
_ ____________ ____ __________ ___ ____ _ __ __
|
||||
/ | / / _/ ____/ / __ \/ __/ __/ /___ ____ _____/ (_)___ ____ _ / __ \(_)________ _/ /_ / /__ _____
|
||||
@@ -33,6 +33,10 @@ Enhanced version supporting both e1000e and e1000 drivers
|
||||
EOF
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "nic-offloading-fix" "tool"
|
||||
|
||||
header_info
|
||||
|
||||
function msg_info() { echo -e "${INFO} ${YW}${1}...${CL}"; }
|
||||
@@ -42,15 +46,18 @@ function msg_warn() { echo -e "${WARN} ${YWB}${1}"; }
|
||||
|
||||
# Check for root privileges
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
msg_error "Error: This script must be run as root."
|
||||
exit 1
|
||||
msg_error "Error: This script must be run as root."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v ethtool >/dev/null 2>&1; then
|
||||
msg_info "Installing ethtool"
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y ethtool &>/dev/null || { msg_error "Failed to install ethtool. Exiting."; exit 1; }
|
||||
msg_ok "ethtool installed successfully"
|
||||
msg_info "Installing ethtool"
|
||||
apt-get update &>/dev/null
|
||||
apt-get install -y ethtool &>/dev/null || {
|
||||
msg_error "Failed to install ethtool. Exiting."
|
||||
exit 1
|
||||
}
|
||||
msg_ok "ethtool installed successfully"
|
||||
fi
|
||||
|
||||
# Get list of network interfaces using Intel e1000e or e1000 drivers
|
||||
@@ -60,95 +67,95 @@ COUNT=0
|
||||
msg_info "Searching for Intel e1000e and e1000 interfaces"
|
||||
|
||||
for device in /sys/class/net/*; do
|
||||
interface="$(basename "$device")" # or adjust the rest of the usages below, as mostly you'll use the path anyway
|
||||
# Skip loopback interface and virtual interfaces
|
||||
if [[ "$interface" != "lo" ]] && [[ ! "$interface" =~ ^(tap|fwbr|veth|vmbr|bonding_masters) ]]; then
|
||||
# Check if the interface uses the e1000e or e1000 driver
|
||||
driver=$(basename $(readlink -f /sys/class/net/$interface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
|
||||
if [[ "$driver" == "e1000e" ]] || [[ "$driver" == "e1000" ]]; then
|
||||
# Get MAC address for additional identification
|
||||
mac=$(cat /sys/class/net/$interface/address 2>/dev/null)
|
||||
INTERFACES+=("$interface" "Intel $driver NIC ($mac)")
|
||||
((COUNT++))
|
||||
fi
|
||||
interface="$(basename "$device")" # or adjust the rest of the usages below, as mostly you'll use the path anyway
|
||||
# Skip loopback interface and virtual interfaces
|
||||
if [[ "$interface" != "lo" ]] && [[ ! "$interface" =~ ^(tap|fwbr|veth|vmbr|bonding_masters) ]]; then
|
||||
# Check if the interface uses the e1000e or e1000 driver
|
||||
driver=$(basename $(readlink -f /sys/class/net/$interface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
|
||||
if [[ "$driver" == "e1000e" ]] || [[ "$driver" == "e1000" ]]; then
|
||||
# Get MAC address for additional identification
|
||||
mac=$(cat /sys/class/net/$interface/address 2>/dev/null)
|
||||
INTERFACES+=("$interface" "Intel $driver NIC ($mac)")
|
||||
((COUNT++))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if any Intel e1000e/e1000 interfaces were found
|
||||
if [ ${#INTERFACES[@]} -eq 0 ]; then
|
||||
whiptail --title "Error" --msgbox "No Intel e1000e or e1000 network interfaces found!" 10 60
|
||||
msg_error "No Intel e1000e or e1000 network interfaces found! Exiting."
|
||||
exit 1
|
||||
whiptail --title "Error" --msgbox "No Intel e1000e or e1000 network interfaces found!" 10 60
|
||||
msg_error "No Intel e1000e or e1000 network interfaces found! Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg_ok "Found ${BL}$COUNT${GN} Intel e1000e/e1000 interfaces"
|
||||
|
||||
# Create a checklist for interface selection with all interfaces initially checked
|
||||
INTERFACES_CHECKLIST=()
|
||||
for ((i=0; i<${#INTERFACES[@]}; i+=2)); do
|
||||
INTERFACES_CHECKLIST+=("${INTERFACES[i]}" "${INTERFACES[i+1]}" "ON")
|
||||
for ((i = 0; i < ${#INTERFACES[@]}; i += 2)); do
|
||||
INTERFACES_CHECKLIST+=("${INTERFACES[i]}" "${INTERFACES[i + 1]}" "ON")
|
||||
done
|
||||
|
||||
# Show interface selection checklist
|
||||
SELECTED_INTERFACES=$(whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --title "Network Interfaces" \
|
||||
--separate-output --checklist "Select Intel e1000e/e1000 network interfaces\n(Space to toggle, Enter to confirm):" 15 80 6 \
|
||||
"${INTERFACES_CHECKLIST[@]}" 3>&1 1>&2 2>&3)
|
||||
--separate-output --checklist "Select Intel e1000e/e1000 network interfaces\n(Space to toggle, Enter to confirm):" 15 80 6 \
|
||||
"${INTERFACES_CHECKLIST[@]}" 3>&1 1>&2 2>&3)
|
||||
|
||||
exitstatus=$?
|
||||
if [ $exitstatus != 0 ]; then
|
||||
msg_info "User canceled. Exiting."
|
||||
exit 0
|
||||
msg_info "User canceled. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if any interfaces were selected
|
||||
if [ -z "$SELECTED_INTERFACES" ]; then
|
||||
msg_error "No interfaces selected. Exiting."
|
||||
exit 0
|
||||
msg_error "No interfaces selected. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Convert the selected interfaces into an array
|
||||
readarray -t INTERFACE_ARRAY <<< "$SELECTED_INTERFACES"
|
||||
readarray -t INTERFACE_ARRAY <<<"$SELECTED_INTERFACES"
|
||||
|
||||
# Show the number of selected interfaces
|
||||
INTERFACE_COUNT=${#INTERFACE_ARRAY[@]}
|
||||
|
||||
# Print selected interfaces with their driver types
|
||||
for iface in "${INTERFACE_ARRAY[@]}"; do
|
||||
driver=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
msg_ok "Selected interface: ${BL}$iface${GN} (${BL}$driver${GN})"
|
||||
driver=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
msg_ok "Selected interface: ${BL}$iface${GN} (${BL}$driver${GN})"
|
||||
done
|
||||
|
||||
# Ask for confirmation with the list of selected interfaces
|
||||
CONFIRMATION_MSG="You have selected the following interface(s):\n\n"
|
||||
for iface in "${INTERFACE_ARRAY[@]}"; do
|
||||
SPEED=$(cat /sys/class/net/$iface/speed 2>/dev/null || echo "Unknown")
|
||||
MAC=$(cat /sys/class/net/$iface/address 2>/dev/null)
|
||||
DRIVER=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
CONFIRMATION_MSG+="- $iface (Driver: $DRIVER, MAC: $MAC, Speed: ${SPEED}Mbps)\n"
|
||||
SPEED=$(cat /sys/class/net/$iface/speed 2>/dev/null || echo "Unknown")
|
||||
MAC=$(cat /sys/class/net/$iface/address 2>/dev/null)
|
||||
DRIVER=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
CONFIRMATION_MSG+="- $iface (Driver: $DRIVER, MAC: $MAC, Speed: ${SPEED}Mbps)\n"
|
||||
done
|
||||
CONFIRMATION_MSG+="\nThis will create systemd service(s) to disable offloading features.\n\nProceed?"
|
||||
|
||||
if ! whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --title "Confirmation" \
|
||||
--yesno "$CONFIRMATION_MSG" 20 80; then
|
||||
msg_info "User canceled. Exiting."
|
||||
exit 0
|
||||
--yesno "$CONFIRMATION_MSG" 20 80; then
|
||||
msg_info "User canceled. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Loop through all selected interfaces and create services for each
|
||||
for SELECTED_INTERFACE in "${INTERFACE_ARRAY[@]}"; do
|
||||
# Get the driver type for this specific interface
|
||||
DRIVER=$(basename $(readlink -f /sys/class/net/$SELECTED_INTERFACE/device/driver 2>/dev/null) 2>/dev/null)
|
||||
|
||||
# Create service name for this interface
|
||||
SERVICE_NAME="disable-nic-offload-$SELECTED_INTERFACE.service"
|
||||
SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME"
|
||||
|
||||
# Create the service file with driver-specific optimizations
|
||||
msg_info "Creating systemd service for interface: ${BL}$SELECTED_INTERFACE${YW} (${BL}$DRIVER${YW})"
|
||||
|
||||
# Start with the common part of the service file
|
||||
cat > "$SERVICE_PATH" << EOF
|
||||
# Get the driver type for this specific interface
|
||||
DRIVER=$(basename $(readlink -f /sys/class/net/$SELECTED_INTERFACE/device/driver 2>/dev/null) 2>/dev/null)
|
||||
|
||||
# Create service name for this interface
|
||||
SERVICE_NAME="disable-nic-offload-$SELECTED_INTERFACE.service"
|
||||
SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME"
|
||||
|
||||
# Create the service file with driver-specific optimizations
|
||||
msg_info "Creating systemd service for interface: ${BL}$SELECTED_INTERFACE${YW} (${BL}$DRIVER${YW})"
|
||||
|
||||
# Start with the common part of the service file
|
||||
cat >"$SERVICE_PATH" <<EOF
|
||||
[Unit]
|
||||
Description=Disable NIC offloading for Intel $DRIVER interface $SELECTED_INTERFACE
|
||||
After=network.target
|
||||
@@ -163,45 +170,49 @@ RemainAfterExit=true
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Check if service file was created successfully
|
||||
if [ ! -f "$SERVICE_PATH" ]; then
|
||||
whiptail --title "Error" --msgbox "Failed to create service file for $SELECTED_INTERFACE!" 10 50
|
||||
msg_error "Failed to create service file for $SELECTED_INTERFACE! Skipping to next interface."
|
||||
continue
|
||||
fi
|
||||
# Check if service file was created successfully
|
||||
if [ ! -f "$SERVICE_PATH" ]; then
|
||||
whiptail --title "Error" --msgbox "Failed to create service file for $SELECTED_INTERFACE!" 10 50
|
||||
msg_error "Failed to create service file for $SELECTED_INTERFACE! Skipping to next interface."
|
||||
continue
|
||||
fi
|
||||
|
||||
# Configure this service
|
||||
{
|
||||
echo "25"; sleep 0.2
|
||||
# Reload systemd to recognize the new service
|
||||
systemctl daemon-reload
|
||||
echo "50"; sleep 0.2
|
||||
# Start the service
|
||||
systemctl start "$SERVICE_NAME"
|
||||
echo "75"; sleep 0.2
|
||||
# Enable the service to start on boot
|
||||
systemctl enable "$SERVICE_NAME"
|
||||
echo "100"; sleep 0.2
|
||||
} | whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --gauge "Configuring service for $SELECTED_INTERFACE..." 10 80 0
|
||||
# Configure this service
|
||||
{
|
||||
echo "25"
|
||||
sleep 0.2
|
||||
# Reload systemd to recognize the new service
|
||||
systemctl daemon-reload
|
||||
echo "50"
|
||||
sleep 0.2
|
||||
# Start the service
|
||||
systemctl start "$SERVICE_NAME"
|
||||
echo "75"
|
||||
sleep 0.2
|
||||
# Enable the service to start on boot
|
||||
systemctl enable "$SERVICE_NAME"
|
||||
echo "100"
|
||||
sleep 0.2
|
||||
} | whiptail --backtitle "Intel e1000e/e1000 NIC Offloading Disabler" --gauge "Configuring service for $SELECTED_INTERFACE..." 10 80 0
|
||||
|
||||
# Individual service status
|
||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
SERVICE_STATUS="Active"
|
||||
else
|
||||
SERVICE_STATUS="Inactive"
|
||||
fi
|
||||
# Individual service status
|
||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
SERVICE_STATUS="Active"
|
||||
else
|
||||
SERVICE_STATUS="Inactive"
|
||||
fi
|
||||
|
||||
if systemctl is-enabled --quiet "$SERVICE_NAME"; then
|
||||
BOOT_STATUS="Enabled"
|
||||
else
|
||||
BOOT_STATUS="Disabled"
|
||||
fi
|
||||
if systemctl is-enabled --quiet "$SERVICE_NAME"; then
|
||||
BOOT_STATUS="Enabled"
|
||||
else
|
||||
BOOT_STATUS="Disabled"
|
||||
fi
|
||||
|
||||
# Show individual service results
|
||||
msg_ok "Service for ${BL}$SELECTED_INTERFACE${GN} (${BL}$DRIVER${GN}) created and enabled!"
|
||||
msg_info "${TAB}Service: ${BL}$SERVICE_NAME${YW}"
|
||||
msg_info "${TAB}Status: ${BL}$SERVICE_STATUS${YW}"
|
||||
msg_info "${TAB}Start on boot: ${BL}$BOOT_STATUS${YW}"
|
||||
# Show individual service results
|
||||
msg_ok "Service for ${BL}$SELECTED_INTERFACE${GN} (${BL}$DRIVER${GN}) created and enabled!"
|
||||
msg_info "${TAB}Service: ${BL}$SERVICE_NAME${YW}"
|
||||
msg_info "${TAB}Status: ${BL}$SERVICE_STATUS${YW}"
|
||||
msg_info "${TAB}Start on boot: ${BL}$BOOT_STATUS${YW}"
|
||||
done
|
||||
|
||||
# Prepare summary of all interfaces
|
||||
@@ -209,22 +220,22 @@ SUMMARY_MSG="Services created successfully!\n\n"
|
||||
SUMMARY_MSG+="Configured Interfaces:\n"
|
||||
|
||||
for iface in "${INTERFACE_ARRAY[@]}"; do
|
||||
SERVICE_NAME="disable-nic-offload-$iface.service"
|
||||
DRIVER=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
|
||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
SVC_STATUS="Active"
|
||||
else
|
||||
SVC_STATUS="Inactive"
|
||||
fi
|
||||
SERVICE_NAME="disable-nic-offload-$iface.service"
|
||||
DRIVER=$(basename $(readlink -f /sys/class/net/$iface/device/driver 2>/dev/null) 2>/dev/null)
|
||||
|
||||
if systemctl is-enabled --quiet "$SERVICE_NAME"; then
|
||||
BOOT_SVC_STATUS="Enabled"
|
||||
else
|
||||
BOOT_SVC_STATUS="Disabled"
|
||||
fi
|
||||
if systemctl is-active --quiet "$SERVICE_NAME"; then
|
||||
SVC_STATUS="Active"
|
||||
else
|
||||
SVC_STATUS="Inactive"
|
||||
fi
|
||||
|
||||
SUMMARY_MSG+="- $iface ($DRIVER): $SVC_STATUS, Boot: $BOOT_SVC_STATUS\n"
|
||||
if systemctl is-enabled --quiet "$SERVICE_NAME"; then
|
||||
BOOT_SVC_STATUS="Enabled"
|
||||
else
|
||||
BOOT_SVC_STATUS="Disabled"
|
||||
fi
|
||||
|
||||
SUMMARY_MSG+="- $iface ($DRIVER): $SVC_STATUS, Boot: $BOOT_SVC_STATUS\n"
|
||||
done
|
||||
|
||||
# Show summary results
|
||||
@@ -236,8 +247,8 @@ msg_ok "Intel e1000e/e1000 optimization complete for ${#INTERFACE_ARRAY[@]} inte
|
||||
echo ""
|
||||
msg_info "Verification commands:"
|
||||
for iface in "${INTERFACE_ARRAY[@]}"; do
|
||||
echo -e "${TAB}${BL}ethtool -k $iface${CL} ${YW}# Check offloading status${CL}"
|
||||
echo -e "${TAB}${BL}systemctl status disable-nic-offload-$iface.service${CL} ${YW}# Check service status${CL}"
|
||||
echo -e "${TAB}${BL}ethtool -k $iface${CL} ${YW}# Check offloading status${CL}"
|
||||
echo -e "${TAB}${BL}systemctl status disable-nic-offload-$iface.service${CL} ${YW}# Check service status${CL}"
|
||||
done
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -44,6 +44,10 @@ msg_error() {
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs3-upgrade" "tool"
|
||||
|
||||
start_routines() {
|
||||
header_info
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PBS 2 BACKUP" --menu "\nMake a backup of /etc/proxmox-backup to ensure that in the worst case, any relevant configuration can be recovered?" 14 58 2 \
|
||||
|
||||
@@ -32,6 +32,10 @@ msg_info() { echo -ne " ${HOLD} ${YW}$1..."; }
|
||||
msg_ok() { echo -e "${BFR} ${CM} ${GN}$1${CL}"; }
|
||||
msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs4-upgrade" "tool"
|
||||
|
||||
start_routines() {
|
||||
header_info
|
||||
CHOICE=$(whiptail --backtitle "Proxmox VE Helper Scripts" --title "PBS 3 BACKUP" --menu \
|
||||
|
||||
@@ -28,6 +28,10 @@ CM="${GN}✓${CL}"
|
||||
CROSS="${RD}✗${CL}"
|
||||
|
||||
msg_info() { echo -ne " ${HOLD} ${YW}$1..."; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pbs-microcode" "tool"
|
||||
msg_ok() { echo -e "${BFR} ${CM} ${GN}$1${CL}"; }
|
||||
msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@ msg_info() { echo -ne " ${HOLD} ${YW}$1..."; }
|
||||
msg_ok() { echo -e "${BFR} ${CM} ${GN}$1${CL}"; }
|
||||
msg_error() { echo -e "${BFR} ${CROSS} ${RD}$1${CL}"; }
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pbs-install" "tool"
|
||||
|
||||
# ---- helpers ----
|
||||
get_pbs_codename() {
|
||||
awk -F'=' '/^VERSION_CODENAME=/{print $2}' /etc/os-release
|
||||
|
||||
@@ -43,6 +43,10 @@ msg_error() {
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pmg-install" "tool"
|
||||
|
||||
if ! grep -q "Proxmox Mail Gateway" /etc/issue 2>/dev/null; then
|
||||
msg_error "This script is only intended for Proxmox Mail Gateway"
|
||||
exit 1
|
||||
|
||||
@@ -44,6 +44,10 @@ msg_error() {
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "post-pve-install" "tool"
|
||||
|
||||
get_pve_version() {
|
||||
local pve_ver
|
||||
pve_ver="$(pveversion | awk -F'/' '{print $2}' | awk -F'-' '{print $1}')"
|
||||
|
||||
@@ -11,7 +11,9 @@ if ! command -v curl >/dev/null 2>&1; then
|
||||
apt-get install -y curl >/dev/null 2>&1
|
||||
fi
|
||||
source <(curl -fsSL https://git.community-scripts.org/community-scripts/ProxmoxVE/raw/branch/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
load_functions
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pve-privilege-converter" "tool"
|
||||
|
||||
set -euo pipefail
|
||||
shopt -s inherit_errexit nullglob
|
||||
|
||||
@@ -44,6 +44,10 @@ msg_error() {
|
||||
echo -e "${BFR} ${CROSS} ${RD}${msg}${CL}"
|
||||
}
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "pve8-upgrade" "tool"
|
||||
|
||||
start_routines() {
|
||||
header_info
|
||||
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
# License: MIT
|
||||
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
set -e
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "scaling-governor" "tool"
|
||||
|
||||
header_info() {
|
||||
clear
|
||||
cat <<EOF
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
||||
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/refs/heads/main/misc/core.func)
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-apps" "tool"
|
||||
|
||||
# =============================================================================
|
||||
# CONFIGURATION VARIABLES
|
||||
@@ -98,14 +100,14 @@ EOF
|
||||
|
||||
# Handle command line arguments
|
||||
case "${1:-}" in
|
||||
--help|-h)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--export-config)
|
||||
export_config_json
|
||||
exit 0
|
||||
;;
|
||||
--help | -h)
|
||||
print_usage
|
||||
exit 0
|
||||
;;
|
||||
--export-config)
|
||||
export_config_json
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# =============================================================================
|
||||
@@ -202,40 +204,40 @@ msg_ok "Loaded ${#menu_items[@]} containers"
|
||||
# Determine container selection based on var_container
|
||||
if [[ -n "$var_container" ]]; then
|
||||
case "$var_container" in
|
||||
all)
|
||||
# Select all containers with matching tags
|
||||
CHOICE=""
|
||||
for ((i=0; i<${#menu_items[@]}; i+=3)); do
|
||||
CHOICE="$CHOICE ${menu_items[$i]}"
|
||||
done
|
||||
CHOICE=$(echo "$CHOICE" | xargs)
|
||||
;;
|
||||
all_running)
|
||||
# Select only running containers with matching tags
|
||||
CHOICE=""
|
||||
for ((i=0; i<${#menu_items[@]}; i+=3)); do
|
||||
cid="${menu_items[$i]}"
|
||||
if pct status "$cid" 2>/dev/null | grep -q "running"; then
|
||||
CHOICE="$CHOICE $cid"
|
||||
fi
|
||||
done
|
||||
CHOICE=$(echo "$CHOICE" | xargs)
|
||||
;;
|
||||
all_stopped)
|
||||
# Select only stopped containers with matching tags
|
||||
CHOICE=""
|
||||
for ((i=0; i<${#menu_items[@]}; i+=3)); do
|
||||
cid="${menu_items[$i]}"
|
||||
if pct status "$cid" 2>/dev/null | grep -q "stopped"; then
|
||||
CHOICE="$CHOICE $cid"
|
||||
fi
|
||||
done
|
||||
CHOICE=$(echo "$CHOICE" | xargs)
|
||||
;;
|
||||
*)
|
||||
# Assume comma-separated list of container IDs
|
||||
CHOICE=$(echo "$var_container" | tr ',' ' ')
|
||||
;;
|
||||
all)
|
||||
# Select all containers with matching tags
|
||||
CHOICE=""
|
||||
for ((i = 0; i < ${#menu_items[@]}; i += 3)); do
|
||||
CHOICE="$CHOICE ${menu_items[$i]}"
|
||||
done
|
||||
CHOICE=$(echo "$CHOICE" | xargs)
|
||||
;;
|
||||
all_running)
|
||||
# Select only running containers with matching tags
|
||||
CHOICE=""
|
||||
for ((i = 0; i < ${#menu_items[@]}; i += 3)); do
|
||||
cid="${menu_items[$i]}"
|
||||
if pct status "$cid" 2>/dev/null | grep -q "running"; then
|
||||
CHOICE="$CHOICE $cid"
|
||||
fi
|
||||
done
|
||||
CHOICE=$(echo "$CHOICE" | xargs)
|
||||
;;
|
||||
all_stopped)
|
||||
# Select only stopped containers with matching tags
|
||||
CHOICE=""
|
||||
for ((i = 0; i < ${#menu_items[@]}; i += 3)); do
|
||||
cid="${menu_items[$i]}"
|
||||
if pct status "$cid" 2>/dev/null | grep -q "stopped"; then
|
||||
CHOICE="$CHOICE $cid"
|
||||
fi
|
||||
done
|
||||
CHOICE=$(echo "$CHOICE" | xargs)
|
||||
;;
|
||||
*)
|
||||
# Assume comma-separated list of container IDs
|
||||
CHOICE=$(echo "$var_container" | tr ',' ' ')
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ -z "$CHOICE" ]]; then
|
||||
|
||||
@@ -24,6 +24,11 @@ RD=$(echo "\033[01;31m")
|
||||
CM='\xE2\x9C\x94\033'
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-lxcs" "tool"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
whiptail --backtitle "Proxmox VE Helper Scripts" --title "Proxmox VE LXC Updater" --yesno "This Will Update LXC Containers. Proceed?" 10 58
|
||||
|
||||
@@ -23,6 +23,10 @@ RD=$(echo "\033[01;31m")
|
||||
GN=$(echo "\033[1;92m")
|
||||
CL=$(echo "\033[m")
|
||||
|
||||
# Telemetry
|
||||
source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/api.func) 2>/dev/null || true
|
||||
declare -f init_tool_telemetry &>/dev/null && init_tool_telemetry "update-repo" "tool"
|
||||
|
||||
header_info
|
||||
echo "Loading..."
|
||||
NODE=$(hostname)
|
||||
|
||||
Reference in New Issue
Block a user